aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorCliff Brake <cbrake@bec-systems.com>2012-08-17 13:43:14 -0400
committerCliff Brake <cbrake@bec-systems.com>2012-08-17 13:43:14 -0400
commita94e78479793722bc97b8771158d1acee3f55413 (patch)
treebf8f79959febb472513b299df99774de524f5fd1 /tools
parentc11f922b0bfa023a4cf49f26e55aec6a1413344b (diff)
downloadopenembedded-admin-a94e78479793722bc97b8771158d1acee3f55413.tar.gz
add node modules to git
This is now the best practice for deployed apps
Diffstat (limited to 'tools')
l---------tools/node_modules/.bin/expresso1
l---------tools/node_modules/.bin/node-jscoverage1
-rw-r--r--tools/node_modules/expresso/.gitmodules3
-rw-r--r--tools/node_modules/expresso/.npmignore3
-rw-r--r--tools/node_modules/expresso/History.md187
-rw-r--r--tools/node_modules/expresso/Makefile53
-rw-r--r--tools/node_modules/expresso/Readme.md75
-rwxr-xr-xtools/node_modules/expresso/bin/expresso1058
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/encoding.Po166
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/generate-resources.Po105
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/highlight.Po196
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-connection.Po190
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-exchange.Po178
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-host.Po161
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-message.Po176
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-server.Po183
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-url.Po176
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/instrument-js.Po249
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/instrument.Po182
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage-server.Po252
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage.Po126
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/resource-manager.Po116
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/stream.Po117
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/util.Po177
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/COPYING339
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/Makefile884
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/Makefile.am81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/Makefile.in884
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/Readme.md8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/aclocal.m4872
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/config.guess1526
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/config.h93
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/config.h.in92
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/config.log899
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/config.rpath666
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/config.status1080
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/config.sub1658
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/configure7971
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/configure.ac88
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/depcomp589
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/demo.html87
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/doc.css45
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/index.html25
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/script.js20
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/jsUnitStyle.css50
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/readme10
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/emptyPage.html11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitCore.js534
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitMockTimeout.js81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestManager.js705
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestSuite.js44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTracer.js102
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitVersionCheck.js59
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-errors.html12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-failures.html13
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-runs.html13
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts.html21
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-data.html189
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-errors.html23
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-frame.html19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-loader.html45
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-progress.html25
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-results.html67
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-status.html13
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainer.html16
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainerController.html77
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/xbDebug.js306
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/css/jsUnitStyle.css83
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/green.gifbin0 -> 811 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/logo_jsunit.gifbin0 -> 2465 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/powerby-transparent.gifbin0 -> 968 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/red.gifbin0 -> 811 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/JDOM_license.txt56
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/Jetty_license.html213
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/MPL-1.1.txt470
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/gpl-2.txt340
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/index.html141
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/lgpl-2.1.txt504
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-c.txt35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-html.txt35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/readme.txt19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/testRunner.html167
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/script.js7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/test.html25
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example/index.html24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example/script.js20
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/faq.html164
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/feed-icon-14x14.pngbin0 -> 689 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/help.html45
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/index.html151
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/index.html25
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-highlight.css38
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-ie.css89
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-throbber.gifbin0 -> 425 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.css328
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.html125
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.js1024
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/script.js65
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/index.html24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-highlight.css38
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-ie.css89
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-throbber.gifbin0 -> 425 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.css328
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.html125
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.js1024
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/script.js65
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/license.html382
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/links.html59
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/manual.html701
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/news.html214
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/reset-fonts-grids.css7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot.pngbin0 -> 19071 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot2.pngbin0 -> 20888 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot3.pngbin0 -> 22690 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot4.pngbin0 -> 20440 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot5.pngbin0 -> 20738 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot6.pngbin0 -> 28866 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot7.pngbin0 -> 18924 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/sh_html.min.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/sh_javascript.min.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/sh_main.min.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/sh_nedit.min.css1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/siliconforks-16x16.pngbin0 -> 338 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/style.css138
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/users.html58
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/encoding.c315
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/encoding.h33
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/generate-resourcesbin0 -> 13201 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/generate-resources.c58
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/global.h29
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/highlight.c478
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/highlight.h37
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-connection.c192
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-exchange.c494
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-host.c95
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-message.c900
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-server.c236
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-server.h208
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-url.c156
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/install-sh519
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/instrument-js.cpp1873
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/instrument-js.h81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/instrument.c226
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/instrument.h31
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/GNUmakefile15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/Makefile.ref483
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/README.html54
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/SpiderMonkey.rsp11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/aclocal.m49
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/bench.sh5
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/acoutput-fast.pl202
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/altoptions.m4154
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.guess1481
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.sub1595
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/install-sh119
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/make-makefile315
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/match-dir.sh101
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/nspr.m482
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/pkg.m459
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/update-makefile.sh118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/cygwin-wrapper75
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/hcc111
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/hcpp155
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/unix/mddepend.pl165
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/unix/uniq.pl63
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/build/win32/pgomerge.py40
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/builtins.tbl98
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config.mk206
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/Makefile.in106
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/Moz/Milestone.pm232
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/autoconf.mk.in349
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-dirs.py108
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-exceptions6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/config.mk884
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/fastcwd.pl66
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/gcc_hidden.h2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/insure.mk53
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/make-system-wrappers.pl59
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/milestone.pl112
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/milestone.txt13
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/Makefile.in84
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/cppsetup.c233
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/def.h184
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.c549
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.h83
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/imakemdep.h733
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/include.c337
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/main.c860
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/mkdepend.man382
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/parse.c686
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/pr.c124
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/nfspwd.pl50
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.c481
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.py139
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.c247
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.h74
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/preprocessor.pl671
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/revdepth-nt.pl48
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/revdepth.pl51
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/rules.mk2269
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/system-headers1038
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/version.mk85
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/version_win.pl423
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/dtoa.c3321
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/Makefile.ref143
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/README83
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/editline.3175
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/editline.c1368
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/editline.h135
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/sysunix.c182
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/unix.h82
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/javascript-trace.d73
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jitstats.tbl52
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js-config.h.in55
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js-config.in111
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js.cpp4050
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js.mdpbin0 -> 17922 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js.msg309
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js3240.rc79
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsOS240.def654
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsapi.cpp6060
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsapi.h2699
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsarena.cpp450
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsarena.h318
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsarray.cpp3426
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsarray.h191
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsatom.cpp1064
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsatom.h458
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsbit.h253
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsbool.cpp182
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsbool.h75
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.cpp497
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.h374
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsclist.h139
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jscntxt.cpp1394
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jscntxt.h1247
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jscompat.h57
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsconfig.mk181
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.cpp388
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.h212
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdate.cpp2475
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdate.h124
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.cpp1954
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.h500
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdhash.cpp876
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdhash.h588
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.cpp572
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.h131
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.c318
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.h81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsemit.cpp6857
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsemit.h777
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsexn.cpp1376
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsexn.h96
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsfile.cpp2736
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsfile.h56
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsfile.msg90
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsfun.cpp2706
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsfun.h296
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsgc.cpp3763
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsgc.h427
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jshash.cpp476
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jshash.h151
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsify.pl483
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsinterp.cpp7225
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsinterp.h591
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsinvoke.cpp42
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsiter.cpp1050
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsiter.h140
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jskeyword.tbl124
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jskwgen.cpp460
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslibmath.h69
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslock.cpp1417
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslock.h311
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslocko.asm60
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslog2.cpp94
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslong.cpp264
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslong.h412
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsmath.cpp721
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsmath.h63
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsnum.cpp1338
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsnum.h287
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsobj.cpp5563
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsobj.h735
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/json.cpp954
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/json.h107
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsopcode.cpp5304
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsopcode.h404
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsopcode.tbl557
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsoplengen.cpp121
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsotypes.h202
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsparse.cpp6822
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsparse.h508
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsprf.cpp1262
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsprf.h150
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsproto.tbl129
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsprvtd.h263
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jspubtd.h727
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsregexp.cpp4772
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsregexp.h192
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsreops.tbl145
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscan.cpp2017
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscan.h389
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscope.cpp1955
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscope.h419
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscript.cpp1891
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscript.h330
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsshell.msg51
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsstaticcheck.h57
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsstddef.h87
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsstr.cpp5347
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsstr.h662
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jstracer.cpp8276
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jstracer.h552
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jstypes.h490
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsutil.cpp345
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsutil.h168
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsversion.h243
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.cpp800
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.h220
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsxml.cpp8343
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsxml.h298
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/lock_SunOS.s119
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/editline/editline.d1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/editline/libedit.abin0 -> 26986 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/editline/sysunix.d1
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/obj/jsbin0 -> 812800 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h55
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h.stamp0
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/js.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsapi.d8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsarena.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsarray.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsatom.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsautocfg.h56
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsautokw.h401
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsautooplen.h237
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsbool.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jscntxt.d7
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfgbin0 -> 12823 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg.d1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsdate.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsdbgapi.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsdhash.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsdtoa.d3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsemit.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsexn.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsfun.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsgc.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jshash.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsinterp.d8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsinvoke.d8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsiter.d6
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/obj/jskwgenbin0 -> 13542 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen.d1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jslock.d1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jslog2.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jslong.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsmath.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsnum.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsobj.d8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/json.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsopcode.d8
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengenbin0 -> 17157 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen.d1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsparse.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsprf.d3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsregexp.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsscan.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsscope.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsscript.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsstr.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsutil.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsxdrapi.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsxml.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.abin0 -> 1175224 bytes
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/obj/libjs.sobin0 -> 903258 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/prmjtime.d3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/plify_jsdhash.sed35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/prmjtime.cpp846
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/prmjtime.h103
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.1.mk65
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.2.mk64
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.3.mk65
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Cygwin.mk14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin.mk85
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.3.mk81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.4.mk41
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.2.mk81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.3.mk81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin64.mk72
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.10.mk77
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.20.mk77
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.11.00.mk80
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX.mk87
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX5.3.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.1.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.2.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.3.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.5.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Linux_All.mk105
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/MSYS.mk7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Mac_OS10.0.mk82
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V4.0.mk72
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V5.0.mk69
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS4.1.4.mk101
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.10.mk50
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.3.mk91
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.4.mk92
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.1.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.mk87
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.6.mk89
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.7.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.8.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.9.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT4.0.mk118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.0.mk118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.1.mk118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.2.mk118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT6.0.mk118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/dgux.mk64
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/resource.h15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/rules.mk206
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/time.sh13
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/win32.order384
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-help.txt12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-highlight.css38
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-ie.css89
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-overlay.js211
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/jscoverage-serverbin0 -> 1126648 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-server-help.txt17
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-server.179
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-server.c1307
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-throbber.gifbin0 -> 425 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.152
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.c142
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.css328
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.html125
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.js1024
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.jsm22
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.manifest2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.xul36
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/m4/iconv.m4180
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/m4/lib-ld.m4110
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/m4/lib-link.m4709
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/m4/lib-prefix.m4185
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh.in24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/make-dist.sh43
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/make-dist.sh.in43
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/missing367
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/node-jscoveragebin0 -> 1012871 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/report.js76
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/resource-manager.c59
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/resource-manager.h46
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/resources.c3596
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/stamp-h11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/stream.c129
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/stream.h57
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/asprintf.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/encoding.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/encodings.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/gethostbyname.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/highlight.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-body.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-url.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-close-after-request.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-host.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-body.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-headers.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-charset.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-chunked.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-close-immediately.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-url.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/instrument-js.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/json.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/mkdirs.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/recursive-dir-list.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/resource-manager.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/stream.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/streams.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/util.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/Makefile846
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/Makefile.am130
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/Makefile.in846
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/asprintf.c42
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/asprintf.sh19
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/charset.sh110
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/chunked.sh74
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/common.sh7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/destination-is-existing-directory.expected.err2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/destination-is-file.expected.err2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/encoding-requires-argument.expected.err2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/encodings.c223
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/encodings.sh19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/exclude-requires-argument.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/fatal.sh110
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.c53
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.sh25
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/help.sh35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-body.c98
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-url.c77
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-client-close-after-request.c57
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-body.c97
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-headers.c97
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-server-charset.c144
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-server-chunked.c196
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-server-close-immediately.c60
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/invalid-option.sh29
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.expected/ignore.js106
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.sh28
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore/ignore.js44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid.expected.err2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid/javascript-invalid.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter.expected.err1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter/javascript-setter.js3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.expected/javascript-utf-8.js15
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.sh43
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8/javascript-utf-8.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml.expected.err1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml/javascript-xml.js8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-array-comprehension.js32
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-assign.js51
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-colon.js24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-comma.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-cr.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-crlf.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-debugger.js21
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dec.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-delete.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-destructuring.js96
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-do.js28
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dot.js30
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-empty.js9
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-for.js51
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-foreach.js16
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-function.js79
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator-expression.js45
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator.js32
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-getter-setter.js31
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-hook.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-if.js71
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-in.js19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-inc.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-iso-8859-1.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lambda.js14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-let.js148
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lf.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-new.js22
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-number.js57
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-object.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-op.js108
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-primary.js21
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rb.js24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rc.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rp.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-special-characters.js30
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-string.js36
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-switch.js55
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-throw.js21
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-try.js66
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-unaryop.js27
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-var.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-while.js79
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-with.js30
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/javascript.sh53
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-array-comprehension.js14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-assign.js14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-colon.js7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-comma.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-cr.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-crlf.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-debugger.js6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dec.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-delete.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-destructuring.js42
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-do.js10
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dot.js8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-empty.js0
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-for.js22
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-foreach.js8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-function.js38
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator-expression.js18
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator.js11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-getter-setter.js19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-hook.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-if.js30
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-in.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-inc.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-iso-8859-1.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lambda.js3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-let.js79
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lf.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-new.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-number.js19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-object.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-op.js55
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-primary.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rb.js5
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rc.js7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rp.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-special-characters.js11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-string.js11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-switch.js21
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-throw.js6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-try.js32
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-unaryop.js6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-var.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-while.js35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-with.js9
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/json-cmp.js65
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/json.c48
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/json.sh19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.c42
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/mkdirs.sh19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/netcat.pl35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/no-arguments.sh29
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/no-instrument-requires-argument.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-request-body.sh58
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body-javascript.sh53
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.expected.err1
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.sh54
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-headers.sh53
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-no-server.sh49
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-url.sh67
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy.sh143
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive-crlf.sh59
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.c93
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.sh19
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive-exclude.sh41
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive-fatal.sh40
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive-no-instrument.sh41
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.html12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.html11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/image.pngbin0 -> 67 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/index.html12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/script.js19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/style.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/unix.txt3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/windows.txt3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/x1
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive.sh55
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.html12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.html11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/image.pngbin0 -> 67 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/index.html12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/script.js6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/style.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/unix.txt3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/windows.txt3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/x1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/same-directory.expected.err1
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/same-directory.sh30
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-bad-requests.sh104
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-close-after-request.sh47
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-content-types.sh68
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.expected4
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.sh57
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-directory-redirect.sh50
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-encoded-url.sh57
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-error.sh61
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-help.sh26
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.expected.out4
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.sh68
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-shutdown-bad-method.sh49
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.expected.err1
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.sh42
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-special-file.sh62
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-directory.sh61
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-file.sh62
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.expected.err4
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-verbose.sh54
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-version.sh25
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/server.pl61
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server.sh216
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/source-does-not-exist.expected.err2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/source-is-file.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-bad-json.sh50
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-bad-request-body.sh48
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-bad-response-headers.sh56
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.err3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.json14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.expected.json6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.js11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.json3
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.sh52
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-server-bad-body.sh59
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-server-closes-immediately.sh58
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.err1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.json6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.json3
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.sh50
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.err3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.json14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.err3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.json14
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-unreadable-json.sh66
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-unwritable-json.sh58
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store.expected.json14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store.json5
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store.sh137
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/streams.c107
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/streams.sh19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/too-many-arguments.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/valgrind.sh7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/verbose.expected.out13
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/version.sh29
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/util.c570
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/util.h133
-rw-r--r--tools/node_modules/expresso/docs/api.html1291
-rw-r--r--tools/node_modules/expresso/docs/index.html174
-rw-r--r--tools/node_modules/expresso/docs/index.md328
-rw-r--r--tools/node_modules/expresso/docs/layout/foot.html3
-rw-r--r--tools/node_modules/expresso/docs/layout/head.html42
-rw-r--r--tools/node_modules/expresso/package.json26
-rw-r--r--tools/node_modules/expresso/test/.invalid.test.js9
-rw-r--r--tools/node_modules/expresso/test/assert.test.js83
-rw-r--r--tools/node_modules/expresso/test/async.test.js12
-rw-r--r--tools/node_modules/expresso/test/bar.test.js13
-rw-r--r--tools/node_modules/expresso/test/earlyexit.test.js22
-rw-r--r--tools/node_modules/expresso/test/earlyexit/forever.test.js8
-rw-r--r--tools/node_modules/expresso/test/foo.test.js14
-rw-r--r--tools/node_modules/expresso/test/http.test.js168
-rw-r--r--tools/node_modules/expresso/test/local-assert.test.js20
-rw-r--r--tools/node_modules/expresso/test/match.test.js25
-rw-r--r--tools/node_modules/expresso/test/match/test.js10
-rw-r--r--tools/node_modules/expresso/test/serial/async.test.js39
-rw-r--r--tools/node_modules/expresso/test/serial/http.test.js48
-rw-r--r--tools/node_modules/expresso/test/serial/teardown.test.js25
-rw-r--r--tools/node_modules/expresso/test/this.test.js20
-rw-r--r--tools/node_modules/nodemailer/.npmignore2
-rw-r--r--tools/node_modules/nodemailer/.travis.yml12
-rw-r--r--tools/node_modules/nodemailer/LICENSE16
-rw-r--r--tools/node_modules/nodemailer/README.md619
-rw-r--r--tools/node_modules/nodemailer/examples/example_dkim.js78
-rw-r--r--tools/node_modules/nodemailer/examples/example_sendmail.js65
-rw-r--r--tools/node_modules/nodemailer/examples/example_ses.js80
-rw-r--r--tools/node_modules/nodemailer/examples/example_smtp.js77
-rw-r--r--tools/node_modules/nodemailer/examples/example_xoauth.js86
-rw-r--r--tools/node_modules/nodemailer/examples/nyan.gifbin0 -> 29361 bytes
-rw-r--r--tools/node_modules/nodemailer/examples/test_private.pem12
-rw-r--r--tools/node_modules/nodemailer/lib/engines/sendmail.js52
-rw-r--r--tools/node_modules/nodemailer/lib/engines/ses.js217
-rw-r--r--tools/node_modules/nodemailer/lib/engines/smtp.js109
-rw-r--r--tools/node_modules/nodemailer/lib/engines/stub.js39
-rw-r--r--tools/node_modules/nodemailer/lib/helpers.js223
-rw-r--r--tools/node_modules/nodemailer/lib/nodemailer.js285
-rw-r--r--tools/node_modules/nodemailer/lib/transport.js110
-rw-r--r--tools/node_modules/nodemailer/lib/wellknown.js58
-rw-r--r--tools/node_modules/nodemailer/lib/xoauth.js71
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/.npmignore1
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/.travis.yml11
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/LICENSE16
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/README.md319
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/lib/dkim.js217
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/lib/mailcomposer.js1260
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/lib/punycode.js329
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/lib/urlfetch.js71
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/LICENSE16
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/README.md17
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/content-types.js60
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/doc.md191
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/index.js3
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js486
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/package.json35
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/package.json46
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/test/dkim.js47
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/test/mailcomposer.js1085
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/test/test_private.pem12
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/test/test_public.pem5
-rw-r--r--tools/node_modules/nodemailer/node_modules/mailcomposer/test/textfile.txt601
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/.npmignore1
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/.travis.yml12
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/LICENSE16
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/README.md275
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/index.js5
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/lib/client.js709
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/lib/pool.js316
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/lib/server.js664
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/lib/starttls.js112
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/.npmignore1
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/.travis.yml12
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/LICENSE16
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/README.md163
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/cert/cert.pem15
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/cert/key.pem15
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/examples/smtp.js73
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/all.css358
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.eotbin0 -> 18590 bytes
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.svg134
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.ttfbin0 -> 18428 bytes
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.woffbin0 -> 11772 bytes
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.eotbin0 -> 19518 bytes
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.svg134
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.ttfbin0 -> 19344 bytes
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.woffbin0 -> 12304 bytes
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/handheld.css217
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/screen.css297
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/files.html133
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/index.html107
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/javascript/all.js326
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/javascript/html5.js6
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/RAIServer.html565
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/RAISocket.html826
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/_global_.html122
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/mockup.html264
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_index.js.html394
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_mockup.js.html110
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_rai.js.html484
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_starttls.js.html120
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/starttls.html237
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/mockup.js113
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/rai.js489
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/starttls.js113
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/package.json41
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/run_tests.js2
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/test/rai.js589
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/package.json52
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/test/client.js444
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/test/pool.js275
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/test/server.js590
-rw-r--r--tools/node_modules/nodemailer/node_modules/simplesmtp/test/testmessage.eml5
-rw-r--r--tools/node_modules/nodemailer/package.json53
-rw-r--r--tools/node_modules/nodemailer/test/nodemailer.js201
834 files changed, 234642 insertions, 0 deletions
diff --git a/tools/node_modules/.bin/expresso b/tools/node_modules/.bin/expresso
new file mode 120000
index 0000000..72c617b
--- /dev/null
+++ b/tools/node_modules/.bin/expresso
@@ -0,0 +1 @@
+../expresso/bin/expresso \ No newline at end of file
diff --git a/tools/node_modules/.bin/node-jscoverage b/tools/node_modules/.bin/node-jscoverage
new file mode 120000
index 0000000..0a6d87f
--- /dev/null
+++ b/tools/node_modules/.bin/node-jscoverage
@@ -0,0 +1 @@
+../expresso/deps/jscoverage/node-jscoverage \ No newline at end of file
diff --git a/tools/node_modules/expresso/.gitmodules b/tools/node_modules/expresso/.gitmodules
new file mode 100644
index 0000000..191ddeb
--- /dev/null
+++ b/tools/node_modules/expresso/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "deps/jscoverage"]
+ path = deps/jscoverage
+ url = git://github.com/visionmedia/node-jscoverage.git
diff --git a/tools/node_modules/expresso/.npmignore b/tools/node_modules/expresso/.npmignore
new file mode 100644
index 0000000..a4dd5fb
--- /dev/null
+++ b/tools/node_modules/expresso/.npmignore
@@ -0,0 +1,3 @@
+.DS_Store
+lib-cov
+node_modules/
diff --git a/tools/node_modules/expresso/History.md b/tools/node_modules/expresso/History.md
new file mode 100644
index 0000000..c644cdf
--- /dev/null
+++ b/tools/node_modules/expresso/History.md
@@ -0,0 +1,187 @@
+
+0.9.2 / 2011-10-12
+==================
+
+ * Fixed serial support
+
+0.9.1 / 2011-10-12
+==================
+
+ * Added 0.5.x support
+ * Added regex based test name filtering argument
+ * Removed "sys" module related calls
+
+0.8.1 / 2011-07-07
+==================
+
+ * Revert "Changed: explicitly exit on failure"
+ * acquire port number from servers that are already running and wait until server started up
+
+0.8.0 / 2011-07-05
+==================
+
+ * Changed: explicitly exit on failure
+
+0.7.9 / 2011-06-22
+==================
+
+ * Fixed; increase maxListeners to prevent reaching the limit
+
+0.7.8 / 2011-06-22
+==================
+
+ * Added `--json [file]` flag to output JSON test coverage reports
+
+0.7.7 / 2011-05-24
+==================
+
+ * Moved to new http request API. Fixing Connection Refused error [Renault John Lecoultre]
+ * Added encoding option to request function. Defaults to utf8 as before. [nateps]
+
+0.7.6 / 2011-04-20
+==================
+
+ * Added teardown for serial tests. Sync tests no longer require parameter. [Raevel]
+
+0.7.5 / 2011-03-31
+==================
+
+ * Fixed; removed some ansi-escape sequences in --boring mode [Norbert Schultz]
+
+0.7.4 / 2011-03-27
+==================
+
+ * Added coffee-script support (wahoo...)
+
+0.7.3 / 2011-03-02
+==================
+
+ * Fixed server listening check. Closes #62. [Andrew Stone]
+
+0.7.2 / 2010-12-29
+==================
+
+ * Fixed problem with `listen()` sometimes firing on the same tick [guillermo]
+
+0.7.1 / 2010-12-28
+==================
+
+ * Fixed `assert.request()` client logic into an issue() function, fired upon the `listen()` callback if the server doesn't have an assigned fd. [guillermo]
+ * Removed `--watch`
+
+0.7.0 / 2010-11-19
+==================
+
+ * Removed `assert` from test function signature
+ Just use `require('assert')` :) this will make integration
+ with libraries like [should](http://github.com/visionmedia/should) cleaner.
+
+0.6.4 / 2010-11-02
+==================
+
+ * Added regexp support to `assert.response()` headers
+ * Removed `waitForExit` code, causing issues
+
+0.6.3 / 2010-11-02
+==================
+
+ * Added `assert.response()` body RegExp support
+ * Fixed issue with _--serial_ not executing files sequentially. Closes #42
+ * Fixed hang when modules use `setInterval` - monitor running tests & force the process to quit after all have completed + timeout [Steve Mason]
+
+0.6.2 / 2010-09-17
+==================
+
+ * Added _node-jsocoverage_ to package.json (aka will respect npm's binroot)
+ * Added _-t, --timeout_ MS option, defaulting to 2000 ms
+ * Added _-s, --serial_
+ * __PREFIX__ clobberable
+ * Fixed `assert.response()` for latest node
+ * Fixed cov reporting from exploding on empty files
+
+0.6.2 / 2010-08-03
+==================
+
+ * Added `assert.type()`
+ * Renamed `assert.isNotUndefined()` to `assert.isDefined()`
+ * Fixed `assert.includes()` param ordering
+
+0.6.0 / 2010-07-31
+==================
+
+ * Added _docs/api.html_
+ * Added -w, --watch
+ * Added `Array` support to `assert.includes()`
+ * Added; outputting exceptions immediately. Closes #19
+ * Fixed `assert.includes()` param ordering
+ * Fixed `assert.length()` param ordering
+ * Fixed jscoverage links
+
+0.5.0 / 2010-07-16
+==================
+
+ * Added support for async exports
+ * Added timeout support to `assert.response()`. Closes #3
+ * Added 4th arg callback support to `assert.response()`
+ * Added `assert.length()`
+ * Added `assert.match()`
+ * Added `assert.isUndefined()`
+ * Added `assert.isNull()`
+ * Added `assert.includes()`
+ * Added growlnotify support via -g, --growl
+ * Added -o, --only TESTS. Ex: --only "test foo()" --only "test foo(), test bar()"
+ * Removed profanity
+
+0.4.0 / 2010-07-09
+==================
+
+ * Added reporting source coverage (respects --boring for color haters)
+ * Added callback to assert.response(). Closes #12
+ * Fixed; putting exceptions to stderr. Closes #13
+
+0.3.1 / 2010-06-28
+==================
+
+ * Faster assert.response()
+
+0.3.0 / 2010-06-28
+==================
+
+ * Added -p, --port NUM flags
+ * Added assert.response(). Closes #11
+
+0.2.1 / 2010-06-25
+==================
+
+ * Fixed issue with reporting object assertions
+
+0.2.0 / 2010-06-21
+==================
+
+ * Added `make uninstall`
+ * Added better readdir() failure message
+ * Fixed `make install` for kiwi
+
+0.1.0 / 2010-06-15
+==================
+
+ * Added better usage docs via --help
+ * Added better conditional color support
+ * Added pre exit assertion support
+
+0.0.3 / 2010-06-02
+==================
+
+ * Added more room for filenames in test coverage
+ * Added boring output support via --boring (suppress colored output)
+ * Fixed async failure exit status
+
+0.0.2 / 2010-05-30
+==================
+
+ * Fixed exit status for CI support
+
+0.0.1 / 2010-05-30
+==================
+
+ * Initial release \ No newline at end of file
diff --git a/tools/node_modules/expresso/Makefile b/tools/node_modules/expresso/Makefile
new file mode 100644
index 0000000..1687df4
--- /dev/null
+++ b/tools/node_modules/expresso/Makefile
@@ -0,0 +1,53 @@
+
+PREFIX ?= /usr/local
+BIN = bin/expresso
+JSCOV = deps/jscoverage/node-jscoverage
+DOCS = docs/index.md
+HTMLDOCS = $(DOCS:.md=.html)
+
+test: $(BIN)
+ @./$(BIN) --growl $(TEST_FLAGS)
+
+test-cov:
+ @./$(BIN) -I lib --cov $(TEST_FLAGS)
+
+test-serial:
+ @./$(BIN) --serial $(TEST_FLAGS) test/serial/*.test.js
+
+install: install-jscov install-expresso
+
+uninstall:
+ rm -f $(PREFIX)/bin/expresso
+ rm -f $(PREFIX)/bin/node-jscoverage
+
+install-jscov: $(JSCOV)
+ install $(JSCOV) $(PREFIX)/bin
+
+install-expresso:
+ install $(BIN) $(PREFIX)/bin
+
+$(JSCOV):
+ cd deps/jscoverage && ./configure && make && mv jscoverage node-jscoverage
+
+clean:
+ @cd deps/jscoverage && git clean -fd
+
+docs: docs/api.html $(HTMLDOCS)
+
+%.html: %.md
+ @echo "... $< > $@"
+ @ronn --html $< \
+ | cat docs/layout/head.html - docs/layout/foot.html \
+ > $@
+
+docs/api.html: bin/expresso
+ dox \
+ --title "Expresso" \
+ --ribbon "http://github.com/visionmedia/expresso" \
+ --desc "Insanely fast TDD framework for [node](http://nodejs.org) featuring code coverage reporting." \
+ $< > $@
+
+docclean:
+ rm -f docs/*.html
+
+.PHONY: test test-cov install uninstall install-expresso install-jscov clean docs docclean \ No newline at end of file
diff --git a/tools/node_modules/expresso/Readme.md b/tools/node_modules/expresso/Readme.md
new file mode 100644
index 0000000..bce1b6b
--- /dev/null
+++ b/tools/node_modules/expresso/Readme.md
@@ -0,0 +1,75 @@
+
+# Expresso
+
+ TDD framework for [nodejs](http://nodejs.org).
+
+## Features
+
+ - light-weight
+ - intuitive async support
+ - intuitive test runner executable
+ - test coverage support and reporting
+ - uses the _assert_ module
+ - `assert.eql()` alias of `assert.deepEqual()`
+ - `assert.response()` http response utility
+ - `assert.includes()`
+ - `assert.type()`
+ - `assert.isNull()`
+ - `assert.isUndefined()`
+ - `assert.isNotNull()`
+ - `assert.isDefined()`
+ - `assert.match()`
+ - `assert.length()`
+
+## Installation
+
+To install both expresso _and_ node-jscoverage run:
+
+ $ make install
+
+To install expresso alone (no build required) run:
+
+ $ make install-expresso
+
+Install via npm:
+
+ $ npm install expresso
+
+## Usage
+
+Create a directory named `test` in your project and place JavaScript files in it. Each JavaScript file can export multiple tests of this format:
+
+```js
+exports['test String#length'] = function(beforeExit, assert) {
+ assert.equal(6, 'foobar'.length);
+};
+```
+
+To run tests, type `expresso`.
+
+For more information, [see the manual](http://visionmedia.github.com/expresso/).
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+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.
diff --git a/tools/node_modules/expresso/bin/expresso b/tools/node_modules/expresso/bin/expresso
new file mode 100755
index 0000000..63b5616
--- /dev/null
+++ b/tools/node_modules/expresso/bin/expresso
@@ -0,0 +1,1058 @@
+#!/usr/bin/env node
+
+/*
+ * Expresso
+ * Copyright(c) TJ Holowaychuk <tj@vision-media.ca>
+ * (MIT Licensed)
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert'),
+ childProcess = require('child_process'),
+ http = require('http'),
+ path = require('path'),
+ util = require('util'),
+ cwd = process.cwd(),
+ fs = require('fs'),
+ defer;
+
+/**
+ * Set the node env to test if it hasn't already been set
+ */
+
+if( !process.env.NODE_ENV ) process.env.NODE_ENV = 'test';
+
+/**
+ * Setup the regex which is used to match test files.
+ * Adjust it to include coffeescript files if CS is available
+ */
+var file_matcher = /\.js$/;
+try {
+ require('coffee-script');
+ file_matcher = /\.(js|coffee)$/;
+} catch (e) {}
+
+/**
+ * Expresso version.
+ */
+
+var version = '0.9.2';
+
+/**
+ * Failure count.
+ */
+
+var failures = 0;
+
+/**
+ * Indicates whether all test files have been loaded.
+ */
+
+var suites = 0;
+var suitesRun = 0;
+
+/**
+ * Number of tests executed.
+ */
+
+var testcount = 0;
+
+/**
+ * Whitelist of tests to run.
+ */
+
+var only = [];
+
+/**
+ * Regex expression filtering tests to run.
+ */
+
+var match = '';
+
+/**
+ * Boring output.
+ */
+
+var boring = false;
+
+/**
+ * Growl notifications.
+ */
+
+var growl = false;
+
+/**
+ * Server port.
+ */
+
+var port = 5555;
+
+/**
+ * Execute serially.
+ */
+
+var serial = false;
+
+/**
+ * Default timeout.
+ */
+
+var timeout = 2000;
+
+/**
+ * Quiet output.
+ */
+
+var quiet = false;
+
+/**
+ * JSON code coverage report
+ */
+var jsonCoverage = false;
+var jsonFile;
+
+/**
+ * Usage documentation.
+ */
+
+var usage = ''
+ + '[bold]{Usage}: expresso [options] <file ...>'
+ + '\n'
+ + '\n[bold]{Options}:'
+ + '\n -g, --growl Enable growl notifications'
+ + '\n -c, --coverage Generate and report test coverage'
+ + '\n -j, --json PATH Used in conjunction with --coverage, ouput JSON coverage to PATH'
+ + '\n -q, --quiet Suppress coverage report if 100%'
+ + '\n -t, --timeout MS Timeout in milliseconds, defaults to 2000'
+ + '\n -r, --require PATH Require the given module path'
+ + '\n -o, --only TESTS Execute only the comma sperated TESTS (can be set several times)'
+ + '\n -m, --match EXP Execute only tests matching a given regular expression (can be set several times)'
+ + '\n -p, --port NUM Port number for test servers, starts at 5555'
+ + '\n -s, --serial Execute tests serially'
+ + '\n -b, --boring Suppress ansi-escape colors'
+ + '\n -v, --version Output version number'
+ + '\n -h, --help Display help information'
+ + '\n';
+
+// Parse arguments
+
+var files = [],
+ args = process.argv.slice(2);
+
+while (args.length) {
+ var arg = args.shift();
+ switch (arg) {
+ case '-h':
+ case '--help':
+ print(usage + '\n');
+ process.exit(1);
+ break;
+ case '-v':
+ case '--version':
+ console.log(version);
+ process.exit(1);
+ break;
+ case '-o':
+ case '--only':
+ if (arg = args.shift()) {
+ only = only.concat(arg.split(/ *, */));
+ } else {
+ throw new Error('--only requires comma-separated test names');
+ }
+ break;
+ case '-m':
+ case '--match':
+ if (arg = args.shift()) {
+ match += (match.length > 0 ? '|' : '') + arg;
+ } else {
+ throw new Error('--match requires argument');
+ }
+ break;
+ case '-p':
+ case '--port':
+ if (arg = args.shift()) {
+ port = parseInt(arg, 10);
+ } else {
+ throw new Error('--port requires a number');
+ }
+ break;
+ case '-r':
+ case '--require':
+ if (arg = args.shift()) {
+ require(arg);
+ } else {
+ throw new Error('--require requires a path');
+ }
+ break;
+ case '-t':
+ case '--timeout':
+ if (arg = args.shift()) {
+ timeout = parseInt(arg, 10);
+ } else {
+ throw new Error('--timeout requires an argument');
+ }
+ break;
+ // case '-c':
+ // case '--cov':
+ // case '--coverage':
+ // defer = true;
+ // childProcess.exec('rm -fr lib-cov && node-jscoverage lib lib-cov', function(err){
+ // if (err) throw err;
+ // require.paths.unshift('lib-cov');
+ // run(files);
+ // })
+ // break;
+ case '-q':
+ case '--quiet':
+ quiet = true;
+ break;
+ case '-b':
+ case '--boring':
+ boring = true;
+ break;
+ case '-g':
+ case '--growl':
+ growl = true;
+ break;
+ case '-s':
+ case '--serial':
+ serial = true;
+ break;
+ case '-j':
+ case '--json':
+ jsonCoverage = true;
+ if (arg = args.shift()) {
+ jsonFile = path.normalize(arg);
+ } else {
+ throw new Error('--json requires file to write to');
+ }
+ break;
+ default:
+ if (file_matcher.test(arg)) {
+ files.push(arg);
+ }
+ break;
+ }
+}
+
+/**
+ * Colorized console.error().
+ *
+ * @param {String} str
+ */
+
+function print(str){
+ console.error(colorize(str));
+}
+
+/**
+ * Colorize the given string using ansi-escape sequences.
+ * Disabled when --boring is set.
+ *
+ * @param {String} str
+ * @return {String}
+ */
+
+function colorize(str) {
+ var colors = { bold: 1, red: 31, green: 32, yellow: 33 };
+ return str.replace(/\[(\w+)\]\{([^]*?)\}/g, function(_, color, str) {
+ return boring
+ ? str
+ : '\x1B[' + colors[color] + 'm' + str + '\x1B[0m';
+ });
+}
+
+// Alias deepEqual as eql for complex equality
+
+assert.eql = assert.deepEqual;
+
+/**
+ * Assert that `val` is null.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isNull = function(val, msg) {
+ assert.strictEqual(null, val, msg);
+};
+
+/**
+ * Assert that `val` is not null.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isNotNull = function(val, msg) {
+ assert.notStrictEqual(null, val, msg);
+};
+
+/**
+ * Assert that `val` is undefined.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isUndefined = function(val, msg) {
+ assert.strictEqual(undefined, val, msg);
+};
+
+/**
+ * Assert that `val` is not undefined.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isDefined = function(val, msg) {
+ assert.notStrictEqual(undefined, val, msg);
+};
+
+/**
+ * Assert that `obj` is `type`.
+ *
+ * @param {Mixed} obj
+ * @param {String} type
+ * @api public
+ */
+
+assert.type = function(obj, type, msg) {
+ var real = typeof obj;
+ msg = msg || 'typeof ' + util.inspect(obj) + ' is ' + real + ', expected ' + type;
+ assert.ok(type === real, msg);
+};
+
+/**
+ * Assert that `str` matches `regexp`.
+ *
+ * @param {String} str
+ * @param {RegExp} regexp
+ * @param {String} msg
+ */
+
+assert.match = function(str, regexp, msg) {
+ msg = msg || util.inspect(str) + ' does not match ' + util.inspect(regexp);
+ assert.ok(regexp.test(str), msg);
+};
+
+/**
+ * Assert that `val` is within `obj`.
+ *
+ * Examples:
+ *
+ * assert.includes('foobar', 'bar');
+ * assert.includes(['foo', 'bar'], 'foo');
+ *
+ * @param {String|Array} obj
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.includes = function(obj, val, msg) {
+ msg = msg || util.inspect(obj) + ' does not include ' + util.inspect(val);
+ assert.ok(obj.indexOf(val) >= 0, msg);
+};
+
+/**
+ * Assert length of `val` is `n`.
+ *
+ * @param {Mixed} val
+ * @param {Number} n
+ * @param {String} msg
+ */
+
+assert.length = function(val, n, msg) {
+ msg = msg || util.inspect(val) + ' has length of ' + val.length + ', expected ' + n;
+ assert.equal(n, val.length, msg);
+};
+
+/**
+ * Assert response from `server` with
+ * the given `req` object and `res` assertions object.
+ *
+ * @param {Server} server
+ * @param {Object} req
+ * @param {Object|Function} res
+ * @param {String} msg
+ */
+assert.response = function(server, req, res, msg) {
+ var test = assert._test;
+
+ // Callback as third or fourth arg
+ var callback = typeof res === 'function'
+ ? res
+ : typeof msg === 'function'
+ ? msg
+ : function() {};
+
+ // Default messate to test title
+ if (typeof msg === 'function') msg = null;
+ msg = msg || test.title;
+ msg += '. ';
+
+ // Add a unique token for this call to assert.response(). We'll move it to
+ // succeeded/failed when done
+ var token = new Error('Response not completed: ' + msg);
+ test._pending.push(token);
+
+ function check() {
+ try {
+ server.__port = server.address().port;
+ server.__listening = true;
+ } catch (err) {
+ process.nextTick(check);
+ return;
+ }
+ if (server.__deferred) {
+ server.__deferred.forEach(function(fn) { fn(); });
+ server.__deferred = null;
+ }
+ }
+
+ // Pending responses
+ server.__pending = server.__pending || 0;
+ server.__pending++;
+
+ // Check that the server is ready or defer
+ if (!server.fd) {
+ server.__deferred = server.__deferred || [];
+ server.listen(server.__port = port++, '127.0.0.1', check);
+ } else if (!server.__port) {
+ server.__deferred = server.__deferred || [];
+ process.nextTick(check);
+ }
+
+ // The socket was created but is not yet listening, so keep deferring
+ if (!server.__listening) {
+ server.__deferred.push(issue);
+ return;
+ } else {
+ issue();
+ }
+
+ function issue() {
+ // Issue request
+ var timer,
+ method = req.method || 'GET',
+ status = res.status || res.statusCode,
+ data = req.data || req.body,
+ requestTimeout = req.timeout || 0,
+ encoding = req.encoding || 'utf8';
+
+ var request = http.request({
+ host: '127.0.0.1',
+ port: server.__port,
+ path: req.url,
+ method: method,
+ headers: req.headers
+ });
+
+ var check = function() {
+ if (--server.__pending === 0) {
+ server.close();
+ server.__listening = false;
+ }
+ };
+
+ // Timeout
+ if (requestTimeout) {
+ timer = setTimeout(function() {
+ check();
+ delete req.timeout;
+ test.failure(new Error(msg + 'Request timed out after ' + requestTimeout + 'ms.'));
+ }, requestTimeout);
+ }
+
+ if (data) request.write(data);
+
+ request.on('response', function(response) {
+ response.body = '';
+ response.setEncoding(encoding);
+ response.on('data', function(chunk) { response.body += chunk; });
+ response.on('end', function() {
+ if (timer) clearTimeout(timer);
+ try {
+ // Assert response body
+ if (res.body !== undefined) {
+ var eql = res.body instanceof RegExp
+ ? res.body.test(response.body)
+ : res.body === response.body;
+ assert.ok(
+ eql,
+ msg + 'Invalid response body.\n'
+ + ' Expected: ' + util.inspect(res.body) + '\n'
+ + ' Got: ' + util.inspect(response.body)
+ );
+ }
+
+ // Assert response status
+ if (typeof status === 'number') {
+ assert.equal(
+ response.statusCode,
+ status,
+ msg + colorize('Invalid response status code.\n'
+ + ' Expected: [green]{' + status + '}\n'
+ + ' Got: [red]{' + response.statusCode + '}')
+ );
+ }
+
+ // Assert response headers
+ if (res.headers) {
+ var keys = Object.keys(res.headers);
+ for (var i = 0, len = keys.length; i < len; ++i) {
+ var name = keys[i],
+ actual = response.headers[name.toLowerCase()],
+ expected = res.headers[name],
+ eql = expected instanceof RegExp
+ ? expected.test(actual)
+ : expected == actual;
+ assert.ok(
+ eql,
+ msg + colorize('Invalid response header [bold]{' + name + '}.\n'
+ + ' Expected: [green]{' + expected + '}\n'
+ + ' Got: [red]{' + actual + '}')
+ );
+ }
+ }
+
+ // Callback
+ callback(response);
+
+ // Add this to the succeeded bin.
+ test.success(msg);
+ } catch (err) {
+ test.failure(err);
+ test.callback();
+ } finally {
+ // Remove our token.
+ var idx = test._pending.indexOf(token);
+ if (idx >= 0) {
+ test._pending.splice(idx, 1);
+ } else {
+ // Someone else took our token. This is an error.
+ test.failure(new Error('Request succeeded, but token vanished: ' + msg));
+ }
+
+ // Potentially shut down the server.
+ check();
+ }
+ });
+ });
+
+ request.end();
+ }
+};
+
+/**
+ * Pad the given string to the maximum width provided.
+ *
+ * @param {String} str
+ * @param {Number} width
+ * @return {String}
+ */
+
+function lpad(str, width) {
+ str = String(str);
+ var n = width - str.length;
+ if (n < 1) return str;
+ while (n--) str = ' ' + str;
+ return str;
+}
+
+/**
+ * Pad the given string to the maximum width provided.
+ *
+ * @param {String} str
+ * @param {Number} width
+ * @return {String}
+ */
+
+function rpad(str, width) {
+ str = String(str);
+ var n = width - str.length;
+ if (n < 1) return str;
+ while (n--) str = str + ' ';
+ return str;
+}
+
+/**
+ * Report test coverage in tabular format
+ *
+ * @param {Object} cov
+ */
+
+function reportCoverageTable(cov) {
+ // Stats
+ print('\n [bold]{Test Coverage}\n');
+ var sep = ' +------------------------------------------+----------+------+------+--------+',
+ lastSep = ' +----------+------+------+--------+';
+ console.log(sep);
+ console.log(' | filename | coverage | LOC | SLOC | missed |');
+ console.log(sep);
+ for (var name in cov) {
+ var file = cov[name];
+ if (Array.isArray(file)) {
+ process.stdout.write(' | ' + rpad(name, 40));
+ process.stdout.write(' | ' + lpad(file.coverage.toFixed(2), 8));
+ process.stdout.write(' | ' + lpad(file.LOC, 4));
+ process.stdout.write(' | ' + lpad(file.SLOC, 4));
+ process.stdout.write(' | ' + lpad(file.totalMisses, 6));
+ process.stdout.write(' |\n');
+ }
+ }
+ console.log(sep);
+ process.stdout.write(' ' + rpad('', 40));
+ process.stdout.write(' | ' + lpad(cov.coverage.toFixed(2), 8));
+ process.stdout.write(' | ' + lpad(cov.LOC, 4));
+ process.stdout.write(' | ' + lpad(cov.SLOC, 4));
+ process.stdout.write(' | ' + lpad(cov.totalMisses, 6));
+ process.stdout.write(' |\n');
+ console.log(lastSep);
+ // Source
+ for (var name in cov) {
+ if (name.match(file_matcher)) {
+ var file = cov[name];
+ if ((file.coverage < 100) || !quiet) {
+ print('\n [bold]{' + name + '}:');
+ print(file.source);
+ process.stdout.write('\n');
+ }
+ }
+ }
+}
+
+/**
+ * Report test coverage in raw json format
+ *
+ * @param {Object} cov
+ */
+
+function reportCoverageJson(cov) {
+ var report = {
+ "coverage" : cov.coverage.toFixed(2),
+ "LOC" : cov.LOC,
+ "SLOC" : cov.SLOC,
+ "totalMisses" : cov.totalMisses,
+ "files" : {}
+ };
+
+ for (var name in cov) {
+ var file = cov[name];
+ if (Array.isArray(file)) {
+ report.files[name] = {
+ "coverage" : file.coverage.toFixed(2),
+ "LOC" : file.LOC,
+ "SLOC" : file.SLOC,
+ "totalMisses" : file.totalMisses
+ };
+ }
+ }
+
+ fs.writeFileSync(jsonFile, JSON.stringify(report), "utf8");
+}
+
+/**
+ * Populate code coverage data.
+ *
+ * @param {Object} cov
+ */
+
+function populateCoverage(cov) {
+ cov.LOC =
+ cov.SLOC =
+ cov.totalFiles =
+ cov.totalHits =
+ cov.totalMisses =
+ cov.coverage = 0;
+ for (var name in cov) {
+ var file = cov[name];
+ if (Array.isArray(file)) {
+ // Stats
+ ++cov.totalFiles;
+ cov.totalHits += file.totalHits = coverage(file, true);
+ cov.totalMisses += file.totalMisses = coverage(file, false);
+ file.totalLines = file.totalHits + file.totalMisses;
+ cov.SLOC += file.SLOC = file.totalLines;
+ if (!file.source) file.source = [];
+ cov.LOC += file.LOC = file.source.length;
+ file.coverage = (file.totalHits / file.totalLines) * 100;
+ // Source
+ var width = file.source.length.toString().length;
+ file.source = file.source.map(function(line, i) {
+ ++i;
+ var hits = file[i] === 0 ? 0 : (file[i] || ' ');
+ if (!boring) {
+ if (hits === 0) {
+ hits = '\x1b[31m' + hits + '\x1b[0m';
+ line = '\x1b[41m' + line + '\x1b[0m';
+ } else {
+ hits = '\x1b[32m' + hits + '\x1b[0m';
+ }
+ }
+ return '\n ' + lpad(i, width) + ' | ' + hits + ' | ' + line;
+ }).join('');
+ }
+ }
+ cov.coverage = (cov.totalHits / cov.SLOC) * 100;
+}
+
+/**
+ * Total coverage for the given file data.
+ *
+ * @param {Array} data
+ * @return {Type}
+ */
+
+function coverage(data, val) {
+ var n = 0;
+ for (var i = 0, len = data.length; i < len; ++i) {
+ if (data[i] !== undefined && data[i] == val) ++n;
+ }
+ return n;
+}
+
+/**
+ * Test if all files have 100% coverage
+ *
+ * @param {Object} cov
+ * @return {Boolean}
+ */
+
+function hasFullCoverage(cov) {
+ for (var name in cov) {
+ var file = cov[name];
+ if (file instanceof Array) {
+ if (file.coverage !== 100) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/**
+ * Run the given test `files`, or try _test/*_.
+ *
+ * @param {Array} files
+ */
+
+function run(files) {
+ cursor(false);
+ if (!files.length) {
+ try {
+ files = fs.readdirSync('test').map(function(file) {
+ return 'test/' + file;
+ }).filter(function(file) {
+ return !(/(^\.)|(\/\.)/.test(file));
+ });
+ } catch (err) {
+ print('\n failed to load tests in [bold]{./test}\n');
+ ++failures;
+ process.exit(1);
+ }
+ }
+ runFiles(files);
+}
+
+/**
+ * Show the cursor when `show` is true, otherwise hide it.
+ *
+ * @param {Boolean} show
+ */
+
+function cursor(show) {
+ if (boring) return;
+ if (show) {
+ process.stdout.write('\x1b[?25h');
+ } else {
+ process.stdout.write('\x1b[?25l');
+ }
+}
+
+/**
+ * Run the given test `files`.
+ *
+ * @param {Array} files
+ */
+
+function runFiles(files) {
+ files = files.filter(function(file) {
+ return file.match(file_matcher);
+ });
+ suites = files.length;
+
+ if (serial) {
+ (function next() {
+ if (files.length) {
+ runFile(files.shift(), next);
+ }
+ })();
+ } else {
+ files.forEach(runFile);
+ }
+}
+
+/**
+ * Run tests for the given `file`, callback `fn()` when finished.
+ *
+ * @param {String} file
+ * @param {Function} fn
+ */
+
+function runFile(file, fn) {
+ var title = path.basename(file),
+ file = path.join(cwd, file),
+ mod = require(file.replace(file_matcher,''));
+ (function check() {
+ var len = Object.keys(mod).length;
+ if (len) {
+ runSuite(title, mod, fn);
+ suitesRun++;
+ } else {
+ setTimeout(check, 20);
+ }
+ })();
+}
+
+/**
+ * Run the given tests, callback `fn()` when finished.
+ *
+ * @param {String} title
+ * @param {Object} tests
+ * @param {Function} fn
+ */
+
+var dots = 0;
+function runSuite(title, tests, callback) {
+ // Keys
+ var keys = only.length
+ ? only.slice(0)
+ : Object.keys(tests);
+
+ // Regular expression test filter
+ var filter = new RegExp('(?:' + (match.length == 0 ? '.' : match) + ')');
+
+ // Setup
+ var setup = tests.setup || function(fn, assert) { fn(); };
+ var teardown = tests.teardown || function(fn, assert) { fn(); };
+
+ process.setMaxListeners(10 + process.listeners('beforeExit').length + keys.length);
+
+ // Iterate tests
+ (function next() {
+ if (keys.length) {
+ var key,
+ fn = tests[key = keys.shift()];
+
+ // Filter
+ if (filter.test(key) === false) return next();
+
+ // Non-tests
+ if (key === 'setup' || key === 'teardown') return next();
+
+ // Run test
+ if (fn) {
+ var test = new Test({
+ fn: fn,
+ suite: title,
+ title: key,
+ setup: setup,
+ teardown: teardown
+ })
+ test.run(next);
+ } else {
+ // @TODO: Add warning message that there's no test.
+ next();
+ }
+ } else if (serial) {
+ callback();
+ }
+ })();
+}
+
+require('util').inherits(Test, require('events').EventEmitter);
+function Test(options) {
+ for (var key in options) {
+ this[key] = options[key];
+ }
+ this._succeeded = [];
+ this._failed = [];
+ this._pending = [];
+ this._beforeExit = [];
+ this.assert = { __proto__: assert, _test: this };
+
+ var test = this;
+ process.on('beforeExit', function() {
+ try {
+ test.emit('exit');
+ } catch (err) {
+ test.failure(err);
+ }
+ test.report();
+ });
+}
+
+Test.prototype.success = function(err) {
+ this._succeeded.push(err);
+};
+
+Test.prototype.failure = function(err) {
+ this._failed.push(err);
+ this.error(err);
+};
+
+Test.prototype.report = function() {
+ for (var i = 0; i < this._pending.length; i++) {
+ this.error(this._pending[i]);
+ }
+};
+
+Test.prototype.run = function(callback) {
+ try {
+ ++testcount;
+ assert._test = this;
+
+ if (serial) {
+ this.runSerial(callback);
+ } else {
+ // @TODO: find a way to run setup/tearDown.
+ this.runParallel();
+ callback();
+ }
+ } catch (err) {
+ this.failure(err);
+ this.report();
+ }
+};
+
+Test.prototype.runSerial = function(callback) {
+ var test = this;
+ process.stdout.write('.');
+ if (++dots % 25 === 0) console.log();
+ test.setup(function() {
+ if (test.fn.length < 1) {
+ test.fn();
+ test.teardown(callback);
+ } else {
+ var id = setTimeout(function() {
+ throw new Error("'" + test.title + "' timed out");
+ }, timeout);
+ test.callback = function() {
+ clearTimeout(id);
+ test.teardown(callback);
+ process.nextTick(function() {
+ test.report();
+ });
+ };
+ test.fn(test.callback);
+ }
+ });
+};
+
+Test.prototype.runParallel = function() {
+ var test = this;
+ test.fn(function(fn) {
+ test.on('exit', function() {
+ fn(test.assert);
+ });
+ }, test.assert);
+};
+
+/**
+ * Report `err` for the given `test` and `suite`.
+ *
+ * @param {String} suite
+ * @param {String} test
+ * @param {Error} err
+ */
+Test.prototype.error = function(err) {
+ if (!err._reported) {
+ ++failures;
+ var name = err.name,
+ stack = err.stack ? err.stack.replace(err.name, '') : '',
+ label = this.title === 'uncaught'
+ ? this.title
+ : this.suite + ' ' + this.title;
+ print('\n [bold]{' + label + '}: [red]{' + name + '}' + stack + '\n');
+ err._reported = true;
+ }
+}
+
+/**
+* Report exceptions.
+ */
+
+function report() {
+ cursor(true);
+ process.emit('beforeExit');
+ if (suitesRun < suites) {
+ print('\n [bold]{Failure}: [red]{Only ' + suitesRun + ' of ' + suites + ' suites have been started}\n\n');
+ }
+ else if (failures) {
+ print('\n [bold]{Failures}: [red]{' + failures + '}\n\n');
+ notify('Failures: ' + failures);
+ } else {
+ if (serial) print('');
+ print('\n [green]{100%} ' + testcount + ' tests\n');
+ notify('100% ok');
+ }
+ if (typeof _$jscoverage === 'object') {
+ populateCoverage(_$jscoverage);
+ if (!hasFullCoverage(_$jscoverage) || !quiet) {
+ (jsonCoverage ? reportCoverageJson(_$jscoverage) : reportCoverageTable(_$jscoverage));
+ }
+ }
+}
+
+/**
+ * Growl notify the given `msg`.
+ *
+ * @param {String} msg
+ */
+
+function notify(msg) {
+ if (growl) {
+ childProcess.exec('growlnotify -name Expresso -m "' + msg + '"');
+ }
+}
+
+// Report uncaught exceptions
+var unknownTest = new Test({
+ suite: 'uncaught',
+ test: 'uncaught'
+});
+
+process.on('uncaughtException', function(err) {
+ unknownTest.error(err);
+});
+
+// Show cursor
+
+['INT', 'TERM', 'QUIT'].forEach(function(sig) {
+ process.on('SIG' + sig, function() {
+ cursor(true);
+ process.exit(1);
+ });
+});
+
+// Report test coverage when available
+// and emit "beforeExit" event to perform
+// final assertions
+
+var orig = process.emit;
+process.emit = function(event) {
+ if (event === 'exit') {
+ report();
+ process.reallyExit(failures);
+ }
+ orig.apply(this, arguments);
+};
+
+// Run test files
+
+if (!defer) run(files);
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/encoding.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/encoding.Po
new file mode 100644
index 0000000..788e721
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/encoding.Po
@@ -0,0 +1,166 @@
+encoding.o: encoding.c config.h encoding.h /usr/include/stdint.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/include/bits/wchar.h /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h js/jsapi.h \
+ /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
+ /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h js/obj/js-config.h \
+ js/jspubtd.h js/jstypes.h js/obj/jsautocfg.h js/jsotypes.h js/jscompat.h \
+ js/jslong.h js/jsproto.tbl js/jsversion.h js/jsutil.h \
+ /usr/include/assert.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/limits.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/syslimits.h \
+ /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/bits/posix2_lim.h /usr/include/string.h \
+ /usr/include/xlocale.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/bits/string3.h \
+ /usr/include/iconv.h util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h
+
+config.h:
+
+encoding.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+js/jsapi.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+js/obj/js-config.h:
+
+js/jspubtd.h:
+
+js/jstypes.h:
+
+js/obj/jsautocfg.h:
+
+js/jsotypes.h:
+
+js/jscompat.h:
+
+js/jslong.h:
+
+js/jsproto.tbl:
+
+js/jsversion.h:
+
+js/jsutil.h:
+
+/usr/include/assert.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/limits.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/syslimits.h:
+
+/usr/include/limits.h:
+
+/usr/include/bits/posix1_lim.h:
+
+/usr/include/bits/local_lim.h:
+
+/usr/include/linux/limits.h:
+
+/usr/include/bits/posix2_lim.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/iconv.h:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/generate-resources.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/generate-resources.Po
new file mode 100644
index 0000000..06cd018
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/generate-resources.Po
@@ -0,0 +1,105 @@
+generate-resources.o: generate-resources.c /usr/include/ctype.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/xlocale.h /usr/include/stdio.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/sys/types.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h
+
+/usr/include/ctype.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/stdio.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/highlight.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/highlight.Po
new file mode 100644
index 0000000..d54c451
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/highlight.Po
@@ -0,0 +1,196 @@
+highlight.o: highlight.c config.h highlight.h js/jscntxt.h js/jsarena.h \
+ /usr/include/stdlib.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h js/jstypes.h \
+ js/obj/jsautocfg.h js/jsotypes.h js/jscompat.h js/jslong.h js/jsclist.h \
+ js/jsatom.h js/jsversion.h js/jshash.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h js/jsdhash.h \
+ js/jsapi.h js/obj/js-config.h js/jspubtd.h js/jsproto.tbl js/jsutil.h \
+ js/jsprvtd.h js/jslock.h js/jsgc.h js/jsbit.h js/jsinterp.h js/jsfun.h \
+ js/jsobj.h js/jsopcode.h js/jsopcode.tbl js/jsscript.h js/jsregexp.h \
+ js/jsstr.h /usr/include/ctype.h /usr/include/xlocale.h js/js.msg \
+ stream.h /usr/include/stdint.h /usr/include/bits/wchar.h \
+ /usr/include/assert.h /usr/include/string.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/bits/string3.h js/jslock.h \
+ js/jsscan.h js/jskeyword.tbl util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h
+
+config.h:
+
+highlight.h:
+
+js/jscntxt.h:
+
+js/jsarena.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+js/jstypes.h:
+
+js/obj/jsautocfg.h:
+
+js/jsotypes.h:
+
+js/jscompat.h:
+
+js/jslong.h:
+
+js/jsclist.h:
+
+js/jsatom.h:
+
+js/jsversion.h:
+
+js/jshash.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+js/jsdhash.h:
+
+js/jsapi.h:
+
+js/obj/js-config.h:
+
+js/jspubtd.h:
+
+js/jsproto.tbl:
+
+js/jsutil.h:
+
+js/jsprvtd.h:
+
+js/jslock.h:
+
+js/jsgc.h:
+
+js/jsbit.h:
+
+js/jsinterp.h:
+
+js/jsfun.h:
+
+js/jsobj.h:
+
+js/jsopcode.h:
+
+js/jsopcode.tbl:
+
+js/jsscript.h:
+
+js/jsregexp.h:
+
+js/jsstr.h:
+
+/usr/include/ctype.h:
+
+/usr/include/xlocale.h:
+
+js/js.msg:
+
+stream.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/assert.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+js/jslock.h:
+
+js/jsscan.h:
+
+js/jskeyword.tbl:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-connection.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-connection.Po
new file mode 100644
index 0000000..2676d36
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-connection.Po
@@ -0,0 +1,190 @@
+http-connection.o: http-connection.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/assert.h /usr/include/string.h /usr/include/xlocale.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h util.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h /usr/include/errno.h /usr/include/bits/errno.h \
+ /usr/include/linux/errno.h /usr/include/asm/errno.h \
+ /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/assert.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+/usr/include/errno.h:
+
+/usr/include/bits/errno.h:
+
+/usr/include/linux/errno.h:
+
+/usr/include/asm/errno.h:
+
+/usr/include/asm-generic/errno.h:
+
+/usr/include/asm-generic/errno-base.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-exchange.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-exchange.Po
new file mode 100644
index 0000000..c10e985
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-exchange.Po
@@ -0,0 +1,178 @@
+http-exchange.o: http-exchange.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/assert.h /usr/include/ctype.h /usr/include/xlocale.h \
+ /usr/include/string.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/bits/string3.h util.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/assert.h:
+
+/usr/include/ctype.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-host.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-host.Po
new file mode 100644
index 0000000..7ff79f1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-host.Po
@@ -0,0 +1,161 @@
+http-host.o: http-host.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h util.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-message.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-message.Po
new file mode 100644
index 0000000..15fa835
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-message.Po
@@ -0,0 +1,176 @@
+http-message.o: http-message.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/assert.h /usr/include/string.h /usr/include/xlocale.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h util.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/assert.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-server.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-server.Po
new file mode 100644
index 0000000..ef3908e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-server.Po
@@ -0,0 +1,183 @@
+http-server.o: http-server.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/string.h /usr/include/xlocale.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/bits/string3.h \
+ /usr/include/pthread.h /usr/include/sched.h /usr/include/bits/sched.h \
+ /usr/include/bits/setjmp.h util.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/pthread.h:
+
+/usr/include/sched.h:
+
+/usr/include/bits/sched.h:
+
+/usr/include/bits/setjmp.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-url.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-url.Po
new file mode 100644
index 0000000..438b6ba
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-url.Po
@@ -0,0 +1,176 @@
+http-url.o: http-url.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/ctype.h /usr/include/xlocale.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h util.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/ctype.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/instrument-js.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/instrument-js.Po
new file mode 100644
index 0000000..ab7680e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/instrument-js.Po
@@ -0,0 +1,249 @@
+instrument-js.o: instrument-js.cpp config.h instrument-js.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h stream.h \
+ /usr/include/stdio.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/xlocale.h /usr/include/sys/types.h /usr/include/time.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h /usr/include/assert.h \
+ /usr/include/math.h /usr/include/bits/huge_val.h \
+ /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
+ /usr/include/bits/inf.h /usr/include/bits/nan.h \
+ /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
+ /usr/include/bits/mathinline.h /usr/include/string.h \
+ /usr/include/bits/string3.h js/jsapi.h js/obj/js-config.h js/jspubtd.h \
+ js/jstypes.h js/obj/jsautocfg.h js/jsotypes.h js/jscompat.h js/jslong.h \
+ js/jsproto.tbl js/jsversion.h js/jsutil.h js/jsarena.h js/jsatom.h \
+ js/jshash.h js/jsdhash.h js/jsapi.h js/jsprvtd.h js/jslock.h js/jsemit.h \
+ js/jsstddef.h js/jsatom.h js/jsopcode.h js/jsopcode.tbl js/jsscript.h \
+ js/jsexn.h js/jsfun.h js/jsobj.h js/jsinterp.h js/jsfun.h js/jsiter.h \
+ js/jsparse.h js/jsscan.h js/jskeyword.tbl js/jsregexp.h js/jsstr.h \
+ /usr/include/ctype.h js/jsscope.h js/jsstr.h encoding.h global.h \
+ highlight.h js/jscntxt.h js/jsarena.h js/jsclist.h js/jsgc.h js/jsbit.h \
+ js/jsinterp.h js/jsregexp.h js/js.msg resource-manager.h
+
+config.h:
+
+instrument-js.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+/usr/include/assert.h:
+
+/usr/include/math.h:
+
+/usr/include/bits/huge_val.h:
+
+/usr/include/bits/huge_valf.h:
+
+/usr/include/bits/huge_vall.h:
+
+/usr/include/bits/inf.h:
+
+/usr/include/bits/nan.h:
+
+/usr/include/bits/mathdef.h:
+
+/usr/include/bits/mathcalls.h:
+
+/usr/include/bits/mathinline.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string3.h:
+
+js/jsapi.h:
+
+js/obj/js-config.h:
+
+js/jspubtd.h:
+
+js/jstypes.h:
+
+js/obj/jsautocfg.h:
+
+js/jsotypes.h:
+
+js/jscompat.h:
+
+js/jslong.h:
+
+js/jsproto.tbl:
+
+js/jsversion.h:
+
+js/jsutil.h:
+
+js/jsarena.h:
+
+js/jsatom.h:
+
+js/jshash.h:
+
+js/jsdhash.h:
+
+js/jsapi.h:
+
+js/jsprvtd.h:
+
+js/jslock.h:
+
+js/jsemit.h:
+
+js/jsstddef.h:
+
+js/jsatom.h:
+
+js/jsopcode.h:
+
+js/jsopcode.tbl:
+
+js/jsscript.h:
+
+js/jsexn.h:
+
+js/jsfun.h:
+
+js/jsobj.h:
+
+js/jsinterp.h:
+
+js/jsfun.h:
+
+js/jsiter.h:
+
+js/jsparse.h:
+
+js/jsscan.h:
+
+js/jskeyword.tbl:
+
+js/jsregexp.h:
+
+js/jsstr.h:
+
+/usr/include/ctype.h:
+
+js/jsscope.h:
+
+js/jsstr.h:
+
+encoding.h:
+
+global.h:
+
+highlight.h:
+
+js/jscntxt.h:
+
+js/jsarena.h:
+
+js/jsclist.h:
+
+js/jsgc.h:
+
+js/jsbit.h:
+
+js/jsinterp.h:
+
+js/jsregexp.h:
+
+js/js.msg:
+
+resource-manager.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/instrument.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/instrument.Po
new file mode 100644
index 0000000..1971764
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/instrument.Po
@@ -0,0 +1,182 @@
+instrument.o: instrument.c config.h instrument.h /usr/include/assert.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/include/errno.h /usr/include/bits/errno.h \
+ /usr/include/linux/errno.h /usr/include/asm/errno.h \
+ /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
+ /usr/include/string.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/xlocale.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/stdlib.h /usr/include/bits/string3.h /usr/include/dirent.h \
+ /usr/include/bits/dirent.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/sys/stat.h /usr/include/time.h /usr/include/bits/stat.h \
+ /usr/include/sys/types.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h encoding.h /usr/include/stdint.h \
+ /usr/include/bits/wchar.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/alloca.h \
+ /usr/include/bits/stdlib.h js/jsapi.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h js/obj/js-config.h \
+ js/jspubtd.h js/jstypes.h js/obj/jsautocfg.h js/jsotypes.h js/jscompat.h \
+ js/jslong.h js/jsproto.tbl js/jsversion.h js/jsutil.h global.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h instrument-js.h \
+ stream.h util.h resource-manager.h
+
+config.h:
+
+instrument.h:
+
+/usr/include/assert.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/errno.h:
+
+/usr/include/bits/errno.h:
+
+/usr/include/linux/errno.h:
+
+/usr/include/asm/errno.h:
+
+/usr/include/asm-generic/errno.h:
+
+/usr/include/asm-generic/errno-base.h:
+
+/usr/include/string.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/dirent.h:
+
+/usr/include/bits/dirent.h:
+
+/usr/include/bits/posix1_lim.h:
+
+/usr/include/bits/local_lim.h:
+
+/usr/include/linux/limits.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/time.h:
+
+/usr/include/bits/stat.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+encoding.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+js/jsapi.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+js/obj/js-config.h:
+
+js/jspubtd.h:
+
+js/jstypes.h:
+
+js/obj/jsautocfg.h:
+
+js/jsotypes.h:
+
+js/jscompat.h:
+
+js/jslong.h:
+
+js/jsproto.tbl:
+
+js/jsversion.h:
+
+js/jsutil.h:
+
+global.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+instrument-js.h:
+
+stream.h:
+
+util.h:
+
+resource-manager.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage-server.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage-server.Po
new file mode 100644
index 0000000..044b1fd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage-server.Po
@@ -0,0 +1,252 @@
+jscoverage-server.o: jscoverage-server.c config.h /usr/include/assert.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/include/ctype.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/xlocale.h /usr/include/signal.h /usr/include/bits/sigset.h \
+ /usr/include/bits/signum.h /usr/include/time.h \
+ /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h \
+ /usr/include/bits/sigcontext.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/sigstack.h /usr/include/sys/ucontext.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/bits/sigthread.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/stdlib.h /usr/include/bits/string3.h /usr/include/dirent.h \
+ /usr/include/bits/dirent.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/pthread.h /usr/include/sched.h /usr/include/bits/sched.h \
+ /usr/include/bits/time.h /usr/include/bits/setjmp.h encoding.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/sys/types.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/sys/sysmacros.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h js/jsapi.h \
+ /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
+ /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h js/obj/js-config.h \
+ js/jspubtd.h js/jstypes.h js/obj/jsautocfg.h js/jsotypes.h js/jscompat.h \
+ js/jslong.h js/jsproto.tbl js/jsversion.h js/jsutil.h global.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h http-server.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h instrument-js.h util.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h resource-manager.h
+
+config.h:
+
+/usr/include/assert.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/ctype.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/signal.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/signum.h:
+
+/usr/include/time.h:
+
+/usr/include/bits/siginfo.h:
+
+/usr/include/bits/sigaction.h:
+
+/usr/include/bits/sigcontext.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/sigstack.h:
+
+/usr/include/sys/ucontext.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/bits/sigthread.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/dirent.h:
+
+/usr/include/bits/dirent.h:
+
+/usr/include/bits/posix1_lim.h:
+
+/usr/include/bits/local_lim.h:
+
+/usr/include/linux/limits.h:
+
+/usr/include/pthread.h:
+
+/usr/include/sched.h:
+
+/usr/include/bits/sched.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/bits/setjmp.h:
+
+encoding.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+js/jsapi.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+js/obj/js-config.h:
+
+js/jspubtd.h:
+
+js/jstypes.h:
+
+js/obj/jsautocfg.h:
+
+js/jsotypes.h:
+
+js/jscompat.h:
+
+js/jslong.h:
+
+js/jsproto.tbl:
+
+js/jsversion.h:
+
+js/jsutil.h:
+
+global.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+http-server.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+instrument-js.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+resource-manager.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage.Po
new file mode 100644
index 0000000..6799cc5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage.Po
@@ -0,0 +1,126 @@
+jscoverage.o: jscoverage.c config.h /usr/include/stdio.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/bits/stdlib.h /usr/include/string.h /usr/include/xlocale.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h global.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h instrument.h \
+ instrument-js.h /usr/include/stdint.h /usr/include/bits/wchar.h stream.h \
+ util.h /usr/include/sys/stat.h /usr/include/bits/stat.h \
+ resource-manager.h
+
+config.h:
+
+/usr/include/stdio.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+global.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+instrument.h:
+
+instrument-js.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+stream.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+resource-manager.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/resource-manager.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/resource-manager.Po
new file mode 100644
index 0000000..2f5fc3c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/resource-manager.Po
@@ -0,0 +1,116 @@
+resource-manager.o: resource-manager.c config.h resource-manager.h \
+ /usr/include/stdio.h /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/bits/stdlib.h /usr/include/assert.h /usr/include/string.h \
+ /usr/include/xlocale.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/bits/string3.h util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h resources.c
+
+config.h:
+
+resource-manager.h:
+
+/usr/include/stdio.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/assert.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+resources.c:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/stream.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/stream.Po
new file mode 100644
index 0000000..6e13a4c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/stream.Po
@@ -0,0 +1,117 @@
+stream.o: stream.c config.h stream.h /usr/include/stdio.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/stdlib.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/xlocale.h \
+ /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/bits/stdlib.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h
+
+config.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/util.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/util.Po
new file mode 100644
index 0000000..3233dfb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/util.Po
@@ -0,0 +1,177 @@
+util.o: util.c config.h util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdio.h /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/xlocale.h /usr/include/sys/types.h /usr/include/time.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h /usr/include/assert.h /usr/include/errno.h \
+ /usr/include/bits/errno.h /usr/include/linux/errno.h \
+ /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
+ /usr/include/asm-generic/errno-base.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/limits.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/syslimits.h \
+ /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/bits/posix2_lim.h /usr/include/bits/xopen_lim.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h /usr/include/strings.h /usr/include/dirent.h \
+ /usr/include/bits/dirent.h /usr/include/libgen.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h
+
+config.h:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdio.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+/usr/include/assert.h:
+
+/usr/include/errno.h:
+
+/usr/include/bits/errno.h:
+
+/usr/include/linux/errno.h:
+
+/usr/include/asm/errno.h:
+
+/usr/include/asm-generic/errno.h:
+
+/usr/include/asm-generic/errno-base.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/limits.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/syslimits.h:
+
+/usr/include/limits.h:
+
+/usr/include/bits/posix1_lim.h:
+
+/usr/include/bits/local_lim.h:
+
+/usr/include/linux/limits.h:
+
+/usr/include/bits/posix2_lim.h:
+
+/usr/include/bits/xopen_lim.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/strings.h:
+
+/usr/include/dirent.h:
+
+/usr/include/bits/dirent.h:
+
+/usr/include/libgen.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/COPYING b/tools/node_modules/expresso/deps/jscoverage/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/tools/node_modules/expresso/deps/jscoverage/Makefile b/tools/node_modules/expresso/deps/jscoverage/Makefile
new file mode 100644
index 0000000..df3509d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/Makefile
@@ -0,0 +1,884 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# Makefile. Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+# Makefile.am - builds jscoverage
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+pkgdatadir = $(datadir)/jscoverage
+pkglibdir = $(libdir)/jscoverage
+pkgincludedir = $(includedir)/jscoverage
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-unknown-linux-gnu
+host_triplet = x86_64-unknown-linux-gnu
+bin_PROGRAMS = jscoverage$(EXEEXT) jscoverage-server$(EXEEXT)
+noinst_PROGRAMS = generate-resources$(EXEEXT)
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(dist_man_MANS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/config.h.in $(srcdir)/make-bin-dist.sh.in \
+ $(srcdir)/make-dist.sh.in $(top_srcdir)/configure COPYING \
+ config.guess config.rpath config.sub depcomp install-sh \
+ missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = make-dist.sh make-bin-dist.sh
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+am_generate_resources_OBJECTS = generate-resources.$(OBJEXT)
+generate_resources_OBJECTS = $(am_generate_resources_OBJECTS)
+generate_resources_LDADD = $(LDADD)
+am__objects_1 =
+am_jscoverage_OBJECTS = encoding.$(OBJEXT) highlight.$(OBJEXT) \
+ instrument.$(OBJEXT) instrument-js.$(OBJEXT) \
+ jscoverage.$(OBJEXT) resource-manager.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT) $(am__objects_1)
+jscoverage_OBJECTS = $(am_jscoverage_OBJECTS)
+jscoverage_DEPENDENCIES = js/obj/libjs.a
+am_jscoverage_server_OBJECTS = http-connection.$(OBJEXT) \
+ http-exchange.$(OBJEXT) http-host.$(OBJEXT) \
+ http-message.$(OBJEXT) http-server.$(OBJEXT) \
+ http-url.$(OBJEXT) encoding.$(OBJEXT) highlight.$(OBJEXT) \
+ instrument-js.$(OBJEXT) jscoverage-server.$(OBJEXT) \
+ resource-manager.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT) \
+ $(am__objects_1)
+jscoverage_server_OBJECTS = $(am_jscoverage_server_OBJECTS)
+jscoverage_server_DEPENDENCIES = js/obj/libjs.a
+DEFAULT_INCLUDES = -I.
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(generate_resources_SOURCES) $(jscoverage_SOURCES) \
+ $(jscoverage_server_SOURCES)
+DIST_SOURCES = $(generate_resources_SOURCES) $(jscoverage_SOURCES) \
+ $(jscoverage_server_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(dist_man_MANS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run aclocal-1.10
+AMTAR = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run tar
+AUTOCONF = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoconf
+AUTOHEADER = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoheader
+AUTOMAKE = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run automake-1.10
+AWK = gawk
+CC = gcc -std=gnu99
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -std=gnu99 -E
+CPPFLAGS =
+CXX = g++
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = /bin/grep -E
+EXEEXT =
+EXTRA_SOCKET_LIBS =
+EXTRA_THREAD_LIBS = -lpthread
+EXTRA_TIMER_LIBS =
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS =
+LIBICONV =
+LIBOBJS =
+LIBS =
+LTLIBICONV =
+LTLIBOBJS =
+MAKEINFO = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJEXT = o
+PACKAGE = jscoverage
+PACKAGE_BUGREPORT =
+PACKAGE_NAME = jscoverage
+PACKAGE_STRING = jscoverage 0.4
+PACKAGE_TARNAME = jscoverage
+PACKAGE_VERSION = 0.4
+PATH_SEPARATOR = :
+SET_MAKE =
+SHELL = /bin/sh
+STRIP =
+VERSION = 0.4
+XP_DEF = -DXP_UNIX
+abs_builddir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+abs_srcdir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+abs_top_builddir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+abs_top_srcdir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-unknown-linux-gnu
+build_alias =
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = unknown
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-unknown-linux-gnu
+host_alias =
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = unknown
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = $(SHELL) /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = /bin/mkdir -p
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias =
+top_builddir = .
+top_srcdir = .
+ACLOCAL_AMFLAGS = -I m4
+SUBDIRS = js
+AM_CFLAGS = -Ijs -Ijs/obj -DXP_UNIX
+AM_CXXFLAGS = -Ijs -Ijs/obj -DXP_UNIX
+resources = jscoverage-help.txt jscoverage-server-help.txt \
+ jscoverage.jsm jscoverage.manifest jscoverage.xul jscoverage-overlay.js \
+ jscoverage.html \
+ jscoverage.css jscoverage-ie.css jscoverage-highlight.css \
+ jscoverage.js report.js \
+ jscoverage-throbber.gif
+
+jscoverage_SOURCES = encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument.c instrument.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+
+jscoverage_LDADD = js/obj/libjs.a -lm
+jscoverage_server_SOURCES = http-connection.c \
+ http-exchange.c \
+ http-host.c \
+ http-message.c \
+ http-server.c http-server.h \
+ http-url.c \
+ encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage-server.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+
+jscoverage_server_LDADD = js/obj/libjs.a -lm -lpthread
+generate_resources_SOURCES = generate-resources.c
+BUILT_SOURCES = resources.c
+dist_man_MANS = jscoverage.1 jscoverage-server.1
+CLEANFILES = *.gcno *.exe resources.c *~
+all: $(BUILT_SOURCES) config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+ cd $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+make-dist.sh: $(top_builddir)/config.status $(srcdir)/make-dist.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+make-bin-dist.sh: $(top_builddir)/config.status $(srcdir)/make-bin-dist.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+generate-resources$(EXEEXT): $(generate_resources_OBJECTS) $(generate_resources_DEPENDENCIES)
+ @rm -f generate-resources$(EXEEXT)
+ $(LINK) $(generate_resources_OBJECTS) $(generate_resources_LDADD) $(LIBS)
+jscoverage$(EXEEXT): $(jscoverage_OBJECTS) $(jscoverage_DEPENDENCIES)
+ @rm -f jscoverage$(EXEEXT)
+ $(CXXLINK) $(jscoverage_OBJECTS) $(jscoverage_LDADD) $(LIBS)
+jscoverage-server$(EXEEXT): $(jscoverage_server_OBJECTS) $(jscoverage_server_DEPENDENCIES)
+ @rm -f jscoverage-server$(EXEEXT)
+ $(CXXLINK) $(jscoverage_server_OBJECTS) $(jscoverage_server_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+include ./$(DEPDIR)/encoding.Po
+include ./$(DEPDIR)/generate-resources.Po
+include ./$(DEPDIR)/highlight.Po
+include ./$(DEPDIR)/http-connection.Po
+include ./$(DEPDIR)/http-exchange.Po
+include ./$(DEPDIR)/http-host.Po
+include ./$(DEPDIR)/http-message.Po
+include ./$(DEPDIR)/http-server.Po
+include ./$(DEPDIR)/http-url.Po
+include ./$(DEPDIR)/instrument-js.Po
+include ./$(DEPDIR)/instrument.Po
+include ./$(DEPDIR)/jscoverage-server.Po
+include ./$(DEPDIR)/jscoverage.Po
+include ./$(DEPDIR)/resource-manager.Po
+include ./$(DEPDIR)/stream.Po
+include ./$(DEPDIR)/util.Po
+
+.c.o:
+ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.cpp.o:
+ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+install-man1: $(man1_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \
+ rm -f "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d $(distdir) || mkdir $(distdir)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r $(distdir)
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
+all-am: Makefile $(PROGRAMS) $(MANS) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-recursive
+
+clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-recursive
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man: install-man1
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-man
+
+uninstall-man: uninstall-man1
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+ install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am am--refresh check check-am clean clean-binPROGRAMS \
+ clean-generic clean-noinstPROGRAMS ctags ctags-recursive dist \
+ dist-all dist-bzip2 dist-gzip dist-lzma dist-shar dist-tarZ \
+ dist-zip distcheck distclean distclean-compile \
+ distclean-generic distclean-hdr distclean-tags distcleancheck \
+ distdir distuninstallcheck dvi dvi-am html html-am info \
+ info-am install install-am install-binPROGRAMS install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-man1 install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-man uninstall-man1
+
+
+resources.c: generate-resources $(resources)
+ $(srcdir)/generate-resources $(resources) > $@
+
+example: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example doc/instrumented
+
+example-inverted: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example-inverted doc/instrumented-inverted
+
+example-jsunit: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn --no-instrument=jsunit doc/example-jsunit doc/instrumented-jsunit
+
+# override default install target so as not to recursively install subpackages
+install: install-am
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tools/node_modules/expresso/deps/jscoverage/Makefile.am b/tools/node_modules/expresso/deps/jscoverage/Makefile.am
new file mode 100644
index 0000000..2b36e6b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/Makefile.am
@@ -0,0 +1,81 @@
+# Makefile.am - builds jscoverage
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = js
+
+AM_CFLAGS = -Ijs -Ijs/obj @XP_DEF@
+AM_CXXFLAGS = -Ijs -Ijs/obj @XP_DEF@
+
+resources = jscoverage-help.txt jscoverage-server-help.txt \
+ jscoverage.jsm jscoverage.manifest jscoverage.xul jscoverage-overlay.js \
+ jscoverage.html \
+ jscoverage.css jscoverage-ie.css jscoverage-highlight.css \
+ jscoverage.js report.js \
+ jscoverage-throbber.gif
+
+bin_PROGRAMS = jscoverage jscoverage-server
+jscoverage_SOURCES = encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument.c instrument.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+jscoverage_LDADD = js/obj/libjs.a -lm @LIBICONV@ @EXTRA_TIMER_LIBS@
+jscoverage_server_SOURCES = http-connection.c \
+ http-exchange.c \
+ http-host.c \
+ http-message.c \
+ http-server.c http-server.h \
+ http-url.c \
+ encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage-server.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+jscoverage_server_LDADD = js/obj/libjs.a -lm @EXTRA_SOCKET_LIBS@ @EXTRA_THREAD_LIBS@ @LIBICONV@ @EXTRA_TIMER_LIBS@
+
+noinst_PROGRAMS = generate-resources
+generate_resources_SOURCES = generate-resources.c
+
+BUILT_SOURCES = resources.c
+
+resources.c: generate-resources $(resources)
+ $(srcdir)/generate-resources $(resources) > $@
+
+dist_man_MANS = jscoverage.1 jscoverage-server.1
+
+CLEANFILES = *.gcno *.exe resources.c *~
+
+example: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example doc/instrumented
+
+example-inverted: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example-inverted doc/instrumented-inverted
+
+example-jsunit: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn --no-instrument=jsunit doc/example-jsunit doc/instrumented-jsunit
+
+# override default install target so as not to recursively install subpackages
+install: install-am
diff --git a/tools/node_modules/expresso/deps/jscoverage/Makefile.in b/tools/node_modules/expresso/deps/jscoverage/Makefile.in
new file mode 100644
index 0000000..a81160d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/Makefile.in
@@ -0,0 +1,884 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am - builds jscoverage
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = jscoverage$(EXEEXT) jscoverage-server$(EXEEXT)
+noinst_PROGRAMS = generate-resources$(EXEEXT)
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(dist_man_MANS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/config.h.in $(srcdir)/make-bin-dist.sh.in \
+ $(srcdir)/make-dist.sh.in $(top_srcdir)/configure COPYING \
+ config.guess config.rpath config.sub depcomp install-sh \
+ missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = make-dist.sh make-bin-dist.sh
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+am_generate_resources_OBJECTS = generate-resources.$(OBJEXT)
+generate_resources_OBJECTS = $(am_generate_resources_OBJECTS)
+generate_resources_LDADD = $(LDADD)
+am__objects_1 =
+am_jscoverage_OBJECTS = encoding.$(OBJEXT) highlight.$(OBJEXT) \
+ instrument.$(OBJEXT) instrument-js.$(OBJEXT) \
+ jscoverage.$(OBJEXT) resource-manager.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT) $(am__objects_1)
+jscoverage_OBJECTS = $(am_jscoverage_OBJECTS)
+jscoverage_DEPENDENCIES = js/obj/libjs.a
+am_jscoverage_server_OBJECTS = http-connection.$(OBJEXT) \
+ http-exchange.$(OBJEXT) http-host.$(OBJEXT) \
+ http-message.$(OBJEXT) http-server.$(OBJEXT) \
+ http-url.$(OBJEXT) encoding.$(OBJEXT) highlight.$(OBJEXT) \
+ instrument-js.$(OBJEXT) jscoverage-server.$(OBJEXT) \
+ resource-manager.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT) \
+ $(am__objects_1)
+jscoverage_server_OBJECTS = $(am_jscoverage_server_OBJECTS)
+jscoverage_server_DEPENDENCIES = js/obj/libjs.a
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(generate_resources_SOURCES) $(jscoverage_SOURCES) \
+ $(jscoverage_server_SOURCES)
+DIST_SOURCES = $(generate_resources_SOURCES) $(jscoverage_SOURCES) \
+ $(jscoverage_server_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(dist_man_MANS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@
+EXTRA_THREAD_LIBS = @EXTRA_THREAD_LIBS@
+EXTRA_TIMER_LIBS = @EXTRA_TIMER_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBICONV = @LTLIBICONV@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+XP_DEF = @XP_DEF@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I m4
+SUBDIRS = js
+AM_CFLAGS = -Ijs -Ijs/obj @XP_DEF@
+AM_CXXFLAGS = -Ijs -Ijs/obj @XP_DEF@
+resources = jscoverage-help.txt jscoverage-server-help.txt \
+ jscoverage.jsm jscoverage.manifest jscoverage.xul jscoverage-overlay.js \
+ jscoverage.html \
+ jscoverage.css jscoverage-ie.css jscoverage-highlight.css \
+ jscoverage.js report.js \
+ jscoverage-throbber.gif
+
+jscoverage_SOURCES = encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument.c instrument.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+
+jscoverage_LDADD = js/obj/libjs.a -lm @LIBICONV@ @EXTRA_TIMER_LIBS@
+jscoverage_server_SOURCES = http-connection.c \
+ http-exchange.c \
+ http-host.c \
+ http-message.c \
+ http-server.c http-server.h \
+ http-url.c \
+ encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage-server.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+
+jscoverage_server_LDADD = js/obj/libjs.a -lm @EXTRA_SOCKET_LIBS@ @EXTRA_THREAD_LIBS@ @LIBICONV@ @EXTRA_TIMER_LIBS@
+generate_resources_SOURCES = generate-resources.c
+BUILT_SOURCES = resources.c
+dist_man_MANS = jscoverage.1 jscoverage-server.1
+CLEANFILES = *.gcno *.exe resources.c *~
+all: $(BUILT_SOURCES) config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+ cd $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+make-dist.sh: $(top_builddir)/config.status $(srcdir)/make-dist.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+make-bin-dist.sh: $(top_builddir)/config.status $(srcdir)/make-bin-dist.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+generate-resources$(EXEEXT): $(generate_resources_OBJECTS) $(generate_resources_DEPENDENCIES)
+ @rm -f generate-resources$(EXEEXT)
+ $(LINK) $(generate_resources_OBJECTS) $(generate_resources_LDADD) $(LIBS)
+jscoverage$(EXEEXT): $(jscoverage_OBJECTS) $(jscoverage_DEPENDENCIES)
+ @rm -f jscoverage$(EXEEXT)
+ $(CXXLINK) $(jscoverage_OBJECTS) $(jscoverage_LDADD) $(LIBS)
+jscoverage-server$(EXEEXT): $(jscoverage_server_OBJECTS) $(jscoverage_server_DEPENDENCIES)
+ @rm -f jscoverage-server$(EXEEXT)
+ $(CXXLINK) $(jscoverage_server_OBJECTS) $(jscoverage_server_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoding.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-resources.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/highlight.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-connection.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-exchange.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-host.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-message.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-url.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instrument-js.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instrument.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jscoverage-server.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jscoverage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resource-manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+install-man1: $(man1_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \
+ rm -f "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d $(distdir) || mkdir $(distdir)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r $(distdir)
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
+all-am: Makefile $(PROGRAMS) $(MANS) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-recursive
+
+clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-recursive
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man: install-man1
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-man
+
+uninstall-man: uninstall-man1
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+ install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am am--refresh check check-am clean clean-binPROGRAMS \
+ clean-generic clean-noinstPROGRAMS ctags ctags-recursive dist \
+ dist-all dist-bzip2 dist-gzip dist-lzma dist-shar dist-tarZ \
+ dist-zip distcheck distclean distclean-compile \
+ distclean-generic distclean-hdr distclean-tags distcleancheck \
+ distdir distuninstallcheck dvi dvi-am html html-am info \
+ info-am install install-am install-binPROGRAMS install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-man1 install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-man uninstall-man1
+
+
+resources.c: generate-resources $(resources)
+ $(srcdir)/generate-resources $(resources) > $@
+
+example: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example doc/instrumented
+
+example-inverted: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example-inverted doc/instrumented-inverted
+
+example-jsunit: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn --no-instrument=jsunit doc/example-jsunit doc/instrumented-jsunit
+
+# override default install target so as not to recursively install subpackages
+install: install-am
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tools/node_modules/expresso/deps/jscoverage/Readme.md b/tools/node_modules/expresso/deps/jscoverage/Readme.md
new file mode 100644
index 0000000..7d7bda7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/Readme.md
@@ -0,0 +1,8 @@
+# node-jscoverage
+
+ [JScoverage](http://siliconforks.com/jscoverage/) for node.
+
+## Installation
+
+ $ ./configure && make && make install
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/aclocal.m4 b/tools/node_modules/expresso/deps/jscoverage/aclocal.m4
new file mode 100644
index 0000000..8c0fb02
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/aclocal.m4
@@ -0,0 +1,872 @@
+# generated automatically by aclocal 1.10.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(AC_AUTOCONF_VERSION, [2.61],,
+[m4_warning([this file was generated for autoconf 2.61.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.10'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.10.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.10.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(AC_AUTOCONF_VERSION)])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], UPC, [depcc="$UPC" am_compiler_list=],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 13
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.60])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/iconv.m4])
+m4_include([m4/lib-ld.m4])
+m4_include([m4/lib-link.m4])
+m4_include([m4/lib-prefix.m4])
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.guess b/tools/node_modules/expresso/deps/jscoverage/config.guess
new file mode 100755
index 0000000..f32079a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.guess
@@ -0,0 +1,1526 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
+
+timestamp='2008-01-23'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[456])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:[3456]*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ EM64T | authenticamd)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^LIBC/{
+ s: ::g
+ p
+ }'`"
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.h b/tools/node_modules/expresso/deps/jscoverage/config.h
new file mode 100644
index 0000000..ece8c61
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.h
@@ -0,0 +1,93 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the `asprintf' function. */
+#define HAVE_ASPRINTF 1
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+#define HAVE_GETHOSTBYNAME_R 1
+
+/* Define if you have the iconv() function and it works. */
+#define HAVE_ICONV 1
+
+/* Define to 1 if you have the <iconv.h> header file. */
+#define HAVE_ICONV_H 1
+
+/* Define to 1 if you have the `inet_aton' function. */
+#define HAVE_INET_ATON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `MultiByteToWideChar' function. */
+/* #undef HAVE_MULTIBYTETOWIDECHAR */
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#define HAVE_PTHREAD_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strndup' function. */
+#define HAVE_STRNDUP 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+
+/* Define to 1 if you have the <windows.h> header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define as const if the declaration of iconv() needs const. */
+#define ICONV_CONST
+
+/* Name of package */
+#define PACKAGE "jscoverage"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "jscoverage"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "jscoverage 0.4"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "jscoverage"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.4"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "0.4"
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.h.in b/tools/node_modules/expresso/deps/jscoverage/config.h.in
new file mode 100644
index 0000000..fb3f802
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.h.in
@@ -0,0 +1,92 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define if you have the iconv() function and it works. */
+#undef HAVE_ICONV
+
+/* Define to 1 if you have the <iconv.h> header file. */
+#undef HAVE_ICONV_H
+
+/* Define to 1 if you have the `inet_aton' function. */
+#undef HAVE_INET_ATON
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `MultiByteToWideChar' function. */
+#undef HAVE_MULTIBYTETOWIDECHAR
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strndup' function. */
+#undef HAVE_STRNDUP
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vasprintf' function. */
+#undef HAVE_VASPRINTF
+
+/* Define to 1 if you have the <windows.h> header file. */
+#undef HAVE_WINDOWS_H
+
+/* Define as const if the declaration of iconv() needs const. */
+#undef ICONV_CONST
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.log b/tools/node_modules/expresso/deps/jscoverage/config.log
new file mode 100644
index 0000000..8600990
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.log
@@ -0,0 +1,899 @@
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by jscoverage configure 0.4, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ ./configure
+
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = happy.bec-systems.com
+uname -m = x86_64
+uname -r = 2.6.35-30-generic
+uname -s = Linux
+uname -v = #54-Ubuntu SMP Tue Jun 7 18:41:54 UTC 2011
+
+/usr/bin/uname -p = unknown
+/bin/uname -X = unknown
+
+/bin/arch = unknown
+/usr/bin/arch -k = unknown
+/usr/convex/getsysinfo = unknown
+/usr/bin/hostinfo = unknown
+/bin/machine = unknown
+/usr/bin/oslevel = unknown
+/bin/universe = unknown
+
+PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin
+PATH: /scratch/oe/oe-admin/tools/node_modules/expresso/node_modules/.bin
+PATH: /scratch/oe/oe-admin/tools/node_modules/.bin
+PATH: /home/cbrake/bin
+PATH: /home/cbrake/bin
+PATH: /usr/local/sbin
+PATH: /usr/local/bin
+PATH: /usr/sbin
+PATH: /usr/bin
+PATH: /sbin
+PATH: /bin
+PATH: /usr/games
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+configure:1807: checking for a BSD-compatible install
+configure:1863: result: /usr/bin/install -c
+configure:1874: checking whether build environment is sane
+configure:1917: result: yes
+configure:1945: checking for a thread-safe mkdir -p
+configure:1984: result: /bin/mkdir -p
+configure:1997: checking for gawk
+configure:2013: found /usr/bin/gawk
+configure:2024: result: gawk
+configure:2035: checking whether make sets $(MAKE)
+configure:2056: result: yes
+configure:2253: checking build system type
+configure:2271: result: x86_64-unknown-linux-gnu
+configure:2293: checking host system type
+configure:2308: result: x86_64-unknown-linux-gnu
+configure:2380: checking for gcc
+configure:2396: found /usr/bin/gcc
+configure:2407: result: gcc
+configure:2645: checking for C compiler version
+configure:2652: gcc --version >&5
+gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
+Copyright (C) 2010 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+configure:2655: $? = 0
+configure:2662: gcc -v >&5
+Using built-in specs.
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.4.4-14ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)
+configure:2665: $? = 0
+configure:2672: gcc -V >&5
+gcc: '-V' option must have argument
+configure:2675: $? = 1
+configure:2698: checking for C compiler default output file name
+configure:2725: gcc conftest.c >&5
+configure:2728: $? = 0
+configure:2766: result: a.out
+configure:2783: checking whether the C compiler works
+configure:2793: ./a.out
+configure:2796: $? = 0
+configure:2813: result: yes
+configure:2820: checking whether we are cross compiling
+configure:2822: result: no
+configure:2825: checking for suffix of executables
+configure:2832: gcc -o conftest conftest.c >&5
+configure:2835: $? = 0
+configure:2859: result:
+configure:2865: checking for suffix of object files
+configure:2891: gcc -c conftest.c >&5
+configure:2894: $? = 0
+configure:2917: result: o
+configure:2921: checking whether we are using the GNU C compiler
+configure:2950: gcc -c conftest.c >&5
+configure:2956: $? = 0
+configure:2973: result: yes
+configure:2978: checking whether gcc accepts -g
+configure:3008: gcc -c -g conftest.c >&5
+configure:3014: $? = 0
+configure:3113: result: yes
+configure:3130: checking for gcc option to accept ISO C89
+configure:3204: gcc -c -g -O2 conftest.c >&5
+configure:3210: $? = 0
+configure:3233: result: none needed
+configure:3262: checking for style of include used by make
+configure:3290: result: GNU
+configure:3315: checking dependency style of gcc
+configure:3406: result: gcc3
+configure:3421: checking for gcc option to accept ISO C99
+configure:3580: gcc -c -g -O2 conftest.c >&5
+conftest.c:60: error: expected ';', ',' or ')' before 'text'
+conftest.c: In function 'main':
+conftest.c:114: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'newvar'
+conftest.c:114: error: 'newvar' undeclared (first use in this function)
+conftest.c:114: error: (Each undeclared identifier is reported only once
+conftest.c:114: error: for each function it appears in.)
+conftest.c:124: error: 'for' loop initial declarations are only allowed in C99 mode
+conftest.c:124: note: use option -std=c99 or -std=gnu99 to compile your code
+configure:3586: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| /* end confdefs.h. */
+| #include <stdarg.h>
+| #include <stdbool.h>
+| #include <stdlib.h>
+| #include <wchar.h>
+| #include <stdio.h>
+|
+| // Check varargs macros. These examples are taken from C99 6.10.3.5.
+| #define debug(...) fprintf (stderr, __VA_ARGS__)
+| #define showlist(...) puts (#__VA_ARGS__)
+| #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+| static void
+| test_varargs_macros (void)
+| {
+| int x = 1234;
+| int y = 5678;
+| debug ("Flag");
+| debug ("X = %d\n", x);
+| showlist (The first, second, and third items.);
+| report (x>y, "x is %d but y is %d", x, y);
+| }
+|
+| // Check long long types.
+| #define BIG64 18446744073709551615ull
+| #define BIG32 4294967295ul
+| #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+| #if !BIG_OK
+| your preprocessor is broken;
+| #endif
+| #if BIG_OK
+| #else
+| your preprocessor is broken;
+| #endif
+| static long long int bignum = -9223372036854775807LL;
+| static unsigned long long int ubignum = BIG64;
+|
+| struct incomplete_array
+| {
+| int datasize;
+| double data[];
+| };
+|
+| struct named_init {
+| int number;
+| const wchar_t *name;
+| double average;
+| };
+|
+| typedef const char *ccp;
+|
+| static inline int
+| test_restrict (ccp restrict text)
+| {
+| // See if C++-style comments work.
+| // Iterate through items via the restricted pointer.
+| // Also check for declarations in for loops.
+| for (unsigned int i = 0; *(text+i) != '\0'; ++i)
+| continue;
+| return 0;
+| }
+|
+| // Check varargs and va_copy.
+| static void
+| test_varargs (const char *format, ...)
+| {
+| va_list args;
+| va_start (args, format);
+| va_list args_copy;
+| va_copy (args_copy, args);
+|
+| const char *str;
+| int number;
+| float fnumber;
+|
+| while (*format)
+| {
+| switch (*format++)
+| {
+| case 's': // string
+| str = va_arg (args_copy, const char *);
+| break;
+| case 'd': // int
+| number = va_arg (args_copy, int);
+| break;
+| case 'f': // float
+| fnumber = va_arg (args_copy, double);
+| break;
+| default:
+| break;
+| }
+| }
+| va_end (args_copy);
+| va_end (args);
+| }
+|
+| int
+| main ()
+| {
+|
+| // Check bool.
+| _Bool success = false;
+|
+| // Check restrict.
+| if (test_restrict ("String literal") == 0)
+| success = true;
+| char *restrict newvar = "Another string";
+|
+| // Check varargs.
+| test_varargs ("s, d' f .", "string", 65, 34.234);
+| test_varargs_macros ();
+|
+| // Check flexible array members.
+| struct incomplete_array *ia =
+| malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+| ia->datasize = 10;
+| for (int i = 0; i < ia->datasize; ++i)
+| ia->data[i] = i * 1.234;
+|
+| // Check named initializers.
+| struct named_init ni = {
+| .number = 34,
+| .name = L"Test wide string",
+| .average = 543.34343,
+| };
+|
+| ni.number = 58;
+|
+| int dynamic_array[ni.number];
+| dynamic_array[ni.number - 1] = 543;
+|
+| // work around unused variable warnings
+| return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
+| || dynamic_array[ni.number - 1] != 543);
+|
+| ;
+| return 0;
+| }
+configure:3580: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:3586: $? = 0
+configure:3616: result: -std=gnu99
+configure:3680: checking for g++
+configure:3696: found /usr/bin/g++
+configure:3707: result: g++
+configure:3738: checking for C++ compiler version
+configure:3745: g++ --version >&5
+g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
+Copyright (C) 2010 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+configure:3748: $? = 0
+configure:3755: g++ -v >&5
+Using built-in specs.
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.4.4-14ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)
+configure:3758: $? = 0
+configure:3765: g++ -V >&5
+g++: '-V' option must have argument
+configure:3768: $? = 1
+configure:3771: checking whether we are using the GNU C++ compiler
+configure:3800: g++ -c conftest.cpp >&5
+configure:3806: $? = 0
+configure:3823: result: yes
+configure:3828: checking whether g++ accepts -g
+configure:3858: g++ -c -g conftest.cpp >&5
+configure:3864: $? = 0
+configure:3963: result: yes
+configure:3988: checking dependency style of g++
+configure:4079: result: gcc3
+configure:4136: checking for ld used by GCC
+configure:4200: result: /usr/bin/ld
+configure:4209: checking if the linker (/usr/bin/ld) is GNU ld
+configure:4222: result: yes
+configure:4229: checking for shared library run path origin
+configure:4242: result: done
+configure:4751: checking for iconv
+configure:4783: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:4789: $? = 0
+configure:4859: result: yes
+configure:4862: checking for working iconv
+configure:4948: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:4951: $? = 0
+configure:4957: ./conftest
+configure:4960: $? = 0
+configure:4978: result: yes
+configure:5008: checking for iconv declaration
+configure:5047: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5053: $? = 0
+configure:5072: result:
+ extern size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+configure:5089: checking how to run the C preprocessor
+configure:5129: gcc -std=gnu99 -E conftest.c
+configure:5135: $? = 0
+configure:5166: gcc -std=gnu99 -E conftest.c
+conftest.c:12: fatal error: ac_nonexistent.h: No such file or directory
+compilation terminated.
+configure:5172: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| /* end confdefs.h. */
+| #include <ac_nonexistent.h>
+configure:5205: result: gcc -std=gnu99 -E
+configure:5234: gcc -std=gnu99 -E conftest.c
+configure:5240: $? = 0
+configure:5271: gcc -std=gnu99 -E conftest.c
+conftest.c:12: fatal error: ac_nonexistent.h: No such file or directory
+compilation terminated.
+configure:5277: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| /* end confdefs.h. */
+| #include <ac_nonexistent.h>
+configure:5315: checking for grep that handles long lines and -e
+configure:5389: result: /bin/grep
+configure:5394: checking for egrep
+configure:5472: result: /bin/grep -E
+configure:5477: checking for ANSI C header files
+configure:5507: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5513: $? = 0
+configure:5612: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:5615: $? = 0
+configure:5621: ./conftest
+configure:5624: $? = 0
+configure:5641: result: yes
+configure:5665: checking for sys/types.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for sys/stat.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for stdlib.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for string.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for memory.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for strings.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for inttypes.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for stdint.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for unistd.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5735: checking pthread.h usability
+configure:5752: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5758: $? = 0
+configure:5772: result: yes
+configure:5776: checking pthread.h presence
+configure:5791: gcc -std=gnu99 -E conftest.c
+configure:5797: $? = 0
+configure:5811: result: yes
+configure:5839: checking for pthread.h
+configure:5847: result: yes
+configure:5875: checking iconv.h usability
+configure:5892: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5898: $? = 0
+configure:5912: result: yes
+configure:5916: checking iconv.h presence
+configure:5931: gcc -std=gnu99 -E conftest.c
+configure:5937: $? = 0
+configure:5951: result: yes
+configure:5979: checking for iconv.h
+configure:5987: result: yes
+configure:6015: checking windows.h usability
+configure:6032: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+conftest.c:57: fatal error: windows.h: No such file or directory
+compilation terminated.
+configure:6038: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_PTHREAD_H 1
+| #define HAVE_ICONV_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <windows.h>
+configure:6052: result: no
+configure:6056: checking windows.h presence
+configure:6071: gcc -std=gnu99 -E conftest.c
+conftest.c:24: fatal error: windows.h: No such file or directory
+compilation terminated.
+configure:6077: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_PTHREAD_H 1
+| #define HAVE_ICONV_H 1
+| /* end confdefs.h. */
+| #include <windows.h>
+configure:6091: result: no
+configure:6119: checking for windows.h
+configure:6127: result: no
+configure:6142: checking whether byte ordering is bigendian
+configure:6175: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:6181: $? = 0
+configure:6213: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:31: error: 'not' undeclared (first use in this function)
+conftest.c:31: error: (Each undeclared identifier is reported only once
+conftest.c:31: error: for each function it appears in.)
+conftest.c:31: error: expected ';' before 'big'
+configure:6219: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_PTHREAD_H 1
+| #define HAVE_ICONV_H 1
+| /* end confdefs.h. */
+| #include <sys/types.h>
+| #include <sys/param.h>
+|
+| int
+| main ()
+| {
+| #if BYTE_ORDER != BIG_ENDIAN
+| not big endian
+| #endif
+|
+| ;
+| return 0;
+| }
+configure:6359: result: no
+configure:6389: checking for getaddrinfo
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6389: checking for gethostbyname_r
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6389: checking for inet_aton
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6389: checking for strndup
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+conftest.c:50: warning: conflicting types for built-in function 'strndup'
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6389: checking for vasprintf
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6389: checking for asprintf
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6479: checking for MultiByteToWideChar
+configure:6508: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+conftest.c:30: fatal error: windows.h: No such file or directory
+compilation terminated.
+configure:6514: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_PTHREAD_H 1
+| #define HAVE_ICONV_H 1
+| #define HAVE_GETADDRINFO 1
+| #define HAVE_GETHOSTBYNAME_R 1
+| #define HAVE_INET_ATON 1
+| #define HAVE_STRNDUP 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| /* end confdefs.h. */
+| #include <windows.h>
+| int
+| main ()
+| {
+| MultiByteToWideChar(0,0,0,0,0,0);
+| ;
+| return 0;
+| }
+configure:6533: result: no
+configure:6699: creating ./config.status
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by jscoverage config.status 0.4, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES =
+ CONFIG_HEADERS =
+ CONFIG_LINKS =
+ CONFIG_COMMANDS =
+ $ ./config.status
+
+on happy.bec-systems.com
+
+config.status:661: creating Makefile
+config.status:661: creating make-dist.sh
+config.status:661: creating make-bin-dist.sh
+config.status:661: creating tests/Makefile
+config.status:661: creating config.h
+config.status:944: executing depfiles commands
+
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+
+ac_cv_build=x86_64-unknown-linux-gnu
+ac_cv_c_bigendian=no
+ac_cv_c_compiler_gnu=yes
+ac_cv_cxx_compiler_gnu=yes
+ac_cv_env_CCC_set=
+ac_cv_env_CCC_value=
+ac_cv_env_CC_set=
+ac_cv_env_CC_value=
+ac_cv_env_CFLAGS_set=
+ac_cv_env_CFLAGS_value=
+ac_cv_env_CPPFLAGS_set=
+ac_cv_env_CPPFLAGS_value=
+ac_cv_env_CPP_set=
+ac_cv_env_CPP_value=
+ac_cv_env_CXXFLAGS_set=
+ac_cv_env_CXXFLAGS_value=
+ac_cv_env_CXX_set=
+ac_cv_env_CXX_value=
+ac_cv_env_LDFLAGS_set=
+ac_cv_env_LDFLAGS_value=
+ac_cv_env_LIBS_set=
+ac_cv_env_LIBS_value=
+ac_cv_env_build_alias_set=
+ac_cv_env_build_alias_value=
+ac_cv_env_host_alias_set=
+ac_cv_env_host_alias_value=
+ac_cv_env_target_alias_set=
+ac_cv_env_target_alias_value=
+ac_cv_func_asprintf=yes
+ac_cv_func_getaddrinfo=yes
+ac_cv_func_gethostbyname_r=yes
+ac_cv_func_inet_aton=yes
+ac_cv_func_strndup=yes
+ac_cv_func_vasprintf=yes
+ac_cv_header_iconv_h=yes
+ac_cv_header_inttypes_h=yes
+ac_cv_header_memory_h=yes
+ac_cv_header_pthread_h=yes
+ac_cv_header_stdc=yes
+ac_cv_header_stdint_h=yes
+ac_cv_header_stdlib_h=yes
+ac_cv_header_string_h=yes
+ac_cv_header_strings_h=yes
+ac_cv_header_sys_stat_h=yes
+ac_cv_header_sys_types_h=yes
+ac_cv_header_unistd_h=yes
+ac_cv_header_windows_h=no
+ac_cv_host=x86_64-unknown-linux-gnu
+ac_cv_objext=o
+ac_cv_path_EGREP='/bin/grep -E'
+ac_cv_path_GREP=/bin/grep
+ac_cv_path_install='/usr/bin/install -c'
+ac_cv_path_mkdir=/bin/mkdir
+ac_cv_prog_AWK=gawk
+ac_cv_prog_CPP='gcc -std=gnu99 -E'
+ac_cv_prog_ac_ct_CC=gcc
+ac_cv_prog_ac_ct_CXX=g++
+ac_cv_prog_cc_c89=
+ac_cv_prog_cc_c99=-std=gnu99
+ac_cv_prog_cc_g=yes
+ac_cv_prog_cxx_g=yes
+ac_cv_prog_make_make_set=yes
+acl_cv_hardcode_direct=no
+acl_cv_hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+acl_cv_hardcode_libdir_separator=
+acl_cv_hardcode_minus_L=no
+acl_cv_libext=a
+acl_cv_libname_spec='lib$name'
+acl_cv_library_names_spec='$libname$shrext'
+acl_cv_path_LD=/usr/bin/ld
+acl_cv_prog_gnu_ld=yes
+acl_cv_rpath=done
+acl_cv_shlibext=so
+acl_cv_wl=-Wl,
+am_cv_CC_dependencies_compiler_type=gcc3
+am_cv_CXX_dependencies_compiler_type=gcc3
+am_cv_func_iconv=yes
+am_cv_func_iconv_works=yes
+am_cv_lib_iconv=no
+am_cv_proto_iconv='extern size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);'
+am_cv_proto_iconv_arg1=
+
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+
+ACLOCAL='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run aclocal-1.10'
+AMDEPBACKSLASH='\'
+AMDEP_FALSE='#'
+AMDEP_TRUE=''
+AMTAR='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run tar'
+AUTOCONF='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoconf'
+AUTOHEADER='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoheader'
+AUTOMAKE='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run automake-1.10'
+AWK='gawk'
+CC='gcc -std=gnu99'
+CCDEPMODE='depmode=gcc3'
+CFLAGS='-g -O2'
+CPP='gcc -std=gnu99 -E'
+CPPFLAGS=''
+CXX='g++'
+CXXDEPMODE='depmode=gcc3'
+CXXFLAGS='-g -O2'
+CYGPATH_W='echo'
+DEFS='-DHAVE_CONFIG_H'
+DEPDIR='.deps'
+ECHO_C=''
+ECHO_N='-n'
+ECHO_T=''
+EGREP='/bin/grep -E'
+EXEEXT=''
+EXTRA_SOCKET_LIBS=''
+EXTRA_THREAD_LIBS='-lpthread'
+EXTRA_TIMER_LIBS=''
+GREP='/bin/grep'
+INSTALL_DATA='${INSTALL} -m 644'
+INSTALL_PROGRAM='${INSTALL}'
+INSTALL_SCRIPT='${INSTALL}'
+INSTALL_STRIP_PROGRAM='$(install_sh) -c -s'
+LDFLAGS=''
+LIBICONV=''
+LIBOBJS=''
+LIBS=''
+LTLIBICONV=''
+LTLIBOBJS=''
+MAKEINFO='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run makeinfo'
+OBJEXT='o'
+PACKAGE='jscoverage'
+PACKAGE_BUGREPORT=''
+PACKAGE_NAME='jscoverage'
+PACKAGE_STRING='jscoverage 0.4'
+PACKAGE_TARNAME='jscoverage'
+PACKAGE_VERSION='0.4'
+PATH_SEPARATOR=':'
+SET_MAKE=''
+SHELL='/bin/sh'
+STRIP=''
+VERSION='0.4'
+XP_DEF='-DXP_UNIX'
+ac_ct_CC='gcc'
+ac_ct_CXX='g++'
+am__fastdepCC_FALSE='#'
+am__fastdepCC_TRUE=''
+am__fastdepCXX_FALSE='#'
+am__fastdepCXX_TRUE=''
+am__include='include'
+am__isrc=''
+am__leading_dot='.'
+am__quote=''
+am__tar='${AMTAR} chof - "$$tardir"'
+am__untar='${AMTAR} xf -'
+bindir='${exec_prefix}/bin'
+build='x86_64-unknown-linux-gnu'
+build_alias=''
+build_cpu='x86_64'
+build_os='linux-gnu'
+build_vendor='unknown'
+datadir='${datarootdir}'
+datarootdir='${prefix}/share'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+dvidir='${docdir}'
+exec_prefix='${prefix}'
+host='x86_64-unknown-linux-gnu'
+host_alias=''
+host_cpu='x86_64'
+host_os='linux-gnu'
+host_vendor='unknown'
+htmldir='${docdir}'
+includedir='${prefix}/include'
+infodir='${datarootdir}/info'
+install_sh='$(SHELL) /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/install-sh'
+libdir='${exec_prefix}/lib'
+libexecdir='${exec_prefix}/libexec'
+localedir='${datarootdir}/locale'
+localstatedir='${prefix}/var'
+mandir='${datarootdir}/man'
+mkdir_p='/bin/mkdir -p'
+oldincludedir='/usr/include'
+pdfdir='${docdir}'
+prefix='/usr/local'
+program_transform_name='s,x,x,'
+psdir='${docdir}'
+sbindir='${exec_prefix}/sbin'
+sharedstatedir='${prefix}/com'
+sysconfdir='${prefix}/etc'
+target_alias=''
+
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+
+#define PACKAGE_NAME "jscoverage"
+#define PACKAGE_TARNAME "jscoverage"
+#define PACKAGE_VERSION "0.4"
+#define PACKAGE_STRING "jscoverage 0.4"
+#define PACKAGE_BUGREPORT ""
+#define PACKAGE "jscoverage"
+#define VERSION "0.4"
+#define HAVE_ICONV 1
+#define ICONV_CONST
+#define STDC_HEADERS 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_PTHREAD_H 1
+#define HAVE_ICONV_H 1
+#define HAVE_GETADDRINFO 1
+#define HAVE_GETHOSTBYNAME_R 1
+#define HAVE_INET_ATON 1
+#define HAVE_STRNDUP 1
+#define HAVE_VASPRINTF 1
+#define HAVE_ASPRINTF 1
+
+configure: exit 0
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.rpath b/tools/node_modules/expresso/deps/jscoverage/config.rpath
new file mode 100755
index 0000000..c547c68
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.rpath
@@ -0,0 +1,666 @@
+#! /bin/sh
+# Output a system dependent set of variables, describing how to set the
+# run time search path of shared libraries in an executable.
+#
+# Copyright 1996-2007 Free Software Foundation, Inc.
+# Taken from GNU libtool, 2001
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# The first argument passed to this file is the canonical host specification,
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
+# should be set by the caller.
+#
+# The set of defined variables is at the end of this script.
+
+# Known limitations:
+# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
+# than 256 bytes, otherwise the compiler driver will dump core. The only
+# known workaround is to choose shorter directory names for the build
+# directory and/or the installation directory.
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+shrext=.so
+
+host="$1"
+host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+# Code taken from libtool.m4's _LT_CC_BASENAME.
+
+for cc_temp in $CC""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
+
+# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC.
+
+wl=
+if test "$GCC" = yes; then
+ wl='-Wl,'
+else
+ case "$host_os" in
+ aix*)
+ wl='-Wl,'
+ ;;
+ darwin*)
+ case $cc_basename in
+ xlc*)
+ wl='-Wl,'
+ ;;
+ esac
+ ;;
+ mingw* | cygwin* | pw32* | os2*)
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ wl='-Wl,'
+ ;;
+ irix5* | irix6* | nonstopux*)
+ wl='-Wl,'
+ ;;
+ newsos6)
+ ;;
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ icc* | ecc*)
+ wl='-Wl,'
+ ;;
+ pgcc | pgf77 | pgf90)
+ wl='-Wl,'
+ ;;
+ ccc*)
+ wl='-Wl,'
+ ;;
+ como)
+ wl='-lopt='
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ wl='-Wl,'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ osf3* | osf4* | osf5*)
+ wl='-Wl,'
+ ;;
+ rdos*)
+ ;;
+ solaris*)
+ wl='-Wl,'
+ ;;
+ sunos4*)
+ wl='-Qoption ld '
+ ;;
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ wl='-Wl,'
+ ;;
+ sysv4*MP*)
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ wl='-Wl,'
+ ;;
+ unicos*)
+ wl='-Wl,'
+ ;;
+ uts4*)
+ ;;
+ esac
+fi
+
+# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS.
+
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+
+case "$host_os" in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ # Unlike libtool, we use -rpath here, not --rpath, since the documented
+ # option of GNU ld is called -rpath, not --rpath.
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ case "$host_os" in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ fi
+ ;;
+ amigaos*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we cannot use
+ # them.
+ ld_shlibs=no
+ ;;
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ cygwin* | mingw* | pw32*)
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ interix[3-9]*)
+ hardcode_direct=no
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ gnu* | linux* | k*bsd*-gnu)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ netbsd*)
+ ;;
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+ sunos4*)
+ hardcode_direct=yes
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ if test "$ld_shlibs" = no; then
+ hardcode_libdir_flag_spec=
+ fi
+else
+ case "$host_os" in
+ aix3*)
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ else
+ aix_use_runtimelinking=no
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+ fi
+ hardcode_direct=yes
+ hardcode_libdir_separator=':'
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ fi
+ # Begin _LT_AC_SYS_LIBPATH_AIX.
+ echo 'int main () { return 0; }' > conftest.c
+ ${CC} ${LDFLAGS} conftest.c -o conftest
+ aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+ if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+ fi
+ if test -z "$aix_libpath"; then
+ aix_libpath="/usr/lib:/lib"
+ fi
+ rm -f conftest.c conftest
+ # End _LT_AC_SYS_LIBPATH_AIX.
+ if test "$aix_use_runtimelinking" = yes; then
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ else
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ fi
+ fi
+ ;;
+ amigaos*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+ bsdi[45]*)
+ ;;
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ libext=lib
+ ;;
+ darwin* | rhapsody*)
+ hardcode_direct=no
+ if test "$GCC" = yes ; then
+ :
+ else
+ case $cc_basename in
+ xlc*)
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+ ;;
+ dgux*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+ freebsd2.2*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ freebsd2*)
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+ freebsd* | dragonfly*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ hpux9*)
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ hpux10*)
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+ hpux11*)
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct=no
+ ;;
+ *)
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+ irix5* | irix6* | nonstopux*)
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ netbsd*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ newsos6)
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct=yes
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ else
+ case "$host_os" in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ osf3*)
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ osf4* | osf5*)
+ if test "$GCC" = yes; then
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ # Both cc and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ hardcode_libdir_separator=:
+ ;;
+ solaris*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ sunos4*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+ sysv4)
+ case $host_vendor in
+ sni)
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ hardcode_direct=no
+ ;;
+ motorola)
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ ;;
+ sysv4.3*)
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ ld_shlibs=yes
+ fi
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator=':'
+ ;;
+ uts4*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+fi
+
+# Check dynamic linker characteristics
+# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER.
+# Unlike libtool.m4, here we don't care about _all_ names of the library, but
+# only about the one the linker finds when passed -lNAME. This is the last
+# element of library_names_spec in libtool.m4, or possibly two of them if the
+# linker has special search rules.
+library_names_spec= # the last element of library_names_spec in libtool.m4
+libname_spec='lib$name'
+case "$host_os" in
+ aix3*)
+ library_names_spec='$libname.a'
+ ;;
+ aix4* | aix5*)
+ library_names_spec='$libname$shrext'
+ ;;
+ amigaos*)
+ library_names_spec='$libname.a'
+ ;;
+ beos*)
+ library_names_spec='$libname$shrext'
+ ;;
+ bsdi[45]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ cygwin* | mingw* | pw32*)
+ shrext=.dll
+ library_names_spec='$libname.dll.a $libname.lib'
+ ;;
+ darwin* | rhapsody*)
+ shrext=.dylib
+ library_names_spec='$libname$shrext'
+ ;;
+ dgux*)
+ library_names_spec='$libname$shrext'
+ ;;
+ freebsd1*)
+ ;;
+ freebsd* | dragonfly*)
+ case "$host_os" in
+ freebsd[123]*)
+ library_names_spec='$libname$shrext$versuffix' ;;
+ *)
+ library_names_spec='$libname$shrext' ;;
+ esac
+ ;;
+ gnu*)
+ library_names_spec='$libname$shrext'
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $host_cpu in
+ ia64*)
+ shrext=.so
+ ;;
+ hppa*64*)
+ shrext=.sl
+ ;;
+ *)
+ shrext=.sl
+ ;;
+ esac
+ library_names_spec='$libname$shrext'
+ ;;
+ interix[3-9]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ irix5* | irix6* | nonstopux*)
+ library_names_spec='$libname$shrext'
+ case "$host_os" in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
+ *) libsuff= shlibsuff= ;;
+ esac
+ ;;
+ esac
+ ;;
+ linux*oldld* | linux*aout* | linux*coff*)
+ ;;
+ linux* | k*bsd*-gnu)
+ library_names_spec='$libname$shrext'
+ ;;
+ knetbsd*-gnu)
+ library_names_spec='$libname$shrext'
+ ;;
+ netbsd*)
+ library_names_spec='$libname$shrext'
+ ;;
+ newsos6)
+ library_names_spec='$libname$shrext'
+ ;;
+ nto-qnx*)
+ library_names_spec='$libname$shrext'
+ ;;
+ openbsd*)
+ library_names_spec='$libname$shrext$versuffix'
+ ;;
+ os2*)
+ libname_spec='$name'
+ shrext=.dll
+ library_names_spec='$libname.a'
+ ;;
+ osf3* | osf4* | osf5*)
+ library_names_spec='$libname$shrext'
+ ;;
+ rdos*)
+ ;;
+ solaris*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sunos4*)
+ library_names_spec='$libname$shrext$versuffix'
+ ;;
+ sysv4 | sysv4.3*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sysv4*MP*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ library_names_spec='$libname$shrext'
+ ;;
+ uts4*)
+ library_names_spec='$libname$shrext'
+ ;;
+esac
+
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
+shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
+escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+
+LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
+
+# How to pass a linker flag through the compiler.
+wl="$escaped_wl"
+
+# Static library suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally "so").
+shlibext="$shlibext"
+
+# Format of library name prefix.
+libname_spec="$escaped_libname_spec"
+
+# Library names that the linker finds when passed -lNAME.
+library_names_spec="$escaped_library_names_spec"
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator="$hardcode_libdir_separator"
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct="$hardcode_direct"
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L="$hardcode_minus_L"
+
+EOF
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.status b/tools/node_modules/expresso/deps/jscoverage/config.status
new file mode 100755
index 0000000..cde41cb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.status
@@ -0,0 +1,1080 @@
+#! /bin/sh
+# Generated by configure.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=${CONFIG_SHELL-/bin/sh}
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by jscoverage $as_me 0.4, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+# Files that config.status was made for.
+config_files=" Makefile make-dist.sh make-bin-dist.sh tests/Makefile"
+config_headers=" config.h"
+config_commands=" depfiles"
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+ac_cs_version="\
+jscoverage config.status 0.4
+configured by ./configure, generated by GNU Autoconf 2.61,
+ with options \"\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='/scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage'
+srcdir='.'
+INSTALL='/usr/bin/install -c'
+MKDIR_P='/bin/mkdir -p'
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+if $ac_cs_recheck; then
+ echo "running CONFIG_SHELL=/bin/sh /bin/sh ./configure " $ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=/bin/sh
+ export CONFIG_SHELL
+ exec /bin/sh "./configure" $ac_configure_extra_args --no-create --no-recursion
+fi
+
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="" ac_aux_dir="."
+
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "make-dist.sh") CONFIG_FILES="$CONFIG_FILES make-dist.sh" ;;
+ "make-bin-dist.sh") CONFIG_FILES="$CONFIG_FILES make-bin-dist.sh" ;;
+ "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+cat >"$tmp/subs-1.sed" <<\CEOF
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@SHELL@,|#_!!_#|/bin/sh,g
+s,@PATH_SEPARATOR@,|#_!!_#|:,g
+s,@PACKAGE_NAME@,|#_!!_#|jscoverage,g
+s,@PACKAGE_TARNAME@,|#_!!_#|jscoverage,g
+s,@PACKAGE_VERSION@,|#_!!_#|0.4,g
+s,@PACKAGE_STRING@,|#_!!_#|jscoverage 0.4,g
+s,@PACKAGE_BUGREPORT@,|#_!!_#|,g
+s,@exec_prefix@,|#_!!_#|${prefix},g
+s,@prefix@,|#_!!_#|/usr/local,g
+s,@program_transform_name@,|#_!!_#|s\,x\,x\,,g
+s,@bindir@,|#_!!_#|${exec_prefix}/bin,g
+s,@sbindir@,|#_!!_#|${exec_prefix}/sbin,g
+s,@libexecdir@,|#_!!_#|${exec_prefix}/libexec,g
+s,@datarootdir@,|#_!!_#|${prefix}/share,g
+s,@datadir@,|#_!!_#|${datarootdir},g
+s,@sysconfdir@,|#_!!_#|${prefix}/etc,g
+s,@sharedstatedir@,|#_!!_#|${prefix}/com,g
+s,@localstatedir@,|#_!!_#|${prefix}/var,g
+s,@includedir@,|#_!!_#|${prefix}/include,g
+s,@oldincludedir@,|#_!!_#|/usr/include,g
+s,@docdir@,|#_!!_#|${datarootdir}/doc/${PACKAGE_TARNAME},g
+s,@infodir@,|#_!!_#|${datarootdir}/info,g
+s,@htmldir@,|#_!!_#|${docdir},g
+s,@dvidir@,|#_!!_#|${docdir},g
+s,@pdfdir@,|#_!!_#|${docdir},g
+s,@psdir@,|#_!!_#|${docdir},g
+s,@libdir@,|#_!!_#|${exec_prefix}/lib,g
+s,@localedir@,|#_!!_#|${datarootdir}/locale,g
+s,@mandir@,|#_!!_#|${datarootdir}/man,g
+s,@DEFS@,|#_!!_#|-DHAVE_CONFIG_H,g
+s,@ECHO_C@,|#_!!_#|,g
+s,@ECHO_N@,|#_!!_#|-n,g
+s,@ECHO_T@,|#_!!_#|,g
+s,@LIBS@,|#_!!_#|,g
+s,@build_alias@,|#_!!_#|,g
+s,@host_alias@,|#_!!_#|,g
+s,@target_alias@,|#_!!_#|,g
+s,@INSTALL_PROGRAM@,|#_!!_#|${INSTALL},g
+s,@INSTALL_SCRIPT@,|#_!!_#|${INSTALL},g
+s,@INSTALL_DATA@,|#_!!_#|${INSTALL} -m 644,g
+s,@am__isrc@,|#_!!_#|,g
+s,@CYGPATH_W@,|#_!!_#|echo,g
+s,@PACKAGE@,|#_!!_#|jscoverage,g
+s,@VERSION@,|#_!!_#|0.4,g
+s,@ACLOCAL@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run aclocal-1.10,g
+s,@AUTOCONF@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoconf,g
+s,@AUTOMAKE@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run automake-1.10,g
+s,@AUTOHEADER@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoheader,g
+s,@MAKEINFO@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run makeinfo,g
+s,@install_sh@,|#_!!_#|$(SHELL) /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/install-sh,g
+s,@STRIP@,|#_!!_#|,g
+s,@INSTALL_STRIP_PROGRAM@,|#_!!_#|$(install_sh) -c -s,g
+s,@mkdir_p@,|#_!!_#|/bin/mkdir -p,g
+s,@AWK@,|#_!!_#|gawk,g
+s,@SET_MAKE@,|#_!!_#|,g
+s,@am__leading_dot@,|#_!!_#|.,g
+s,@AMTAR@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run tar,g
+s,@am__tar@,|#_!!_#|${AMTAR} chof - "$$tardir",g
+s,@am__untar@,|#_!!_#|${AMTAR} xf -,g
+s,@build@,|#_!!_#|x86_64-unknown-linux-gnu,g
+s,@build_cpu@,|#_!!_#|x86_64,g
+s,@build_vendor@,|#_!!_#|unknown,g
+s,@build_os@,|#_!!_#|linux-gnu,g
+s,@host@,|#_!!_#|x86_64-unknown-linux-gnu,g
+s,@host_cpu@,|#_!!_#|x86_64,g
+s,@host_vendor@,|#_!!_#|unknown,g
+s,@host_os@,|#_!!_#|linux-gnu,g
+s,@CC@,|#_!!_#|gcc -std=gnu99,g
+s,@CFLAGS@,|#_!!_#|-g -O2,g
+s,@LDFLAGS@,|#_!!_#|,g
+s,@CPPFLAGS@,|#_!!_#|,g
+s,@ac_ct_CC@,|#_!!_#|gcc,g
+s,@EXEEXT@,|#_!!_#|,g
+s,@OBJEXT@,|#_!!_#|o,g
+s,@DEPDIR@,|#_!!_#|.deps,g
+s,@am__include@,|#_!!_#|include,g
+s,@am__quote@,|#_!!_#|,g
+s,@AMDEP_TRUE@,|#_!!_#|,g
+s,@AMDEP_FALSE@,|#_!!_#|#,g
+s,@AMDEPBACKSLASH@,|#_!!_#|\\,g
+s,@CCDEPMODE@,|#_!!_#|depmode=gcc3,g
+s,@am__fastdepCC_TRUE@,|#_!!_#|,g
+s,@am__fastdepCC_FALSE@,|#_!!_#|#,g
+s,@CXX@,|#_!!_#|g++,g
+s,@CXXFLAGS@,|#_!!_#|-g -O2,g
+s,@ac_ct_CXX@,|#_!!_#|g++,g
+s,@CXXDEPMODE@,|#_!!_#|depmode=gcc3,g
+s,@am__fastdepCXX_TRUE@,|#_!!_#|,g
+s,@am__fastdepCXX_FALSE@,|#_!!_#|#,g
+s,@LIBICONV@,|#_!!_#|,g
+s,@LTLIBICONV@,|#_!!_#|,g
+s,@CPP@,|#_!!_#|gcc -std=gnu99 -E,g
+s,@GREP@,|#_!!_#|/bin/grep,g
+s,@EGREP@,|#_!!_#|/bin/grep -E,g
+s,@XP_DEF@,|#_!!_#|-DXP_UNIX,g
+s,@EXTRA_SOCKET_LIBS@,|#_!!_#|,g
+s,@EXTRA_THREAD_LIBS@,|#_!!_#|-lpthread,g
+CEOF
+cat >"$tmp/subs-2.sed" <<\CEOF
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+s,@EXTRA_TIMER_LIBS@,|#_!!_#|,g
+s,@LIBOBJS@,|#_!!_#|,g
+s,@LTLIBOBJS@,|#_!!_#|,g
+:end
+s/|#_!!_#|//g
+CEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ ac_datarootdir_hack='
+ s&@datadir@&${datarootdir}&g
+ s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g
+ s&@infodir@&${datarootdir}/info&g
+ s&@localedir@&${datarootdir}/locale&g
+ s&@mandir@&${datarootdir}/man&g
+ s&\${datarootdir}&${prefix}/share&g' ;;
+esac
+ sed "/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}
+
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ # First, check the format of the line:
+ cat >"$tmp/defines.sed" <<\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[ ]*$/b def
+/^[ ]*#[ ]*define[ ][ ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[( ]/b def
+b
+:def
+s/$/ /
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE_NAME\)[ (].*,\1define\2 "jscoverage" ,
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE_TARNAME\)[ (].*,\1define\2 "jscoverage" ,
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE_VERSION\)[ (].*,\1define\2 "0.4" ,
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE_STRING\)[ (].*,\1define\2 "jscoverage 0.4" ,
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE_BUGREPORT\)[ (].*,\1define\2 "" ,
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE\)[ (].*,\1define\2 "jscoverage" ,
+s,^\([ #]*\)[^ ]*\([ ]*VERSION\)[ (].*,\1define\2 "0.4" ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_ICONV\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*ICONV_CONST\)[ (].*,\1define\2 ,
+s,^\([ #]*\)[^ ]*\([ ]*STDC_HEADERS\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_SYS_TYPES_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_SYS_STAT_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_STDLIB_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_STRING_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_MEMORY_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_STRINGS_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_INTTYPES_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_STDINT_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_UNISTD_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_PTHREAD_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_ICONV_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_GETADDRINFO\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_GETHOSTBYNAME_R\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_INET_ATON\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_STRNDUP\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_VASPRINTF\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_ASPRINTF\)[ (].*,\1define\2 1 ,
+s/ $//
+s,^[ #]*u.*,/* & */,
+CEOF
+ sed -f "$tmp/defines.sed" $ac_file_inputs >"$tmp/out1"
+ac_result="$tmp/out1"
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+# Compute $ac_file's index in $config_headers.
+_am_arg=$ac_file
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$_am_arg" : 'X\(//\)[^/]' \| \
+ X"$_am_arg" : 'X\(//\)$' \| \
+ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$_am_arg" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir=$dirpart/$fdir
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+ ;;
+
+ esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.sub b/tools/node_modules/expresso/deps/jscoverage/config.sub
new file mode 100755
index 0000000..6759825
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.sub
@@ -0,0 +1,1658 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
+
+timestamp='2008-01-16'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fido | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore | mep \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tile*)
+ basic_machine=tile-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/configure b/tools/node_modules/expresso/deps/jscoverage/configure
new file mode 100755
index 0000000..71e6752
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/configure
@@ -0,0 +1,7971 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61 for jscoverage 0.4.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='jscoverage'
+PACKAGE_TARNAME='jscoverage'
+PACKAGE_VERSION='0.4'
+PACKAGE_STRING='jscoverage 0.4'
+PACKAGE_BUGREPORT=''
+
+ac_unique_file="jscoverage.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+am__isrc
+CYGPATH_W
+PACKAGE
+VERSION
+ACLOCAL
+AUTOCONF
+AUTOMAKE
+AUTOHEADER
+MAKEINFO
+install_sh
+STRIP
+INSTALL_STRIP_PROGRAM
+mkdir_p
+AWK
+SET_MAKE
+am__leading_dot
+AMTAR
+am__tar
+am__untar
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+DEPDIR
+am__include
+am__quote
+AMDEP_TRUE
+AMDEP_FALSE
+AMDEPBACKSLASH
+CCDEPMODE
+am__fastdepCC_TRUE
+am__fastdepCC_FALSE
+CXX
+CXXFLAGS
+ac_ct_CXX
+CXXDEPMODE
+am__fastdepCXX_TRUE
+am__fastdepCXX_FALSE
+LIBICONV
+LTLIBICONV
+CPP
+GREP
+EGREP
+XP_DEF
+EXTRA_SOCKET_LIBS
+EXTRA_THREAD_LIBS
+EXTRA_TIMER_LIBS
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures jscoverage 0.4 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/jscoverage]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of jscoverage 0.4:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --disable-rpath do not hardcode runtime library paths
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-gnu-ld assume the C compiler uses GNU ld default=no
+ --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib
+ --without-libiconv-prefix don't search for libiconv in includedir and libdir
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+jscoverage configure 0.4
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by jscoverage $as_me 0.4, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+am__api_version='1.10'
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $. echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm -f conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+{ echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5
+echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; }
+if test -z "$MKDIR_P"; then
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+ case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir (GNU coreutils) '* | \
+ 'mkdir (coreutils) '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+done
+IFS=$as_save_IFS
+
+fi
+
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ test -d ./--version && rmdir ./--version
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $MKDIR_P" >&5
+echo "${ECHO_T}$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+ [\\/$]* | ?:[\\/]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ SET_MAKE=
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='jscoverage'
+ VERSION='0.4'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+# Checks for programs.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+
+
+{ echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC" am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+ { echo "$as_me:$LINENO: checking for $CC option to accept ISO C99" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C99... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c99+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <stdio.h>
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+#define debug(...) fprintf (stderr, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ your preprocessor is broken;
+#endif
+#if BIG_OK
+#else
+ your preprocessor is broken;
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\0'; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static void
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str;
+ int number;
+ float fnumber;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case 's': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case 'd': // int
+ number = va_arg (args_copy, int);
+ break;
+ case 'f': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+}
+
+int
+main ()
+{
+
+ // Check bool.
+ _Bool success = false;
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ test_varargs ("s, d' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
+ || dynamic_array[ni.number - 1] != 543);
+
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -std=gnu99 -c99 -qlanglvl=extc99
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c99=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c99" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c99"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c99" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c99" >&6; } ;;
+esac
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CXXFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CXX" am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+fi
+
+
+
+# Checks for libraries.
+
+ if test "X$prefix" = "XNONE"; then
+ acl_final_prefix="$ac_default_prefix"
+ else
+ acl_final_prefix="$prefix"
+ fi
+ if test "X$exec_prefix" = "XNONE"; then
+ acl_final_exec_prefix='${prefix}'
+ else
+ acl_final_exec_prefix="$exec_prefix"
+ fi
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+ prefix="$acl_save_prefix"
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { echo "$as_me:$LINENO: checking for ld used by GCC" >&5
+echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | [A-Za-z]:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ { echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+else
+ { echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+fi
+if test "${acl_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ acl_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break ;;
+ *)
+ test "$with_gnu_ld" != yes && break ;;
+ esac
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+ { echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+if test "${acl_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ acl_cv_prog_gnu_ld=yes ;;
+*)
+ acl_cv_prog_gnu_ld=no ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $acl_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$acl_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$acl_cv_prog_gnu_ld
+
+
+
+
+ { echo "$as_me:$LINENO: checking for shared library run path origin" >&5
+echo $ECHO_N "checking for shared library run path origin... $ECHO_C" >&6; }
+if test "${acl_cv_rpath+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+ . ./conftest.sh
+ rm -f ./conftest.sh
+ acl_cv_rpath=done
+
+fi
+{ echo "$as_me:$LINENO: result: $acl_cv_rpath" >&5
+echo "${ECHO_T}$acl_cv_rpath" >&6; }
+ wl="$acl_cv_wl"
+ acl_libext="$acl_cv_libext"
+ acl_shlibext="$acl_cv_shlibext"
+ acl_libname_spec="$acl_cv_libname_spec"
+ acl_library_names_spec="$acl_cv_library_names_spec"
+ acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+ acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+ acl_hardcode_direct="$acl_cv_hardcode_direct"
+ acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
+ # Check whether --enable-rpath was given.
+if test "${enable_rpath+set}" = set; then
+ enableval=$enable_rpath; :
+else
+ enable_rpath=yes
+fi
+
+
+
+ acl_libdirstem=lib
+ searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
+ if test -n "$searchpath"; then
+ acl_save_IFS="${IFS= }"; IFS=":"
+ for searchdir in $searchpath; do
+ if test -d "$searchdir"; then
+ case "$searchdir" in
+ */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
+ *) searchdir=`cd "$searchdir" && pwd`
+ case "$searchdir" in
+ */lib64 ) acl_libdirstem=lib64 ;;
+ esac ;;
+ esac
+ fi
+ done
+ IFS="$acl_save_IFS"
+ fi
+
+
+
+
+
+
+
+
+
+ use_additional=yes
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+
+# Check whether --with-libiconv-prefix was given.
+if test "${with_libiconv_prefix+set}" = set; then
+ withval=$with_libiconv_prefix;
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/$acl_libdirstem"
+ fi
+ fi
+
+fi
+
+ LIBICONV=
+ LTLIBICONV=
+ INCICONV=
+ LIBICONV_PREFIX=
+ rpathdirs=
+ ltrpathdirs=
+ names_already_handled=
+ names_next_round='iconv '
+ while test -n "$names_next_round"; do
+ names_this_round="$names_next_round"
+ names_next_round=
+ for name in $names_this_round; do
+ already_handled=
+ for n in $names_already_handled; do
+ if test "$n" = "$name"; then
+ already_handled=yes
+ break
+ fi
+ done
+ if test -z "$already_handled"; then
+ names_already_handled="$names_already_handled $name"
+ uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+ eval value=\"\$HAVE_LIB$uppername\"
+ if test -n "$value"; then
+ if test "$value" = yes; then
+ eval value=\"\$LIB$uppername\"
+ test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value"
+ eval value=\"\$LTLIB$uppername\"
+ test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value"
+ else
+ :
+ fi
+ else
+ found_dir=
+ found_la=
+ found_so=
+ found_a=
+ eval libname=\"$acl_libname_spec\" # typically: libname=lib$name
+ if test -n "$acl_shlibext"; then
+ shrext=".$acl_shlibext" # typically: shrext=.so
+ else
+ shrext=
+ fi
+ if test $use_additional = yes; then
+ dir="$additional_libdir"
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ for x in $LDFLAGS $LTLIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ case "$x" in
+ -L*)
+ dir=`echo "X$x" | sed -e 's/^X-L//'`
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ ;;
+ esac
+ if test "X$found_dir" != "X"; then
+ break
+ fi
+ done
+ fi
+ if test "X$found_dir" != "X"; then
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name"
+ if test "X$found_so" != "X"; then
+ if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $found_dir"
+ fi
+ if test "$acl_hardcode_direct" = yes; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $found_dir"
+ fi
+ else
+ haveit=
+ for x in $LDFLAGS $LIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir"
+ fi
+ if test "$acl_hardcode_minus_L" != no; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+ fi
+ fi
+ fi
+ fi
+ else
+ if test "X$found_a" != "X"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a"
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name"
+ fi
+ fi
+ additional_includedir=
+ case "$found_dir" in
+ */$acl_libdirstem | */$acl_libdirstem/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
+ LIBICONV_PREFIX="$basedir"
+ additional_includedir="$basedir/include"
+ ;;
+ esac
+ if test "X$additional_includedir" != "X"; then
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ for x in $CPPFLAGS $INCICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ fi
+ if test -n "$found_la"; then
+ save_libdir="$libdir"
+ case "$found_la" in
+ */* | *\\*) . "$found_la" ;;
+ *) . "./$found_la" ;;
+ esac
+ libdir="$save_libdir"
+ for dep in $dependency_libs; do
+ case "$dep" in
+ -L*)
+ additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+ if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+ haveit=
+ if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ haveit=
+ for x in $LDFLAGS $LIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir"
+ fi
+ fi
+ haveit=
+ for x in $LDFLAGS $LTLIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ ;;
+ -R*)
+ dir=`echo "X$dep" | sed -e 's/^X-R//'`
+ if test "$enable_rpath" != no; then
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $dir"
+ fi
+ fi
+ ;;
+ -l*)
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+ ;;
+ *.la)
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+ ;;
+ *)
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$dep"
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep"
+ ;;
+ esac
+ done
+ fi
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name"
+ fi
+ fi
+ fi
+ done
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n "$acl_hardcode_libdir_separator"; then
+ alldirs=
+ for found_dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
+ done
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+ else
+ for found_dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$found_dir"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+ done
+ fi
+ fi
+ if test "X$ltrpathdirs" != "X"; then
+ for found_dir in $ltrpathdirs; do
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir"
+ done
+ fi
+
+
+
+
+
+
+
+
+ am_save_CPPFLAGS="$CPPFLAGS"
+
+ for element in $INCICONV; do
+ haveit=
+ for x in $CPPFLAGS; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X$element"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
+ fi
+ done
+
+
+ { echo "$as_me:$LINENO: checking for iconv" >&5
+echo $ECHO_N "checking for iconv... $ECHO_C" >&6; }
+if test "${am_cv_func_iconv+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ am_cv_func_iconv="no, consider installing GNU libiconv"
+ am_cv_lib_iconv=no
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ am_cv_func_iconv=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ if test "$am_cv_func_iconv" != yes; then
+ am_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBICONV"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ am_cv_lib_iconv=yes
+ am_cv_func_iconv=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$am_save_LIBS"
+ fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_func_iconv" >&5
+echo "${ECHO_T}$am_cv_func_iconv" >&6; }
+ if test "$am_cv_func_iconv" = yes; then
+ { echo "$as_me:$LINENO: checking for working iconv" >&5
+echo $ECHO_N "checking for working iconv... $ECHO_C" >&6; }
+if test "${am_cv_func_iconv_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ am_save_LIBS="$LIBS"
+ if test $am_cv_lib_iconv = yes; then
+ LIBS="$LIBS $LIBICONV"
+ fi
+ if test "$cross_compiling" = yes; then
+ case "$host_os" in
+ aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
+ *) am_cv_func_iconv_works="guessing yes" ;;
+ esac
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <iconv.h>
+#include <string.h>
+int main ()
+{
+ /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
+ returns. */
+ {
+ iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
+ if (cd_utf8_to_88591 != (iconv_t)(-1))
+ {
+ static const char input[] = "\342\202\254"; /* EURO SIGN */
+ char buf[10];
+ const char *inptr = input;
+ size_t inbytesleft = strlen (input);
+ char *outptr = buf;
+ size_t outbytesleft = sizeof (buf);
+ size_t res = iconv (cd_utf8_to_88591,
+ (char **) &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if (res == 0)
+ return 1;
+ }
+ }
+#if 0 /* This bug could be worked around by the caller. */
+ /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */
+ {
+ iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
+ if (cd_88591_to_utf8 != (iconv_t)(-1))
+ {
+ static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
+ char buf[50];
+ const char *inptr = input;
+ size_t inbytesleft = strlen (input);
+ char *outptr = buf;
+ size_t outbytesleft = sizeof (buf);
+ size_t res = iconv (cd_88591_to_utf8,
+ (char **) &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if ((int)res > 0)
+ return 1;
+ }
+ }
+#endif
+ /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
+ provided. */
+ if (/* Try standardized names. */
+ iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
+ /* Try IRIX, OSF/1 names. */
+ && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
+ /* Try AIX names. */
+ && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
+ /* Try HP-UX names. */
+ && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
+ return 1;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ am_cv_func_iconv_works=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+am_cv_func_iconv_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+ LIBS="$am_save_LIBS"
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_func_iconv_works" >&5
+echo "${ECHO_T}$am_cv_func_iconv_works" >&6; }
+ case "$am_cv_func_iconv_works" in
+ *no) am_func_iconv=no am_cv_lib_iconv=no ;;
+ *) am_func_iconv=yes ;;
+ esac
+ else
+ am_func_iconv=no am_cv_lib_iconv=no
+ fi
+ if test "$am_func_iconv" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ICONV 1
+_ACEOF
+
+ fi
+ if test "$am_cv_lib_iconv" = yes; then
+ { echo "$as_me:$LINENO: checking how to link with libiconv" >&5
+echo $ECHO_N "checking how to link with libiconv... $ECHO_C" >&6; }
+ { echo "$as_me:$LINENO: result: $LIBICONV" >&5
+echo "${ECHO_T}$LIBICONV" >&6; }
+ else
+ CPPFLAGS="$am_save_CPPFLAGS"
+ LIBICONV=
+ LTLIBICONV=
+ fi
+
+
+
+ if test "$am_cv_func_iconv" = yes; then
+ { echo "$as_me:$LINENO: checking for iconv declaration" >&5
+echo $ECHO_N "checking for iconv declaration... $ECHO_C" >&6; }
+ if test "${am_cv_proto_iconv+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ am_cv_proto_iconv_arg1=""
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ am_cv_proto_iconv_arg1="const"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"
+fi
+
+ am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+ { echo "$as_me:$LINENO: result: ${ac_t:-
+ }$am_cv_proto_iconv" >&5
+echo "${ECHO_T}${ac_t:-
+ }$am_cv_proto_iconv" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define ICONV_CONST $am_cv_proto_iconv_arg1
+_ACEOF
+
+ fi
+
+
+# Checks for header files.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+ # Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_GREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+ # Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_EGREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in pthread.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in iconv.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in windows.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \
+ && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN)
+ bogus endian macros
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_bigendian=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_bigendian=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+ # try to guess the endianness by grepping values into an object file
+ ac_cv_c_bigendian=unknown
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+ ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_bigendian=no
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6; }
+case $ac_cv_c_bigendian in
+ yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+ no)
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+
+
+# Checks for library functions.
+
+
+
+
+
+
+for ac_func in getaddrinfo gethostbyname_r inet_aton strndup vasprintf asprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+{ echo "$as_me:$LINENO: checking for MultiByteToWideChar" >&5
+echo $ECHO_N "checking for MultiByteToWideChar... $ECHO_C" >&6; }
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <windows.h>
+int
+main ()
+{
+MultiByteToWideChar(0,0,0,0,0,0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MULTIBYTETOWIDECHAR 1
+_ACEOF
+
+ jscoverage_have_multibytetowidechar=yes
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ jscoverage_have_multibytetowidechar=no
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+
+
+case "$host_os" in
+ mingw*)
+ XP_DEF='-DXP_WIN'
+ ;;
+ *)
+ XP_DEF='-DXP_UNIX'
+ ;;
+esac
+
+
+
+
+case "$host_os" in
+ mingw*)
+ EXTRA_SOCKET_LIBS='-lws2_32'
+ EXTRA_THREAD_LIBS=''
+ EXTRA_TIMER_LIBS='-lwinmm'
+ ;;
+ *)
+ EXTRA_SOCKET_LIBS=''
+ EXTRA_THREAD_LIBS='-lpthread'
+ EXTRA_TIMER_LIBS=''
+ ;;
+esac
+
+if test "$am_cv_func_iconv" != yes && test "$jscoverage_have_multibytetowidechar" != yes
+then
+ echo -ne '\033[1;31m'
+ { echo "$as_me:$LINENO: WARNING: neither iconv nor Windows character encoding conversion functions found" >&5
+echo "$as_me: WARNING: neither iconv nor Windows character encoding conversion functions found" >&2;}
+ { echo "$as_me:$LINENO: WARNING: only ASCII will be supported" >&5
+echo "$as_me: WARNING: only ASCII will be supported" >&2;}
+ echo -ne '\033[0m'
+fi
+
+ac_config_files="$ac_config_files Makefile make-dist.sh make-bin-dist.sh tests/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by jscoverage $as_me 0.4, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+jscoverage config.status 0.4
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "make-dist.sh") CONFIG_FILES="$CONFIG_FILES make-dist.sh" ;;
+ "make-bin-dist.sh") CONFIG_FILES="$CONFIG_FILES make-bin-dist.sh" ;;
+ "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+am__isrc!$am__isrc$ac_delim
+CYGPATH_W!$CYGPATH_W$ac_delim
+PACKAGE!$PACKAGE$ac_delim
+VERSION!$VERSION$ac_delim
+ACLOCAL!$ACLOCAL$ac_delim
+AUTOCONF!$AUTOCONF$ac_delim
+AUTOMAKE!$AUTOMAKE$ac_delim
+AUTOHEADER!$AUTOHEADER$ac_delim
+MAKEINFO!$MAKEINFO$ac_delim
+install_sh!$install_sh$ac_delim
+STRIP!$STRIP$ac_delim
+INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim
+mkdir_p!$mkdir_p$ac_delim
+AWK!$AWK$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+am__leading_dot!$am__leading_dot$ac_delim
+AMTAR!$AMTAR$ac_delim
+am__tar!$am__tar$ac_delim
+am__untar!$am__untar$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+DEPDIR!$DEPDIR$ac_delim
+am__include!$am__include$ac_delim
+am__quote!$am__quote$ac_delim
+AMDEP_TRUE!$AMDEP_TRUE$ac_delim
+AMDEP_FALSE!$AMDEP_FALSE$ac_delim
+AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim
+CCDEPMODE!$CCDEPMODE$ac_delim
+am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim
+am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+CXXDEPMODE!$CXXDEPMODE$ac_delim
+am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim
+am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim
+LIBICONV!$LIBICONV$ac_delim
+LTLIBICONV!$LTLIBICONV$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+XP_DEF!$XP_DEF$ac_delim
+EXTRA_SOCKET_LIBS!$EXTRA_SOCKET_LIBS$ac_delim
+EXTRA_THREAD_LIBS!$EXTRA_THREAD_LIBS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+CEOF$ac_eof
+_ACEOF
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+EXTRA_TIMER_LIBS!$EXTRA_TIMER_LIBS$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 3; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+# Compute $ac_file's index in $config_headers.
+_am_arg=$ac_file
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$_am_arg" : 'X\(//\)[^/]' \| \
+ X"$_am_arg" : 'X\(//\)$' \| \
+ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$_am_arg" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir=$dirpart/$fdir
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+ ;;
+
+ esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/configure.ac b/tools/node_modules/expresso/deps/jscoverage/configure.ac
new file mode 100644
index 0000000..33aa915
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/configure.ac
@@ -0,0 +1,88 @@
+# configure.ac - configures jscoverage
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+AC_PREREQ(2.61)
+AC_INIT([jscoverage], [0.4])
+AM_INIT_AUTOMAKE([-Wall foreign])
+AC_CONFIG_SRCDIR([jscoverage.c])
+AC_CONFIG_HEADERS([config.h])
+AC_CANONICAL_HOST
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_CC_C99
+AC_PROG_CXX
+
+# Checks for libraries.
+AM_ICONV
+
+# Checks for header files.
+AC_CHECK_HEADERS([pthread.h])
+AC_CHECK_HEADERS([iconv.h])
+AC_CHECK_HEADERS([windows.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_BIGENDIAN
+
+# Checks for library functions.
+AC_CHECK_FUNCS([getaddrinfo gethostbyname_r inet_aton strndup vasprintf asprintf])
+AC_MSG_CHECKING([for MultiByteToWideChar])
+AC_LANG(C)
+AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[#include <windows.h>]],[[MultiByteToWideChar(0,0,0,0,0,0);]])],
+ [AC_DEFINE([HAVE_MULTIBYTETOWIDECHAR], [1], [Define to 1 if you have the `MultiByteToWideChar' function.])
+ jscoverage_have_multibytetowidechar=yes
+ AC_MSG_RESULT([yes])],
+ [jscoverage_have_multibytetowidechar=no
+ AC_MSG_RESULT([no])])
+
+AC_SUBST([XP_DEF])
+case "$host_os" in
+ mingw*)
+ XP_DEF='-DXP_WIN'
+ ;;
+ *)
+ XP_DEF='-DXP_UNIX'
+ ;;
+esac
+
+AC_SUBST([EXTRA_SOCKET_LIBS])
+AC_SUBST([EXTRA_THREAD_LIBS])
+AC_SUBST([EXTRA_TIMER_LIBS])
+case "$host_os" in
+ mingw*)
+ EXTRA_SOCKET_LIBS='-lws2_32'
+ EXTRA_THREAD_LIBS=''
+ EXTRA_TIMER_LIBS='-lwinmm'
+ ;;
+ *)
+ EXTRA_SOCKET_LIBS=''
+ EXTRA_THREAD_LIBS='-lpthread'
+ EXTRA_TIMER_LIBS=''
+ ;;
+esac
+
+if test "$am_cv_func_iconv" != yes && test "$jscoverage_have_multibytetowidechar" != yes
+then
+ echo -ne '\033@<:@1;31m'
+ AC_MSG_WARN([neither iconv nor Windows character encoding conversion functions found])
+ AC_MSG_WARN([only ASCII will be supported])
+ echo -ne '\033@<:@0m'
+fi
+
+AC_CONFIG_FILES([Makefile make-dist.sh make-bin-dist.sh tests/Makefile])
+AC_OUTPUT
diff --git a/tools/node_modules/expresso/deps/jscoverage/depcomp b/tools/node_modules/expresso/deps/jscoverage/depcomp
new file mode 100755
index 0000000..e5f9736
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/depcomp
@@ -0,0 +1,589 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2007-03-29.01
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software
+# Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+ '')
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+ depmode Dependency tracking mode.
+ source Source file read by `PROGRAMS ARGS'.
+ object Object file output by `PROGRAMS ARGS'.
+ DEPDIR directory where to store dependencies.
+ depfile Dependency file to output.
+ tmpdepfile Temporary file to use when outputing dependencies.
+ libtool Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "depcomp $scriptversion"
+ exit $?
+ ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+ sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am. Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+ for arg
+ do
+ case $arg in
+ -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+ *) set fnord "$@" "$arg" ;;
+ esac
+ shift # fnord
+ shift # $arg
+ done
+ "$@"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> $depfile
+ echo >> $depfile
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> $depfile
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. In older versions, this file always lives in the
+ # current directory. Also, the AIX compiler puts `$object:' at the
+ # start of each line; $object doesn't have directory information.
+ # Version 6 uses the directory in both cases.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$base.u
+ tmpdepfile3=$dir.libs/$base.u
+ "$@" -Wc,-M
+ else
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$dir$base.u
+ tmpdepfile3=$dir$base.u
+ "$@" -M
+ fi
+ stat=$?
+
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+icc)
+ # Intel's C compiler understands `-MD -MF file'. However on
+ # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+ # ICC 7.0 will fill foo.d with something like
+ # foo.o: sub/foo.c
+ # foo.o: sub/foo.h
+ # which is wrong. We want:
+ # sub/foo.o: sub/foo.c
+ # sub/foo.o: sub/foo.h
+ # sub/foo.c:
+ # sub/foo.h:
+ # ICC 7.1 will output
+ # foo.o: sub/foo.c sub/foo.h
+ # and will wrap long lines using \ :
+ # foo.o: sub/foo.c ... \
+ # sub/foo.h ... \
+ # ...
+
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each line is of the form `foo.o: dependent.h',
+ # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+ sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp2)
+ # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+ # compilers, which have integrated preprocessors. The correct option
+ # to use with these is +Maked; it writes dependencies to a file named
+ # 'foo.d', which lands next to the object file, wherever that
+ # happens to be.
+ # Much of this is similar to the tru64 case; see comments there.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir.libs/$base.d
+ "$@" -Wc,+Maked
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ "$@" +Maked
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+ # Add `dependent.h:' lines.
+ sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile" "$tmpdepfile2"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in `foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+ if test "$libtool" = yes; then
+ # With Tru64 cc, shared objects can also be used to make a
+ # static library. This mechanism is used in libtool 1.4 series to
+ # handle both shared and static libraries in a single compilation.
+ # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+ #
+ # With libtool 1.5 this exception was removed, and libtool now
+ # generates 2 separate objects for the 2 libraries. These two
+ # compilations output dependencies in $dir.libs/$base.o.d and
+ # in $dir$base.o.d. We have to check for both files, because
+ # one of the two compilations can be disabled. We should prefer
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+ # automatically cleaned when .libs/ is deleted, while ignoring
+ # the former would cause a distcleancheck panic.
+ tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
+ tmpdepfile2=$dir$base.o.d # libtool 1.5
+ tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
+ tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.o.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ tmpdepfile4=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ test -z "$dashmflag" && dashmflag=-M
+ # Require at least two characters before searching for `:'
+ # in the target name. This is to cope with DOS-style filenames:
+ # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+ "$@" $dashmflag |
+ sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ "$@" || exit $?
+ # Remove any Libtool call
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+ # X makedepend
+ shift
+ cleared=no
+ for arg in "$@"; do
+ case $cleared in
+ no)
+ set ""; shift
+ cleared=yes ;;
+ esac
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift ;;
+ # Strip any option that makedepend may not understand. Remove
+ # the object too, otherwise makedepend will parse it as a source file.
+ -*|$object)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift ;;
+ esac
+ done
+ obj_suffix="`echo $object | sed 's/^.*\././'`"
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ "$@" -E |
+ sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ "$@" || exit $?
+ IFS=" "
+ for arg
+ do
+ case "$arg" in
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/demo.html b/tools/node_modules/expresso/deps/jscoverage/doc/demo.html
new file mode 100644
index 0000000..3d7729e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/demo.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - demo</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <h2>Demo</h2>
+ <p>
+ Several examples of JSCoverage in action are available online. For each demo, click the "Summary" tab
+ after the JavaScript code in the "Browser" tab has executed. See the <a href="manual.html">manual</a>
+ for more information.
+ </p>
+ <dl>
+ <dt><a href="instrumented/jscoverage.html?index.html">Simple demo</a></dt>
+ <dd>A trivial demonstration of JSCoverage. Simply choose a number and then click the "Summary" tab.</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-mochikit/jscoverage.html?tests/index.html">MochiKit test suite</a></dt>
+ <dd>The <a href="http://mochikit.com/">MochiKit</a> library test suite, instrumented using JSCoverage.</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-jquery/jscoverage.html?test/index.html">jQuery test suite</a></dt>
+ <dd>The <a href="http://jquery.com/">jQuery</a> library test suite
+ (which uses the <a href="http://docs.jquery.com/QUnit">QUnit</a> test framework),
+ instrumented using JSCoverage.</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-scriptaculous/jscoverage.html?test/run_unit_tests.html">script.aculo.us test suite</a></dt>
+ <dd>The <a href="http://script.aculo.us/">script.aculo.us</a> library test suite, instrumented using JSCoverage. (For this one you
+ will have to click the links in the left frame to run the tests.)</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-mootools/jscoverage.html?Specs/index.html">MooTools test suite</a></dt>
+ <dd>The <a href="http://mootools.net/">MooTools</a> library test suite
+ (which uses the <a href="http://jania.pe.kr/aw/moin.cgi/JSSpec">JSSpec</a> test framework),
+ instrumented using JSCoverage.</dd>
+ </dl>
+ <h3>Inverted mode</h3>
+ <p>
+ The following are examples of running JSCoverage in "inverted mode":
+ for each demo, click the "Coverage report" button after the JavaScript
+ code on the page has executed.
+ </p>
+ <dl>
+ <dt><a href="instrumented-inverted/index.html">Simple inverted mode demo</a></dt>
+ <dd>A trivial demonstration JSCoverage in "inverted mode".
+ Choose a number and then click the "Coverage report" button.</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-jsunit/jsunit/testRunner.html?testPage=http://siliconforks.com/jscoverage/instrumented-jsunit/test.html&amp;autoRun=true">Simple JsUnit demo</a></dt>
+ <dd>A trivial demonstration of using JSCoverage with JsUnit. Once the
+ JsUnit unit tests have run, click the "Coverage report" button.</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-jsunit-self/jsunit/testRunner.html?testPage=http://siliconforks.com/jscoverage/instrumented-jsunit-self/jsunit/tests/jsUnitTestSuite.html&amp;autoRun=true">JsUnit test suite</a></dt>
+ <dd>JsUnit's own test suite, instrumented using JSCoverage. (Note: some versions of Safari seem to have trouble with the tests in the latest version of JsUnit.)</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-yui/tests/YUI.html">YUI test suite</a>
+ <dd>The <a href="http://developer.yahoo.com/yui/">YUI</a> library test suite
+ (which uses the <a href="http://developer.yahoo.com/yui/yuitest/">YUI Test</a> test framework),
+ instrumented using JSCoverage.
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-dojo/dojo/tests/runTests.html">Dojo test suite</a>
+ <dd>The <a href="http://dojotoolkit.org/">Dojo</a> library test suite
+ (which uses the <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-4-meta-dojo/d-o-h-unit-testing"><acronym title="Dojo Objective Harness">D.O.H.</acronym></a> test framework),
+ instrumented using JSCoverage. (Note: Internet Explorer may generate errors for some tests in this suite.)
+ </dl>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li>Demo
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/doc.css b/tools/node_modules/expresso/deps/jscoverage/doc/doc.css
new file mode 100644
index 0000000..9ac26f4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/doc.css
@@ -0,0 +1,45 @@
+body {
+ margin-left: 3%;
+ margin-right: 3%;
+ font-family: sans-serif;
+}
+
+pre {
+ margin-left: 3%;
+ margin-right: 3%;
+ padding: 1em;
+ border: 1px dotted black;
+ background-color: #eee;
+}
+
+pre.sh_sourceCode {
+ background-color: #eee;
+}
+
+table {
+ margin-left: 3%;
+ margin-right: 3%;
+ border-collapse: collapse;
+}
+
+td {
+ vertical-align: top;
+ border-width: 0;
+ padding: 0;
+}
+
+td.arrow {
+ vertical-align: middle;
+ font-size: xx-large;
+ padding-left: 20px;
+ padding-right: 20px;
+}
+
+td pre {
+ margin: 0;
+}
+
+img.icon {
+ vertical-align: middle;
+ border-width: 0px;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/index.html
new file mode 100644
index 0000000..be0f8ea
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/index.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Example</title>
+<script type="text/javascript" src="script.js"></script>
+<style>
+div.black {
+ color: black;
+}
+div.red {
+ color: red;
+ font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="request" class="red">Please select your favorite number:</div>
+<input type="radio" name="number" id="radio1" onclick="go(this);"><label for="radio1">One</label><br>
+<input type="radio" name="number" id="radio2" onclick="go(this);"><label for="radio2">Two</label><br>
+<input type="radio" name="number" id="radio3" onclick="go(this);"><label for="radio3">Three</label><br>
+<input type="radio" name="number" id="radio4" onclick="go(this);"><label for="radio4">Four</label><br>
+<div id="result" class="red"></div>
+<button onclick='window.open("jscoverage.html");'>Coverage report</button>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/script.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/script.js
new file mode 100644
index 0000000..f36a51d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/script.js
@@ -0,0 +1,20 @@
+function go(element) {
+ var message;
+ if (element.id === 'radio1') {
+ message = 'You selected the number 1.';
+ }
+ else if (element.id === 'radio2') {
+ message = 'You selected the number 2.';
+ }
+ else if (element.id === 'radio3') {
+ message = 'You selected the number 3.';
+ }
+ else if (element.id === 'radio4') {
+ message = 'You selected the number 4.';
+ }
+ var div = document.getElementById('request');
+ div.className = 'black';
+ div = document.getElementById('result');
+ div.innerHTML = '<p>' + message + '</p>';
+ div.innerHTML += '<p>If you are running the instrumented version of this program, you can click the "Coverage report" button to view a coverage report.</p>';
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/jsUnitStyle.css b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/jsUnitStyle.css
new file mode 100644
index 0000000..358bffe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/jsUnitStyle.css
@@ -0,0 +1,50 @@
+body {
+ margin-top: 0;
+ margin-bottom: 0;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ color: #000;
+ font-size: 0.8em;
+ background-color: #fff;
+}
+
+a:link, a:visited {
+ color: #00F;
+}
+
+a:hover {
+ color: #F00;
+}
+
+h1 {
+ font-size: 1.2em;
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h2 {
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h3 {
+ font-weight: bold;
+ color: #039;
+ text-decoration: underline;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h4 {
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+.jsUnitTestResultSuccess {
+ color: #000;
+}
+
+.jsUnitTestResultNotSuccess {
+ color: #F00;
+} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/readme b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/readme
new file mode 100644
index 0000000..f722210
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/readme
@@ -0,0 +1,10 @@
+this file is required due to differences in behavior between Mozilla/Opera
+and Internet Explorer.
+
+main-data.html calls kickOffTests() which calls top.testManager.start()
+in the top most frame. top.testManager.start() initializes the output
+frames using document.write and HTML containing a relative <link> to the
+jsUnitStyle.css file. In MSIE, the base href used to find the CSS file is
+that of the top level frame however in Mozilla/Opera the base href is
+that of main-data.html. This leads to not-found for the jsUnitStyle.css
+in Mozilla/Opera. Creating app/css/jsUnitStyle.css works around this problem.
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/emptyPage.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/emptyPage.html
new file mode 100644
index 0000000..f9729dc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/emptyPage.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>emptyPage</title>
+</head>
+
+<body>
+</body>
+</html>
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitCore.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitCore.js
new file mode 100644
index 0000000..438513e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitCore.js
@@ -0,0 +1,534 @@
+var JSUNIT_UNDEFINED_VALUE;
+var JSUNIT_VERSION = 2.2;
+var isTestPageLoaded = false;
+
+//hack for NS62 bug
+function jsUnitFixTop() {
+ var tempTop = top;
+ if (!tempTop) {
+ tempTop = window;
+ while (tempTop.parent) {
+ tempTop = tempTop.parent;
+ if (tempTop.top && tempTop.top.jsUnitTestSuite) {
+ tempTop = tempTop.top;
+ break;
+ }
+ }
+ }
+ try {
+ window.top = tempTop;
+ } catch (e) {
+ }
+}
+
+jsUnitFixTop();
+
+/**
+ + * A more functional typeof
+ + * @param Object o
+ + * @return String
+ + */
+function _trueTypeOf(something) {
+ var result = typeof something;
+ try {
+ switch (result) {
+ case 'string':
+ case 'boolean':
+ case 'number':
+ break;
+ case 'object':
+ case 'function':
+ switch (something.constructor)
+ {
+ case String:
+ result = 'String';
+ break;
+ case Boolean:
+ result = 'Boolean';
+ break;
+ case Number:
+ result = 'Number';
+ break;
+ case Array:
+ result = 'Array';
+ break;
+ case RegExp:
+ result = 'RegExp';
+ break;
+ case Function:
+ result = 'Function';
+ break;
+ default:
+ var m = something.constructor.toString().match(/function\s*([^( ]+)\(/);
+ if (m)
+ result = m[1];
+ else
+ break;
+ }
+ break;
+ }
+ }
+ finally {
+ result = result.substr(0, 1).toUpperCase() + result.substr(1);
+ return result;
+ }
+}
+
+function _displayStringForValue(aVar) {
+ var result = '<' + aVar + '>';
+ if (!(aVar === null || aVar === top.JSUNIT_UNDEFINED_VALUE)) {
+ result += ' (' + _trueTypeOf(aVar) + ')';
+ }
+ return result;
+}
+
+function fail(failureMessage) {
+ throw new JsUnitException("Call to fail()", failureMessage);
+}
+
+function error(errorMessage) {
+ var errorObject = new Object();
+ errorObject.description = errorMessage;
+ errorObject.stackTrace = getStackTrace();
+ throw errorObject;
+}
+
+function argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) {
+ return args.length == expectedNumberOfNonCommentArgs + 1;
+}
+
+function commentArg(expectedNumberOfNonCommentArgs, args) {
+ if (argumentsIncludeComments(expectedNumberOfNonCommentArgs, args))
+ return args[0];
+
+ return null;
+}
+
+function nonCommentArg(desiredNonCommentArgIndex, expectedNumberOfNonCommentArgs, args) {
+ return argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) ?
+ args[desiredNonCommentArgIndex] :
+ args[desiredNonCommentArgIndex - 1];
+}
+
+function _validateArguments(expectedNumberOfNonCommentArgs, args) {
+ if (!( args.length == expectedNumberOfNonCommentArgs ||
+ (args.length == expectedNumberOfNonCommentArgs + 1 && typeof(args[0]) == 'string') ))
+ error('Incorrect arguments passed to assert function');
+}
+
+function _assert(comment, booleanValue, failureMessage) {
+ if (!booleanValue)
+ throw new JsUnitException(comment, failureMessage);
+}
+
+function assert() {
+ _validateArguments(1, arguments);
+ var booleanValue = nonCommentArg(1, 1, arguments);
+
+ if (typeof(booleanValue) != 'boolean')
+ error('Bad argument to assert(boolean)');
+
+ _assert(commentArg(1, arguments), booleanValue === true, 'Call to assert(boolean) with false');
+}
+
+function assertTrue() {
+ _validateArguments(1, arguments);
+ var booleanValue = nonCommentArg(1, 1, arguments);
+
+ if (typeof(booleanValue) != 'boolean')
+ error('Bad argument to assertTrue(boolean)');
+
+ _assert(commentArg(1, arguments), booleanValue === true, 'Call to assertTrue(boolean) with false');
+}
+
+function assertFalse() {
+ _validateArguments(1, arguments);
+ var booleanValue = nonCommentArg(1, 1, arguments);
+
+ if (typeof(booleanValue) != 'boolean')
+ error('Bad argument to assertFalse(boolean)');
+
+ _assert(commentArg(1, arguments), booleanValue === false, 'Call to assertFalse(boolean) with true');
+}
+
+function assertEquals() {
+ _validateArguments(2, arguments);
+ var var1 = nonCommentArg(1, 2, arguments);
+ var var2 = nonCommentArg(2, 2, arguments);
+ _assert(commentArg(2, arguments), var1 === var2, 'Expected ' + _displayStringForValue(var1) + ' but was ' + _displayStringForValue(var2));
+}
+
+function assertNotEquals() {
+ _validateArguments(2, arguments);
+ var var1 = nonCommentArg(1, 2, arguments);
+ var var2 = nonCommentArg(2, 2, arguments);
+ _assert(commentArg(2, arguments), var1 !== var2, 'Expected not to be ' + _displayStringForValue(var2));
+}
+
+function assertNull() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), aVar === null, 'Expected ' + _displayStringForValue(null) + ' but was ' + _displayStringForValue(aVar));
+}
+
+function assertNotNull() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), aVar !== null, 'Expected not to be ' + _displayStringForValue(null));
+}
+
+function assertUndefined() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), aVar === top.JSUNIT_UNDEFINED_VALUE, 'Expected ' + _displayStringForValue(top.JSUNIT_UNDEFINED_VALUE) + ' but was ' + _displayStringForValue(aVar));
+}
+
+function assertNotUndefined() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), aVar !== top.JSUNIT_UNDEFINED_VALUE, 'Expected not to be ' + _displayStringForValue(top.JSUNIT_UNDEFINED_VALUE));
+}
+
+function assertNaN() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), isNaN(aVar), 'Expected NaN');
+}
+
+function assertNotNaN() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), !isNaN(aVar), 'Expected not NaN');
+}
+
+function assertObjectEquals() {
+ _validateArguments(2, arguments);
+ var var1 = nonCommentArg(1, 2, arguments);
+ var var2 = nonCommentArg(2, 2, arguments);
+ var type;
+ var msg = commentArg(2, arguments)?commentArg(2, arguments):'';
+ var isSame = (var1 === var2);
+ //shortpath for references to same object
+ var isEqual = ( (type = _trueTypeOf(var1)) == _trueTypeOf(var2) );
+ if (isEqual && !isSame) {
+ switch (type) {
+ case 'String':
+ case 'Number':
+ isEqual = (var1 == var2);
+ break;
+ case 'Boolean':
+ case 'Date':
+ isEqual = (var1 === var2);
+ break;
+ case 'RegExp':
+ case 'Function':
+ isEqual = (var1.toString() === var2.toString());
+ break;
+ default: //Object | Array
+ var i;
+ if (isEqual = (var1.length === var2.length))
+ for (i in var1)
+ assertObjectEquals(msg + ' found nested ' + type + '@' + i + '\n', var1[i], var2[i]);
+ }
+ _assert(msg, isEqual, 'Expected ' + _displayStringForValue(var1) + ' but was ' + _displayStringForValue(var2));
+ }
+}
+
+assertArrayEquals = assertObjectEquals;
+
+function assertEvaluatesToTrue() {
+ _validateArguments(1, arguments);
+ var value = nonCommentArg(1, 1, arguments);
+ if (!value)
+ fail(commentArg(1, arguments));
+}
+
+function assertEvaluatesToFalse() {
+ _validateArguments(1, arguments);
+ var value = nonCommentArg(1, 1, arguments);
+ if (value)
+ fail(commentArg(1, arguments));
+}
+
+function assertHTMLEquals() {
+ _validateArguments(2, arguments);
+ var var1 = nonCommentArg(1, 2, arguments);
+ var var2 = nonCommentArg(2, 2, arguments);
+ var var1Standardized = standardizeHTML(var1);
+ var var2Standardized = standardizeHTML(var2);
+
+ _assert(commentArg(2, arguments), var1Standardized === var2Standardized, 'Expected ' + _displayStringForValue(var1Standardized) + ' but was ' + _displayStringForValue(var2Standardized));
+}
+
+function assertHashEquals() {
+ _validateArguments(2, arguments);
+ var var1 = nonCommentArg(1, 2, arguments);
+ var var2 = nonCommentArg(2, 2, arguments);
+ for (var key in var1) {
+ assertNotUndefined("Expected hash had key " + key + " that was not found", var2[key]);
+ assertEquals(
+ "Value for key " + key + " mismatch - expected = " + var1[key] + ", actual = " + var2[key],
+ var1[key], var2[key]
+ );
+ }
+ for (var key in var2) {
+ assertNotUndefined("Actual hash had key " + key + " that was not expected", var1[key]);
+ }
+}
+
+function assertRoughlyEquals() {
+ _validateArguments(3, arguments);
+ var expected = nonCommentArg(1, 3, arguments);
+ var actual = nonCommentArg(2, 3, arguments);
+ var tolerance = nonCommentArg(3, 3, arguments);
+ assertTrue(
+ "Expected " + expected + ", but got " + actual + " which was more than " + tolerance + " away",
+ Math.abs(expected - actual) < tolerance
+ );
+}
+
+function assertContains() {
+ _validateArguments(2, arguments);
+ var contained = nonCommentArg(1, 2, arguments);
+ var container = nonCommentArg(2, 2, arguments);
+ assertTrue(
+ "Expected '" + container + "' to contain '" + contained + "'",
+ container.indexOf(contained) != -1
+ );
+}
+
+function standardizeHTML(html) {
+ var translator = document.createElement("DIV");
+ translator.innerHTML = html;
+ return translator.innerHTML;
+}
+
+function isLoaded() {
+ return isTestPageLoaded;
+}
+
+function setUp() {
+}
+
+function tearDown() {
+}
+
+function getFunctionName(aFunction) {
+ var regexpResult = aFunction.toString().match(/function(\s*)(\w*)/);
+ if (regexpResult && regexpResult.length >= 2 && regexpResult[2]) {
+ return regexpResult[2];
+ }
+ return 'anonymous';
+}
+
+function getStackTrace() {
+ var result = '';
+
+ if (typeof(arguments.caller) != 'undefined') { // IE, not ECMA
+ for (var a = arguments.caller; a != null; a = a.caller) {
+ result += '> ' + getFunctionName(a.callee) + '\n';
+ if (a.caller == a) {
+ result += '*';
+ break;
+ }
+ }
+ }
+ else { // Mozilla, not ECMA
+ // fake an exception so we can get Mozilla's error stack
+ var testExcp;
+ try
+ {
+ foo.bar;
+ }
+ catch(testExcp)
+ {
+ var stack = parseErrorStack(testExcp);
+ for (var i = 1; i < stack.length; i++)
+ {
+ result += '> ' + stack[i] + '\n';
+ }
+ }
+ }
+
+ return result;
+}
+
+function parseErrorStack(excp)
+{
+ var stack = [];
+ var name;
+
+ if (!excp || !excp.stack)
+ {
+ return stack;
+ }
+
+ var stacklist = excp.stack.split('\n');
+
+ for (var i = 0; i < stacklist.length - 1; i++)
+ {
+ var framedata = stacklist[i];
+
+ name = framedata.match(/^(\w*)/)[1];
+ if (!name) {
+ name = 'anonymous';
+ }
+
+ stack[stack.length] = name;
+ }
+ // remove top level anonymous functions to match IE
+
+ while (stack.length && stack[stack.length - 1] == 'anonymous')
+ {
+ stack.length = stack.length - 1;
+ }
+ return stack;
+}
+
+function JsUnitException(comment, message) {
+ this.isJsUnitException = true;
+ this.comment = comment;
+ this.jsUnitMessage = message;
+ this.stackTrace = getStackTrace();
+}
+
+function warn() {
+ if (top.tracer != null)
+ top.tracer.warn(arguments[0], arguments[1]);
+}
+
+function inform() {
+ if (top.tracer != null)
+ top.tracer.inform(arguments[0], arguments[1]);
+}
+
+function info() {
+ inform(arguments[0], arguments[1]);
+}
+
+function debug() {
+ if (top.tracer != null)
+ top.tracer.debug(arguments[0], arguments[1]);
+}
+
+function setJsUnitTracer(aJsUnitTracer) {
+ top.tracer = aJsUnitTracer;
+}
+
+function trim(str) {
+ if (str == null)
+ return null;
+
+ var startingIndex = 0;
+ var endingIndex = str.length - 1;
+
+ while (str.substring(startingIndex, startingIndex + 1) == ' ')
+ startingIndex++;
+
+ while (str.substring(endingIndex, endingIndex + 1) == ' ')
+ endingIndex--;
+
+ if (endingIndex < startingIndex)
+ return '';
+
+ return str.substring(startingIndex, endingIndex + 1);
+}
+
+function isBlank(str) {
+ return trim(str) == '';
+}
+
+// the functions push(anArray, anObject) and pop(anArray)
+// exist because the JavaScript Array.push(anObject) and Array.pop()
+// functions are not available in IE 5.0
+
+function push(anArray, anObject) {
+ anArray[anArray.length] = anObject;
+}
+function pop(anArray) {
+ if (anArray.length >= 1) {
+ delete anArray[anArray.length - 1];
+ anArray.length--;
+ }
+}
+
+function jsUnitGetParm(name)
+{
+ if (typeof(top.jsUnitParmHash[name]) != 'undefined')
+ {
+ return top.jsUnitParmHash[name];
+ }
+ return null;
+}
+
+if (top && typeof(top.xbDEBUG) != 'undefined' && top.xbDEBUG.on && top.testManager)
+{
+ top.xbDebugTraceObject('top.testManager.containerTestFrame', 'JSUnitException');
+ // asserts
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', '_displayStringForValue');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'error');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'argumentsIncludeComments');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'commentArg');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'nonCommentArg');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', '_validateArguments');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', '_assert');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assert');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertTrue');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertEquals');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotEquals');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNull');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotNull');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertUndefined');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotUndefined');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNaN');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotNaN');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'isLoaded');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'setUp');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'tearDown');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'getFunctionName');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'getStackTrace');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'warn');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'inform');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'debug');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'setJsUnitTracer');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'trim');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'isBlank');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'newOnLoadEvent');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'push');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'pop');
+}
+
+function newOnLoadEvent() {
+ isTestPageLoaded = true;
+}
+
+function jsUnitSetOnLoad(windowRef, onloadHandler)
+{
+ var isKonqueror = navigator.userAgent.indexOf('Konqueror/') != -1 ||
+ navigator.userAgent.indexOf('Safari/') != -1;
+
+ if (typeof(windowRef.attachEvent) != 'undefined') {
+ // Internet Explorer, Opera
+ windowRef.attachEvent("onload", onloadHandler);
+ } else if (typeof(windowRef.addEventListener) != 'undefined' && !isKonqueror) {
+ // Mozilla, Konqueror
+ // exclude Konqueror due to load issues
+ windowRef.addEventListener("load", onloadHandler, false);
+ } else if (typeof(windowRef.document.addEventListener) != 'undefined' && !isKonqueror) {
+ // DOM 2 Events
+ // exclude Mozilla, Konqueror due to load issues
+ windowRef.document.addEventListener("load", onloadHandler, false);
+ } else if (typeof(windowRef.onload) != 'undefined' && windowRef.onload) {
+ windowRef.jsunit_original_onload = windowRef.onload;
+ windowRef.onload = function() {
+ windowRef.jsunit_original_onload();
+ onloadHandler();
+ };
+ } else {
+ // browsers that do not support windowRef.attachEvent or
+ // windowRef.addEventListener will override a page's own onload event
+ windowRef.onload = onloadHandler;
+ }
+}
+
+jsUnitSetOnLoad(window, newOnLoadEvent); \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitMockTimeout.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitMockTimeout.js
new file mode 100644
index 0000000..99a4bf1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitMockTimeout.js
@@ -0,0 +1,81 @@
+// Mock setTimeout, clearTimeout
+// Contributed by Pivotal Computer Systems, www.pivotalsf.com
+
+var Clock = {
+ timeoutsMade: 0,
+ scheduledFunctions: {},
+ nowMillis: 0,
+ reset: function() {
+ this.scheduledFunctions = {};
+ this.nowMillis = 0;
+ this.timeoutsMade = 0;
+ },
+ tick: function(millis) {
+ var oldMillis = this.nowMillis;
+ var newMillis = oldMillis + millis;
+ this.runFunctionsWithinRange(oldMillis, newMillis);
+ this.nowMillis = newMillis;
+ },
+ runFunctionsWithinRange: function(oldMillis, nowMillis) {
+ var scheduledFunc;
+ var funcsToRun = [];
+ for (var timeoutKey in this.scheduledFunctions) {
+ scheduledFunc = this.scheduledFunctions[timeoutKey];
+ if (scheduledFunc != undefined &&
+ scheduledFunc.runAtMillis >= oldMillis &&
+ scheduledFunc.runAtMillis <= nowMillis) {
+ funcsToRun.push(scheduledFunc);
+ this.scheduledFunctions[timeoutKey] = undefined;
+ }
+ }
+
+ if (funcsToRun.length > 0) {
+ funcsToRun.sort(function(a, b) {
+ return a.runAtMillis - b.runAtMillis;
+ });
+ for (var i = 0; i < funcsToRun.length; ++i) {
+ try {
+ this.nowMillis = funcsToRun[i].runAtMillis;
+ funcsToRun[i].funcToCall();
+ if (funcsToRun[i].recurring) {
+ Clock.scheduleFunction(funcsToRun[i].timeoutKey,
+ funcsToRun[i].funcToCall,
+ funcsToRun[i].millis,
+ true);
+ }
+ } catch(e) {
+ }
+ }
+ this.runFunctionsWithinRange(oldMillis, nowMillis);
+ }
+ },
+ scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
+ Clock.scheduledFunctions[timeoutKey] = {
+ runAtMillis: Clock.nowMillis + millis,
+ funcToCall: funcToCall,
+ recurring: recurring,
+ timeoutKey: timeoutKey,
+ millis: millis
+ };
+ }
+};
+
+function setTimeout(funcToCall, millis) {
+ Clock.timeoutsMade = Clock.timeoutsMade + 1;
+ Clock.scheduleFunction(Clock.timeoutsMade, funcToCall, millis, false);
+ return Clock.timeoutsMade;
+}
+
+function setInterval(funcToCall, millis) {
+ Clock.timeoutsMade = Clock.timeoutsMade + 1;
+ Clock.scheduleFunction(Clock.timeoutsMade, funcToCall, millis, true);
+ return Clock.timeoutsMade;
+}
+
+function clearTimeout(timeoutKey) {
+ Clock.scheduledFunctions[timeoutKey] = undefined;
+}
+
+function clearInterval(timeoutKey) {
+ Clock.scheduledFunctions[timeoutKey] = undefined;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestManager.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestManager.js
new file mode 100644
index 0000000..7d5bf0f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestManager.js
@@ -0,0 +1,705 @@
+function jsUnitTestManager() {
+ this._windowForAllProblemMessages = null;
+
+ this.container = top.frames.testContainer
+ this.documentLoader = top.frames.documentLoader;
+ this.mainFrame = top.frames.mainFrame;
+
+ this.containerController = this.container.frames.testContainerController;
+ this.containerTestFrame = this.container.frames.testFrame;
+
+ var mainData = this.mainFrame.frames.mainData;
+
+ // form elements on mainData frame
+ this.testFileName = mainData.document.testRunnerForm.testFileName;
+ this.runButton = mainData.document.testRunnerForm.runButton;
+ this.traceLevel = mainData.document.testRunnerForm.traceLevel;
+ this.closeTraceWindowOnNewRun = mainData.document.testRunnerForm.closeTraceWindowOnNewRun;
+ this.timeout = mainData.document.testRunnerForm.timeout;
+ this.setUpPageTimeout = mainData.document.testRunnerForm.setUpPageTimeout;
+
+ // image output
+ this.progressBar = this.mainFrame.frames.mainProgress.document.progress;
+
+ this.problemsListField = this.mainFrame.frames.mainErrors.document.testRunnerForm.problemsList;
+ this.testCaseResultsField = this.mainFrame.frames.mainResults.document.resultsForm.testCases;
+ this.resultsTimeField = this.mainFrame.frames.mainResults.document.resultsForm.time;
+
+ // 'layer' output frames
+ this.uiFrames = new Object();
+ this.uiFrames.mainStatus = this.mainFrame.frames.mainStatus;
+
+ var mainCounts = this.mainFrame.frames.mainCounts;
+
+ this.uiFrames.mainCountsErrors = mainCounts.frames.mainCountsErrors;
+ this.uiFrames.mainCountsFailures = mainCounts.frames.mainCountsFailures;
+ this.uiFrames.mainCountsRuns = mainCounts.frames.mainCountsRuns;
+ this._baseURL = "";
+
+ this.setup();
+}
+
+// seconds to wait for each test page to load
+jsUnitTestManager.TESTPAGE_WAIT_SEC = 120;
+jsUnitTestManager.TIMEOUT_LENGTH = 20;
+
+// seconds to wait for setUpPage to complete
+jsUnitTestManager.SETUPPAGE_TIMEOUT = 120;
+
+// milliseconds to wait between polls on setUpPages
+jsUnitTestManager.SETUPPAGE_INTERVAL = 100;
+
+jsUnitTestManager.RESTORED_HTML_DIV_ID = "jsUnitRestoredHTML";
+
+jsUnitTestManager.prototype.setup = function () {
+ this.totalCount = 0;
+ this.errorCount = 0;
+ this.failureCount = 0;
+ this._suiteStack = Array();
+
+ var initialSuite = new top.jsUnitTestSuite();
+ push(this._suiteStack, initialSuite);
+}
+
+jsUnitTestManager.prototype.start = function () {
+ this._baseURL = this.resolveUserEnteredTestFileName();
+ var firstQuery = this._baseURL.indexOf("?");
+ if (firstQuery >= 0) {
+ this._baseURL = this._baseURL.substring(0, firstQuery);
+ }
+ var lastSlash = this._baseURL.lastIndexOf("/");
+ var lastRevSlash = this._baseURL.lastIndexOf("\\");
+ if (lastRevSlash > lastSlash) {
+ lastSlash = lastRevSlash;
+ }
+ if (lastSlash > 0) {
+ this._baseURL = this._baseURL.substring(0, lastSlash + 1);
+ }
+
+ this._timeRunStarted = new Date();
+ this.initialize();
+ setTimeout('top.testManager._nextPage();', jsUnitTestManager.TIMEOUT_LENGTH);
+}
+
+jsUnitTestManager.prototype.getBaseURL = function () {
+ return this._baseURL;
+}
+
+jsUnitTestManager.prototype.doneLoadingPage = function (pageName) {
+ //this.containerTestFrame.setTracer(top.tracer);
+ this._testFileName = pageName;
+ if (this.isTestPageSuite())
+ this._handleNewSuite();
+ else
+ {
+ this._testIndex = 0;
+ this._testsInPage = this.getTestFunctionNames();
+ this._numberOfTestsInPage = this._testsInPage.length;
+ this._runTest();
+ }
+}
+
+jsUnitTestManager.prototype._handleNewSuite = function () {
+ var allegedSuite = this.containerTestFrame.suite();
+ if (allegedSuite.isjsUnitTestSuite) {
+ var newSuite = allegedSuite.clone();
+ if (newSuite.containsTestPages())
+ push(this._suiteStack, newSuite);
+ this._nextPage();
+ }
+ else {
+ this.fatalError('Invalid test suite in file ' + this._testFileName);
+ this.abort();
+ }
+}
+
+jsUnitTestManager.prototype._runTest = function () {
+ if (this._testIndex + 1 > this._numberOfTestsInPage)
+ {
+ // execute tearDownPage *synchronously*
+ // (unlike setUpPage which is asynchronous)
+ if (typeof this.containerTestFrame.tearDownPage == 'function') {
+ this.containerTestFrame.tearDownPage();
+ }
+
+ this._nextPage();
+ return;
+ }
+
+ if (this._testIndex == 0) {
+ this.storeRestoredHTML();
+ if (typeof(this.containerTestFrame.setUpPage) == 'function') {
+ // first test for this page and a setUpPage is defined
+ if (typeof(this.containerTestFrame.setUpPageStatus) == 'undefined') {
+ // setUpPage() not called yet, so call it
+ this.containerTestFrame.setUpPageStatus = false;
+ this.containerTestFrame.startTime = new Date();
+ this.containerTestFrame.setUpPage();
+ // try test again later
+ setTimeout('top.testManager._runTest()', jsUnitTestManager.SETUPPAGE_INTERVAL);
+ return;
+ }
+
+ if (this.containerTestFrame.setUpPageStatus != 'complete') {
+ top.status = 'setUpPage not completed... ' + this.containerTestFrame.setUpPageStatus + ' ' + (new Date());
+ if ((new Date() - this.containerTestFrame.startTime) / 1000 > this.getsetUpPageTimeout()) {
+ this.fatalError('setUpPage timed out without completing.');
+ if (!this.userConfirm('Retry Test Run?')) {
+ this.abort();
+ return;
+ }
+ this.containerTestFrame.startTime = (new Date());
+ }
+ // try test again later
+ setTimeout('top.testManager._runTest()', jsUnitTestManager.SETUPPAGE_INTERVAL);
+ return;
+ }
+ }
+ }
+
+ top.status = '';
+ // either not first test, or no setUpPage defined, or setUpPage completed
+ this.executeTestFunction(this._testsInPage[this._testIndex]);
+ this.totalCount++;
+ this.updateProgressIndicators();
+ this._testIndex++;
+ setTimeout('top.testManager._runTest()', jsUnitTestManager.TIMEOUT_LENGTH);
+}
+
+jsUnitTestManager.prototype._done = function () {
+ var secondsSinceRunBegan = (new Date() - this._timeRunStarted) / 1000;
+ this.setStatus('Done (' + secondsSinceRunBegan + ' seconds)');
+ this._cleanUp();
+ if (top.shouldSubmitResults()) {
+ this.resultsTimeField.value = secondsSinceRunBegan;
+ top.submitResults();
+ }
+}
+
+jsUnitTestManager.prototype._nextPage = function () {
+ this._restoredHTML = null;
+ if (this._currentSuite().hasMorePages()) {
+ this.loadPage(this._currentSuite().nextPage());
+ }
+ else {
+ pop(this._suiteStack);
+ if (this._currentSuite() == null)
+ this._done();
+ else
+ this._nextPage();
+ }
+}
+
+jsUnitTestManager.prototype._currentSuite = function () {
+ var suite = null;
+
+ if (this._suiteStack && this._suiteStack.length > 0)
+ suite = this._suiteStack[this._suiteStack.length - 1];
+
+ return suite;
+}
+
+jsUnitTestManager.prototype.calculateProgressBarProportion = function () {
+ if (this.totalCount == 0)
+ return 0;
+ var currentDivisor = 1;
+ var result = 0;
+
+ for (var i = 0; i < this._suiteStack.length; i++) {
+ var aSuite = this._suiteStack[i];
+ currentDivisor *= aSuite.testPages.length;
+ result += (aSuite.pageIndex - 1) / currentDivisor;
+ }
+ result += (this._testIndex + 1) / (this._numberOfTestsInPage * currentDivisor);
+ return result;
+}
+
+jsUnitTestManager.prototype._cleanUp = function () {
+ this.containerController.setTestPage('./app/emptyPage.html');
+ this.finalize();
+ top.tracer.finalize();
+}
+
+jsUnitTestManager.prototype.abort = function () {
+ this.setStatus('Aborted');
+ this._cleanUp();
+}
+
+jsUnitTestManager.prototype.getTimeout = function () {
+ var result = jsUnitTestManager.TESTPAGE_WAIT_SEC;
+ try {
+ result = eval(this.timeout.value);
+ }
+ catch (e) {
+ }
+ return result;
+}
+
+jsUnitTestManager.prototype.getsetUpPageTimeout = function () {
+ var result = jsUnitTestManager.SETUPPAGE_TIMEOUT;
+ try {
+ result = eval(this.setUpPageTimeout.value);
+ }
+ catch (e) {
+ }
+ return result;
+}
+
+jsUnitTestManager.prototype.isTestPageSuite = function () {
+ var result = false;
+ if (typeof(this.containerTestFrame.suite) == 'function')
+ {
+ result = true;
+ }
+ return result;
+}
+
+jsUnitTestManager.prototype.getTestFunctionNames = function () {
+ var testFrame = this.containerTestFrame;
+ var testFunctionNames = new Array();
+ var i;
+
+ if (testFrame && typeof(testFrame.exposeTestFunctionNames) == 'function')
+ return testFrame.exposeTestFunctionNames();
+
+ if (testFrame &&
+ testFrame.document &&
+ typeof(testFrame.document.scripts) != 'undefined' &&
+ testFrame.document.scripts.length > 0) { // IE5 and up
+ var scriptsInTestFrame = testFrame.document.scripts;
+
+ for (i = 0; i < scriptsInTestFrame.length; i++) {
+ var someNames = this._extractTestFunctionNamesFromScript(scriptsInTestFrame[i]);
+ if (someNames)
+ testFunctionNames = testFunctionNames.concat(someNames);
+ }
+ }
+ else {
+ for (i in testFrame) {
+ if (i.substring(0, 4) == 'test' && typeof(testFrame[i]) == 'function')
+ push(testFunctionNames, i);
+ }
+ }
+ return testFunctionNames;
+}
+
+jsUnitTestManager.prototype._extractTestFunctionNamesFromScript = function (aScript) {
+ var result;
+ var remainingScriptToInspect = aScript.text;
+ var currentIndex = this._indexOfTestFunctionIn(remainingScriptToInspect);
+ while (currentIndex != -1) {
+ if (!result)
+ result = new Array();
+
+ var fragment = remainingScriptToInspect.substring(currentIndex, remainingScriptToInspect.length);
+ result = result.concat(fragment.substring('function '.length, fragment.indexOf('(')));
+ remainingScriptToInspect = remainingScriptToInspect.substring(currentIndex + 12, remainingScriptToInspect.length);
+ currentIndex = this._indexOfTestFunctionIn(remainingScriptToInspect);
+ }
+ return result;
+}
+
+jsUnitTestManager.prototype._indexOfTestFunctionIn = function (string) {
+ return string.indexOf('function test');
+}
+
+jsUnitTestManager.prototype.loadPage = function (testFileName) {
+ this._testFileName = testFileName;
+ this._loadAttemptStartTime = new Date();
+ this.setStatus('Opening Test Page "' + this._testFileName + '"');
+ this.containerController.setTestPage(this._testFileName);
+ this._callBackWhenPageIsLoaded();
+}
+
+jsUnitTestManager.prototype._callBackWhenPageIsLoaded = function () {
+ if ((new Date() - this._loadAttemptStartTime) / 1000 > this.getTimeout()) {
+ this.fatalError('Reading Test Page ' + this._testFileName + ' timed out.\nMake sure that the file exists and is a Test Page.');
+ if (this.userConfirm('Retry Test Run?')) {
+ this.loadPage(this._testFileName);
+ return;
+ } else {
+ this.abort();
+ return;
+ }
+ }
+ if (!this._isTestFrameLoaded()) {
+ setTimeout('top.testManager._callBackWhenPageIsLoaded();', jsUnitTestManager.TIMEOUT_LENGTH);
+ return;
+ }
+ this.doneLoadingPage(this._testFileName);
+}
+
+jsUnitTestManager.prototype._isTestFrameLoaded = function () {
+ try {
+ return this.containerController.isPageLoaded();
+ }
+ catch (e) {
+ }
+ return false;
+}
+
+jsUnitTestManager.prototype.executeTestFunction = function (functionName) {
+ this._testFunctionName = functionName;
+ this.setStatus('Running test "' + this._testFunctionName + '"');
+ var excep = null;
+ var timeBefore = new Date();
+ try {
+ if (this._restoredHTML)
+ top.testContainer.testFrame.document.getElementById(jsUnitTestManager.RESTORED_HTML_DIV_ID).innerHTML = this._restoredHTML;
+ if (this.containerTestFrame.setUp !== JSUNIT_UNDEFINED_VALUE)
+ this.containerTestFrame.setUp();
+ this.containerTestFrame[this._testFunctionName]();
+ }
+ catch (e1) {
+ excep = e1;
+ }
+ finally {
+ try {
+ if (this.containerTestFrame.tearDown !== JSUNIT_UNDEFINED_VALUE)
+ this.containerTestFrame.tearDown();
+ }
+ catch (e2) {
+ //Unlike JUnit, only assign a tearDown exception to excep if there is not already an exception from the test body
+ if (excep == null)
+ excep = e2;
+ }
+ }
+ var timeTaken = (new Date() - timeBefore) / 1000;
+ if (excep != null)
+ this._handleTestException(excep);
+ var serializedTestCaseString = this._currentTestFunctionNameWithTestPageName(true) + "|" + timeTaken + "|";
+ if (excep == null)
+ serializedTestCaseString += "S||";
+ else {
+ if (typeof(excep.isJsUnitException) != 'undefined' && excep.isJsUnitException)
+ serializedTestCaseString += "F|";
+ else {
+ serializedTestCaseString += "E|";
+ }
+ serializedTestCaseString += this._problemDetailMessageFor(excep);
+ }
+ this._addOption(this.testCaseResultsField,
+ serializedTestCaseString,
+ serializedTestCaseString);
+}
+
+jsUnitTestManager.prototype._currentTestFunctionNameWithTestPageName = function(useFullyQualifiedTestPageName) {
+ var testURL = this.containerTestFrame.location.href;
+ var testQuery = testURL.indexOf("?");
+ if (testQuery >= 0) {
+ testURL = testURL.substring(0, testQuery);
+ }
+ if (!useFullyQualifiedTestPageName) {
+ if (testURL.substring(0, this._baseURL.length) == this._baseURL)
+ testURL = testURL.substring(this._baseURL.length);
+ }
+ return testURL + ':' + this._testFunctionName;
+}
+
+jsUnitTestManager.prototype._addOption = function(listField, problemValue, problemMessage) {
+ if (typeof(listField.ownerDocument) != 'undefined'
+ && typeof(listField.ownerDocument.createElement) != 'undefined') {
+ // DOM Level 2 HTML method.
+ // this is required for Opera 7 since appending to the end of the
+ // options array does not work, and adding an Option created by new Option()
+ // and appended by listField.options.add() fails due to WRONG_DOCUMENT_ERR
+ var problemDocument = listField.ownerDocument;
+ var errOption = problemDocument.createElement('option');
+ errOption.setAttribute('value', problemValue);
+ errOption.appendChild(problemDocument.createTextNode(problemMessage));
+ listField.appendChild(errOption);
+ }
+ else {
+ // new Option() is DOM 0
+ errOption = new Option(problemMessage, problemValue);
+ if (typeof(listField.add) != 'undefined') {
+ // DOM 2 HTML
+ listField.add(errOption, null);
+ }
+ else if (typeof(listField.options.add) != 'undefined') {
+ // DOM 0
+ listField.options.add(errOption, null);
+ }
+ else {
+ // DOM 0
+ listField.options[listField.length] = errOption;
+ }
+ }
+}
+
+jsUnitTestManager.prototype._handleTestException = function (excep) {
+ var problemMessage = this._currentTestFunctionNameWithTestPageName(false) + ' ';
+ var errOption;
+ if (typeof(excep.isJsUnitException) == 'undefined' || !excep.isJsUnitException) {
+ problemMessage += 'had an error';
+ this.errorCount++;
+ }
+ else {
+ problemMessage += 'failed';
+ this.failureCount++;
+ }
+ var listField = this.problemsListField;
+ this._addOption(listField,
+ this._problemDetailMessageFor(excep),
+ problemMessage);
+}
+
+jsUnitTestManager.prototype._problemDetailMessageFor = function (excep) {
+ var result = null;
+ if (typeof(excep.isJsUnitException) != 'undefined' && excep.isJsUnitException) {
+ result = '';
+ if (excep.comment != null)
+ result += ('"' + excep.comment + '"\n');
+
+ result += excep.jsUnitMessage;
+
+ if (excep.stackTrace)
+ result += '\n\nStack trace follows:\n' + excep.stackTrace;
+ }
+ else {
+ result = 'Error message is:\n"';
+ result +=
+ (typeof(excep.description) == 'undefined') ?
+ excep :
+ excep.description;
+ result += '"';
+ if (typeof(excep.stack) != 'undefined') // Mozilla only
+ result += '\n\nStack trace follows:\n' + excep.stack;
+ }
+ return result;
+}
+
+jsUnitTestManager.prototype._setTextOnLayer = function (layerName, str) {
+ try {
+ var content;
+ if (content = this.uiFrames[layerName].document.getElementById('content'))
+ content.innerHTML = str;
+ else
+ throw 'No content div found.';
+ }
+ catch (e) {
+ var html = '';
+ html += '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
+ html += '<html><head><link rel="stylesheet" type="text/css" href="css/jsUnitStyle.css"><\/head>';
+ html += '<body><div id="content">';
+ html += str;
+ html += '<\/div><\/body>';
+ html += '<\/html>';
+ this.uiFrames[layerName].document.write(html);
+ this.uiFrames[layerName].document.close();
+ }
+}
+
+jsUnitTestManager.prototype.setStatus = function (str) {
+ this._setTextOnLayer('mainStatus', '<b>Status:<\/b> ' + str);
+}
+
+jsUnitTestManager.prototype._setErrors = function (n) {
+ this._setTextOnLayer('mainCountsErrors', '<b>Errors: <\/b>' + n);
+}
+
+jsUnitTestManager.prototype._setFailures = function (n) {
+ this._setTextOnLayer('mainCountsFailures', '<b>Failures:<\/b> ' + n);
+}
+
+jsUnitTestManager.prototype._setTotal = function (n) {
+ this._setTextOnLayer('mainCountsRuns', '<b>Runs:<\/b> ' + n);
+}
+
+jsUnitTestManager.prototype._setProgressBarImage = function (imgName) {
+ this.progressBar.src = imgName;
+}
+
+jsUnitTestManager.prototype._setProgressBarWidth = function (w) {
+ this.progressBar.width = w;
+}
+
+jsUnitTestManager.prototype.updateProgressIndicators = function () {
+ this._setTotal(this.totalCount);
+ this._setErrors(this.errorCount);
+ this._setFailures(this.failureCount);
+ this._setProgressBarWidth(300 * this.calculateProgressBarProportion());
+
+ if (this.errorCount > 0 || this.failureCount > 0)
+ this._setProgressBarImage('../images/red.gif');
+ else
+ this._setProgressBarImage('../images/green.gif');
+}
+
+jsUnitTestManager.prototype.showMessageForSelectedProblemTest = function () {
+ var problemTestIndex = this.problemsListField.selectedIndex;
+ if (problemTestIndex != -1)
+ this.fatalError(this.problemsListField[problemTestIndex].value);
+}
+
+jsUnitTestManager.prototype.showMessagesForAllProblemTests = function () {
+ if (this.problemsListField.length == 0)
+ return;
+
+ try {
+ if (this._windowForAllProblemMessages && !this._windowForAllProblemMessages.closed)
+ this._windowForAllProblemMessages.close();
+ }
+ catch(e) {
+ }
+
+ this._windowForAllProblemMessages = window.open('', '', 'width=600, height=350,status=no,resizable=yes,scrollbars=yes');
+ var resDoc = this._windowForAllProblemMessages.document;
+ resDoc.write('<html><head><link rel="stylesheet" href="../css/jsUnitStyle.css"><title>Tests with problems - JsUnit<\/title><head><body>');
+ resDoc.write('<p class="jsUnitSubHeading">Tests with problems (' + this.problemsListField.length + ' total) - JsUnit<\/p>');
+ resDoc.write('<p class="jsUnitSubSubHeading"><i>Running on ' + navigator.userAgent + '</i></p>');
+ for (var i = 0; i < this.problemsListField.length; i++)
+ {
+ resDoc.write('<p class="jsUnitDefault">');
+ resDoc.write('<b>' + (i + 1) + '. ');
+ resDoc.write(this.problemsListField[i].text);
+ resDoc.write('<\/b><\/p><p><pre>');
+ resDoc.write(this._makeHTMLSafe(this.problemsListField[i].value));
+ resDoc.write('<\/pre><\/p>');
+ }
+
+ resDoc.write('<\/body><\/html>');
+ resDoc.close();
+}
+
+jsUnitTestManager.prototype._makeHTMLSafe = function (string) {
+ string = string.replace(/&/g, '&amp;');
+ string = string.replace(/</g, '&lt;');
+ string = string.replace(/>/g, '&gt;');
+ return string;
+}
+
+jsUnitTestManager.prototype._clearProblemsList = function () {
+ var listField = this.problemsListField;
+ var initialLength = listField.options.length;
+
+ for (var i = 0; i < initialLength; i++)
+ listField.remove(0);
+}
+
+jsUnitTestManager.prototype.initialize = function () {
+ this.setStatus('Initializing...');
+ this._setRunButtonEnabled(false);
+ this._clearProblemsList();
+ this.updateProgressIndicators();
+ this.setStatus('Done initializing');
+}
+
+jsUnitTestManager.prototype.finalize = function () {
+ this._setRunButtonEnabled(true);
+}
+
+jsUnitTestManager.prototype._setRunButtonEnabled = function (b) {
+ this.runButton.disabled = !b;
+}
+
+jsUnitTestManager.prototype.getTestFileName = function () {
+ var rawEnteredFileName = this.testFileName.value;
+ var result = rawEnteredFileName;
+
+ while (result.indexOf('\\') != -1)
+ result = result.replace('\\', '/');
+
+ return result;
+}
+
+jsUnitTestManager.prototype.getTestFunctionName = function () {
+ return this._testFunctionName;
+}
+
+jsUnitTestManager.prototype.resolveUserEnteredTestFileName = function (rawText) {
+ var userEnteredTestFileName = top.testManager.getTestFileName();
+
+ // only test for file:// since Opera uses a different format
+ if (userEnteredTestFileName.indexOf('http://') == 0 || userEnteredTestFileName.indexOf('https://') == 0 || userEnteredTestFileName.indexOf('file://') == 0)
+ return userEnteredTestFileName;
+
+ return getTestFileProtocol() + this.getTestFileName();
+}
+
+jsUnitTestManager.prototype.storeRestoredHTML = function () {
+ if (document.getElementById && top.testContainer.testFrame.document.getElementById(jsUnitTestManager.RESTORED_HTML_DIV_ID))
+ this._restoredHTML = top.testContainer.testFrame.document.getElementById(jsUnitTestManager.RESTORED_HTML_DIV_ID).innerHTML;
+}
+
+jsUnitTestManager.prototype.fatalError = function(aMessage) {
+ if (top.shouldSubmitResults())
+ this.setStatus(aMessage);
+ else
+ alert(aMessage);
+}
+
+jsUnitTestManager.prototype.userConfirm = function(aMessage) {
+ if (top.shouldSubmitResults())
+ return false;
+ else
+ return confirm(aMessage);
+}
+
+function getTestFileProtocol() {
+ return getDocumentProtocol();
+}
+
+function getDocumentProtocol() {
+ var protocol = top.document.location.protocol;
+
+ if (protocol == "file:")
+ return "file:///";
+
+ if (protocol == "http:")
+ return "http://";
+
+ if (protocol == 'https:')
+ return 'https://';
+
+ if (protocol == "chrome:")
+ return "chrome://";
+
+ return null;
+}
+
+function browserSupportsReadingFullPathFromFileField() {
+ return !isOpera() && !isIE7();
+}
+
+function isOpera() {
+ return navigator.userAgent.toLowerCase().indexOf("opera") != -1;
+}
+
+function isIE7() {
+ return navigator.userAgent.toLowerCase().indexOf("msie 7") != -1;
+}
+
+function isBeingRunOverHTTP() {
+ return getDocumentProtocol() == "http://";
+}
+
+function getWebserver() {
+ if (isBeingRunOverHTTP()) {
+ var myUrl = location.href;
+ var myUrlWithProtocolStripped = myUrl.substring(myUrl.indexOf("/") + 2);
+ return myUrlWithProtocolStripped.substring(0, myUrlWithProtocolStripped.indexOf("/"));
+ }
+ return null;
+}
+
+// the functions push(anArray, anObject) and pop(anArray)
+// exist because the JavaScript Array.push(anObject) and Array.pop()
+// functions are not available in IE 5.0
+
+function push(anArray, anObject) {
+ anArray[anArray.length] = anObject;
+}
+
+function pop(anArray) {
+ if (anArray.length >= 1) {
+ delete anArray[anArray.length - 1];
+ anArray.length--;
+ }
+}
+
+if (xbDEBUG.on) {
+ xbDebugTraceObject('window', 'jsUnitTestManager');
+ xbDebugTraceFunction('window', 'getTestFileProtocol');
+ xbDebugTraceFunction('window', 'getDocumentProtocol');
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestSuite.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestSuite.js
new file mode 100644
index 0000000..3f3eb8c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestSuite.js
@@ -0,0 +1,44 @@
+function jsUnitTestSuite() {
+ this.isjsUnitTestSuite = true;
+ this.testPages = Array();
+ this.pageIndex = 0;
+}
+
+jsUnitTestSuite.prototype.addTestPage = function (pageName)
+{
+ this.testPages[this.testPages.length] = pageName;
+}
+
+jsUnitTestSuite.prototype.addTestSuite = function (suite)
+{
+ for (var i = 0; i < suite.testPages.length; i++)
+ this.addTestPage(suite.testPages[i]);
+}
+
+jsUnitTestSuite.prototype.containsTestPages = function ()
+{
+ return this.testPages.length > 0;
+}
+
+jsUnitTestSuite.prototype.nextPage = function ()
+{
+ return this.testPages[this.pageIndex++];
+}
+
+jsUnitTestSuite.prototype.hasMorePages = function ()
+{
+ return this.pageIndex < this.testPages.length;
+}
+
+jsUnitTestSuite.prototype.clone = function ()
+{
+ var clone = new jsUnitTestSuite();
+ clone.testPages = this.testPages;
+ return clone;
+}
+
+if (xbDEBUG.on)
+{
+ xbDebugTraceObject('window', 'jsUnitTestSuite');
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTracer.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTracer.js
new file mode 100644
index 0000000..b120e39
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTracer.js
@@ -0,0 +1,102 @@
+var TRACE_LEVEL_NONE = new JsUnitTraceLevel(0, null);
+var TRACE_LEVEL_WARNING = new JsUnitTraceLevel(1, "#FF0000");
+var TRACE_LEVEL_INFO = new JsUnitTraceLevel(2, "#009966");
+var TRACE_LEVEL_DEBUG = new JsUnitTraceLevel(3, "#0000FF");
+
+function JsUnitTracer(testManager) {
+ this._testManager = testManager;
+ this._traceWindow = null;
+ this.popupWindowsBlocked = false;
+}
+
+JsUnitTracer.prototype.initialize = function() {
+ if (this._traceWindow != null && top.testManager.closeTraceWindowOnNewRun.checked)
+ this._traceWindow.close();
+ this._traceWindow = null;
+}
+
+JsUnitTracer.prototype.finalize = function() {
+ if (this._traceWindow != null) {
+ this._traceWindow.document.write('<\/body>\n<\/html>');
+ this._traceWindow.document.close();
+ }
+}
+
+JsUnitTracer.prototype.warn = function() {
+ this._trace(arguments[0], arguments[1], TRACE_LEVEL_WARNING);
+}
+
+JsUnitTracer.prototype.inform = function() {
+ this._trace(arguments[0], arguments[1], TRACE_LEVEL_INFO);
+}
+
+JsUnitTracer.prototype.debug = function() {
+ this._trace(arguments[0], arguments[1], TRACE_LEVEL_DEBUG);
+}
+
+JsUnitTracer.prototype._trace = function(message, value, traceLevel) {
+ if (!top.shouldSubmitResults() && this._getChosenTraceLevel().matches(traceLevel)) {
+ var traceString = message;
+ if (value)
+ traceString += ': ' + value;
+ var prefix = this._testManager.getTestFileName() + ":" +
+ this._testManager.getTestFunctionName() + " - ";
+ this._writeToTraceWindow(prefix, traceString, traceLevel);
+ }
+}
+
+JsUnitTracer.prototype._getChosenTraceLevel = function() {
+ var levelNumber = eval(top.testManager.traceLevel.value);
+ return traceLevelByLevelNumber(levelNumber);
+}
+
+JsUnitTracer.prototype._writeToTraceWindow = function(prefix, traceString, traceLevel) {
+ var htmlToAppend = '<p class="jsUnitDefault">' + prefix + '<font color="' + traceLevel.getColor() + '">' + traceString + '</font><\/p>\n';
+ this._getTraceWindow().document.write(htmlToAppend);
+}
+
+JsUnitTracer.prototype._getTraceWindow = function() {
+ if (this._traceWindow == null && !top.shouldSubmitResults() && !this.popupWindowsBlocked) {
+ this._traceWindow = window.open('', '', 'width=600, height=350,status=no,resizable=yes,scrollbars=yes');
+ if (!this._traceWindow)
+ this.popupWindowsBlocked = true;
+ else {
+ var resDoc = this._traceWindow.document;
+ resDoc.write('<html>\n<head>\n<link rel="stylesheet" href="css/jsUnitStyle.css">\n<title>Tracing - JsUnit<\/title>\n<head>\n<body>');
+ resDoc.write('<h2>Tracing - JsUnit<\/h2>\n');
+ resDoc.write('<p class="jsUnitDefault"><i>(Traces are color coded: ');
+ resDoc.write('<font color="' + TRACE_LEVEL_WARNING.getColor() + '">Warning</font> - ');
+ resDoc.write('<font color="' + TRACE_LEVEL_INFO.getColor() + '">Information</font> - ');
+ resDoc.write('<font color="' + TRACE_LEVEL_DEBUG.getColor() + '">Debug</font>');
+ resDoc.write(')</i></p>');
+ }
+ }
+ return this._traceWindow;
+}
+
+if (xbDEBUG.on) {
+ xbDebugTraceObject('window', 'JsUnitTracer');
+}
+
+function JsUnitTraceLevel(levelNumber, color) {
+ this._levelNumber = levelNumber;
+ this._color = color;
+}
+
+JsUnitTraceLevel.prototype.matches = function(anotherTraceLevel) {
+ return this._levelNumber >= anotherTraceLevel._levelNumber;
+}
+
+JsUnitTraceLevel.prototype.getColor = function() {
+ return this._color;
+}
+
+function traceLevelByLevelNumber(levelNumber) {
+ switch (levelNumber) {
+ case 0: return TRACE_LEVEL_NONE;
+ case 1: return TRACE_LEVEL_WARNING;
+ case 2: return TRACE_LEVEL_INFO;
+ case 3: return TRACE_LEVEL_DEBUG;
+ }
+ return null;
+} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitVersionCheck.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitVersionCheck.js
new file mode 100644
index 0000000..41c8862
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitVersionCheck.js
@@ -0,0 +1,59 @@
+var versionRequest;
+
+function isOutOfDate(newVersionNumber) {
+ return JSUNIT_VERSION < newVersionNumber;
+}
+
+function sendRequestForLatestVersion(url) {
+ versionRequest = createXmlHttpRequest();
+ if (versionRequest) {
+ versionRequest.onreadystatechange = requestStateChanged;
+ versionRequest.open("GET", url, true);
+ versionRequest.send(null);
+ }
+}
+
+function createXmlHttpRequest() {
+ if (window.XMLHttpRequest)
+ return new XMLHttpRequest();
+ else if (window.ActiveXObject)
+ return new ActiveXObject("Microsoft.XMLHTTP");
+}
+
+function requestStateChanged() {
+ if (versionRequest && versionRequest.readyState == 4) {
+ if (versionRequest.status == 200) {
+ var latestVersion = versionRequest.responseText;
+ if (isOutOfDate(latestVersion))
+ versionNotLatest(latestVersion);
+ else
+ versionLatest();
+ } else
+ versionCheckError();
+ }
+}
+
+function checkForLatestVersion(url) {
+ setLatestVersionDivHTML("Checking for newer version...");
+ try {
+ sendRequestForLatestVersion(url);
+ } catch (e) {
+ setLatestVersionDivHTML("An error occurred while checking for a newer version: " + e.message);
+ }
+}
+
+function versionNotLatest(latestVersion) {
+ setLatestVersionDivHTML('<font color="red">A newer version of JsUnit, version ' + latestVersion + ', is available.</font>');
+}
+
+function versionLatest() {
+ setLatestVersionDivHTML("You are running the latest version of JsUnit.");
+}
+
+function setLatestVersionDivHTML(string) {
+ document.getElementById("versionCheckDiv").innerHTML = string;
+}
+
+function versionCheckError() {
+ setLatestVersionDivHTML("An error occurred while checking for a newer version.");
+} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-errors.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-errors.html
new file mode 100644
index 0000000..ca726b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-errors.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title></title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<div id="content"><b>Errors:</b> 0</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-failures.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-failures.html
new file mode 100644
index 0000000..861c78b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-failures.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title></title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<div id="content"><b>Failures:</b> 0</div>
+
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-runs.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-runs.html
new file mode 100644
index 0000000..5429f8f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-runs.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title></title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<div id="content"><b>Runs:</b> 0</div>
+
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts.html
new file mode 100644
index 0000000..0431eae
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title></title>
+</head>
+
+<frameset cols="200,190,*" border="0">
+ <frame name="mainCountsRuns" src="main-counts-runs.html" scrolling="no" frameborder="0">
+ <frame name="mainCountsErrors" src="main-counts-errors.html" scrolling="no" frameborder="0">
+ <frame name="mainCountsFailures" src="main-counts-failures.html" scrolling="no" frameborder="0">
+
+ <noframes>
+ <body>
+ <p>jsUnit uses frames in order to remove dependencies upon a browser's implementation of document.getElementById
+ and HTMLElement.innerHTML.</p>
+ </body>
+ </noframes>
+</frameset>
+</html>
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-data.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-data.html
new file mode 100644
index 0000000..8a15b97
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-data.html
@@ -0,0 +1,189 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit main-data.html</title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+ <script language="JavaScript" type="text/javascript" src="jsUnitCore.js"></script>
+ <script language="JavaScript" type="text/javascript" src="jsUnitVersionCheck.js"></script>
+ <script language="JavaScript" type="text/javascript">
+
+ function pageLoaded() {
+ giveFocusToTestFileNameField();
+ }
+
+ function giveFocusToTestFileNameField() {
+ if (document.testRunnerForm.testFileName.type != "hidden")
+ document.testRunnerForm.testFileName.focus();
+ }
+
+ function kickOffTests() {
+ //
+ // Check if Init was called by onload handler
+ //
+ if (typeof(top.testManager) == 'undefined') {
+ top.init();
+ }
+
+ if (isBlank(top.testManager.getTestFileName())) {
+ top.testManager.fatalError('No Test Page specified.');
+ return;
+ }
+
+ top.testManager.setup();
+
+ top.testManager._currentSuite().addTestPage(top.testManager.resolveUserEnteredTestFileName());
+ top.tracer.initialize();
+
+ var traceLevel = document.forms.testRunnerForm.traceLevel;
+ if (traceLevel.value != '0')
+ {
+ var traceWindow = top.tracer._getTraceWindow();
+ if (traceWindow) {
+ traceWindow.focus();
+ }
+ else {
+ top.testManager.fatalError('Tracing requires popup windows, and popups are blocked in your browser.\n\nPlease enable popups if you wish to use tracing.');
+ }
+ }
+
+ top.testManager.start();
+ }
+
+ </script>
+</head>
+
+<body onload="pageLoaded();">
+<table width="100%" cellpadding="0" cellspacing="0" border="0" summary="jsUnit Information" bgcolor="#DDDDDD">
+ <tr>
+ <td width="1"><a href="http://www.jsunit.net" target="_blank"><img src="../images/logo_jsunit.gif" alt="JsUnit" border="0"/></a></td>
+ <td width="50">&nbsp;</td>
+ <th nowrap align="left">
+ <h4>JsUnit <script language="javascript">document.write(JSUNIT_VERSION);</script> TestRunner</h4>
+ <font size="-2"><i>Running on <script language="javascript" type="text/javascript">document.write(navigator.userAgent);</script>
+ </i></font>
+ </th>
+
+ <td nowrap align="right" valign="middle">
+ <font size="-2">
+ <b><a href="http://www.jsunit.net/" target="_blank">www.jsunit.net</a></b>&nbsp;&nbsp;<br>
+ </font>
+ <a href="http://www.pivotalsf.com/" target="top">
+ <img border="0" src="../images/powerby-transparent.gif" alt="Powered By Pivotal">
+ </a>
+ </td>
+ </tr>
+</table>
+
+<form name="testRunnerForm" action="">
+ <script type="text/javascript" language="javascript">
+ if (!jsUnitGetParm('testpage')) {
+ document.write("<p>Enter the filename of the Test Page to be run:</p>");
+ } else {
+ document.write("<br>");
+ };
+ </script>
+
+ <table cellpadding="0" cellspacing="0" border="0" summary="Form for entering test case location">
+ <tr>
+ <td align="center" valign="middle">
+ <script language="JavaScript" type="text/javascript">
+ document.write(top.getDocumentProtocol());
+ </script>
+ </td>
+
+ <td nowrap align="center" valign="bottom">
+ &nbsp;
+ <script language="JavaScript" type="text/javascript">
+ var specifiedTestPage = jsUnitGetParm('testpage');
+ if (specifiedTestPage) {
+ var html = '<input type="hidden" name="testFileName" value="';
+ var valueString = '';
+ if ((top.getDocumentProtocol() == 'http://' || top.getDocumentProtocol() == 'https://') && jsUnitGetParm('testpage').indexOf('/') == 0)
+ valueString += top.location.host;
+ valueString += specifiedTestPage;
+ var testParms = top.jsUnitConstructTestParms();
+ if (testParms != '') {
+ valueString += '?';
+ valueString += testParms;
+ }
+ html += valueString;
+ html += '">';
+ html += valueString;
+ document.write(html);
+ } else {
+ if (top.getDocumentProtocol() == 'file:///' && top.browserSupportsReadingFullPathFromFileField())
+ document.write('<input type="file" name="testFileName" size="60">');
+ else
+ document.write('<input type="text" name="testFileName" size="60">');
+ }
+ </script>
+ <input type="button" name="runButton" value="Run" onclick="kickOffTests()">
+ <script type="text/javascript">
+ function jscoverageWindow() {
+ /*
+ the path may have to be adjusted: it should point to the
+ jscoverage.html file (relative to the jsunit/app
+ directory)
+ */
+ window.open("../../jscoverage.html");
+ }
+ </script>
+ <button onclick="jscoverageWindow();">Coverage report</button>
+ </td>
+ </tr>
+ </table>
+ <br>
+ <hr>
+
+ <table cellpadding="0" cellspacing="0" border="0" summary="Choose Trace Level">
+ <tr>
+ <td nowrap>Trace level:</td>
+
+ <td><select name="traceLevel">
+ <option value="0" selected>
+ no tracing
+ </option>
+
+ <option value="1">
+ warning (lowest)
+ </option>
+
+ <option value="2">
+ info
+ </option>
+
+ <option value="3">
+ debug (highest)
+ </option>
+ </select></td>
+
+ <td>&nbsp;&nbsp;&nbsp;</td>
+
+ <td><input type="checkbox" name="closeTraceWindowOnNewRun" checked></td>
+ <td nowrap>Close old trace window on new run</td>
+
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+
+ <td nowrap>Page load timeout:</td>
+ <td>&nbsp;
+ <script language="javascript" type="text/javascript">
+ document.write('<input type="text" size="2" name="timeout" value="' + top.jsUnitTestManager.TESTPAGE_WAIT_SEC + '">');
+ </script>
+ </td>
+
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+
+ <td nowrap>Setup page timeout:</td>
+ <td>&nbsp;
+ <script language="javascript" type="text/javascript">
+ document.write('<input type="text" size="2" name="setUpPageTimeout" value="' + top.jsUnitTestManager.SETUPPAGE_TIMEOUT + '">');
+ </script>
+ </td>
+ </tr>
+ </table>
+ <hr>
+</form>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-errors.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-errors.html
new file mode 100644
index 0000000..cc76ff0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-errors.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit main-errors.html</title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<hr>
+
+<form name="testRunnerForm" action="javascript:top.testManager.showMessageForSelectedProblemTest()">
+ <p>Errors and failures:&nbsp;</p>
+ <select size="5" ondblclick="top.testManager.showMessageForSelectedProblemTest()" name="problemsList">
+ <option>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</option>
+ </select>
+ <br>
+ <input type="button" value="Show selected" onclick="top.testManager.showMessageForSelectedProblemTest()">
+ &nbsp;&nbsp;&nbsp;
+ <input type="button" value="Show all" onclick="top.testManager.showMessagesForAllProblemTests()">
+</form>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-frame.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-frame.html
new file mode 100644
index 0000000..af0dc7a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-frame.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<html>
+<head>
+ <title>jsUnit Main Frame</title>
+</head>
+<frameset rows="230,30,30,30,0,*" border="0">>
+ <frame name="mainData" src="main-data.html" scrolling="no" frameborder="0">
+ <frame name="mainStatus" src="main-status.html" scrolling="no" frameborder="0">
+ <frame name="mainProgress" src="main-progress.html" scrolling="no" frameborder="0">
+ <frame name="mainCounts" src="main-counts.html" scrolling="no" frameborder="0">
+ <frame name="mainResults" src="main-results.html" scrolling="no" frameborder="0">
+ <frame name="mainErrors" src="main-errors.html" scrolling="no" frameborder="0">
+ <noframes>
+ <body>
+ <p>Sorry, JsUnit requires frames.</p>
+ </body>
+ </noframes>
+</frameset>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-loader.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-loader.html
new file mode 100644
index 0000000..302c084
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-loader.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>jsUnit External Data Document loader</title>
+ <script language="JavaScript" type="text/javascript">
+
+ var loadStatus;
+ var callback = function () {
+ };
+
+ function buffer() {
+ return window.frames.documentBuffer;
+ }
+
+ function load(uri) {
+ loadStatus = 'loading';
+ buffer().document.location.href = uri;
+ }
+
+ function loadComplete() {
+ top.xbDEBUG.dump('main-loader.html:loadComplete(): loadStatus = ' + loadStatus + ' href=' + buffer().document.location.href);
+ if (loadStatus == 'loading') {
+ loadStatus = 'complete';
+ callback();
+ callback = function () {
+ };
+ }
+ }
+
+ if (top.xbDEBUG.on) {
+ var scopeName = 'main_loader_' + (new Date()).getTime();
+ top[scopeName] = window;
+ top.xbDebugTraceFunction(scopeName, 'buffer');
+ top.xbDebugTraceFunction(scopeName, 'load');
+ top.xbDebugTraceFunction(scopeName, 'loadComplete');
+ }
+
+ </script>
+</head>
+
+<body>
+<iframe name="documentBuffer" onload="loadComplete()"></iframe>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-progress.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-progress.html
new file mode 100644
index 0000000..5ca52f6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-progress.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit main-progress.html</title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<table width="375" cellpadding="0" cellspacing="0" border="0" summary="Test progress indicator">
+ <tr>
+ <td width="65" valign="top"><b>Progress:</b></td>
+
+ <td width="300" height="14" valign="middle">
+ <table width="300" cellpadding="0" cellspacing="0" border="1" summary="Progress image">
+ <tr>
+ <td width="300" height="14" valign="top"><img name="progress" height="14" width="0"
+ alt="progress image" src="../images/green.gif"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-results.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-results.html
new file mode 100644
index 0000000..5a904cd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-results.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit main-results.html</title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<script language="javascript" type="text/javascript">
+ var DEFAULT_SUBMIT_WEBSERVER = "localhost:8080";
+
+ function submitUrlFromSpecifiedUrl() {
+ var result = "";
+ var specifiedUrl = top.getSpecifiedResultUrl();
+ if (specifiedUrl.indexOf("http://") != 0)
+ result = "http://";
+ result += specifiedUrl;
+ return result;
+ }
+
+ function submitUrlFromTestRunnerLocation() {
+ var result = "http://";
+ var webserver = top.getWebserver();
+ if (webserver == null) // running over file:///
+ webserver = DEFAULT_SUBMIT_WEBSERVER;
+ result += webserver;
+ result += "/jsunit/acceptor";
+ return result;
+ }
+
+ var submitUrl = "";
+ if (top.wasResultUrlSpecified()) {
+ submitUrl = submitUrlFromSpecifiedUrl();
+ } else {
+ submitUrl = submitUrlFromTestRunnerLocation();
+ }
+
+ var formString = "<form name=\"resultsForm\" action=\"" + submitUrl + "\" method=\"post\" target=\"_top\">";
+ document.write(formString);
+</script>
+<input type="hidden" name="id">
+<input type="hidden" name="userAgent">
+<input type="hidden" name="jsUnitVersion">
+<input type="hidden" name="time">
+<input type="hidden" name="url">
+<input type="hidden" name="cacheBuster">
+<select size="5" name="testCases" multiple></select>
+</form>
+<script language="javascript" type="text/javascript">
+ function populateHeaderFields(id, userAgent, jsUnitVersion, baseURL) {
+ document.resultsForm.id.value = id;
+ document.resultsForm.userAgent.value = userAgent;
+ document.resultsForm.jsUnitVersion.value = jsUnitVersion;
+ document.resultsForm.url.value = baseURL;
+ document.resultsForm.cacheBuster.value = new Date().getTime();
+ }
+ function submitResults() {
+ var testCasesField = document.resultsForm.testCases;
+ for (var i = 0; i < testCasesField.length; i++) {
+ testCasesField[i].selected = true;
+ }
+ document.resultsForm.submit();
+ }
+</script>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-status.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-status.html
new file mode 100644
index 0000000..1053f5d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-status.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit main-status.html</title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<div id="content"><b>Status:</b> (Idle)</div>
+
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainer.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainer.html
new file mode 100644
index 0000000..df6a997
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainer.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit Test Container</title>
+</head>
+<frameset rows="0, *" border="0">
+ <frame name="testContainerController" src="testContainerController.html">
+ <frame name="testFrame" src="emptyPage.html">
+ <noframes>
+ <body>
+ <p>Sorry, JsUnit requires frames.</p>
+ </body>
+ </noframes>
+</frameset>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainerController.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainerController.html
new file mode 100644
index 0000000..3130d76
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainerController.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit Test Container Controller</title>
+ <script language="javascript" type="text/javascript">
+ var containerReady = false;
+
+ function init() {
+ containerReady = true;
+ }
+
+ function isPageLoaded() {
+ if (!containerReady)
+ return false;
+
+ var isTestPageLoaded = false;
+
+ try {
+ // attempt to access the var isTestPageLoaded in the testFrame
+ if (typeof(top.testManager.containerTestFrame.isTestPageLoaded) != 'undefined') {
+ isTestPageLoaded = top.testManager.containerTestFrame.isTestPageLoaded;
+ }
+
+ // ok, if the above did not throw an exception, then the
+ // variable is defined. If the onload has not fired in the
+ // testFrame then isTestPageLoaded is still false. Otherwise
+ // the testFrame has set it to true
+ }
+ catch (e) {
+ // an error occured while attempting to access the isTestPageLoaded
+ // in the testFrame, therefore the testFrame has not loaded yet
+ isTestPageLoaded = false;
+ }
+ return isTestPageLoaded;
+ }
+
+ function isContainerReady() {
+ return containerReady;
+ }
+
+ function setNotReady() {
+ try {
+ // attempt to set the isTestPageLoaded variable
+ // in the test frame to false.
+ top.testManager.containerTestFrame.isTestPageLoaded = false;
+ }
+ catch (e) {
+ // testFrame.isTestPageLoaded not available... ignore
+ }
+ }
+ function setTestPage(testPageURI) {
+ setNotReady();
+ top.jsUnitParseParms(testPageURI);
+ testPageURI = appendCacheBusterParameterTo(testPageURI);
+ try {
+ top.testManager.containerTestFrame.location.href = testPageURI;
+ } catch (e) {
+ }
+ }
+
+ function appendCacheBusterParameterTo(testPageURI) {
+ if (testPageURI.indexOf("?") == -1)
+ testPageURI += "?";
+ else
+ testPageURI += "&";
+ testPageURI += "cacheBuster=";
+ testPageURI += new Date().getTime();
+ return testPageURI;
+ }
+ </script>
+</head>
+
+<body onload="init()">
+Test Container Controller
+</body>
+</html> \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/xbDebug.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/xbDebug.js
new file mode 100644
index 0000000..b7167ec
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/xbDebug.js
@@ -0,0 +1,306 @@
+// xbDebug.js revision: 0.003 2002-02-26
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Licensed under Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * Full Terms at /xbProjects-srce/license/mpl-tri-license.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Netscape code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Bob Clary <bclary@netscape.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ChangeLog:
+
+2002-02-25: bclary - modified xbDebugTraceOject to make sure
+ that original versions of wrapped functions were not
+ rewrapped. This had caused an infinite loop in IE.
+
+2002-02-07: bclary - modified xbDebug.prototype.close to not null
+ the debug window reference. This can cause problems with
+ Internet Explorer if the page is refreshed. These issues will
+ be addressed at a later date.
+*/
+
+function xbDebug()
+{
+ this.on = false;
+ this.stack = new Array();
+ this.debugwindow = null;
+ this.execprofile = new Object();
+}
+
+xbDebug.prototype.push = function ()
+{
+ this.stack[this.stack.length] = this.on;
+ this.on = true;
+}
+
+xbDebug.prototype.pop = function ()
+{
+ this.on = this.stack[this.stack.length - 1];
+ --this.stack.length;
+}
+
+xbDebug.prototype.open = function ()
+{
+ if (this.debugwindow && !this.debugwindow.closed)
+ this.close();
+
+ this.debugwindow = window.open('about:blank', 'DEBUGWINDOW', 'height=400,width=600,resizable=yes,scrollbars=yes');
+
+ this.debugwindow.title = 'xbDebug Window';
+ this.debugwindow.document.write('<html><head><title>xbDebug Window</title></head><body><h3>Javascript Debug Window</h3></body></html>');
+ this.debugwindow.focus();
+}
+
+xbDebug.prototype.close = function ()
+{
+ if (!this.debugwindow)
+ return;
+
+ if (!this.debugwindow.closed)
+ this.debugwindow.close();
+
+ // bc 2002-02-07, other windows may still hold a reference to this: this.debugwindow = null;
+}
+
+xbDebug.prototype.dump = function (msg)
+{
+ if (!this.on)
+ return;
+
+ if (!this.debugwindow || this.debugwindow.closed)
+ this.open();
+
+ this.debugwindow.document.write(msg + '<br>');
+
+ return;
+}
+
+var xbDEBUG = new xbDebug();
+
+window.onunload = function () {
+ xbDEBUG.close();
+}
+
+function xbDebugGetFunctionName(funcref)
+{
+
+ if (!funcref)
+ {
+ return '';
+ }
+
+ if (funcref.name)
+ return funcref.name;
+
+ var name = funcref + '';
+ name = name.substring(name.indexOf(' ') + 1, name.indexOf('('));
+ funcref.name = name;
+
+ if (!name) alert('name not defined');
+ return name;
+}
+
+// emulate functionref.apply for IE mac and IE win < 5.5
+function xbDebugApplyFunction(funcname, funcref, thisref, argumentsref)
+{
+ var rv;
+
+ if (!funcref)
+ {
+ alert('xbDebugApplyFunction: funcref is null');
+ }
+
+ if (typeof(funcref.apply) != 'undefined')
+ return funcref.apply(thisref, argumentsref);
+
+ var applyexpr = 'thisref.xbDebug_orig_' + funcname + '(';
+ var i;
+
+ for (i = 0; i < argumentsref.length; i++)
+ {
+ applyexpr += 'argumentsref[' + i + '],';
+ }
+
+ if (argumentsref.length > 0)
+ {
+ applyexpr = applyexpr.substring(0, applyexpr.length - 1);
+ }
+
+ applyexpr += ')';
+
+ return eval(applyexpr);
+}
+
+function xbDebugCreateFunctionWrapper(scopename, funcname, precall, postcall)
+{
+ var wrappedfunc;
+ var scopeobject = eval(scopename);
+ var funcref = scopeobject[funcname];
+
+ scopeobject['xbDebug_orig_' + funcname] = funcref;
+
+ wrappedfunc = function ()
+ {
+ var rv;
+
+ precall(scopename, funcname, arguments);
+ rv = xbDebugApplyFunction(funcname, funcref, scopeobject, arguments);
+ postcall(scopename, funcname, arguments, rv);
+ return rv;
+ };
+
+ if (typeof(funcref.constructor) != 'undefined')
+ wrappedfunc.constructor = funcref.constuctor;
+
+ if (typeof(funcref.prototype) != 'undefined')
+ wrappedfunc.prototype = funcref.prototype;
+
+ scopeobject[funcname] = wrappedfunc;
+}
+
+function xbDebugCreateMethodWrapper(contextname, classname, methodname, precall, postcall)
+{
+ var context = eval(contextname);
+ var methodref = context[classname].prototype[methodname];
+
+ context[classname].prototype['xbDebug_orig_' + methodname] = methodref;
+
+ var wrappedmethod = function ()
+ {
+ var rv;
+ // eval 'this' at method run time to pick up reference to the object's instance
+ var thisref = eval('this');
+ // eval 'arguments' at method run time to pick up method's arguments
+ var argsref = arguments;
+
+ precall(contextname + '.' + classname, methodname, argsref);
+ rv = xbDebugApplyFunction(methodname, methodref, thisref, argsref);
+ postcall(contextname + '.' + classname, methodname, argsref, rv);
+ return rv;
+ };
+
+ return wrappedmethod;
+}
+
+function xbDebugPersistToString(obj)
+{
+ var s = '';
+ var p;
+
+ if (obj == null)
+ return 'null';
+
+ switch (typeof(obj))
+ {
+ case 'number':
+ return obj;
+ case 'string':
+ return '"' + obj + '"';
+ case 'undefined':
+ return 'undefined';
+ case 'boolean':
+ return obj + '';
+ }
+
+ if (obj.constructor)
+ return '[' + xbDebugGetFunctionName(obj.constructor) + ']';
+
+ return null;
+}
+
+function xbDebugTraceBefore(scopename, funcname, funcarguments)
+{
+ var i;
+ var s = '';
+ var execprofile = xbDEBUG.execprofile[scopename + '.' + funcname];
+ if (!execprofile)
+ execprofile = xbDEBUG.execprofile[scopename + '.' + funcname] = { started: 0, time: 0, count: 0 };
+
+ for (i = 0; i < funcarguments.length; i++)
+ {
+ s += xbDebugPersistToString(funcarguments[i]);
+ if (i < funcarguments.length - 1)
+ s += ', ';
+ }
+
+ xbDEBUG.dump('enter ' + scopename + '.' + funcname + '(' + s + ')');
+ execprofile.started = (new Date()).getTime();
+}
+
+function xbDebugTraceAfter(scopename, funcname, funcarguments, rv)
+{
+ var i;
+ var s = '';
+ var execprofile = xbDEBUG.execprofile[scopename + '.' + funcname];
+ if (!execprofile)
+ xbDEBUG.dump('xbDebugTraceAfter: execprofile not created for ' + scopename + '.' + funcname);
+ else if (execprofile.started == 0)
+ xbDEBUG.dump('xbDebugTraceAfter: execprofile.started == 0 for ' + scopename + '.' + funcname);
+ else
+ {
+ execprofile.time += (new Date()).getTime() - execprofile.started;
+ execprofile.count++;
+ execprofile.started = 0;
+ }
+
+ for (i = 0; i < funcarguments.length; i++)
+ {
+ s += xbDebugPersistToString(funcarguments[i]);
+ if (i < funcarguments.length - 1)
+ s += ', ';
+ }
+
+ xbDEBUG.dump('exit ' + scopename + '.' + funcname + '(' + s + ')==' + xbDebugPersistToString(rv));
+}
+
+function xbDebugTraceFunction(scopename, funcname)
+{
+ xbDebugCreateFunctionWrapper(scopename, funcname, xbDebugTraceBefore, xbDebugTraceAfter);
+}
+
+function xbDebugTraceObject(contextname, classname)
+{
+ var classref = eval(contextname + '.' + classname);
+ var p;
+ var sp;
+
+ if (!classref || !classref.prototype)
+ return;
+
+ for (p in classref.prototype)
+ {
+ sp = p + '';
+ if (typeof(classref.prototype[sp]) == 'function' && (sp).indexOf('xbDebug_orig') == -1)
+ {
+ classref.prototype[sp] = xbDebugCreateMethodWrapper(contextname, classname, sp, xbDebugTraceBefore, xbDebugTraceAfter);
+ }
+ }
+}
+
+function xbDebugDumpProfile()
+{
+ var p;
+ var execprofile;
+ var avg;
+
+ for (p in xbDEBUG.execprofile)
+ {
+ execprofile = xbDEBUG.execprofile[p];
+ avg = Math.round(100 * execprofile.time / execprofile.count) / 100;
+ xbDEBUG.dump('Execution profile ' + p + ' called ' + execprofile.count + ' times. Total time=' + execprofile.time + 'ms. Avg Time=' + avg + 'ms.');
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/css/jsUnitStyle.css b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/css/jsUnitStyle.css
new file mode 100644
index 0000000..cee6849
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/css/jsUnitStyle.css
@@ -0,0 +1,83 @@
+body {
+ margin-top: 0;
+ margin-bottom: 0;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ color: #000;
+ font-size: 0.8em;
+ background-color: #fff;
+}
+
+a:link, a:visited {
+ color: #00F;
+}
+
+a:hover {
+ color: #F00;
+}
+
+h1 {
+ font-size: 1.2em;
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h2 {
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h3 {
+ font-weight: bold;
+ color: #039;
+ text-decoration: underline;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h4 {
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+.jsUnitTestResultSuccess {
+ color: #000;
+}
+
+.jsUnitTestResultNotSuccess {
+ color: #F00;
+}
+
+.unselectedTab {
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ height: 26px;
+ background: #FFFFFF;
+ border-style: solid;
+ border-bottom-width: 1px;
+ border-top-width: 1px;
+ border-left-width: 1px;
+ border-right-width: 1px;
+}
+
+.selectedTab {
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ height: 26px;
+ background: #DDDDDD;
+ font-weight: bold;
+ border-style: solid;
+ border-bottom-width: 0px;
+ border-top-width: 1px;
+ border-left-width: 1px;
+ border-right-width: 1px;
+}
+
+.tabHeaderSeparator {
+ height: 26px;
+ background: #FFFFFF;
+ border-style: solid;
+ border-bottom-width: 1px;
+ border-top-width: 0px;
+ border-left-width: 0px;
+ border-right-width: 0px;
+} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/green.gif b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/green.gif
new file mode 100644
index 0000000..b57ca34
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/green.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/logo_jsunit.gif b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/logo_jsunit.gif
new file mode 100644
index 0000000..65b4bda
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/logo_jsunit.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/powerby-transparent.gif b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/powerby-transparent.gif
new file mode 100644
index 0000000..69c7d9d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/powerby-transparent.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/red.gif b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/red.gif
new file mode 100644
index 0000000..262550d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/red.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/JDOM_license.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/JDOM_license.txt
new file mode 100644
index 0000000..86e1d54
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/JDOM_license.txt
@@ -0,0 +1,56 @@
+/*--
+
+ $Id: JDOM_license.txt 81 2003-07-24 04:44:54Z edwardhieatt $
+
+ Copyright (C) 2000-2003 Jason Hunter & Brett McLaughlin.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions, and the disclaimer that follows
+ these conditions in the documentation and/or other materials
+ provided with the distribution.
+
+ 3. The name "JDOM" must not be used to endorse or promote products
+ derived from this software without prior written permission. For
+ written permission, please contact <license AT jdom DOT org>.
+
+ 4. Products derived from this software may not be called "JDOM", nor
+ may "JDOM" appear in their name, without prior written permission
+ from the JDOM Project Management <pm AT jdom DOT org>.
+
+ In addition, we request (but do not require) that you include in the
+ end-user documentation provided with the redistribution and/or in the
+ software itself an acknowledgement equivalent to the following:
+ "This product includes software developed by the
+ JDOM Project (http://www.jdom.org/)."
+ Alternatively, the acknowledgment may be graphical using the logos
+ available at http://www.jdom.org/images/logos.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 JDOM AUTHORS OR THE PROJECT
+ 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.
+
+ This software consists of voluntary contributions made by many
+ individuals on behalf of the JDOM Project and was originally
+ created by Jason Hunter <jhunter AT jdom DOT org> and
+ Brett McLaughlin <brett AT jdom DOT org>. For more information on
+ the JDOM Project, please see <http://www.jdom.org/>.
+
+ */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/Jetty_license.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/Jetty_license.html
new file mode 100644
index 0000000..9e470e3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/Jetty_license.html
@@ -0,0 +1,213 @@
+<HTML>
+<HEAD>
+ <TITLE>Jetty License</TITLE>
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF">
+<FONT FACE=ARIAL,HELVETICA>
+<CENTER><FONT SIZE=+3><B>Jetty License</B></FONT></CENTER>
+<CENTER><FONT SIZE=-1><B>$Revision$</B></FONT></CENTER>
+
+<B>Preamble:</B>
+
+<p>
+
+ The intent of this document is to state the conditions under which the
+ Jetty Package may be copied, such that the Copyright Holder maintains some
+ semblance of control over the development of the package, while giving the
+ users of the package the right to use, distribute and make reasonable
+ modifications to the Package in accordance with the goals and ideals of
+ the Open Source concept as described at
+ <A HREF="http://www.opensource.org">http://www.opensource.org</A>.
+
+<P>
+ It is the intent of this license to allow commercial usage of the Jetty
+ package, so long as the source code is distributed or suitable visible
+ credit given or other arrangements made with the copyright holders.
+
+<P><B>Definitions:</B>
+
+<P>
+
+<UL>
+ <LI> "Jetty" refers to the collection of Java classes that are
+ distributed as a HTTP server with servlet capabilities and
+ associated utilities.
+
+ <p>
+
+ <LI> "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ <P>
+
+ <LI> "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder.
+
+ <P>
+
+ <LI> "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package. <BR>
+ Mort Bay Consulting Pty. Ltd. (Australia) is the "Copyright
+ Holder" for the Jetty package.
+
+ <P>
+
+ <LI> "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ <P>
+
+ <LI> "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ <P>
+
+ <LI> "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+ <P>
+</UL>
+
+0. The Jetty Package is Copyright (c) Mort Bay Consulting Pty. Ltd.
+(Australia) and others. Individual files in this package may contain
+additional copyright notices. The javax.servlet packages are copyright
+Sun Microsystems Inc. <P>
+
+ 1. The Standard Version of the Jetty package is
+ available from <A HREF=http://jetty.mortbay.org>http://jetty.mortbay.org</A>.
+
+<P>
+
+ 2. You may make and distribute verbatim copies of the source form
+ of the Standard Version of this Package without restriction, provided that
+ you include this license and all of the original copyright notices
+ and associated disclaimers.
+
+<P>
+
+ 3. You may make and distribute verbatim copies of the compiled form of the
+ Standard Version of this Package without restriction, provided that you
+ include this license.
+
+<P>
+
+ 4. You may apply bug fixes, portability fixes and other modifications
+ derived from the Public Domain or from the Copyright Holder. A Package
+ modified in such a way shall still be considered the Standard Version.
+
+<P>
+
+ 5. You may otherwise modify your copy of this Package in any way, provided
+ that you insert a prominent notice in each changed file stating how and
+ when you changed that file, and provided that you do at least ONE of the
+ following:
+
+<P>
+
+<BLOCKQUOTE>
+ a) Place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as ftp.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.<P>
+
+ b) Use the modified Package only within your corporation or organization.
+
+ <P>
+
+ c) Rename any non-standard classes so the names do not conflict
+ with standard classes, which must also be provided, and provide
+ a separate manual page for each non-standard class that clearly
+ documents how it differs from the Standard Version.
+
+ <P>
+
+ d) Make other arrangements with the Copyright Holder.
+
+ <P>
+</BLOCKQUOTE>
+
+6. You may distribute modifications or subsets of this Package in source
+code or compiled form, provided that you do at least ONE of the following:<P>
+
+<BLOCKQUOTE>
+ a) Distribute this license and all original copyright messages, together
+ with instructions (in the about dialog, manual page or equivalent) on where
+ to get the complete Standard Version.<P>
+
+ b) Accompany the distribution with the machine-readable source of
+ the Package with your modifications. The modified package must include
+ this license and all of the original copyright notices and associated
+ disclaimers, together with instructions on where to get the complete
+ Standard Version.
+
+ <P>
+
+ c) Make other arrangements with the Copyright Holder.
+
+ <P>
+</BLOCKQUOTE>
+
+7. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this Package.
+You may not charge a fee for this Package itself. However,
+you may distribute this Package in aggregate with other (possibly
+commercial) programs as part of a larger (possibly commercial) software
+distribution provided that you meet the other distribution requirements
+of this license.<P>
+
+ 8. Input to or the output produced from the programs of this Package
+ do not automatically fall under the copyright of this Package, but
+ belong to whomever generated them, and may be sold commercially, and
+ may be aggregated with this Package.
+
+<P>
+
+ 9. Any program subroutines supplied by you and linked into this Package
+ shall not be considered part of this Package.
+
+<P>
+
+ 10. The name of the Copyright Holder may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+<P>
+
+ 11. This license may change with each release of a Standard Version of
+ the Package. You may choose to use the license associated with version
+ you are using or the license of the latest Standard Version.
+
+<P>
+
+ 12. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+<P>
+
+ 13. If any superior law implies a warranty, the sole remedy under such shall
+ be , at the Copyright Holders option either a) return of any price paid or
+ b) use or reasonable endeavours to repair or replace the software.
+
+<P>
+
+ 14. This license shall be read under the laws of Australia.
+
+<P>
+
+<center>The End</center>
+
+<center><FONT size=-1>This license was derived from the <I>Artistic</I> license published
+ on <a href=http://www.opensource.org>http://www.opensource.com</a></font></center>
+</FONT>
+
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/MPL-1.1.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/MPL-1.1.txt
new file mode 100644
index 0000000..7a45bfe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/MPL-1.1.txt
@@ -0,0 +1,470 @@
+ MOZILLA PUBLIC LICENSE
+ Version 1.1
+
+ ---------------
+
+1. Definitions.
+
+ 1.0.1. "Commercial Use" means distribution or otherwise making the
+ Covered Code available to a third party.
+
+ 1.1. "Contributor" means each entity that creates or contributes to
+ the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the Original
+ Code, prior Modifications used by a Contributor, and the Modifications
+ made by that particular Contributor.
+
+ 1.3. "Covered Code" means the Original Code or Modifications or the
+ combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. "Electronic Distribution Mechanism" means a mechanism generally
+ accepted in the software development community for the electronic
+ transfer of data.
+
+ 1.5. "Executable" means Covered Code in any form other than Source
+ Code.
+
+ 1.6. "Initial Developer" means the individual or entity identified
+ as the Initial Developer in the Source Code notice required by Exhibit
+ A.
+
+ 1.7. "Larger Work" means a work which combines Covered Code or
+ portions thereof with code not governed by the terms of this License.
+
+ 1.8. "License" means this document.
+
+ 1.8.1. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. "Modifications" means any addition to or deletion from the
+ substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original Code or
+ previous Modifications.
+
+ 1.10. "Original Code" means Source Code of computer software code
+ which is described in the Source Code notice required by Exhibit A as
+ Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by grantor.
+
+ 1.11. "Source Code" means the preferred form of the Covered Code for
+ making modifications to it, including all modules it contains, plus
+ any associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or source code
+ differential comparisons against either the Original Code or another
+ well known, available Covered Code of the Contributor's choice. The
+ Source Code can be in a compressed or archival form, provided the
+ appropriate decompression or de-archiving software is widely available
+ for no charge.
+
+ 1.12. "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of, this
+ License or a future version of this License issued under Section 6.1.
+ For legal entities, "You" includes any entity which controls, is
+ controlled by, or is under common control with You. For purposes of
+ this definition, "control" means (a) the power, direct or indirect,
+ to cause the direction or management of such entity, whether by
+ contract or otherwise, or (b) ownership of more than fifty percent
+ (50%) of the outstanding shares or beneficial ownership of such
+ entity.
+
+2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer to use, reproduce,
+ modify, display, perform, sublicense and distribute the Original
+ Code (or portions thereof) with or without Modifications, and/or
+ as part of a Larger Work; and
+
+ (b) under Patents Claims infringed by the making, using or
+ selling of Original Code, to make, have made, use, practice,
+ sell, and offer for sale, and/or otherwise dispose of the
+ Original Code (or portions thereof).
+
+ (c) the licenses granted in this Section 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes
+ Original Code under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: 1) for code that You delete from the Original Code; 2)
+ separate from the Original Code; or 3) for infringements caused
+ by: i) the modification of the Original Code or ii) the
+ combination of the Original Code with other software or devices.
+
+ 2.2. Contributor Grant.
+ Subject to third party intellectual property claims, each Contributor
+ hereby grants You a world-wide, royalty-free, non-exclusive license
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor, to use, reproduce, modify,
+ display, perform, sublicense and distribute the Modifications
+ created by such Contributor (or portions thereof) either on an
+ unmodified basis, with other Modifications, as Covered Code
+ and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or
+ selling of Modifications made by that Contributor either alone
+ and/or in combination with its Contributor Version (or portions
+ of such combination), to make, use, sell, offer for sale, have
+ made, and/or otherwise dispose of: 1) Modifications made by that
+ Contributor (or portions thereof); and 2) the combination of
+ Modifications made by that Contributor with its Contributor
+ Version (or portions of such combination).
+
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first makes Commercial Use of
+ the Covered Code.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: 1) for any code that Contributor has deleted from the
+ Contributor Version; 2) separate from the Contributor Version;
+ 3) for infringements caused by: i) third party modifications of
+ Contributor Version or ii) the combination of Modifications made
+ by that Contributor with other software (except as part of the
+ Contributor Version) or other devices; or 4) under Patent Claims
+ infringed by Covered Code in the absence of Modifications made by
+ that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Application of License.
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be
+ distributed only under the terms of this License or a future version
+ of this License released under Section 6.1, and You must include a
+ copy of this License with every copy of the Source Code You
+ distribute. You may not offer or impose any terms on any Source Code
+ version that alters or restricts the applicable version of this
+ License or the recipients' rights hereunder. However, You may include
+ an additional document offering the additional rights described in
+ Section 3.5.
+
+ 3.2. Availability of Source Code.
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License
+ either on the same media as an Executable version or via an accepted
+ Electronic Distribution Mechanism to anyone to whom you made an
+ Executable version available; and if made available via Electronic
+ Distribution Mechanism, must remain available for at least twelve (12)
+ months after the date it initially became available, or at least six
+ (6) months after a subsequent version of that particular Modification
+ has been made available to such recipients. You are responsible for
+ ensuring that the Source Code version remains available even if the
+ Electronic Distribution Mechanism is maintained by a third party.
+
+ 3.3. Description of Modifications.
+ You must cause all Covered Code to which You contribute to contain a
+ file documenting the changes You made to create that Covered Code and
+ the date of any change. You must include a prominent statement that
+ the Modification is derived, directly or indirectly, from Original
+ Code provided by the Initial Developer and including the name of the
+ Initial Developer in (a) the Source Code, and (b) in any notice in an
+ Executable version or related documentation in which You describe the
+ origin or ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+ (a) Third Party Claims.
+ If Contributor has knowledge that a license under a third party's
+ intellectual property rights is required to exercise the rights
+ granted by such Contributor under Sections 2.1 or 2.2,
+ Contributor must include a text file with the Source Code
+ distribution titled "LEGAL" which describes the claim and the
+ party making the claim in sufficient detail that a recipient will
+ know whom to contact. If Contributor obtains such knowledge after
+ the Modification is made available as described in Section 3.2,
+ Contributor shall promptly modify the LEGAL file in all copies
+ Contributor makes available thereafter and shall take other steps
+ (such as notifying appropriate mailing lists or newsgroups)
+ reasonably calculated to inform those who received the Covered
+ Code that new knowledge has been obtained.
+
+ (b) Contributor APIs.
+ If Contributor's Modifications include an application programming
+ interface and Contributor has knowledge of patent licenses which
+ are reasonably necessary to implement that API, Contributor must
+ also include this information in the LEGAL file.
+
+ (c) Representations.
+ Contributor represents that, except as disclosed pursuant to
+ Section 3.4(a) above, Contributor believes that Contributor's
+ Modifications are Contributor's original creation(s) and/or
+ Contributor has sufficient rights to grant the rights conveyed by
+ this License.
+
+ 3.5. Required Notices.
+ You must duplicate the notice in Exhibit A in each file of the Source
+ Code. If it is not possible to put such notice in a particular Source
+ Code file due to its structure, then You must include such notice in a
+ location (such as a relevant directory) where a user would be likely
+ to look for such a notice. If You created one or more Modification(s)
+ You may add your name as a Contributor to the notice described in
+ Exhibit A. You must also duplicate this License in any documentation
+ for the Source Code where You describe recipients' rights or ownership
+ rights relating to Covered Code. You may choose to offer, and to
+ charge a fee for, warranty, support, indemnity or liability
+ obligations to one or more recipients of Covered Code. However, You
+ may do so only on Your own behalf, and not on behalf of the Initial
+ Developer or any Contributor. You must make it absolutely clear than
+ any such warranty, support, indemnity or liability obligation is
+ offered by You alone, and You hereby agree to indemnify the Initial
+ Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of warranty,
+ support, indemnity or liability terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered Code,
+ and if You include a notice stating that the Source Code version of
+ the Covered Code is available under the terms of this License,
+ including a description of how and where You have fulfilled the
+ obligations of Section 3.2. The notice must be conspicuously included
+ in any notice in an Executable version, related documentation or
+ collateral in which You describe recipients' rights relating to the
+ Covered Code. You may distribute the Executable version of Covered
+ Code or ownership rights under a license of Your choice, which may
+ contain terms different from this License, provided that You are in
+ compliance with the terms of this License and that the license for the
+ Executable version does not attempt to limit or alter the recipient's
+ rights in the Source Code version from the rights set forth in this
+ License. If You distribute the Executable version under a different
+ license You must make it absolutely clear that any terms which differ
+ from this License are offered by You alone, not by the Initial
+ Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by
+ the Initial Developer or such Contributor as a result of any such
+ terms You offer.
+
+ 3.7. Larger Works.
+ You may create a Larger Work by combining Covered Code with other code
+ not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to
+ statute, judicial order, or regulation then You must: (a) comply with
+ the terms of this License to the maximum extent possible; and (b)
+ describe the limitations and the code they affect. Such description
+ must be included in the LEGAL file described in Section 3.4 and must
+ be included with all distributions of the Source Code. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Application of this License.
+
+ This License applies to code to which the Initial Developer has
+ attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+ 6.1. New Versions.
+ Netscape Communications Corporation ("Netscape") may publish revised
+ and/or new versions of the License from time to time. Each version
+ will be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+ Once Covered Code has been published under a particular version of the
+ License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms
+ of any subsequent version of the License published by Netscape. No one
+ other than Netscape has the right to modify the terms applicable to
+ Covered Code created under this License.
+
+ 6.3. Derivative Works.
+ If You create or use a modified version of this License (which you may
+ only do in order to apply it to code which is not already Covered Code
+ governed by this License), You must (a) rename Your license so that
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+ "MPL", "NPL" or any confusingly similar phrase do not appear in your
+ license (except to note that your license differs from this License)
+ and (b) otherwise make it clear that Your version of the license
+ contains terms which differ from the Mozilla Public License and
+ Netscape Public License. (Filling in the name of the Initial
+ Developer, Original Code or Contributor in the notice described in
+ Exhibit A shall not of themselves be deemed to be modifications of
+ this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+ 8.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall
+ survive any termination of this License. Provisions which, by their
+ nature, must remain in effect beyond the termination of this License
+ shall survive.
+
+ 8.2. If You initiate litigation by asserting a patent infringement
+ claim (excluding declatory judgment actions) against Initial Developer
+ or a Contributor (the Initial Developer or Contributor against whom
+ You file such action is referred to as "Participant") alleging that:
+
+ (a) such Participant's Contributor Version directly or indirectly
+ infringes any patent, then any and all rights granted by such
+ Participant to You under Sections 2.1 and/or 2.2 of this License
+ shall, upon 60 days notice from Participant terminate prospectively,
+ unless if within 60 days after receipt of notice You either: (i)
+ agree in writing to pay Participant a mutually agreeable reasonable
+ royalty for Your past and future use of Modifications made by such
+ Participant, or (ii) withdraw Your litigation claim with respect to
+ the Contributor Version against such Participant. If within 60 days
+ of notice, a reasonable royalty and payment arrangement are not
+ mutually agreed upon in writing by the parties or the litigation claim
+ is not withdrawn, the rights granted by Participant to You under
+ Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+ the 60 day notice period specified above.
+
+ (b) any software, hardware, or device, other than such Participant's
+ Contributor Version, directly or indirectly infringes any patent, then
+ any rights granted to You by such Participant under Sections 2.1(b)
+ and 2.2(b) are revoked effective as of the date You first made, used,
+ sold, distributed, or had made, Modifications made by that
+ Participant.
+
+ 8.3. If You assert a patent infringement claim against Participant
+ alleging that such Participant's Contributor Version directly or
+ indirectly infringes any patent where such claim is resolved (such as
+ by license or settlement) prior to the initiation of patent
+ infringement litigation, then the reasonable value of the licenses
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken
+ into account in determining the amount or value of any payment or
+ license.
+
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above,
+ all end user license agreements (excluding distributors and resellers)
+ which have been validly granted by You or any distributor hereunder
+ prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+ THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a "commercial item," as that term is defined in
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+ software" and "commercial computer software documentation," as such
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+ all U.S. Government End Users acquire Covered Code with only those
+ rights set forth herein.
+
+11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed by
+ California law provisions (except to the extent applicable law, if
+ any, provides otherwise), excluding its conflict-of-law provisions.
+ With respect to disputes in which at least one party is a citizen of,
+ or an entity chartered or registered to do business in the United
+ States of America, any litigation relating to this License shall be
+ subject to the jurisdiction of the Federal Courts of the Northern
+ District of California, with venue lying in Santa Clara County,
+ California, with the losing party responsible for costs, including
+ without limitation, court costs and reasonable attorneys' fees and
+ expenses. The application of the United Nations Convention on
+ Contracts for the International Sale of Goods is expressly excluded.
+ Any law or regulation which provides that the language of a contract
+ shall be construed against the drafter shall not apply to this
+ License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or indirectly,
+ out of its utilization of rights under this License and You agree to
+ work with Initial Developer and Contributors to distribute such
+ responsibility on an equitable basis. Nothing herein is intended or
+ shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+ Initial Developer may designate portions of the Covered Code as
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial
+ Developer permits you to utilize portions of the Covered Code under
+ Your choice of the NPL or the alternative licenses, if any, specified
+ by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+ ``The contents of this file are subject to the Mozilla Public License
+ Version 1.1 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ License for the specific language governing rights and limitations
+ under the License.
+
+ The Original Code is ______________________________________.
+
+ The Initial Developer of the Original Code is ________________________.
+ Portions created by ______________________ are Copyright (C) ______
+ _______________________. All Rights Reserved.
+
+ Contributor(s): ______________________________________.
+
+ Alternatively, the contents of this file may be used under the terms
+ of the _____ license (the "[___] License"), in which case the
+ provisions of [______] License are applicable instead of those
+ above. If you wish to allow use of your version of this file only
+ under the terms of the [____] License and not to allow others to use
+ your version of this file under the MPL, indicate your decision by
+ deleting the provisions above and replace them with the notice and
+ other provisions required by the [___] License. If you do not delete
+ the provisions above, a recipient may use your version of this file
+ under either the MPL or the [___] License."
+
+ [NOTE: The text of this Exhibit A may differ slightly from the text of
+ the notices in the Source Code files of the Original Code. You should
+ use the text of this Exhibit A rather than the text found in the
+ Original Code Source Code for Your Modifications.]
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/gpl-2.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/gpl-2.txt
new file mode 100644
index 0000000..45645b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/gpl-2.txt
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/index.html
new file mode 100644
index 0000000..7df3cfb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/index.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<!-- JsUnit -->
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Edward Hieatt code.
+ -
+ - The Initial Developer of the Original Code is
+ - Edward Hieatt, edward@jsunit.net.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Edward Hieatt, edward@jsunit.net (original author)
+ - Bob Clary, bc@bclary.comn
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Licensing</title>
+ <link rel="stylesheet" type="text/css" href="../app/css/jsUnitStyle.css">
+</head>
+
+<body>
+<table width="100%" cellpadding="0" cellspacing="0" border="1" summary="jsUnit Information">
+ <tr>
+ <th align="center" valign="top"><h1>JsUnit Licenses</h1></th>
+
+ <td align="right" valign="top">
+ <a href="http://www.jsunit.net/" target="_blank">JsUnit Home</a><br>
+ <a href="mailto:edward@jsunit.net">edward@jsunit.net</a><br>
+ </tr>
+</table>
+
+<p><h2>Third-party licenses:</h2>
+ <ul>
+ <li>JDOM: Portions of this software are copyright Copyright (C) 2000-2003 Jason Hunter & Brett McLaughlin. All
+ rights reserved. See <a href="JDOM_license.txt">JDOM_license.txt</a>.
+ <li>Jetty: Portions of this software are copyright � Mort Bay Consulting Pty. Ltd. (Australia) and others. All
+ Rights Reserved. See <a href="Jetty_license.html">Jetty_license.html</a>.
+ <li>Individual files in this package may contain additional copyright notices. The javax.servlet packages are
+ copyright Sun Microsystems Inc. All Rights Reserved.
+ </ul>
+</p>
+
+<p><h2>JsUnit licenses:</h2>
+ JsUnit is licensed under 3 different licenses giving you the freedom
+ to use, modify and distribute JsUnit in a variety of fashions.
+</p>
+
+<ol>
+ <li>
+ <p><a href="MPL-1.1.txt">Mozilla Public License 1.1</a></p>
+
+ <p>See <a href="http://www.mozilla.org/MPL/">mozilla.org</a>
+ for more details.</p>
+ </li>
+
+ <li>
+ <p><a href="gpl-2.txt">GNU Public License 2</a></p>
+
+ <p>See <a href="http://www.gnu.org/licenses/licenses.html">www.gnu.org</a>
+ for more details.</p>
+ </li>
+
+ <li>
+ <p><a href="lgpl-2.1.txt">GNU Lesser Public License 2.1</a></p>
+
+ <p>See <a href="http://www.gnu.org/licenses/licenses.html">www.gnu.org</a>
+ for more details.</p>
+ </li>
+</ol>
+
+<p>
+ Every Java and JavaScript source file in this distribution should be considered to be under the following licensing
+ terms.
+ <pre>
+ ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Edward Hieatt code.
+ -
+ - The Initial Developer of the Original Code is
+ - Edward Hieatt, edward@jsunit.net.
+ - Portions created by the Initial Developer are Copyright (C) 2003
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Author Edward Hieatt, edward@jsunit.net
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK *****
+ </pre>
+</p>
+</body>
+</html>
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/lgpl-2.1.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/lgpl-2.1.txt
new file mode 100644
index 0000000..cbee875
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/lgpl-2.1.txt
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-c.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-c.txt
new file mode 100644
index 0000000..bd3ad22
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-c.txt
@@ -0,0 +1,35 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is __________________________________________.
+ *
+ * The Initial Developer of the Original Code is
+ * ____________________________________________.
+ * Portions created by the Initial Developer are Copyright (C) 2___
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-html.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-html.txt
new file mode 100644
index 0000000..33f0980
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-html.txt
@@ -0,0 +1,35 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is __________________________________________.
+ -
+ - The Initial Developer of the Original Code is
+ - ____________________________________________.
+ - Portions created by the Initial Developer are Copyright (C) 2___
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/readme.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/readme.txt
new file mode 100644
index 0000000..d260774
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/readme.txt
@@ -0,0 +1,19 @@
+JsUnit
+Copyright (C) 2001-6 Edward Hieatt, edward@jsunit.net
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Please see http://www.jsunit.net/ for JsUnit documentation and
+the "licenses" directory for license information. \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/testRunner.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/testRunner.html
new file mode 100644
index 0000000..71a0c1a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/testRunner.html
@@ -0,0 +1,167 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>JsUnit Test Runner</title>
+<script language="JavaScript" type="text/javascript" src="app/xbDebug.js"></script>
+<script language="JavaScript" type="text/javascript" src="app/jsUnitCore.js"></script>
+<script language="JavaScript" type="text/javascript">
+ var DEFAULT_TEST_FRAME_HEIGHT = 250;
+
+ function jsUnitParseParms(string) {
+ var i;
+ var searchString = unescape(string);
+ var parameterHash = new Object();
+
+ if (!searchString) {
+ return parameterHash;
+ }
+
+ i = searchString.indexOf('?');
+ if (i != -1) {
+ searchString = searchString.substring(i + 1);
+ }
+
+ var parmList = searchString.split('&');
+ var a;
+ for (i = 0; i < parmList.length; i++) {
+ a = parmList[i].split('=');
+ a[0] = a[0].toLowerCase();
+ if (a.length > 1) {
+ parameterHash[a[0]] = a[1];
+ }
+ else {
+ parameterHash[a[0]] = true;
+ }
+ }
+ return parameterHash;
+ }
+
+ function jsUnitConstructTestParms() {
+ var p;
+ var parms = '';
+
+ for (p in jsUnitParmHash) {
+ var value = jsUnitParmHash[p];
+
+ if (!value ||
+ p == 'testpage' ||
+ p == 'autorun' ||
+ p == 'submitresults' ||
+ p == 'showtestframe' ||
+ p == 'resultid') {
+ continue;
+ }
+
+ if (parms) {
+ parms += '&';
+ }
+
+ parms += p;
+
+ if (typeof(value) != 'boolean') {
+ parms += '=' + value;
+ }
+ }
+ return escape(parms);
+ }
+
+ var jsUnitParmHash = jsUnitParseParms(document.location.search);
+
+ // set to true to turn debugging code on, false to turn it off.
+ xbDEBUG.on = jsUnitGetParm('debug') ? true : false;
+</script>
+
+<script language="JavaScript" type="text/javascript" src="app/jsUnitTestManager.js"></script>
+<script language="JavaScript" type="text/javascript" src="app/jsUnitTracer.js"></script>
+<script language="JavaScript" type="text/javascript" src="app/jsUnitTestSuite.js"></script>
+<script language="JavaScript" type="text/javascript">
+
+ var testManager;
+ var utility;
+ var tracer;
+
+
+ if (!Array.prototype.push) {
+ Array.prototype.push = function (anObject) {
+ this[this.length] = anObject;
+ }
+ }
+
+ if (!Array.prototype.pop) {
+ Array.prototype.pop = function () {
+ if (this.length > 0) {
+ delete this[this.length - 1];
+ this.length--;
+ }
+ }
+ }
+
+ function shouldKickOffTestsAutomatically() {
+ return jsUnitGetParm('autorun') == "true";
+ }
+
+ function shouldShowTestFrame() {
+ return jsUnitGetParm('showtestframe');
+ }
+
+ function shouldSubmitResults() {
+ return jsUnitGetParm('submitresults');
+ }
+
+ function getResultId() {
+ if (jsUnitGetParm('resultid'))
+ return jsUnitGetParm('resultid');
+ return "";
+ }
+
+ function submitResults() {
+ window.mainFrame.mainData.document.testRunnerForm.runButton.disabled = true;
+ window.mainFrame.mainResults.populateHeaderFields(getResultId(), navigator.userAgent, JSUNIT_VERSION, testManager.resolveUserEnteredTestFileName());
+ window.mainFrame.mainResults.submitResults();
+ }
+
+ function wasResultUrlSpecified() {
+ return shouldSubmitResults() && jsUnitGetParm('submitresults') != 'true';
+ }
+
+ function getSpecifiedResultUrl() {
+ return jsUnitGetParm('submitresults');
+ }
+
+ function init() {
+ var testRunnerFrameset = document.getElementById('testRunnerFrameset');
+ if (shouldShowTestFrame() && testRunnerFrameset) {
+ var testFrameHeight;
+ if (jsUnitGetParm('showtestframe') == 'true')
+ testFrameHeight = DEFAULT_TEST_FRAME_HEIGHT;
+ else
+ testFrameHeight = jsUnitGetParm('showtestframe');
+ testRunnerFrameset.rows = '*,0,' + testFrameHeight;
+ }
+ testManager = new jsUnitTestManager();
+ tracer = new JsUnitTracer(testManager);
+ if (shouldKickOffTestsAutomatically()) {
+ window.mainFrame.mainData.kickOffTests();
+ }
+ }
+
+
+</script>
+</head>
+
+<frameset id="testRunnerFrameset" rows="*,0,0" border="0" onload="init()">
+
+ <frame frameborder="0" name="mainFrame" src="./app/main-frame.html">
+ <frame frameborder="0" name="documentLoader" src="./app/main-loader.html">
+ <frame frameborder="0" name="testContainer" src="./app/testContainer.html">
+
+ <noframes>
+ <body>
+ <p>Sorry, JsUnit requires support for frames.</p>
+ </body>
+ </noframes>
+</frameset>
+
+</html> \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/script.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/script.js
new file mode 100644
index 0000000..8120054
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/script.js
@@ -0,0 +1,7 @@
+function f() {
+ return true;
+}
+
+function g() {
+ return true;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/test.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/test.html
new file mode 100644
index 0000000..0d4d9bc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/test.html
@@ -0,0 +1,25 @@
+<html>
+<head>
+<title>Test</title>
+
+<script type="text/javascript" src="jsunit/app/jsUnitCore.js"></script>
+<script type="text/javascript" src="script.js"></script>
+<script type="text/javascript">
+function test_f() {
+ assert(f());
+}
+
+/*
+This code automatically stores coverage reports when running under
+jscoverage-server.
+*/
+function tearDownPage() {
+ if (window.jscoverage_report) {
+ jscoverage_report();
+ }
+}
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/example/index.html
new file mode 100644
index 0000000..e7230b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Example</title>
+<script type="text/javascript" src="script.js"></script>
+<style>
+div.black {
+ color: black;
+}
+div.red {
+ color: red;
+ font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="request" class="red">Please select your favorite number:</div>
+<input type="radio" name="number" id="radio1" onclick="go(this);"><label for="radio1">One</label><br>
+<input type="radio" name="number" id="radio2" onclick="go(this);"><label for="radio2">Two</label><br>
+<input type="radio" name="number" id="radio3" onclick="go(this);"><label for="radio3">Three</label><br>
+<input type="radio" name="number" id="radio4" onclick="go(this);"><label for="radio4">Four</label><br>
+<div id="result" class="red"></div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example/script.js b/tools/node_modules/expresso/deps/jscoverage/doc/example/script.js
new file mode 100644
index 0000000..0589c76
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example/script.js
@@ -0,0 +1,20 @@
+function go(element) {
+ var message;
+ if (element.id === 'radio1') {
+ message = 'You selected the number 1.';
+ }
+ else if (element.id === 'radio2') {
+ message = 'You selected the number 2.';
+ }
+ else if (element.id === 'radio3') {
+ message = 'You selected the number 3.';
+ }
+ else if (element.id === 'radio4') {
+ message = 'You selected the number 4.';
+ }
+ var div = document.getElementById('request');
+ div.className = 'black';
+ div = document.getElementById('result');
+ div.innerHTML = '<p>' + message + '</p>';
+ div.innerHTML += '<p>If you are running the instrumented version of this program, you can click the "Summary" tab to view a coverage report.</p>';
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/faq.html b/tools/node_modules/expresso/deps/jscoverage/doc/faq.html
new file mode 100644
index 0000000..7b783a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/faq.html
@@ -0,0 +1,164 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - FAQ</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <h2><abbr title="Frequently Asked Questions">FAQ</abbr></h2>
+
+ <h3>Can I use JSCoverage to measure code coverage for a page on <code>http://example.com/</code>?</h3>
+
+ <p>
+ In order to measure the code coverage of a page on <code>http://example.com/</code>,
+ you must run <code>jscoverage</code> to create a <code>jscoverage.html</code> file on the
+ <code>example.com</code> server. You cannot use <code>http://example.org/jscoverage.html</code>
+ to measure the code coverage of a page located on <code>http://example.com/</code>.
+ </p>
+
+ <p>
+ The fundamental reason for this limitation is the
+ <a href="http://www.mozilla.org/projects/security/components/same-origin.html">Same Origin Policy</a>
+ for untrusted JavaScript.
+ </p>
+
+ <p>
+ (In fact, the current version of JSCoverage is slightly more restrictive
+ than this: it requires that the JavaScript being measured reside under the
+ same <strong>directory</strong> as the <code>jscoverage.html</code> file.)
+ </p>
+
+ <h3>Why doesn't my test suite run under JSCoverage in Firefox 3?</h3>
+
+ <p>
+ Firefox 3 introduces <a
+ href="http://tech.groups.yahoo.com/group/jsunit/message/1075">new
+ security restrictions</a> on local files. Depending on the way your
+ test suite is organized, this may cause problems for JSCoverage.
+ (You may get the error "uncaught exception: Permission denied to get property Window._$jscoverage".)
+ There are several workarounds:
+ </p>
+
+ <ul class="list">
+ <li><p>Place your files on a web server instead of loading them from the file system.
+ This is usually the simplest solution.</p>
+ <li><p>Organize your HTML files in your test suite in a flat directory structure. For example, suppose that
+ you instrument your test suite with this command:</p>
+<pre>
+jscoverage src instrumented
+</pre>
+ <p>If all your HTML files are located directly under the <code>src/</code> directory (i.e., not in a
+ subdirectory of <code>src/</code>), then you should not have any problems using Firefox 3.</p>
+ <li><p>Set the <a href="http://kb.mozillazine.org/Editing_configuration">Firefox preference</a> named
+ <code><a href="http://kb.mozillazine.org/Security.fileuri.origin_policy">security.fileuri.origin_policy</a></code>
+ to 3.</p>
+ </ul>
+
+ <h3>I'm trying to load my code with the URL
+ <code>file:///C:/foo/bar/jscoverage.html?foo/bar.html</code>
+ and I'm getting all kinds of JavaScript errors.</h3>
+
+ <p>
+ Internet Explorer 6 seems to have problems with a <code>file:</code> URL
+ that has a query string with a slash in it.
+ </p>
+ <p>
+ As a workaround:
+ </p>
+ <ul class="list">
+ <li><p>Place your files on a web server instead of loading them from the file system.
+ (<code>http:</code> URLs work fine.)</p>
+ <li><p>Do not use a query string; enter your URL in the "URL" field in the "Browser" tab.</p>
+ <li><p>Rearrange your directory structure so that <code>bar.html</code>
+ ends up in the same directory as <code>jscoverage.html</code>; then
+ you can use the URL
+ <code>file:///C:/foo/bar/jscoverage.html?bar.html</code>
+ with no slash in the query string.</p>
+ <li><p>Use a different browser. (IE 7 seems to work.)</p>
+ </ul>
+
+ <h3>JSCoverage changes my cursor to a busy cursor, and it never changes back!</h3>
+
+ <p>
+ Certain browsers (<i>e. g</i>., Internet Explorer 6, Opera, Safari) have trouble changing
+ the cursor. Try moving the mouse and your cursor should change back to normal.
+ </p>
+
+ <p>
+ See <a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/631908bd63241136/783c307480f95d8c">this discussion</a> for more information.
+ </p>
+
+ <h3>JSCoverage hangs sometimes when rendering the coverage report.</h3>
+
+ <p>
+ With Internet Explorer 6 (I think I see a pattern here), garbage collection can cause performance problems.
+ (More information <a href="http://ajaxian.com/archives/garbage-collection-in-ie6">here</a>.)
+ </p>
+
+ <h3 id="jsunit">Can JSCoverage be used with <a href="http://www.jsunit.net/">JsUnit</a>?</h3>
+
+ <p>
+ It is necessary to run JSCoverage in <dfn>inverted mode</dfn>. You will have to
+ modify JsUnit to launch JSCoverage.
+ </p>
+
+ <p>
+ See the directory <code>doc/example-jsunit</code> for an example. It
+ contains a copy of JsUnit version 2.2alpha11, with the file
+ <code>jsunit/app/main-data.html</code> slightly modified to add a button
+ which launches JSCoverage. It also contains a simple unit test file <code>test.html</code>. You
+ can instrument this example as follows:
+ </p>
+
+<pre>
+jscoverage --no-instrument=jsunit doc/example-jsunit doc/instrumented-jsunit
+</pre>
+
+ <p>
+ You can then run the <code>test.html</code> file in JsUnit's <code>jsunit/testRunner.html</code>.
+ The simplest way to do this is probably to copy the contents of <code>doc/instrumented-jsunit</code>
+ to the root of a web server and then access the URL
+ </p>
+
+<pre>
+http://127.0.0.1/jsunit/testRunner.html?testPage=http://127.0.0.1/test.html&amp;autoRun=true
+</pre>
+
+ <p>
+ After the test suite has been run, click on the "Coverage report" button
+ to get a coverage report.
+ </p>
+
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li>FAQ
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/feed-icon-14x14.png b/tools/node_modules/expresso/deps/jscoverage/doc/feed-icon-14x14.png
new file mode 100644
index 0000000..b3c949d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/feed-icon-14x14.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/help.html b/tools/node_modules/expresso/deps/jscoverage/doc/help.html
new file mode 100644
index 0000000..00463e0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/help.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - help</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <h2>Help</h2>
+ <p>
+ Questions, problems, suggestions, bug reports, and so on can be posted at the
+ online <a href="http://siliconforks.com/forum/viewforum.php?f=1">forum</a>.
+ </p>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li>Help
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/index.html
new file mode 100644
index 0000000..7deca7e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/index.html
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - code coverage for JavaScript</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><span class="h1">JSCoverage</span><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <p>
+ JSCoverage is a tool that measures code coverage for
+ JavaScript programs.
+ </p>
+ <p>
+ <dfn>Code coverage</dfn> statistics show which lines of a program have
+ been executed (and which have been missed). This information is useful
+ for constructing comprehensive test suites (hence, it is often called
+ <dfn>test coverage</dfn>).
+ </p>
+ <p>
+ JSCoverage works by instrumenting the JavaScript code used in web
+ pages. Code coverage statistics are collected while the instrumented
+ JavaScript code is executed in a web browser.
+ </p>
+ <p>
+ JSCoverage supports the complete language syntax described in the
+ <cite>ECMAScript Language Specification</cite> (ECMA-262, 3rd edition).
+ JSCoverage works with any modern standards-compliant web browser -
+ including Internet Explorer (IE 6 and IE 7), Firefox (FF 2 and FF 3),
+ Opera, Safari, and Google Chrome - on Microsoft Windows and GNU/Linux.
+ </p>
+ <p>
+ JSCoverage is free software, distributed under the
+ <a href="license.html">GNU General Public License version 2</a>.
+ </p>
+
+ <h2>Latest News <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a></h2>
+
+ <h3><a name="20081211">December 11, 2008 - JSCoverage 0.4</a></h3>
+ <p>
+ JSCoverage 0.4 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ This release includes many new features:
+ </p>
+ <ul class="list">
+ <li>
+ The new <code>jscoverage-server</code> program is provided as an
+ alternative to the <code>jscoverage</code> program. The
+ <code>jscoverage-server</code> program is a simple HTTP server which
+ instruments JavaScript code as it is served; this allows you to execute
+ JavaScript and gather code coverage statistics without a preliminary
+ step of creating instrumented code. The <code>jscoverage-server</code>
+ program can either serve files directly from the filesystem or run as a
+ proxy server (with the <code>--proxy</code> option), instrumenting
+ JavaScript provided by another web server.
+ <li>
+ Using <code>jscoverage-server</code>, coverage reports can now be stored
+ to the filesystem.
+ </li>
+ <li>
+ JSCoverage now recognizes special JavaScript comments which specify that
+ certain lines of code should be ignored in coverage reports.
+ </li>
+ <li>
+ The new <code>--encoding</code> option provides better support for
+ different character encodings.
+ </li>
+ <li>
+ The JSCoverage user interface is now faster and more responsive.
+ </li>
+ <li>
+ The new <code>--no-highlight</code> option can be used to disable syntax
+ highlighting (giving better performance for large JavaScript files).
+ </li>
+ <li>
+ The build system has been modified so that <code>make install</code>
+ only installs the <code>jscoverage</code> and
+ <code>jscoverage-server</code> executables and their manual pages.
+ (Previous versions installed SpiderMonkey library and executable files,
+ which could conflict with other versions of SpiderMonkey installed on
+ your system.)
+ </li>
+ <li>
+ JSCoverage now supports several features beyond those found in the
+ <cite>ECMAScript Language Specification</cite>, including the following:
+ <ul class="list">
+ <li>getters and setters
+ <li><code>for each</code> loops
+ <li>generators and iterators
+ <li>the <code>let</code> keyword
+ <li>destructuring assignment
+ <li>array comprehensions
+ <li>expression closures
+ <li>generator expressions
+ </ul>
+ Use the new <code>--js-version</code> option to enable these features.
+ </li>
+ </ul>
+ <p>
+ The GCC C++ compiler (<code>g++</code>) is now required to compile
+ JSCoverage. (Previously, only the C compiler was needed.)
+ </p>
+ <p>
+ Please report any bugs you find using the new <a href="http://siliconforks.com/jscoverage/bugs/">bug tracker</a>.
+ </p>
+
+ <h3><a name="20080331">March 31, 2008 - JSCoverage and Firefox 3</a></h3>
+ <p>
+ The <a href="faq.html">JSCoverage FAQ</a> has been updated to address problems using JSCoverage with Firefox 3.
+ </p>
+
+ <h3><a name="20080324">March 24, 2008 - JSCoverage in Debian GNU/Linux</a></h3>
+ <p>
+ JSCoverage is now <a href="http://packages.debian.org/sid/jscoverage">available</a> in the Debian unstable distribution.
+ </p>
+
+ <p>
+ <a href="news.html">All news items...</a>
+ </p>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li>Home
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/index.html
new file mode 100644
index 0000000..be0f8ea
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/index.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Example</title>
+<script type="text/javascript" src="script.js"></script>
+<style>
+div.black {
+ color: black;
+}
+div.red {
+ color: red;
+ font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="request" class="red">Please select your favorite number:</div>
+<input type="radio" name="number" id="radio1" onclick="go(this);"><label for="radio1">One</label><br>
+<input type="radio" name="number" id="radio2" onclick="go(this);"><label for="radio2">Two</label><br>
+<input type="radio" name="number" id="radio3" onclick="go(this);"><label for="radio3">Three</label><br>
+<input type="radio" name="number" id="radio4" onclick="go(this);"><label for="radio4">Four</label><br>
+<div id="result" class="red"></div>
+<button onclick='window.open("jscoverage.html");'>Coverage report</button>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-highlight.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-highlight.css
new file mode 100644
index 0000000..31a4695
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-highlight.css
@@ -0,0 +1,38 @@
+/*
+ jscoverage-highlight.css - JSCoverage syntax highlighting style sheet
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/* keyword, type, symbol, cbracket */
+#sourceTable .k {
+ font-weight: bold;
+}
+
+/* string, regexp, number */
+#sourceTable .s {
+ color: #006400;
+}
+
+/* specialchar */
+#sourceTable .t {
+ color: #2e8b57;
+}
+
+/* comment */
+#sourceTable .c {
+ font-style: italic;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-ie.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-ie.css
new file mode 100644
index 0000000..afb2b80
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-ie.css
@@ -0,0 +1,89 @@
+#headingDiv {
+ position: static;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding-top: 0.5em;
+}
+
+#tabs {
+ clear: all;
+ position: static;
+ top: auto;
+ left: auto;
+ right: auto;
+ height: auto;
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+#tabs div {
+ position: relative;
+ height: auto;
+ line-height: normal;
+ padding-top: 5px;
+ padding-bottom: 5px;
+}
+
+#tabs div.selected {
+ padding-bottom: 6px;
+ z-index: 2;
+}
+
+.TabPage {
+ position: relative;
+ top: -1px;
+ left: auto;
+ right: auto;
+ bottom: auto;
+ clear: left;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 10px;
+ z-index: 1;
+}
+
+#locationDiv {
+ margin-bottom: 10px;
+}
+
+#iframeDiv {
+ position: static;
+ width: 100%;
+}
+
+#summaryDiv {
+ position: static;
+ width: 100%;
+}
+
+#fileDiv {
+ margin-bottom: 10px;
+}
+
+#sourceDiv {
+ position: static;
+ width: 100%;
+}
+
+#storeDiv {
+ position: static;
+ width: 100%;
+}
+
+/* some defaults */
+
+.TabPage {
+ height: 650px;
+}
+
+#iframeDiv {
+ height: 600px;
+}
+
+#summaryDiv {
+ height: 600px;
+}
+
+#sourceDiv {
+ height: 600px;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-throbber.gif b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-throbber.gif
new file mode 100644
index 0000000..f13c0b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-throbber.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.css
new file mode 100644
index 0000000..98af69b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.css
@@ -0,0 +1,328 @@
+/*
+ jscoverage.css - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+body {
+ background-color: #bfffbf;
+ font-family: sans-serif;
+ font-size: 100%;
+ margin: 0;
+}
+
+#mainDiv {
+ font-size: 0.8125em;
+}
+
+#headingDiv {
+ position: absolute;
+ top: 0.5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 0;
+ line-height: 1.5em;
+}
+
+h1 {
+ float: left;
+ margin: 0;
+ padding-bottom: 0.5em;
+ font-size: 1.3em;
+}
+
+.ProgressBar {
+ float: left;
+ visibility: hidden;
+}
+
+.ProgressPercentage {
+ display: block;
+ float: left;
+ width: 5em;
+ text-align: right;
+}
+
+.ProgressGraph {
+ float: left;
+ width: 100px;
+ height: 10px;
+ border: 1px solid black;
+ margin-top: 0.3em;
+ background-color: #d4d0c8;
+ overflow: hidden;
+}
+
+.ProgressCovered {
+ /* windows system color ActiveCaption or Highlight */
+ background-color: #0a246a;
+ width: 0;
+ height: 10px;
+ overflow: hidden;
+}
+
+#progressLabel {
+ display: block;
+ float: left;
+ padding-left: 0.3em;
+}
+
+/*******************************************************************************
+browser tab
+*/
+
+input#location, button {
+ border: 1px solid black;
+ margin-left: 1px;
+ margin-right: 1px;
+}
+
+#iframeDiv {
+ position: absolute;
+ top: 3.5em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+}
+
+iframe {
+ width: 100%;
+ height: 100%;
+}
+
+/*******************************************************************************
+summary tab
+*/
+
+#summaryDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#summaryTable {
+ width: 100%;
+ margin-left: 0px;
+ margin-right: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+table#summaryTable th, table#summaryTable td {
+ border-left: 1px solid #d9d9d9;
+}
+
+table#summaryTable th.leftColumn, table#summaryTable td.leftColumn {
+ border-left-width: 0px;
+}
+
+table#summaryTable th, table#summaryTable td {
+ padding: 2px;
+}
+
+th {
+ background-color: #e6ffe6;
+}
+
+td.numeric {
+ text-align: right;
+}
+
+abbr {
+ cursor: help;
+}
+
+tr#summaryTotals td.leftColumn span {
+ float: right;
+}
+tr#summaryTotals td.leftColumn span.title {
+ float: left;
+ font-weight: bold;
+}
+tr#summaryTotals td {
+ background-color: #ffd;
+}
+td.coverage {
+ width: 150px;
+}
+td.coverage span {
+ float: right;
+ margin-right: 5px;
+}
+.pctGraph {
+ width: 100px;
+ height: 10px;
+ float: right;
+ border: 1px solid #000;
+ background-color: #e00000;
+ overflow: hidden;
+ margin-top: 4px;
+}
+.pctGraph .covered {
+ background-color: #00f000;
+ width: 0;
+ height: 10px;
+}
+.pctGraph .skipped {
+ background-color: #d4d0c8;
+ width: 100px;
+ height: 10px;
+}
+tbody#summaryTbody tr.even td {
+ background-color: #e6ffe6;
+}
+
+/*******************************************************************************
+source tab
+*/
+
+#fileDiv {
+ font-size: large;
+ font-weight: bold;
+}
+
+#sourceDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#sourceTable {
+ border: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+/*
+IE default behavior is to make <pre> smaller than surrounding text. Because
+the table already has font-size small, this would make the font-size within the
+<pre> x-small. So we don't rely on the default.
+*/
+table#sourceTable pre {
+ font-size: medium;
+}
+
+table#sourceTable td {
+ border: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+table#sourceTable pre {
+ border: 0px;
+ margin: 0px;
+}
+
+.g {
+ background-color: #bfffbf;
+}
+
+.y {
+ background-color: #ffffbf;
+}
+
+.r {
+ background-color: #ffbfbf;
+}
+
+/*******************************************************************************
+store tab
+*/
+
+#storeDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+/*******************************************************************************
+about tab
+*/
+
+p {
+ margin-top: 0;
+}
+
+/*******************************************************************************
+tabs
+*/
+
+#tabs {
+ position: absolute;
+ top: 3em;
+ left: 1.5em;
+ right: 1.5em;
+ height: 2em;
+}
+
+#tabs div {
+ background-color: white;
+ position: relative;
+ float: left;
+ border: 1px solid black;
+ border-bottom-width: 0;
+ cursor: pointer;
+ margin-left: 0.5em;
+ margin-right: 0.5em;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ height: 2em;
+ z-index: 1;
+ line-height: 1.8em;
+}
+
+#tabs div.selected {
+ z-index: 3;
+ cursor: default;
+}
+
+#tabs div.disabled {
+ /* windows system color GrayText */
+ color: #808080;
+ cursor: default;
+}
+
+.TabPage {
+ background-color: white;
+ border: 1px solid black;
+ position: absolute;
+ top: 5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 1.5em;
+ z-index: 2;
+ padding: 1em;
+ display: none;
+}
+
+#tabPages div.selected {
+ display: block;
+}
+
+img {
+ visibility: hidden;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.html b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.html
new file mode 100644
index 0000000..601f62a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<!--
+ jscoverage.html - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
+
+<html>
+<head>
+<title>JSCoverage</title>
+<link rel="stylesheet" type="text/css" href="jscoverage-highlight.css">
+<link rel="stylesheet" type="text/css" href="jscoverage.css">
+<!--[if IE]>
+<link rel="stylesheet" type="text/css" href="jscoverage-ie.css">
+<![endif]-->
+<script type="text/javascript" src="jscoverage.js"></script>
+</head>
+
+<body onload="jscoverage_body_load();" onresize="jscoverage_body_resize();">
+<div id="mainDiv">
+<div id="headingDiv">
+<h1>JSCoverage</h1>
+<div class="ProgressBar" id="progressBar"><span class="ProgressPercentage"></span><div class="ProgressGraph"><div class="ProgressCovered"></div></div></div>
+<span id="progressLabel"></span>
+</div>
+
+<div id="tabs" class="Tabs">
+ <div id="browserTab"><img src="jscoverage-throbber.gif" alt=""> Browser <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="summaryTab"><img id="summaryThrobber" src="jscoverage-throbber.gif" alt=""> Summary <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="sourceTab" class="disabled"><img src="jscoverage-throbber.gif" alt=""> Source <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="storeTab"><img id="storeThrobber" src="jscoverage-throbber.gif" alt=""> Store <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="aboutTab"><img src="jscoverage-throbber.gif" alt=""> About <img src="jscoverage-throbber.gif" alt=""></div>
+</div>
+<div id="tabPages" class="TabPages">
+ <div class="TabPage" id="browserTabPage">
+ <div id="locationDiv">
+ URL: <input id="location" type="text" size="70" onkeypress="jscoverage_input_keypress(event)">
+ <button onclick="jscoverage_button_click();">Go</button>
+ </div>
+ <div id="iframeDiv">
+ <iframe id="browserIframe" onload="jscoverage_browser_load();"></iframe>
+ </div>
+ </div>
+ <div class="TabPage">
+ <input type="checkbox" id="checkbox" onclick="return jscoverage_checkbox_click();"> <label for="checkbox">Show missing statements column</label>
+ <div id="summaryDiv">
+ <div id="summaryErrorDiv"></div>
+ <table id="summaryTable">
+ <thead>
+ <tr id="headerRow">
+ <th class="leftColumn">File</th>
+ <th><abbr title="The total number of executable statements">Statements</abbr></th>
+ <th><abbr title="The number of statements actually executed">Executed</abbr></th>
+ <th><abbr title="Number of executed statements as a percentage of total number of statements">Coverage</abbr></th>
+ </tr>
+ <tr id="summaryTotals">
+ <td class="leftColumn">
+ <span class="title">Total:</span>
+ <span>0</span>
+ </td>
+ <td class="numeric">0</td>
+ <td class="numeric">0</td>
+ <td class="coverage">
+ <div class="pctGraph">
+ <div class="covered"></div>
+ </div>
+ <span class="pct">0%</span>
+ </td>
+ </tr>
+
+ </thead>
+ <tbody id="summaryTbody">
+
+ <!--
+ <tr>
+ <td>0</td>
+ <td>0</td>
+ <td>0</td>
+ <td>0%</td>
+ <td>0</td>
+ </tr>
+ -->
+
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="TabPage">
+ <div id="fileDiv"></div>
+ <div id="sourceDiv"></div>
+ </div>
+ <div class="TabPage" id="storeTabPage">
+ <button id="storeButton" onclick="jscoverage_storeButton_click();">Store Report</button>
+ <img id="storeImg" src="jscoverage-throbber.gif" alt="loading...">
+ <div id="storeDiv"></div>
+ </div>
+ <div class="TabPage">
+ <p>
+ This is version 0.4 of JSCoverage, a program that calculates code
+ coverage statistics for JavaScript.
+ </p>
+ <p>
+ See <a href="http://siliconforks.com/jscoverage/">http://siliconforks.com/jscoverage/</a> for more information.
+ </p>
+ <p>
+ Copyright &copy; 2007, 2008 siliconforks.com
+ </p>
+ </div>
+</div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.js b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.js
new file mode 100644
index 0000000..9e2ea5b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.js
@@ -0,0 +1,1024 @@
+/*
+ jscoverage.js - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/**
+Initializes the _$jscoverage object in a window. This should be the first
+function called in the page.
+@param w this should always be the global window object
+*/
+function jscoverage_init(w) {
+ try {
+ // in Safari, "import" is a syntax error
+ Components.utils['import']('resource://gre/modules/jscoverage.jsm');
+ jscoverage_isInvertedMode = true;
+ return;
+ }
+ catch (e) {}
+
+ if (w.opener && w.opener.top._$jscoverage) {
+ // we are in inverted mode
+ jscoverage_isInvertedMode = true;
+ if (! w._$jscoverage) {
+ w._$jscoverage = w.opener.top._$jscoverage;
+ }
+ }
+ else {
+ // we are not in inverted mode
+ jscoverage_isInvertedMode = false;
+ if (! w._$jscoverage) {
+ w._$jscoverage = {};
+ }
+ }
+}
+
+var jscoverage_currentFile = null;
+var jscoverage_currentLine = null;
+
+var jscoverage_inLengthyOperation = false;
+
+/*
+Possible states:
+ isInvertedMode isServer isReport tabs
+normal false false false Browser
+inverted true false false
+server, normal false true false Browser, Store
+server, inverted true true false Store
+report false false true
+*/
+var jscoverage_isInvertedMode = false;
+var jscoverage_isServer = false;
+var jscoverage_isReport = false;
+
+jscoverage_init(window);
+
+function jscoverage_createRequest() {
+ // Note that the IE7 XMLHttpRequest does not support file URL's.
+ // http://xhab.blogspot.com/2006/11/ie7-support-for-xmlhttprequest.html
+ // http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx
+//#JSCOVERAGE_IF
+ if (window.ActiveXObject) {
+ return new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ else {
+ return new XMLHttpRequest();
+ }
+}
+
+// http://www.quirksmode.org/js/findpos.html
+function jscoverage_findPos(obj) {
+ var result = 0;
+ do {
+ result += obj.offsetTop;
+ obj = obj.offsetParent;
+ }
+ while (obj);
+ return result;
+}
+
+// http://www.quirksmode.org/viewport/compatibility.html
+function jscoverage_getViewportHeight() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ if (self.innerHeight) {
+ // all except Explorer
+ return self.innerHeight;
+ }
+ else if (document.documentElement && document.documentElement.clientHeight) {
+ // Explorer 6 Strict Mode
+ return document.documentElement.clientHeight;
+ }
+ else if (document.body) {
+ // other Explorers
+ return document.body.clientHeight;
+ }
+ else {
+ throw "Couldn't calculate viewport height";
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Indicates visually that a lengthy operation has begun. The progress bar is
+displayed, and the cursor is changed to busy (on browsers which support this).
+*/
+function jscoverage_beginLengthyOperation() {
+ jscoverage_inLengthyOperation = true;
+
+ var progressBar = document.getElementById('progressBar');
+ progressBar.style.visibility = 'visible';
+ ProgressBar.setPercentage(progressBar, 0);
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'visible';
+
+ /* blacklist buggy browsers */
+//#JSCOVERAGE_IF
+ if (! /Opera|WebKit/.test(navigator.userAgent)) {
+ /*
+ Change the cursor style of each element. Note that changing the class of the
+ element (to one with a busy cursor) is buggy in IE.
+ */
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = 'wait';
+ }
+ }
+}
+
+/**
+Removes the progress bar and busy cursor.
+*/
+function jscoverage_endLengthyOperation() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 100);
+ setTimeout(function() {
+ jscoverage_inLengthyOperation = false;
+ progressBar.style.visibility = 'hidden';
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'hidden';
+ progressLabel.innerHTML = '';
+
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = '';
+ }
+ }, 50);
+}
+
+function jscoverage_setSize() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ var viewportHeight = jscoverage_getViewportHeight();
+
+ /*
+ border-top-width: 1px
+ padding-top: 10px
+ padding-bottom: 10px
+ border-bottom-width: 1px
+ margin-bottom: 10px
+ ----
+ 32px
+ */
+ var tabPages = document.getElementById('tabPages');
+ var tabPageHeight = (viewportHeight - jscoverage_findPos(tabPages) - 32) + 'px';
+ var nodeList = tabPages.childNodes;
+ var length = nodeList.length;
+ for (var i = 0; i < length; i++) {
+ var node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+ node.style.height = tabPageHeight;
+ }
+
+ var iframeDiv = document.getElementById('iframeDiv');
+ // may not exist if we have removed the first tab
+ if (iframeDiv) {
+ iframeDiv.style.height = (viewportHeight - jscoverage_findPos(iframeDiv) - 21) + 'px';
+ }
+
+ var summaryDiv = document.getElementById('summaryDiv');
+ summaryDiv.style.height = (viewportHeight - jscoverage_findPos(summaryDiv) - 21) + 'px';
+
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.style.height = (viewportHeight - jscoverage_findPos(sourceDiv) - 21) + 'px';
+
+ var storeDiv = document.getElementById('storeDiv');
+ if (storeDiv) {
+ storeDiv.style.height = (viewportHeight - jscoverage_findPos(storeDiv) - 21) + 'px';
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Returns the boolean value of a string. Values 'false', 'f', 'no', 'n', 'off',
+and '0' (upper or lower case) are false.
+@param s the string
+@return a boolean value
+*/
+function jscoverage_getBooleanValue(s) {
+ s = s.toLowerCase();
+ if (s === 'false' || s === 'f' || s === 'no' || s === 'n' || s === 'off' || s === '0') {
+ return false;
+ }
+ return true;
+}
+
+function jscoverage_removeTab(id) {
+ var tab = document.getElementById(id + 'Tab');
+ tab.parentNode.removeChild(tab);
+ var tabPage = document.getElementById(id + 'TabPage');
+ tabPage.parentNode.removeChild(tabPage);
+}
+
+/**
+Initializes the contents of the tabs. This sets the initial values of the
+input field and iframe in the "Browser" tab and the checkbox in the "Summary"
+tab.
+@param queryString this should always be location.search
+*/
+function jscoverage_initTabContents(queryString) {
+ var showMissingColumn = false;
+ var parameters, parameter, i, index, url, name, value;
+ if (queryString.length > 0) {
+ // chop off the question mark
+ queryString = queryString.substring(1);
+ parameters = queryString.split(/&|;/);
+ for (i = 0; i < parameters.length; i++) {
+ parameter = parameters[i];
+ index = parameter.indexOf('=');
+ if (index === -1) {
+ // still works with old syntax
+ url = parameter;
+ }
+ else {
+ name = parameter.substr(0, index);
+ value = parameter.substr(index + 1);
+ if (name === 'missing' || name === 'm') {
+ showMissingColumn = jscoverage_getBooleanValue(value);
+ }
+ else if (name === 'url' || name === 'u') {
+ url = value;
+ }
+ }
+ }
+ }
+
+ var checkbox = document.getElementById('checkbox');
+ checkbox.checked = showMissingColumn;
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+
+ // this will automatically propagate to the input field
+ if (url) {
+ frames[0].location = url;
+ }
+
+ // if the browser tab is absent, we have to initialize the summary tab
+ if (! document.getElementById('browserTab')) {
+ jscoverage_recalculateSummaryTab();
+ }
+}
+
+function jscoverage_body_load() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.init(progressBar);
+
+ function reportError(e) {
+ jscoverage_endLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'hidden';
+ var div = document.getElementById('summaryErrorDiv');
+ div.innerHTML = 'Error: ' + e;
+ }
+
+ if (jscoverage_isReport) {
+ jscoverage_beginLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'visible';
+ var request = jscoverage_createRequest();
+ try {
+ request.open('GET', 'jscoverage.json', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ try {
+ if (request.status !== 0 && request.status !== 200) {
+ throw request.status;
+ }
+ var response = request.responseText;
+ if (response === '') {
+ throw 404;
+ }
+ var json = eval('(' + response + ')');
+ var file;
+ for (file in json) {
+ var fileCoverage = json[file];
+ _$jscoverage[file] = fileCoverage.coverage;
+ _$jscoverage[file].source = fileCoverage.source;
+ }
+ jscoverage_recalculateSummaryTab();
+ summaryThrobber.style.visibility = 'hidden';
+ }
+ catch (e) {
+ reportError(e);
+ }
+ }
+ };
+ request.send(null);
+ }
+ catch (e) {
+ reportError(e);
+ }
+
+ jscoverage_removeTab('browser');
+ jscoverage_removeTab('store');
+ }
+ else {
+ if (jscoverage_isInvertedMode) {
+ jscoverage_removeTab('browser');
+ }
+
+ if (! jscoverage_isServer) {
+ jscoverage_removeTab('store');
+ }
+ }
+
+ jscoverage_initTabControl();
+
+ jscoverage_initTabContents(location.search);
+}
+
+function jscoverage_body_resize() {
+ if (/MSIE/.test(navigator.userAgent)) {
+ jscoverage_setSize();
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 1
+
+function jscoverage_updateBrowser() {
+ var input = document.getElementById("location");
+ frames[0].location = input.value;
+}
+
+function jscoverage_input_keypress(e) {
+ if (e.keyCode === 13) {
+ jscoverage_updateBrowser();
+ }
+}
+
+function jscoverage_button_click() {
+ jscoverage_updateBrowser();
+}
+
+function jscoverage_browser_load() {
+ /* update the input box */
+ var input = document.getElementById("location");
+
+ /* sometimes IE seems to fire this after the tab has been removed */
+ if (input) {
+ input.value = frames[0].location;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 2
+
+function jscoverage_createLink(file, line) {
+ var link = document.createElement("a");
+
+ var url;
+ var call;
+ var text;
+ if (line) {
+ url = file + ".jscoverage.html?" + line;
+ call = "jscoverage_get('" + file + "', " + line + ");";
+ text = line.toString();
+ }
+ else {
+ url = file + ".jscoverage.html";
+ call = "jscoverage_get('" + file + "');";
+ text = file;
+ }
+
+ link.setAttribute('href', 'javascript:' + call);
+ link.appendChild(document.createTextNode(text));
+
+ return link;
+}
+
+function jscoverage_recalculateSummaryTab(cc) {
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+
+ if (! cc) {
+ cc = window._$jscoverage;
+ }
+ if (! cc) {
+//#JSCOVERAGE_IF 0
+ throw "No coverage information found.";
+//#JSCOVERAGE_ENDIF
+ }
+
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+
+ var totals = { files:0, statements:0, executed:0, coverage:0, skipped:0 };
+
+ var file;
+ var files = [];
+ for (file in cc) {
+ files.push(file);
+ }
+ files.sort();
+
+ var rowCounter = 0;
+ for (var f = 0; f < files.length; f++) {
+ file = files[f];
+ var lineNumber;
+ var num_statements = 0;
+ var num_executed = 0;
+ var missing = [];
+ var fileCC = cc[file];
+ var length = fileCC.length;
+ var currentConditionalEnd = 0;
+ var conditionals = null;
+ if (fileCC.conditionals) {
+ conditionals = fileCC.conditionals;
+ }
+ for (lineNumber = 0; lineNumber < length; lineNumber++) {
+ var n = fileCC[lineNumber];
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && conditionals && conditionals[lineNumber]) {
+ currentConditionalEnd = conditionals[lineNumber];
+ }
+
+ if (currentConditionalEnd !== 0) {
+ continue;
+ }
+
+ if (n === undefined || n === null) {
+ continue;
+ }
+
+ if (n === 0) {
+ missing.push(lineNumber);
+ }
+ else {
+ num_executed++;
+ }
+ num_statements++;
+ }
+
+ var percentage = ( num_statements === 0 ? 0 : parseInt(100 * num_executed / num_statements) );
+
+ var row = document.createElement("tr");
+ row.className = ( rowCounter++ % 2 == 0 ? "odd" : "even" );
+
+ var cell = document.createElement("td");
+ cell.className = 'leftColumn';
+ var link = jscoverage_createLink(file);
+ cell.appendChild(link);
+
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_statements));
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_executed));
+ row.appendChild(cell);
+
+ // new coverage td containing a bar graph
+ cell = document.createElement("td");
+ cell.className = 'coverage';
+ var pctGraph = document.createElement("div"),
+ covered = document.createElement("div"),
+ pct = document.createElement("span");
+ pctGraph.className = "pctGraph";
+ if( num_statements === 0 ) {
+ covered.className = "skipped";
+ pct.appendChild(document.createTextNode("N/A"));
+ } else {
+ covered.className = "covered";
+ covered.style.width = percentage + "px";
+ pct.appendChild(document.createTextNode(percentage + '%'));
+ }
+ pct.className = "pct";
+ pctGraph.appendChild(covered);
+ cell.appendChild(pctGraph);
+ cell.appendChild(pct);
+ row.appendChild(cell);
+
+ if (showMissingColumn) {
+ cell = document.createElement("td");
+ for (var i = 0; i < missing.length; i++) {
+ if (i !== 0) {
+ cell.appendChild(document.createTextNode(", "));
+ }
+ link = jscoverage_createLink(file, missing[i]);
+ cell.appendChild(link);
+ }
+ row.appendChild(cell);
+ }
+
+ tbody.appendChild(row);
+
+ totals['files'] ++;
+ totals['statements'] += num_statements;
+ totals['executed'] += num_executed;
+ totals['coverage'] += percentage;
+ if( num_statements === 0 ) {
+ totals['skipped']++;
+ }
+
+ // write totals data into summaryTotals row
+ var tr = document.getElementById("summaryTotals");
+ if (tr) {
+ var tds = tr.getElementsByTagName("td");
+ tds[0].getElementsByTagName("span")[1].firstChild.nodeValue = totals['files'];
+ tds[1].firstChild.nodeValue = totals['statements'];
+ tds[2].firstChild.nodeValue = totals['executed'];
+
+ var coverage = parseInt(totals['coverage'] / ( totals['files'] - totals['skipped'] ) );
+ if( isNaN( coverage ) ) {
+ coverage = 0;
+ }
+ tds[3].getElementsByTagName("span")[0].firstChild.nodeValue = coverage + '%';
+ tds[3].getElementsByTagName("div")[1].style.width = coverage + 'px';
+ }
+
+ }
+ jscoverage_endLengthyOperation();
+}
+
+function jscoverage_appendMissingColumn() {
+ var headerRow = document.getElementById('headerRow');
+ var missingHeader = document.createElement('th');
+ missingHeader.id = 'missingHeader';
+ missingHeader.innerHTML = '<abbr title="List of statements missed during execution">Missing</abbr>';
+ headerRow.appendChild(missingHeader);
+ var summaryTotals = document.getElementById('summaryTotals');
+ var empty = document.createElement('td');
+ empty.id = 'missingCell';
+ summaryTotals.appendChild(empty);
+}
+
+function jscoverage_removeMissingColumn() {
+ var missingNode;
+ missingNode = document.getElementById('missingHeader');
+ missingNode.parentNode.removeChild(missingNode);
+ missingNode = document.getElementById('missingCell');
+ missingNode.parentNode.removeChild(missingNode);
+}
+
+function jscoverage_checkbox_click() {
+ if (jscoverage_inLengthyOperation) {
+ return false;
+ }
+ jscoverage_beginLengthyOperation();
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+ setTimeout(function() {
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+ else {
+ jscoverage_removeMissingColumn();
+ }
+ jscoverage_recalculateSummaryTab();
+ }, 50);
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+// tab 3
+
+function jscoverage_makeTable() {
+ var coverage = _$jscoverage[jscoverage_currentFile];
+ var lines = coverage.source;
+
+ // this can happen if there is an error in the original JavaScript file
+ if (! lines) {
+ lines = [];
+ }
+
+ var rows = ['<table id="sourceTable">'];
+ var i = 0;
+ var progressBar = document.getElementById('progressBar');
+ var tableHTML;
+ var currentConditionalEnd = 0;
+
+ function joinTableRows() {
+ tableHTML = rows.join('');
+ ProgressBar.setPercentage(progressBar, 60);
+ /*
+ This may be a long delay, so set a timeout of 100 ms to make sure the
+ display is updated.
+ */
+ setTimeout(appendTable, 100);
+ }
+
+ function appendTable() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = tableHTML;
+ ProgressBar.setPercentage(progressBar, 80);
+ setTimeout(jscoverage_scrollToLine, 0);
+ }
+
+ while (i < lines.length) {
+ var lineNumber = i + 1;
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && coverage.conditionals && coverage.conditionals[lineNumber]) {
+ currentConditionalEnd = coverage.conditionals[lineNumber];
+ }
+
+ var row = '<tr>';
+ row += '<td class="numeric">' + lineNumber + '</td>';
+ var timesExecuted = coverage[lineNumber];
+ if (timesExecuted !== undefined && timesExecuted !== null) {
+ if (currentConditionalEnd !== 0) {
+ row += '<td class="y numeric">';
+ }
+ else if (timesExecuted === 0) {
+ row += '<td class="r numeric" id="line-' + lineNumber + '">';
+ }
+ else {
+ row += '<td class="g numeric">';
+ }
+ row += timesExecuted;
+ row += '</td>';
+ }
+ else {
+ row += '<td></td>';
+ }
+ row += '<td><pre>' + lines[i] + '</pre></td>';
+ row += '</tr>';
+ row += '\n';
+ rows[lineNumber] = row;
+ i++;
+ }
+ rows[i + 1] = '</table>';
+ ProgressBar.setPercentage(progressBar, 40);
+ setTimeout(joinTableRows, 0);
+}
+
+function jscoverage_scrollToLine() {
+ jscoverage_selectTab('sourceTab');
+ if (! window.jscoverage_currentLine) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var div = document.getElementById('sourceDiv');
+ if (jscoverage_currentLine === 1) {
+ div.scrollTop = 0;
+ }
+ else {
+ var cell = document.getElementById('line-' + jscoverage_currentLine);
+
+ // this might not be there if there is an error in the original JavaScript
+ if (cell) {
+ var divOffset = jscoverage_findPos(div);
+ var cellOffset = jscoverage_findPos(cell);
+ div.scrollTop = cellOffset - divOffset;
+ }
+ }
+ jscoverage_currentLine = 0;
+ jscoverage_endLengthyOperation();
+}
+
+/**
+Loads the given file (and optional line) in the source tab.
+*/
+function jscoverage_get(file, line) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ jscoverage_selectTab('sourceTab');
+ if (file === jscoverage_currentFile) {
+ jscoverage_currentLine = line;
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ if (jscoverage_currentFile === null) {
+ var tab = document.getElementById('sourceTab');
+ tab.className = '';
+ tab.onclick = jscoverage_tab_click;
+ }
+ jscoverage_currentFile = file;
+ jscoverage_currentLine = line || 1; // when changing the source, always scroll to top
+ var fileDiv = document.getElementById('fileDiv');
+ fileDiv.innerHTML = jscoverage_currentFile;
+ jscoverage_recalculateSourceTab();
+ return;
+ }
+ }, 50);
+}
+
+/**
+Calculates coverage statistics for the current source file.
+*/
+function jscoverage_recalculateSourceTab() {
+ if (! jscoverage_currentFile) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.innerHTML = 'Calculating coverage ...';
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 20);
+ setTimeout(jscoverage_makeTable, 0);
+}
+
+// -----------------------------------------------------------------------------
+// tabs
+
+/**
+Initializes the tab control. This function must be called when the document is
+loaded.
+*/
+function jscoverage_initTabControl() {
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child.className !== 'disabled') {
+ child.onclick = jscoverage_tab_click;
+ }
+ tabNum++;
+ }
+ }
+ jscoverage_selectTab(0);
+}
+
+/**
+Selects a tab.
+@param tab the integer index of the tab (0, 1, 2, or 3)
+ OR
+ the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_selectTab(tab) {
+ if (typeof tab !== 'number') {
+ tab = jscoverage_tabIndexOf(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var tabPages = document.getElementById('tabPages');
+ var nodeList;
+ var tabNum;
+ var i;
+ var node;
+
+ nodeList = tabs.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (node.className !== 'disabled') {
+ if (tabNum === tab) {
+ node.className = 'selected';
+ }
+ else {
+ node.className = '';
+ }
+ }
+ tabNum++;
+ }
+
+ nodeList = tabPages.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (tabNum === tab) {
+ node.className = 'selected TabPage';
+ }
+ else {
+ node.className = 'TabPage';
+ }
+ tabNum++;
+ }
+}
+
+/**
+Returns an integer (0, 1, 2, or 3) representing the index of a given tab.
+@param tab the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_tabIndexOf(tab) {
+ if (typeof tab === 'string') {
+ tab = document.getElementById(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child === tab) {
+ return tabNum;
+ }
+ tabNum++;
+ }
+ }
+//#JSCOVERAGE_IF 0
+ throw "Tab not found";
+//#JSCOVERAGE_ENDIF
+}
+
+function jscoverage_tab_click(e) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ var target;
+//#JSCOVERAGE_IF
+ if (e) {
+ target = e.target;
+ }
+ else if (window.event) {
+ // IE
+ target = window.event.srcElement;
+ }
+ if (target.className === 'selected') {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ if (target.id === 'summaryTab') {
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+ }
+ else if (target.id === 'sourceTab') {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ }
+ jscoverage_selectTab(target);
+ if (target.id === 'summaryTab') {
+ jscoverage_recalculateSummaryTab();
+ }
+ else if (target.id === 'sourceTab') {
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ jscoverage_endLengthyOperation();
+ }
+ }, 50);
+}
+
+// -----------------------------------------------------------------------------
+// progress bar
+
+var ProgressBar = {
+ init: function(element) {
+ element._percentage = 0;
+
+ /* doing this via JavaScript crashes Safari */
+/*
+ var pctGraph = document.createElement('div');
+ pctGraph.className = 'pctGraph';
+ element.appendChild(pctGraph);
+ var covered = document.createElement('div');
+ covered.className = 'covered';
+ pctGraph.appendChild(covered);
+ var pct = document.createElement('span');
+ pct.className = 'pct';
+ element.appendChild(pct);
+*/
+
+ ProgressBar._update(element);
+ },
+ setPercentage: function(element, percentage) {
+ element._percentage = percentage;
+ ProgressBar._update(element);
+ },
+ _update: function(element) {
+ var pctGraph = element.getElementsByTagName('div').item(0);
+ var covered = pctGraph.getElementsByTagName('div').item(0);
+ var pct = element.getElementsByTagName('span').item(0);
+ pct.innerHTML = element._percentage.toString() + '%';
+ covered.style.width = element._percentage + 'px';
+ }
+};
+
+// -----------------------------------------------------------------------------
+// reports
+
+function jscoverage_pad(s) {
+ return '0000'.substr(s.length) + s;
+}
+
+function jscoverage_quote(s) {
+ return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) {
+ switch (c) {
+ case '\b':
+ return '\\b';
+ case '\f':
+ return '\\f';
+ case '\n':
+ return '\\n';
+ case '\r':
+ return '\\r';
+ case '\t':
+ return '\\t';
+ // IE doesn't support this
+ /*
+ case '\v':
+ return '\\v';
+ */
+ case '"':
+ return '\\"';
+ case '\\':
+ return '\\\\';
+ default:
+ return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16));
+ }
+ }) + '"';
+}
+
+function jscoverage_serializeCoverageToJSON() {
+ var json = [];
+ for (var file in _$jscoverage) {
+ var coverage = _$jscoverage[file];
+ var array = [];
+ var length = coverage.length;
+ for (var line = 0; line < length; line++) {
+ var value = coverage[line];
+ if (value === undefined || value === null) {
+ value = 'null';
+ }
+ array.push(value);
+ }
+ json.push(jscoverage_quote(file) + ':[' + array.join(',') + ']');
+ }
+ return '{' + json.join(',') + '}';
+}
+
+function jscoverage_storeButton_click() {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+
+ jscoverage_beginLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'visible';
+
+ var request = jscoverage_createRequest();
+ request.open('POST', '/jscoverage-store', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ var message;
+ try {
+ if (request.status !== 200 && request.status !== 201 && request.status !== 204) {
+ throw request.status;
+ }
+ message = request.responseText;
+ }
+ catch (e) {
+ if (e.toString().search(/^\d{3}$/) === 0) {
+ message = e + ': ' + request.responseText;
+ }
+ else {
+ message = 'Could not connect to server: ' + e;
+ }
+ }
+
+ jscoverage_endLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'hidden';
+
+ var div = document.getElementById('storeDiv');
+ div.appendChild(document.createTextNode(new Date() + ': ' + message));
+ div.appendChild(document.createElement('br'));
+ }
+ };
+ request.setRequestHeader('Content-Type', 'application/json');
+ var json = jscoverage_serializeCoverageToJSON();
+ request.setRequestHeader('Content-Length', json.length.toString());
+ request.send(json);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/script.js b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/script.js
new file mode 100644
index 0000000..5ea28fc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/script.js
@@ -0,0 +1,65 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['script.js']) {
+ _$jscoverage['script.js'] = [];
+ _$jscoverage['script.js'][1] = 0;
+ _$jscoverage['script.js'][2] = 0;
+ _$jscoverage['script.js'][3] = 0;
+ _$jscoverage['script.js'][4] = 0;
+ _$jscoverage['script.js'][6] = 0;
+ _$jscoverage['script.js'][7] = 0;
+ _$jscoverage['script.js'][9] = 0;
+ _$jscoverage['script.js'][10] = 0;
+ _$jscoverage['script.js'][12] = 0;
+ _$jscoverage['script.js'][13] = 0;
+ _$jscoverage['script.js'][15] = 0;
+ _$jscoverage['script.js'][16] = 0;
+ _$jscoverage['script.js'][17] = 0;
+ _$jscoverage['script.js'][18] = 0;
+ _$jscoverage['script.js'][19] = 0;
+}
+_$jscoverage['script.js'][1]++;
+function go(element) {
+ _$jscoverage['script.js'][2]++;
+ var message;
+ _$jscoverage['script.js'][3]++;
+ if (element.id === "radio1") {
+ _$jscoverage['script.js'][4]++;
+ message = "You selected the number 1.";
+ }
+ else {
+ _$jscoverage['script.js'][6]++;
+ if (element.id === "radio2") {
+ _$jscoverage['script.js'][7]++;
+ message = "You selected the number 2.";
+ }
+ else {
+ _$jscoverage['script.js'][9]++;
+ if (element.id === "radio3") {
+ _$jscoverage['script.js'][10]++;
+ message = "You selected the number 3.";
+ }
+ else {
+ _$jscoverage['script.js'][12]++;
+ if (element.id === "radio4") {
+ _$jscoverage['script.js'][13]++;
+ message = "You selected the number 4.";
+ }
+ }
+ }
+ }
+ _$jscoverage['script.js'][15]++;
+ var div = document.getElementById("request");
+ _$jscoverage['script.js'][16]++;
+ div.className = "black";
+ _$jscoverage['script.js'][17]++;
+ div = document.getElementById("result");
+ _$jscoverage['script.js'][18]++;
+ div.innerHTML = "<p>" + message + "</p>";
+ _$jscoverage['script.js'][19]++;
+ div.innerHTML += "<p>If you are running the instrumented version of this program, you can click the \"Coverage report\" button to view a coverage report.</p>";
+}
+_$jscoverage['script.js'].source = ["<span class=\"k\">function</span> go<span class=\"k\">(</span>element<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> message<span class=\"k\">;</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio1'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 1.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio2'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 2.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio3'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 3.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio4'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 4.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">var</span> div <span class=\"k\">=</span> document<span class=\"k\">.</span>getElementById<span class=\"k\">(</span><span class=\"s\">'request'</span><span class=\"k\">);</span>"," div<span class=\"k\">.</span>className <span class=\"k\">=</span> <span class=\"s\">'black'</span><span class=\"k\">;</span>"," div <span class=\"k\">=</span> document<span class=\"k\">.</span>getElementById<span class=\"k\">(</span><span class=\"s\">'result'</span><span class=\"k\">);</span>"," div<span class=\"k\">.</span>innerHTML <span class=\"k\">=</span> <span class=\"s\">'&lt;p&gt;'</span> <span class=\"k\">+</span> message <span class=\"k\">+</span> <span class=\"s\">'&lt;/p&gt;'</span><span class=\"k\">;</span>"," div<span class=\"k\">.</span>innerHTML <span class=\"k\">+=</span> <span class=\"s\">'&lt;p&gt;If you are running the instrumented version of this program, you can click the \"Coverage report\" button to view a coverage report.&lt;/p&gt;'</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/index.html
new file mode 100644
index 0000000..e7230b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Example</title>
+<script type="text/javascript" src="script.js"></script>
+<style>
+div.black {
+ color: black;
+}
+div.red {
+ color: red;
+ font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="request" class="red">Please select your favorite number:</div>
+<input type="radio" name="number" id="radio1" onclick="go(this);"><label for="radio1">One</label><br>
+<input type="radio" name="number" id="radio2" onclick="go(this);"><label for="radio2">Two</label><br>
+<input type="radio" name="number" id="radio3" onclick="go(this);"><label for="radio3">Three</label><br>
+<input type="radio" name="number" id="radio4" onclick="go(this);"><label for="radio4">Four</label><br>
+<div id="result" class="red"></div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-highlight.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-highlight.css
new file mode 100644
index 0000000..31a4695
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-highlight.css
@@ -0,0 +1,38 @@
+/*
+ jscoverage-highlight.css - JSCoverage syntax highlighting style sheet
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/* keyword, type, symbol, cbracket */
+#sourceTable .k {
+ font-weight: bold;
+}
+
+/* string, regexp, number */
+#sourceTable .s {
+ color: #006400;
+}
+
+/* specialchar */
+#sourceTable .t {
+ color: #2e8b57;
+}
+
+/* comment */
+#sourceTable .c {
+ font-style: italic;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-ie.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-ie.css
new file mode 100644
index 0000000..afb2b80
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-ie.css
@@ -0,0 +1,89 @@
+#headingDiv {
+ position: static;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding-top: 0.5em;
+}
+
+#tabs {
+ clear: all;
+ position: static;
+ top: auto;
+ left: auto;
+ right: auto;
+ height: auto;
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+#tabs div {
+ position: relative;
+ height: auto;
+ line-height: normal;
+ padding-top: 5px;
+ padding-bottom: 5px;
+}
+
+#tabs div.selected {
+ padding-bottom: 6px;
+ z-index: 2;
+}
+
+.TabPage {
+ position: relative;
+ top: -1px;
+ left: auto;
+ right: auto;
+ bottom: auto;
+ clear: left;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 10px;
+ z-index: 1;
+}
+
+#locationDiv {
+ margin-bottom: 10px;
+}
+
+#iframeDiv {
+ position: static;
+ width: 100%;
+}
+
+#summaryDiv {
+ position: static;
+ width: 100%;
+}
+
+#fileDiv {
+ margin-bottom: 10px;
+}
+
+#sourceDiv {
+ position: static;
+ width: 100%;
+}
+
+#storeDiv {
+ position: static;
+ width: 100%;
+}
+
+/* some defaults */
+
+.TabPage {
+ height: 650px;
+}
+
+#iframeDiv {
+ height: 600px;
+}
+
+#summaryDiv {
+ height: 600px;
+}
+
+#sourceDiv {
+ height: 600px;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-throbber.gif b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-throbber.gif
new file mode 100644
index 0000000..f13c0b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-throbber.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.css
new file mode 100644
index 0000000..98af69b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.css
@@ -0,0 +1,328 @@
+/*
+ jscoverage.css - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+body {
+ background-color: #bfffbf;
+ font-family: sans-serif;
+ font-size: 100%;
+ margin: 0;
+}
+
+#mainDiv {
+ font-size: 0.8125em;
+}
+
+#headingDiv {
+ position: absolute;
+ top: 0.5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 0;
+ line-height: 1.5em;
+}
+
+h1 {
+ float: left;
+ margin: 0;
+ padding-bottom: 0.5em;
+ font-size: 1.3em;
+}
+
+.ProgressBar {
+ float: left;
+ visibility: hidden;
+}
+
+.ProgressPercentage {
+ display: block;
+ float: left;
+ width: 5em;
+ text-align: right;
+}
+
+.ProgressGraph {
+ float: left;
+ width: 100px;
+ height: 10px;
+ border: 1px solid black;
+ margin-top: 0.3em;
+ background-color: #d4d0c8;
+ overflow: hidden;
+}
+
+.ProgressCovered {
+ /* windows system color ActiveCaption or Highlight */
+ background-color: #0a246a;
+ width: 0;
+ height: 10px;
+ overflow: hidden;
+}
+
+#progressLabel {
+ display: block;
+ float: left;
+ padding-left: 0.3em;
+}
+
+/*******************************************************************************
+browser tab
+*/
+
+input#location, button {
+ border: 1px solid black;
+ margin-left: 1px;
+ margin-right: 1px;
+}
+
+#iframeDiv {
+ position: absolute;
+ top: 3.5em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+}
+
+iframe {
+ width: 100%;
+ height: 100%;
+}
+
+/*******************************************************************************
+summary tab
+*/
+
+#summaryDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#summaryTable {
+ width: 100%;
+ margin-left: 0px;
+ margin-right: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+table#summaryTable th, table#summaryTable td {
+ border-left: 1px solid #d9d9d9;
+}
+
+table#summaryTable th.leftColumn, table#summaryTable td.leftColumn {
+ border-left-width: 0px;
+}
+
+table#summaryTable th, table#summaryTable td {
+ padding: 2px;
+}
+
+th {
+ background-color: #e6ffe6;
+}
+
+td.numeric {
+ text-align: right;
+}
+
+abbr {
+ cursor: help;
+}
+
+tr#summaryTotals td.leftColumn span {
+ float: right;
+}
+tr#summaryTotals td.leftColumn span.title {
+ float: left;
+ font-weight: bold;
+}
+tr#summaryTotals td {
+ background-color: #ffd;
+}
+td.coverage {
+ width: 150px;
+}
+td.coverage span {
+ float: right;
+ margin-right: 5px;
+}
+.pctGraph {
+ width: 100px;
+ height: 10px;
+ float: right;
+ border: 1px solid #000;
+ background-color: #e00000;
+ overflow: hidden;
+ margin-top: 4px;
+}
+.pctGraph .covered {
+ background-color: #00f000;
+ width: 0;
+ height: 10px;
+}
+.pctGraph .skipped {
+ background-color: #d4d0c8;
+ width: 100px;
+ height: 10px;
+}
+tbody#summaryTbody tr.even td {
+ background-color: #e6ffe6;
+}
+
+/*******************************************************************************
+source tab
+*/
+
+#fileDiv {
+ font-size: large;
+ font-weight: bold;
+}
+
+#sourceDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#sourceTable {
+ border: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+/*
+IE default behavior is to make <pre> smaller than surrounding text. Because
+the table already has font-size small, this would make the font-size within the
+<pre> x-small. So we don't rely on the default.
+*/
+table#sourceTable pre {
+ font-size: medium;
+}
+
+table#sourceTable td {
+ border: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+table#sourceTable pre {
+ border: 0px;
+ margin: 0px;
+}
+
+.g {
+ background-color: #bfffbf;
+}
+
+.y {
+ background-color: #ffffbf;
+}
+
+.r {
+ background-color: #ffbfbf;
+}
+
+/*******************************************************************************
+store tab
+*/
+
+#storeDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+/*******************************************************************************
+about tab
+*/
+
+p {
+ margin-top: 0;
+}
+
+/*******************************************************************************
+tabs
+*/
+
+#tabs {
+ position: absolute;
+ top: 3em;
+ left: 1.5em;
+ right: 1.5em;
+ height: 2em;
+}
+
+#tabs div {
+ background-color: white;
+ position: relative;
+ float: left;
+ border: 1px solid black;
+ border-bottom-width: 0;
+ cursor: pointer;
+ margin-left: 0.5em;
+ margin-right: 0.5em;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ height: 2em;
+ z-index: 1;
+ line-height: 1.8em;
+}
+
+#tabs div.selected {
+ z-index: 3;
+ cursor: default;
+}
+
+#tabs div.disabled {
+ /* windows system color GrayText */
+ color: #808080;
+ cursor: default;
+}
+
+.TabPage {
+ background-color: white;
+ border: 1px solid black;
+ position: absolute;
+ top: 5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 1.5em;
+ z-index: 2;
+ padding: 1em;
+ display: none;
+}
+
+#tabPages div.selected {
+ display: block;
+}
+
+img {
+ visibility: hidden;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.html b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.html
new file mode 100644
index 0000000..601f62a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<!--
+ jscoverage.html - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
+
+<html>
+<head>
+<title>JSCoverage</title>
+<link rel="stylesheet" type="text/css" href="jscoverage-highlight.css">
+<link rel="stylesheet" type="text/css" href="jscoverage.css">
+<!--[if IE]>
+<link rel="stylesheet" type="text/css" href="jscoverage-ie.css">
+<![endif]-->
+<script type="text/javascript" src="jscoverage.js"></script>
+</head>
+
+<body onload="jscoverage_body_load();" onresize="jscoverage_body_resize();">
+<div id="mainDiv">
+<div id="headingDiv">
+<h1>JSCoverage</h1>
+<div class="ProgressBar" id="progressBar"><span class="ProgressPercentage"></span><div class="ProgressGraph"><div class="ProgressCovered"></div></div></div>
+<span id="progressLabel"></span>
+</div>
+
+<div id="tabs" class="Tabs">
+ <div id="browserTab"><img src="jscoverage-throbber.gif" alt=""> Browser <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="summaryTab"><img id="summaryThrobber" src="jscoverage-throbber.gif" alt=""> Summary <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="sourceTab" class="disabled"><img src="jscoverage-throbber.gif" alt=""> Source <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="storeTab"><img id="storeThrobber" src="jscoverage-throbber.gif" alt=""> Store <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="aboutTab"><img src="jscoverage-throbber.gif" alt=""> About <img src="jscoverage-throbber.gif" alt=""></div>
+</div>
+<div id="tabPages" class="TabPages">
+ <div class="TabPage" id="browserTabPage">
+ <div id="locationDiv">
+ URL: <input id="location" type="text" size="70" onkeypress="jscoverage_input_keypress(event)">
+ <button onclick="jscoverage_button_click();">Go</button>
+ </div>
+ <div id="iframeDiv">
+ <iframe id="browserIframe" onload="jscoverage_browser_load();"></iframe>
+ </div>
+ </div>
+ <div class="TabPage">
+ <input type="checkbox" id="checkbox" onclick="return jscoverage_checkbox_click();"> <label for="checkbox">Show missing statements column</label>
+ <div id="summaryDiv">
+ <div id="summaryErrorDiv"></div>
+ <table id="summaryTable">
+ <thead>
+ <tr id="headerRow">
+ <th class="leftColumn">File</th>
+ <th><abbr title="The total number of executable statements">Statements</abbr></th>
+ <th><abbr title="The number of statements actually executed">Executed</abbr></th>
+ <th><abbr title="Number of executed statements as a percentage of total number of statements">Coverage</abbr></th>
+ </tr>
+ <tr id="summaryTotals">
+ <td class="leftColumn">
+ <span class="title">Total:</span>
+ <span>0</span>
+ </td>
+ <td class="numeric">0</td>
+ <td class="numeric">0</td>
+ <td class="coverage">
+ <div class="pctGraph">
+ <div class="covered"></div>
+ </div>
+ <span class="pct">0%</span>
+ </td>
+ </tr>
+
+ </thead>
+ <tbody id="summaryTbody">
+
+ <!--
+ <tr>
+ <td>0</td>
+ <td>0</td>
+ <td>0</td>
+ <td>0%</td>
+ <td>0</td>
+ </tr>
+ -->
+
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="TabPage">
+ <div id="fileDiv"></div>
+ <div id="sourceDiv"></div>
+ </div>
+ <div class="TabPage" id="storeTabPage">
+ <button id="storeButton" onclick="jscoverage_storeButton_click();">Store Report</button>
+ <img id="storeImg" src="jscoverage-throbber.gif" alt="loading...">
+ <div id="storeDiv"></div>
+ </div>
+ <div class="TabPage">
+ <p>
+ This is version 0.4 of JSCoverage, a program that calculates code
+ coverage statistics for JavaScript.
+ </p>
+ <p>
+ See <a href="http://siliconforks.com/jscoverage/">http://siliconforks.com/jscoverage/</a> for more information.
+ </p>
+ <p>
+ Copyright &copy; 2007, 2008 siliconforks.com
+ </p>
+ </div>
+</div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.js b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.js
new file mode 100644
index 0000000..9e2ea5b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.js
@@ -0,0 +1,1024 @@
+/*
+ jscoverage.js - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/**
+Initializes the _$jscoverage object in a window. This should be the first
+function called in the page.
+@param w this should always be the global window object
+*/
+function jscoverage_init(w) {
+ try {
+ // in Safari, "import" is a syntax error
+ Components.utils['import']('resource://gre/modules/jscoverage.jsm');
+ jscoverage_isInvertedMode = true;
+ return;
+ }
+ catch (e) {}
+
+ if (w.opener && w.opener.top._$jscoverage) {
+ // we are in inverted mode
+ jscoverage_isInvertedMode = true;
+ if (! w._$jscoverage) {
+ w._$jscoverage = w.opener.top._$jscoverage;
+ }
+ }
+ else {
+ // we are not in inverted mode
+ jscoverage_isInvertedMode = false;
+ if (! w._$jscoverage) {
+ w._$jscoverage = {};
+ }
+ }
+}
+
+var jscoverage_currentFile = null;
+var jscoverage_currentLine = null;
+
+var jscoverage_inLengthyOperation = false;
+
+/*
+Possible states:
+ isInvertedMode isServer isReport tabs
+normal false false false Browser
+inverted true false false
+server, normal false true false Browser, Store
+server, inverted true true false Store
+report false false true
+*/
+var jscoverage_isInvertedMode = false;
+var jscoverage_isServer = false;
+var jscoverage_isReport = false;
+
+jscoverage_init(window);
+
+function jscoverage_createRequest() {
+ // Note that the IE7 XMLHttpRequest does not support file URL's.
+ // http://xhab.blogspot.com/2006/11/ie7-support-for-xmlhttprequest.html
+ // http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx
+//#JSCOVERAGE_IF
+ if (window.ActiveXObject) {
+ return new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ else {
+ return new XMLHttpRequest();
+ }
+}
+
+// http://www.quirksmode.org/js/findpos.html
+function jscoverage_findPos(obj) {
+ var result = 0;
+ do {
+ result += obj.offsetTop;
+ obj = obj.offsetParent;
+ }
+ while (obj);
+ return result;
+}
+
+// http://www.quirksmode.org/viewport/compatibility.html
+function jscoverage_getViewportHeight() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ if (self.innerHeight) {
+ // all except Explorer
+ return self.innerHeight;
+ }
+ else if (document.documentElement && document.documentElement.clientHeight) {
+ // Explorer 6 Strict Mode
+ return document.documentElement.clientHeight;
+ }
+ else if (document.body) {
+ // other Explorers
+ return document.body.clientHeight;
+ }
+ else {
+ throw "Couldn't calculate viewport height";
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Indicates visually that a lengthy operation has begun. The progress bar is
+displayed, and the cursor is changed to busy (on browsers which support this).
+*/
+function jscoverage_beginLengthyOperation() {
+ jscoverage_inLengthyOperation = true;
+
+ var progressBar = document.getElementById('progressBar');
+ progressBar.style.visibility = 'visible';
+ ProgressBar.setPercentage(progressBar, 0);
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'visible';
+
+ /* blacklist buggy browsers */
+//#JSCOVERAGE_IF
+ if (! /Opera|WebKit/.test(navigator.userAgent)) {
+ /*
+ Change the cursor style of each element. Note that changing the class of the
+ element (to one with a busy cursor) is buggy in IE.
+ */
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = 'wait';
+ }
+ }
+}
+
+/**
+Removes the progress bar and busy cursor.
+*/
+function jscoverage_endLengthyOperation() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 100);
+ setTimeout(function() {
+ jscoverage_inLengthyOperation = false;
+ progressBar.style.visibility = 'hidden';
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'hidden';
+ progressLabel.innerHTML = '';
+
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = '';
+ }
+ }, 50);
+}
+
+function jscoverage_setSize() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ var viewportHeight = jscoverage_getViewportHeight();
+
+ /*
+ border-top-width: 1px
+ padding-top: 10px
+ padding-bottom: 10px
+ border-bottom-width: 1px
+ margin-bottom: 10px
+ ----
+ 32px
+ */
+ var tabPages = document.getElementById('tabPages');
+ var tabPageHeight = (viewportHeight - jscoverage_findPos(tabPages) - 32) + 'px';
+ var nodeList = tabPages.childNodes;
+ var length = nodeList.length;
+ for (var i = 0; i < length; i++) {
+ var node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+ node.style.height = tabPageHeight;
+ }
+
+ var iframeDiv = document.getElementById('iframeDiv');
+ // may not exist if we have removed the first tab
+ if (iframeDiv) {
+ iframeDiv.style.height = (viewportHeight - jscoverage_findPos(iframeDiv) - 21) + 'px';
+ }
+
+ var summaryDiv = document.getElementById('summaryDiv');
+ summaryDiv.style.height = (viewportHeight - jscoverage_findPos(summaryDiv) - 21) + 'px';
+
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.style.height = (viewportHeight - jscoverage_findPos(sourceDiv) - 21) + 'px';
+
+ var storeDiv = document.getElementById('storeDiv');
+ if (storeDiv) {
+ storeDiv.style.height = (viewportHeight - jscoverage_findPos(storeDiv) - 21) + 'px';
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Returns the boolean value of a string. Values 'false', 'f', 'no', 'n', 'off',
+and '0' (upper or lower case) are false.
+@param s the string
+@return a boolean value
+*/
+function jscoverage_getBooleanValue(s) {
+ s = s.toLowerCase();
+ if (s === 'false' || s === 'f' || s === 'no' || s === 'n' || s === 'off' || s === '0') {
+ return false;
+ }
+ return true;
+}
+
+function jscoverage_removeTab(id) {
+ var tab = document.getElementById(id + 'Tab');
+ tab.parentNode.removeChild(tab);
+ var tabPage = document.getElementById(id + 'TabPage');
+ tabPage.parentNode.removeChild(tabPage);
+}
+
+/**
+Initializes the contents of the tabs. This sets the initial values of the
+input field and iframe in the "Browser" tab and the checkbox in the "Summary"
+tab.
+@param queryString this should always be location.search
+*/
+function jscoverage_initTabContents(queryString) {
+ var showMissingColumn = false;
+ var parameters, parameter, i, index, url, name, value;
+ if (queryString.length > 0) {
+ // chop off the question mark
+ queryString = queryString.substring(1);
+ parameters = queryString.split(/&|;/);
+ for (i = 0; i < parameters.length; i++) {
+ parameter = parameters[i];
+ index = parameter.indexOf('=');
+ if (index === -1) {
+ // still works with old syntax
+ url = parameter;
+ }
+ else {
+ name = parameter.substr(0, index);
+ value = parameter.substr(index + 1);
+ if (name === 'missing' || name === 'm') {
+ showMissingColumn = jscoverage_getBooleanValue(value);
+ }
+ else if (name === 'url' || name === 'u') {
+ url = value;
+ }
+ }
+ }
+ }
+
+ var checkbox = document.getElementById('checkbox');
+ checkbox.checked = showMissingColumn;
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+
+ // this will automatically propagate to the input field
+ if (url) {
+ frames[0].location = url;
+ }
+
+ // if the browser tab is absent, we have to initialize the summary tab
+ if (! document.getElementById('browserTab')) {
+ jscoverage_recalculateSummaryTab();
+ }
+}
+
+function jscoverage_body_load() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.init(progressBar);
+
+ function reportError(e) {
+ jscoverage_endLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'hidden';
+ var div = document.getElementById('summaryErrorDiv');
+ div.innerHTML = 'Error: ' + e;
+ }
+
+ if (jscoverage_isReport) {
+ jscoverage_beginLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'visible';
+ var request = jscoverage_createRequest();
+ try {
+ request.open('GET', 'jscoverage.json', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ try {
+ if (request.status !== 0 && request.status !== 200) {
+ throw request.status;
+ }
+ var response = request.responseText;
+ if (response === '') {
+ throw 404;
+ }
+ var json = eval('(' + response + ')');
+ var file;
+ for (file in json) {
+ var fileCoverage = json[file];
+ _$jscoverage[file] = fileCoverage.coverage;
+ _$jscoverage[file].source = fileCoverage.source;
+ }
+ jscoverage_recalculateSummaryTab();
+ summaryThrobber.style.visibility = 'hidden';
+ }
+ catch (e) {
+ reportError(e);
+ }
+ }
+ };
+ request.send(null);
+ }
+ catch (e) {
+ reportError(e);
+ }
+
+ jscoverage_removeTab('browser');
+ jscoverage_removeTab('store');
+ }
+ else {
+ if (jscoverage_isInvertedMode) {
+ jscoverage_removeTab('browser');
+ }
+
+ if (! jscoverage_isServer) {
+ jscoverage_removeTab('store');
+ }
+ }
+
+ jscoverage_initTabControl();
+
+ jscoverage_initTabContents(location.search);
+}
+
+function jscoverage_body_resize() {
+ if (/MSIE/.test(navigator.userAgent)) {
+ jscoverage_setSize();
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 1
+
+function jscoverage_updateBrowser() {
+ var input = document.getElementById("location");
+ frames[0].location = input.value;
+}
+
+function jscoverage_input_keypress(e) {
+ if (e.keyCode === 13) {
+ jscoverage_updateBrowser();
+ }
+}
+
+function jscoverage_button_click() {
+ jscoverage_updateBrowser();
+}
+
+function jscoverage_browser_load() {
+ /* update the input box */
+ var input = document.getElementById("location");
+
+ /* sometimes IE seems to fire this after the tab has been removed */
+ if (input) {
+ input.value = frames[0].location;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 2
+
+function jscoverage_createLink(file, line) {
+ var link = document.createElement("a");
+
+ var url;
+ var call;
+ var text;
+ if (line) {
+ url = file + ".jscoverage.html?" + line;
+ call = "jscoverage_get('" + file + "', " + line + ");";
+ text = line.toString();
+ }
+ else {
+ url = file + ".jscoverage.html";
+ call = "jscoverage_get('" + file + "');";
+ text = file;
+ }
+
+ link.setAttribute('href', 'javascript:' + call);
+ link.appendChild(document.createTextNode(text));
+
+ return link;
+}
+
+function jscoverage_recalculateSummaryTab(cc) {
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+
+ if (! cc) {
+ cc = window._$jscoverage;
+ }
+ if (! cc) {
+//#JSCOVERAGE_IF 0
+ throw "No coverage information found.";
+//#JSCOVERAGE_ENDIF
+ }
+
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+
+ var totals = { files:0, statements:0, executed:0, coverage:0, skipped:0 };
+
+ var file;
+ var files = [];
+ for (file in cc) {
+ files.push(file);
+ }
+ files.sort();
+
+ var rowCounter = 0;
+ for (var f = 0; f < files.length; f++) {
+ file = files[f];
+ var lineNumber;
+ var num_statements = 0;
+ var num_executed = 0;
+ var missing = [];
+ var fileCC = cc[file];
+ var length = fileCC.length;
+ var currentConditionalEnd = 0;
+ var conditionals = null;
+ if (fileCC.conditionals) {
+ conditionals = fileCC.conditionals;
+ }
+ for (lineNumber = 0; lineNumber < length; lineNumber++) {
+ var n = fileCC[lineNumber];
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && conditionals && conditionals[lineNumber]) {
+ currentConditionalEnd = conditionals[lineNumber];
+ }
+
+ if (currentConditionalEnd !== 0) {
+ continue;
+ }
+
+ if (n === undefined || n === null) {
+ continue;
+ }
+
+ if (n === 0) {
+ missing.push(lineNumber);
+ }
+ else {
+ num_executed++;
+ }
+ num_statements++;
+ }
+
+ var percentage = ( num_statements === 0 ? 0 : parseInt(100 * num_executed / num_statements) );
+
+ var row = document.createElement("tr");
+ row.className = ( rowCounter++ % 2 == 0 ? "odd" : "even" );
+
+ var cell = document.createElement("td");
+ cell.className = 'leftColumn';
+ var link = jscoverage_createLink(file);
+ cell.appendChild(link);
+
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_statements));
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_executed));
+ row.appendChild(cell);
+
+ // new coverage td containing a bar graph
+ cell = document.createElement("td");
+ cell.className = 'coverage';
+ var pctGraph = document.createElement("div"),
+ covered = document.createElement("div"),
+ pct = document.createElement("span");
+ pctGraph.className = "pctGraph";
+ if( num_statements === 0 ) {
+ covered.className = "skipped";
+ pct.appendChild(document.createTextNode("N/A"));
+ } else {
+ covered.className = "covered";
+ covered.style.width = percentage + "px";
+ pct.appendChild(document.createTextNode(percentage + '%'));
+ }
+ pct.className = "pct";
+ pctGraph.appendChild(covered);
+ cell.appendChild(pctGraph);
+ cell.appendChild(pct);
+ row.appendChild(cell);
+
+ if (showMissingColumn) {
+ cell = document.createElement("td");
+ for (var i = 0; i < missing.length; i++) {
+ if (i !== 0) {
+ cell.appendChild(document.createTextNode(", "));
+ }
+ link = jscoverage_createLink(file, missing[i]);
+ cell.appendChild(link);
+ }
+ row.appendChild(cell);
+ }
+
+ tbody.appendChild(row);
+
+ totals['files'] ++;
+ totals['statements'] += num_statements;
+ totals['executed'] += num_executed;
+ totals['coverage'] += percentage;
+ if( num_statements === 0 ) {
+ totals['skipped']++;
+ }
+
+ // write totals data into summaryTotals row
+ var tr = document.getElementById("summaryTotals");
+ if (tr) {
+ var tds = tr.getElementsByTagName("td");
+ tds[0].getElementsByTagName("span")[1].firstChild.nodeValue = totals['files'];
+ tds[1].firstChild.nodeValue = totals['statements'];
+ tds[2].firstChild.nodeValue = totals['executed'];
+
+ var coverage = parseInt(totals['coverage'] / ( totals['files'] - totals['skipped'] ) );
+ if( isNaN( coverage ) ) {
+ coverage = 0;
+ }
+ tds[3].getElementsByTagName("span")[0].firstChild.nodeValue = coverage + '%';
+ tds[3].getElementsByTagName("div")[1].style.width = coverage + 'px';
+ }
+
+ }
+ jscoverage_endLengthyOperation();
+}
+
+function jscoverage_appendMissingColumn() {
+ var headerRow = document.getElementById('headerRow');
+ var missingHeader = document.createElement('th');
+ missingHeader.id = 'missingHeader';
+ missingHeader.innerHTML = '<abbr title="List of statements missed during execution">Missing</abbr>';
+ headerRow.appendChild(missingHeader);
+ var summaryTotals = document.getElementById('summaryTotals');
+ var empty = document.createElement('td');
+ empty.id = 'missingCell';
+ summaryTotals.appendChild(empty);
+}
+
+function jscoverage_removeMissingColumn() {
+ var missingNode;
+ missingNode = document.getElementById('missingHeader');
+ missingNode.parentNode.removeChild(missingNode);
+ missingNode = document.getElementById('missingCell');
+ missingNode.parentNode.removeChild(missingNode);
+}
+
+function jscoverage_checkbox_click() {
+ if (jscoverage_inLengthyOperation) {
+ return false;
+ }
+ jscoverage_beginLengthyOperation();
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+ setTimeout(function() {
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+ else {
+ jscoverage_removeMissingColumn();
+ }
+ jscoverage_recalculateSummaryTab();
+ }, 50);
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+// tab 3
+
+function jscoverage_makeTable() {
+ var coverage = _$jscoverage[jscoverage_currentFile];
+ var lines = coverage.source;
+
+ // this can happen if there is an error in the original JavaScript file
+ if (! lines) {
+ lines = [];
+ }
+
+ var rows = ['<table id="sourceTable">'];
+ var i = 0;
+ var progressBar = document.getElementById('progressBar');
+ var tableHTML;
+ var currentConditionalEnd = 0;
+
+ function joinTableRows() {
+ tableHTML = rows.join('');
+ ProgressBar.setPercentage(progressBar, 60);
+ /*
+ This may be a long delay, so set a timeout of 100 ms to make sure the
+ display is updated.
+ */
+ setTimeout(appendTable, 100);
+ }
+
+ function appendTable() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = tableHTML;
+ ProgressBar.setPercentage(progressBar, 80);
+ setTimeout(jscoverage_scrollToLine, 0);
+ }
+
+ while (i < lines.length) {
+ var lineNumber = i + 1;
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && coverage.conditionals && coverage.conditionals[lineNumber]) {
+ currentConditionalEnd = coverage.conditionals[lineNumber];
+ }
+
+ var row = '<tr>';
+ row += '<td class="numeric">' + lineNumber + '</td>';
+ var timesExecuted = coverage[lineNumber];
+ if (timesExecuted !== undefined && timesExecuted !== null) {
+ if (currentConditionalEnd !== 0) {
+ row += '<td class="y numeric">';
+ }
+ else if (timesExecuted === 0) {
+ row += '<td class="r numeric" id="line-' + lineNumber + '">';
+ }
+ else {
+ row += '<td class="g numeric">';
+ }
+ row += timesExecuted;
+ row += '</td>';
+ }
+ else {
+ row += '<td></td>';
+ }
+ row += '<td><pre>' + lines[i] + '</pre></td>';
+ row += '</tr>';
+ row += '\n';
+ rows[lineNumber] = row;
+ i++;
+ }
+ rows[i + 1] = '</table>';
+ ProgressBar.setPercentage(progressBar, 40);
+ setTimeout(joinTableRows, 0);
+}
+
+function jscoverage_scrollToLine() {
+ jscoverage_selectTab('sourceTab');
+ if (! window.jscoverage_currentLine) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var div = document.getElementById('sourceDiv');
+ if (jscoverage_currentLine === 1) {
+ div.scrollTop = 0;
+ }
+ else {
+ var cell = document.getElementById('line-' + jscoverage_currentLine);
+
+ // this might not be there if there is an error in the original JavaScript
+ if (cell) {
+ var divOffset = jscoverage_findPos(div);
+ var cellOffset = jscoverage_findPos(cell);
+ div.scrollTop = cellOffset - divOffset;
+ }
+ }
+ jscoverage_currentLine = 0;
+ jscoverage_endLengthyOperation();
+}
+
+/**
+Loads the given file (and optional line) in the source tab.
+*/
+function jscoverage_get(file, line) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ jscoverage_selectTab('sourceTab');
+ if (file === jscoverage_currentFile) {
+ jscoverage_currentLine = line;
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ if (jscoverage_currentFile === null) {
+ var tab = document.getElementById('sourceTab');
+ tab.className = '';
+ tab.onclick = jscoverage_tab_click;
+ }
+ jscoverage_currentFile = file;
+ jscoverage_currentLine = line || 1; // when changing the source, always scroll to top
+ var fileDiv = document.getElementById('fileDiv');
+ fileDiv.innerHTML = jscoverage_currentFile;
+ jscoverage_recalculateSourceTab();
+ return;
+ }
+ }, 50);
+}
+
+/**
+Calculates coverage statistics for the current source file.
+*/
+function jscoverage_recalculateSourceTab() {
+ if (! jscoverage_currentFile) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.innerHTML = 'Calculating coverage ...';
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 20);
+ setTimeout(jscoverage_makeTable, 0);
+}
+
+// -----------------------------------------------------------------------------
+// tabs
+
+/**
+Initializes the tab control. This function must be called when the document is
+loaded.
+*/
+function jscoverage_initTabControl() {
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child.className !== 'disabled') {
+ child.onclick = jscoverage_tab_click;
+ }
+ tabNum++;
+ }
+ }
+ jscoverage_selectTab(0);
+}
+
+/**
+Selects a tab.
+@param tab the integer index of the tab (0, 1, 2, or 3)
+ OR
+ the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_selectTab(tab) {
+ if (typeof tab !== 'number') {
+ tab = jscoverage_tabIndexOf(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var tabPages = document.getElementById('tabPages');
+ var nodeList;
+ var tabNum;
+ var i;
+ var node;
+
+ nodeList = tabs.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (node.className !== 'disabled') {
+ if (tabNum === tab) {
+ node.className = 'selected';
+ }
+ else {
+ node.className = '';
+ }
+ }
+ tabNum++;
+ }
+
+ nodeList = tabPages.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (tabNum === tab) {
+ node.className = 'selected TabPage';
+ }
+ else {
+ node.className = 'TabPage';
+ }
+ tabNum++;
+ }
+}
+
+/**
+Returns an integer (0, 1, 2, or 3) representing the index of a given tab.
+@param tab the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_tabIndexOf(tab) {
+ if (typeof tab === 'string') {
+ tab = document.getElementById(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child === tab) {
+ return tabNum;
+ }
+ tabNum++;
+ }
+ }
+//#JSCOVERAGE_IF 0
+ throw "Tab not found";
+//#JSCOVERAGE_ENDIF
+}
+
+function jscoverage_tab_click(e) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ var target;
+//#JSCOVERAGE_IF
+ if (e) {
+ target = e.target;
+ }
+ else if (window.event) {
+ // IE
+ target = window.event.srcElement;
+ }
+ if (target.className === 'selected') {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ if (target.id === 'summaryTab') {
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+ }
+ else if (target.id === 'sourceTab') {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ }
+ jscoverage_selectTab(target);
+ if (target.id === 'summaryTab') {
+ jscoverage_recalculateSummaryTab();
+ }
+ else if (target.id === 'sourceTab') {
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ jscoverage_endLengthyOperation();
+ }
+ }, 50);
+}
+
+// -----------------------------------------------------------------------------
+// progress bar
+
+var ProgressBar = {
+ init: function(element) {
+ element._percentage = 0;
+
+ /* doing this via JavaScript crashes Safari */
+/*
+ var pctGraph = document.createElement('div');
+ pctGraph.className = 'pctGraph';
+ element.appendChild(pctGraph);
+ var covered = document.createElement('div');
+ covered.className = 'covered';
+ pctGraph.appendChild(covered);
+ var pct = document.createElement('span');
+ pct.className = 'pct';
+ element.appendChild(pct);
+*/
+
+ ProgressBar._update(element);
+ },
+ setPercentage: function(element, percentage) {
+ element._percentage = percentage;
+ ProgressBar._update(element);
+ },
+ _update: function(element) {
+ var pctGraph = element.getElementsByTagName('div').item(0);
+ var covered = pctGraph.getElementsByTagName('div').item(0);
+ var pct = element.getElementsByTagName('span').item(0);
+ pct.innerHTML = element._percentage.toString() + '%';
+ covered.style.width = element._percentage + 'px';
+ }
+};
+
+// -----------------------------------------------------------------------------
+// reports
+
+function jscoverage_pad(s) {
+ return '0000'.substr(s.length) + s;
+}
+
+function jscoverage_quote(s) {
+ return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) {
+ switch (c) {
+ case '\b':
+ return '\\b';
+ case '\f':
+ return '\\f';
+ case '\n':
+ return '\\n';
+ case '\r':
+ return '\\r';
+ case '\t':
+ return '\\t';
+ // IE doesn't support this
+ /*
+ case '\v':
+ return '\\v';
+ */
+ case '"':
+ return '\\"';
+ case '\\':
+ return '\\\\';
+ default:
+ return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16));
+ }
+ }) + '"';
+}
+
+function jscoverage_serializeCoverageToJSON() {
+ var json = [];
+ for (var file in _$jscoverage) {
+ var coverage = _$jscoverage[file];
+ var array = [];
+ var length = coverage.length;
+ for (var line = 0; line < length; line++) {
+ var value = coverage[line];
+ if (value === undefined || value === null) {
+ value = 'null';
+ }
+ array.push(value);
+ }
+ json.push(jscoverage_quote(file) + ':[' + array.join(',') + ']');
+ }
+ return '{' + json.join(',') + '}';
+}
+
+function jscoverage_storeButton_click() {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+
+ jscoverage_beginLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'visible';
+
+ var request = jscoverage_createRequest();
+ request.open('POST', '/jscoverage-store', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ var message;
+ try {
+ if (request.status !== 200 && request.status !== 201 && request.status !== 204) {
+ throw request.status;
+ }
+ message = request.responseText;
+ }
+ catch (e) {
+ if (e.toString().search(/^\d{3}$/) === 0) {
+ message = e + ': ' + request.responseText;
+ }
+ else {
+ message = 'Could not connect to server: ' + e;
+ }
+ }
+
+ jscoverage_endLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'hidden';
+
+ var div = document.getElementById('storeDiv');
+ div.appendChild(document.createTextNode(new Date() + ': ' + message));
+ div.appendChild(document.createElement('br'));
+ }
+ };
+ request.setRequestHeader('Content-Type', 'application/json');
+ var json = jscoverage_serializeCoverageToJSON();
+ request.setRequestHeader('Content-Length', json.length.toString());
+ request.send(json);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/script.js b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/script.js
new file mode 100644
index 0000000..ac233a2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/script.js
@@ -0,0 +1,65 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['script.js']) {
+ _$jscoverage['script.js'] = [];
+ _$jscoverage['script.js'][1] = 0;
+ _$jscoverage['script.js'][2] = 0;
+ _$jscoverage['script.js'][3] = 0;
+ _$jscoverage['script.js'][4] = 0;
+ _$jscoverage['script.js'][6] = 0;
+ _$jscoverage['script.js'][7] = 0;
+ _$jscoverage['script.js'][9] = 0;
+ _$jscoverage['script.js'][10] = 0;
+ _$jscoverage['script.js'][12] = 0;
+ _$jscoverage['script.js'][13] = 0;
+ _$jscoverage['script.js'][15] = 0;
+ _$jscoverage['script.js'][16] = 0;
+ _$jscoverage['script.js'][17] = 0;
+ _$jscoverage['script.js'][18] = 0;
+ _$jscoverage['script.js'][19] = 0;
+}
+_$jscoverage['script.js'][1]++;
+function go(element) {
+ _$jscoverage['script.js'][2]++;
+ var message;
+ _$jscoverage['script.js'][3]++;
+ if (element.id === "radio1") {
+ _$jscoverage['script.js'][4]++;
+ message = "You selected the number 1.";
+ }
+ else {
+ _$jscoverage['script.js'][6]++;
+ if (element.id === "radio2") {
+ _$jscoverage['script.js'][7]++;
+ message = "You selected the number 2.";
+ }
+ else {
+ _$jscoverage['script.js'][9]++;
+ if (element.id === "radio3") {
+ _$jscoverage['script.js'][10]++;
+ message = "You selected the number 3.";
+ }
+ else {
+ _$jscoverage['script.js'][12]++;
+ if (element.id === "radio4") {
+ _$jscoverage['script.js'][13]++;
+ message = "You selected the number 4.";
+ }
+ }
+ }
+ }
+ _$jscoverage['script.js'][15]++;
+ var div = document.getElementById("request");
+ _$jscoverage['script.js'][16]++;
+ div.className = "black";
+ _$jscoverage['script.js'][17]++;
+ div = document.getElementById("result");
+ _$jscoverage['script.js'][18]++;
+ div.innerHTML = "<p>" + message + "</p>";
+ _$jscoverage['script.js'][19]++;
+ div.innerHTML += "<p>If you are running the instrumented version of this program, you can click the \"Summary\" tab to view a coverage report.</p>";
+}
+_$jscoverage['script.js'].source = ["<span class=\"k\">function</span> go<span class=\"k\">(</span>element<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> message<span class=\"k\">;</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio1'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 1.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio2'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 2.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio3'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 3.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio4'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 4.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">var</span> div <span class=\"k\">=</span> document<span class=\"k\">.</span>getElementById<span class=\"k\">(</span><span class=\"s\">'request'</span><span class=\"k\">);</span>"," div<span class=\"k\">.</span>className <span class=\"k\">=</span> <span class=\"s\">'black'</span><span class=\"k\">;</span>"," div <span class=\"k\">=</span> document<span class=\"k\">.</span>getElementById<span class=\"k\">(</span><span class=\"s\">'result'</span><span class=\"k\">);</span>"," div<span class=\"k\">.</span>innerHTML <span class=\"k\">=</span> <span class=\"s\">'&lt;p&gt;'</span> <span class=\"k\">+</span> message <span class=\"k\">+</span> <span class=\"s\">'&lt;/p&gt;'</span><span class=\"k\">;</span>"," div<span class=\"k\">.</span>innerHTML <span class=\"k\">+=</span> <span class=\"s\">'&lt;p&gt;If you are running the instrumented version of this program, you can click the \"Summary\" tab to view a coverage report.&lt;/p&gt;'</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/license.html b/tools/node_modules/expresso/deps/jscoverage/doc/license.html
new file mode 100644
index 0000000..0acc7a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/license.html
@@ -0,0 +1,382 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - license</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+<h2>License</h2>
+<pre>
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ &lt;one line to give the program's name and a brief idea of what it does.&gt;
+ Copyright (C) &lt;year&gt; &lt;name of author&gt;
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ &lt;signature of Ty Coon&gt;, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+</pre>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li>License
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/links.html b/tools/node_modules/expresso/deps/jscoverage/doc/links.html
new file mode 100644
index 0000000..df6d793
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/links.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - links</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <h2>Links</h2>
+ <p>
+ The design of JSCoverage has been influenced by other code coverage tools:
+ </p>
+ <dl>
+ <dt><a href="http://gcc.gnu.org/onlinedocs/gcc/Gcov.html">gcov</a>
+ <dd>Code coverage for C/C++.
+ <dt><a href="http://cobertura.sourceforge.net/">Cobertura</a>
+ <dd>Code coverage for Java.
+ <dt><a href="http://nedbatchelder.com/code/modules/coverage.html">coverage.py</a>
+ <dd>Code coverage for Python.
+ </dl>
+ <p>
+ The implementation of JSCoverage includes the following libraries:
+ </p>
+ <dl>
+ <dt><a href="https://developer.mozilla.org/en/SpiderMonkey">Mozilla SpiderMonkey</a>
+ <dd>JSCoverage uses Mozilla's JavaScript implementation to parse JavaScript.
+ </dl>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li>Links
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/manual.html b/tools/node_modules/expresso/deps/jscoverage/doc/manual.html
new file mode 100644
index 0000000..61d8e9e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/manual.html
@@ -0,0 +1,701 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage user manual</title>
+<link rel="stylesheet" type="text/css" href="sh_nedit.min.css">
+<link rel="stylesheet" type="text/css" href="doc.css">
+<script type="text/javascript" src="sh_main.min.js"></script>
+<script type="text/javascript" src="sh_html.min.js"></script>
+<script type="text/javascript" src="sh_javascript.min.js"></script>
+</head>
+<body onload="sh_highlightDocument();">
+
+<h1>JSCoverage user manual</h1>
+
+<p>
+JSCoverage is a tool that measures code coverage for JavaScript programs.
+</p>
+
+<p>
+JSCoverage works by adding instrumentation to JavaScript code before it is
+executed in a web browser. JSCoverage provides several alternative ways of doing
+this:
+</p>
+
+<ul>
+<li>The simplest method is to use the <code>jscoverage</code> program to generate
+instrumented JavaScript files.
+</li>
+<li>Alternatively, you can use the <code>jscoverage-server</code> program, a simple web server that instruments
+JavaScript code as it is served.
+</li>
+<li>Finally, <code>jscoverage-server</code> can be run with the <code>--proxy</code> option to
+act as a proxy server which instruments any JavaScript code proxied through it.
+</li>
+</ul>
+
+<p>
+The <code>jscoverage-server</code> program (with or without the <code>--proxy</code>
+option) has the advantage of being able to store coverage reports to the filesystem.
+</p>
+
+<h2>Compiling JSCoverage</h2>
+
+<p>
+You can compile JSCoverage on GNU/Linux or Microsoft Windows, using the GCC C++ compiler (<code>g++</code>). On
+Windows you will require <a href="http://cygwin.com/">Cygwin</a> or <a
+href="http://mingw.org/">MinGW/MSYS</a>.
+</p>
+
+<p>
+You can extract and compile the code with the following commands:
+</p>
+
+<pre>
+tar jxvf jscoverage-0.4.tar.bz2
+cd jscoverage-0.4/
+./configure
+make
+</pre>
+
+<p>
+This will create the <code>jscoverage</code> and <code>jscoverage-server</code>
+executables (<code>jscoverage.exe</code> and <code>jscoverage-server.exe</code>
+on Windows). You can install the executables in <code>/usr/local</code> with the
+command:
+</p>
+
+<pre>
+make install
+</pre>
+
+<p>
+Alternatively, you may simply copy the <code>jscoverage</code> executable and/or
+the <code>jscoverage-server</code> executable to a suitable location in your
+<code>PATH</code>.
+</p>
+
+<h2>Using the <code>jscoverage</code> program</h2>
+
+<p>
+To demonstrate how the <code>jscoverage</code> program works, we will use the
+trivial example JavaScript code located in the
+<code>doc/example/</code> directory of the JSCoverage distribution. You can run
+this example by viewing the file <code>doc/example/index.html</code> in your web browser.
+</p>
+
+<p>
+Generating code coverage statistics for this example using the
+<code>jscoverage</code> program involves the following steps:
+</p>
+
+<h3>1. Instrumenting code</h3>
+
+<p>
+The first step is to add instrumentation to your JavaScript code. You do this by
+executing <code>jscoverage</code> with two arguments:
+</p>
+
+<pre>
+jscoverage <var>SOURCE-DIRECTORY</var> <var>DESTINATION-DIRECTORY</var>
+</pre>
+
+<p>
+<var>SOURCE-DIRECTORY</var> is the directory containing the JavaScript code to be instrumented,
+and <var>DESTINATION-DIRECTORY</var> is the name of the
+directory to which <code>jscoverage</code> should output the instrumented code.
+The <code>jscoverage</code> program will create <var>DESTINATION-DIRECTORY</var> if necessary and (recursively) copy
+<var>SOURCE-DIRECTORY</var> to <var>DESTINATION-DIRECTORY</var>, instrumenting
+any files ending with a <code>.js</code> extension.
+</p>
+
+<p>
+The directory structure under <var>SOURCE-DIRECTORY</var> is preserved, so that if you have a file
+<code><var>SOURCE-DIRECTORY</var>/dir/index.html</code> referencing the script
+<code><var>SOURCE-DIRECTORY</var>/dir/script.js</code>, then
+<code>jscoverage</code> will create a copy of the HTML file at
+<code><var>DESTINATION-DIRECTORY</var>/dir/index.html</code> and an instrumented
+version of the script at
+<code><var>DESTINATION-DIRECTORY</var>/dir/script.js</code>.
+In addition, <code>jscoverage</code> creates a file called <code>jscoverage.html</code>
+which is used to execute the instrumented code.
+</p>
+
+<table>
+<tr>
+<td><pre>
+<var>SOURCE-DIRECTORY</var>/
+ dir/
+ index.html
+ script.js
+
+</pre></td>
+<td class="arrow">&rarr;</td>
+<td><pre>
+<var>DESTINATION-DIRECTORY</var>/
+ dir/
+ index.html
+ script.js [instrumented]
+ jscoverage.html
+</pre></td>
+</tr>
+</table>
+
+<p>
+For the example code in the <code>doc/example/</code> directory, you can execute the
+following command line from the top-level directory of the JSCoverage distribution:
+</p>
+
+<pre>
+jscoverage doc/example doc/instrumented
+</pre>
+
+<p>
+This will create the directory <code>doc/instrumented/</code> and place an
+instrumented copy of the code from <code>doc/example/</code> in
+<code>doc/instrumented/</code>.
+</p>
+
+<table>
+<tr>
+<td><pre>
+doc/example/
+ index.html
+ script.js
+
+</pre></td>
+<td class="arrow">&rarr;</td>
+<td><pre>
+doc/instrumented/
+ index.html
+ script.js [instrumented]
+ jscoverage.html
+</pre></td>
+</tr>
+</table>
+
+<h3>2. Executing the instrumented code in a web browser</h3>
+
+<p>
+Open the generated <code>jscoverage.html</code> file
+(<code>doc/instrumented/jscoverage.html</code>) in your web browser.
+The page contains a tabbed user interface:
+</p>
+
+<ul>
+<li>The "Browser" tab is used to display pages with instrumented scripts.
+<li>The "Summary" tab is used to display code coverage data.
+<li>The "Source" tab is used to display JavaScript code, showing the number of times
+each line of code was executed.
+<li>The "About" tab displays information about the current version of JSCoverage.
+</ul>
+
+<p><img src="screenshot.png" alt="Screenshot"></p>
+
+<p>
+The "Browser" tab contains an <code>&lt;iframe&gt;</code>, which is initially empty.
+You can load a page into this frame by
+entering its URL into the "URL" input field.
+You can load any page located in <code><var>DESTINATION-DIRECTORY</var>/</code>
+or a subdirectory underneath <code><var>DESTINATION-DIRECTORY</var>/</code>; loading a page
+from outside <code><var>DESTINATION-DIRECTORY</var>/</code>, or from a foreign web
+server, will give unexpected results.
+</p>
+
+<p>
+For example, you can load the file <code>doc/instrumented/index.html</code> by typing
+<code>index.html</code> in the "URL" input field (relative URLs are acceptable).
+</p>
+
+<p>
+Alternatively, you can load a page into the <code>&lt;iframe&gt;</code> by
+appending the page URL to the query string of the <code>jscoverage.html</code> URL.
+For example, appending <code>?index.html</code> to the <code>jscoverage.html</code> URL
+will cause the <code>index.html</code> file to be loaded automatically.
+</p>
+
+<p><img src="screenshot2.png" alt="Screenshot"></p>
+
+<p>
+For this example, the JavaScript does not execute automatically:
+you have to select one of the radio buttons to execute the code.
+</p>
+
+<p><img src="screenshot3.png" alt="Screenshot"></p>
+
+<h3>3. Generating a coverage report</h3>
+
+<p>
+Once the JavaScript code in the page in the "Browser" tab has been executed, click on
+the "Summary" tab. This will display the current code coverage statistics.
+</p>
+
+<p><img src="screenshot4.png" alt="Screenshot"></p>
+
+<p>
+You can click the checkbox to show a list of statements missed during execution.
+</p>
+
+<p><img src="screenshot5.png" alt="Screenshot"></p>
+
+<p>
+You can click one of the links to get a detailed view of a JavaScript source file.
+</p>
+
+<p><img src="screenshot6.png" alt="Screenshot"></p>
+
+<p>
+As long as you do not reload the
+<code>jscoverage.html</code> page, the coverage report statistics are
+cumulative. If you execute more JavaScript in the frame in the "Browser" tab (e.g., by clicking on a link to
+another scripted page, or by reloading the frame containing a scripted
+page) and switch to the "Summary" tab again,
+the coverage report will combine the statistics from the previous report with any newly generated statistics.
+Reloading <code>jscoverage.html</code> resets all code coverage statistics to zero.
+</p>
+
+<h2>Inverted mode</h2>
+
+<p>
+In some situations it may be difficult to execute your code within the
+JSCoverage "Browser" tab. For example, the code may assume that it is running in
+the top-level browser window, generating errors if it is executed from within a
+frame. JSCoverage has an alternative mode of operation, called <dfn>inverted
+mode</dfn>, which may be useful in this case.
+</p>
+
+<p>
+Normally you load <code>jscoverage.html</code> in your web browser, and in its
+"Browser" tab you launch your test code. In inverted mode, you do the
+opposite: you load your test page directly in your web browser, and from there
+you launch JSCoverage. To do this you need to add some code to your test page:
+</p>
+
+<pre class="sh_javascript">
+window.open('path/to/jscoverage.html');
+</pre>
+
+<p>
+The <code>"path/to/jscoverage.html"</code> should be a URL pointing to the
+location of the <code>jscoverage.html</code> file (remember, this will be in the
+top level of the <var>DESTINATION-DIRECTORY</var> you specified when running
+the <code>jscoverage</code> executable).
+</p>
+
+<p>
+You can place this code wherever you like in your page: for example, you could
+attach it to a button:
+</p>
+
+<pre class="sh_html">
+&lt;button onclick="window.open('path/to/jscoverage.html');"&gt;Coverage report&lt;/button&gt;
+</pre>
+
+<p>
+Note that you <em>must</em> use a <code>window.open</code> call; simply making a
+link to <code>jscoverage.html</code> is not sufficient.
+</p>
+
+<p>
+An example is located in the <code>doc/example-inverted</code> directory.
+You can instrument the code with the <code>jscoverage</code> program:
+</p>
+
+<pre>
+jscoverage doc/example-inverted doc/instrumented-inverted
+</pre>
+
+<p>
+You can load the page <code>doc/instrumented-inverted/index.html</code>
+directly in your web browser.
+From this page, you select one of the radio buttons and then click the "Coverage
+report" button to launch the JSCoverage report.
+</p>
+
+<p>
+Another example is located in the <code>doc/example-jsunit</code> directory.
+See the <a href="faq.html#jsunit">FAQ</a> for more information.
+</p>
+
+<h2><code>jscoverage</code> command line options</h2>
+
+<p>
+The <code>jscoverage</code> program accepts the following options:
+</p>
+
+<dl>
+<dt><code>-h</code>, <code>--help</code>
+<dd>Display a brief help message.
+<dt><code>-V</code>, <code>--version</code>
+<dd>Display the version of the program.
+<dt><code>-v</code>, <code>--verbose</code>
+<dd>Explain what is being done.
+<dt><code>--encoding=<var>ENCODING</var></code>
+<dd>Assume that all JavaScript files use the given character encoding. The
+default is ISO-8859-1.
+<dt><code>--exclude=<var>PATH</var></code>
+<dd>The command
+<pre>
+jscoverage --exclude=<var>PATH</var> <var>SOURCE-DIRECTORY</var> <var>DESTINATION-DIRECTORY</var>
+</pre>
+copies <var>SOURCE-DIRECTORY</var> to <var>DESTINATION-DIRECTORY</var>
+recursively, but does not copy <var>SOURCE-DIRECTORY</var>/<var>PATH</var>.
+<var>PATH</var> must be a complete path relative to <var>SOURCE-DIRECTORY</var>.
+<var>PATH</var> can be a file or a directory (in which case the directory and
+its entire contents are skipped). This option may be given multiple times.
+<dt><code>--js-version=<var>VERSION</var></code>
+<dd>Use the specified JavaScript version; valid values for <var>VERSION</var>
+are <code>1.0</code>, <code>1.1</code>, <code>1.2</code>, ..., <code>1.8</code>,
+or <code>ECMAv3</code> (the default).
+<dt><code>--no-highlight</code>
+<dd>Do not perform syntax highlighting of JavaScript code.
+<dt><code>--no-instrument=<var>PATH</var></code>
+<dd>The command
+<pre>
+jscoverage --no-instrument=<var>PATH</var> <var>SOURCE-DIRECTORY</var> <var>DESTINATION-DIRECTORY</var>
+</pre>
+copies <var>SOURCE-DIRECTORY</var> to <var>DESTINATION-DIRECTORY</var>
+recursively, but does not instrument any JavaScript code in
+<var>SOURCE-DIRECTORY</var>/<var>PATH</var>. <var>PATH</var> must be a complete
+path relative to <var>SOURCE-DIRECTORY</var>. <var>PATH</var> can be a
+(JavaScript) file or a directory (in which case any JavaScript files located
+anywhere underneath the directory are not instrumented). This option may be
+given multiple times.
+</dl>
+
+<h2>Query string options</h2>
+
+<p>
+When accessing <code>jscoverage.html</code> in a web browser, you may provide a
+query string consisting of options separated by ampersand (<code>&amp;</code>)
+or semicolon (<code>;</code>). Any option not containing an equals sign
+(<code>=</code>) is considered to be a URL which will be loaded in the "Browser"
+tab.
+</p>
+
+<dl>
+<dt><code>u=<var>URL</var></code>, <code>url=<var>URL</var></code>
+<dd>Load <var>URL</var> in the "Browser" tab. (This is the same as specifying
+an option without an equals sign.)
+<dt><code>m=<var>BOOLEAN</var></code>, <code>missing=<var>BOOLEAN</var></code>
+<dd>Determines whether to initially display the "Missing" column in the "Summary"
+tab. <var>BOOLEAN</var> can be
+<code>true</code>, <code>t</code>, <code>yes</code>, <code>y</code>, <code>on</code>, <code>1</code>
+(to display the "Missing" column), or
+<code>false</code>, <code>f</code>, <code>no</code>, <code>n</code>, <code>off</code>, <code>0</code>
+(to hide the "Missing" column). By default, the "Missing" column is not displayed.
+</dl>
+
+<h2>Using the <code>jscoverage-server</code> program</h2>
+
+<p>
+The <code>jscoverage-server</code> program is a simple web server. You can use
+<code>jscoverage-server</code> to serve files from the <code>doc/example/</code>
+directory:
+</p>
+
+<pre>
+ cd doc/example
+ jscoverage-server --verbose
+</pre>
+
+<p>
+Once the server is running, you can access the JSCoverage web interface by
+visiting the URL <code>http://127.0.0.1:8080/jscoverage.html</code>, and you can
+load the <code>doc/example/index.html</code> file by entering
+<code>index.html</code> in the "URL" input field. (Or you can do this all in
+one step by loading the URL
+<code>http://127.0.0.1:8080/jscoverage.html?index.html</code> in your web
+browser.) The
+<code>jscoverage-server</code> program automatically instruments any served
+JavaScript code, so that code coverage data will be gathered as the code is
+executed in your browser.
+</p>
+
+<p>
+The web interface is slightly different from that generated by the
+<code>jscoverage</code> program: it has a new tab named "Store".
+To store coverage data, click the "Store" tab.
+</p>
+
+<p><img src="screenshot7.png" alt="Screenshot"></p>
+
+<p>
+When you click the "Store Report" button, the coverage data will be saved to a directory named <code>jscoverage-report/</code>.
+You can view this stored report at any time by opening the file <code>jscoverage-report/jscoverage.html</code> in
+your web browser - you don't need the <code>jscoverage-server</code> running to access it.
+</p>
+
+<p>
+If you use the "Store" tab again to store coverage data, the new data will be merged with
+the previous data in the <code>jscoverage-report/</code> directory. This can be useful,
+for instance, if you wish to run a set of tests in different browsers and generate an
+aggregate report which combines the data for all of them.
+</p>
+
+<p>
+You can stop the server by running another instance of <code>jscoverage-server</code> with the
+<code>--shutdown</code> option:
+</p>
+
+<pre>
+ jscoverage-server --shutdown
+</pre>
+
+<h2>Using <code>jscoverage-server --proxy</code></h2>
+
+<p>
+To use <code>jscoverage-server</code> as a proxy server, use the <code>--proxy</code> option:
+</p>
+
+<pre>
+ jscoverage-server --verbose --proxy
+</pre>
+
+<p>
+Configure your browser to use an HTTP proxy with address 127.0.0.1 and port 8080.
+You can then generate code coverage data for a web page on the server <code>example.com</code>
+by accessing the JSCoverage web interface at the special URL <code>http://example.com/jscoverage.html</code>.
+Note that this URL is not provided by the <code>example.com</code> server; it is automatically generated
+by the proxy server whenever a URL with path <code>/jscoverage.html</code> is requested.
+</p>
+
+<h2><code>jscoverage-server</code> command line options</h2>
+
+<dl>
+<dt><code>-h</code>, <code>--help</code>
+<dd>Display a brief help message.
+<dt><code>-V</code>, <code>--version</code>
+<dd>Display the version of the program.
+<dt><code>-v</code>, <code>--verbose</code>
+<dd>Explain what is being done.
+<dt><code>--document-root=<var>PATH</var></code>
+<dd>Serve web content from the directory given by <var>PATH</var>. The default is
+the current directory. This option may not be given with the <code>--proxy</code> option.
+<dt><code>--encoding=<var>ENCODING</var></code>
+<dd>Assume that all JavaScript files use the given character encoding. The
+default is ISO-8859-1. Note that if you use the <code>--proxy</code> option, the
+character encoding will be determined from the <code>charset</code> parameter in
+the <code>Content-Type</code> HTTP header.
+<dt><code>--ip-address=<var>ADDRESS</var></code>
+<dd>Run the server on the IP address given by <var>ADDRESS</var>. The default is <code>127.0.0.1</code>. Specify
+<code>0.0.0.0</code> to use any address.
+<dt><code>--js-version=<var>VERSION</var></code>
+<dd>Use the specified JavaScript version; valid values for <var>VERSION</var>
+are <code>1.0</code>, <code>1.1</code>, <code>1.2</code>, ..., <code>1.8</code>,
+or <code>ECMAv3</code> (the default).
+<dt><code>--no-highlight</code>
+<dd>Do not perform syntax highlighting of JavaScript code.
+<dt><code>--no-instrument=<var>URL</var></code>
+<dd>Do not instrument JavaScript code from <var>URL</var>. If you are running <code>jscoverage-server</code>
+with the <code>--proxy</code> option, <var>URL</var> should be a full URL. For example:
+<pre>
+jscoverage-server --proxy --no-instrument=http://example.com/scripts/
+</pre>
+Without <code>--proxy</code>, <var>URL</var> should be only the path portion of a URL:
+<pre>
+jscoverage-server --no-instrument=/scripts/
+</pre>
+This option may be given multiple times.
+<dt><code>--port=<var>PORT</var></code>
+<dd>Run the server on the port given by <var>PORT</var>. The default is port 8080.
+<dt><code>--proxy</code>
+<dd>Run as a proxy server.
+<dt><code>--report-dir=<var>PATH</var></code>
+<dd>Use the directory given by <var>PATH</var> for storing coverage reports. The default is
+<code>jscoverage-report/</code> in the current directory.
+<dt><code>--shutdown</code>
+<dd>Stop a running instance of the server.
+</dl>
+
+<h2>Advanced topics</h2>
+
+<h3>Storing coverage reports programmatically</h3>
+
+<p>
+If you are executing a test suite using <code>jscoverage-server</code>, you can
+store a coverage report programmatically by having your test suite call the
+<code>jscoverage_report</code> function (automatically generated by
+<code>jscoverage-server</code>) after all your tests have finished running:
+</p>
+
+<pre class="sh_javascript">
+if (window.jscoverage_report) {
+ jscoverage_report();
+}
+</pre>
+
+<p>
+You can specify the name of the directory in which to store the report by
+passing the name as a parameter to the <code>jscoverage_report</code> function:
+</p>
+
+<pre class="sh_javascript">
+if (window.jscoverage_report) {
+ // determine the directory name based on the browser
+ var directory;
+ if (/MSIE/.test(navigator.userAgent)) {
+ directory = 'IE';
+ }
+ else {
+ directory = 'other';
+ }
+ jscoverage_report(directory);
+}
+</pre>
+
+<p>
+This directory will be a subdirectory under the <code>jscoverage-report/</code>
+directory (or whatever is specified with the <code>--report-dir</code> option).
+Using the above example, the report would be stored to either
+<code>jscoverage-report/IE/</code> or <code>jscoverage-report/other/</code>.
+</p>
+
+<p>
+It is not necessary that your test suite be executed within the
+<code>jscoverage.html</code> web interface to store a coverage report. The URL
+of the test suite can simply be loaded directly in a web browser.
+</p>
+
+<p>
+The example in <code>doc/example-jsunit/</code> demonstrates storing coverage
+reports programmatically.
+</p>
+
+<h3>Ignoring certain lines of code</h3>
+
+<p>
+Sometimes you may wish to exclude certain lines of code from coverage
+statistics. Some lines of code may be executed only in certain browsers; other
+lines should never be executed at all (they may be present only to detect
+programming errors). You can use specially formatted comments in your code to
+tell JSCoverage to ignore certain lines of code. These lines will not be
+included in the JSCoverage "Summary" tab; in the "Source" tab, these lines will
+be indicated with the color yellow.
+</p>
+
+<p>
+These comments take the following form:
+</p>
+
+<pre class="sh_javascript">
+//#JSCOVERAGE_IF <var>CONDITION</var>
+...
+//#JSCOVERAGE_ENDIF
+</pre>
+
+<p>
+The comment must be formatted exactly as shown: it must be a line comment
+starting with <code>//</code>, it must start in the first column, and it must be
+followed by <code>#JSCOVERAGE_IF</code> or <code>#JSCOVERAGE_ENDIF</code> in
+uppercase letters with no intervening white space.
+</p>
+
+<p>
+The <var>CONDITION</var> is an ordinary JavaScript expression; if this
+expression evaluates to <code>true</code>, then the lines of code between the
+<code>//#JSCOVERAGE_IF</code> and <code>//#JSCOVERAGE_ENDIF</code> comments are
+included in coverage statistics; otherwise, they are excluded from coverage
+statistics.
+</p>
+
+<p>
+For example:
+</p>
+
+<pre class="sh_javascript">
+function log(s) {
+ if (window.console) {
+//#JSCOVERAGE_IF window.console
+ console.log(s);
+//#JSCOVERAGE_ENDIF
+ }
+}
+</pre>
+
+<p>
+You can exclude code from coverage statistics unconditionally by using
+<code>#JSCOVERAGE_IF 0</code> or <code>#JSCOVERAGE_IF false</code>:
+</p>
+
+<pre class="sh_javascript">
+function f(x) {
+ if (x === null) {
+//#JSCOVERAGE_IF 0
+ throw 'error';
+//#JSCOVERAGE_ENDIF
+ }
+ ...
+</pre>
+
+<p>
+There is also a short form, which must appear on the line preceding an
+<code>if</code> statement:
+</p>
+
+<pre class="sh_javascript">
+//#JSCOVERAGE_IF
+if (...) {
+ ...
+}
+else if (...) {
+ ...
+}
+...
+else {
+ ...
+}
+</pre>
+
+<p>
+
+In this form, there is no condition on the <code>//#JSCOVERAGE_IF</code> line
+and no <code>//#JSCOVERAGE_ENDIF</code>. You use this form to tell JSCoverage
+that you expect only one branch of the <code>if</code> statement to be executed;
+coverage statistics will not be collected for the other branch(es). For
+example:
+</p>
+
+<pre class="sh_javascript">
+function log(s) {
+//#JSCOVERAGE_IF
+ if (window.console) {
+ console.log(s);
+ }
+ else if (window.opera) {
+ opera.postError(s);
+ }
+ else {
+ throw 'no logging function available';
+ }
+}
+</pre>
+
+<p>
+Currently, <code>//#JSCOVERAGE_IF</code> comments are not recorded in stored coverage reports.
+</p>
+
+<h2>Caveats</h2>
+
+<ul>
+<li>JSCoverage adds instrumentation to JavaScript code, which will slow down execution speed.
+Expect instrumented code to take at least twice as much time to run.
+<li>JSCoverage currently instruments only <code>.js</code> files; it does not instrument code in <code>&lt;script&gt;</code>
+elements in HTML files.
+<li>HTML files must use relative URLs to reference scripts. If you use an absolute URL, your page will reference
+the original uninstrumented script rather than the instrumented one, and no code coverage data will be collected.
+<li>JSCoverage instruments physical lines of code rather than logical JavaScript statements; it works bests with code
+that has exactly one statement per line. If you put multiple statements on a line, or split a line across two or more
+statements, you may get strange results.
+<li>JSCoverage uses frames. Some web pages that use frames may not function properly when run under JSCoverage, especially
+those which try to access the top-level frame (<code>window.top</code>, <code>target="_top"</code>, etc.).
+<li>JSCoverage is distributed without any warranty. See the <a href="license.html">license</a> for more details.
+</ul>
+
+<address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+</address>
+
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/news.html b/tools/node_modules/expresso/deps/jscoverage/doc/news.html
new file mode 100644
index 0000000..c51450f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/news.html
@@ -0,0 +1,214 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - news</title>
+<link rel="alternate" type="application/rss+xml" href="http://siliconforks.com/jscoverage/news.xml" title="RSS feed for JSCoverage">
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <h2>News <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a></h2>
+
+ <h3><a name="20081211">December 11, 2008 - JSCoverage 0.4</a></h3>
+ <p>
+ JSCoverage 0.4 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ This release includes many new features:
+ </p>
+ <ul class="list">
+ <li>
+ The new <code>jscoverage-server</code> program is provided as an
+ alternative to the <code>jscoverage</code> program. The
+ <code>jscoverage-server</code> program is a simple HTTP server which
+ instruments JavaScript code as it is served; this allows you to execute
+ JavaScript and gather code coverage statistics without a preliminary
+ step of creating instrumented code. The <code>jscoverage-server</code>
+ program can either serve files directly from the filesystem or run as a
+ proxy server (with the <code>--proxy</code> option), instrumenting
+ JavaScript provided by another web server.
+ <li>
+ Using <code>jscoverage-server</code>, coverage reports can now be stored
+ to the filesystem.
+ </li>
+ <li>
+ JSCoverage now recognizes special JavaScript comments which specify that
+ certain lines of code should be ignored in coverage reports.
+ </li>
+ <li>
+ The new <code>--encoding</code> option provides better support for
+ different character encodings.
+ </li>
+ <li>
+ The JSCoverage user interface is now faster and more responsive.
+ </li>
+ <li>
+ The new <code>--no-highlight</code> option can be used to disable syntax
+ highlighting (giving better performance for large JavaScript files).
+ </li>
+ <li>
+ The build system has been modified so that <code>make install</code>
+ only installs the <code>jscoverage</code> and
+ <code>jscoverage-server</code> executables and their manual pages.
+ (Previous versions installed SpiderMonkey library and executable files,
+ which could conflict with other versions of SpiderMonkey installed on
+ your system.)
+ </li>
+ <li>
+ JSCoverage now supports several features beyond those found in the
+ <cite>ECMAScript Language Specification</cite>, including the following:
+ <ul class="list">
+ <li>getters and setters
+ <li><code>for each</code> loops
+ <li>generators and iterators
+ <li>the <code>let</code> keyword
+ <li>destructuring assignment
+ <li>array comprehensions
+ <li>expression closures
+ <li>generator expressions
+ </ul>
+ Use the new <code>--js-version</code> option to enable these features.
+ </li>
+ </ul>
+ <p>
+ The GCC C++ compiler (<code>g++</code>) is now required to compile
+ JSCoverage. (Previously, only the C compiler was needed.)
+ </p>
+ <p>
+ Please report any bugs you find using the new <a href="http://siliconforks.com/jscoverage/bugs/">bug tracker</a>.
+ </p>
+
+ <h3><a name="20080331">March 31, 2008 - JSCoverage and Firefox 3</a></h3>
+ <p>
+ The <a href="faq.html">JSCoverage FAQ</a> has been updated to address problems using JSCoverage with Firefox 3.
+ </p>
+
+ <h3><a name="20080324">March 24, 2008 - JSCoverage in Debian GNU/Linux</a></h3>
+ <p>
+ JSCoverage is now <a href="http://packages.debian.org/sid/jscoverage">available</a> in the Debian unstable distribution.
+ </p>
+
+ <h3><a name="20071122">November 22, 2007 - JSCoverage 0.3.1</a></h3>
+ <p>
+ JSCoverage 0.3.1 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ This release has a number of bug fixes:
+ </p>
+ <ul class="list">
+ <li>
+ It should now be possible to run the native Windows version of <code>jscoverage</code>
+ with minimal privileges.
+ </li>
+ <li>
+ All files used by JSCoverage now use a <code>jscoverage</code>
+ prefix to avoid name collisions.
+ </li>
+ <li>
+ Compilation bugs which occurred under some versions of MSYS have been fixed.
+ </li>
+ <li>
+ Various documentation improvements.
+ </li>
+ </ul>
+
+ <h3><a name="20070826">August 26, 2007 - JSCoverage 0.3</a></h3>
+ <p>
+ JSCoverage 0.3 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ This release has the following new features:
+ </p>
+ <ul class="list">
+ <li>
+ The coverage summary now displays bar graphs (thanks to Ross Simpson).
+ </li>
+ <li>
+ A progress bar is displayed for lengthy computations.
+ </li>
+ <li>
+ JavaScript syntax highlighting has improved.
+ </li>
+ <li>
+ The display of missed statements can be turned on and off.
+ </li>
+ <li>
+ New "inverted mode" provides better support for working with <a href="http://www.jsunit.net/">JsUnit</a>.
+ </li>
+ </ul>
+
+ <h3><a name="20070823">August 23, 2007 - JSCoverage in Linux Format magazine</a></h3>
+ <p>
+ JSCoverage is in the October 2007 issue of Linux Format magazine
+ (<a href="http://www.linuxformat.co.uk/modules.php?op=modload&amp;name=NewArchives&amp;issue=97">table of contents</a>).
+ </p>
+
+ <h3><a name="20070731">July 31, 2007 - Subversion repository now available</a></h3>
+ <p>
+ See the <a href="http://siliconforks.com/jscoverage/download.html">download page</a> for instructions on accessing the Subversion repository.
+ </p>
+
+ <h3><a name="20070708">July 8, 2007 - JSCoverage 0.2</a></h3>
+ <p>
+ JSCoverage 0.2 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ JSCoverage 0.2 features a new tabbed user interface.
+ </p>
+
+ <h3><a name="20070701">July 1, 2007 - JSCoverage 0.1.1</a></h3>
+ <p>
+ JSCoverage 0.1.1 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ JSCoverage 0.1.1 fixes a bug that can cause large JavaScript files to be truncated when viewed with Opera.
+ </p>
+
+ <h3><a name="20070615">June 15, 2007 - documentation of JSCoverage internals</a></h3>
+ <p>
+ A new document,
+ <a href="http://siliconforks.com/doc/parsing-javascript-with-spidermonkey/">Parsing JavaScript with SpiderMonkey</a>,
+ describes the technique used by JSCoverage to parse JavaScript programs.
+ </p>
+
+ <h3><a name="20070530">May 30, 2007 - new examples</a></h3>
+ <p>
+ Added some <a href="demo.html">examples</a> of running JSCoverage on popular JavaScript libraries.
+ </p>
+
+ <h3><a name="20070526">May 26, 2007 - JSCoverage 0.1</a></h3>
+ <p>
+ JSCoverage 0.1 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li>News <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/reset-fonts-grids.css b/tools/node_modules/expresso/deps/jscoverage/doc/reset-fonts-grids.css
new file mode 100644
index 0000000..b3e042c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/reset-fonts-grids.css
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2008, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.6.0
+*/
+html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}del,ins{text-decoration:none;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}body{text-align:center;}#ft{clear:both;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;min-width:750px;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main,.yui-g .yui-u .yui-g{width:100%;}{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-g .yui-u{width:48.1%;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;} .yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#bd:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#bd,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot.png
new file mode 100644
index 0000000..e523c8a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot2.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot2.png
new file mode 100644
index 0000000..2c02f49
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot2.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot3.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot3.png
new file mode 100644
index 0000000..d63c862
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot3.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot4.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot4.png
new file mode 100644
index 0000000..0dc234b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot4.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot5.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot5.png
new file mode 100644
index 0000000..ffbfabe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot5.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot6.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot6.png
new file mode 100644
index 0000000..b2c09d4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot6.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot7.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot7.png
new file mode 100644
index 0000000..2d51202
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot7.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/sh_html.min.js b/tools/node_modules/expresso/deps/jscoverage/doc/sh_html.min.js
new file mode 100644
index 0000000..64472a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/sh_html.min.js
@@ -0,0 +1 @@
+if(!this.sh_languages){this.sh_languages={}}sh_languages.html=[[[/<\?xml/g,"sh_preproc",1,1],[/<!DOCTYPE/g,"sh_preproc",3,1],[/<!--/g,"sh_comment",5],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",6,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",8,1]],[[/\?>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",2]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",4]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/-->/g,"sh_comment",-2],[/<!--/g,"sh_comment",5]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",7]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",9]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]]]; \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/sh_javascript.min.js b/tools/node_modules/expresso/deps/jscoverage/doc/sh_javascript.min.js
new file mode 100644
index 0000000..a7d930e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/sh_javascript.min.js
@@ -0,0 +1 @@
+if(!this.sh_languages){this.sh_languages={}}sh_languages.javascript=[[[/\/(?:\\.|[^*\\\/])(?:\\.|[^\\\/])*\/[gim]*(?![*\/])/g,"sh_regexp",-1],[/\b(?:import|package)\b/g,"sh_preproc",-1],[/\/\/\//g,"sh_comment",1],[/\/\//g,"sh_comment",11],[/\/\*\*/g,"sh_comment",12],[/\/\*/g,"sh_comment",22],[/\b[+-]?(?:(?:0x[A-Fa-f0-9]+)|(?:(?:[\d]*\.)?[\d]+(?:[eE][+-]?[\d]+)?))u?(?:(?:int(?:8|16|32|64))|L)?\b/g,"sh_number",-1],[/"/g,"sh_string",23],[/'/g,"sh_string",24],[/(\b(?:class|interface))([ \t]+)([$A-Za-z0-9_]+)/g,["sh_keyword","sh_normal","sh_classname"],-1],[/\b(?:abstract|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|final|finally|for|function|goto|if|implements|in|instanceof|interface|native|new|null|private|protected|prototype|public|return|static|super|switch|synchronized|throw|throws|this|transient|true|try|typeof|var|volatile|while|with)\b/g,"sh_keyword",-1],[/\b(?:int|byte|boolean|char|long|float|double|short|void)\b/g,"sh_type",-1],[/~|!|%|\^|\*|\(|\)|-|\+|=|\[|\]|\\|:|;|,|\.|\/|\?|&|<|>|\|/g,"sh_symbol",-1],[/\{|\}/g,"sh_cbracket",-1],[/(?:[A-Za-z]|_)[A-Za-z0-9_]*(?=[ \t]*\()/g,"sh_function",-1]],[[/$/g,null,-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/<\?xml/g,"sh_preproc",2,1],[/<!DOCTYPE/g,"sh_preproc",4,1],[/<!--/g,"sh_comment",6],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",7,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",9,1],[/@[A-Za-z]+/g,"sh_type",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]],[[/\?>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",3]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",5]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/-->/g,"sh_comment",-2],[/<!--/g,"sh_comment",6]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",8]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",10]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/$/g,null,-2]],[[/\*\//g,"sh_comment",-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/<\?xml/g,"sh_preproc",13,1],[/<!DOCTYPE/g,"sh_preproc",15,1],[/<!--/g,"sh_comment",17],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",18,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",20,1],[/@[A-Za-z]+/g,"sh_type",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]],[[/\?>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",14]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",16]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/-->/g,"sh_comment",-2],[/<!--/g,"sh_comment",17]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",19]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",21]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/\*\//g,"sh_comment",-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]],[[/"/g,"sh_string",-2],[/\\./g,"sh_specialchar",-1]],[[/'/g,"sh_string",-2],[/\\./g,"sh_specialchar",-1]]]; \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/sh_main.min.js b/tools/node_modules/expresso/deps/jscoverage/doc/sh_main.min.js
new file mode 100644
index 0000000..5f5f944
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/sh_main.min.js
@@ -0,0 +1,4 @@
+/* Copyright (C) 2007, 2008 gnombat@users.sourceforge.net */
+/* License: http://shjs.sourceforge.net/doc/gplv3.html */
+
+if(!this.sh_languages){this.sh_languages={}}var sh_requests={};function sh_isEmailAddress(A){if(/^mailto:/.test(A)){return false}return A.indexOf("@")!==-1}function sh_setHref(B,C,D){var A=D.substring(B[C-2].pos,B[C-1].pos);if(A.length>=2&&A.charAt(0)==="<"&&A.charAt(A.length-1)===">"){A=A.substr(1,A.length-2)}if(sh_isEmailAddress(A)){A="mailto:"+A}B[C-2].node.href=A}function sh_konquerorExec(B){var A=[""];A.index=B.length;A.input=B;return A}function sh_highlightString(V,L){if(/Konqueror/.test(navigator.userAgent)){if(!L.konquered){for(var b=0;b<L.length;b++){for(var d=0;d<L[b].length;d++){var c=L[b][d][0];if(c.source==="$"){c.exec=sh_konquerorExec}}}L.konquered=true}}var k=document.createElement("a");var M=document.createElement("span");var U=[];var H=0;var K=[];var W=0;var I=null;var R=function(i,a){var m=i.length;if(m===0){return }if(!a){var p=K.length;if(p!==0){var n=K[p-1];if(!n[3]){a=n[1]}}}if(I!==a){if(I){U[H++]={pos:W};if(I==="sh_url"){sh_setHref(U,H,V)}}if(a){var o;if(a==="sh_url"){o=k.cloneNode(false)}else{o=M.cloneNode(false)}o.className=a;U[H++]={node:o,pos:W}}}W+=m;I=a};var N=/\r\n|\r|\n/g;N.lastIndex=0;var C=V.length;var j=[];while(W<C){var P=W;var J;var Q;var G=N.exec(V);if(G===null){J=C;Q=C}else{J=G.index;Q=N.lastIndex}var F=V.substring(P,J);var X=-1;for(;;){var e=W-P;var Y;var S=K.length;if(S===0){Y=0}else{Y=K[S-1][2]}var l=L[Y];var T=l.length;if(Y!==X){j.length=0}var Z=null;var O=-1;for(var g=0;g<T;g++){var E;if(Y===X&&g<j.length&&(j[g]===null||e<=j[g].index)){E=j[g]}else{var B=l[g][0];B.lastIndex=e;E=B.exec(F);j[g]=E}if(E!==null&&(Z===null||E.index<Z.index)){Z=E;O=g;if(E.index===e){break}}}X=Y;if(Z===null){R(F.substring(e),null);break}else{if(Z.index>e){R(F.substring(e,Z.index),null)}var D=l[O];var f=D[1];var A;if(f instanceof Array){for(var h=0;h<f.length;h++){A=Z[h+1];R(A,f[h])}}else{A=Z[0];R(A,f)}switch(D[2]){case -1:break;case -2:K.pop();break;case -3:K.length=0;break;default:K.push(D);break}}}if(I){U[H++]={pos:W};if(I==="sh_url"){sh_setHref(U,H,V)}I=null}W=Q}return U}function sh_getClasses(D){var A=[];var B=D.className;if(B&&B.length>0){var E=B.split(" ");for(var C=0;C<E.length;C++){if(E[C].length>0){A.push(E[C])}}}return A}function sh_addClass(C,A){var D=sh_getClasses(C);for(var B=0;B<D.length;B++){if(A.toLowerCase()===D[B].toLowerCase()){return }}D.push(A);C.className=D.join(" ")}function sh_extractTagsFromNodeList(C,A){var F=C.length;for(var D=0;D<F;D++){var E=C.item(D);switch(E.nodeType){case 1:if(E.nodeName.toLowerCase()==="br"){var B;if(/MSIE/.test(navigator.userAgent)){B="\r"}else{B="\n"}A.text.push(B);A.pos++}else{A.tags.push({node:E.cloneNode(false),pos:A.pos});sh_extractTagsFromNodeList(E.childNodes,A);A.tags.push({pos:A.pos})}break;case 3:case 4:A.text.push(E.data);A.pos+=E.length;break}}}function sh_extractTags(C,B){var A={};A.text=[];A.tags=B;A.pos=0;sh_extractTagsFromNodeList(C.childNodes,A);return A.text.join("")}function sh_mergeTags(D,F){var A=D.length;if(A===0){return F}var C=F.length;if(C===0){return D}var I=[];var E=0;var B=0;while(E<A&&B<C){var H=D[E];var G=F[B];if(H.pos<=G.pos){I.push(H);E++}else{I.push(G);if(F[B+1].pos<=H.pos){B++;I.push(F[B]);B++}else{I.push({pos:H.pos});F[B]={node:G.node.cloneNode(false),pos:H.pos}}}}while(E<A){I.push(D[E]);E++}while(B<C){I.push(F[B]);B++}return I}function sh_insertTags(K,H){var G=document;var L=document.createDocumentFragment();var E=0;var D=K.length;var B=0;var J=H.length;var C=L;while(B<J||E<D){var I;var A;if(E<D){I=K[E];A=I.pos}else{A=J}if(A<=B){if(I.node){var F=I.node;C.appendChild(F);C=F}else{C=C.parentNode}E++}else{C.appendChild(G.createTextNode(H.substring(B,A)));B=A}}return L}function sh_highlightElement(D,G){sh_addClass(D,"sh_sourceCode");var C=[];var E=sh_extractTags(D,C);var F=sh_highlightString(E,G);var B=sh_mergeTags(C,F);var A=sh_insertTags(B,E);while(D.hasChildNodes()){D.removeChild(D.firstChild)}D.appendChild(A)}function sh_getXMLHttpRequest(){if(window.ActiveXObject){return new ActiveXObject("Msxml2.XMLHTTP")}else{if(window.XMLHttpRequest){return new XMLHttpRequest()}}throw"No XMLHttpRequest implementation available"}function sh_load(language,element,prefix,suffix){if(language in sh_requests){sh_requests[language].push(element);return }sh_requests[language]=[element];var request=sh_getXMLHttpRequest();var url=prefix+"sh_"+language+suffix;request.open("GET",url,true);request.onreadystatechange=function(){if(request.readyState===4){try{if(!request.status||request.status===200){eval(request.responseText);var elements=sh_requests[language];for(var i=0;i<elements.length;i++){sh_highlightElement(elements[i],sh_languages[language])}}else{throw"HTTP error: status "+request.status}}finally{request=null}}};request.send(null)}function sh_highlightDocument(G,I){var B=document.getElementsByTagName("pre");for(var E=0;E<B.length;E++){var F=B.item(E);var A=sh_getClasses(F);for(var C=0;C<A.length;C++){var H=A[C].toLowerCase();if(H==="sh_sourcecode"){continue}if(H.substr(0,3)==="sh_"){var D=H.substring(3);if(D in sh_languages){sh_highlightElement(F,sh_languages[D])}else{if(typeof (G)==="string"&&typeof (I)==="string"){sh_load(D,F,G,I)}else{throw'Found <pre> element with class="'+H+'", but no such language exists'}}break}}}}; \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/sh_nedit.min.css b/tools/node_modules/expresso/deps/jscoverage/doc/sh_nedit.min.css
new file mode 100644
index 0000000..cf09093
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/sh_nedit.min.css
@@ -0,0 +1 @@
+pre.sh_sourceCode{background-color:#fff;color:#000;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_keyword{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_type{color:#a52a2a;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_string{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_regexp{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_specialchar{color:#2e8b57;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_comment{color:#000;font-weight:normal;font-style:italic;}pre.sh_sourceCode .sh_number{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_preproc{color:#27408b;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_symbol{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_function{color:#000;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_cbracket{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_url{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_date{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_time{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_file{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_ip{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_name{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_variable{color:#dda0dd;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_oldfile{color:#2e8b57;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_newfile{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_difflines{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_selector{color:#dda0dd;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_property{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_value{color:#006400;font-weight:normal;font-style:normal;} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/siliconforks-16x16.png b/tools/node_modules/expresso/deps/jscoverage/doc/siliconforks-16x16.png
new file mode 100644
index 0000000..c3684aa
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/siliconforks-16x16.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/style.css b/tools/node_modules/expresso/deps/jscoverage/doc/style.css
new file mode 100644
index 0000000..4681e69
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/style.css
@@ -0,0 +1,138 @@
+html {
+ background: #bfffbf;
+}
+h1 a {
+ color: black;
+ text-decoration: none;
+ font-size: 182%;
+ font-weight: bold;
+}
+span.h1 {
+ font-size: 182%;
+ font-weight: bold;
+}
+span.tag {
+ font-size: 85%;
+ font-style: italic;
+}
+h2 {
+ font-size: 136%;
+ font-weight: bold;
+ margin-bottom: 1em;
+}
+h3 {
+ font-size: 122%;
+ font-weight: bold;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+h4 {
+ font-size: 107%;
+ font-weight: bold;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+p {
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+p:first-child {
+ margin-top: 0;
+}
+div {
+ background: white;
+}
+div#doc3 {
+ font-size: 107%;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ border: 1px solid #aaa;
+}
+div#hd {
+ margin: 1em;
+}
+div#bd {
+ margin: 1em;
+ border-top: 1px solid #aaa;
+ border-bottom: 1px solid #aaa;
+ padding-top: 1em;
+ padding-bottom: 1em;
+}
+div#ft {
+ margin: 1em;
+}
+div#yui-main {
+
+}
+div#jscoverage-main {
+
+}
+div#jscoverage-sidebar {
+ border-left: 1px solid #aaa;
+ padding-left: 10px;
+}
+dd {
+ padding-left: 1em;
+}
+ul.list {
+ padding-left: 1em;
+}
+ul.list li {
+ display: list-item;
+ list-style-position: outside;
+ list-style-type: disc;
+}
+address {
+ font-style: italic;
+}
+em {
+ font-style: italic;
+}
+strong {
+ font-weight: bold;
+}
+var {
+ font-style: italic;
+}
+dfn {
+ font-style: italic;
+}
+cite {
+ font-style: italic;
+}
+abbr {
+ cursor: help;
+ border-bottom-width: 1px;
+ border-bottom-style: dotted;
+}
+img.icon {
+ vertical-align: middle;
+}
+
+/* tables */
+table {
+ border-collapse: collapse;
+}
+col {
+ border-left: 1px solid #d9d9d9;
+}
+col.first-col {
+ border-left-width: 0px;
+}
+thead {
+ border-bottom: 1px solid #666666;
+}
+th {
+ font-weight: normal;
+ text-align: left;
+}
+th, td {
+ padding-left: 5px;
+ padding-right: 5px;
+}
+.numeric {
+ text-align: right;
+}
+tr.odd td {
+ background-color: #e6ffe6;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/users.html b/tools/node_modules/expresso/deps/jscoverage/doc/users.html
new file mode 100644
index 0000000..57fa070
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/users.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - users</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+<h2>Who's using JSCoverage?</h2>
+<ul class="list">
+<li>The <a href="http://pokersource.info/">pokersource</a> online poker project has used JSCoverage in testing the
+<a href="http://jspoker.pokersource.info/">JavaScript client</a>
+<li><a href="http://github.com/nickstenning/micromvc/tree/master">MicroMVC</a>, a JavaScript Model-View-Controller framework
+<li>The <a href="http://kssproject.org/">KSS</a> Ajax framework
+<li><a href="http://knowledgeforge.net/project/microfacts/">Micro Facts</a>
+<li>The <a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/">jQuery Validation plugin</a>
+<li>The <a href="http://code.google.com/p/jqmock/">jqMock</a> JavaScript mock object framework
+<li>The <a href="http://www.mozilla.org/">Mozilla</a> project has used JSCoverage for instrumenting JavaScript code in <a href="http://www.mozilla.com/en-US/firefox/">Firefox</a>
+</ul>
+<p>
+If you, your project, or your company uses JSCoverage in testing your JavaScript
+code, please send email to <a
+href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a> so
+you can be added to this list. (It is not necessary that it be a Free
+Software/Open Source project.)
+</p>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li>Users
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/encoding.c b/tools/node_modules/expresso/deps/jscoverage/encoding.c
new file mode 100644
index 0000000..76b2f26
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/encoding.c
@@ -0,0 +1,315 @@
+/*
+ encoding.c - character encoding
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "encoding.h"
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+#ifdef HAVE_ICONV_H
+#include <iconv.h>
+#elif defined HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
+#include "util.h"
+
+static void skip_bom(jschar ** characters, size_t * num_characters) {
+ jschar * c = *characters;
+ size_t nc = *num_characters;
+
+ size_t i;
+ for (i = 0; i < nc; i++) {
+ if (c[i] != 0xfeff) {
+ break;
+ }
+ }
+
+ if (i == 0) {
+ return;
+ }
+
+ nc -= i;
+ jschar * old = c;
+ c = xnew(jschar, nc);
+ memcpy(c, old + i, nc * sizeof(jschar));
+ free(old);
+
+ *characters = c;
+ *num_characters = nc;
+}
+
+#ifdef HAVE_ICONV
+
+#ifdef WORDS_BIGENDIAN
+#define UTF_16_INTERNAL "UTF-16BE"
+#else
+#define UTF_16_INTERNAL "UTF-16LE"
+#endif
+
+int jscoverage_bytes_to_characters(const char * encoding, const uint8_t * bytes, size_t num_bytes, jschar ** characters, size_t * num_characters) {
+ assert(encoding != NULL);
+
+ iconv_t state = iconv_open(UTF_16_INTERNAL, encoding);
+ if (state == (iconv_t) -1) {
+ return JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED;
+ }
+
+ ICONV_CONST char * input = (char *) bytes;
+ size_t input_bytes_left = num_bytes;
+
+ jschar * c = xnew(jschar, num_bytes);
+ char * output = (char *) c;
+ size_t output_bytes_left = sizeof(jschar) * num_bytes;
+
+ size_t result = iconv(state, &input, &input_bytes_left, &output, &output_bytes_left);
+ iconv_close(state);
+ if (result == (size_t) -1) {
+ free(c);
+ return JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE;
+ }
+
+ assert(input_bytes_left == 0);
+
+ size_t nc = ((jschar *) output) - c;
+
+ skip_bom(&c, &nc);
+
+ *characters = c;
+ *num_characters = nc;
+ return 0;
+}
+
+#elif HAVE_MULTIBYTETOWIDECHAR
+
+/* http://msdn.microsoft.com/en-us/library/ms776446(VS.85).aspx */
+static struct CodePage {
+ UINT value;
+ LPCSTR string;
+} code_pages[] = {
+ {37, "IBM037"}, /* IBM EBCDIC US-Canada */
+ {437, "IBM437"}, /* OEM United States */
+ {500, "IBM500"}, /* IBM EBCDIC International */
+ {708, "ASMO-708"}, /* Arabic (ASMO 708) */
+ {720, "DOS-720"}, /* Arabic (Transparent ASMO); Arabic (DOS) */
+ {737, "ibm737"}, /* OEM Greek (formerly 437G); Greek (DOS) */
+ {775, "ibm775"}, /* OEM Baltic; Baltic (DOS) */
+ {850, "ibm850"}, /* OEM Multilingual Latin 1; Western European (DOS) */
+ {852, "ibm852"}, /* OEM Latin 2; Central European (DOS) */
+ {855, "IBM855"}, /* OEM Cyrillic (primarily Russian) */
+ {857, "ibm857"}, /* OEM Turkish; Turkish (DOS) */
+ {858, "IBM00858"}, /* OEM Multilingual Latin 1 + Euro symbol */
+ {860, "IBM860"}, /* OEM Portuguese; Portuguese (DOS) */
+ {861, "ibm861"}, /* OEM Icelandic; Icelandic (DOS) */
+ {862, "DOS-862"}, /* OEM Hebrew; Hebrew (DOS) */
+ {863, "IBM863"}, /* OEM French Canadian; French Canadian (DOS) */
+ {864, "IBM864"}, /* OEM Arabic; Arabic (864) */
+ {865, "IBM865"}, /* OEM Nordic; Nordic (DOS) */
+ {866, "cp866"}, /* OEM Russian; Cyrillic (DOS) */
+ {869, "ibm869"}, /* OEM Modern Greek; Greek, Modern (DOS) */
+ {870, "IBM870"}, /* IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2 */
+ {874, "windows-874"}, /* ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows) */
+ {875, "cp875"}, /* IBM EBCDIC Greek Modern */
+ {932, "shift_jis"}, /* ANSI/OEM Japanese; Japanese (Shift-JIS) */
+ {936, "gb2312"}, /* ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) */
+ {949, "ks_c_5601-1987"}, /* ANSI/OEM Korean (Unified Hangul Code) */
+ {950, "big5"}, /* ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5) */
+ {1026, "IBM1026"}, /* IBM EBCDIC Turkish (Latin 5) */
+ {1047, "IBM01047"}, /* IBM EBCDIC Latin 1/Open System */
+ {1140, "IBM01140"}, /* IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro) */
+ {1141, "IBM01141"}, /* IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro) */
+ {1142, "IBM01142"}, /* IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro) */
+ {1143, "IBM01143"}, /* IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro) */
+ {1144, "IBM01144"}, /* IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro) */
+ {1145, "IBM01145"}, /* IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro) */
+ {1146, "IBM01146"}, /* IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro) */
+ {1147, "IBM01147"}, /* IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro) */
+ {1148, "IBM01148"}, /* IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro) */
+ {1149, "IBM01149"}, /* IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro) */
+ {1200, "utf-16"}, /* Unicode UTF-16, little endian byte order (BMP of ISO 10646); available only to managed applications */
+ {1201, "unicodeFFFE"}, /* Unicode UTF-16, big endian byte order; available only to managed applications */
+ {1250, "windows-1250"}, /* ANSI Central European; Central European (Windows) */
+ {1251, "windows-1251"}, /* ANSI Cyrillic; Cyrillic (Windows) */
+ {1252, "windows-1252"}, /* ANSI Latin 1; Western European (Windows) */
+ {1253, "windows-1253"}, /* ANSI Greek; Greek (Windows) */
+ {1254, "windows-1254"}, /* ANSI Turkish; Turkish (Windows) */
+ {1255, "windows-1255"}, /* ANSI Hebrew; Hebrew (Windows) */
+ {1256, "windows-1256"}, /* ANSI Arabic; Arabic (Windows) */
+ {1257, "windows-1257"}, /* ANSI Baltic; Baltic (Windows) */
+ {1258, "windows-1258"}, /* ANSI/OEM Vietnamese; Vietnamese (Windows) */
+ {1361, "Johab"}, /* Korean (Johab) */
+ {10000, "macintosh"}, /* MAC Roman; Western European (Mac) */
+ {10001, "x-mac-japanese"}, /* Japanese (Mac) */
+ {10002, "x-mac-chinesetrad"}, /* MAC Traditional Chinese (Big5); Chinese Traditional (Mac) */
+ {10003, "x-mac-korean"}, /* Korean (Mac) */
+ {10004, "x-mac-arabic"}, /* Arabic (Mac) */
+ {10005, "x-mac-hebrew"}, /* Hebrew (Mac) */
+ {10006, "x-mac-greek"}, /* Greek (Mac) */
+ {10007, "x-mac-cyrillic"}, /* Cyrillic (Mac) */
+ {10008, "x-mac-chinesesimp"}, /* MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac) */
+ {10010, "x-mac-romanian"}, /* Romanian (Mac) */
+ {10017, "x-mac-ukrainian"}, /* Ukrainian (Mac) */
+ {10021, "x-mac-thai"}, /* Thai (Mac) */
+ {10029, "x-mac-ce"}, /* MAC Latin 2; Central European (Mac) */
+ {10079, "x-mac-icelandic"}, /* Icelandic (Mac) */
+ {10081, "x-mac-turkish"}, /* Turkish (Mac) */
+ {10082, "x-mac-croatian"}, /* Croatian (Mac) */
+ {12000, "utf-32"}, /* Unicode UTF-32, little endian byte order; available only to managed applications */
+ {12001, "utf-32BE"}, /* Unicode UTF-32, big endian byte order; available only to managed applications */
+ {20000, "x-Chinese_CNS"}, /* CNS Taiwan; Chinese Traditional (CNS) */
+ {20001, "x-cp20001"}, /* TCA Taiwan */
+ {20002, "x_Chinese-Eten"}, /* Eten Taiwan; Chinese Traditional (Eten) */
+ {20003, "x-cp20003"}, /* IBM5550 Taiwan */
+ {20004, "x-cp20004"}, /* TeleText Taiwan */
+ {20005, "x-cp20005"}, /* Wang Taiwan */
+ {20105, "x-IA5"}, /* IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5) */
+ {20106, "x-IA5-German"}, /* IA5 German (7-bit) */
+ {20107, "x-IA5-Swedish"}, /* IA5 Swedish (7-bit) */
+ {20108, "x-IA5-Norwegian"}, /* IA5 Norwegian (7-bit) */
+ {20127, "us-ascii"}, /* US-ASCII (7-bit) */
+ {20261, "x-cp20261"}, /* T.61 */
+ {20269, "x-cp20269"}, /* ISO 6937 Non-Spacing Accent */
+ {20273, "IBM273"}, /* IBM EBCDIC Germany */
+ {20277, "IBM277"}, /* IBM EBCDIC Denmark-Norway */
+ {20278, "IBM278"}, /* IBM EBCDIC Finland-Sweden */
+ {20280, "IBM280"}, /* IBM EBCDIC Italy */
+ {20284, "IBM284"}, /* IBM EBCDIC Latin America-Spain */
+ {20285, "IBM285"}, /* IBM EBCDIC United Kingdom */
+ {20290, "IBM290"}, /* IBM EBCDIC Japanese Katakana Extended */
+ {20297, "IBM297"}, /* IBM EBCDIC France */
+ {20420, "IBM420"}, /* IBM EBCDIC Arabic */
+ {20423, "IBM423"}, /* IBM EBCDIC Greek */
+ {20424, "IBM424"}, /* IBM EBCDIC Hebrew */
+ {20833, "x-EBCDIC-KoreanExtended"}, /* IBM EBCDIC Korean Extended */
+ {20838, "IBM-Thai"}, /* IBM EBCDIC Thai */
+ {20866, "koi8-r"}, /* Russian (KOI8-R); Cyrillic (KOI8-R) */
+ {20871, "IBM871"}, /* IBM EBCDIC Icelandic */
+ {20880, "IBM880"}, /* IBM EBCDIC Cyrillic Russian */
+ {20905, "IBM905"}, /* IBM EBCDIC Turkish */
+ {20924, "IBM00924"}, /* IBM EBCDIC Latin 1/Open System (1047 + Euro symbol) */
+ {20932, "EUC-JP"}, /* Japanese (JIS 0208-1990 and 0121-1990) */
+ {20936, "x-cp20936"}, /* Simplified Chinese (GB2312); Chinese Simplified (GB2312-80) */
+ {20949, "x-cp20949"}, /* Korean Wansung */
+ {21025, "cp1025"}, /* IBM EBCDIC Cyrillic Serbian-Bulgarian */
+ {21866, "koi8-u"}, /* Ukrainian (KOI8-U); Cyrillic (KOI8-U) */
+ {28591, "iso-8859-1"}, /* ISO 8859-1 Latin 1; Western European (ISO) */
+ {28592, "iso-8859-2"}, /* ISO 8859-2 Central European; Central European (ISO) */
+ {28593, "iso-8859-3"}, /* ISO 8859-3 Latin 3 */
+ {28594, "iso-8859-4"}, /* ISO 8859-4 Baltic */
+ {28595, "iso-8859-5"}, /* ISO 8859-5 Cyrillic */
+ {28596, "iso-8859-6"}, /* ISO 8859-6 Arabic */
+ {28597, "iso-8859-7"}, /* ISO 8859-7 Greek */
+ {28598, "iso-8859-8"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Visual) */
+ {28599, "iso-8859-9"}, /* ISO 8859-9 Turkish */
+ {28603, "iso-8859-13"}, /* ISO 8859-13 Estonian */
+ {28605, "iso-8859-15"}, /* ISO 8859-15 Latin 9 */
+ {29001, "x-Europa"}, /* Europa 3 */
+ {38598, "iso-8859-8-i"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Logical) */
+ {50220, "iso-2022-jp"}, /* ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS) */
+ {50221, "csISO2022JP"}, /* ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana) */
+ {50222, "iso-2022-jp"}, /* ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI) */
+ {50225, "iso-2022-kr"}, /* ISO 2022 Korean */
+ {50227, "x-cp50227"}, /* ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022) */
+ {51932, "euc-jp"}, /* EUC Japanese */
+ {51936, "EUC-CN"}, /* EUC Simplified Chinese; Chinese Simplified (EUC) */
+ {51949, "euc-kr"}, /* EUC Korean */
+ {52936, "hz-gb-2312"}, /* HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ) */
+ {54936, "GB18030"}, /* Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030) */
+ {57002, "x-iscii-de"}, /* ISCII Devanagari */
+ {57003, "x-iscii-be"}, /* ISCII Bengali */
+ {57004, "x-iscii-ta"}, /* ISCII Tamil */
+ {57005, "x-iscii-te"}, /* ISCII Telugu */
+ {57006, "x-iscii-as"}, /* ISCII Assamese */
+ {57007, "x-iscii-or"}, /* ISCII Oriya */
+ {57008, "x-iscii-ka"}, /* ISCII Kannada */
+ {57009, "x-iscii-ma"}, /* ISCII Malayalam */
+ {57010, "x-iscii-gu"}, /* ISCII Gujarati */
+ {57011, "x-iscii-pa"}, /* ISCII Punjabi */
+ {65000, "utf-7"}, /* Unicode (UTF-7) */
+ {65001, "utf-8"}, /* Unicode (UTF-8) */
+};
+
+int find_code_page(const char * encoding, UINT * code_page) {
+ for (size_t i = 0; i < sizeof(code_pages) / sizeof(code_pages[0]); i++) {
+ if (strcasecmp(encoding, code_pages[i].string) == 0) {
+ *code_page = code_pages[i].value;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int jscoverage_bytes_to_characters(const char * encoding, const uint8_t * bytes, size_t num_bytes, jschar ** characters, size_t * num_characters) {
+ assert(encoding != NULL);
+
+ if (num_bytes == 0) {
+ *characters = xnew(jschar, 0);
+ *num_characters = 0;
+ return 0;
+ }
+
+ UINT code_page;
+ if (find_code_page(encoding, &code_page) != 0) {
+ return JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED;
+ }
+
+ if (num_bytes > INT_MAX) {
+ fatal("overflow");
+ }
+
+ *characters = xnew(jschar, num_bytes);
+
+ int result = MultiByteToWideChar(code_page, MB_ERR_INVALID_CHARS, bytes, num_bytes, *characters, num_bytes);
+ if (result == 0) {
+ free(*characters);
+ return JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE;
+ }
+
+ *num_characters = result;
+ skip_bom(characters, num_characters);
+ return 0;
+}
+
+#else
+
+int jscoverage_bytes_to_characters(const char * encoding, const uint8_t * bytes, size_t num_bytes, jschar ** characters, size_t * num_characters) {
+ assert(encoding != NULL);
+
+ if (strcasecmp(encoding, "us-ascii") != 0 && strcasecmp(encoding, "iso-8859-1") != 0 && strcasecmp(encoding, "utf-8") != 0) {
+ return JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED;
+ }
+
+ jschar * c = xnew(jschar, num_bytes);
+ for (size_t i = 0; i < num_bytes; i++) {
+ if (bytes[i] > 127) {
+ free(c);
+ return JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED;
+ }
+ c[i] = bytes[i];
+ }
+
+ *characters = c;
+ *num_characters = num_bytes;
+ return 0;
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/encoding.h b/tools/node_modules/expresso/deps/jscoverage/encoding.h
new file mode 100644
index 0000000..0e4edbb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/encoding.h
@@ -0,0 +1,33 @@
+/*
+ encoding.h - character encoding
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef ENCODING_H_
+#define ENCODING_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <jsapi.h>
+
+#define JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED (-1)
+#define JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE (-2)
+
+int jscoverage_bytes_to_characters(const char * encoding, const uint8_t * bytes, size_t num_bytes, jschar ** characters, size_t * num_characters);
+
+#endif /* ENCODING_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/generate-resources b/tools/node_modules/expresso/deps/jscoverage/generate-resources
new file mode 100755
index 0000000..aa650cf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/generate-resources
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/generate-resources.c b/tools/node_modules/expresso/deps/jscoverage/generate-resources.c
new file mode 100644
index 0000000..adabf60
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/generate-resources.c
@@ -0,0 +1,58 @@
+/*
+ generate-resources.c - code generator for embedded resources
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/stat.h>
+
+int main(int argc, char ** argv) {
+ for (int i = 1; i < argc; i++) {
+ printf("const unsigned char RESOURCE%d_[] = {\n", i);
+ FILE * f = fopen(argv[i], "rb");
+ if (f == NULL) {
+ fprintf(stderr, "cannot open file %s\n", argv[i]);
+ exit(EXIT_FAILURE);
+ }
+ int c;
+ int j = 0;
+ while ((c = fgetc(f)) != EOF) {
+ if (j % 16 == 0) {
+ printf("\n ");
+ }
+ printf("0x%02x,", c);
+ j++;
+ }
+ fclose(f);
+ printf("\n};\n");
+ }
+
+ printf("const struct Resource RESOURCES[] = {\n");
+ for (int i = 1; i < argc; i++) {
+ printf(" {\n");
+ printf(" \"%s\",\n", argv[i]);
+ printf(" RESOURCE%d_,\n", i);
+ printf(" sizeof(RESOURCE%d_)\n", i);
+ printf(" },\n");
+ }
+ printf("};\n");
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/global.h b/tools/node_modules/expresso/deps/jscoverage/global.h
new file mode 100644
index 0000000..1384d12
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/global.h
@@ -0,0 +1,29 @@
+/*
+ global.h - global variables
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef GLOBAL_H_
+#define GLOBAL_H_
+
+#include <stdbool.h>
+
+extern const char * jscoverage_encoding;
+
+extern bool jscoverage_highlight;
+
+#endif /* GLOBAL_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/highlight.c b/tools/node_modules/expresso/deps/jscoverage/highlight.c
new file mode 100644
index 0000000..7dddf3b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/highlight.c
@@ -0,0 +1,478 @@
+/*
+ highlight.c - JavaScript syntax highlighting
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "highlight.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <jslock.h>
+#include <jsscan.h>
+
+#include "util.h"
+
+enum Class {
+ CLASS_NONE,
+ CLASS_COMMENT,
+ CLASS_REGEXP,
+ CLASS_NUMBER,
+ CLASS_STRING,
+ CLASS_SPECIALCHAR,
+ CLASS_KEYWORD,
+ CLASS_TYPE,
+ CLASS_SYMBOL,
+ CLASS_CBRACKET
+};
+
+static const char * get_class_name(enum Class class) {
+ switch (class) {
+ case CLASS_NONE:
+ abort();
+ break;
+ case CLASS_COMMENT:
+ return "c";
+ break;
+ case CLASS_REGEXP:
+ return "s";
+ break;
+ case CLASS_NUMBER:
+ return "s";
+ break;
+ case CLASS_STRING:
+ return "s";
+ break;
+ case CLASS_SPECIALCHAR:
+ return "t";
+ break;
+ case CLASS_KEYWORD:
+ return "k";
+ break;
+ case CLASS_TYPE:
+ return "k";
+ break;
+ case CLASS_SYMBOL:
+ return "k";
+ break;
+ case CLASS_CBRACKET:
+ return "k";
+ break;
+ default:
+ abort();
+ break;
+ }
+}
+
+static const char * g_id;
+static const jschar * g_characters;
+static size_t g_num_characters;
+static Stream * g_output;
+static size_t character_offset;
+static uint16_t line_num;
+static uint16_t column_num;
+static enum Class current_class;
+
+static void output_character(jschar c, enum Class class) {
+ if (c == '\r' || c == '\n' || c == 0x2028 || c == 0x2029) {
+ class = CLASS_NONE;
+ }
+
+ if (class != current_class) {
+ /* output the end tag */
+ if (current_class != CLASS_NONE) {
+ Stream_write_string(g_output, "</span>");
+ }
+
+ current_class = class;
+
+ /* output the start tag */
+ if (current_class != CLASS_NONE) {
+ Stream_printf(g_output, "<span class=\"%s\">", get_class_name(class));
+ }
+ }
+
+ if (column_num == UINT16_MAX) {
+ fatal("%s: script contains a line with more than 65,535 columns", g_id);
+ }
+ column_num++;
+ switch (c) {
+ case '&':
+ Stream_write_string(g_output, "&amp;");
+ break;
+ case '<':
+ Stream_write_string(g_output, "&lt;");
+ break;
+ case '>':
+ Stream_write_string(g_output, "&gt;");
+ break;
+ case '\t':
+ Stream_write_char(g_output, c);
+ break;
+ case '\r':
+ case '\n':
+ case 0x2028:
+ case 0x2029:
+ if (c == '\r' && character_offset + 1 < g_num_characters && g_characters[character_offset + 1] == '\n') {
+ break;
+ }
+ Stream_write_char(g_output, '\n');
+ column_num = 0;
+ if (line_num == UINT16_MAX) {
+ fatal("%s: script contains more than 65,535 lines", g_id);
+ }
+ line_num++;
+ break;
+ default:
+ if (32 <= c && c <= 126) {
+ Stream_write_char(g_output, c);
+ }
+ else {
+ Stream_printf(g_output, "&#%d;", c);
+ }
+ break;
+ }
+ character_offset++;
+}
+
+static void mark_nontoken_chars(uint16_t end_line, uint16_t end_column) {
+ enum State {
+ STATE_NORMAL,
+ STATE_LINE_COMMENT,
+ STATE_MULTILINE_COMMENT
+ };
+
+ enum State state = STATE_NORMAL;
+ while (character_offset < g_num_characters) {
+ if (end_line != 0 && line_num > end_line) {
+ break;
+ }
+ else if (line_num == end_line && column_num >= end_column) {
+ break;
+ }
+
+ jschar c = g_characters[character_offset];
+ if (c == '\0') {
+ fatal("%s: script contains NULL character", g_id);
+ }
+
+ switch (state) {
+ case STATE_NORMAL:
+ if (c == '/' && character_offset + 1 < g_num_characters && g_characters[character_offset + 1] == '/') {
+ state = STATE_LINE_COMMENT;
+ }
+ else if (c == '/' && character_offset + 1 < g_num_characters && g_characters[character_offset + 1] == '*') {
+ state = STATE_MULTILINE_COMMENT;
+ output_character('/', CLASS_COMMENT);
+ output_character('*', CLASS_COMMENT);
+ continue;
+ }
+ break;
+ case STATE_LINE_COMMENT:
+ if (c == '\r' || c == '\n' || c == 0x2028 || c == 0x2029) {
+ state = STATE_NORMAL;
+ }
+ break;
+ case STATE_MULTILINE_COMMENT:
+ if (c == '*' && character_offset + 1 < g_num_characters && g_characters[character_offset + 1] == '/') {
+ output_character('*', CLASS_COMMENT);
+ output_character('/', CLASS_COMMENT);
+ state = STATE_NORMAL;
+ continue;
+ }
+ break;
+ }
+
+ if (state == STATE_NORMAL) {
+ output_character(c, CLASS_NONE);
+ }
+ else {
+ output_character(c, CLASS_COMMENT);
+ }
+ }
+}
+
+void jscoverage_highlight_js(JSContext * context, const char * id, const jschar * characters, size_t num_characters, Stream * output) {
+ g_id = id;
+ g_characters = characters;
+ g_num_characters = num_characters;
+ g_output = output;
+
+ character_offset = 0;
+ line_num = 1;
+ column_num = 0;
+ current_class = CLASS_NONE;
+
+ /* tokenize the JavaScript */
+ JSTokenStream token_stream;
+ if (! js_InitTokenStream(context, &token_stream, characters, num_characters, NULL, NULL, 1)) {
+ fatal("cannot create token stream from JavaScript file %s", id);
+ }
+
+ for (;;) {
+ JSTokenType tt = js_GetToken(context, &token_stream);
+
+ if (tt == TOK_ERROR) {
+ fatal("JavaScript parse error: %s: line = %d, col = %d\n", id, line_num, column_num);
+ }
+
+ if (tt == TOK_EOF) {
+ mark_nontoken_chars(0, 0);
+ break;
+ }
+
+ /* mark the chars before the token */
+ JSToken t = CURRENT_TOKEN(&token_stream);
+ mark_nontoken_chars(t.pos.begin.lineno, t.pos.begin.index);
+
+ /* mark the token */
+ enum Class class;
+ switch (tt) {
+ case TOK_ERROR:
+ case TOK_EOF:
+ abort();
+ case TOK_EOL:
+ class = CLASS_NONE;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_SEMI:
+ case TOK_COMMA:
+ case TOK_ASSIGN:
+ case TOK_HOOK:
+ case TOK_COLON:
+ case TOK_OR:
+ case TOK_AND:
+ case TOK_BITOR:
+ case TOK_BITXOR:
+ case TOK_BITAND:
+ case TOK_EQOP:
+ case TOK_RELOP:
+ case TOK_SHOP:
+ case TOK_PLUS:
+ case TOK_MINUS:
+ case TOK_STAR:
+ case TOK_DIVOP:
+ class = CLASS_SYMBOL;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_UNARYOP:
+ switch (t.t_op) {
+ case JSOP_NEG:
+ case JSOP_POS:
+ case JSOP_NOT:
+ case JSOP_BITNOT:
+ class = CLASS_SYMBOL;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case JSOP_TYPEOF:
+ class = CLASS_KEYWORD;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case JSOP_VOID:
+ class = CLASS_TYPE;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ default:
+ abort();
+ }
+ break;
+ case TOK_INC:
+ case TOK_DEC:
+ class = CLASS_SYMBOL;
+ /* token_stream.flags does not change w.r.t. TSF_OPERAND */
+ break;
+ case TOK_DOT:
+ case TOK_LB:
+ class = CLASS_SYMBOL;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_RB:
+ class = CLASS_SYMBOL;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_LC:
+ class = CLASS_CBRACKET;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_RC:
+ class = CLASS_CBRACKET;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_LP:
+ class = CLASS_SYMBOL;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_RP:
+ class = CLASS_SYMBOL;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_NAME:
+ class = CLASS_NONE;
+ token_stream.flags &= ~TSF_OPERAND;
+ if (js_PeekToken(context, &token_stream) == TOK_LP) {
+ /* function */
+ class = CLASS_NONE;
+ }
+ break;
+ case TOK_NUMBER:
+ class = CLASS_NUMBER;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_STRING:
+ class = CLASS_STRING;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_REGEXP:
+ class = CLASS_REGEXP;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_PRIMARY:
+ switch (t.t_op) {
+ case JSOP_TRUE:
+ case JSOP_FALSE:
+ case JSOP_NULL:
+ case JSOP_THIS:
+ class = CLASS_KEYWORD;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ default:
+ abort();
+ }
+ break;
+ case TOK_FUNCTION:
+ class = CLASS_KEYWORD;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_IF:
+ case TOK_ELSE:
+ case TOK_SWITCH:
+ case TOK_CASE:
+ case TOK_DEFAULT:
+ case TOK_WHILE:
+ case TOK_DO:
+ case TOK_FOR:
+ case TOK_BREAK:
+ case TOK_CONTINUE:
+ case TOK_IN:
+ case TOK_VAR:
+ case TOK_WITH:
+ case TOK_RETURN:
+ case TOK_NEW:
+ case TOK_DELETE:
+ token_stream.flags |= TSF_OPERAND;
+ class = CLASS_KEYWORD;
+ break;
+ case TOK_DEFSHARP:
+ case TOK_USESHARP:
+ abort();
+ break;
+ case TOK_TRY:
+ case TOK_CATCH:
+ case TOK_FINALLY:
+ case TOK_THROW:
+ case TOK_INSTANCEOF:
+ case TOK_DEBUGGER:
+ token_stream.flags |= TSF_OPERAND;
+ class = CLASS_KEYWORD;
+ break;
+ case TOK_XMLSTAGO:
+ case TOK_XMLETAGO:
+ case TOK_XMLPTAGC:
+ case TOK_XMLTAGC:
+ case TOK_XMLNAME:
+ case TOK_XMLATTR:
+ case TOK_XMLSPACE:
+ case TOK_XMLTEXT:
+ case TOK_XMLCOMMENT:
+ case TOK_XMLCDATA:
+ case TOK_XMLPI:
+ case TOK_AT:
+ case TOK_DBLCOLON:
+ case TOK_ANYNAME:
+ case TOK_DBLDOT:
+ case TOK_FILTER:
+ case TOK_XMLELEM:
+ case TOK_XMLLIST:
+ abort();
+ break;
+ case TOK_YIELD:
+ token_stream.flags |= TSF_OPERAND;
+ class = CLASS_KEYWORD;
+ break;
+ case TOK_ARRAYCOMP:
+ case TOK_ARRAYPUSH:
+ case TOK_LEXICALSCOPE:
+ abort();
+ break;
+ case TOK_LET:
+ token_stream.flags |= TSF_OPERAND;
+ class = CLASS_KEYWORD;
+ break;
+ case TOK_SEQ:
+ case TOK_FORHEAD:
+ case TOK_RESERVED:
+ case TOK_LIMIT:
+ abort();
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ uint16_t start_line = t.pos.begin.lineno;
+ uint16_t end_line = t.pos.end.lineno;
+ uint16_t start_column = t.pos.begin.index;
+ uint16_t end_column = t.pos.end.index;
+ assert(line_num == start_line);
+ assert(column_num == start_column);
+ if (start_line == end_line && start_column >= end_column) {
+ fatal("%s: script contains line with more than 65,535 characters", id);
+ }
+ for (;;) {
+ assert(character_offset < num_characters);
+ jschar c = characters[character_offset];
+ if (tt == TOK_STRING && c == '\\') {
+ output_character(c, CLASS_SPECIALCHAR);
+ assert(character_offset < num_characters);
+ c = characters[character_offset];
+ output_character(c, CLASS_SPECIALCHAR);
+ }
+ else {
+ output_character(c, class);
+ }
+
+ if (line_num > end_line) {
+ break;
+ }
+ else if (line_num == end_line && column_num >= end_column) {
+ break;
+ }
+ }
+
+ assert(line_num == end_line);
+ assert(column_num = end_column);
+ }
+
+ if (current_class != CLASS_NONE) {
+ output_character('\n', CLASS_NONE);
+ }
+
+ js_CloseTokenStream(context, &token_stream);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/highlight.h b/tools/node_modules/expresso/deps/jscoverage/highlight.h
new file mode 100644
index 0000000..5bc8c88
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/highlight.h
@@ -0,0 +1,37 @@
+/*
+ highlight.h - JavaScript syntax highlighting
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef HIGHLIGHT_H_
+#define HIGHLIGHT_H_
+
+#include <jscntxt.h>
+
+#include "stream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void jscoverage_highlight_js(JSContext * context, const char * id, const jschar * characters, size_t num_characters, Stream * output);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HIGHLIGHT_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-connection.c b/tools/node_modules/expresso/deps/jscoverage/http-connection.c
new file mode 100644
index 0000000..4280d0a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-connection.c
@@ -0,0 +1,192 @@
+/*
+ http-connection.c - TCP connection between HTTP client and server
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "util.h"
+
+#define CONNECTION_BUFFER_CAPACITY 8192
+
+#ifdef _WIN32
+#define ERRNO (WSAGetLastError())
+#else
+#include <errno.h>
+#define ERRNO errno
+#endif
+
+struct HTTPConnection {
+ SOCKET s;
+ uint8_t input_buffer[CONNECTION_BUFFER_CAPACITY];
+ size_t input_buffer_offset;
+ size_t input_buffer_length;
+ uint8_t output_buffer[CONNECTION_BUFFER_CAPACITY];
+ size_t output_buffer_offset;
+ size_t output_buffer_length;
+};
+
+static HTTPConnection * HTTPConnection_new(SOCKET s) {
+ HTTPConnection * connection = xmalloc(sizeof(HTTPConnection));
+ connection->s = s;
+ connection->input_buffer_offset = 0;
+ connection->input_buffer_length = 0;
+ connection->output_buffer_offset = 0;
+ connection->output_buffer_length = 0;
+ return connection;
+}
+
+HTTPConnection * HTTPConnection_new_client(const char * host, uint16_t port) {
+ struct in_addr ip_address;
+ if (! inet_aton(host, &ip_address)) {
+ /* it's a host name */
+ if (xgethostbyname(host, &ip_address) != 0) {
+ return NULL;
+ }
+ }
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET) {
+ return NULL;
+ }
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(port);
+ a.sin_addr = ip_address;
+
+ if (connect(s, (struct sockaddr *) &a, sizeof(a)) < 0) {
+ closesocket(s);
+ return NULL;
+ }
+
+ return HTTPConnection_new(s);
+}
+
+HTTPConnection * HTTPConnection_new_server(SOCKET s) {
+ return HTTPConnection_new(s);
+}
+
+int HTTPConnection_delete(HTTPConnection * connection) {
+ int result = 0;
+ if (closesocket(connection->s) == -1) {
+ result = ERRNO;
+ assert(result != 0);
+ }
+ free(connection);
+ return result;
+}
+
+int HTTPConnection_get_peer(HTTPConnection * connection, struct sockaddr_in * peer) {
+ int result = 0;
+ socklen_t length = sizeof(struct sockaddr_in);
+ if (getpeername(connection->s, (struct sockaddr *) peer, &length) == -1) {
+ result = ERRNO;
+ assert(result != 0);
+ }
+ return result;
+}
+
+int HTTPConnection_read_octet(HTTPConnection * connection, int * octet) {
+ if (connection->input_buffer_offset >= connection->input_buffer_length) {
+ ssize_t bytes_received = recv(connection->s, connection->input_buffer, CONNECTION_BUFFER_CAPACITY, 0);
+ if (bytes_received == -1) {
+ int result = ERRNO;
+ assert(result != 0);
+ return result;
+ }
+ else if (bytes_received == 0) {
+ /* orderly shutdown */
+ *octet = -1;
+ return 0;
+ }
+ else {
+ connection->input_buffer_offset = 0;
+ connection->input_buffer_length = bytes_received;
+ }
+ }
+ *octet = connection->input_buffer[connection->input_buffer_offset];
+ connection->input_buffer_offset++;
+ return 0;
+}
+
+int HTTPConnection_peek_octet(HTTPConnection * connection, int * octet) {
+ int result = HTTPConnection_read_octet(connection, octet);
+
+ /* check for error */
+ if (result != 0) {
+ return result;
+ }
+
+ /* check for end */
+ if (*octet == -1) {
+ return 0;
+ }
+
+ /* reset input buffer */
+ connection->input_buffer_offset--;
+ return 0;
+}
+
+int HTTPConnection_write(HTTPConnection * connection, const void * p, size_t size) {
+ while (size > 0) {
+ if (connection->output_buffer_length == CONNECTION_BUFFER_CAPACITY) {
+ /* buffer full */
+ ssize_t bytes_sent = send(connection->s, connection->output_buffer, CONNECTION_BUFFER_CAPACITY, 0);
+ if (bytes_sent == -1) {
+ int result = ERRNO;
+ assert(result != 0);
+ return result;
+ }
+ connection->output_buffer_length = 0;
+ }
+
+ size_t buffer_remaining = CONNECTION_BUFFER_CAPACITY - connection->output_buffer_length;
+ size_t bytes_to_copy;
+ if (size <= buffer_remaining) {
+ bytes_to_copy = size;
+ }
+ else {
+ bytes_to_copy = buffer_remaining;
+ }
+
+ memcpy(connection->output_buffer + connection->output_buffer_length, p, bytes_to_copy);
+ connection->output_buffer_length += bytes_to_copy;
+ p += bytes_to_copy;
+ size -= bytes_to_copy;
+ }
+
+ return 0;
+}
+
+int HTTPConnection_flush(HTTPConnection * connection) {
+ if (connection->output_buffer_length > 0) {
+ ssize_t bytes_sent = send(connection->s, connection->output_buffer, connection->output_buffer_length, 0);
+ if (bytes_sent == -1) {
+ int result = ERRNO;
+ assert(result != 0);
+ return result;
+ }
+ connection->output_buffer_length = 0;
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-exchange.c b/tools/node_modules/expresso/deps/jscoverage/http-exchange.c
new file mode 100644
index 0000000..9356455
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-exchange.c
@@ -0,0 +1,494 @@
+/*
+ http-exchange.c - HTTP request/response exchange
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "util.h"
+
+struct HTTPExchange {
+ HTTPConnection * connection;
+
+ HTTPMessage * request_message;
+
+ char * method;
+ char * request_uri;
+ char * request_http_version;
+
+ char * host;
+ uint16_t port;
+ char * abs_path;
+ char * query;
+
+ HTTPMessage * response_message;
+
+ uint16_t status_code;
+ char * response_http_version;
+};
+
+static const struct {
+ const int status_code;
+ const char * const reason_phrase;
+} reason_phrases[] = {
+ {100, "Continue"},
+ {101, "Switching Protocols"},
+ {200, "OK"},
+ {201, "Created"},
+ {202, "Accepted"},
+ {203, "Non-Authoritative Information"},
+ {204, "No Content"},
+ {205, "Reset Content"},
+ {206, "Partial Content"},
+ {301, "Moved Permanently"},
+ {302, "Found"},
+ {303, "See Other"},
+ {304, "Not Modified"},
+ {305, "Use Proxy"},
+ {307, "Temporary Redirect"},
+ {400, "Bad Request"},
+ {401, "Unauthorized"},
+ {402, "Payment Required"},
+ {403, "Forbidden"},
+ {404, "Not Found"},
+ {405, "Method Not Allowed"},
+ {406, "Not Acceptable"},
+ {407, "Proxy Authentication Required"},
+ {408, "Request Time-out"},
+ {409, "Conflict"},
+ {410, "Gone"},
+ {411, "Length Required"},
+ {412, "Precondition Failed"},
+ {413, "Request Entity Too Large"},
+ {414, "Request-URI Too Large"},
+ {415, "Unsupported Media Type"},
+ {416, "Requested range not satisfiable"},
+ {417, "Expectation Failed"},
+ {500, "Internal Server Error"},
+ {501, "Not Implemented"},
+ {502, "Bad Gateway"},
+ {503, "Service Unavailable"},
+ {504, "Gateway Time-out"},
+ {505, "HTTP Version not supported"},
+};
+
+HTTPExchange * HTTPExchange_new(HTTPConnection * connection) {
+ HTTPExchange * exchange = xmalloc(sizeof(HTTPExchange));
+
+ exchange->connection = connection;
+
+ exchange->request_message = HTTPMessage_new(connection);
+ exchange->method = NULL;
+ exchange->request_uri = NULL;
+ exchange->request_http_version = NULL;
+ exchange->host = NULL;
+ exchange->port = 0;
+ exchange->abs_path = NULL;
+ exchange->query = NULL;
+
+ exchange->response_message = HTTPMessage_new(connection);
+ exchange->response_http_version = NULL;
+ exchange->status_code = 0;
+
+ return exchange;
+}
+
+void HTTPExchange_delete(HTTPExchange * exchange) {
+ HTTPMessage_delete(exchange->response_message);
+ free(exchange->response_http_version);
+
+ HTTPMessage_delete(exchange->request_message);
+ free(exchange->method);
+ free(exchange->request_uri);
+ free(exchange->request_http_version);
+ free(exchange->host);
+ free(exchange->abs_path);
+ free(exchange->query);
+
+ free(exchange);
+}
+
+int HTTPExchange_get_peer(const HTTPExchange * exchange, struct sockaddr_in * peer) {
+ return HTTPConnection_get_peer(exchange->connection, peer);
+}
+
+HTTPMessage * HTTPExchange_get_request_message(const HTTPExchange * exchange) {
+ return exchange->request_message;
+}
+
+const char * HTTPExchange_get_request_line(const HTTPExchange * exchange) {
+ return HTTPMessage_get_start_line(exchange->request_message);
+}
+
+const char * HTTPExchange_get_method(const HTTPExchange * exchange) {
+ return exchange->method;
+}
+
+const char * HTTPExchange_get_request_uri(const HTTPExchange * exchange) {
+ return exchange->request_uri;
+}
+
+const char * HTTPExchange_get_request_http_version(const HTTPExchange * exchange) {
+ return exchange->request_http_version;
+}
+
+const char * HTTPExchange_get_host(const HTTPExchange * exchange) {
+ return exchange->host;
+}
+
+uint16_t HTTPExchange_get_port(const HTTPExchange * exchange) {
+ return exchange->port;
+}
+
+const char * HTTPExchange_get_abs_path(const HTTPExchange * exchange) {
+ return exchange->abs_path;
+}
+
+void HTTPExchange_set_method(HTTPExchange * exchange, const char * method) {
+ free(exchange->method);
+ exchange->method = xstrdup(method);
+}
+
+void HTTPExchange_set_request_uri(HTTPExchange * exchange, const char * request_uri) {
+ free(exchange->request_uri);
+ exchange->request_uri = xstrdup(request_uri);
+}
+
+const HTTPHeader * HTTPExchange_get_request_headers(const HTTPExchange * exchange) {
+ return HTTPMessage_get_headers(exchange->request_message);
+}
+
+const char * HTTPExchange_find_request_header(const HTTPExchange * exchange, const char * name) {
+ return HTTPMessage_find_header(exchange->request_message, name);
+}
+
+void HTTPExchange_add_request_header(HTTPExchange * exchange, const char * name, const char * value) {
+ HTTPMessage_add_header(exchange->request_message, name, value);
+}
+
+void HTTPExchange_set_request_header(HTTPExchange * exchange, const char * name, const char * value) {
+ HTTPMessage_set_header(exchange->request_message, name, value);
+}
+
+void HTTPExchange_set_request_content_length(HTTPExchange * exchange, size_t value) {
+ HTTPMessage_set_content_length(exchange->request_message, value);
+}
+
+int HTTPExchange_read_request_headers(HTTPExchange * exchange) {
+ int result = 0;
+
+ result = HTTPMessage_read_start_line_and_headers(exchange->request_message);
+ if (result != 0) {
+ return result;
+ }
+
+ /* parse the Request-Line */
+ const char * request_line = HTTPMessage_get_start_line(exchange->request_message);
+ const char * p = request_line;
+
+ /* parse the Method */
+ while (*p != ' ') {
+ if (*p == '\0') {
+ return -1;
+ }
+ p++;
+ }
+ if (p == request_line) {
+ return -1;
+ }
+ exchange->method = xstrndup(request_line, p - request_line);
+
+ /* skip over space */
+ p++;
+
+ /* parse the Request-URI */
+ const char * start = p;
+ while (*p != ' ') {
+ if (*p == '\0') {
+ return -1;
+ }
+ p++;
+ }
+ if (p == start) {
+ return -1;
+ }
+ exchange->request_uri = xstrndup(start, p - start);
+
+ /* skip over space */
+ p++;
+
+ /* parse the HTTP-Version */
+ start = p;
+ while (*p != '\r' && *p != '\n') {
+ if (*p == '\0') {
+ return -1;
+ }
+ p++;
+ }
+ if (p == start) {
+ return -1;
+ }
+ exchange->request_http_version = xstrndup(start, p - start);
+
+ /* uri elements */
+ /* RFC 2616 5.1.2: the Request-URI can be an `absoluteURI' or an `abs_path' */
+ result = URL_parse(exchange->request_uri, &(exchange->host), &(exchange->port),
+ &(exchange->abs_path), &(exchange->query));
+ if (result != 0) {
+ return result;
+ }
+
+ if (exchange->host == NULL) {
+ /* abs_path */
+ const char * h = HTTPMessage_find_header(exchange->request_message, HTTP_HOST);
+ if (h == NULL) {
+ /* this must be an HTTP/1.0 client */
+ }
+ else {
+ result = URL_parse_host_and_port(h, &(exchange->host), &(exchange->port));
+ if (result != 0) {
+ return result;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int HTTPExchange_write_request_headers(HTTPExchange * exchange) {
+ if (HTTPMessage_has_sent_headers(exchange->request_message)) {
+ return 0;
+ }
+
+ /* set the Request-Line */
+ if (HTTPMessage_get_start_line(exchange->request_message) == NULL) {
+ if (exchange->method == NULL) {
+ exchange->method = xstrdup("GET");
+ }
+ assert(exchange->request_uri != NULL);
+ char * request_line;
+ xasprintf(&request_line, "%s %s HTTP/1.1\r\n", exchange->method, exchange->request_uri);
+ HTTPMessage_set_start_line(exchange->request_message, request_line);
+ free(request_line);
+ }
+
+ /* set the Host, if necessary */
+ if (! str_starts_with(exchange->request_uri, "http://")) {
+ const char * host = HTTPMessage_find_header(exchange->request_message, HTTP_HOST);
+ if (host == NULL) {
+ struct sockaddr_in peer;
+ int result = HTTPConnection_get_peer(exchange->connection, &peer);
+ if (result != 0) {
+ return result;
+ }
+ const char * a = inet_ntoa(peer.sin_addr);
+ char * value;
+ xasprintf(&value, "%s:%u", a, ntohs(peer.sin_port));
+ HTTPMessage_add_header(exchange->request_message, HTTP_HOST, value);
+ free(value);
+ }
+ }
+
+ return HTTPMessage_write_start_line_and_headers(exchange->request_message);
+}
+
+bool HTTPExchange_request_has_body(const HTTPExchange * exchange) {
+ /*
+ RFC 2616 4.3: a request has a body iff the request has a Content-Length or Transfer-Encoding header
+ */
+ return HTTPMessage_find_header(exchange->request_message, HTTP_CONTENT_LENGTH) != NULL ||
+ HTTPMessage_find_header(exchange->request_message, HTTP_TRANSFER_ENCODING) != NULL;
+}
+
+int HTTPExchange_read_entire_request_entity_body(HTTPExchange * exchange, Stream * stream) {
+ return HTTPMessage_read_entire_entity_body(exchange->request_message, stream);
+}
+
+int HTTPExchange_flush_request(HTTPExchange * exchange) {
+ return HTTPMessage_flush(exchange->request_message);
+}
+
+/* response methods */
+
+HTTPMessage * HTTPExchange_get_response_message(const HTTPExchange * exchange) {
+ return exchange->response_message;
+}
+
+const char * HTTPExchange_get_response_http_version(const HTTPExchange * exchange) {
+ return exchange->response_http_version;
+}
+
+uint16_t HTTPExchange_get_status_code(const HTTPExchange * exchange) {
+ return exchange->status_code;
+}
+
+void HTTPExchange_set_status_code(HTTPExchange * exchange, uint16_t status_code) {
+ exchange->status_code = status_code;
+}
+
+const HTTPHeader * HTTPExchange_get_response_headers(const HTTPExchange * exchange) {
+ return HTTPMessage_get_headers(exchange->response_message);
+}
+
+const char * HTTPExchange_find_response_header(const HTTPExchange * exchange, const char * name) {
+ return HTTPMessage_find_header(exchange->response_message, name);
+}
+
+void HTTPExchange_add_response_header(HTTPExchange * exchange, const char * name, const char * value) {
+ HTTPMessage_add_header(exchange->response_message, name, value);
+}
+
+void HTTPExchange_set_response_header(HTTPExchange * exchange, const char * name, const char * value) {
+ HTTPMessage_set_header(exchange->response_message, name, value);
+}
+
+void HTTPExchange_set_response_content_length(HTTPExchange * exchange, size_t value) {
+ HTTPMessage_set_content_length(exchange->response_message, value);
+}
+
+static void skip_digits(const char ** p) {
+ while (**p != '\0' && isdigit(**p)) {
+ (*p)++;
+ }
+}
+
+int HTTPExchange_read_response_headers(HTTPExchange * exchange) {
+ /* make sure the request went through before we try to read stuff */
+ int result = HTTPExchange_flush_request(exchange);
+ if (result != 0) {
+ return result;
+ }
+
+ result = HTTPMessage_read_start_line_and_headers(exchange->response_message);
+ if (result != 0) {
+ return result;
+ }
+
+ /* parse the Status-Line (RFC 2616 6.1) */
+ const char * status_line = HTTPMessage_get_start_line(exchange->response_message);
+ const char * p = status_line;
+
+ /* read the HTTP-Version */
+ if (! str_starts_with(p, "HTTP/")) {
+ return -1;
+ }
+ p += 5;
+ const char * start = p;
+ skip_digits(&p);
+ if (start == p) {
+ return -1;
+ }
+ if (*p != '.') {
+ return -1;
+ }
+ p++;
+ start = p;
+ skip_digits(&p);
+ if (start == p) {
+ return -1;
+ }
+ if (*p != ' ') {
+ return -1;
+ }
+ exchange->response_http_version = xstrndup(status_line, p - status_line);
+
+ /* skip over the space */
+ p++;
+
+ /* read the Status-Code */
+ start = p;
+ skip_digits(&p);
+ if (p - start != 3) {
+ return -1;
+ }
+ if (*p != ' ') {
+ return -1;
+ }
+ exchange->status_code = strtoul(start, NULL, 10);
+
+ return 0;
+}
+
+int HTTPExchange_write_response_headers(HTTPExchange * exchange) {
+ if (HTTPMessage_has_sent_headers(exchange->response_message)) {
+ return 0;
+ }
+
+ /* set the Status-Line (RFC 2616 6.1) */
+ if (exchange->status_code == 0) {
+ exchange->status_code = 200;
+ }
+ const char * reason_phrase = NULL;
+ size_t num_reason_phrases = sizeof(reason_phrases) / sizeof(reason_phrases[0]);
+ for (size_t i = 0; i < num_reason_phrases; i++) {
+ if (reason_phrases[i].status_code == exchange->status_code) {
+ reason_phrase = reason_phrases[i].reason_phrase;
+ break;
+ }
+ }
+ assert(reason_phrase != NULL);
+ char * status_line;
+ xasprintf(&status_line, "HTTP/1.1 %u %s\r\n", exchange->status_code, reason_phrase);
+ HTTPMessage_set_start_line(exchange->response_message, status_line);
+ free(status_line);
+
+ /* set the Content-Type, if necessary */
+ const char * content_type = HTTPMessage_find_header(exchange->response_message, HTTP_CONTENT_TYPE);
+ if (content_type == NULL) {
+ HTTPMessage_set_header(exchange->response_message, HTTP_CONTENT_TYPE, "text/html");
+ }
+
+ return HTTPMessage_write_start_line_and_headers(exchange->response_message);
+}
+
+bool HTTPExchange_response_has_body(const HTTPExchange * exchange) {
+ /*
+ RFC 2616 4.3: a response has a body iff the request is not HEAD and the response is not 1xx, 204, 304
+ */
+ const char * request_method = HTTPExchange_get_method(exchange);
+ assert(request_method != NULL);
+ return strcmp(request_method, "HEAD") != 0 &&
+ exchange->status_code != 304 &&
+ exchange->status_code != 204 &&
+ exchange->status_code / 100 != 1;
+}
+
+int HTTPExchange_read_entire_response_entity_body(HTTPExchange * exchange, Stream * stream) {
+ return HTTPMessage_read_entire_entity_body(exchange->response_message, stream);
+}
+
+int HTTPExchange_write_response(HTTPExchange * exchange, const void * p, size_t size) {
+ int result = HTTPExchange_write_response_headers(exchange);
+ if (result != 0) {
+ return result;
+ }
+ return HTTPMessage_write(exchange->response_message, p, size);
+}
+
+int HTTPExchange_flush_response(HTTPExchange * exchange) {
+ int result = HTTPExchange_write_response_headers(exchange);
+ if (result != 0) {
+ return result;
+ }
+ return HTTPMessage_flush(exchange->response_message);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-host.c b/tools/node_modules/expresso/deps/jscoverage/http-host.c
new file mode 100644
index 0000000..4458eee
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-host.c
@@ -0,0 +1,95 @@
+/*
+ http-host.c - thread-safe host lookup
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include "util.h"
+
+int xgethostbyname(const char * host, struct in_addr * a) {
+#if defined(__CYGWIN__) || defined(__MINGW32__)
+ /* gethostbyname is thread-safe */
+ struct hostent * p = gethostbyname(host);
+ if (p == NULL || p->h_addrtype != AF_INET) {
+ return -1;
+ }
+ *a = *((struct in_addr *) p->h_addr);
+ return 0;
+#elif HAVE_GETADDRINFO
+ struct addrinfo hints;
+ hints.ai_flags = 0;
+ hints.ai_family = PF_INET;
+ hints.ai_socktype = 0;
+ hints.ai_protocol = 0;
+ hints.ai_addrlen = 0;
+ hints.ai_addr = NULL;
+ hints.ai_canonname = NULL;
+ hints.ai_next = NULL;
+ struct addrinfo * p;
+ int result = getaddrinfo(host, NULL, &hints, &p);
+ if (result != 0 || p == NULL) {
+ return -1;
+ }
+ if (p->ai_family != PF_INET) {
+ freeaddrinfo(p);
+ return -1;
+ }
+ struct sockaddr_in * address_and_port = (struct sockaddr_in *) p->ai_addr;
+ *a = address_and_port->sin_addr;
+ freeaddrinfo(p);
+ return 0;
+#elif HAVE_GETHOSTBYNAME_R
+ struct hostent h;
+ struct hostent * p;
+ char * buffer;
+ size_t buffer_size;
+ int error;
+ int result;
+
+ buffer_size = 1024;
+ buffer = xmalloc(buffer_size);
+ while ((result = gethostbyname_r(host, &h, buffer, buffer_size, &p, &error)) == ERANGE) {
+ buffer_size = mulst(buffer_size, 2);
+ buffer = xrealloc(buffer, buffer_size);
+ }
+ if (result != 0 || p == NULL || p->h_addrtype != AF_INET) {
+ free(buffer);
+ return -1;
+ }
+ *a = *((struct in_addr *) p->h_addr);
+ free(buffer);
+ return 0;
+#else
+#error "No thread-safe host lookup available"
+#endif
+}
+
+#ifndef HAVE_INET_ATON
+int inet_aton(const char * name, struct in_addr * a) {
+ unsigned long result = inet_addr(name);
+ if (result == INADDR_NONE) {
+ return 0;
+ }
+ else {
+ a->s_addr = result;
+ return 1;
+ }
+}
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-message.c b/tools/node_modules/expresso/deps/jscoverage/http-message.c
new file mode 100644
index 0000000..6a92956
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-message.c
@@ -0,0 +1,900 @@
+/*
+ http-message.c - HTTP message object
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "stream.h"
+#include "util.h"
+
+enum ChunkedBodyState {
+ CHUNKED_BODY_CHUNK_SIZE, CHUNKED_BODY_CHUNK_DATA, CHUNKED_BODY_TRAILER, CHUNKED_BODY_DONE
+};
+
+struct HTTPMessage {
+ char * start_line;
+ HTTPHeader * headers;
+
+ /* used for sending and receiving */
+ struct HTTPConnection * connection;
+
+ /* used only for receiving */
+ bool has_content_length;
+ bool is_chunked;
+ size_t bytes_remaining;
+ enum ChunkedBodyState chunked_body_state;
+ Stream * chunk_buffer;
+
+ /* used only for sending */
+ bool is_started;
+};
+
+static bool is_lws(uint8_t c) {
+ return c == '\r' || c == '\n' || c == ' ' || c == '\t';
+}
+
+static bool is_separator(uint8_t c) {
+ /* RFC 2616 2.2 */
+ return strchr("()<>@,;:\\\"/[]?={} \t", c) != NULL;
+}
+
+static bool is_token_char(uint8_t c) {
+ /* RFC 2616 2.2 */
+ return 32 <= c && c <= 126 && ! is_separator(c);
+}
+
+static bool is_text(uint8_t c) {
+ return ! (c <= 31 || c == 127);
+}
+
+static void skip_lws(const uint8_t ** p) {
+ while (**p != '\0' && is_lws(**p)) {
+ (*p)++;
+ }
+}
+
+static uint8_t * parse_token(const uint8_t ** p) {
+ const uint8_t * start = *p;
+ while (**p != '\0' && is_token_char(**p)) {
+ (*p)++;
+ }
+
+ if (*p == start) {
+ return NULL;
+ }
+
+ return (uint8_t *) xstrndup((char *) start, *p - start);
+}
+
+static uint8_t * parse_quoted_string(const uint8_t ** p) {
+ const uint8_t * start = *p;
+
+ if (**p != '"') {
+ return NULL;
+ }
+ (*p)++;
+
+ while (**p != '\0' && **p != '"') {
+ if (**p == '\\') {
+ (*p)++;
+ if (**p < 1 || **p > 127) {
+ return NULL;
+ }
+ (*p)++;
+ }
+ else if (is_text(**p)) {
+ (*p)++;
+ }
+ else {
+ return NULL;
+ }
+ }
+
+ if (**p != '"') {
+ return NULL;
+ }
+ (*p)++;
+
+ return (uint8_t *) xstrndup((char *) start, *p - start);
+}
+
+HTTPMessage * HTTPMessage_new(HTTPConnection * connection) {
+ HTTPMessage * message = xmalloc(sizeof(HTTPMessage));
+ message->start_line = NULL;
+ message->headers = NULL;
+ message->connection = connection;
+
+ message->has_content_length = false;
+ message->is_chunked = false;
+ message->bytes_remaining = 0;
+ message->chunked_body_state = CHUNKED_BODY_CHUNK_SIZE;
+ message->chunk_buffer = NULL;
+
+ message->is_started = false;
+ return message;
+}
+
+void HTTPMessage_delete(HTTPMessage * message) {
+ free(message->start_line);
+
+ HTTPHeader * h = message->headers;
+ while (h != NULL) {
+ HTTPHeader * doomed = h;
+ h = h->next;
+ free(doomed->name);
+ free(doomed->value);
+ free(doomed);
+ }
+
+ if (message->chunk_buffer != NULL) {
+ Stream_delete(message->chunk_buffer);
+ }
+
+ free(message);
+}
+
+HTTPConnection * HTTPMessage_get_connection(const HTTPMessage * message) {
+ return message->connection;
+}
+
+void HTTPMessage_add_header(HTTPMessage * message, const char * name, const char * value) {
+ HTTPHeader * last = NULL;
+ for (HTTPHeader * h = message->headers; h != NULL; h = h->next) {
+ if (strcmp(h->name, name) == 0) {
+ char * new_value;
+ xasprintf(&new_value, "%s, %s", h->value, value);
+ free(h->value);
+ h->value = new_value;
+ return;
+ }
+ last = h;
+ }
+
+ HTTPHeader * header = xmalloc(sizeof(HTTPHeader));
+ header->name = xstrdup(name);
+ header->value = xstrdup(value);
+ header->next = NULL;
+ if (last == NULL) {
+ message->headers = header;
+ }
+ else {
+ last->next = header;
+ }
+}
+
+void HTTPMessage_set_header(HTTPMessage * message, const char * name, const char * value) {
+ for (HTTPHeader * h = message->headers; h != NULL; h = h->next) {
+ if (strcmp(name, h->name) == 0) {
+ free(h->value);
+ h->value = xstrdup(value);
+ return;
+ }
+ }
+ HTTPMessage_add_header(message, name, value);
+}
+
+char * HTTPMessage_get_charset(const HTTPMessage * message) {
+ const char * content_type = HTTPMessage_find_header(message, HTTP_CONTENT_TYPE);
+ if (content_type == NULL) {
+ return NULL;
+ }
+
+ const uint8_t * p = (const uint8_t *) content_type;
+
+ /* e.g., text/html */
+ uint8_t * token;
+ skip_lws(&p);
+ if (! is_token_char(*p)) {
+ return NULL;
+ }
+ token = parse_token(&p);
+ free(token);
+ skip_lws(&p);
+ if (*p != '/') {
+ return NULL;
+ }
+ p++;
+ skip_lws(&p);
+ if (! is_token_char(*p)) {
+ return NULL;
+ }
+ token = parse_token(&p);
+ free(token);
+
+ skip_lws(&p);
+
+ while (*p != '\0') {
+ bool is_charset = false;
+ if (*p != ';') {
+ return NULL;
+ }
+ p++;
+
+ skip_lws(&p);
+
+ if (! is_token_char(*p)) {
+ return NULL;
+ }
+ uint8_t * attribute = parse_token(&p);
+ if (strcasecmp((char *) attribute, "charset") == 0) {
+ is_charset = true;
+ }
+ free(attribute);
+ skip_lws(&p);
+ if (*p != '=') {
+ return NULL;
+ }
+ p++;
+
+ skip_lws(&p);
+
+ if (*p == '"') {
+ uint8_t * value = parse_quoted_string(&p);
+ if (value == NULL) {
+ return NULL;
+ }
+ if (is_charset) {
+ return (char *) value;
+ }
+ free(value);
+ }
+ else if (is_token_char(*p)) {
+ uint8_t * value = parse_token(&p);
+ if (is_charset) {
+ return (char *) value;
+ }
+ free(value);
+ }
+ else {
+ return NULL;
+ }
+
+ skip_lws(&p);
+ }
+
+ return NULL;
+}
+
+void HTTPMessage_set_content_length(HTTPMessage * message, size_t value) {
+ char * s;
+ xasprintf(&s, "%u", value);
+ HTTPMessage_set_header(message, HTTP_CONTENT_LENGTH, s);
+ free(s);
+}
+
+const char * HTTPMessage_find_header(const HTTPMessage * message, const char * name) {
+ for (HTTPHeader * h = message->headers; h != NULL; h = h->next) {
+ if (strcasecmp(h->name, name) == 0) {
+ return h->value;
+ }
+ }
+ return NULL;
+}
+
+const HTTPHeader * HTTPMessage_get_headers(const HTTPMessage * message) {
+ return message->headers;
+}
+
+const char * HTTPMessage_get_start_line(const HTTPMessage * message) {
+ return message->start_line;
+}
+
+void HTTPMessage_set_start_line(HTTPMessage * message, const char * start_line) {
+ free(message->start_line);
+ message->start_line = xstrdup(start_line);
+}
+
+static int read_line(Stream * stream, HTTPConnection * connection) __attribute__((warn_unused_result));
+
+static int read_line(Stream * stream, HTTPConnection * connection) {
+ for (;;) {
+ int octet;
+ int result = HTTPConnection_read_octet(connection, &octet);
+ if (result != 0) {
+ return result;
+ }
+
+ /* check for end of input */
+ if (octet == -1) {
+ return 0;
+ }
+
+ char c = (char) octet;
+ Stream_write_char(stream, c);
+ if (c == '\n') {
+ return 0;
+ }
+ }
+}
+
+static int read_header(Stream * stream, HTTPConnection * connection) __attribute__((warn_unused_result));
+
+static int read_header(Stream * stream, HTTPConnection * connection) {
+ int c;
+
+ do {
+ int result = read_line(stream, connection);
+ if (result != 0) {
+ return result;
+ }
+
+ /* check for blank line ending the headers */
+ if (stream->length == 0 ||
+ (stream->length == 1 && stream->data[0] == '\n') ||
+ (stream->length == 2 && stream->data[0] == '\r' && stream->data[1] == '\n')) {
+ break;
+ }
+
+ result = HTTPConnection_peek_octet(connection, &c);
+ if (result != 0) {
+ return result;
+ }
+ }
+ while (c == ' ' || c == '\t');
+
+ return 0;
+}
+
+static bool stream_contains_nul(const Stream * stream) {
+ for (size_t i = 0; i < stream->length; i++) {
+ if (stream->data[i] == '\0') {
+ return true;
+ }
+ }
+ return false;
+}
+
+int HTTPMessage_read_start_line_and_headers(HTTPMessage * message) {
+ Stream * stream = Stream_new(0);
+
+ /* read the start line */
+ int result = read_line(stream, message->connection);
+ if (result != 0) {
+ Stream_delete(stream);
+ return -1;
+ }
+
+ /* check for NUL byte */
+ if (stream_contains_nul(stream)) {
+ Stream_delete(stream);
+ return -1;
+ }
+
+ message->start_line = xstrndup((char *) stream->data, stream->length);
+
+ /* read the headers - RFC 2616 4.2 */
+ message->headers = NULL;
+ for (;;) {
+ Stream_reset(stream);
+ result = read_header(stream, message->connection);
+ if (result != 0) {
+ Stream_delete(stream);
+ return -1;
+ }
+
+ /* check for CRLF (or similar) to terminate headers */
+ if (stream->length == 0 ||
+ (stream->length == 1 && stream->data[0] == '\n') ||
+ (stream->length == 2 && stream->data[0] == '\r' && stream->data[1] == '\n')) {
+ break;
+ }
+
+ /* check for NUL byte */
+ if (stream_contains_nul(stream)) {
+ Stream_delete(stream);
+ return -1;
+ }
+
+ /* NUL-terminate the header */
+ Stream_write_char(stream, '\0');
+
+ const uint8_t * p = stream->data;
+
+ char * name = (char *) parse_token(&p);
+ if (name == NULL) {
+ Stream_delete(stream);
+ return -1;
+ }
+
+ skip_lws(&p);
+
+ /* expect colon */
+ if (*p != ':') {
+ free(name);
+ Stream_delete(stream);
+ return -1;
+ }
+
+ /* skip over colon */
+ p++;
+
+ skip_lws(&p);
+
+ if (*p == '\0') {
+ free(name);
+ Stream_delete(stream);
+ return -1;
+ }
+
+ /* skip backward over LWS, starting from the last char in the buffer */
+ uint8_t * end = stream->data + stream->length - 2;
+ while (end > p && is_lws(*end)) {
+ end--;
+ }
+
+ char * value = xstrndup((char *) p, end - p + 1);
+
+ HTTPMessage_add_header(message, name, value);
+ free(name);
+ free(value);
+ }
+
+ Stream_delete(stream);
+
+ /*
+ RFC 2616 4.3:
+ - a request has a body iff the request headers include Content-Length or Transfer-Encoding
+ - a response has a body iff the request is not HEAD and the response is not 1xx, 204, 304
+ */
+
+ const char * content_length = HTTPMessage_find_header(message, HTTP_CONTENT_LENGTH);
+ if (content_length != NULL) {
+ size_t value = 0;
+ for (const char * p = content_length; *p != '\0'; p++) {
+ /* check for overflow */
+ if (SIZE_MAX / 10 < value) {
+ return -1;
+ }
+ value *= 10;
+
+ uint8_t digit = *p;
+
+ /* check that it contains only decimal digits */
+ if (digit < '0' || digit > '9') {
+ return -1;
+ }
+
+ size_t digit_value = digit - '0';
+
+ /* check for overflow */
+ if (SIZE_MAX - digit_value < value) {
+ return -1;
+ }
+ value += digit_value;
+ }
+
+ message->bytes_remaining = value;
+ message->has_content_length = true;
+ }
+
+ const char * transfer_encoding = HTTPMessage_find_header(message, HTTP_TRANSFER_ENCODING);
+ if (transfer_encoding != NULL) {
+ uint8_t * token = NULL;
+
+ const uint8_t * p = (const uint8_t *) transfer_encoding;
+ result = 0;
+ for (;;) {
+ skip_lws(&p);
+
+ if (! is_token_char(*p)) {
+ result = -1;
+ break;
+ }
+
+ free(token);
+ token = parse_token(&p);
+
+ skip_lws(&p);
+
+ while (*p == ';') {
+ p++;
+
+ skip_lws(&p);
+
+ if (! is_token_char(*p)) {
+ result = -1;
+ break;
+ }
+ uint8_t * attribute = parse_token(&p);
+ free(attribute);
+
+ skip_lws(&p);
+
+ if (*p != '=') {
+ result = -1;
+ break;
+ }
+ p++;
+
+ skip_lws(&p);
+
+ if (*p == '"') {
+ uint8_t * value = parse_quoted_string(&p);
+ if (value == NULL) {
+ result = -1;
+ break;
+ }
+ free(value);
+ }
+ else if (is_token_char(*p)) {
+ uint8_t * value = parse_token(&p);
+ free(value);
+ }
+ else {
+ result = -1;
+ break;
+ }
+
+ skip_lws(&p);
+ }
+
+ if (result == -1) {
+ break;
+ }
+
+ if (*p != ',') {
+ break;
+ }
+
+ p++;
+ }
+
+ if (result == 0 && *p == '\0' && token != NULL && strcasecmp((char *) token, "chunked") == 0) {
+ message->is_chunked = true;
+ message->chunk_buffer = Stream_new(0);
+ }
+
+ free(token);
+ }
+
+ return result;
+}
+
+int HTTPMessage_write_start_line_and_headers(HTTPMessage * message) {
+ int result = 0;
+
+ if (message->is_started) {
+ return result;
+ }
+
+ message->is_started = true;
+
+ /* send the start line */
+ assert(message->start_line != NULL);
+ size_t length = strlen(message->start_line);
+ assert(length >= 2 && message->start_line[length - 2] == '\r' && message->start_line[length - 1] == '\n');
+ result = HTTPConnection_write(message->connection, message->start_line, length);
+ if (result != 0) {
+ return result;
+ }
+
+ /* send the headers */
+ HTTPMessage_set_header(message, HTTP_CONNECTION, "close");
+ for (HTTPHeader * h = message->headers; h != NULL; h = h->next) {
+ result = HTTPConnection_write(message->connection, h->name, strlen(h->name));
+ if (result != 0) {
+ return result;
+ }
+ result = HTTPConnection_write(message->connection, ": ", 2);
+ if (result != 0) {
+ return result;
+ }
+ result = HTTPConnection_write(message->connection, h->value, strlen(h->value));
+ if (result != 0) {
+ return result;
+ }
+ result = HTTPConnection_write(message->connection, "\r\n", 2);
+ if (result != 0) {
+ return result;
+ }
+ }
+
+ result = HTTPConnection_write(message->connection, "\r\n", 2);
+ return result;
+}
+
+bool HTTPMessage_has_sent_headers(const HTTPMessage * message) {
+ return message->is_started;
+}
+
+int HTTPMessage_write(HTTPMessage * message, const void * p, size_t size) {
+ int result = 0;
+ result = HTTPMessage_write_start_line_and_headers(message);
+ if (result != 0) {
+ return result;
+ }
+ result = HTTPConnection_write(message->connection, p, size);
+ return result;
+}
+
+int HTTPMessage_flush(HTTPMessage * message) {
+ int result = 0;
+ result = HTTPMessage_write_start_line_and_headers(message);
+ if (result != 0) {
+ return result;
+ }
+ result = HTTPConnection_flush(message->connection);
+ return result;
+}
+
+static int read_chunk_size_line(HTTPMessage * message) __attribute__((warn_unused_result));
+
+static int read_chunk_size_line(HTTPMessage * message) {
+ Stream_reset(message->chunk_buffer);
+ int result = read_line(message->chunk_buffer, message->connection);
+ if (result != 0) {
+ return result;
+ }
+ if (message->chunk_buffer->length < 2) {
+ return -1;
+ }
+ return 0;
+}
+
+static int read_chunk_size(Stream * stream, size_t * chunk_size) __attribute__((warn_unused_result));
+
+static int read_chunk_size(Stream * stream, size_t * chunk_size) {
+ size_t value = 0;
+ for (size_t i = 0; i < stream->length; i++) {
+ uint8_t digit = stream->data[i];
+
+ /* check that it contains only hexadecimal digits */
+ size_t digit_value;
+ if ('0' <= digit && digit <= '9') {
+ digit_value = digit - '0';
+ }
+ else if ('a' <= digit && digit <= 'f') {
+ digit_value = digit - 'a' + 10;
+ }
+ else if ('A' <= digit && digit <= 'F') {
+ digit_value = digit - 'A' + 10;
+ }
+ else if (is_lws(digit) || digit == ';') {
+ break;
+ }
+ else {
+ return -1;
+ }
+
+ /* check for overflow */
+ if (SIZE_MAX / 16 < value) {
+ return -1;
+ }
+ value *= 16;
+
+ /* check for overflow */
+ if (SIZE_MAX - digit_value < value) {
+ return -1;
+ }
+ value += digit_value;
+ }
+
+ *chunk_size = value;
+ return 0;
+}
+
+static int read_chunked_message_body(HTTPMessage * message, void * p, size_t capacity, size_t * bytes_read) {
+ int result = 0;
+ *bytes_read = 0;
+
+ if (message->chunked_body_state == CHUNKED_BODY_DONE) {
+ return 0;
+ }
+
+ uint8_t * s = p;
+ int c;
+ for (*bytes_read = 0; *bytes_read < capacity; (*bytes_read)++) {
+ switch (message->chunked_body_state) {
+ case CHUNKED_BODY_CHUNK_SIZE:
+ if (message->chunk_buffer->length == 0) {
+ /* read a `chunk-size' line */
+ result = read_chunk_size_line(message);
+ if (result != 0) {
+ return result;
+ }
+
+ message->bytes_remaining = message->chunk_buffer->length;
+ }
+
+ if (message->bytes_remaining == 0) {
+ return -1;
+ }
+
+ /* serve from the chunk buffer */
+ s[*bytes_read] = message->chunk_buffer->data[message->chunk_buffer->length - message->bytes_remaining];
+ message->bytes_remaining--;
+
+ if (message->bytes_remaining == 0) {
+ size_t chunk_size;
+ result = read_chunk_size(message->chunk_buffer, &chunk_size);
+ if (result != 0) {
+ return result;
+ }
+ Stream_reset(message->chunk_buffer);
+ if (chunk_size == 0) {
+ message->chunked_body_state = CHUNKED_BODY_TRAILER;
+ }
+ else if (SIZE_MAX - 2 < chunk_size) {
+ /* overflow */
+ return -1;
+ }
+ else {
+ message->chunked_body_state = CHUNKED_BODY_CHUNK_DATA;
+ message->bytes_remaining = chunk_size + 2;
+ }
+ }
+
+ break;
+ case CHUNKED_BODY_CHUNK_DATA:
+ /* serve from the chunk */
+ result = HTTPConnection_read_octet(message->connection, &c);
+ if (result != 0) {
+ return result;
+ }
+ if (c == -1) {
+ result = -1;
+ message->chunked_body_state = CHUNKED_BODY_DONE;
+ return result;
+ }
+ s[*bytes_read] = (uint8_t) c;
+ message->bytes_remaining--;
+
+ if (message->bytes_remaining == 0) {
+ message->chunked_body_state = CHUNKED_BODY_CHUNK_SIZE;
+ }
+
+ break;
+ case CHUNKED_BODY_TRAILER:
+ if (message->chunk_buffer->length == 0) {
+ /* read a header */
+ result = read_header(message->chunk_buffer, message->connection);
+ if (result != 0) {
+ return result;
+ }
+ message->bytes_remaining = message->chunk_buffer->length;
+ }
+
+ if (message->bytes_remaining == 0) {
+ message->chunked_body_state = CHUNKED_BODY_DONE;
+ return result;
+ }
+
+ /* serve from the chunk buffer */
+ s[*bytes_read] = message->chunk_buffer->data[message->chunk_buffer->length - message->bytes_remaining];
+ message->bytes_remaining--;
+
+ if (message->bytes_remaining == 0) {
+ size_t length = message->chunk_buffer->length;
+ uint8_t * chunk_buffer = message->chunk_buffer->data;
+ if (length == 0 ||
+ (length == 1 && chunk_buffer[0] == '\n') ||
+ (length == 2 && chunk_buffer[0] == '\r' && chunk_buffer[1] == '\n')) {
+ message->chunked_body_state = CHUNKED_BODY_DONE;
+ return result;
+ }
+ Stream_reset(message->chunk_buffer);
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ return result;
+}
+
+static int read_chunked_entity_body(HTTPMessage * message, void * p, size_t capacity, size_t * bytes_read) {
+ int result = 0;
+ *bytes_read = 0;
+
+ if (message->chunked_body_state == CHUNKED_BODY_DONE) {
+ return result;
+ }
+
+ uint8_t * s = p;
+ for (*bytes_read = 0; *bytes_read < capacity; (*bytes_read)++) {
+ if (message->bytes_remaining == 0) {
+ result = read_chunk_size_line(message);
+ if (result != 0) {
+ break;
+ }
+ size_t chunk_size;
+ result = read_chunk_size(message->chunk_buffer, &chunk_size);
+ if (result != 0) {
+ break;
+ }
+ message->bytes_remaining = chunk_size;
+ if (chunk_size == 0) {
+ message->chunked_body_state = CHUNKED_BODY_DONE;
+ break;
+ }
+ }
+
+ int c;
+ result = HTTPConnection_read_octet(message->connection, &c);
+ if (result != 0) {
+ break;
+ }
+ if (c == -1) {
+ result = -1;
+ message->chunked_body_state = CHUNKED_BODY_DONE;
+ break;
+ }
+ s[*bytes_read] = (uint8_t) c;
+ message->bytes_remaining--;
+ }
+
+ return result;
+}
+
+int HTTPMessage_read_message_body(HTTPMessage * message, void * p, size_t capacity, size_t * bytes_read) {
+ if (message->is_chunked) {
+ return read_chunked_message_body(message, p, capacity, bytes_read);
+ }
+
+ int result = 0;
+ uint8_t * s = p;
+ for (*bytes_read = 0; *bytes_read < capacity; (*bytes_read)++) {
+ if (message->has_content_length && message->bytes_remaining == 0) {
+ break;
+ }
+
+ int c;
+ result = HTTPConnection_read_octet(message->connection, &c);
+ if (result != 0) {
+ break;
+ }
+ if (c == -1) {
+ break;
+ }
+ s[*bytes_read] = (uint8_t) c;
+ message->bytes_remaining--;
+ }
+ return result;
+}
+
+int HTTPMessage_read_entity_body(HTTPMessage * message, void * p, size_t capacity, size_t * bytes_read) {
+ if (message->is_chunked) {
+ return read_chunked_entity_body(message, p, capacity, bytes_read);
+ }
+
+ return HTTPMessage_read_message_body(message, p, capacity, bytes_read);
+}
+
+int HTTPMessage_read_entire_entity_body(HTTPMessage * message, Stream * input_stream) {
+ int result = 0;
+ uint8_t * buffer[8192];
+ for (;;) {
+ size_t bytes_read;
+ result = HTTPMessage_read_entity_body(message, buffer, 8192, &bytes_read);
+ if (result != 0) {
+ break;
+ }
+ if (bytes_read == 0) {
+ break;
+ }
+ Stream_write(input_stream, buffer, bytes_read);
+ }
+ return result;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-server.c b/tools/node_modules/expresso/deps/jscoverage/http-server.c
new file mode 100644
index 0000000..853d285
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-server.c
@@ -0,0 +1,236 @@
+/*
+ http-server.c - generic HTTP server
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include <stdarg.h>
+#include <string.h>
+
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#ifdef __MINGW32__
+#include <process.h>
+#endif
+
+#include "util.h"
+
+#ifdef __MINGW32__
+typedef void ThreadRoutineReturnType;
+#define THREAD_ROUTINE_RETURN return
+#else
+typedef void * ThreadRoutineReturnType;
+#define THREAD_ROUTINE_RETURN return NULL
+#endif
+
+struct HTTPServer {
+ char * ip_address;
+ uint16_t port;
+ HTTPServerHandler handler;
+ SOCKET s;
+};
+
+struct HTTPServerConnection {
+ HTTPConnection * connection;
+ struct HTTPServer * server;
+};
+
+static bool is_shutdown = false;
+#ifdef __MINGW32__
+CRITICAL_SECTION shutdown_mutex;
+#define LOCK EnterCriticalSection
+#define UNLOCK LeaveCriticalSection
+#else
+pthread_mutex_t shutdown_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define LOCK pthread_mutex_lock
+#define UNLOCK pthread_mutex_unlock
+#endif
+
+static ThreadRoutineReturnType handle_connection(void * p) {
+ struct HTTPServerConnection * connection = p;
+ uint16_t port = connection->server->port;
+
+ HTTPExchange * exchange = HTTPExchange_new(connection->connection);
+ if (HTTPExchange_read_request_headers(exchange) == 0) {
+ connection->server->handler(exchange);
+ }
+ else {
+ HTTPExchange_set_status_code(exchange, 400);
+ const char * message = "Could not parse request headers\n";
+ if (HTTPExchange_write_response(exchange, message, strlen(message)) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ }
+ if (HTTPExchange_flush_response(exchange) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ HTTPExchange_delete(exchange);
+ if (HTTPConnection_delete(connection->connection) != 0) {
+ HTTPServer_log_err("Warning: error closing connection to client\n");
+ }
+ free(connection);
+
+ /* HACK: make connection to server to force accept() to return */
+ LOCK(&shutdown_mutex);
+ if (is_shutdown) {
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET) {
+ HTTPServer_log_err("Warning: error creating socket\n");
+ }
+ else {
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(port);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ if (connect(s, (struct sockaddr *) &a, sizeof(a)) == -1) {
+ HTTPServer_log_err("Warning: error connecting to server\n");
+ }
+ closesocket(s);
+ }
+ }
+ UNLOCK(&shutdown_mutex);
+
+ THREAD_ROUTINE_RETURN;
+}
+
+static struct HTTPServer * HTTPServer_new(const char * ip_address, uint16_t port, HTTPServerHandler handler) {
+ struct HTTPServer * result = xmalloc(sizeof(struct HTTPServer));
+ if (ip_address == NULL) {
+ result->ip_address = NULL;
+ }
+ else {
+ result->ip_address = xstrdup(ip_address);
+ }
+ result->port = port;
+ result->handler = handler;
+ result->s = -1;
+ return result;
+}
+
+static void HTTPServer_delete(struct HTTPServer * server) {
+ free(server->ip_address);
+ closesocket(server->s);
+ free(server);
+}
+
+void HTTPServer_run(const char * ip_address, uint16_t port, HTTPServerHandler handler) {
+ struct HTTPServer * server = HTTPServer_new(ip_address, port, handler);
+
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ fatal("could not start Winsock");
+ }
+ InitializeCriticalSection(&shutdown_mutex);
+#endif
+
+ server->s = socket(PF_INET, SOCK_STREAM, 0);
+ if (server->s == INVALID_SOCKET) {
+ fatal("could not create socket");
+ }
+
+ /* http://hea-www.harvard.edu/~fine/Tech/addrinuse.html */
+ int optval = 1;
+ setsockopt(server->s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(server->port);
+ if (server->ip_address == NULL) {
+ /*
+ a.sin_addr.s_addr = htonl(INADDR_ANY);
+ */
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ }
+ else {
+ if (inet_aton(server->ip_address, &(a.sin_addr)) == 0) {
+ closesocket(server->s);
+ fatal("invalid address: %s", server->ip_address);
+ }
+ }
+
+ if (bind(server->s, (struct sockaddr *) &a, sizeof(a)) == -1) {
+ closesocket(server->s);
+ fatal("could not bind to address");
+ }
+
+ if (listen(server->s, 5) == -1) {
+ closesocket(server->s);
+ fatal("could not listen for connections");
+ }
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t client_address_size = sizeof(client_address);
+ SOCKET s = accept(server->s, (struct sockaddr *) &client_address, &client_address_size);
+ if (s == INVALID_SOCKET) {
+ HTTPServer_log_err("Warning: could not accept client connection\n");
+ continue;
+ }
+
+ LOCK(&shutdown_mutex);
+ if (is_shutdown) {
+ closesocket(s);
+ break;
+ }
+ UNLOCK(&shutdown_mutex);
+
+ struct HTTPServerConnection * connection = xmalloc(sizeof(struct HTTPServerConnection));
+ connection->server = server;
+ connection->connection = HTTPConnection_new_server(s);
+
+#ifdef __MINGW32__
+ unsigned long thread = _beginthread(handle_connection, 0, connection);
+#else
+ pthread_t thread;
+ pthread_attr_t a;
+ pthread_attr_init(&a);
+ pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
+ pthread_create(&thread, &a, handle_connection, connection);
+ pthread_attr_destroy(&a);
+#endif
+ }
+
+ HTTPServer_delete(server);
+}
+
+void HTTPServer_shutdown(void) {
+ LOCK(&shutdown_mutex);
+ is_shutdown = true;
+ UNLOCK(&shutdown_mutex);
+}
+
+void HTTPServer_log_out(const char * format, ...) {
+ va_list a;
+ va_start(a, format);
+ vfprintf(stdout, format, a);
+ va_end(a);
+ fflush(stdout);
+}
+
+void HTTPServer_log_err(const char * format, ...) {
+ va_list a;
+ va_start(a, format);
+ vfprintf(stderr, format, a);
+ va_end(a);
+ fflush(stderr);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-server.h b/tools/node_modules/expresso/deps/jscoverage/http-server.h
new file mode 100644
index 0000000..b7024f2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-server.h
@@ -0,0 +1,208 @@
+/*
+ http-server.h - generic HTTP server
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef HTTP_SERVER_H_
+#define HTTP_SERVER_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __MINGW32__
+#include <winsock2.h>
+typedef int socklen_t;
+#else
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+typedef int SOCKET;
+#define INVALID_SOCKET (-1)
+#define closesocket close
+#endif
+
+#include "stream.h"
+
+#define HTTP_ACCEPT "Accept"
+#define HTTP_ACCEPT_CHARSET "Accept-Charset"
+#define HTTP_ACCEPT_ENCODING "Accept-Encoding"
+#define HTTP_ACCEPT_LANGUAGE "Accept-Language"
+#define HTTP_ACCEPT_RANGES "Accept-Ranges"
+#define HTTP_AGE "Age"
+#define HTTP_ALLOW "Allow"
+#define HTTP_AUTHORIZATION "Authorization"
+#define HTTP_CACHE_CONTROL "Cache-Control"
+#define HTTP_CONNECTION "Connection"
+#define HTTP_CONTENT_ENCODING "Content-Encoding"
+#define HTTP_CONTENT_LANGUAGE "Content-Language"
+#define HTTP_CONTENT_LENGTH "Content-Length"
+#define HTTP_CONTENT_LOCATION "Content-Location"
+#define HTTP_CONTENT_MD5 "Content-MD5"
+#define HTTP_CONTENT_RANGE "Content-Range"
+#define HTTP_CONTENT_TYPE "Content-Type"
+#define HTTP_DATE "Date"
+#define HTTP_ETAG "ETag"
+#define HTTP_EXPECT "Expect"
+#define HTTP_EXPIRES "Expires"
+#define HTTP_FROM "From"
+#define HTTP_HOST "Host"
+#define HTTP_IF_MATCH "If-Match"
+#define HTTP_IF_MODIFIED_SINCE "If-Modified-Since"
+#define HTTP_IF_NONE_MATCH "If-None-Match"
+#define HTTP_IF_RANGE "If-Range"
+#define HTTP_IF_UNMODIFIED_SINCE "If-Unmodified-Since"
+#define HTTP_LAST_MODIFIED "Last-Modified"
+#define HTTP_LOCATION "Location"
+#define HTTP_MAX_FORWARDS "Max-Forwards"
+#define HTTP_PRAGMA "Pragma"
+#define HTTP_PROXY_AUTHENTICATE "Proxy-Authenticate"
+#define HTTP_PROXY_AUTHORIZATION "Proxy-Authorization"
+#define HTTP_RANGE "Range"
+#define HTTP_REFERER "Referer"
+#define HTTP_RETRY_AFTER "Retry-After"
+#define HTTP_SERVER "Server"
+#define HTTP_TE "TE"
+#define HTTP_TRAILER "Trailer"
+#define HTTP_TRANSFER_ENCODING "Transfer-Encoding"
+#define HTTP_UPGRADE "Upgrade"
+#define HTTP_USER_AGENT "User-Agent"
+#define HTTP_VARY "Vary"
+#define HTTP_VIA "Via"
+#define HTTP_WARNING "Warning"
+#define HTTP_WWW_AUTHENTICATE "WWW-Authenticate"
+
+typedef struct HTTPHeader {
+ char * name;
+ char * value;
+ struct HTTPHeader * next;
+} HTTPHeader;
+
+typedef struct HTTPMessage HTTPMessage;
+
+typedef struct HTTPExchange HTTPExchange;
+
+typedef struct HTTPConnection HTTPConnection;
+
+typedef void (*HTTPServerHandler)(HTTPExchange * exchange);
+
+/* HTTPConnection */
+HTTPConnection * HTTPConnection_new_server(SOCKET s);
+HTTPConnection * HTTPConnection_new_client(const char * host, uint16_t port) __attribute__((warn_unused_result));
+int HTTPConnection_delete(HTTPConnection * connection) __attribute__((warn_unused_result));
+int HTTPConnection_get_peer(HTTPConnection * connection, struct sockaddr_in * peer) __attribute__((warn_unused_result));
+int HTTPConnection_read_octet(HTTPConnection * connection, int * octet) __attribute__((warn_unused_result));
+int HTTPConnection_peek_octet(HTTPConnection * connection, int * octet) __attribute__((warn_unused_result));
+int HTTPConnection_write(HTTPConnection * connection, const void * p, size_t size) __attribute__((warn_unused_result));
+int HTTPConnection_flush(HTTPConnection * connection) __attribute__((warn_unused_result));
+
+/* HTTPMessage */
+HTTPMessage * HTTPMessage_new(HTTPConnection * connection);
+void HTTPMessage_delete(HTTPMessage * message);
+HTTPConnection * HTTPMessage_get_connection(const HTTPMessage * message);
+const char * HTTPMessage_get_start_line(const HTTPMessage * message);
+void HTTPMessage_set_start_line(HTTPMessage * message, const char * start_line);
+const HTTPHeader * HTTPMessage_get_headers(const HTTPMessage * message);
+const char * HTTPMessage_find_header(const HTTPMessage * message, const char * name);
+void HTTPMessage_add_header(HTTPMessage * message, const char * name, const char * value);
+void HTTPMessage_set_header(HTTPMessage * message, const char * name, const char * value);
+char * HTTPMessage_get_charset(const HTTPMessage * message);
+void HTTPMessage_set_content_length(HTTPMessage * message, size_t value);
+int HTTPMessage_read_start_line_and_headers(HTTPMessage * message) __attribute__((warn_unused_result));
+int HTTPMessage_write_start_line_and_headers(HTTPMessage * message) __attribute__((warn_unused_result));
+bool HTTPMessage_has_sent_headers(const HTTPMessage * message);
+int HTTPMessage_write(HTTPMessage * message, const void * p, size_t size) __attribute__((warn_unused_result));
+int HTTPMessage_flush(HTTPMessage * message) __attribute__((warn_unused_result));
+
+/*
+This function reads the entire entity body from a message. If the message uses
+the "chunked" Transfer-Encoding, this function will decode it, so that the
+result will be the original entity.
+*/
+int HTTPMessage_read_entire_entity_body(HTTPMessage * message, Stream * input_stream) __attribute__((warn_unused_result));
+
+/*
+This function makes no attempt to decode the Transfer-Encoding.
+*/
+int HTTPMessage_read_message_body(HTTPMessage * message, void * p, size_t capacity, size_t * bytes_read) __attribute__((warn_unused_result));
+
+/* HTTPExchange */
+HTTPExchange * HTTPExchange_new(HTTPConnection * connection);
+void HTTPExchange_delete(HTTPExchange * exchange);
+int HTTPExchange_get_peer(const HTTPExchange * exchange, struct sockaddr_in * peer) __attribute__((warn_unused_result));
+
+HTTPMessage * HTTPExchange_get_request_message(const HTTPExchange * exchange);
+
+const char * HTTPExchange_get_request_line(const HTTPExchange * exchange);
+const char * HTTPExchange_get_method(const HTTPExchange * exchange);
+const char * HTTPExchange_get_request_uri(const HTTPExchange * exchange);
+const char * HTTPExchange_get_request_http_version(const HTTPExchange * exchange);
+const char * HTTPExchange_get_host(const HTTPExchange * exchange);
+uint16_t HTTPExchange_get_port(const HTTPExchange * exchange);
+const char * HTTPExchange_get_abs_path(const HTTPExchange * exchange);
+void HTTPExchange_set_method(HTTPExchange * exchange, const char * method);
+void HTTPExchange_set_request_uri(HTTPExchange * exchange, const char * request_uri);
+
+const HTTPHeader * HTTPExchange_get_request_headers(const HTTPExchange * exchange);
+const char * HTTPExchange_find_request_header(const HTTPExchange * exchange, const char * name);
+void HTTPExchange_add_request_header(HTTPExchange * exchange, const char * name, const char * value);
+void HTTPExchange_set_request_header(HTTPExchange * exchange, const char * name, const char * value);
+void HTTPExchange_set_request_content_length(HTTPExchange * exchange, size_t value);
+
+int HTTPExchange_read_request_headers(HTTPExchange * exchange) __attribute__((warn_unused_result));
+int HTTPExchange_write_request_headers(HTTPExchange * exchange) __attribute__((warn_unused_result));
+bool HTTPExchange_request_has_body(const HTTPExchange * exchange);
+int HTTPExchange_read_entire_request_entity_body(HTTPExchange * exchange, Stream * stream) __attribute__((warn_unused_result));
+int HTTPExchange_flush_request(HTTPExchange * exchange) __attribute__((warn_unused_result));
+
+HTTPMessage * HTTPExchange_get_response_message(const HTTPExchange * exchange);
+
+uint16_t HTTPExchange_get_status_code(const HTTPExchange * exchange);
+const char * HTTPExchange_get_response_http_version(const HTTPExchange * exchange);
+void HTTPExchange_set_status_code(HTTPExchange * exchange, uint16_t status_code);
+
+const HTTPHeader * HTTPExchange_get_response_headers(const HTTPExchange * exchange);
+const char * HTTPExchange_find_response_header(const HTTPExchange * exchange, const char * name);
+void HTTPExchange_add_response_header(HTTPExchange * exchange, const char * name, const char * value);
+void HTTPExchange_set_response_header(HTTPExchange * exchange, const char * name, const char * value);
+void HTTPExchange_set_response_content_length(HTTPExchange * exchange, size_t value);
+
+int HTTPExchange_read_response_headers(HTTPExchange * exchange) __attribute__((warn_unused_result));
+int HTTPExchange_write_response_headers(HTTPExchange * exchange) __attribute__((warn_unused_result));
+bool HTTPExchange_response_has_body(const HTTPExchange * exchange);
+int HTTPExchange_read_entire_response_entity_body(HTTPExchange * exchange, Stream * stream) __attribute__((warn_unused_result));
+int HTTPExchange_write_response(HTTPExchange * exchange, const void * p, size_t size) __attribute__((warn_unused_result));
+int HTTPExchange_flush_response(HTTPExchange * exchange) __attribute__((warn_unused_result));
+
+void HTTPServer_run(const char * ip_address, uint16_t port, HTTPServerHandler handler);
+void HTTPServer_shutdown(void);
+void HTTPServer_log_out(const char * format, ...) __attribute__((__format__(printf, 1, 2)));
+void HTTPServer_log_err(const char * format, ...) __attribute__((__format__(printf, 1, 2)));
+
+int URL_parse(const char * url, char ** host, uint16_t * port, char ** abs_path, char ** query) __attribute__((warn_unused_result));
+int URL_parse_host_and_port(const char * s, char ** host, uint16_t * port) __attribute__((warn_unused_result));
+int URL_parse_abs_path_and_query(const char * s, char ** abs_path, char ** query) __attribute__((warn_unused_result));
+
+int xgethostbyname(const char * host, struct in_addr * result) __attribute__((warn_unused_result));
+
+#ifndef HAVE_INET_ATON
+int inet_aton(const char * name, struct in_addr * a);
+#endif
+
+#endif /* HTTP_SERVER_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-url.c b/tools/node_modules/expresso/deps/jscoverage/http-url.c
new file mode 100644
index 0000000..ee2fa78
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-url.c
@@ -0,0 +1,156 @@
+/*
+ http-url.c - URL parsing routines
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "util.h"
+
+int URL_parse_host_and_port(const char * s, char ** host, uint16_t * port) {
+ char * colon = strchr(s, ':');
+ if (colon == NULL) {
+ *host = xstrdup(s);
+ *port = 80;
+ }
+ else {
+ if (*(colon + 1) == '\0') {
+ *port = 80;
+ }
+ else {
+ char * end;
+ unsigned long p = strtoul(colon + 1, &end, 10);
+ if (*end == '\0') {
+ if (p > UINT16_MAX) {
+ return -1;
+ }
+ else {
+ *port = p;
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ *host = xstrndup(s, colon - s);
+ }
+ return 0;
+}
+
+int URL_parse_abs_path_and_query(const char * s, char ** abs_path, char ** query) {
+ if (*s == '\0') {
+ *abs_path = xstrdup("/");
+ *query = NULL;
+ }
+ else if (*s == '?') {
+ *abs_path = xstrdup("/");
+ *query = xstrdup(s + 1);
+ }
+ else if (*s == '/') {
+ char * question = strchr(s, '?');
+ if (question == NULL) {
+ *abs_path = xstrdup(s);
+ *query = NULL;
+ }
+ else {
+ *abs_path = xstrndup(s, question - s);
+ *query = xstrdup(question + 1);
+ }
+ }
+ else {
+ return -1;
+ }
+ return 0;
+}
+
+int URL_parse(const char * url, char ** host, uint16_t * port, char ** abs_path, char ** query) {
+ /* check for invalid characters */
+ for (const char * p = url; *p != '\0'; p++) {
+ switch (*p) {
+ case ';':
+ case '/':
+ case '?':
+ case ':':
+ case '@':
+ case '&':
+ case '=':
+ case '+':
+ case '$':
+ case ',':
+ case '-':
+ case '_':
+ case '.':
+ case '!':
+ case '~':
+ case '*':
+ case '\'':
+ case '(':
+ case ')':
+ case '%':
+ break;
+ default:
+ if (! isalnum(*p)) {
+ return -1;
+ }
+ break;
+ }
+ }
+
+ int result;
+ if (strncasecmp(url, "http://", 7) == 0) {
+ /* absoluteURI */
+
+ /* advance past the http:// */
+ const char * authority_start = url + 7;
+
+ /* look for a slash or question mark */
+ const char * p;
+ for (p = authority_start; *p != '/' && *p != '?' && *p != '\0'; p++) {
+ ;
+ }
+
+ char * host_and_port = xstrndup(authority_start, p - authority_start);
+ result = URL_parse_host_and_port(host_and_port, host, port);
+ free(host_and_port);
+ if (result != 0) {
+ return result;
+ }
+
+ result = URL_parse_abs_path_and_query(p, abs_path, query);
+ if (result != 0) {
+ free(*host);
+ *host = NULL;
+ return result;
+ }
+ }
+ else {
+ /* abs_path */
+ *host = NULL;
+ *port = 80;
+ result = URL_parse_abs_path_and_query(url, abs_path, query);
+ if (result != 0) {
+ return result;
+ }
+ }
+ result = 0;
+ return result;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/install-sh b/tools/node_modules/expresso/deps/jscoverage/install-sh
new file mode 100755
index 0000000..a5897de
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/install-sh
@@ -0,0 +1,519 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-12-25.00
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# 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
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dst_arg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ -*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/instrument-js.cpp b/tools/node_modules/expresso/deps/jscoverage/instrument-js.cpp
new file mode 100644
index 0000000..7a1868a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/instrument-js.cpp
@@ -0,0 +1,1873 @@
+/*
+ instrument-js.cpp - JavaScript instrumentation routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "instrument-js.h"
+
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <jsapi.h>
+#include <jsarena.h>
+#include <jsatom.h>
+#include <jsemit.h>
+#include <jsexn.h>
+#include <jsfun.h>
+#include <jsinterp.h>
+#include <jsiter.h>
+#include <jsparse.h>
+#include <jsregexp.h>
+#include <jsscope.h>
+#include <jsstr.h>
+
+#include "encoding.h"
+#include "global.h"
+#include "highlight.h"
+#include "resource-manager.h"
+#include "util.h"
+
+struct IfDirective {
+ const jschar * condition_start;
+ const jschar * condition_end;
+ uint16_t start_line;
+ uint16_t end_line;
+ struct IfDirective * next;
+};
+
+bool jscoverage_mozilla = false;
+
+static bool * exclusive_directives = NULL;
+
+static JSRuntime * runtime = NULL;
+static JSContext * context = NULL;
+static JSObject * global = NULL;
+static JSVersion js_version = JSVERSION_ECMA_3;
+
+/*
+JSParseNode objects store line numbers starting from 1.
+The lines array stores line numbers starting from 0.
+*/
+static const char * file_id = NULL;
+static char * lines = NULL;
+static uint16_t num_lines = 0;
+
+void jscoverage_set_js_version(const char * version) {
+ js_version = JS_StringToVersion(version);
+ if (js_version != JSVERSION_UNKNOWN) {
+ return;
+ }
+
+ char * end;
+ js_version = (JSVersion) strtol(version, &end, 10);
+ if ((size_t) (end - version) != strlen(version)) {
+ fatal("invalid version: %s", version);
+ }
+}
+
+void jscoverage_init(void) {
+ runtime = JS_NewRuntime(8L * 1024L * 1024L);
+ if (runtime == NULL) {
+ fatal("cannot create runtime");
+ }
+
+ context = JS_NewContext(runtime, 8192);
+ if (context == NULL) {
+ fatal("cannot create context");
+ }
+
+ JS_SetVersion(context, js_version);
+
+ global = JS_NewObject(context, NULL, NULL, NULL);
+ if (global == NULL) {
+ fatal("cannot create global object");
+ }
+
+ if (! JS_InitStandardClasses(context, global)) {
+ fatal("cannot initialize standard classes");
+ }
+}
+
+void jscoverage_cleanup(void) {
+ JS_DestroyContext(context);
+ JS_DestroyRuntime(runtime);
+}
+
+static void print_javascript(const jschar * characters, size_t num_characters, Stream * f) {
+ for (size_t i = 0; i < num_characters; i++) {
+ jschar c = characters[i];
+ /*
+ XXX does not handle no-break space, other unicode "space separator"
+ */
+ switch (c) {
+ case 0x9:
+ case 0xB:
+ case 0xC:
+ Stream_write_char(f, c);
+ break;
+ default:
+ if (32 <= c && c <= 126) {
+ Stream_write_char(f, c);
+ }
+ else {
+ Stream_printf(f, "\\u%04x", c);
+ }
+ break;
+ }
+ }
+}
+
+static void print_string(JSString * s, Stream * f) {
+ size_t length = JSSTRING_LENGTH(s);
+ jschar * characters = JSSTRING_CHARS(s);
+ for (size_t i = 0; i < length; i++) {
+ jschar c = characters[i];
+ if (32 <= c && c <= 126) {
+ switch (c) {
+ case '"':
+ Stream_write_string(f, "\\\"");
+ break;
+/*
+ case '\'':
+ Stream_write_string(f, "\\'");
+ break;
+*/
+ case '\\':
+ Stream_write_string(f, "\\\\");
+ break;
+ default:
+ Stream_write_char(f, c);
+ break;
+ }
+ }
+ else {
+ switch (c) {
+ case 0x8:
+ Stream_write_string(f, "\\b");
+ break;
+ case 0x9:
+ Stream_write_string(f, "\\t");
+ break;
+ case 0xa:
+ Stream_write_string(f, "\\n");
+ break;
+ /* IE doesn't support this */
+ /*
+ case 0xb:
+ Stream_write_string(f, "\\v");
+ break;
+ */
+ case 0xc:
+ Stream_write_string(f, "\\f");
+ break;
+ case 0xd:
+ Stream_write_string(f, "\\r");
+ break;
+ default:
+ Stream_printf(f, "\\u%04x", c);
+ break;
+ }
+ }
+ }
+}
+
+static void print_string_atom(JSAtom * atom, Stream * f) {
+ assert(ATOM_IS_STRING(atom));
+ JSString * s = ATOM_TO_STRING(atom);
+ print_string(s, f);
+}
+
+static void print_regex(jsval value, Stream * f) {
+ assert(JSVAL_IS_STRING(value));
+ JSString * s = JSVAL_TO_STRING(value);
+ size_t length = JSSTRING_LENGTH(s);
+ jschar * characters = JSSTRING_CHARS(s);
+ for (size_t i = 0; i < length; i++) {
+ jschar c = characters[i];
+ if (32 <= c && c <= 126) {
+ Stream_write_char(f, c);
+ }
+ else {
+ Stream_printf(f, "\\u%04x", c);
+ }
+ }
+}
+
+static void print_quoted_string_atom(JSAtom * atom, Stream * f) {
+ assert(ATOM_IS_STRING(atom));
+ JSString * s = ATOM_TO_STRING(atom);
+ Stream_write_char(f, '"');
+ print_string(s, f);
+ Stream_write_char(f, '"');
+}
+
+static const char * get_op(uint8 op) {
+ switch(op) {
+ case JSOP_OR:
+ return "||";
+ case JSOP_AND:
+ return "&&";
+ case JSOP_BITOR:
+ return "|";
+ case JSOP_BITXOR:
+ return "^";
+ case JSOP_BITAND:
+ return "&";
+ case JSOP_EQ:
+ return "==";
+ case JSOP_NE:
+ return "!=";
+ case JSOP_STRICTEQ:
+ return "===";
+ case JSOP_STRICTNE:
+ return "!==";
+ case JSOP_LT:
+ return "<";
+ case JSOP_LE:
+ return "<=";
+ case JSOP_GT:
+ return ">";
+ case JSOP_GE:
+ return ">=";
+ case JSOP_LSH:
+ return "<<";
+ case JSOP_RSH:
+ return ">>";
+ case JSOP_URSH:
+ return ">>>";
+ case JSOP_ADD:
+ return "+";
+ case JSOP_SUB:
+ return "-";
+ case JSOP_MUL:
+ return "*";
+ case JSOP_DIV:
+ return "/";
+ case JSOP_MOD:
+ return "%";
+ default:
+ abort();
+ }
+}
+
+static void output_expression(JSParseNode * node, Stream * f, bool parenthesize_object_literals);
+static void instrument_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if);
+static void output_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if);
+
+enum FunctionType {
+ FUNCTION_NORMAL,
+ FUNCTION_GETTER_OR_SETTER
+};
+
+static void output_for_in(JSParseNode * node, Stream * f) {
+ assert(node->pn_type == TOK_FOR);
+ assert(node->pn_arity == PN_BINARY);
+ Stream_write_string(f, "for ");
+ if (node->pn_iflags & JSITER_FOREACH) {
+ Stream_write_string(f, "each ");
+ }
+ Stream_write_char(f, '(');
+ output_expression(node->pn_left, f, false);
+ Stream_write_char(f, ')');
+}
+
+static void output_array_comprehension_or_generator_expression(JSParseNode * node, Stream * f) {
+ assert(node->pn_type == TOK_LEXICALSCOPE);
+ assert(node->pn_arity == PN_NAME);
+ JSParseNode * for_node = node->pn_expr;
+ assert(for_node->pn_type == TOK_FOR);
+ assert(for_node->pn_arity == PN_BINARY);
+ JSParseNode * p = for_node;
+ while (p->pn_type == TOK_FOR) {
+ p = p->pn_right;
+ }
+ JSParseNode * if_node = NULL;
+ if (p->pn_type == TOK_IF) {
+ if_node = p;
+ assert(if_node->pn_arity == PN_TERNARY);
+ p = if_node->pn_kid2;
+ }
+ switch (p->pn_arity) {
+ case PN_UNARY:
+ p = p->pn_kid;
+ if (p->pn_type == TOK_YIELD) {
+ /* for generator expressions */
+ p = p->pn_kid;
+ }
+ output_expression(p, f, false);
+ break;
+ case PN_LIST:
+ /*
+ When the array comprehension contains "if (0)", it will be optimized away and
+ the result will be an empty TOK_LC list.
+ */
+ assert(p->pn_type == TOK_LC);
+ assert(p->pn_head == NULL);
+ /* the "1" is arbitrary (since the list is empty) */
+ Stream_write_char(f, '1');
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ p = for_node;
+ while (p->pn_type == TOK_FOR) {
+ Stream_write_char(f, ' ');
+ output_for_in(p, f);
+ p = p->pn_right;
+ }
+ if (p->pn_type == TOK_LC) {
+ /* this is the optimized-away "if (0)" */
+ Stream_write_string(f, " if (0)");
+ }
+ else if (if_node) {
+ Stream_write_string(f, " if (");
+ output_expression(if_node->pn_kid1, f, false);
+ Stream_write_char(f, ')');
+ }
+}
+
+static void instrument_function(JSParseNode * node, Stream * f, int indent, enum FunctionType type) {
+ assert(node->pn_type == TOK_FUNCTION);
+ assert(node->pn_arity == PN_FUNC);
+ JSObject * object = node->pn_funpob->object;
+ assert(JS_ObjectIsFunction(context, object));
+ JSFunction * function = (JSFunction *) JS_GetPrivate(context, object);
+ assert(function);
+ assert(object == &function->object);
+ Stream_printf(f, "%*s", indent, "");
+ if (type == FUNCTION_NORMAL) {
+ Stream_write_string(f, "function ");
+ }
+
+ /* function name */
+ if (function->atom) {
+ print_string_atom(function->atom, f);
+ }
+
+ /*
+ function parameters - see JS_DecompileFunction in jsapi.cpp, which calls
+ js_DecompileFunction in jsopcode.cpp
+ */
+ Stream_write_char(f, '(');
+ JSArenaPool pool;
+ JS_INIT_ARENA_POOL(&pool, "instrument_function", 256, 1, &context->scriptStackQuota);
+ jsuword * local_names = NULL;
+ if (JS_GET_LOCAL_NAME_COUNT(function)) {
+ local_names = js_GetLocalNameArray(context, function, &pool);
+ if (local_names == NULL) {
+ fatal("out of memory");
+ }
+ }
+ bool destructuring = false;
+ for (int i = 0; i < function->nargs; i++) {
+ if (i > 0) {
+ Stream_write_string(f, ", ");
+ }
+ JSAtom * param = JS_LOCAL_NAME_TO_ATOM(local_names[i]);
+ if (param == NULL) {
+ destructuring = true;
+ JSParseNode * expression = NULL;
+ assert(node->pn_body->pn_type == TOK_LC || node->pn_body->pn_type == TOK_SEQ);
+ JSParseNode * semi = node->pn_body->pn_head;
+ assert(semi->pn_type == TOK_SEMI);
+ JSParseNode * comma = semi->pn_kid;
+ assert(comma->pn_type == TOK_COMMA);
+ for (JSParseNode * p = comma->pn_head; p != NULL; p = p->pn_next) {
+ assert(p->pn_type == TOK_ASSIGN);
+ JSParseNode * rhs = p->pn_right;
+ assert(JSSTRING_LENGTH(ATOM_TO_STRING(rhs->pn_atom)) == 0);
+ if (rhs->pn_slot == i) {
+ expression = p->pn_left;
+ break;
+ }
+ }
+ assert(expression != NULL);
+ output_expression(expression, f, false);
+ }
+ else {
+ print_string_atom(param, f);
+ }
+ }
+ JS_FinishArenaPool(&pool);
+ Stream_write_string(f, ") {\n");
+
+ /* function body */
+ if (function->flags & JSFUN_EXPR_CLOSURE) {
+ /* expression closure - use output_statement instead of instrument_statement */
+ if (node->pn_body->pn_type == TOK_SEQ) {
+ assert(node->pn_body->pn_arity == PN_LIST);
+ assert(node->pn_body->pn_count == 2);
+ output_statement(node->pn_body->pn_head->pn_next, f, indent + 2, false);
+ }
+ else {
+ output_statement(node->pn_body, f, indent + 2, false);
+ }
+ }
+ else {
+ assert(node->pn_body->pn_type == TOK_LC);
+ assert(node->pn_body->pn_arity == PN_LIST);
+ JSParseNode * p = node->pn_body->pn_head;
+ if (destructuring) {
+ p = p->pn_next;
+ }
+ for (; p != NULL; p = p->pn_next) {
+ instrument_statement(p, f, indent + 2, false);
+ }
+ }
+
+ Stream_write_char(f, '}');
+}
+
+static void instrument_function_call(JSParseNode * node, Stream * f) {
+ JSParseNode * function_node = node->pn_head;
+ if (function_node->pn_type == TOK_FUNCTION) {
+ JSObject * object = function_node->pn_funpob->object;
+ assert(JS_ObjectIsFunction(context, object));
+ JSFunction * function = (JSFunction *) JS_GetPrivate(context, object);
+ assert(function);
+ assert(object == &function->object);
+
+ if (function_node->pn_flags & TCF_GENEXP_LAMBDA) {
+ /* it's a generator expression */
+ Stream_write_char(f, '(');
+ output_array_comprehension_or_generator_expression(function_node->pn_body, f);
+ Stream_write_char(f, ')');
+ return;
+ }
+ }
+ output_expression(function_node, f, false);
+ Stream_write_char(f, '(');
+ for (struct JSParseNode * p = function_node->pn_next; p != NULL; p = p->pn_next) {
+ if (p != node->pn_head->pn_next) {
+ Stream_write_string(f, ", ");
+ }
+ output_expression(p, f, false);
+ }
+ Stream_write_char(f, ')');
+}
+
+static void instrument_declarations(JSParseNode * list, Stream * f) {
+ assert(list->pn_arity == PN_LIST);
+ for (JSParseNode * p = list->pn_head; p != NULL; p = p->pn_next) {
+ if (p != list->pn_head) {
+ Stream_write_string(f, ", ");
+ }
+ output_expression(p, f, false);
+ }
+}
+
+/*
+See <Expressions> in jsparse.h.
+TOK_FUNCTION is handled as a statement and as an expression.
+TOK_DBLDOT is not handled (XML op).
+TOK_DEFSHARP and TOK_USESHARP are not handled.
+TOK_ANYNAME is not handled (XML op).
+TOK_AT is not handled (XML op).
+TOK_DBLCOLON is not handled.
+TOK_XML* are not handled.
+There seem to be some undocumented expressions:
+TOK_INSTANCEOF binary
+TOK_IN binary
+*/
+static void output_expression(JSParseNode * node, Stream * f, bool parenthesize_object_literals) {
+ switch (node->pn_type) {
+ case TOK_FUNCTION:
+ Stream_write_char(f, '(');
+ instrument_function(node, f, 0, FUNCTION_NORMAL);
+ Stream_write_char(f, ')');
+ break;
+ case TOK_COMMA:
+ for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
+ if (p != node->pn_head) {
+ Stream_write_string(f, ", ");
+ }
+ output_expression(p, f, parenthesize_object_literals);
+ }
+ break;
+ case TOK_ASSIGN:
+ output_expression(node->pn_left, f, parenthesize_object_literals);
+ Stream_write_char(f, ' ');
+ switch (node->pn_op) {
+ case JSOP_ADD:
+ case JSOP_SUB:
+ case JSOP_MUL:
+ case JSOP_MOD:
+ case JSOP_LSH:
+ case JSOP_RSH:
+ case JSOP_URSH:
+ case JSOP_BITAND:
+ case JSOP_BITOR:
+ case JSOP_BITXOR:
+ case JSOP_DIV:
+ Stream_printf(f, "%s", get_op(node->pn_op));
+ break;
+ default:
+ /* do nothing - it must be a simple assignment */
+ break;
+ }
+ Stream_write_string(f, "= ");
+ output_expression(node->pn_right, f, false);
+ break;
+ case TOK_HOOK:
+ output_expression(node->pn_kid1, f, parenthesize_object_literals);
+ Stream_write_string(f, "? ");
+ output_expression(node->pn_kid2, f, false);
+ Stream_write_string(f, ": ");
+ output_expression(node->pn_kid3, f, false);
+ break;
+ case TOK_OR:
+ case TOK_AND:
+ case TOK_BITOR:
+ case TOK_BITXOR:
+ case TOK_BITAND:
+ case TOK_EQOP:
+ case TOK_RELOP:
+ case TOK_SHOP:
+ case TOK_PLUS:
+ case TOK_MINUS:
+ case TOK_STAR:
+ case TOK_DIVOP:
+ switch (node->pn_arity) {
+ case PN_BINARY:
+ output_expression(node->pn_left, f, parenthesize_object_literals);
+ Stream_printf(f, " %s ", get_op(node->pn_op));
+ output_expression(node->pn_right, f, false);
+ break;
+ case PN_LIST:
+ for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
+ if (p == node->pn_head) {
+ output_expression(p, f, parenthesize_object_literals);
+ }
+ else {
+ Stream_printf(f, " %s ", get_op(node->pn_op));
+ output_expression(p, f, false);
+ }
+ }
+ break;
+ default:
+ abort();
+ }
+ break;
+ case TOK_UNARYOP:
+ switch (node->pn_op) {
+ case JSOP_NEG:
+ Stream_write_string(f, "- ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_POS:
+ Stream_write_string(f, "+ ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_NOT:
+ Stream_write_string(f, "! ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_BITNOT:
+ Stream_write_string(f, "~ ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_TYPEOF:
+ Stream_write_string(f, "typeof ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_VOID:
+ Stream_write_string(f, "void ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ default:
+ fatal_source(file_id, node->pn_pos.begin.lineno, "unknown operator (%d)", node->pn_op);
+ break;
+ }
+ break;
+ case TOK_INC:
+ case TOK_DEC:
+ /*
+ This is not documented, but node->pn_op tells whether it is pre- or post-increment.
+ */
+ switch (node->pn_op) {
+ case JSOP_INCNAME:
+ case JSOP_INCPROP:
+ case JSOP_INCELEM:
+ Stream_write_string(f, "++");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_DECNAME:
+ case JSOP_DECPROP:
+ case JSOP_DECELEM:
+ Stream_write_string(f, "--");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_NAMEINC:
+ case JSOP_PROPINC:
+ case JSOP_ELEMINC:
+ output_expression(node->pn_kid, f, parenthesize_object_literals);
+ Stream_write_string(f, "++");
+ break;
+ case JSOP_NAMEDEC:
+ case JSOP_PROPDEC:
+ case JSOP_ELEMDEC:
+ output_expression(node->pn_kid, f, parenthesize_object_literals);
+ Stream_write_string(f, "--");
+ break;
+ default:
+ abort();
+ break;
+ }
+ break;
+ case TOK_NEW:
+ Stream_write_string(f, "new ");
+ instrument_function_call(node, f);
+ break;
+ case TOK_DELETE:
+ Stream_write_string(f, "delete ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case TOK_DOT:
+ /* numeric literals must be parenthesized */
+ switch (node->pn_expr->pn_type) {
+ case TOK_NUMBER:
+ Stream_write_char(f, '(');
+ output_expression(node->pn_expr, f, false);
+ Stream_write_char(f, ')');
+ break;
+ default:
+ output_expression(node->pn_expr, f, true);
+ break;
+ }
+ /*
+ This may have originally been x['foo-bar']. Because the string 'foo-bar'
+ contains illegal characters, we have to use the subscript syntax instead of
+ the dot syntax.
+ */
+ assert(ATOM_IS_STRING(node->pn_atom));
+ {
+ JSString * s = ATOM_TO_STRING(node->pn_atom);
+ bool must_quote;
+ if (JSSTRING_LENGTH(s) == 0) {
+ must_quote = true;
+ }
+ else if (js_CheckKeyword(JSSTRING_CHARS(s), JSSTRING_LENGTH(s)) != TOK_EOF) {
+ must_quote = true;
+ }
+ else if (! js_IsIdentifier(s)) {
+ must_quote = true;
+ }
+ else {
+ must_quote = false;
+ }
+ if (must_quote) {
+ Stream_write_char(f, '[');
+ print_quoted_string_atom(node->pn_atom, f);
+ Stream_write_char(f, ']');
+ }
+ else {
+ Stream_write_char(f, '.');
+ print_string_atom(node->pn_atom, f);
+ }
+ }
+ break;
+ case TOK_LB:
+ output_expression(node->pn_left, f, false);
+ Stream_write_char(f, '[');
+ output_expression(node->pn_right, f, false);
+ Stream_write_char(f, ']');
+ break;
+ case TOK_LP:
+ instrument_function_call(node, f);
+ break;
+ case TOK_RB:
+ Stream_write_char(f, '[');
+ for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
+ if (p != node->pn_head) {
+ Stream_write_string(f, ", ");
+ }
+ /* TOK_COMMA is a special case: a hole in the array */
+ if (p->pn_type != TOK_COMMA) {
+ output_expression(p, f, false);
+ }
+ }
+ if (node->pn_extra == PNX_ENDCOMMA) {
+ Stream_write_char(f, ',');
+ }
+ Stream_write_char(f, ']');
+ break;
+ case TOK_RC:
+ if (parenthesize_object_literals) {
+ Stream_write_char(f, '(');
+ }
+ Stream_write_char(f, '{');
+ for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
+ if (p->pn_type != TOK_COLON) {
+ fatal_source(file_id, p->pn_pos.begin.lineno, "unsupported node type (%d)", p->pn_type);
+ }
+ if (p != node->pn_head) {
+ Stream_write_string(f, ", ");
+ }
+
+ /* check whether this is a getter or setter */
+ switch (p->pn_op) {
+ case JSOP_GETTER:
+ case JSOP_SETTER:
+ if (p->pn_op == JSOP_GETTER) {
+ Stream_write_string(f, "get ");
+ }
+ else {
+ Stream_write_string(f, "set ");
+ }
+ output_expression(p->pn_left, f, false);
+ Stream_write_char(f, ' ');
+ if (p->pn_right->pn_type != TOK_FUNCTION) {
+ fatal_source(file_id, p->pn_pos.begin.lineno, "expected function");
+ }
+ instrument_function(p->pn_right, f, 0, FUNCTION_GETTER_OR_SETTER);
+ break;
+ default:
+ output_expression(p->pn_left, f, false);
+ Stream_write_string(f, ": ");
+ output_expression(p->pn_right, f, false);
+ break;
+ }
+ }
+ Stream_write_char(f, '}');
+ if (parenthesize_object_literals) {
+ Stream_write_char(f, ')');
+ }
+ break;
+ case TOK_RP:
+ Stream_write_char(f, '(');
+ output_expression(node->pn_kid, f, false);
+ Stream_write_char(f, ')');
+ break;
+ case TOK_NAME:
+ print_string_atom(node->pn_atom, f);
+ if (node->pn_expr != NULL) {
+ Stream_write_string(f, " = ");
+ output_expression(node->pn_expr, f, false);
+ }
+ break;
+ case TOK_STRING:
+ print_quoted_string_atom(node->pn_atom, f);
+ break;
+ case TOK_REGEXP:
+ assert(node->pn_op == JSOP_REGEXP);
+ {
+ JSObject * object = node->pn_pob->object;
+ jsval result;
+ js_regexp_toString(context, object, &result);
+ print_regex(result, f);
+ }
+ break;
+ case TOK_NUMBER:
+ /*
+ A 64-bit IEEE 754 floating point number has a 52-bit fraction.
+ 2^(-52) = 2.22 x 10^(-16)
+ Thus there are 16 significant digits.
+ To keep the output simple, special-case zero.
+ */
+ if (node->pn_dval == 0.0) {
+ if (signbit(node->pn_dval)) {
+ Stream_write_string(f, "-0");
+ }
+ else {
+ Stream_write_string(f, "0");
+ }
+ }
+ else if (node->pn_dval == INFINITY) {
+ Stream_write_string(f, "Number.POSITIVE_INFINITY");
+ }
+ else if (node->pn_dval == -INFINITY) {
+ Stream_write_string(f, "Number.NEGATIVE_INFINITY");
+ }
+ else if (isnan(node->pn_dval)) {
+ Stream_write_string(f, "Number.NaN");
+ }
+ else {
+ Stream_printf(f, "%.15g", node->pn_dval);
+ }
+ break;
+ case TOK_PRIMARY:
+ switch (node->pn_op) {
+ case JSOP_TRUE:
+ Stream_write_string(f, "true");
+ break;
+ case JSOP_FALSE:
+ Stream_write_string(f, "false");
+ break;
+ case JSOP_NULL:
+ Stream_write_string(f, "null");
+ break;
+ case JSOP_THIS:
+ Stream_write_string(f, "this");
+ break;
+ /* jsscan.h mentions `super' ??? */
+ default:
+ abort();
+ }
+ break;
+ case TOK_INSTANCEOF:
+ output_expression(node->pn_left, f, parenthesize_object_literals);
+ Stream_write_string(f, " instanceof ");
+ output_expression(node->pn_right, f, false);
+ break;
+ case TOK_IN:
+ output_expression(node->pn_left, f, false);
+ Stream_write_string(f, " in ");
+ output_expression(node->pn_right, f, false);
+ break;
+ case TOK_LEXICALSCOPE:
+ assert(node->pn_arity == PN_NAME);
+ assert(node->pn_expr->pn_type == TOK_LET);
+ assert(node->pn_expr->pn_arity == PN_BINARY);
+ Stream_write_string(f, "let(");
+ assert(node->pn_expr->pn_left->pn_type == TOK_LP);
+ assert(node->pn_expr->pn_left->pn_arity == PN_LIST);
+ instrument_declarations(node->pn_expr->pn_left, f);
+ Stream_write_string(f, ") ");
+ output_expression(node->pn_expr->pn_right, f, true);
+ break;
+ case TOK_YIELD:
+ assert(node->pn_arity == PN_UNARY);
+ Stream_write_string(f, "yield");
+ if (node->pn_kid != NULL) {
+ Stream_write_char(f, ' ');
+ output_expression(node->pn_kid, f, true);
+ }
+ break;
+ case TOK_ARRAYCOMP:
+ assert(node->pn_arity == PN_LIST);
+ {
+ JSParseNode * block_node;
+ switch (node->pn_count) {
+ case 1:
+ block_node = node->pn_head;
+ break;
+ case 2:
+ block_node = node->pn_head->pn_next;
+ break;
+ default:
+ abort();
+ break;
+ }
+ Stream_write_char(f, '[');
+ output_array_comprehension_or_generator_expression(block_node, f);
+ Stream_write_char(f, ']');
+ }
+ break;
+ case TOK_VAR:
+ assert(node->pn_arity == PN_LIST);
+ Stream_write_string(f, "var ");
+ instrument_declarations(node, f);
+ break;
+ case TOK_LET:
+ assert(node->pn_arity == PN_LIST);
+ Stream_write_string(f, "let ");
+ instrument_declarations(node, f);
+ break;
+ default:
+ fatal_source(file_id, node->pn_pos.begin.lineno, "unsupported node type (%d)", node->pn_type);
+ }
+}
+
+static void output_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if) {
+ switch (node->pn_type) {
+ case TOK_FUNCTION:
+ instrument_function(node, f, indent, FUNCTION_NORMAL);
+ Stream_write_char(f, '\n');
+ break;
+ case TOK_LC:
+ assert(node->pn_arity == PN_LIST);
+/*
+ Stream_write_string(f, "{\n");
+*/
+ for (struct JSParseNode * p = node->pn_u.list.head; p != NULL; p = p->pn_next) {
+ instrument_statement(p, f, indent, false);
+ }
+/*
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+*/
+ break;
+ case TOK_IF:
+ {
+ assert(node->pn_arity == PN_TERNARY);
+
+ uint16_t line = node->pn_pos.begin.lineno;
+ if (! is_jscoverage_if) {
+ if (line > num_lines) {
+ fatal("file %s contains more than 65,535 lines", file_id);
+ }
+ if (line >= 2 && exclusive_directives[line - 2]) {
+ is_jscoverage_if = true;
+ }
+ }
+
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "if (");
+ output_expression(node->pn_kid1, f, false);
+ Stream_write_string(f, ") {\n");
+ if (is_jscoverage_if && node->pn_kid3) {
+ uint16_t else_start = node->pn_kid3->pn_pos.begin.lineno;
+ uint16_t else_end = node->pn_kid3->pn_pos.end.lineno + 1;
+ Stream_printf(f, "%*s", indent + 2, "");
+ Stream_printf(f, "_$jscoverage['%s'].conditionals[%d] = %d;\n", file_id, else_start, else_end);
+ }
+ instrument_statement(node->pn_kid2, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+
+ if (node->pn_kid3 || is_jscoverage_if) {
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "else {\n");
+
+ if (is_jscoverage_if) {
+ uint16_t if_start = node->pn_kid2->pn_pos.begin.lineno + 1;
+ uint16_t if_end = node->pn_kid2->pn_pos.end.lineno + 1;
+ Stream_printf(f, "%*s", indent + 2, "");
+ Stream_printf(f, "_$jscoverage['%s'].conditionals[%d] = %d;\n", file_id, if_start, if_end);
+ }
+
+ if (node->pn_kid3) {
+ instrument_statement(node->pn_kid3, f, indent + 2, is_jscoverage_if);
+ }
+
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ }
+
+ break;
+ }
+ case TOK_SWITCH:
+ assert(node->pn_arity == PN_BINARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "switch (");
+ output_expression(node->pn_left, f, false);
+ Stream_write_string(f, ") {\n");
+ {
+ JSParseNode * list = node->pn_right;
+ if (list->pn_type == TOK_LEXICALSCOPE) {
+ list = list->pn_expr;
+ }
+ for (struct JSParseNode * p = list->pn_head; p != NULL; p = p->pn_next) {
+ Stream_printf(f, "%*s", indent, "");
+ switch (p->pn_type) {
+ case TOK_CASE:
+ Stream_write_string(f, "case ");
+ output_expression(p->pn_left, f, false);
+ Stream_write_string(f, ":\n");
+ break;
+ case TOK_DEFAULT:
+ Stream_write_string(f, "default:\n");
+ break;
+ default:
+ abort();
+ break;
+ }
+ instrument_statement(p->pn_right, f, indent + 2, false);
+ }
+ }
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ break;
+ case TOK_CASE:
+ case TOK_DEFAULT:
+ abort();
+ break;
+ case TOK_WHILE:
+ assert(node->pn_arity == PN_BINARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "while (");
+ output_expression(node->pn_left, f, false);
+ Stream_write_string(f, ") {\n");
+ instrument_statement(node->pn_right, f, indent + 2, false);
+ Stream_write_string(f, "}\n");
+ break;
+ case TOK_DO:
+ assert(node->pn_arity == PN_BINARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "do {\n");
+ instrument_statement(node->pn_left, f, indent + 2, false);
+ Stream_write_string(f, "}\n");
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "while (");
+ output_expression(node->pn_right, f, false);
+ Stream_write_string(f, ");\n");
+ break;
+ case TOK_FOR:
+ assert(node->pn_arity == PN_BINARY);
+ Stream_printf(f, "%*s", indent, "");
+ switch (node->pn_left->pn_type) {
+ case TOK_IN:
+ /* for/in */
+ assert(node->pn_left->pn_arity == PN_BINARY);
+ output_for_in(node, f);
+ break;
+ case TOK_FORHEAD:
+ /* for (;;) */
+ assert(node->pn_left->pn_arity == PN_TERNARY);
+ Stream_write_string(f, "for (");
+ if (node->pn_left->pn_kid1) {
+ output_expression(node->pn_left->pn_kid1, f, false);
+ }
+ Stream_write_string(f, ";");
+ if (node->pn_left->pn_kid2) {
+ Stream_write_char(f, ' ');
+ output_expression(node->pn_left->pn_kid2, f, false);
+ }
+ Stream_write_string(f, ";");
+ if (node->pn_left->pn_kid3) {
+ Stream_write_char(f, ' ');
+ output_expression(node->pn_left->pn_kid3, f, false);
+ }
+ Stream_write_char(f, ')');
+ break;
+ default:
+ abort();
+ break;
+ }
+ Stream_write_string(f, " {\n");
+ instrument_statement(node->pn_right, f, indent + 2, false);
+ Stream_write_string(f, "}\n");
+ break;
+ case TOK_THROW:
+ assert(node->pn_arity == PN_UNARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "throw ");
+ output_expression(node->pn_u.unary.kid, f, false);
+ Stream_write_string(f, ";\n");
+ break;
+ case TOK_TRY:
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "try {\n");
+ instrument_statement(node->pn_kid1, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ if (node->pn_kid2) {
+ assert(node->pn_kid2->pn_type == TOK_RESERVED);
+ for (JSParseNode * scope = node->pn_kid2->pn_head; scope != NULL; scope = scope->pn_next) {
+ assert(scope->pn_type == TOK_LEXICALSCOPE);
+ JSParseNode * catch_node = scope->pn_expr;
+ assert(catch_node->pn_type == TOK_CATCH);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "catch (");
+ output_expression(catch_node->pn_kid1, f, false);
+ if (catch_node->pn_kid2) {
+ Stream_write_string(f, " if ");
+ output_expression(catch_node->pn_kid2, f, false);
+ }
+ Stream_write_string(f, ") {\n");
+ instrument_statement(catch_node->pn_kid3, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ }
+ }
+ if (node->pn_kid3) {
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "finally {\n");
+ instrument_statement(node->pn_kid3, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ }
+ break;
+ case TOK_CATCH:
+ abort();
+ break;
+ case TOK_BREAK:
+ case TOK_CONTINUE:
+ assert(node->pn_arity == PN_NAME || node->pn_arity == PN_NULLARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, node->pn_type == TOK_BREAK? "break": "continue");
+ if (node->pn_atom != NULL) {
+ Stream_write_char(f, ' ');
+ print_string_atom(node->pn_atom, f);
+ }
+ Stream_write_string(f, ";\n");
+ break;
+ case TOK_WITH:
+ assert(node->pn_arity == PN_BINARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "with (");
+ output_expression(node->pn_left, f, false);
+ Stream_write_string(f, ") {\n");
+ instrument_statement(node->pn_right, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ break;
+ case TOK_VAR:
+ Stream_printf(f, "%*s", indent, "");
+ output_expression(node, f, false);
+ Stream_write_string(f, ";\n");
+ break;
+ case TOK_RETURN:
+ assert(node->pn_arity == PN_UNARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "return");
+ if (node->pn_kid != NULL) {
+ Stream_write_char(f, ' ');
+ output_expression(node->pn_kid, f, true);
+ }
+ Stream_write_string(f, ";\n");
+ break;
+ case TOK_SEMI:
+ assert(node->pn_arity == PN_UNARY);
+ Stream_printf(f, "%*s", indent, "");
+ if (node->pn_kid != NULL) {
+ output_expression(node->pn_kid, f, true);
+ }
+ Stream_write_string(f, ";\n");
+ break;
+ case TOK_COLON:
+ {
+ assert(node->pn_arity == PN_NAME);
+ Stream_printf(f, "%*s", indent < 2? 0: indent - 2, "");
+ print_string_atom(node->pn_atom, f);
+ Stream_write_string(f, ":\n");
+ JSParseNode * labelled = node->pn_expr;
+ if (labelled->pn_type == TOK_LEXICALSCOPE) {
+ labelled = labelled->pn_expr;
+ }
+ if (labelled->pn_type == TOK_LC) {
+ /* labelled block */
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "{\n");
+ instrument_statement(labelled, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ }
+ else {
+ /*
+ This one is tricky: can't output instrumentation between the label and the
+ statement it's supposed to label, so use output_statement instead of
+ instrument_statement.
+ */
+ output_statement(labelled, f, indent, false);
+ }
+ break;
+ }
+ case TOK_LEXICALSCOPE:
+ /* let statement */
+ assert(node->pn_arity == PN_NAME);
+ switch (node->pn_expr->pn_type) {
+ case TOK_LET:
+ /* let statement */
+ assert(node->pn_expr->pn_arity == PN_BINARY);
+ instrument_statement(node->pn_expr, f, indent, false);
+ break;
+ case TOK_LC:
+ /* block */
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "{\n");
+ instrument_statement(node->pn_expr, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ break;
+ case TOK_FOR:
+ instrument_statement(node->pn_expr, f, indent, false);
+ break;
+ default:
+ abort();
+ break;
+ }
+ break;
+ case TOK_LET:
+ switch (node->pn_arity) {
+ case PN_BINARY:
+ /* let statement */
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "let (");
+ assert(node->pn_left->pn_type == TOK_LP);
+ assert(node->pn_left->pn_arity == PN_LIST);
+ instrument_declarations(node->pn_left, f);
+ Stream_write_string(f, ") {\n");
+ instrument_statement(node->pn_right, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ break;
+ case PN_LIST:
+ /* let definition */
+ Stream_printf(f, "%*s", indent, "");
+ output_expression(node, f, false);
+ Stream_write_string(f, ";\n");
+ break;
+ default:
+ abort();
+ break;
+ }
+ break;
+ case TOK_DEBUGGER:
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "debugger;\n");
+ break;
+ case TOK_SEQ:
+ /*
+ This occurs with the statement:
+ for (var a = b in c) {}
+ */
+ assert(node->pn_arity == PN_LIST);
+ for (JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
+ instrument_statement(p, f, indent, false);
+ }
+ break;
+ default:
+ fatal_source(file_id, node->pn_pos.begin.lineno, "unsupported node type (%d)", node->pn_type);
+ }
+}
+
+/*
+See <Statements> in jsparse.h.
+TOK_FUNCTION is handled as a statement and as an expression.
+TOK_EXPORT, TOK_IMPORT are not handled.
+*/
+static void instrument_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if) {
+ if (node->pn_type != TOK_LC && node->pn_type != TOK_LEXICALSCOPE) {
+ uint16_t line = node->pn_pos.begin.lineno;
+ if (line > num_lines) {
+ fatal("file %s contains more than 65,535 lines", file_id);
+ }
+
+ /* the root node has line number 0 */
+ if (line != 0) {
+ Stream_printf(f, "%*s", indent, "");
+ Stream_printf(f, "_$jscoverage['%s'][%d]++;\n", file_id, line);
+ lines[line - 1] = 1;
+ }
+ }
+ output_statement(node, f, indent, is_jscoverage_if);
+}
+
+static bool characters_start_with(const jschar * characters, size_t line_start, size_t line_end, const char * prefix) {
+ const jschar * characters_end = characters + line_end;
+ const jschar * cp = characters + line_start;
+ const char * bp = prefix;
+ for (;;) {
+ if (*bp == '\0') {
+ return true;
+ }
+ else if (cp == characters_end) {
+ return false;
+ }
+ else if (*cp != *bp) {
+ return false;
+ }
+ bp++;
+ cp++;
+ }
+}
+
+static bool characters_are_white_space(const jschar * characters, size_t line_start, size_t line_end) {
+ /* XXX - other Unicode space */
+ const jschar * end = characters + line_end;
+ for (const jschar * p = characters + line_start; p < end; p++) {
+ jschar c = *p;
+ if (c == 0x9 || c == 0xB || c == 0xC || c == 0x20 || c == 0xA0) {
+ continue;
+ }
+ else {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void error_reporter(JSContext * context, const char * message, JSErrorReport * report) {
+ warn_source(file_id, report->lineno, "%s", message);
+}
+
+void jscoverage_instrument_js(const char * id, const uint16_t * characters, size_t num_characters, Stream * output) {
+ file_id = id;
+
+ /* parse the javascript */
+ JSParseContext parse_context;
+ if (! js_InitParseContext(context, &parse_context, NULL, NULL, characters, num_characters, NULL, NULL, 1)) {
+ fatal("cannot create token stream from file %s", file_id);
+ }
+ JSErrorReporter old_error_reporter = JS_SetErrorReporter(context, error_reporter);
+ JSParseNode * node = js_ParseScript(context, global, &parse_context);
+ if (node == NULL) {
+ js_ReportUncaughtException(context);
+ fatal("parse error in file %s", file_id);
+ }
+ JS_SetErrorReporter(context, old_error_reporter);
+ num_lines = node->pn_pos.end.lineno;
+ lines = (char *) xmalloc(num_lines);
+ for (unsigned int i = 0; i < num_lines; i++) {
+ lines[i] = 0;
+ }
+
+ /* search code for conditionals */
+ exclusive_directives = xnew(bool, num_lines);
+ for (unsigned int i = 0; i < num_lines; i++) {
+ exclusive_directives[i] = false;
+ }
+
+ bool has_conditionals = false;
+ struct IfDirective * if_directives = NULL;
+ size_t line_number = 0;
+ size_t i = 0;
+ while (i < num_characters) {
+ if (line_number == UINT16_MAX) {
+ fatal("file %s contains more than 65,535 lines", file_id);
+ }
+ line_number++;
+ size_t line_start = i;
+ jschar c;
+ bool done = false;
+ while (! done && i < num_characters) {
+ c = characters[i];
+ switch (c) {
+ case '\r':
+ case '\n':
+ case 0x2028:
+ case 0x2029:
+ done = true;
+ break;
+ default:
+ i++;
+ }
+ }
+ size_t line_end = i;
+ if (i < num_characters) {
+ i++;
+ if (c == '\r' && i < num_characters && characters[i] == '\n') {
+ i++;
+ }
+ }
+
+ if (characters_start_with(characters, line_start, line_end, "//#JSCOVERAGE_IF")) {
+ has_conditionals = true;
+
+ if (characters_are_white_space(characters, line_start + 16, line_end)) {
+ exclusive_directives[line_number - 1] = true;
+ }
+ else {
+ struct IfDirective * if_directive = xnew(struct IfDirective, 1);
+ if_directive->condition_start = characters + line_start + 16;
+ if_directive->condition_end = characters + line_end;
+ if_directive->start_line = line_number;
+ if_directive->end_line = 0;
+ if_directive->next = if_directives;
+ if_directives = if_directive;
+ }
+ }
+ else if (characters_start_with(characters, line_start, line_end, "//#JSCOVERAGE_ENDIF")) {
+ for (struct IfDirective * p = if_directives; p != NULL; p = p->next) {
+ if (p->end_line == 0) {
+ p->end_line = line_number;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ An instrumented JavaScript file has 4 sections:
+ 1. initialization
+ 2. instrumented source code
+ 3. conditionals
+ 4. original source code
+ */
+
+ Stream * instrumented = Stream_new(0);
+ instrument_statement(node, instrumented, 0, false);
+ js_FinishParseContext(context, &parse_context);
+
+ /* write line number info to the output */
+ Stream_write_string(output, "/* automatically generated by JSCoverage - do not edit */\n");
+ Stream_write_string(output, "if (typeof _$jscoverage === 'undefined') _$jscoverage = {};\n");
+ Stream_printf(output, "if (! _$jscoverage['%s']) {\n", file_id);
+ Stream_printf(output, " _$jscoverage['%s'] = [];\n", file_id);
+ for (int i = 0; i < num_lines; i++) {
+ if (lines[i]) {
+ Stream_printf(output, " _$jscoverage['%s'][%d] = 0;\n", file_id, i + 1);
+ }
+ }
+ Stream_write_string(output, "}\n");
+ free(lines);
+ lines = NULL;
+ free(exclusive_directives);
+ exclusive_directives = NULL;
+
+ /* conditionals */
+ if (has_conditionals) {
+ Stream_printf(output, "_$jscoverage['%s'].conditionals = [];\n", file_id);
+ }
+
+ /* copy the instrumented source code to the output */
+ Stream_write(output, instrumented->data, instrumented->length);
+
+ /* conditionals */
+ for (struct IfDirective * if_directive = if_directives; if_directive != NULL; if_directive = if_directive->next) {
+ Stream_write_string(output, "if (!(");
+ print_javascript(if_directive->condition_start, if_directive->condition_end - if_directive->condition_start, output);
+ Stream_write_string(output, ")) {\n");
+ Stream_printf(output, " _$jscoverage['%s'].conditionals[%d] = %d;\n", file_id, if_directive->start_line, if_directive->end_line);
+ Stream_write_string(output, "}\n");
+ }
+
+ /* free */
+ while (if_directives != NULL) {
+ struct IfDirective * if_directive = if_directives;
+ if_directives = if_directives->next;
+ free(if_directive);
+ }
+
+ /* copy the original source to the output */
+ Stream_printf(output, "_$jscoverage['%s'].source = ", file_id);
+ jscoverage_write_source(id, characters, num_characters, output);
+ Stream_printf(output, ";\n");
+
+ Stream_delete(instrumented);
+
+ file_id = NULL;
+}
+
+void jscoverage_write_source(const char * id, const jschar * characters, size_t num_characters, Stream * output) {
+ Stream_write_string(output, "[");
+ if (jscoverage_highlight) {
+ Stream * highlighted_stream = Stream_new(num_characters);
+ jscoverage_highlight_js(context, id, characters, num_characters, highlighted_stream);
+ size_t i = 0;
+ while (i < highlighted_stream->length) {
+ if (i > 0) {
+ Stream_write_char(output, ',');
+ }
+
+ Stream_write_char(output, '"');
+ bool done = false;
+ while (! done) {
+ char c = highlighted_stream->data[i];
+ switch (c) {
+ case 0x8:
+ /* backspace */
+ Stream_write_string(output, "\\b");
+ break;
+ case 0x9:
+ /* horizontal tab */
+ Stream_write_string(output, "\\t");
+ break;
+ case 0xa:
+ /* line feed (new line) */
+ done = true;
+ break;
+ /* IE doesn't support this */
+ /*
+ case 0xb:
+ Stream_write_string(output, "\\v");
+ break;
+ */
+ case 0xc:
+ /* form feed */
+ Stream_write_string(output, "\\f");
+ break;
+ case 0xd:
+ /* carriage return */
+ done = true;
+ if (i + 1 < highlighted_stream->length && highlighted_stream->data[i + 1] == '\n') {
+ i++;
+ }
+ break;
+ case '"':
+ Stream_write_string(output, "\\\"");
+ break;
+ case '\\':
+ Stream_write_string(output, "\\\\");
+ break;
+ default:
+ Stream_write_char(output, c);
+ break;
+ }
+ i++;
+ if (i >= highlighted_stream->length) {
+ done = true;
+ }
+ }
+ Stream_write_char(output, '"');
+ }
+ Stream_delete(highlighted_stream);
+ }
+ else {
+ size_t i = 0;
+ while (i < num_characters) {
+ if (i > 0) {
+ Stream_write_char(output, ',');
+ }
+
+ Stream_write_char(output, '"');
+ bool done = false;
+ while (! done) {
+ jschar c = characters[i];
+ switch (c) {
+ case 0x8:
+ /* backspace */
+ Stream_write_string(output, "\\b");
+ break;
+ case 0x9:
+ /* horizontal tab */
+ Stream_write_string(output, "\\t");
+ break;
+ case 0xa:
+ /* line feed (new line) */
+ done = true;
+ break;
+ /* IE doesn't support this */
+ /*
+ case 0xb:
+ Stream_write_string(output, "\\v");
+ break;
+ */
+ case 0xc:
+ /* form feed */
+ Stream_write_string(output, "\\f");
+ break;
+ case 0xd:
+ /* carriage return */
+ done = true;
+ if (i + 1 < num_characters && characters[i + 1] == '\n') {
+ i++;
+ }
+ break;
+ case '"':
+ Stream_write_string(output, "\\\"");
+ break;
+ case '\\':
+ Stream_write_string(output, "\\\\");
+ break;
+ case '&':
+ Stream_write_string(output, "&amp;");
+ break;
+ case '<':
+ Stream_write_string(output, "&lt;");
+ break;
+ case '>':
+ Stream_write_string(output, "&gt;");
+ break;
+ case 0x2028:
+ case 0x2029:
+ done = true;
+ break;
+ default:
+ if (32 <= c && c <= 126) {
+ Stream_write_char(output, c);
+ }
+ else {
+ Stream_printf(output, "&#%d;", c);
+ }
+ break;
+ }
+ i++;
+ if (i >= num_characters) {
+ done = true;
+ }
+ }
+ Stream_write_char(output, '"');
+ }
+ }
+ Stream_write_string(output, "]");
+}
+
+void jscoverage_copy_resources(const char * destination_directory) {
+ copy_resource("jscoverage.html", destination_directory);
+ copy_resource("jscoverage.css", destination_directory);
+ copy_resource("jscoverage.js", destination_directory);
+ copy_resource("jscoverage-ie.css", destination_directory);
+ copy_resource("jscoverage-throbber.gif", destination_directory);
+ copy_resource("jscoverage-highlight.css", destination_directory);
+}
+
+/*
+coverage reports
+*/
+
+struct FileCoverageList {
+ FileCoverage * file_coverage;
+ struct FileCoverageList * next;
+};
+
+struct Coverage {
+ JSHashTable * coverage_table;
+ struct FileCoverageList * coverage_list;
+};
+
+static int compare_strings(const void * p1, const void * p2) {
+ return strcmp((const char *) p1, (const char *) p2) == 0;
+}
+
+Coverage * Coverage_new(void) {
+ Coverage * result = (Coverage *) xmalloc(sizeof(Coverage));
+ result->coverage_table = JS_NewHashTable(1024, JS_HashString, compare_strings, NULL, NULL, NULL);
+ if (result->coverage_table == NULL) {
+ fatal("cannot create hash table");
+ }
+ result->coverage_list = NULL;
+ return result;
+}
+
+void Coverage_delete(Coverage * coverage) {
+ JS_HashTableDestroy(coverage->coverage_table);
+ struct FileCoverageList * p = coverage->coverage_list;
+ while (p != NULL) {
+ free(p->file_coverage->coverage_lines);
+ if (p->file_coverage->source_lines != NULL) {
+ for (uint32 i = 0; i < p->file_coverage->num_source_lines; i++) {
+ free(p->file_coverage->source_lines[i]);
+ }
+ free(p->file_coverage->source_lines);
+ }
+ free(p->file_coverage->id);
+ free(p->file_coverage);
+ struct FileCoverageList * q = p;
+ p = p->next;
+ free(q);
+ }
+ free(coverage);
+}
+
+struct EnumeratorArg {
+ CoverageForeachFunction f;
+ void * p;
+};
+
+static intN enumerator(JSHashEntry * entry, intN i, void * arg) {
+ struct EnumeratorArg * enumerator_arg = (struct EnumeratorArg *) arg;
+ enumerator_arg->f((FileCoverage *) entry->value, i, enumerator_arg->p);
+ return 0;
+}
+
+void Coverage_foreach_file(Coverage * coverage, CoverageForeachFunction f, void * p) {
+ struct EnumeratorArg enumerator_arg;
+ enumerator_arg.f = f;
+ enumerator_arg.p = p;
+ JS_HashTableEnumerateEntries(coverage->coverage_table, enumerator, &enumerator_arg);
+}
+
+int jscoverage_parse_json(Coverage * coverage, const uint8_t * json, size_t length) {
+ int result = 0;
+
+ jschar * base = js_InflateString(context, (char *) json, &length);
+ if (base == NULL) {
+ fatal("out of memory");
+ }
+
+ jschar * parenthesized_json = xnew(jschar, addst(length, 2));
+ parenthesized_json[0] = '(';
+ memcpy(parenthesized_json + 1, base, mulst(length, sizeof(jschar)));
+ parenthesized_json[length + 1] = ')';
+
+ JS_free(context, base);
+
+ JSParseContext parse_context;
+ if (! js_InitParseContext(context, &parse_context, NULL, NULL, parenthesized_json, length + 2, NULL, NULL, 1)) {
+ free(parenthesized_json);
+ return -1;
+ }
+ JSParseNode * root = js_ParseScript(context, global, &parse_context);
+ free(parenthesized_json);
+
+ JSParseNode * semi = NULL;
+ JSParseNode * object = NULL;
+
+ if (root == NULL) {
+ result = -1;
+ goto done;
+ }
+
+ /* root node must be TOK_LC */
+ if (root->pn_type != TOK_LC) {
+ result = -1;
+ goto done;
+ }
+ semi = root->pn_u.list.head;
+
+ /* the list must be TOK_SEMI and it must contain only one element */
+ if (semi->pn_type != TOK_SEMI || semi->pn_next != NULL) {
+ result = -1;
+ goto done;
+ }
+ object = semi->pn_kid;
+
+ /* this must be an object literal */
+ if (object->pn_type != TOK_RC) {
+ result = -1;
+ goto done;
+ }
+
+ for (JSParseNode * p = object->pn_head; p != NULL; p = p->pn_next) {
+ /* every element of this list must be TOK_COLON */
+ if (p->pn_type != TOK_COLON) {
+ result = -1;
+ goto done;
+ }
+
+ /* the key must be a string representing the file */
+ JSParseNode * key = p->pn_left;
+ if (key->pn_type != TOK_STRING || ! ATOM_IS_STRING(key->pn_atom)) {
+ result = -1;
+ goto done;
+ }
+ char * id_bytes = JS_GetStringBytes(ATOM_TO_STRING(key->pn_atom));
+
+ /* the value must be an object literal OR an array */
+ JSParseNode * value = p->pn_right;
+ if (! (value->pn_type == TOK_RC || value->pn_type == TOK_RB)) {
+ result = -1;
+ goto done;
+ }
+
+ JSParseNode * array = NULL;
+ JSParseNode * source = NULL;
+ if (value->pn_type == TOK_RB) {
+ /* an array */
+ array = value;
+ }
+ else if (value->pn_type == TOK_RC) {
+ /* an object literal */
+ if (value->pn_count != 2) {
+ result = -1;
+ goto done;
+ }
+ for (JSParseNode * element = value->pn_head; element != NULL; element = element->pn_next) {
+ if (element->pn_type != TOK_COLON) {
+ result = -1;
+ goto done;
+ }
+ JSParseNode * left = element->pn_left;
+ if (left->pn_type != TOK_STRING || ! ATOM_IS_STRING(left->pn_atom)) {
+ result = -1;
+ goto done;
+ }
+ const char * s = JS_GetStringBytes(ATOM_TO_STRING(left->pn_atom));
+ if (strcmp(s, "coverage") == 0) {
+ array = element->pn_right;
+ if (array->pn_type != TOK_RB) {
+ result = -1;
+ goto done;
+ }
+ }
+ else if (strcmp(s, "source") == 0) {
+ source = element->pn_right;
+ if (source->pn_type != TOK_RB) {
+ result = -1;
+ goto done;
+ }
+ }
+ else {
+ result = -1;
+ goto done;
+ }
+ }
+ }
+ else {
+ result = -1;
+ goto done;
+ }
+
+ if (array == NULL) {
+ result = -1;
+ goto done;
+ }
+
+ /* look up the file in the coverage table */
+ FileCoverage * file_coverage = (FileCoverage *) JS_HashTableLookup(coverage->coverage_table, id_bytes);
+ if (file_coverage == NULL) {
+ /* not there: create a new one */
+ char * id = xstrdup(id_bytes);
+ file_coverage = (FileCoverage *) xmalloc(sizeof(FileCoverage));
+ file_coverage->id = id;
+ file_coverage->num_coverage_lines = array->pn_count;
+ file_coverage->coverage_lines = xnew(int, array->pn_count);
+ file_coverage->source_lines = NULL;
+
+ /* set coverage for all lines */
+ uint32 i = 0;
+ for (JSParseNode * element = array->pn_head; element != NULL; element = element->pn_next, i++) {
+ if (element->pn_type == TOK_NUMBER) {
+ file_coverage->coverage_lines[i] = (int) element->pn_dval;
+ }
+ else if (element->pn_type == TOK_PRIMARY && element->pn_op == JSOP_NULL) {
+ file_coverage->coverage_lines[i] = -1;
+ }
+ else {
+ result = -1;
+ goto done;
+ }
+ }
+ assert(i == array->pn_count);
+
+ /* add to the hash table */
+ JS_HashTableAdd(coverage->coverage_table, id, file_coverage);
+ struct FileCoverageList * coverage_list = (FileCoverageList *) xmalloc(sizeof(struct FileCoverageList));
+ coverage_list->file_coverage = file_coverage;
+ coverage_list->next = coverage->coverage_list;
+ coverage->coverage_list = coverage_list;
+ }
+ else {
+ /* sanity check */
+ assert(strcmp(file_coverage->id, id_bytes) == 0);
+ if (file_coverage->num_coverage_lines != array->pn_count) {
+ result = -2;
+ goto done;
+ }
+
+ /* merge the coverage */
+ uint32 i = 0;
+ for (JSParseNode * element = array->pn_head; element != NULL; element = element->pn_next, i++) {
+ if (element->pn_type == TOK_NUMBER) {
+ if (file_coverage->coverage_lines[i] == -1) {
+ result = -2;
+ goto done;
+ }
+ file_coverage->coverage_lines[i] += (int) element->pn_dval;
+ }
+ else if (element->pn_type == TOK_PRIMARY && element->pn_op == JSOP_NULL) {
+ if (file_coverage->coverage_lines[i] != -1) {
+ result = -2;
+ goto done;
+ }
+ }
+ else {
+ result = -1;
+ goto done;
+ }
+ }
+ assert(i == array->pn_count);
+ }
+
+ /* if this JSON file has source, use it */
+ if (file_coverage->source_lines == NULL && source != NULL) {
+ file_coverage->num_source_lines = source->pn_count;
+ file_coverage->source_lines = xnew(char *, source->pn_count);
+ uint32 i = 0;
+ for (JSParseNode * element = source->pn_head; element != NULL; element = element->pn_next, i++) {
+ if (element->pn_type != TOK_STRING) {
+ result = -1;
+ goto done;
+ }
+ file_coverage->source_lines[i] = xstrdup(JS_GetStringBytes(ATOM_TO_STRING(element->pn_atom)));
+ }
+ assert(i == source->pn_count);
+ }
+ }
+
+done:
+ js_FinishParseContext(context, &parse_context);
+ return result;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/instrument-js.h b/tools/node_modules/expresso/deps/jscoverage/instrument-js.h
new file mode 100644
index 0000000..07c60ab
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/instrument-js.h
@@ -0,0 +1,81 @@
+/*
+ instrument-js.h - JavaScript instrumentation routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef INSTRUMENT_JS_H_
+#define INSTRUMENT_JS_H_
+
+/* ISO C99 specifies that C++ code must define this to get UINT16_MAX etc. */
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
+#include "stream.h"
+#include "util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum FileType {
+ FILE_TYPE_JS,
+ FILE_TYPE_HTML,
+ FILE_TYPE_OTHER
+};
+
+extern bool jscoverage_mozilla;
+
+void jscoverage_set_js_version(const char * version);
+
+void jscoverage_init(void);
+
+void jscoverage_cleanup(void);
+
+void jscoverage_instrument_js(const char * id, const uint16_t * characters, size_t num_characters, Stream * output);
+
+void jscoverage_copy_resources(const char * destination_directory);
+
+typedef struct Coverage Coverage;
+
+typedef struct FileCoverage {
+ char * id;
+
+ int * coverage_lines;
+ char ** source_lines;
+
+ /* SpiderMonkey uses uint32 for array lengths */
+ uint32_t num_coverage_lines;
+ uint32_t num_source_lines;
+} FileCoverage;
+
+Coverage * Coverage_new(void);
+
+void Coverage_delete(Coverage * coverage);
+
+typedef void (*CoverageForeachFunction) (const FileCoverage * file_coverage, int i, void * p);
+
+void Coverage_foreach_file(Coverage * coverage, CoverageForeachFunction f, void * p);
+
+int jscoverage_parse_json(Coverage * coverage, const uint8_t * data, size_t length) __attribute__((warn_unused_result));
+
+void jscoverage_write_source(const char * id, const uint16_t * characters, size_t num_characters, Stream * output);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INSTRUMENT_JS_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/instrument.c b/tools/node_modules/expresso/deps/jscoverage/instrument.c
new file mode 100644
index 0000000..d19b690
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/instrument.c
@@ -0,0 +1,226 @@
+/*
+ instrument.c - file and directory instrumentation routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "instrument.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "encoding.h"
+#include "global.h"
+#include "instrument-js.h"
+#include "resource-manager.h"
+#include "util.h"
+
+static int g_verbose = 0;
+
+static int string_ends_with(const char * s, const char * suffix) {
+ size_t length = strlen(s);
+ size_t suffix_length = strlen(suffix);
+ if (length < suffix_length) {
+ return 0;
+ }
+ return strcasecmp(s + (length - suffix_length), suffix) == 0;
+}
+
+static enum FileType get_file_type(const char * file) {
+ if (string_ends_with(file, ".js")) {
+ return FILE_TYPE_JS;
+ }
+ else if (string_ends_with(file, ".html") || string_ends_with(file, ".htm")) {
+ return FILE_TYPE_HTML;
+ }
+ else {
+ return FILE_TYPE_OTHER;
+ }
+}
+
+static void check_same_file(const char * file1, const char * file2) {
+ if (is_same_file(file1, file2)) {
+ fatal("source and destination are the same");
+ }
+}
+
+static void check_contains_file(const char * file1, const char * file2) {
+ if (contains_file(file1, file2)) {
+ fatal("%s contains %s", file1, file2);
+ }
+}
+
+static void instrument_file(const char * source_file, const char * destination_file, const char * id, int instrumenting) {
+ if (g_verbose) {
+ printf("Instrumenting file %s\n", id);
+ }
+
+ /* check if they are the same */
+ char * canonical_source_file = make_canonical_path(source_file);
+ char * canonical_destination_file = make_canonical_path(destination_file);
+ check_same_file(canonical_source_file, canonical_destination_file);
+ free(canonical_source_file);
+ free(canonical_destination_file);
+
+ if (instrumenting) {
+ enum FileType file_type = get_file_type(source_file);
+ switch (file_type) {
+ case FILE_TYPE_OTHER:
+ case FILE_TYPE_HTML:
+ copy_file(source_file, destination_file);
+ break;
+ case FILE_TYPE_JS:
+ {
+ FILE * input = xfopen(source_file, "rb");
+ FILE * output = xfopen(destination_file, "wb");
+
+ Stream * input_stream = Stream_new(0);
+ Stream * output_stream = Stream_new(0);
+
+ Stream_write_file_contents(input_stream, input);
+
+ size_t num_characters = input_stream->length;
+ uint16_t * characters = NULL;
+ int result = jscoverage_bytes_to_characters(jscoverage_encoding, input_stream->data, input_stream->length, &characters, &num_characters);
+ if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) {
+ fatal("encoding %s not supported", jscoverage_encoding);
+ }
+ else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) {
+ fatal("error decoding %s in file %s", jscoverage_encoding, id);
+ }
+ jscoverage_instrument_js(id, characters, num_characters, output_stream);
+ free(characters);
+
+ if (fwrite(output_stream->data, 1, output_stream->length, output) != output_stream->length) {
+ fatal("cannot write to file: %s", destination_file);
+ }
+
+ Stream_delete(input_stream);
+ Stream_delete(output_stream);
+
+ fclose(input);
+ fclose(output);
+ }
+ break;
+ }
+ }
+ else {
+ copy_file(source_file, destination_file);
+ }
+}
+
+void jscoverage_instrument(const char * source,
+ const char * destination,
+ int verbose,
+ char ** exclude,
+ int num_exclude,
+ char ** no_instrument,
+ int num_no_instrument)
+{
+ assert(source != NULL);
+ assert(destination != NULL);
+
+ g_verbose = verbose;
+
+ /* check if they are the same */
+ check_same_file(source, destination);
+
+ /* check if source directory is an ancestor of destination directory */
+ check_contains_file(source, destination);
+
+ /* check that the source exists and is a directory */
+ struct stat buf;
+ xstat(source, &buf);
+ if (! S_ISDIR(buf.st_mode)) {
+ fatal("not a directory: %s", source);
+ }
+
+ /* if the destination directory exists, check that it is a jscoverage directory */
+ if (stat(destination, &buf) == 0) {
+ /* it exists */
+ if (! S_ISDIR(buf.st_mode)) {
+ fatal("not a directory: %s", destination);
+ }
+ if (! directory_is_empty(destination)) {
+ char * expected_file = NULL;
+ if (jscoverage_mozilla) {
+ char * modules_directory = make_path(destination, "modules");
+ expected_file = make_path(modules_directory, "jscoverage.jsm");
+ free(modules_directory);
+ }
+ else {
+ expected_file = make_path(destination, "jscoverage.html");
+ }
+ if (stat(expected_file, &buf) == -1) {
+ fatal("refusing to overwrite directory: %s", destination);
+ }
+ free(expected_file);
+ }
+ }
+ else if (errno == ENOENT) {
+ xmkdir(destination);
+ }
+ else {
+ fatal("cannot stat directory: %s", destination);
+ }
+
+ /* finally: copy the directory */
+ struct DirListEntry * list = make_recursive_dir_list(source);
+ for (struct DirListEntry * p = list; p != NULL; p = p->next) {
+ char * s = make_path(source, p->name);
+ char * d = make_path(destination, p->name);
+
+ /* check if it's on the exclude list */
+ for (int i = 0; i < num_exclude; i++) {
+ char * x = make_path(source, exclude[i]);
+ if (is_same_file(x, s) || contains_file(x, s)) {
+ free(x);
+ goto cleanup;
+ }
+ free(x);
+ }
+
+ char * dd = make_dirname(d);
+ mkdirs(dd);
+ free(dd);
+
+ int instrument_this = 1;
+
+ /* check if it's on the no-instrument list */
+ for (int i = 0; i < num_no_instrument; i++) {
+ char * ni = make_path(source, no_instrument[i]);
+ if (is_same_file(ni, s) || contains_file(ni, s)) {
+ instrument_this = 0;
+ }
+ free(ni);
+ }
+
+ instrument_file(s, d, p->name, instrument_this);
+
+ cleanup:
+ free(s);
+ free(d);
+ }
+
+ free_dir_list(list);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/instrument.h b/tools/node_modules/expresso/deps/jscoverage/instrument.h
new file mode 100644
index 0000000..a8720b0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/instrument.h
@@ -0,0 +1,31 @@
+/*
+ instrument.h - file and directory instrumentation routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef INSTRUMENT_H_
+#define INSTRUMENT_H_
+
+void jscoverage_instrument(const char * source,
+ const char * destination,
+ int verbose,
+ char ** exclude,
+ int num_exclude,
+ char ** no_instrument,
+ int num_no_instrument);
+
+#endif /* INSTRUMENT_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/GNUmakefile b/tools/node_modules/expresso/deps/jscoverage/js/GNUmakefile
new file mode 100644
index 0000000..2548cf6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/GNUmakefile
@@ -0,0 +1,15 @@
+overrides = DISABLE_JIT=1 OBJROOT=obj BUILD_OPT=1
+uname = $(shell uname)
+ifeq "$(findstring CYGWIN,$(uname))" "CYGWIN"
+overrides += OS_CONFIG=Cygwin OS_ARCH=Cygwin
+else
+ifeq "$(findstring MINGW,$(uname))" "MINGW"
+overrides += OS_CONFIG=MSYS OS_ARCH=MSYS
+endif
+endif
+
+all:
+ $(MAKE) -f Makefile.ref $(overrides)
+
+clean:
+ $(MAKE) -f Makefile.ref $(overrides) clean
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/Makefile.ref b/tools/node_modules/expresso/deps/jscoverage/js/Makefile.ref
new file mode 100644
index 0000000..97803e9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/Makefile.ref
@@ -0,0 +1,483 @@
+# -*- Mode: makefile -*-
+# vim: ft=make
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Michael Ang <mang@subcarrier.org>
+# Kevin Buhr <buhr@stat.wisc.edu>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# JSRef GNUmake makefile.
+#
+# Note: dependency rules are missing for some files (some
+# .h, all .msg, etc.) Re-make clean if in doubt.
+#
+
+
+DEPTH = .
+
+include config.mk
+
+#NS_USE_NATIVE = 1
+
+ifndef NANOJIT_ARCH
+$(warning NANOJIT_ARCH not defined in config/$(OS_CONFIG).mk, JIT disabled)
+else
+ifdef DISABLE_JIT
+$(warning disabling JIT per build specification)
+else
+ENABLE_JIT=1
+endif
+endif
+
+ifdef ENABLE_JIT
+DEFINES += -DJS_TRACER
+DEFINES += -DFEATURE_NANOJIT
+INCLUDES += -Inanojit
+endif
+
+#ifndef BUILD_OPT
+#DEFINES += -Ivprof
+#endif
+
+ifdef NARCISSUS
+DEFINES += -DNARCISSUS
+endif
+
+# Look in OBJDIR to find jsautocfg.h, jsautokw.h, and js-config.h
+INCLUDES += -I. -I$(OBJDIR)
+
+ifdef JS_THREADSAFE
+DEFINES += -DJS_THREADSAFE
+INCLUDES += -I$(DIST)/include/nspr
+ifdef USE_MSVC
+OTHER_LIBS += $(DIST)/lib/libnspr$(NSPR_LIBSUFFIX).lib
+else
+OTHER_LIBS += -L$(DIST)/lib -lnspr$(NSPR_LIBSUFFIX)
+endif
+endif
+
+ifdef JS_NO_THIN_LOCKS
+DEFINES += -DJS_USE_ONLY_NSPR_LOCKS
+endif
+
+ifdef JS_HAS_FILE_OBJECT
+DEFINES += -DJS_HAS_FILE_OBJECT
+endif
+
+ifdef JS_GC_ZEAL
+DEFINES += -DJS_GC_ZEAL
+endif
+
+#
+# XCFLAGS may be set in the environment or on the gmake command line
+#
+#CFLAGS += -DDEBUG -DDEBUG_brendan -DJS_ARENAMETER -DJS_HASHMETER -DJS_DUMP_PROPTREE_STATS -DJS_DUMP_SCOPE_METERS -DJS_SCOPE_DEPTH_METER -DJS_BASIC_STATS
+CFLAGS += $(OS_CFLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS)
+
+LDFLAGS = $(XLDFLAGS)
+LDFLAGS += $(OS_LDFLAGS)
+
+ifdef MOZ_SHARK
+DEFINES += -DMOZ_SHARK
+CFLAGS += -F/System/Library/PrivateFrameworks
+LDFLAGS += -F/System/Library/PrivateFrameworks -framework CHUD
+endif
+ifdef MOZ_CALLGRIND
+DEFINES += -DMOZ_CALLGRIND
+endif
+ifdef MOZ_VTUNE
+DEFINES += -DMOZ_VTUNE
+CXXFLAGS += -IC:/Program\ Files/Intel/VTune/Analyzer/Include
+OTHER_LIBS += C:/Program\ Files/Intel/VTune/Analyzer/Lib/VtuneApi.lib
+endif
+
+ifndef NO_LIBM
+LDFLAGS += -lm
+endif
+
+# Prevent floating point errors caused by VC++ optimizations
+ifeq ($(OS_ARCH),WINNT)
+_MSC_VER = $(shell $(CXX) 2>&1 | sed -n 's/.*Compiler Version \([0-9]*\)\.\([0-9]*\).*/\1\2/p')
+ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER)))
+CFLAGS += -Op
+else
+CFLAGS += -fp:precise
+endif
+endif # WINNT
+
+#
+# Server-related changes :
+#
+ifdef NES40
+DEFINES += -DNES40
+endif
+
+#
+# Line editing support.
+# Define JS_READLINE or JS_EDITLINE to enable line editing in the
+# js command-line interpreter.
+#
+ifdef JS_READLINE
+# For those platforms with the readline library installed.
+DEFINES += -DEDITLINE
+PROG_LIBS += -lreadline -ltermcap
+else
+ifdef JS_EDITLINE
+# Use the editline library, built locally.
+PREDIRS += editline
+DEFINES += -DEDITLINE
+PROG_LIBS += $(OBJDIR)/editline/libedit.a
+endif
+endif
+
+# For purify
+PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \
+ $(INCLUDES) $(XCFLAGS)
+
+#
+# JS file lists
+#
+JS_HFILES = \
+ jsarray.h \
+ jsatom.h \
+ jsbool.h \
+ jscntxt.h \
+ jsdate.h \
+ jsemit.h \
+ jsexn.h \
+ jsfun.h \
+ jsgc.h \
+ jsinterp.h \
+ jsiter.h \
+ jslibmath.h \
+ jslock.h \
+ jsmath.h \
+ jsnum.h \
+ jsobj.h \
+ json.h \
+ jsopcode.h \
+ jsparse.h \
+ jsarena.h \
+ jsclist.h \
+ jsdhash.h \
+ jsdtoa.h \
+ jshash.h \
+ jslong.h \
+ jstypes.h \
+ jsprvtd.h \
+ jspubtd.h \
+ jsregexp.h \
+ jsscan.h \
+ jsscope.h \
+ jsscript.h \
+ jsstr.h \
+ jsversion.h \
+ jsxdrapi.h \
+ jsxml.h \
+ $(NULL)
+
+ifdef ENABLE_JIT
+JS_HFILES += \
+ jstracer.h \
+ nanojit/Assembler.h \
+ nanojit/LIR.h \
+ nanojit/Native$(NANOJIT_ARCH).h \
+ nanojit/avmplus.h \
+ nanojit/vm_fops.h \
+ nanojit/Fragmento.h \
+ nanojit/Native.h \
+ nanojit/RegAlloc.h \
+ nanojit/nanojit.h \
+ nanojit/TraceTreeDrawer.h \
+ $(NULL)
+endif
+
+ifndef BUILD_OPT
+#JS_HFILES += \
+# vprof/vprof.h \
+# $(NULL)
+endif
+
+API_HFILES = \
+ jsapi.h \
+ jsdbgapi.h \
+ $(NULL)
+
+OTHER_HFILES = \
+ jsbit.h \
+ jscompat.h \
+ jscpucfg.h \
+ jsotypes.h \
+ jsstddef.h \
+ prmjtime.h \
+ resource.h \
+ jsopcode.tbl \
+ jsproto.tbl \
+ js.msg \
+ jsshell.msg \
+ jskeyword.tbl \
+ $(NULL)
+
+ifdef ENABLE_JIT
+OTHER_HFILES += builtins.tbl
+endif
+
+ifndef PREBUILT_CPUCFG
+OTHER_HFILES += $(OBJDIR)/jsautocfg.h
+endif
+OTHER_HFILES += $(OBJDIR)/jsautokw.h $(OBJDIR)/js-config.h
+
+HFILES = $(JS_HFILES) $(API_HFILES) $(OTHER_HFILES)
+
+JS_CPPFILES = \
+ jsapi.cpp \
+ jsarena.cpp \
+ jsarray.cpp \
+ jsatom.cpp \
+ jsbool.cpp \
+ jscntxt.cpp \
+ jsdate.cpp \
+ jsdbgapi.cpp \
+ jsdhash.cpp \
+ jsdtoa.cpp \
+ jsemit.cpp \
+ jsexn.cpp \
+ jsfun.cpp \
+ jsgc.cpp \
+ jshash.cpp \
+ jsinterp.cpp \
+ jsinvoke.cpp \
+ jsiter.cpp \
+ jslock.cpp \
+ jslog2.cpp \
+ jslong.cpp \
+ jsmath.cpp \
+ jsnum.cpp \
+ jsobj.cpp \
+ json.cpp \
+ jsopcode.cpp \
+ jsparse.cpp \
+ jsprf.cpp \
+ jsregexp.cpp \
+ jsscan.cpp \
+ jsscope.cpp \
+ jsscript.cpp \
+ jsstr.cpp \
+ jsutil.cpp \
+ jsxdrapi.cpp \
+ jsxml.cpp \
+ prmjtime.cpp \
+ $(NULL)
+
+ifdef ENABLE_JIT
+JS_CPPFILES += \
+ jsbuiltins.cpp \
+ jstracer.cpp \
+ nanojit/Assembler.cpp \
+ nanojit/Fragmento.cpp \
+ nanojit/LIR.cpp \
+ nanojit/Native$(NANOJIT_ARCH).cpp \
+ nanojit/RegAlloc.cpp \
+ nanojit/avmplus.cpp \
+ $(NULL)
+
+ifdef DEBUG
+JS_CPPFILES += nanojit/TraceTreeDrawer.cpp
+endif
+endif
+
+ifndef BUILD_OPT
+#JS_CPPFILES += \
+# vprof/vprof.cpp \
+# $(NULL)
+endif
+
+ifdef JS_LIVECONNECT
+DIRS += liveconnect
+endif
+
+ifdef JS_HAS_FILE_OBJECT
+JS_CPPFILES += jsfile.cpp
+JS_HFILES += jsfile.h
+endif
+
+LIB_CPPFILES = $(JS_CPPFILES)
+LIB_ASFILES := $(wildcard *_$(OS_ARCH).s)
+PROG_CPPFILES = js.cpp
+
+ifdef USE_MSVC
+LIBRARY = $(OBJDIR)/js32.lib
+SHARED_LIBRARY = $(OBJDIR)/js32.dll
+PROGRAM = $(OBJDIR)/js.exe
+else
+LIBRARY = $(OBJDIR)/libjs.a
+SHARED_LIBRARY = $(OBJDIR)/libjs.$(SO_SUFFIX)
+PROGRAM = $(OBJDIR)/js
+endif
+
+include rules.mk
+
+MOZ_DEPTH = ../..
+include jsconfig.mk
+
+nsinstall-target:
+ cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR)
+
+#
+# Automatic header generation
+#
+
+AUTO_HEADERS = \
+ $(OBJDIR)/jsautokw.h \
+ $(OBJDIR)/jsautooplen.h \
+ $(NULL)
+
+$(OBJDIR)/jsautokw.h: jskeyword.tbl
+
+$(OBJDIR)/jsautooplen.h: jsopcode.tbl
+
+GARBAGE += $(AUTO_HEADERS)
+GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen$(HOST_BIN_SUFFIX))
+
+ifdef USE_MSVC
+
+GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.obj)
+
+$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(OPTIMIZER) $<
+ link.exe -out:"$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX)" $(EXE_LINK_FLAGS) $(OBJDIR)/js$*gen.obj
+ $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@
+else
+
+GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.d)
+$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $(CFLAGS) $(OPTIMIZER) $(LDFLAGS) $<
+ $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@
+
+endif
+
+# force creation of autoheaders before compiling any source that may use them
+$(LIB_OBJS) : $(AUTO_HEADERS)
+
+#
+# An installed header file describing configuration options that affect
+# the API.
+#
+
+# Avoid rebuilding unless js-config.h's contents actually change. The
+# timestamp on js-config.h.stamp corresponds to the last time we
+# checked that js-config.h was up to date. If the stamp changes but
+# js-config.h does not, then make concludes that targets depending on
+# js-config.h don't need to be rebuilt. The dummy '@true' rule here
+# keeps make from concluding that js-config.h never changes.
+$(OBJDIR)/js-config.h: $(OBJDIR)/js-config.h.stamp
+ @true
+
+js-config-switch=$(if $(value $($1)),-e 's/\#undef $1/\#define $1/')
+$(OBJDIR)/js-config.h.stamp: js-config.h.in Makefile.ref
+ sed < $< > $(@:.stamp=.tmp) \
+ $(call js-config-switch,JS_THREADSAFE) \
+ $(call js-config-switch,JS_GC_ZEAL) \
+ -e :dummy
+ if ! [ -f $(@:.stamp=) ] || ! cmp $(@:.stamp=.tmp) $(@:.stamp=); then \
+ mv $(@:.stamp=.tmp) $(@:.stamp=); \
+ fi
+ touch $@
+
+GARBAGE += $(OBJDIR)/js-config.h $(OBJDIR)/js-config.h.stamp
+
+# Force creation of js-config.h before compiling any source that may use it.
+$(LIB_OBJS) : $(OBJDIR)/js-config.h
+
+#
+# JS shell executable
+#
+
+ifdef USE_MSVC
+$(PROGRAM): $(PROG_OBJS) $(LIBRARY)
+ link.exe -out:"$@" $(EXE_LINK_FLAGS) $^
+else
+$(PROGRAM): $(PROG_OBJS) $(LIBRARY)
+ $(CXX) -o $@ $(CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) $(OTHER_LIBS) \
+ $(PROG_LIBS)
+endif
+
+$(PROGRAM).pure: $(PROG_OBJS) $(LIBRARY)
+ purify $(PUREFLAGS) \
+ $(CXX) -o $@ $(PURE_OS_CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) \
+ $(OTHER_LIBS) $(PROG_LIBS)
+
+ifndef PREBUILT_CPUCFG
+$(filter-out jscpucfg.h $(OBJDIR)/jsautocfg.h, $(HFILES)) $(CPPFILES): $(OBJDIR)/jsautocfg.h
+
+$(OBJDIR)/jsautocfg.h: $(OBJDIR)/jscpucfg
+ rm -f $@
+ $(OBJDIR)/jscpucfg > $@
+
+$(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o
+ $(CXX) $(OS_LDFLAGS) -o $@ $(OBJDIR)/jscpucfg.o
+
+GARBAGE += $(OBJDIR)/jsautocfg.h $(OBJDIR)/jscpucfg \
+ $(OBJDIR)/jscpucfg.o $(OBJDIR)/jscpucfg.d
+endif
+
+# Automatic make dependencies files
+DEPENDENCIES = $(CPPFILES:%.cpp=$(OBJDIR)/%.d)
+
+#
+# Hardwire dependencies for some files
+#
+ifdef USE_MSVC
+OBJ=obj
+else
+OBJ=o
+endif
+
+$(OBJDIR)/jsinvoke.$(OBJ): jsinterp.h jsinterp.cpp
+$(OBJDIR)/jsinvoke.obj : jsinterp.h jsinterp.cpp
+
+-include $(DEPENDENCIES)
+
+TARNAME = jsref.tar
+TARFILES = files `cat files`
+
+SUFFIXES: .i
+%.i: %.cpp
+ $(CXX) -C -E $(CFLAGS) $< > $*.i
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/README.html b/tools/node_modules/expresso/deps/jscoverage/js/README.html
new file mode 100644
index 0000000..6eb1567
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/README.html
@@ -0,0 +1,54 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta http-equiv="Refresh"
+ content="0;URL=http://developer.mozilla.org/en/docs/SpiderMonkey">
+ <title>SpiderMonkey README</title>
+</head>
+<body>
+
+<h1>SpiderMonkey README</h1>
+
+<p>See the
+<a href="http://developer.mozilla.org/en/docs/SpiderMonkey">SpiderMonkey
+pages</a> on the Mozilla Developer Center</a>.
+
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/SpiderMonkey.rsp b/tools/node_modules/expresso/deps/jscoverage/js/SpiderMonkey.rsp
new file mode 100644
index 0000000..fc162d9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/SpiderMonkey.rsp
@@ -0,0 +1,11 @@
+mozilla/js/src/*
+mozilla/js/src/config/*
+mozilla/js/src/liveconnect/*
+mozilla/js/src/liveconnect/_jni/*
+mozilla/js/src/liveconnect/classes/*
+mozilla/js/src/liveconnect/classes/netscape/*
+mozilla/js/src/liveconnect/classes/netscape/javascript/*
+mozilla/js/src/liveconnect/config/*
+mozilla/js/src/liveconnect/macbuild/*
+mozilla/js/src/liveconnect/macbuild/JavaSession/*
+mozilla/js/src/macbuild/*
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/aclocal.m4 b/tools/node_modules/expresso/deps/jscoverage/js/aclocal.m4
new file mode 100644
index 0000000..538065c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/aclocal.m4
@@ -0,0 +1,9 @@
+dnl
+dnl Local autoconf macros used with mozilla
+dnl The contents of this file are under the Public Domain.
+dnl
+
+builtin(include, build/autoconf/pkg.m4)dnl
+builtin(include, build/autoconf/nspr.m4)dnl
+builtin(include, build/autoconf/altoptions.m4)dnl
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/bench.sh b/tools/node_modules/expresso/deps/jscoverage/js/bench.sh
new file mode 100755
index 0000000..8b7fe75
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/bench.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+X="var d = Date.now();";
+for i in t/*.js; do X="$X load(\"$i\");"; done
+X="$X print(Date.now() - d);"
+echo $X | (./Darwin_OPT.OBJ/js -j || ./Linux_All_OPT.OBJ/js -j)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/acoutput-fast.pl b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/acoutput-fast.pl
new file mode 100644
index 0000000..973dd86
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/acoutput-fast.pl
@@ -0,0 +1,202 @@
+#! /usr/bin/env perl
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# acoutput-fast.pl - Quickly create makefiles that are in a common format.
+#
+# Most of the makefiles in mozilla only refer to two configure variables:
+# @srcdir@
+# @top_srcdir@
+# However, configure does not know any better and it runs sed on each file
+# with over 150 replacement rules (slow as molasses).
+#
+# This script takes a list of makefiles as input. For example,
+#
+# echo $MAKEFILES | acoutput-fast.pl
+#
+# The script creates each Makefile that only references @srcdir@ and
+# @top_srcdir@. For other files, it lists them in a shell command that is
+# printed to stdout:
+#
+# CONFIG_FILES="unhandled_files..."; export CONFIG_FILES
+#
+# This command can be used to have config.status create the unhandled
+# files. For example,
+#
+# eval "echo $MAKEFILES | acoutput-fast.pl"
+# AC_OUTPUT($MAKEFILES)
+#
+# Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com).
+
+#use File::Basename;
+sub dirname {
+ my $dir = $_[0];
+ return '.' if not $dir =~ m%/%;
+ $dir =~ s%/[^/][^/]*$%%;
+ return $dir;
+}
+
+# Create one directory. Assumes it doesn't already exist.
+# Will create parent(s) if needed.
+sub create_directory {
+ my $dir = $_[0];
+ my $parent = dirname($dir);
+ create_directory($parent) if not -d $parent;
+ mkdir "$dir",0777;
+}
+
+# Create all the directories at once.
+# This can be much faster than calling mkdir() for each one.
+sub create_directories {
+ my @makefiles = @_;
+ my @dirs = ();
+ my $ac_file;
+ foreach $ac_file (@makefiles) {
+ push @dirs, dirname($ac_file);
+ }
+ # Call mkdir with the directories sorted by subdir count (how many /'s)
+ if (@dirs) {
+ foreach $dir (@dirs) {
+ if (not -d $dir) {
+ print STDERR "Creating directory $dir\n";
+ create_directory($dir);
+ }
+ }
+ }
+}
+
+while($arg = shift) {
+ if ($arg =~ /^--srcdir=/) {
+ $ac_given_srcdir = (split /=/, $arg)[1];
+ }
+ if ($arg =~ /^--cygwin-srcdir/) {
+ $ac_cygwin_srcdir = (split /=/, $arg)[1];
+ }
+}
+
+if (!$ac_given_srcdir) {
+ $ac_given_srcdir = $0;
+ $ac_given_srcdir =~ s|/?build/autoconf/.*$||;
+ $ac_given_srcdir = '.' if $ac_given_srcdir eq '';
+}
+
+if (!$ac_cygwin_srcdir) {
+ $ac_cygwin_srcdir = $ac_given_srcdir;
+}
+
+# Read list of makefiles from the stdin or,
+# from files listed on the command-line.
+#
+@makefiles=();
+push @makefiles, split while (<STDIN>);
+
+# Create all the directories at once.
+# This can be much faster than calling mkdir() for each one.
+create_directories(@makefiles);
+
+# Output the makefiles.
+#
+@unhandled=();
+foreach $ac_file (@makefiles) {
+ if (not $ac_file =~ /Makefile$/ or $ac_file =~ /:/) {
+ push @unhandled, $ac_file;
+ next;
+ }
+ $ac_file_in = "$ac_given_srcdir/$ac_file.in";
+ $ac_dir = dirname($ac_file);
+ if ($ac_dir eq '.') {
+ $ac_dir_suffix = '';
+ $ac_dots = '';
+ } else {
+ $ac_dir_suffix = "/$ac_dir";
+ $ac_dir_suffix =~ s%^/\./%/%;
+ $ac_dots = $ac_dir_suffix;
+ $ac_dots =~ s%/[^/]*%../%g;
+ }
+ if ($ac_given_srcdir eq '.') {
+ $srcdir = '.';
+ if ($ac_dots eq '') {
+ $top_srcdir = '.'
+ } else {
+ $top_srcdir = $ac_dots;
+ $top_srcdir =~ s%/$%%;
+ }
+ } elsif ($ac_cygwin_srcdir =~ m%^/% or $ac_cygwin_srcdir =~ m%^.:/%) {
+ $srcdir = "$ac_cygwin_srcdir$ac_dir_suffix";
+ $top_srcdir = "$ac_cygwin_srcdir";
+ } else {
+ $srcdir = "$ac_dots$ac_cygwin_srcdir$ac_dir_suffix";
+ $top_srcdir = "$ac_dots$ac_cygwin_srcdir";
+ }
+
+ if (-e $ac_file) {
+ next if -M _ < -M $ac_file_in;
+ print STDERR "updating $ac_file\n";
+ } else {
+ print STDERR "creating $ac_file\n";
+ }
+
+ open (INFILE, "<$ac_file_in")
+ or ( warn "can't read $ac_file_in: No such file or directory\n" and next);
+ open (OUTFILE, ">$ac_file")
+ or ( warn "Unable to create $ac_file\n" and next);
+
+ while (<INFILE>) {
+ #if (/\@[_a-zA-Z]*\@.*\@[_a-zA-Z]*\@/) {
+ # warn "Two defines on a line:$ac_file:$.:$_";
+ # push @unhandled, $ac_file;
+ # last;
+ #}
+
+ s/\@srcdir\@/$srcdir/g;
+ s/\@top_srcdir\@/$top_srcdir/g;
+
+ if (/\@[_a-zA-Z]*\@/) {
+ warn "Unknown variable:$ac_file:$.:$_";
+ push @unhandled, $ac_file;
+ last;
+ }
+ print OUTFILE;
+ }
+ close INFILE;
+ close OUTFILE;
+}
+
+# Print the shell command to be evaluated by configure.
+#
+print "CONFIG_FILES=\"".join(' ', @unhandled)."\"; export CONFIG_FILES\n";
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/altoptions.m4 b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/altoptions.m4
new file mode 100644
index 0000000..f9db0a5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/altoptions.m4
@@ -0,0 +1,154 @@
+dnl ***** BEGIN LICENSE BLOCK *****
+dnl Version: MPL 1.1/GPL 2.0/LGPL 2.1
+dnl
+dnl The contents of this file are subject to the Mozilla Public License Version
+dnl 1.1 (the "License"); you may not use this file except in compliance with
+dnl the License. You may obtain a copy of the License at
+dnl http://www.mozilla.org/MPL/
+dnl
+dnl Software distributed under the License is distributed on an "AS IS" basis,
+dnl WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+dnl for the specific language governing rights and limitations under the
+dnl License.
+dnl
+dnl The Original Code is mozilla.org code.
+dnl
+dnl The Initial Developer of the Original Code is
+dnl Netscape Communications Corporation.
+dnl Portions created by the Initial Developer are Copyright (C) 1999
+dnl the Initial Developer. All Rights Reserved.
+dnl
+dnl Contributor(s):
+dnl
+dnl Alternatively, the contents of this file may be used under the terms of
+dnl either of the GNU General Public License Version 2 or later (the "GPL"),
+dnl or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+dnl in which case the provisions of the GPL or the LGPL are applicable instead
+dnl of those above. If you wish to allow use of your version of this file only
+dnl under the terms of either the GPL or the LGPL, and not to allow others to
+dnl use your version of this file under the terms of the MPL, indicate your
+dnl decision by deleting the provisions above and replace them with the notice
+dnl and other provisions required by the GPL or the LGPL. If you do not delete
+dnl the provisions above, a recipient may use your version of this file under
+dnl the terms of any one of the MPL, the GPL or the LGPL.
+dnl
+dnl ***** END LICENSE BLOCK *****
+
+dnl altoptions.m4 - An alternative way of specifying command-line options.
+dnl These macros are needed to support a menu-based configurator.
+dnl This file also includes the macro, AM_READ_MYCONFIG, for reading
+dnl the 'myconfig.m4' file.
+
+dnl Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com).
+
+
+dnl MOZ_ARG_ENABLE_BOOL( NAME, HELP, IF-YES [, IF-NO [, ELSE]])
+dnl MOZ_ARG_DISABLE_BOOL( NAME, HELP, IF-NO [, IF-YES [, ELSE]])
+dnl MOZ_ARG_ENABLE_STRING( NAME, HELP, IF-SET [, ELSE])
+dnl MOZ_ARG_ENABLE_BOOL_OR_STRING( NAME, HELP, IF-YES, IF-NO, IF-SET[, ELSE]]])
+dnl MOZ_ARG_WITH_BOOL( NAME, HELP, IF-YES [, IF-NO [, ELSE])
+dnl MOZ_ARG_WITHOUT_BOOL( NAME, HELP, IF-NO [, IF-YES [, ELSE])
+dnl MOZ_ARG_WITH_STRING( NAME, HELP, IF-SET [, ELSE])
+dnl MOZ_ARG_HEADER(Comment)
+dnl MOZ_CHECK_PTHREADS( NAME, IF-YES [, ELSE ])
+dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
+
+
+dnl MOZ_TWO_STRING_TEST(NAME, VAL, STR1, IF-STR1, STR2, IF-STR2 [, ELSE])
+AC_DEFUN([MOZ_TWO_STRING_TEST],
+[if test "[$2]" = "[$3]"; then
+ ifelse([$4], , :, [$4])
+ elif test "[$2]" = "[$5]"; then
+ ifelse([$6], , :, [$6])
+ else
+ ifelse([$7], ,
+ [AC_MSG_ERROR([Option, [$1], does not take an argument ([$2]).])],
+ [$7])
+ fi])
+
+dnl MOZ_ARG_ENABLE_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE]])
+AC_DEFUN([MOZ_ARG_ENABLE_BOOL],
+[AC_ARG_ENABLE([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_DISABLE_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE]])
+AC_DEFUN([MOZ_ARG_DISABLE_BOOL],
+[AC_ARG_ENABLE([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$enableval], no, [$3], yes, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_ENABLE_STRING(NAME, HELP, IF-SET [, ELSE])
+AC_DEFUN([MOZ_ARG_ENABLE_STRING],
+[AC_ARG_ENABLE([$1], [$2], [$3], [$4])])
+
+dnl MOZ_ARG_ENABLE_BOOL_OR_STRING(NAME, HELP, IF-YES, IF-NO, IF-SET[, ELSE]]])
+AC_DEFUN([MOZ_ARG_ENABLE_BOOL_OR_STRING],
+[ifelse([$5], ,
+ [errprint([Option, $1, needs an "IF-SET" argument.
+])
+ m4exit(1)],
+ [AC_ARG_ENABLE([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4], [$5])],
+ [$6])])])
+
+dnl MOZ_ARG_WITH_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE])
+AC_DEFUN([MOZ_ARG_WITH_BOOL],
+[AC_ARG_WITH([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$withval], yes, [$3], no, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_WITHOUT_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE])
+AC_DEFUN([MOZ_ARG_WITHOUT_BOOL],
+[AC_ARG_WITH([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$withval], no, [$3], yes, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_WITH_STRING(NAME, HELP, IF-SET [, ELSE])
+AC_DEFUN([MOZ_ARG_WITH_STRING],
+[AC_ARG_WITH([$1], [$2], [$3], [$4])])
+
+dnl MOZ_ARG_HEADER(Comment)
+dnl This is used by webconfig to group options
+define(MOZ_ARG_HEADER, [# $1])
+
+dnl
+dnl Apparently, some systems cannot properly check for the pthread
+dnl library unless <pthread.h> is included so we need to test
+dnl using it
+dnl
+dnl MOZ_CHECK_PTHREADS(lib, success, failure)
+AC_DEFUN([MOZ_CHECK_PTHREADS],
+[
+AC_MSG_CHECKING([for pthread_create in -l$1])
+echo "
+ #include <pthread.h>
+ #include <stdlib.h>
+ void *foo(void *v) { int a = 1; }
+ int main() {
+ pthread_t t;
+ if (!pthread_create(&t, 0, &foo, 0)) {
+ pthread_join(t, 0);
+ }
+ exit(0);
+ }" > dummy.c ;
+ echo "${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -l[$1] $LDFLAGS $LIBS" 1>&5;
+ ${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -l[$1] $LDFLAGS $LIBS 2>&5;
+ _res=$? ;
+ rm -f dummy.c dummy${ac_exeext} ;
+ if test "$_res" = "0"; then
+ AC_MSG_RESULT([yes])
+ [$2]
+ else
+ AC_MSG_RESULT([no])
+ [$3]
+ fi
+])
+
+dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
+AC_DEFUN([MOZ_READ_MOZCONFIG],
+[AC_REQUIRE([AC_INIT_BINSH])dnl
+# Read in '.mozconfig' script to set the initial options.
+# See the mozconfig2configure script for more details.
+_AUTOCONF_TOOLS_DIR=`dirname [$]0`/[$1]/build/autoconf
+. $_AUTOCONF_TOOLS_DIR/mozconfig2configure])
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.guess b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.guess
new file mode 100644
index 0000000..a20b311
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.guess
@@ -0,0 +1,1481 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-10-13'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+#### MozillaHack
+# Netscape's hacked uname
+ xx:WINNT:* | xx:WIN95:*)
+ echo i586-pc-msvc
+ exit ;;
+### End MozillaHack
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+#### MozillaHack
+ *:*OpenVMS*:*:*)
+ case "${UNAME_SYSTEM}" in
+ POSIX_for_OpenVMS_AXP) echo alpha-dec-openvmsposix ;;
+ POSIX_for_OpenVMS_VAX) echo vax-dec-openvmsposix ;;
+ OpenVMS) echo alpha-dec-openvms ;;
+ *) echo unknown-dec-openvms ;;
+ esac
+ exit ;;
+#### End MozillaHack
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.sub b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.sub
new file mode 100644
index 0000000..2d91b11
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.sub
@@ -0,0 +1,1595 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-10-13'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+#### MozillaHack
+# mips*el
+#### End MozillaHack
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+ | mips | mipsbe | mipseb | mips*el | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | ms1 \
+ | msp430 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m32c)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+#### MozillaHack
+# mips*el
+#### End MozillaHack
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mips*el-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | ms1-* \
+ | msp430-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ m32c-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+#### MozillaHack
+ i386-msvc | msvc)
+ basic_machine=i386-pc
+ os=-msvc
+ ;;
+#### End MozillaHack
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+#### MozillaHack
+# msvc
+#### End MozillaHack
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -msvc* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/install-sh b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/install-sh
new file mode 100644
index 0000000..0ff4b6a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/install-sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+#
+# install - install a program, script, or datafile
+# This comes from X11R5; it is not part of GNU.
+#
+# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+
+instcmd="$mvprog"
+chmodcmd=""
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+fi
+
+if [ x"$dst" = x ]
+then
+ echo "install: no destination specified"
+ exit 1
+fi
+
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+if [ -d $dst ]
+then
+ dst="$dst"/`basename $src`
+fi
+
+# Make a temp file name in the proper directory.
+
+dstdir=`dirname $dst`
+dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+$doit $instcmd $src $dsttmp
+
+# and set any options; do chmod last to preserve setuid bits
+
+if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
+if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
+if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
+if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
+
+# Now rename the file to the real destination.
+
+$doit $rmcmd $dst
+$doit $mvcmd $dsttmp $dst
+
+
+exit 0
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/make-makefile b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/make-makefile
new file mode 100644
index 0000000..5343f6f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/make-makefile
@@ -0,0 +1,315 @@
+#! /usr/bin/env perl
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# make-makefiles - Quickly create Makefiles for subdirectories.
+# Also, creates any needed subdirectories.
+#
+# usage: make-makefiles [ -t <topsrcdir> -p <print_topsrcdir> -d <depth> ] [ <subdir> | <subdir>/Makefile ] ...
+
+# Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com).
+
+#$debug = 1;
+
+# Determine various tree path variables
+#
+($topsrcdir, $ptopsrcdir, $depth, @makefiles) = parse_arguments(@ARGV);
+
+$object_fullpath = `pwd`;
+chdir $depth;
+$object_root = `pwd`;
+chomp $object_fullpath;
+chomp $object_root;
+
+# $source_subdir is the path from the object root to where
+# 'make-makefile' was called. For example, if make-makefile was
+# called from "mozilla/gfx/src", then $source_subdir would be
+# "gfx/src/".
+$source_subdir = "$object_fullpath/";
+my $quoted_object_root = quotemeta($object_root);
+$source_subdir =~ s|^$quoted_object_root/||;
+
+# Prefix makefiles with $source_subdir so that paths
+# will be relative to the top of the object tree.
+#
+for $makefile (@makefiles) {
+ $makefile = "$source_subdir$makefile";
+}
+
+create_directories(@makefiles);
+
+# Find the path to the source directory based on how 'make-makefile'
+# was invoked. The path is either relative to the object directory
+# or an absolute path.
+$given_srcdir = find_srcdir($topsrcdir, $depth);
+$pgiven_srcdir = find_srcdir($ptopsrcdir, $depth);
+
+if ($debug) {
+ warn "object_fullpath = $object_fullpath\n";
+ warn "object_root = $object_root\n";
+ warn "source_subdir = $source_subdir\n";
+ warn "makefiles = @makefiles\n";
+ warn "given_srcdir = $given_srcdir\n";
+}
+
+@unhandled = update_makefiles($given_srcdir, $pgiven_srcdir, @makefiles);
+
+run_config_status(@unhandled);
+
+# end of Main
+############################################################
+
+sub dirname {
+ return $_[0] =~ /(.*)\/.*/ ? "$1" : '.';
+}
+
+# find_depth: Pull the value of DEPTH out of a Makefile (or Makefile.in)
+sub find_depth {
+ my $depth = '';
+ open(MAKEFILE, "<$_[0]") || die "Unable to open $_[0]: $!\n";
+ while (<MAKEFILE>) {
+ next unless /^DEPTH\s*=\s*(\..*)/;
+ $depth = $1;
+ last;
+ }
+ close MAKEFILE;
+ return $depth;
+}
+
+sub parse_arguments {
+ my @args = @_;
+ my $depth = '';
+ my $topsrcdir = '';
+ my $ptopsrcdir;
+ my @makefiles = ();
+
+ while (1) {
+ if ($args[0] eq '-d') {
+ $depth = $args[1];
+ shift @args;
+ shift @args;
+ } elsif ($args[0] eq '-t') {
+ $topsrcdir = $args[1];
+ shift @args;
+ shift @args;
+ } elsif ($args[0] eq '-p') {
+ $ptopsrcdir = $args[1];
+ shift @args;
+ shift @args;
+ } else {
+ last;
+ }
+ }
+
+ if ($topsrcdir eq '') {
+ $topsrcdir = $0; # Figure out topsrcdir based on program name.
+ $topsrcdir =~ s|/?build/autoconf/.*$||;
+ }
+ if ($ptopsrcdir eq '') {
+ $ptopsrcdir = $topsrcdir;
+ }
+ if ($depth eq '') {
+ # Use $(DEPTH) in the Makefile or Makefile.in to determine the depth
+ if (-e "Makefile.in") {
+ $depth = find_depth("Makefile.in");
+ } elsif (-e "Makefile") {
+ $depth = find_depth("Makefile");
+ } elsif (-e "../Makefile") {
+ $depth = "../".find_depth("../Makefile");
+ $depth =~ s/\/\.$//;
+ } else {
+ warn "Unable to determine depth (e.g. ../..) to root of objdir tree.\n";
+ die "No Makefile(.in) present. Try running with '-d <depth>'\n";
+ }
+ }
+
+ # Build the list of makefiles to generate
+ #
+ @makefiles = ();
+ my $makefile;
+ foreach $makefile (@args) {
+ $makefile =~ s/\.in$//;
+ $makefile =~ s/\/$//;
+ $makefile =~ /Makefile$/ or $makefile .= "/Makefile";
+ push @makefiles, "$makefile";
+ }
+ @makefiles = "Makefile" unless @args;
+
+ return ($topsrcdir, $ptopsrcdir, $depth, @makefiles);
+}
+
+
+# Create all the directories at once.
+# This can be much faster than calling mkdir() for each one.
+sub create_directories {
+ my @makefiles = @_;
+ my @dirs = ();
+ my $ac_file;
+ foreach $ac_file (@makefiles) {
+ push @dirs, dirname($ac_file);
+ }
+ # Call mkdir with the directories sorted by subdir count (how many /'s)
+ system "mkdir -p ". join(' ', map("\"$_\"", @dirs)) if @dirs;
+}
+
+# Find the top of the source directory
+# (Assuming that the executable is in $top_srcdir/build/autoconf)
+sub find_srcdir {
+ my ($ac_given_srcdir, $depth) = @_;
+
+ if ($debug) {
+ print "ac_given_srcdir = $ac_given_srcdir\n";
+ print "depth = $depth\n";
+ }
+ if ($ac_given_srcdir =~ /^\./ and $depth ne '.') {
+ my $quoted_depth = quotemeta($depth);
+ $ac_given_srcdir =~ s|^$quoted_depth/?||;
+ }
+ if ($debug) {
+ print "ac_given_srcdir = $ac_given_srcdir\n";
+ }
+ $ac_given_srcdir = '.' if $ac_given_srcdir eq '';
+ return $ac_given_srcdir;
+}
+
+# Output the makefiles.
+#
+sub update_makefiles {
+ my ($ac_given_srcdir, $pac_given_srcdir, @makefiles) = @_;
+ my @unhandled=();
+
+ my $ac_file;
+ foreach $ac_file (@makefiles) {
+ my $ac_file_in = "$ac_given_srcdir/${ac_file}.in";
+ my $ac_dir = dirname($ac_file);
+ my $ac_dots = '';
+ my $ac_dir_suffix = '';
+ my $srcdir = '.';
+ my $top_srcdir = '.';
+
+ # Determine $srcdir and $top_srcdir
+ #
+ if ($ac_dir ne '.') {
+ $ac_dir_suffix = "/$ac_dir";
+ $ac_dir_suffix =~ s%^/\./%/%;
+ $ac_dots = $ac_dir_suffix;
+ # Remove .. components from the provided dir suffix, and
+ # also the forward path components they were reversing.
+ my $backtracks = $ac_dots =~ s%\.\.(/|$)%%g;
+ while ($backtracks--) {
+ $ac_dots =~ s%/[^/]*%%;
+ }
+ $ac_dots =~ s%/[^/]*%../%g;
+ }
+ if ($ac_given_srcdir eq '.') {
+ if ($ac_dots ne '') {
+ $top_srcdir = $ac_dots;
+ $top_srcdir =~ s%/$%%;
+ }
+ } elsif ($pac_given_srcdir =~ m%^/% or $pac_given_srcdir =~ m%^.:/%) {
+ $srcdir = "$pac_given_srcdir$ac_dir_suffix";
+ $top_srcdir = "$pac_given_srcdir";
+ } else {
+ if ($debug) {
+ print "ac_dots = $ac_dots\n";
+ print "ac_dir_suffix = $ac_dir_suffix\n";
+ }
+ $srcdir = "$ac_dots$ac_given_srcdir$ac_dir_suffix";
+ $top_srcdir = "$ac_dots$ac_given_srcdir";
+ }
+
+ if ($debug) {
+ print "ac_dir = $ac_dir\n";
+ print "ac_file = $ac_file\n";
+ print "ac_file_in = $ac_file_in\n";
+ print "srcdir = $srcdir\n";
+ print "top_srcdir = $top_srcdir\n";
+ print "cwd = " . `pwd` . "\n";
+ }
+
+ # Copy the file and make substitutions.
+ # @srcdir@ -> value of $srcdir
+ # @top_srcdir@ -> value of $top_srcdir
+ #
+ if (-e $ac_file) {
+ next if -M _ < -M $ac_file_in; # Next if Makefile is up-to-date.
+ warn "updating $ac_file\n";
+ } else {
+ warn "creating $ac_file\n";
+ }
+
+ open INFILE, "<$ac_file_in" or do {
+ warn "$0: Cannot read $ac_file_in: No such file or directory\n";
+ next;
+ };
+ open OUTFILE, ">$ac_file" or do {
+ warn "$0: Unable to create $ac_file\n";
+ next;
+ };
+
+ while (<INFILE>) {
+ #if (/\@[_a-zA-Z]*\@.*\@[_a-zA-Z]*\@/) {
+ # #warn "Two defines on a line:$ac_file:$.:$_";
+ # push @unhandled, $ac_file;
+ # last;
+ #}
+
+ s/\@srcdir\@/$srcdir/g;
+ s/\@top_srcdir\@/$top_srcdir/g;
+
+ if (/\@[_a-zA-Z]*\@/) {
+ #warn "Unknown variable:$ac_file:$.:$_";
+ push @unhandled, $ac_file;
+ last;
+ }
+ print OUTFILE;
+ }
+ close INFILE;
+ close OUTFILE;
+ }
+ return @unhandled;
+}
+
+sub run_config_status {
+ my @unhandled = @_;
+
+ # Run config.status with any unhandled files.
+ #
+ if (@unhandled) {
+ $ENV{CONFIG_FILES}= join ' ', @unhandled;
+ system "./config.status";
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/match-dir.sh b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/match-dir.sh
new file mode 100644
index 0000000..c579a9d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/match-dir.sh
@@ -0,0 +1,101 @@
+#!/bin/sh
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# This script will match a dir with a set of dirs.
+#
+# Usage: match-dir.sh match [dir1 dir2 ... dirn]
+#
+# Send comments, improvements, bugs to ramiro@netscape.com
+#
+
+if [ -f Makefile ]; then
+ MAKEFILE="Makefile"
+else
+ if [ -f Makefile.in ]; then
+ MAKEFILE="Makefile.in"
+ else
+ echo
+ echo "There ain't no 'Makefile' or 'Makefile.in' over here: $pwd, dude."
+ echo
+ exit 1
+ fi
+fi
+
+# Use DEPTH in the Makefile.in to determine the depth
+depth=`grep -w DEPTH ${MAKEFILE} | grep "\.\." | awk -F"=" '{ print $2; }'`
+cwd=`pwd`
+
+# Determine the depth count
+n=`echo $depth | tr '/' ' ' | wc -w`
+
+cd $depth
+objdir=`pwd`
+
+path=`echo $cwd | sed "s|^${objdir}/||"`
+
+match=$path
+
+for i in $*
+do
+# echo "Looking for $match in $i"
+
+ echo $i | grep -q -x $match
+
+ if [ $? -eq 0 ]
+ then
+ echo "1"
+
+ exit 0
+ fi
+
+# echo "Looking for $i in $match"
+
+ echo $match | grep -q $i
+
+ if [ $? -eq 0 ]
+ then
+ echo "1"
+
+ exit 0
+ fi
+done
+
+echo "0"
+
+exit 0
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/nspr.m4 b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/nspr.m4
new file mode 100644
index 0000000..d21df69
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/nspr.m4
@@ -0,0 +1,82 @@
+# -*- tab-width: 4; -*-
+# Configure paths for NSPR
+# Public domain - Chris Seawood <cls@seawood.org> 2001-04-05
+# Based upon gtk.m4 (also PD) by Owen Taylor
+
+dnl AM_PATH_NSPR([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for NSPR, and define NSPR_CFLAGS and NSPR_LIBS
+AC_DEFUN([AM_PATH_NSPR],
+[dnl
+
+AC_ARG_WITH(nspr-prefix,
+ [ --with-nspr-prefix=PFX Prefix where NSPR is installed],
+ nspr_config_prefix="$withval",
+ nspr_config_prefix="")
+
+AC_ARG_WITH(nspr-exec-prefix,
+ [ --with-nspr-exec-prefix=PFX
+ Exec prefix where NSPR is installed],
+ nspr_config_exec_prefix="$withval",
+ nspr_config_exec_prefix="")
+
+ if test -n "$nspr_config_exec_prefix"; then
+ nspr_config_args="$nspr_config_args --exec-prefix=$nspr_config_exec_prefix"
+ if test -z "$NSPR_CONFIG"; then
+ NSPR_CONFIG=$nspr_config_exec_prefix/bin/nspr-config
+ fi
+ fi
+ if test -n "$nspr_config_prefix"; then
+ nspr_config_args="$nspr_config_args --prefix=$nspr_config_prefix"
+ if test -z "$NSPR_CONFIG"; then
+ NSPR_CONFIG=$nspr_config_prefix/bin/nspr-config
+ fi
+ fi
+
+ unset ac_cv_path_NSPR_CONFIG
+ AC_PATH_PROG(NSPR_CONFIG, nspr-config, no)
+ min_nspr_version=ifelse([$1], ,4.0.0,$1)
+ AC_MSG_CHECKING(for NSPR - version >= $min_nspr_version)
+
+ no_nspr=""
+ if test "$NSPR_CONFIG" = "no"; then
+ no_nspr="yes"
+ else
+ NSPR_CFLAGS=`$NSPR_CONFIG $nspr_config_args --cflags`
+ NSPR_LIBS=`$NSPR_CONFIG $nspr_config_args --libs`
+
+ nspr_config_major_version=`$NSPR_CONFIG $nspr_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ nspr_config_minor_version=`$NSPR_CONFIG $nspr_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ nspr_config_micro_version=`$NSPR_CONFIG $nspr_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ min_nspr_major_version=`echo $min_nspr_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ min_nspr_minor_version=`echo $min_nspr_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ min_nspr_micro_version=`echo $min_nspr_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ if test "$nspr_config_major_version" -ne "$min_nspr_major_version"; then
+ no_nspr="yes"
+ elif test "$nspr_config_major_version" -eq "$min_nspr_major_version" &&
+ test "$nspr_config_minor_version" -lt "$min_nspr_minor_version"; then
+ no_nspr="yes"
+ elif test "$nspr_config_major_version" -eq "$min_nspr_major_version" &&
+ test "$nspr_config_minor_version" -eq "$min_nspr_minor_version" &&
+ test "$nspr_config_micro_version" -lt "$min_nspr_micro_version"; then
+ no_nspr="yes"
+ fi
+ fi
+
+ if test -z "$no_nspr"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ AC_MSG_RESULT(no)
+ fi
+
+
+ AC_SUBST(NSPR_CFLAGS)
+ AC_SUBST(NSPR_LIBS)
+
+])
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/pkg.m4 b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/pkg.m4
new file mode 100644
index 0000000..d84d210
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/pkg.m4
@@ -0,0 +1,59 @@
+# PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
+# defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page
+# also defines GSTUFF_PKG_ERRORS on error
+AC_DEFUN([PKG_CHECK_MODULES],
+[succeeded=no
+
+ if test -z "$PKG_CONFIG"; then
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+ fi
+
+ if test "$PKG_CONFIG" = "no" ; then
+ echo "*** The pkg-config script could not be found. Make sure it is"
+ echo "*** in your path, or set the PKG_CONFIG environment variable"
+ echo "*** to the full path to pkg-config."
+ echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
+ else
+ PKG_CONFIG_MIN_VERSION=0.9.0
+ if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
+ AC_MSG_CHECKING(for $2)
+
+ if $PKG_CONFIG --exists "$2" ; then
+ AC_MSG_RESULT(yes)
+ succeeded=yes
+
+ AC_MSG_CHECKING($1_CFLAGS)
+ $1_CFLAGS=`$PKG_CONFIG --cflags "$2"`
+ AC_MSG_RESULT($$1_CFLAGS)
+
+ AC_MSG_CHECKING($1_LIBS)
+ ## Remove evil flags like -Wl,--export-dynamic
+ $1_LIBS="`$PKG_CONFIG --libs \"$2\" |sed s/-Wl,--export-dynamic//g`"
+ AC_MSG_RESULT($$1_LIBS)
+ else
+ $1_CFLAGS=""
+ $1_LIBS=""
+ ## If we have a custom action on failure, don't print errors, but
+ ## do set a variable so people can do so.
+ $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ ifelse([$4], ,echo $$1_PKG_ERRORS,)
+ fi
+
+ AC_SUBST($1_CFLAGS)
+ AC_SUBST($1_LIBS)
+ else
+ echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
+ echo "*** See http://www.freedesktop.org/software/pkgconfig"
+ fi
+ fi
+
+ if test $succeeded = yes; then
+ ifelse([$3], , :, [$3])
+ else
+ if test "$COMPILE_ENVIRONMENT"; then
+ ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
+ fi
+ fi
+])
+
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/update-makefile.sh b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/update-makefile.sh
new file mode 100644
index 0000000..42f78eb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/update-makefile.sh
@@ -0,0 +1,118 @@
+#!/bin/sh
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# This script will generate a single Makefile from a Makefile.in using
+# the config.status script.
+#
+# The config.status script is generated the first time you run
+# ./configure.
+#
+#
+# Usage: update-makefile.sh
+#
+# Send comments, improvements, bugs to ramiro@netscape.com
+#
+
+update_makefile_usage() {
+ _progname=`expr //$0 : '.*/\(.*\)'`
+ cat <<END_USAGE 2>&1
+
+Usage: $_progname [-h -u] [<keyword>]
+ -d <dir> Subdir to update
+ -h Print usage
+END_USAGE
+}
+
+# Parse the command-line options
+#
+subdir=
+while getopts d:h OPT; do
+ case $OPT in
+ d) # Make sure "subdir" has exactly one ending slash
+ subdir=`echo $OPTARG | sed 's/\/$//;'`"/" ;;
+ \?|h) update_makefile_usage
+ exit 1
+ ;;
+ esac
+done
+
+
+# find_depth: Pull the value of DEPTH out of Makefile (or Makefile.in)
+find_depth() {
+ egrep '^DEPTH[ ]*=[ ]*\.' $1 | awk -F= '{ print $2; }'
+}
+
+# The Makefile to create
+target_makefile=`pwd`"/${subdir}Makefile"
+
+# Use $(DEPTH) in the Makefile or Makefile.in to determine the depth
+if [ -f Makefile.in ]
+then
+ depth=`find_depth Makefile.in`
+elif [ -f Makefile ]
+then
+ depth=`find_depth Makefile`
+elif [ -f ../Makefile ]
+then
+ depth="../"`find_depth Makefile`
+else
+ echo
+ echo "There ain't no 'Makefile' or 'Makefile.in' over here: $pwd"
+ echo
+ exit
+fi
+
+# 'cd' to the root of the tree to run "config.status" there
+cd $depth
+
+# Strip the tree root off the Makefile's path
+#
+root_path=`pwd`
+target_makefile=`expr $target_makefile : $root_path'/\(.*\)'`
+
+# Make sure config.status exists
+#
+if [ -f config.status ]
+then
+ CONFIG_FILES=$target_makefile ./config.status
+else
+ echo
+ echo "There ain't no 'config.status' over here: $pwd"
+ echo
+fi
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/cygwin-wrapper b/tools/node_modules/expresso/deps/jscoverage/js/build/cygwin-wrapper
new file mode 100644
index 0000000..679f0a1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/cygwin-wrapper
@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# Stupid wrapper to avoid win32 dospath/cygdrive issues
+# Try not to spawn programs from within this file. If the stuff in here looks royally
+# confusing, see bug: http://bugzilla.mozilla.org/show_bug.cgi?id=206643
+# and look at the older versions of this file that are easier to read, but
+# do basically the same thing
+#
+
+prog=$1
+shift
+if test -z "$prog"; then
+ exit 0
+fi
+
+# If $CYGDRIVE_MOUNT was not set in configure, give $mountpoint the results of mount -p
+mountpoint=$CYGDRIVE_MOUNT
+if test -z "$mountpoint"; then
+ mountpoint=`mount -p`
+ if test -z "$mountpoint"; then
+ print "Cannot determine cygwin mount points. Exiting"
+ exit 1
+ fi
+fi
+
+# Delete everything but "/cygdrive" (or other mountpoint) from mount=`mount -p`
+mountpoint=${mountpoint#*/}
+mountpoint=/${mountpoint%%[!A-Za-z0-9_]*}
+mountpoint=${mountpoint%/}
+
+args=""
+up=""
+if test "${prog}" = "-up"; then
+ up=1
+ prog=${1}
+ shift
+fi
+
+process=1
+
+# Convert the mountpoint in parameters to Win32 filenames
+# For instance: /cygdrive/c/foo -> c:/foo
+for i in "${@}"
+do
+ if test "${i}" = "-wrap"; then
+ process=1
+ else
+ if test "${i}" = "-nowrap"; then
+ process=
+ else
+ if test -n "${process}"; then
+ if test -n "${up}"; then
+ pathname=${i#-I[a-zA-Z]:/}
+ if ! test "${pathname}" = "${i}"; then
+ no_i=${i#-I}
+ driveletter=${no_i%%:*}
+ i=-I${mountpoint}/${driveletter}/${pathname}
+ fi
+ else
+ eval 'leader=${i%%'${mountpoint}'/[a-zA-Z]/*}'
+ if ! test "${leader}" = "${i}"; then
+ eval 'pathname=${i#'${leader}${mountpoint}'/[a-zA-Z]/}'
+ eval 'no_mountpoint=${i#'${leader}${mountpoint}'/}'
+ driveletter=${no_mountpoint%%/*}
+ i=${leader}${driveletter}:/${pathname}
+ fi
+ fi
+ fi
+
+ args="${args} ${i}"
+ fi
+ fi
+done
+
+exec $prog $args
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/hcc b/tools/node_modules/expresso/deps/jscoverage/js/build/hcc
new file mode 100644
index 0000000..adadbe4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/hcc
@@ -0,0 +1,111 @@
+#!/bin/sh
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Fix brain-damaged compilers that don't understand -o and -c together
+#
+CC=`echo $1 | sed -e "s|'||g" -e 's|"||g'`
+shift
+DASH_C=0
+DASH_O=0
+DUMMY="XxxXxxX"
+GET_OBJECT=0
+OBJ="${DUMMY}"
+OBJECT="${DUMMY}"
+
+for i in $*
+do
+ [ "${CHECK_O}" = yes ] && {
+ case $i in
+ ./*/*.o) OBJECT="$i"
+ OPTS="${OPTS} -o"
+ DASH_O=1
+ ;;
+ ./*.o) OBJECT="`basename $i`"
+ i=""
+ DASH_O=1
+ ;;
+ *.o) if [ $i = `basename $i` ]
+ then
+ OBJECT="$i"
+ i=""
+ else
+ OPTS="${OPTS} -o"
+ fi
+ DASH_O=1
+ ;;
+ *) OPTS="${OPTS} -o $i"
+ DASH_O=1
+ i=""
+ ;;
+ esac
+ CHECK_O=no
+ }
+ case $i in
+ -c) DASH_C=1
+ OPTS="${OPTS} -c"
+ ;;
+ -o) CHECK_O=yes
+ ;;
+ *.c) C_SRC=$i
+ OPTS="${OPTS} $i"
+# cc always creates the .o from the .c name
+ OBJ=`basename $C_SRC .c`.o
+ ;;
+ *.s) S_SRC=$i
+ OPTS="${OPTS} $i"
+# or the .o from the .s name
+ OBJ=`basename $S_SRC .s`.o
+ ;;
+ *.o) OBJECT=$i
+ OPTS="${OPTS} $i"
+ ;;
+ *) OPTS="${OPTS} $i"
+ ;;
+ esac
+done
+
+${CC} ${OPTS} || exit $?
+
+# if there was no -c and -o we're done
+[ $DASH_C = 1 -a $DASH_O = 1 ] || exit 0
+
+# if $OBJ and $OBJECT are the same we're done
+[ $OBJ = $OBJECT ] && exit 0
+
+[ -f $OBJ ] && mv -f $OBJ $OBJECT
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/hcpp b/tools/node_modules/expresso/deps/jscoverage/js/build/hcpp
new file mode 100644
index 0000000..ea55fa4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/hcpp
@@ -0,0 +1,155 @@
+#!/bin/sh
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Wrapper for brain-damaged compilers that don't understand -o and -c together.
+#
+CXX=`echo $1 | sed -e "s|'||g" -e 's|"||g'`
+shift
+DUMMY="XxxXxxX"
+DASH_C=0
+DASH_O=0
+GET_OBJECT=0
+C_SRC="${DUMMY}"
+CC_SRC="${DUMMY}"
+CPP_SRC="${DUMMY}"
+S_SRC="${DUMMY}"
+OBJECT="${DUMMY}"
+NEW_i="${DUMMY}"
+PLATFORM=`uname -s`
+
+for i in $*
+do
+ [ ${GET_OBJECT} -eq 1 ] && {
+ case $i in
+ ./*/*.o) OBJECT="$i"
+ OPTS="${OPTS} -o"
+ DASH_O=1
+ ;;
+ ./*.o) OBJECT="`basename $i`"
+ i=""
+ DASH_O=1
+ ;;
+ *.o) if [ $i = `basename $i` ]
+ then
+ i=""
+ else
+ OPTS="${OPTS} -o"
+ DASH_O=1
+ fi
+ ;;
+ *) OPTS="${OPTS} -o $i"
+ DASH_O=1
+ i=""
+ ;;
+ esac
+ GET_OBJECT=0
+ }
+ case $i in
+ -c)
+ DASH_C=1
+ OPTS="${OPTS} -c"
+ ;;
+ -o)
+ GET_OBJECT=1
+ ;;
+ *.c)
+ C_SRC="$i"
+ OPTS="${OPTS} $i"
+# cc always creates the .o from the .c name
+ OBJ=`basename ${C_SRC} .c`.o
+ ;;
+ +.*)
+ OPTS="${OPTS} $i"
+ ;;
+ *.cpp)
+ CPP_SRC="$i"
+ if [ "${PLATFORM}" = "SCO_SV" ]; then
+ OPTS="${OPTS} +.cpp $i"
+ elif [ "${PLATFORM}" = "IRIX" ]; then
+ NEW_i=`basename ${CPP_SRC} .cpp`.C
+ rm -f ${NEW_i}
+ cp $i ${NEW_i}
+ OPTS="${OPTS} ${NEW_i}"
+ else
+ OPTS="${OPTS} $i"
+ fi
+# cc always creates the .o from the .cpp name
+ OBJ=`basename ${CPP_SRC} .cpp`.o
+ ;;
+ *.cc)
+ CC_SRC="$i"
+ OPTS="${OPTS} $i"
+# cc always creates the .o from the .cc name
+ OBJ=`basename ${CC_SRC} .cc`.o
+ ;;
+ *.s)
+ S_SRC="$i"
+ OPTS="${OPTS} $i"
+# cc always creates the .o from the .s name
+ OBJ=`basename ${S_SRC} .s`.o
+ ;;
+ *.o) OBJECT=$i
+ OPTS="${OPTS} $i"
+ ;;
+ *) OPTS="${OPTS} $i"
+ ;;
+ esac
+done
+
+${CXX} ${OPTS} || exit $?
+rm -f ${NEW_i}
+
+# Really only needed for NSPR now.
+if [ "${PLATFORM}" = "IRIX" -a "$OBJ" != "$OBJECT" ]; then
+ OBJ=$OBJECT
+fi
+
+# LAME!!!
+if [ -f -O ]; then
+ mv -f -- -O ${OBJECT}
+fi
+
+# if there was no -c and -o we're done
+[ ${DASH_C} -eq 1 -a ${DASH_O} -eq 1 ] || exit 0
+
+# if $OBJ and $OBJECT are the same we're done
+[ $OBJ = $OBJECT ] && exit 0
+
+[ -f $OBJ ] && mv -f $OBJ $OBJECT
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/unix/mddepend.pl b/tools/node_modules/expresso/deps/jscoverage/js/build/unix/mddepend.pl
new file mode 100644
index 0000000..380e4ff
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/unix/mddepend.pl
@@ -0,0 +1,165 @@
+#!/usr/bin/env perl
+
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is this file as it was released upon March 8, 1999.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# mddepend.pl - Reads in dependencies generated my -MD flag. Prints list
+# of objects that need to be rebuilt. These can then be added to the
+# PHONY target. Using this script copes with the problem of header
+# files that have been removed from the build.
+#
+# Usage:
+# mddepend.pl <output_file> <dependency_files...>
+#
+# Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com).
+
+use strict;
+
+use constant DEBUG => 0;
+
+my $outfile = shift @ARGV;
+my $silent = $ENV{MAKEFLAGS} =~ /^\w*s|\s-s/;
+
+my $line = '';
+my %alldeps;
+# Parse dependency files
+while (<>) {
+ s/\r?\n$//; # Handle both unix and DOS line endings
+ $line .= $_;
+ if ($line =~ /\\$/) {
+ chop $line;
+ next;
+ }
+
+ my ($obj,$rest) = split /\s*:\s+/, $line, 2;
+ $line = '';
+ next if !$obj || !$rest;
+
+ my @deps = split /\s+/, $rest;
+ push @{$alldeps{$obj}}, @deps;
+ if (DEBUG >= 2) {
+ foreach my $dep (@deps) { print "add $obj $dep\n"; }
+ }
+}
+
+# Test dependencies
+my %modtimes; # cache
+my @objs; # force rebuild on these
+OBJ_LOOP: foreach my $obj (keys %alldeps) {
+ my $mtime = (stat $obj)[9] or next;
+
+ my %not_in_cache;
+ my $deps = $alldeps{$obj};
+ foreach my $dep_file (@{$deps}) {
+ my $dep_mtime = $modtimes{$dep_file};
+ if (not defined $dep_mtime) {
+ print "Skipping $dep_file for $obj, will stat() later\n" if DEBUG >= 2;
+ $not_in_cache{$dep_file} = 1;
+ next;
+ }
+
+ print "Found $dep_file in cache\n" if DEBUG >= 2;
+
+ if ($dep_mtime > $mtime) {
+ print "$dep_file($dep_mtime) newer than $obj($mtime)\n" if DEBUG;
+ }
+ elsif ($dep_mtime == -1) {
+ print "Couldn't stat $dep_file for $obj\n" if DEBUG;
+ }
+ else {
+ print "$dep_file($dep_mtime) older than $obj($mtime)\n" if DEBUG >= 2;
+ next;
+ }
+
+ push @objs, $obj; # dependency is missing or newer
+ next OBJ_LOOP; # skip checking the rest of the dependencies
+ }
+
+ foreach my $dep_file (keys %not_in_cache) {
+ print "STAT $dep_file for $obj\n" if DEBUG >= 2;
+ my $dep_mtime = $modtimes{$dep_file} = (stat $dep_file)[9] || -1;
+
+ if ($dep_mtime > $mtime) {
+ print "$dep_file($dep_mtime) newer than $obj($mtime)\n" if DEBUG;
+ }
+ elsif ($dep_mtime == -1) {
+ print "Couldn't stat $dep_file for $obj\n" if DEBUG;
+ }
+ else {
+ print "$dep_file($dep_mtime) older than $obj($mtime)\n" if DEBUG >= 2;
+ next;
+ }
+
+ push @objs, $obj; # dependency is missing or newer
+ next OBJ_LOOP; # skip checking the rest of the dependencies
+ }
+
+ # If we get here it means nothing needs to be done for $obj
+}
+
+# Output objects to rebuild (if needed).
+if (@objs) {
+ my $old_output;
+ my $new_output = "@objs: FORCE\n";
+
+ # Read in the current dependencies file.
+ open(OLD, "<$outfile")
+ and $old_output = <OLD>;
+ close(OLD);
+
+ # Only write out the dependencies if they are different.
+ if ($new_output ne $old_output) {
+ open(OUT, ">$outfile") and print OUT "$new_output";
+ print "Updating dependencies file, $outfile\n" unless $silent;
+ if (DEBUG) {
+ print "new: $new_output\n";
+ print "was: $old_output\n" if $old_output ne '';
+ }
+ }
+} elsif (-s $outfile) {
+ # Remove the old dependencies because all objects are up to date.
+ print "Removing old dependencies file, $outfile\n" unless $silent;
+
+ if (DEBUG) {
+ my $old_output;
+ open(OLD, "<$outfile")
+ and $old_output = <OLD>;
+ close(OLD);
+ print "was: $old_output\n";
+ }
+
+ unlink $outfile;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/unix/uniq.pl b/tools/node_modules/expresso/deps/jscoverage/js/build/unix/uniq.pl
new file mode 100644
index 0000000..1b40bda
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/unix/uniq.pl
@@ -0,0 +1,63 @@
+#!/usr/bin/env perl
+
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is this file as it was released upon December 26, 2000.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Christopher Seawood <cls@seawood.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+use Getopt::Std;
+
+getopts('rs');
+$regexp = 1 if (defined($opt_r));
+$sort = 1 if (defined($opt_s));
+
+undef @out;
+if ($sort) {
+ @in = sort @ARGV;
+} else {
+ @in = @ARGV;
+}
+foreach $d (@in) {
+ if ($regexp) {
+ $found = 0;
+ foreach $dir (@out) {
+ $found++, last if ($d =~ m/^$dir\// || $d eq $dir);
+ }
+ push @out, $d if (!$found);
+ } else {
+ push @out, $d if (!grep(/^$d$/, @out));
+ }
+}
+print "@out\n"
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/win32/pgomerge.py b/tools/node_modules/expresso/deps/jscoverage/js/build/win32/pgomerge.py
new file mode 100755
index 0000000..528c4ff
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/win32/pgomerge.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+# Usage: pgomerge.py <binary basename> <dist/bin>
+# Gathers .pgc files from dist/bin and merges them into
+# $PWD/$basename.pgd using pgomgr, then deletes them.
+# No errors if any of these files don't exist.
+
+import sys, os, os.path, subprocess
+if not sys.platform == "win32":
+ raise Exception("This script was only meant for Windows.")
+
+def MergePGOFiles(basename, pgddir, pgcdir):
+ """Merge pgc files produced from an instrumented binary
+ into the pgd file for the second pass of profile-guided optimization
+ with MSVC. |basename| is the name of the DLL or EXE without the
+ extension. |pgddir| is the path that contains <basename>.pgd
+ (should be the objdir it was built in). |pgcdir| is the path
+ containing basename!N.pgc files, which is probably dist/bin.
+ Calls pgomgr to merge each pgc file into the pgd, then deletes
+ the pgc files."""
+ if not os.path.isdir(pgddir) or not os.path.isdir(pgcdir):
+ return
+ pgdfile = os.path.abspath(os.path.join(pgddir, basename + ".pgd"))
+ if not os.path.isfile(pgdfile):
+ return
+ for file in os.listdir(pgcdir):
+ if file.startswith(basename) and file.endswith(".pgc"):
+ try:
+ pgcfile = os.path.normpath(os.path.join(pgcdir, file))
+ subprocess.call(['pgomgr', '-merge',
+ pgcfile,
+ pgdfile])
+ os.remove(pgcfile)
+ except OSError:
+ pass
+
+if __name__ == '__main__':
+ if len(sys.argv) != 3:
+ print >>sys.stderr, "Usage: pgomerge.py <binary basename> <dist/bin>"
+ sys.exit(1)
+ MergePGOFiles(sys.argv[1], os.getcwd(), sys.argv[2])
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/builtins.tbl b/tools/node_modules/expresso/deps/jscoverage/js/builtins.tbl
new file mode 100644
index 0000000..a725d97
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/builtins.tbl
@@ -0,0 +1,98 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=0 ft=C:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * June 22, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Andreas Gal <gal@uci.edu>
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * This file declares builtin functions that can be called from JITted code.
+ * Each line starts with "BUILTIN" and an integer, the number of arguments the
+ * builtin takes. Builtins with no arguments are not supported.
+ *
+ * The macro arguments are:
+ *
+ * - 'extern' to indicate extern linkage for these functions and the associated
+ * CallInfo.
+ *
+ * - The return type. This identifier must name one of the _JS_TYPEINFO_*
+ * macros defined in jsbuiltins.h.
+ *
+ * - The builtin name. Prefixed with "js_" this gives the native function name.
+ *
+ * - The parameter types.
+ *
+ * - The cse flag. 1 if the builtin call can be optimized away by common
+ * subexpression elimination; otherwise 0. This should be 1 only if the
+ * function is idempotent and the return value is determined solely by the
+ * arguments.
+ *
+ * - The fold flag. Reserved. The same as cse for now.
+ */
+
+/*
+ * NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
+ * Do not use bool FASTCALL, use JSBool only!
+ */
+
+BUILTIN2(extern, JSVAL, js_BoxDouble, CONTEXT, DOUBLE, 1, 1)
+BUILTIN2(extern, JSVAL, js_BoxInt32, CONTEXT, INT32, 1, 1)
+BUILTIN1(extern, DOUBLE, js_UnboxDouble, JSVAL, 1, 1)
+BUILTIN1(extern, INT32, js_UnboxInt32, JSVAL, 1, 1)
+BUILTIN2(extern, DOUBLE, js_dmod, DOUBLE, DOUBLE, 1, 1)
+BUILTIN2(extern, INT32, js_imod, INT32, INT32, 1, 1)
+BUILTIN1(extern, INT32, js_DoubleToInt32, DOUBLE, 1, 1)
+BUILTIN1(extern, UINT32, js_DoubleToUint32, DOUBLE, 1, 1)
+
+BUILTIN2(extern, DOUBLE, js_StringToNumber, CONTEXT, STRING, 1, 1)
+BUILTIN2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, 1)
+BUILTIN3(extern, JSVAL, js_Any_getprop, CONTEXT, OBJECT, STRING, 0, 0)
+BUILTIN4(extern, BOOL, js_Any_setprop, CONTEXT, OBJECT, STRING, JSVAL, 0, 0)
+BUILTIN3(extern, JSVAL, js_Any_getelem, CONTEXT, OBJECT, INT32, 0, 0)
+BUILTIN4(extern, BOOL, js_Any_setelem, CONTEXT, OBJECT, INT32, JSVAL, 0, 0)
+BUILTIN3(extern, OBJECT, js_FastValueToIterator, CONTEXT, UINT32, JSVAL, 0, 0)
+BUILTIN2(extern, JSVAL, js_FastCallIteratorNext, CONTEXT, OBJECT, 0, 0)
+BUILTIN2(FRIEND, BOOL, js_CloseIterator, CONTEXT, JSVAL, 0, 0)
+BUILTIN2(extern, SIDEEXIT, js_CallTree, INTERPSTATE, FRAGMENT, 0, 0)
+BUILTIN2(extern, OBJECT, js_FastNewObject, CONTEXT, OBJECT, 0, 0)
+BUILTIN3(extern, BOOL, js_AddProperty, CONTEXT, OBJECT, SCOPEPROP, 0, 0)
+BUILTIN3(extern, BOOL, js_HasNamedProperty, CONTEXT, OBJECT, STRING, 0, 0)
+BUILTIN3(extern, BOOL, js_HasNamedPropertyInt32, CONTEXT, OBJECT, INT32, 0, 0)
+BUILTIN3(extern, JSVAL, js_CallGetter, CONTEXT, OBJECT, SCOPEPROP, 0, 0)
+BUILTIN2(extern, STRING, js_TypeOfObject, CONTEXT, OBJECT, 1, 1)
+BUILTIN2(extern, STRING, js_TypeOfBoolean, CONTEXT, INT32, 1, 1)
+BUILTIN2(extern, DOUBLE, js_BooleanOrUndefinedToNumber, CONTEXT, INT32, 1, 1)
+BUILTIN2(extern, STRING, js_BooleanOrUndefinedToString, CONTEXT, INT32, 1, 1)
+BUILTIN2(extern, STRING, js_ObjectToString, CONTEXT, OBJECT, 0, 0)
+BUILTIN1(extern, OBJECT, js_Arguments, CONTEXT, 0, 0)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config.mk b/tools/node_modules/expresso/deps/jscoverage/js/config.mk
new file mode 100644
index 0000000..ddd96ed
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config.mk
@@ -0,0 +1,206 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998-1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+ifdef JS_DIST
+DIST = $(JS_DIST)
+else
+DIST = $(DEPTH)/../../dist
+endif
+
+# Set os+release dependent make variables
+OS_ARCH := $(subst /,_,$(shell uname -s | sed /\ /s//_/))
+
+# Attempt to differentiate between SunOS 5.4 and x86 5.4
+OS_CPUARCH := $(shell uname -m)
+ifeq ($(OS_CPUARCH),i86pc)
+OS_RELEASE := $(shell uname -r)_$(OS_CPUARCH)
+else
+ifeq ($(OS_ARCH),AIX)
+OS_RELEASE := $(shell uname -v).$(shell uname -r)
+else
+OS_RELEASE := $(shell uname -r)
+endif
+endif
+ifeq ($(OS_ARCH),IRIX64)
+OS_ARCH := IRIX
+endif
+
+# Handle output from win32 unames other than Netscape's version
+ifeq (,$(filter-out Windows_95 Windows_98 CYGWIN_95-4.0 CYGWIN_98-4.10, $(OS_ARCH)))
+ OS_ARCH := WIN95
+endif
+ifeq ($(OS_ARCH),WIN95)
+ OS_ARCH := WINNT
+ OS_RELEASE := 4.0
+endif
+ifeq ($(OS_ARCH), Windows_NT)
+ OS_ARCH := WINNT
+ OS_MINOR_RELEASE := $(shell uname -v)
+ ifeq ($(OS_MINOR_RELEASE),00)
+ OS_MINOR_RELEASE = 0
+ endif
+ OS_RELEASE := $(OS_RELEASE).$(OS_MINOR_RELEASE)
+endif
+ifeq (CYGWIN_NT,$(findstring CYGWIN_NT,$(OS_ARCH)))
+ OS_RELEASE := $(patsubst CYGWIN_NT-%,%,$(OS_ARCH))
+ OS_ARCH := WINNT
+endif
+ifeq ($(OS_ARCH), CYGWIN32_NT)
+ OS_ARCH := WINNT
+endif
+ifeq (MINGW32_NT,$(findstring MINGW32_NT,$(OS_ARCH)))
+ OS_RELEASE := $(patsubst MINGW32_NT-%,%,$(OS_ARCH))
+ OS_ARCH := WINNT
+endif
+
+# Virtually all Linux versions are identical.
+# Any distinctions are handled in linux.h
+ifeq ($(OS_ARCH),Linux)
+OS_CONFIG := Linux_All
+else
+ifeq ($(OS_ARCH),dgux)
+OS_CONFIG := dgux
+else
+ifeq ($(OS_ARCH),Darwin)
+OS_CONFIG := Darwin
+else
+ifeq ($(OS_ARCH),Darwin64)
+OS_CONFIG := Darwin64
+else
+OS_CONFIG := $(OS_ARCH)$(OS_OBJTYPE)$(OS_RELEASE)
+endif
+endif
+endif
+endif
+
+ASFLAGS =
+DEFINES =
+
+ifeq ($(OS_ARCH), WINNT)
+INSTALL = nsinstall
+CP = cp
+else
+INSTALL = $(DIST)/bin/nsinstall
+CP = cp
+endif
+
+ifdef BUILD_OPT
+ifdef USE_MSVC
+OPTIMIZER = -O2 -GL
+INTERP_OPTIMIZER = -O2 -GL
+BUILTINS_OPTIMIZER = -O2 -GL
+LDFLAGS += -LTCG
+else
+OPTIMIZER = -Os -fstrict-aliasing -fno-exceptions -fno-rtti -Wstrict-aliasing=2
+BUILTINS_OPTIMIZER = -O9 -fstrict-aliasing -fno-exceptions -fno-rtti
+INTERP_OPTIMIZER = -O3 -fstrict-aliasing -fno-exceptions -fno-rtti
+endif
+DEFINES += -UDEBUG -DNDEBUG -UDEBUG_$(USER)
+OBJDIR_TAG = _OPT
+else
+ifdef USE_MSVC
+OPTIMIZER = -Zi
+INTERP_OPTIMIZER = -Zi
+BUILTINS_OPTIMIZER = $(INTERP_OPTIMIZER)
+else
+OPTIMIZER = -g3 -fstrict-aliasing -fno-exceptions -fno-rtti -Wstrict-aliasing=2
+INTERP_OPTIMIZER = -g3 -fstrict-aliasing -fno-exceptions -fno-rtti
+BUILTINS_OPTIMIZER = $(INTERP_OPTIMIZER)
+endif
+DEFINES += -DDEBUG -DDEBUG_$(USER)
+OBJDIR_TAG = _DBG
+endif
+
+SO_SUFFIX = so
+
+NS_USE_NATIVE = 1
+
+# Java stuff
+CLASSDIR = $(DEPTH)/liveconnect/classes
+JAVA_CLASSES = $(patsubst %.java,%.class,$(JAVA_SRCS))
+TARGETS += $(addprefix $(CLASSDIR)/$(OBJDIR)/$(JARPATH)/, $(JAVA_CLASSES))
+JAVAC = $(JDK)/bin/javac
+JAVAC_FLAGS = -classpath "$(CLASSPATH)" -d $(CLASSDIR)/$(OBJDIR)
+ifeq ($(OS_ARCH), WINNT)
+ SEP = ;
+else
+ SEP = :
+endif
+CLASSPATH = $(JDK)/lib/classes.zip$(SEP)$(CLASSDIR)/$(OBJDIR)
+
+include $(DEPTH)/ref-config/$(OS_CONFIG).mk
+
+ifndef OBJ_SUFFIX
+ifdef USE_MSVC
+OBJ_SUFFIX = obj
+else
+OBJ_SUFFIX = o
+endif
+endif
+
+ifndef HOST_BIN_SUFFIX
+ifeq ($(OS_ARCH),WINNT)
+HOST_BIN_SUFFIX = .exe
+else
+HOST_BIN_SUFFIX =
+endif
+endif
+
+# Name of the binary code directories
+ifdef OBJROOT
+# prepend $(DEPTH) to the root unless it is an absolute path
+OBJDIR = $(if $(filter /%,$(OBJROOT)),$(OBJROOT),$(DEPTH)/$(OBJROOT))
+else
+ifeq ($(DEPTH),.)
+OBJDIR = $(OS_CONFIG)$(OBJDIR_TAG).$(if $(BUILD_IDG),OBJD,OBJ)
+else
+OBJDIR = $(DEPTH)/$(OS_CONFIG)$(OBJDIR_TAG).$(if $(BUILD_IDG),OBJD,OBJ)
+endif
+endif
+
+VPATH = $(OBJDIR)
+
+LCJAR = js15lc30.jar
+
+# Library name
+LIBDIR := lib
+ifeq ($(CPU_ARCH), x86_64)
+LIBDIR := lib64
+endif
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/Makefile.in b/tools/node_modules/expresso/deps/jscoverage/js/config/Makefile.in
new file mode 100644
index 0000000..39f9912
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/Makefile.in
@@ -0,0 +1,106 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Robert Ginda <rginda@netscape.com>
+# John Taylor <jtaylor@netscape.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+# For sanity's sake, we compile nsinstall without the wrapped system
+# headers, so that we can use it to set up the wrapped system headers.
+VISIBILITY_FLAGS =
+
+ifneq (,$(CROSS_COMPILE)$(filter-out WINNT OS2,$(OS_ARCH)))
+ifneq ($(OS_ARCH), WINCE)
+HOST_PROGRAM = nsinstall$(HOST_BIN_SUFFIX)
+HOST_CSRCS = nsinstall.c pathsub.c
+endif
+endif
+
+PLSRCS = nfspwd.pl revdepth.pl
+
+TARGETS = $(HOST_PROGRAM) $(PLSRCS:.pl=) $(SIMPLE_PROGRAMS)
+
+# IMPORTANT: Disable NSBUILDROOT for this directory only, otherwise we have
+# a recursive rule for finding nsinstall and the Perl scripts.
+ifdef NSBUILDROOT
+override NSBUILDROOT :=
+endif
+
+ifdef GNU_CC
+MODULE_OPTIMIZE_FLAGS = -O3
+endif
+
+ifndef COMPILER_DEPEND
+ifndef MOZ_NATIVE_MAKEDEPEND
+DIRS += mkdepend
+endif
+endif
+
+include $(topsrcdir)/config/config.mk
+
+# Do not install util programs
+NO_INSTALL=1
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+ifdef HOST_PROGRAM
+ $(INSTALL) $(HOST_PROGRAM) $(DIST)/bin
+endif
+
+ifdef WRAP_SYSTEM_INCLUDES
+export::
+ if test ! -d system_wrappers; then mkdir system_wrappers; fi
+ $(PERL) $(srcdir)/preprocessor.pl $(DEFINES) $(ACDEFINES) \
+ -DBUILD_STATIC_LIBS=$(BUILD_STATIC_LIBS) \
+ $(srcdir)/system-headers | $(PERL) $(srcdir)/make-system-wrappers.pl system_wrappers
+ $(INSTALL) system_wrappers $(DIST)/include
+
+GARBAGE_DIRS += system_wrappers
+endif
+
+FORCE:
+
+ifdef MKDEPEND_DIR
+clean clobber realclean clobber_all::
+ cd $(MKDEPEND_DIR); $(MAKE) $@
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/Moz/Milestone.pm b/tools/node_modules/expresso/deps/jscoverage/js/config/Moz/Milestone.pm
new file mode 100644
index 0000000..8dd1449
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/Moz/Milestone.pm
@@ -0,0 +1,232 @@
+#!/usr/bin/perl -w
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Win32 Version System.
+#
+# The Initial Developer of the Original Code is Netscape Communications Corporation
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+package Moz::Milestone;
+use strict;
+
+use vars qw($officialMilestone
+ $milestone);
+
+local $Moz::Milestone::milestone;
+local $Moz::Milestone::officialMilestone;
+
+#
+# Usage: getOfficialMilestone($milestoneFile)
+# Returns full milestone (x.x.x.x[ab12pre+])
+#
+sub getOfficialMilestone($) {
+ my $mfile = $_[0];
+ open(FILE,"$mfile") ||
+ die ("Can't open $mfile for reading!");
+
+ my $num = <FILE>;
+ while($num =~ /^\s*#/ || $num !~ /^\d/) {
+ $num = <FILE>;
+ }
+
+ close(FILE);
+ if ($num !~ /^\d/) { return; }
+ chomp($num);
+ # Remove extra ^M caused by using dos-mode line-endings
+ chop $num if (substr($num, -1, 1) eq "\r");
+ $Moz::Milestone::officialMilestone = $num;
+ $Moz::Milestone::milestone = &getMilestoneNum;
+ return $num;
+}
+
+#
+# Usage: getMilestoneNum($num)
+# Returns: milestone without a + if it exists.
+#
+sub getMilestoneNum {
+ if (defined($Moz::Milestone::milestone)) {
+ return $Moz::Milestone::milestone;
+ }
+
+ if (defined($Moz::Milestone::officialMilestone)) {
+ $Moz::Milestone::milestone = $Moz::Milestone::officialMilestone;
+ } else {
+ $Moz::Milestone::milestone = $_[0];
+ }
+
+ if ($Moz::Milestone::milestone =~ /\+$/) { # for x.x.x+, strip off the +
+ $Moz::Milestone::milestone =~ s/\+$//;
+ }
+
+ return $Moz::Milestone::milestone;
+}
+
+#
+# Usage: getMilestoneQualifier($num)
+# Returns: + if it exists.
+#
+sub getMilestoneQualifier {
+ my $milestoneQualifier;
+ if (defined($Moz::Milestone::officialMilestone)) {
+ $milestoneQualifier = $Moz::Milestone::officialMilestone;
+ } else {
+ $milestoneQualifier = $_[0];
+ }
+
+ if ($milestoneQualifier =~ /\+$/) {
+ return "+";
+ }
+}
+
+sub getMilestoneMajor {
+ my $milestoneMajor;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMajor = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMajor = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMajor);
+ return $parts[0];
+}
+
+sub getMilestoneMinor {
+ my $milestoneMinor;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMinor = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMinor = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMinor);
+
+ if ($#parts < 1 ) { return 0; }
+ return $parts[1];
+}
+
+sub getMilestoneMini {
+ my $milestoneMini;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMini = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMini = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMini);
+
+ if ($#parts < 2 ) { return 0; }
+ return $parts[2];
+}
+
+sub getMilestoneMicro {
+ my $milestoneMicro;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMicro = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMicro = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMicro);
+
+ if ($#parts < 3 ) { return 0; }
+ return $parts[3];
+}
+
+sub getMilestoneAB {
+ my $milestoneAB;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneAB = $Moz::Milestone::milestone;
+ } else {
+ $milestoneAB = $_[0];
+ }
+
+ if ($milestoneAB =~ /a/) { return "alpha"; }
+ if ($milestoneAB =~ /b/) { return "beta"; }
+ return "final";
+}
+
+#
+# build_file($template_file,$output_file)
+#
+sub build_file($$) {
+ my @FILE;
+ my @MILESTONE_PARTS;
+ my $MINI_VERSION = 0;
+ my $MICRO_VERSION = 0;
+ my $OFFICIAL = 0;
+ my $QUALIFIER = "";
+
+ if (!defined($Moz::Milestone::milestone)) { die("$0: no milestone file set!\n"); }
+ @MILESTONE_PARTS = split(/\./, &getMilestoneNum);
+ if ($#MILESTONE_PARTS >= 2) {
+ $MINI_VERSION = 1;
+ } else {
+ $MILESTONE_PARTS[2] = 0;
+ }
+ if ($#MILESTONE_PARTS >= 3) {
+ $MICRO_VERSION = 1;
+ } else {
+ $MILESTONE_PARTS[3] = 0;
+ }
+ if (! &getMilestoneQualifier) {
+ $OFFICIAL = 1;
+ } else {
+ $QUALIFIER = "+";
+ }
+
+ if (-e $_[0]) {
+ open(FILE, "$_[0]") || die("$0: Can't open $_[0] for reading!\n");
+ @FILE = <FILE>;
+ close(FILE);
+
+ open(FILE, ">$_[1]") || die("$0: Can't open $_[1] for writing!\n");
+
+ #
+ # There will be more of these based on what we need for files.
+ #
+ foreach(@FILE) {
+ s/__MOZ_MAJOR_VERSION__/$MILESTONE_PARTS[0]/g;
+ s/__MOZ_MINOR_VERSION__/$MILESTONE_PARTS[1]/g;
+ s/__MOZ_MINI_VERSION__/$MILESTONE_PARTS[2]/g;
+ s/__MOZ_MICRO_VERSION__/$MILESTONE_PARTS[3]/g;
+ if ($MINI_VERSION) {
+ s/__MOZ_OPTIONAL_MINI_VERSION__/.$MILESTONE_PARTS[2]/g;
+ }
+ if ($MICRO_VERSION) {
+ s/__MOZ_OPTIONAL_MICRO_VERSION__/.$MILESTONE_PARTS[3]/g;
+ }
+
+ print FILE $_;
+ }
+ close(FILE);
+ } else {
+ die("$0: $_[0] doesn't exist for autoversioning!\n");
+ }
+
+}
+
+1;
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/autoconf.mk.in b/tools/node_modules/expresso/deps/jscoverage/js/config/autoconf.mk.in
new file mode 100644
index 0000000..d82e614
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/autoconf.mk.in
@@ -0,0 +1,349 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is this file as it was released upon August 6, 1998.
+#
+# The Initial Developer of the Original Code is
+# Christopher Seawood.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Benjamin Smedberg <benjamin@smedbergs.us>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# A netscape style .mk file for autoconf builds
+
+INCLUDED_AUTOCONF_MK = 1
+USE_AUTOCONF = 1
+MOZILLA_CLIENT = 1
+target = @target@
+ac_configure_args = @ac_configure_args@
+BUILD_MODULES = @BUILD_MODULES@
+MOZILLA_VERSION = @MOZILLA_VERSION@
+
+MOZ_BUILD_APP = @MOZ_BUILD_APP@
+MOZ_APP_NAME = @MOZ_APP_NAME@
+MOZ_APP_DISPLAYNAME = @MOZ_APP_DISPLAYNAME@
+MOZ_APP_VERSION = @MOZ_APP_VERSION@
+
+MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+includedir = @includedir@
+libdir = @libdir@
+datadir = @datadir@
+mandir = @mandir@
+
+installdir = $(libdir)/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
+sdkdir = $(libdir)/$(MOZ_APP_NAME)-devel-$(MOZ_APP_VERSION)
+
+DIST = $(DEPTH)/dist
+
+MOZ_JS_LIBS = @MOZ_JS_LIBS@
+
+MOZ_SYNC_BUILD_FILES = @MOZ_SYNC_BUILD_FILES@
+
+MOZ_DEBUG = @MOZ_DEBUG@
+MOZ_DEBUG_MODULES = @MOZ_DEBUG_MODULES@
+MOZ_PROFILE_MODULES = @MOZ_PROFILE_MODULES@
+MOZ_DEBUG_ENABLE_DEFS = @MOZ_DEBUG_ENABLE_DEFS@
+MOZ_DEBUG_DISABLE_DEFS = @MOZ_DEBUG_DISABLE_DEFS@
+MOZ_DEBUG_FLAGS = @MOZ_DEBUG_FLAGS@
+MOZ_DEBUG_LDFLAGS=@MOZ_DEBUG_LDFLAGS@
+MOZ_DBGRINFO_MODULES = @MOZ_DBGRINFO_MODULES@
+MOZ_EXTENSIONS = @MOZ_EXTENSIONS@
+MOZ_IMG_DECODERS= @MOZ_IMG_DECODERS@
+MOZ_IMG_ENCODERS= @MOZ_IMG_ENCODERS@
+MOZ_JSDEBUGGER = @MOZ_JSDEBUGGER@
+MOZ_PERF_METRICS = @MOZ_PERF_METRICS@
+MOZ_LEAKY = @MOZ_LEAKY@
+MOZ_MEMORY = @MOZ_MEMORY@
+MOZ_JPROF = @MOZ_JPROF@
+MOZ_SHARK = @MOZ_SHARK@
+MOZ_CALLGRIND = @MOZ_CALLGRIND@
+MOZ_VTUNE = @MOZ_VTUNE@
+DEHYDRA_PATH = @DEHYDRA_PATH@
+
+ENABLE_EAZEL_PROFILER=@ENABLE_EAZEL_PROFILER@
+EAZEL_PROFILER_CFLAGS=@EAZEL_PROFILER_CFLAGS@
+EAZEL_PROFILER_LIBS=@EAZEL_PROFILER_LIBS@
+GC_LEAK_DETECTOR = @GC_LEAK_DETECTOR@
+NS_TRACE_MALLOC = @NS_TRACE_MALLOC@
+INCREMENTAL_LINKER = @INCREMENTAL_LINKER@
+MACOSX_DEPLOYMENT_TARGET = @MACOSX_DEPLOYMENT_TARGET@
+BUILD_STATIC_LIBS = @BUILD_STATIC_LIBS@
+ENABLE_TESTS = @ENABLE_TESTS@
+JS_ULTRASPARC_OPTS = @JS_ULTRASPARC_OPTS@
+JS_STATIC_BUILD = @JS_STATIC_BUILD@
+
+TAR=@TAR@
+
+# The MOZ_UI_LOCALE var is used to build a particular locale. Do *not*
+# use the var to change any binary files. Do *not* use this var unless you
+# write rules for the "clean-locale" and "locale" targets.
+MOZ_UI_LOCALE = @MOZ_UI_LOCALE@
+
+MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS = @MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS@
+MOZ_COMPONENT_NSPR_LIBS=@MOZ_COMPONENT_NSPR_LIBS@
+
+MOZ_FIX_LINK_PATHS=@MOZ_FIX_LINK_PATHS@
+
+XPCOM_FROZEN_LDOPTS=@XPCOM_FROZEN_LDOPTS@
+XPCOM_LIBS=@XPCOM_LIBS@
+MOZ_TIMELINE=@MOZ_TIMELINE@
+
+ENABLE_STRIP = @ENABLE_STRIP@
+PKG_SKIP_STRIP = @PKG_SKIP_STRIP@
+
+MOZ_POST_DSO_LIB_COMMAND = @MOZ_POST_DSO_LIB_COMMAND@
+MOZ_POST_PROGRAM_COMMAND = @MOZ_POST_PROGRAM_COMMAND@
+
+MOZ_BUILD_ROOT = @MOZ_BUILD_ROOT@
+
+MOZ_INSURE = @MOZ_INSURE@
+MOZ_INSURIFYING = @MOZ_INSURIFYING@
+MOZ_INSURE_DIRS = @MOZ_INSURE_DIRS@
+MOZ_INSURE_EXCLUDE_DIRS = @MOZ_INSURE_EXCLUDE_DIRS@
+
+MOZ_NATIVE_NSPR = @MOZ_NATIVE_NSPR@
+
+CROSS_COMPILE = @CROSS_COMPILE@
+
+WCHAR_CFLAGS = @WCHAR_CFLAGS@
+
+OS_CPPFLAGS = @CPPFLAGS@
+OS_CFLAGS = $(OS_CPPFLAGS) @CFLAGS@
+OS_CXXFLAGS = $(OS_CPPFLAGS) @CXXFLAGS@
+OS_LDFLAGS = @LDFLAGS@
+
+OS_COMPILE_CFLAGS = $(OS_CPPFLAGS) @COMPILE_CFLAGS@
+OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS) @COMPILE_CXXFLAGS@
+
+OS_INCLUDES = $(NSPR_CFLAGS)
+OS_LIBS = @LIBS@
+ACDEFINES = @MOZ_DEFINES@
+
+WARNINGS_AS_ERRORS = @WARNINGS_AS_ERRORS@
+
+MOZ_OPTIMIZE = @MOZ_OPTIMIZE@
+MOZ_OPTIMIZE_FLAGS = @MOZ_OPTIMIZE_FLAGS@
+MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@
+MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@
+
+MOZ_RTTI_FLAGS_ON = @_MOZ_RTTI_FLAGS_ON@
+
+MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE = @MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE@
+PROFILE_GEN_CFLAGS = @PROFILE_GEN_CFLAGS@
+PROFILE_GEN_LDFLAGS = @PROFILE_GEN_LDFLAGS@
+PROFILE_USE_CFLAGS = @PROFILE_USE_CFLAGS@
+PROFILE_USE_LDFLAGS = @PROFILE_USE_LDFLAGS@
+
+WIN_TOP_SRC = @WIN_TOP_SRC@
+CYGWIN_WRAPPER = @CYGWIN_WRAPPER@
+AS_PERL = @AS_PERL@
+CYGDRIVE_MOUNT = @CYGDRIVE_MOUNT@
+AR = @AR@
+AR_FLAGS = @AR_FLAGS@
+AR_EXTRACT = @AR_EXTRACT@
+AR_LIST = @AR_LIST@
+AR_DELETE = @AR_DELETE@
+AS = @AS@
+ASFLAGS = @ASFLAGS@
+AS_DASH_C_FLAG = @AS_DASH_C_FLAG@
+LD = @LD@
+RC = @RC@
+RCFLAGS = @RCFLAGS@
+WINDRES = @WINDRES@
+USE_SHORT_LIBNAME = @USE_SHORT_LIBNAME@
+IMPLIB = @IMPLIB@
+FILTER = @FILTER@
+BIN_FLAGS = @BIN_FLAGS@
+MIDL = @MIDL@
+MIDL_FLAGS = @MIDL_FLAGS@
+_MSC_VER = @_MSC_VER@
+
+DLL_PREFIX = @DLL_PREFIX@
+LIB_PREFIX = @LIB_PREFIX@
+OBJ_SUFFIX = @OBJ_SUFFIX@
+LIB_SUFFIX = @LIB_SUFFIX@
+DLL_SUFFIX = @DLL_SUFFIX@
+BIN_SUFFIX = @BIN_SUFFIX@
+ASM_SUFFIX = @ASM_SUFFIX@
+IMPORT_LIB_SUFFIX = @IMPORT_LIB_SUFFIX@
+USE_N32 = @USE_N32@
+HAVE_64BIT_OS = @HAVE_64BIT_OS@
+
+# Temp hack. It is not my intention to leave this crap in here for ever.
+# Im talking to fur right now to solve the problem without introducing
+# NS_USE_NATIVE to the build system -ramiro.
+NS_USE_NATIVE = @NS_USE_NATIVE@
+
+CC = @CC@
+CXX = @CXX@
+
+CC_VERSION = @CC_VERSION@
+CXX_VERSION = @CXX_VERSION@
+
+GNU_AS = @GNU_AS@
+GNU_LD = @GNU_LD@
+GNU_CC = @GNU_CC@
+GNU_CXX = @GNU_CXX@
+HAVE_GCC3_ABI = @HAVE_GCC3_ABI@
+INTEL_CC = @INTEL_CC@
+INTEL_CXX = @INTEL_CXX@
+
+HOST_CC = @HOST_CC@
+HOST_CXX = @HOST_CXX@
+HOST_CFLAGS = @HOST_CFLAGS@
+HOST_CXXFLAGS = @HOST_CXXFLAGS@
+HOST_OPTIMIZE_FLAGS = @HOST_OPTIMIZE_FLAGS@
+HOST_NSPR_MDCPUCFG = @HOST_NSPR_MDCPUCFG@
+HOST_AR = @HOST_AR@
+HOST_AR_FLAGS = @HOST_AR_FLAGS@
+HOST_LD = @HOST_LD@
+HOST_RANLIB = @HOST_RANLIB@
+HOST_BIN_SUFFIX = @HOST_BIN_SUFFIX@
+
+HOST_OS_ARCH = @HOST_OS_ARCH@
+host_cpu = @host_cpu@
+host_vendor = @host_vendor@
+host_os = @host_os@
+
+TARGET_NSPR_MDCPUCFG = @TARGET_NSPR_MDCPUCFG@
+TARGET_CPU = @TARGET_CPU@
+TARGET_VENDOR = @TARGET_VENDOR@
+TARGET_OS = @TARGET_OS@
+TARGET_MD_ARCH = @TARGET_MD_ARCH@
+TARGET_XPCOM_ABI = @TARGET_XPCOM_ABI@
+
+AUTOCONF = @AUTOCONF@
+PERL = @PERL@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+WHOAMI = @WHOAMI@
+UNZIP = @UNZIP@
+ZIP = @ZIP@
+XARGS = @XARGS@
+STRIP = @STRIP@
+DOXYGEN = @DOXYGEN@
+MAKE = @MAKE@
+PBBUILD_BIN = @PBBUILD@
+SDP = @SDP@
+NSINSTALL_BIN = @NSINSTALL_BIN@
+
+NSPR_CONFIG = @NSPR_CONFIG@
+NSPR_CFLAGS = @NSPR_CFLAGS@
+NSPR_LIBS = @NSPR_LIBS@
+
+USE_DEPENDENT_LIBS = @USE_DEPENDENT_LIBS@
+
+# MKSHLIB_FORCE_ALL is used to force the linker to include all object
+# files present in an archive. MKSHLIB_UNFORCE_ALL reverts the linker
+# to normal behavior. Makefile's that create shared libraries out of
+# archives use these flags to force in all of the .o files in the
+# archives into the shared library.
+WRAP_MALLOC_LIB = @WRAP_MALLOC_LIB@
+WRAP_MALLOC_CFLAGS = @WRAP_MALLOC_CFLAGS@
+DSO_CFLAGS = @DSO_CFLAGS@
+DSO_PIC_CFLAGS = @DSO_PIC_CFLAGS@
+MKSHLIB = @MKSHLIB@
+MKCSHLIB = @MKCSHLIB@
+MKSHLIB_FORCE_ALL = @MKSHLIB_FORCE_ALL@
+MKSHLIB_UNFORCE_ALL = @MKSHLIB_UNFORCE_ALL@
+DSO_LDOPTS = @DSO_LDOPTS@
+DLL_SUFFIX = @DLL_SUFFIX@
+
+NO_LD_ARCHIVE_FLAGS = @NO_LD_ARCHIVE_FLAGS@
+
+MOZ_TOOLKIT_REGISTRY_CFLAGS = \
+ $(TK_CFLAGS)
+
+MOZ_NATIVE_MAKEDEPEND = @SYSTEM_MAKEDEPEND@
+
+# Used for LD_LIBRARY_PATH
+LIBS_PATH = @LIBS_PATH@
+
+MOZ_AUTO_DEPS = @MOZ_AUTO_DEPS@
+COMPILER_DEPEND = @COMPILER_DEPEND@
+MDDEPDIR := @MDDEPDIR@
+
+MOZ_DEMANGLE_SYMBOLS = @MOZ_DEMANGLE_SYMBOLS@
+
+# XXX - these need to be cleaned up and have real checks added -cls
+CM_BLDTYPE=dbg
+AWT_11=1
+MOZ_BITS=32
+OS_TARGET=@OS_TARGET@
+OS_ARCH=@OS_ARCH@
+OS_RELEASE=@OS_RELEASE@
+OS_TEST=@OS_TEST@
+
+TARGET_DEVICE = @TARGET_DEVICE@
+
+# For AIX build
+AIX_OBJMODEL = @AIX_OBJMODEL@
+
+# For OS/2 build
+MOZ_OS2_TOOLS = @MOZ_OS2_TOOLS@
+MOZ_OS2_USE_DECLSPEC = @MOZ_OS2_USE_DECLSPEC@
+MOZ_OS2_HIGH_MEMORY = @MOZ_OS2_HIGH_MEMORY@
+
+MOZILLA_OFFICIAL = @MOZILLA_OFFICIAL@
+BUILD_OFFICIAL = @BUILD_OFFICIAL@
+MOZ_MILESTONE_RELEASE = @MOZ_MILESTONE_RELEASE@
+
+# Win32 options
+MOZ_PROFILE = @MOZ_PROFILE@
+MOZ_BROWSE_INFO = @MOZ_BROWSE_INFO@
+MOZ_TOOLS_DIR = @MOZ_TOOLS_DIR@
+MOZ_DEBUG_SYMBOLS = @MOZ_DEBUG_SYMBOLS@
+MOZ_QUANTIFY = @MOZ_QUANTIFY@
+MSMANIFEST_TOOL = @MSMANIFEST_TOOL@
+WIN32_REDIST_DIR = @WIN32_REDIST_DIR@
+WIN32_CRT_SRC_DIR = @WIN32_CRT_SRC_DIR@
+WIN32_CUSTOM_CRT_DIR = @WIN32_CUSTOM_CRT_DIR@
+
+# Codesighs tools option, enables win32 mapfiles.
+MOZ_MAPINFO = @MOZ_MAPINFO@
+
+WINCE = @WINCE@
+
+MACOS_SDK_DIR = @MACOS_SDK_DIR@
+NEXT_ROOT = @NEXT_ROOT@
+GCC_VERSION = @GCC_VERSION@
+XCODEBUILD_VERSION= @XCODEBUILD_VERSION@
+HAS_XCODE_2_1 = @HAS_XCODE_2_1@
+UNIVERSAL_BINARY= @UNIVERSAL_BINARY@
+HAVE_DTRACE= @HAVE_DTRACE@
+
+VISIBILITY_FLAGS = @VISIBILITY_FLAGS@
+WRAP_SYSTEM_INCLUDES = @WRAP_SYSTEM_INCLUDES@
+
+HAVE_ARM_SIMD= @HAVE_ARM_SIMD@
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-dirs.py b/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-dirs.py
new file mode 100644
index 0000000..916696e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-dirs.py
@@ -0,0 +1,108 @@
+# check-sync-dirs.py --- check that one directory is an exact subset of another
+#
+# Usage: python check-sync-dirs.py COPY ORIGINAL
+#
+# Check that the files present in the directory tree COPY are exact
+# copies of their counterparts in the directory tree ORIGINAL. COPY
+# need not have all the files in ORIGINAL, but COPY may not have files
+# absent from ORIGINAL.
+#
+# Each directory in COPY may have a file named
+# 'check-sync-exceptions', which lists files in COPY that need not be
+# the same as the corresponding file in ORIGINAL, or exist at all in
+# ORIGINAL. (The 'check-sync-exceptions' file itself is always
+# treated as exceptional.) Blank lines and '#' comments in the file
+# are ignored.
+
+import sys
+import os
+from os.path import join
+import filecmp
+import textwrap
+import fnmatch
+
+if len(sys.argv) != 3:
+ print >> sys.stderr, "Usage: %s COPY ORIGINAL" % sys.argv[0]
+ sys.exit(1)
+
+copy = sys.argv[1]
+original = sys.argv[2]
+
+# Ignore detritus left lying around by editing tools.
+ignored_patterns = ['*~', '.#*', '#*#', '*.orig', '*.rej']
+
+# Return the contents of FILENAME, a 'check-sync-exceptions' file, as
+# a dictionary whose keys are exactly the list of filenames, along
+# with the basename of FILENAME itself. If FILENAME does not exist,
+# return the empty dictionary.
+def read_exceptions(filename):
+ if (os.path.exists(filename)):
+ f = file(filename)
+ exceptions={}
+ for line in f:
+ line = line.strip()
+ if line != '' and line[0] != '#':
+ exceptions[line] = None
+ exceptions[os.path.basename (filename)] = None
+ f.close()
+ return exceptions
+ else:
+ return {}
+
+# Return true if FILENAME matches any pattern in the list of filename
+# patterns PATTERNS.
+def fnmatch_any(filename, patterns):
+ for pattern in patterns:
+ if fnmatch.fnmatch(filename, pattern):
+ return True
+ return False
+
+# Check the contents of the directory tree COPY against ORIGINAL. For each
+# file that differs, apply REPORT to COPY, ORIGINAL, and the file's
+# relative path. COPY and ORIGINAL should be absolute. Ignore files
+# that match patterns given in the list IGNORE.
+def check(copy, original, ignore, report):
+ os.chdir(copy)
+ for (dirpath, dirnames, filenames) in os.walk('.'):
+ exceptions = read_exceptions(join(dirpath, 'check-sync-exceptions'))
+ for filename in filenames:
+ if filename in exceptions:
+ continue
+ if fnmatch_any(filename, ignore):
+ continue
+ relative_name = join(dirpath, filename)
+ original_name = join(original, relative_name)
+ if (os.path.exists(original_name)
+ and filecmp.cmp(relative_name, original_name)):
+ continue
+ report(copy, original, relative_name)
+
+
+differences_found = False
+
+# Print an error message for DIFFERING, which was found to differ
+# between COPY and ORIGINAL. Set the global variable differences_found.
+def report(copy, original, differing):
+ global differences_found
+ if not differences_found:
+ print >> sys.stderr, "TEST-FAIL | build file copies are not in sync"
+ print >> sys.stderr, "file(s) found in: %s" % (copy)
+ print >> sys.stderr, ("differ from their originals in: %s"
+ % (original))
+ print >> sys.stderr, "file differs: %s" % (differing)
+ differences_found = True
+
+check(os.path.abspath(copy),
+ os.path.abspath(original),
+ ignored_patterns,
+ report)
+
+if differences_found:
+ msg=('''In general, the files in '%s' should always be exact copies of
+originals in '%s'. A change made to one should also be made to the
+other. See 'check-sync-dirs.py' for more details.'''
+ % (copy, original))
+ print >> sys.stderr, textwrap.fill(msg, 75)
+ sys.exit(1)
+
+sys.exit(0)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-exceptions b/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-exceptions
new file mode 100644
index 0000000..7c0bc47
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-exceptions
@@ -0,0 +1,6 @@
+Makefile.in
+autoconf.mk.in
+check-sync-dirs.py
+
+# This is a copy of nspr's config/make-system-wrappers.pl.
+make-system-wrappers.pl
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/config.mk b/tools/node_modules/expresso/deps/jscoverage/js/config/config.mk
new file mode 100644
index 0000000..d19ca4a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/config.mk
@@ -0,0 +1,884 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Benjamin Smedberg <benjamin@smedbergs.us>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# config.mk
+#
+# Determines the platform and builds the macros needed to load the
+# appropriate platform-specific .mk file, then defines all (most?)
+# of the generic macros.
+#
+
+# Define an include-at-most-once flag
+INCLUDED_CONFIG_MK = 1
+
+EXIT_ON_ERROR = set -e; # Shell loops continue past errors without this.
+
+ifndef topsrcdir
+topsrcdir = $(DEPTH)
+endif
+
+ifndef INCLUDED_AUTOCONF_MK
+include $(DEPTH)/config/autoconf.mk
+endif
+ifndef INCLUDED_INSURE_MK
+ifdef MOZ_INSURIFYING
+include $(topsrcdir)/config/insure.mk
+endif
+endif
+
+COMMA = ,
+
+# Sanity check some variables
+CHECK_VARS := \
+ XPI_NAME \
+ LIBRARY_NAME \
+ MODULE \
+ DEPTH \
+ SHORT_LIBNAME \
+ XPI_PKGNAME \
+ INSTALL_EXTENSION_ID \
+ $(NULL)
+
+# checks for internal spaces or trailing spaces in the variable
+# named by $x
+check-variable = $(if $(filter-out 0 1,$(words $($(x))z)),$(error Spaces are not allowed in $(x)))
+
+$(foreach x,$(CHECK_VARS),$(check-variable))
+
+# FINAL_TARGET specifies the location into which we copy end-user-shipped
+# build products (typelibs, components, chrome).
+#
+# It will usually be the well-loved $(DIST)/bin, today, but can also be an
+# XPI-contents staging directory for ambitious and right-thinking extensions.
+FINAL_TARGET = $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(DIST)/bin)
+
+# MAKE_JARS_TARGET is a staging area for make-jars.pl. When packaging in
+# the jar format, make-jars leaves behind a directory structure that's not
+# needed in $(FINAL_TARGET). For both, flat, and symlink, the directory
+# structure contains the chrome, so leave it in $(FINAL_TARGET).
+ifeq (jar,$(MOZ_CHROME_FILE_FORMAT))
+MAKE_JARS_TARGET = $(if $(XPI_NAME),$(FINAL_TARGET).stage,$(DIST)/chrome-stage)
+else
+MAKE_JARS_TARGET = $(FINAL_TARGET)
+endif
+
+#
+# The VERSION_NUMBER is suffixed onto the end of the DLLs we ship.
+# Since the longest of these is 5 characters without the suffix,
+# be sure to not set VERSION_NUMBER to anything longer than 3
+# characters for Win16's sake.
+#
+VERSION_NUMBER = 50
+
+ifeq ($(HOST_OS_ARCH),WINNT)
+win_srcdir := $(subst $(topsrcdir),$(WIN_TOP_SRC),$(srcdir))
+BUILD_TOOLS = $(WIN_TOP_SRC)/build/unix
+else
+win_srcdir := $(srcdir)
+BUILD_TOOLS = $(topsrcdir)/build/unix
+endif
+
+CONFIG_TOOLS = $(MOZ_BUILD_ROOT)/config
+AUTOCONF_TOOLS = $(topsrcdir)/build/autoconf
+
+ifeq ($(OS_ARCH),QNX)
+ifeq ($(OS_TARGET),NTO)
+LD := qcc -Vgcc_ntox86 -nostdlib
+else
+LD := $(CC)
+endif
+endif
+ifeq ($(OS_ARCH),BeOS)
+BEOS_ADDON_WORKAROUND = 1
+endif
+
+#
+# Strip off the excessively long version numbers on these platforms,
+# but save the version to allow multiple versions of the same base
+# platform to be built in the same tree.
+#
+ifneq (,$(filter FreeBSD HP-UX IRIX Linux NetBSD OpenBSD OSF1 SunOS,$(OS_ARCH)))
+OS_RELEASE := $(basename $(OS_RELEASE))
+
+# Allow the user to ignore the OS_VERSION, which is usually irrelevant.
+ifdef WANT_MOZILLA_CONFIG_OS_VERSION
+OS_VERS := $(suffix $(OS_RELEASE))
+OS_VERSION := $(shell echo $(OS_VERS) | sed 's/-.*//')
+endif
+
+endif
+
+OS_CONFIG := $(OS_ARCH)$(OS_RELEASE)
+
+FINAL_LINK_LIBS = $(DEPTH)/config/final-link-libs
+FINAL_LINK_COMPS = $(DEPTH)/config/final-link-comps
+FINAL_LINK_COMP_NAMES = $(DEPTH)/config/final-link-comp-names
+
+MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX)
+MOZ_WIDGET_SUPPORT_LIBS = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX)
+
+ifdef MOZ_MEMORY
+ifneq ($(OS_ARCH),WINNT)
+JEMALLOC_LIBS = $(MKSHLIB_FORCE_ALL) $(call EXPAND_LIBNAME,jemalloc) $(MKSHLIB_UNFORCE_ALL)
+endif
+endif
+
+# determine debug-related options
+_DEBUG_CFLAGS :=
+_DEBUG_LDFLAGS :=
+
+ifndef MOZ_DEBUG
+ # global debugging is disabled
+ # check if it was explicitly enabled for this module
+ ifneq (, $(findstring $(MODULE), $(MOZ_DEBUG_MODULES)))
+ MOZ_DEBUG:=1
+ endif
+else
+ # global debugging is enabled
+ # check if it was explicitly disabled for this module
+ ifneq (, $(findstring ^$(MODULE), $(MOZ_DEBUG_MODULES)))
+ MOZ_DEBUG:=
+ endif
+endif
+
+ifdef MOZ_DEBUG
+ _DEBUG_CFLAGS += $(MOZ_DEBUG_ENABLE_DEFS)
+ XULPPFLAGS += $(MOZ_DEBUG_ENABLE_DEFS)
+else
+ _DEBUG_CFLAGS += $(MOZ_DEBUG_DISABLE_DEFS)
+ XULPPFLAGS += $(MOZ_DEBUG_DISABLE_DEFS)
+endif
+
+# determine if -g should be passed to the compiler, based on
+# the current module, and the value of MOZ_DBGRINFO_MODULES
+
+ifdef MOZ_DEBUG
+ MOZ_DBGRINFO_MODULES += ALL_MODULES
+ pattern := ALL_MODULES ^ALL_MODULES
+else
+ MOZ_DBGRINFO_MODULES += ^ALL_MODULES
+ pattern := ALL_MODULES ^ALL_MODULES
+endif
+
+ifdef MODULE
+ # our current Makefile specifies a module name - add it to our pattern
+ pattern += $(MODULE) ^$(MODULE)
+endif
+
+# start by finding the first relevant module name
+# (remember that the order of the module names in MOZ_DBGRINFO_MODULES
+# is reversed from the order the user specified to configure -
+# this allows the user to put general names at the beginning
+# of the list, and to override them with explicit module names later
+# in the list)
+
+first_match:=$(firstword $(filter $(pattern), $(MOZ_DBGRINFO_MODULES)))
+
+ifeq ($(first_match), $(MODULE))
+ # the user specified explicitly that
+ # this module should be compiled with -g
+ _DEBUG_CFLAGS += $(MOZ_DEBUG_FLAGS)
+ _DEBUG_LDFLAGS += $(MOZ_DEBUG_LDFLAGS)
+else
+ ifeq ($(first_match), ^$(MODULE))
+ # the user specified explicitly that this module
+ # should not be compiled with -g (nothing to do)
+ else
+ ifeq ($(first_match), ALL_MODULES)
+ # the user didn't mention this module explicitly,
+ # but wanted all modules to be compiled with -g
+ _DEBUG_CFLAGS += $(MOZ_DEBUG_FLAGS)
+ _DEBUG_LDFLAGS += $(MOZ_DEBUG_LDFLAGS)
+ else
+ ifeq ($(first_match), ^ALL_MODULES)
+ # the user didn't mention this module explicitly,
+ # but wanted all modules to be compiled without -g (nothing to do)
+ endif
+ endif
+ endif
+endif
+
+
+# append debug flags
+# (these might have been above when processing MOZ_DBGRINFO_MODULES)
+OS_CFLAGS += $(_DEBUG_CFLAGS)
+OS_CXXFLAGS += $(_DEBUG_CFLAGS)
+OS_LDFLAGS += $(_DEBUG_LDFLAGS)
+
+# MOZ_PROFILE equivs for win32
+ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
+ifdef MOZ_DEBUG
+ifneq (,$(MOZ_BROWSE_INFO)$(MOZ_BSCFILE))
+OS_CFLAGS += -FR
+OS_CXXFLAGS += -FR
+endif
+else # ! MOZ_DEBUG
+
+# MOZ_DEBUG_SYMBOLS generates debug symbols in separate PDB files.
+# Used for generating an optimized build with debugging symbols.
+# Used in the Windows nightlies to generate symbols for crash reporting.
+ifdef MOZ_DEBUG_SYMBOLS
+OS_CXXFLAGS += -Zi -UDEBUG -DNDEBUG
+OS_CFLAGS += -Zi -UDEBUG -DNDEBUG
+OS_LDFLAGS += -DEBUG -OPT:REF -OPT:nowin98
+endif
+
+ifdef MOZ_QUANTIFY
+# -FIXED:NO is needed for Quantify to work, but it increases the size
+# of executables, so only use it if building for Quantify.
+WIN32_EXE_LDFLAGS += -FIXED:NO
+
+# We need -OPT:NOICF to prevent identical methods from being merged together.
+# Otherwise, Quantify doesn't know which method was actually called when it's
+# showing you the profile.
+OS_LDFLAGS += -OPT:NOICF
+endif
+
+#
+# Handle trace-malloc in optimized builds.
+# No opt to give sane callstacks.
+#
+ifdef NS_TRACE_MALLOC
+MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDEBUG
+OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF -OPT:nowin98
+endif # NS_TRACE_MALLOC
+
+endif # MOZ_DEBUG
+endif # WINNT && !GNU_CC
+
+#
+# Build using PIC by default
+# Do not use PIC if not building a shared lib (see exceptions below)
+#
+
+ifndef BUILD_STATIC_LIBS
+_ENABLE_PIC=1
+endif
+ifneq (,$(FORCE_SHARED_LIB)$(FORCE_USE_PIC))
+_ENABLE_PIC=1
+endif
+
+# In Firefox, all components are linked into either libxul or the static
+# meta-component, and should be compiled with PIC.
+ifdef MOZ_META_COMPONENT
+_ENABLE_PIC=1
+endif
+
+# If module is going to be merged into the nsStaticModule,
+# make sure that the entry points are translated and
+# the module is built static.
+
+ifdef IS_COMPONENT
+ifdef EXPORT_LIBRARY
+ifneq (,$(BUILD_STATIC_LIBS))
+ifdef MODULE_NAME
+DEFINES += -DXPCOM_TRANSLATE_NSGM_ENTRY_POINT=1
+FORCE_STATIC_LIB=1
+endif
+endif
+endif
+endif
+
+# Determine if module being compiled is destined
+# to be merged into libxul
+
+ifdef MOZ_ENABLE_LIBXUL
+ifdef LIBXUL_LIBRARY
+ifdef IS_COMPONENT
+ifdef MODULE_NAME
+DEFINES += -DXPCOM_TRANSLATE_NSGM_ENTRY_POINT=1
+else
+$(error Component makefile does not specify MODULE_NAME.)
+endif
+endif
+FORCE_STATIC_LIB=1
+_ENABLE_PIC=1
+SHORT_LIBNAME=
+endif
+endif
+
+# If we are building this component into an extension/xulapp, it cannot be
+# statically linked. In the future we may want to add a xulapp meta-component
+# build option.
+
+ifdef XPI_NAME
+_ENABLE_PIC=1
+ifdef IS_COMPONENT
+EXPORT_LIBRARY=
+FORCE_STATIC_LIB=
+FORCE_SHARED_LIB=1
+endif
+endif
+
+#
+# Disable PIC if necessary
+#
+
+ifndef _ENABLE_PIC
+DSO_CFLAGS=
+ifeq ($(OS_ARCH)_$(HAVE_GCC3_ABI),Darwin_1)
+DSO_PIC_CFLAGS=-mdynamic-no-pic
+else
+DSO_PIC_CFLAGS=
+endif
+endif
+
+# This comes from configure
+ifdef MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE
+NO_PROFILE_GUIDED_OPTIMIZE = 1
+endif
+
+# Enable profile-based feedback
+ifndef NO_PROFILE_GUIDED_OPTIMIZE
+ifdef MOZ_PROFILE_GENERATE
+# No sense in profiling tools
+ifndef INTERNAL_TOOLS
+OS_CFLAGS += $(PROFILE_GEN_CFLAGS)
+OS_CXXFLAGS += $(PROFILE_GEN_CFLAGS)
+OS_LDFLAGS += $(PROFILE_GEN_LDFLAGS)
+ifeq (WINNT,$(OS_ARCH))
+AR_FLAGS += -LTCG
+endif
+endif # INTERNAL_TOOLS
+endif # MOZ_PROFILE_GENERATE
+
+ifdef MOZ_PROFILE_USE
+ifndef INTERNAL_TOOLS
+OS_CFLAGS += $(PROFILE_USE_CFLAGS)
+OS_CXXFLAGS += $(PROFILE_USE_CFLAGS)
+OS_LDFLAGS += $(PROFILE_USE_LDFLAGS)
+ifeq (WINNT,$(OS_ARCH))
+AR_FLAGS += -LTCG
+endif
+endif # INTERNAL_TOOLS
+endif # MOZ_PROFILE_USE
+endif # NO_PROFILE_GUIDED_OPTIMIZE
+
+
+# Does the makefile specifies the internal XPCOM API linkage?
+ifneq (,$(MOZILLA_INTERNAL_API)$(LIBXUL_LIBRARY))
+DEFINES += -DMOZILLA_INTERNAL_API
+endif
+
+# Force XPCOM/widget/gfx methods to be _declspec(dllexport) when we're
+# building libxul libraries
+ifdef MOZ_ENABLE_LIBXUL
+ifdef LIBXUL_LIBRARY
+DEFINES += \
+ -D_IMPL_NS_COM \
+ -DEXPORT_XPT_API \
+ -DEXPORT_XPTC_API \
+ -D_IMPL_NS_COM_OBSOLETE \
+ -D_IMPL_NS_GFX \
+ -D_IMPL_NS_WIDGET \
+ -DIMPL_XREAPI \
+ -DIMPL_NS_NET \
+ -DIMPL_THEBES \
+ $(NULL)
+
+ifndef MOZ_NATIVE_ZLIB
+DEFINES += -DZLIB_INTERNAL
+endif
+endif
+endif
+
+# Force _all_ exported methods to be |_declspec(dllexport)| when we're
+# building them into the executable.
+
+ifeq (,$(filter-out WINNT WINCE OS2, $(OS_ARCH)))
+ifdef BUILD_STATIC_LIBS
+DEFINES += \
+ -D_IMPL_NS_GFX \
+ -D_IMPL_NS_MSG_BASE \
+ -D_IMPL_NS_WIDGET \
+ $(NULL)
+endif
+endif
+
+# Flags passed to make-jars.pl
+
+MAKE_JARS_FLAGS = \
+ -t $(topsrcdir) \
+ -f $(MOZ_CHROME_FILE_FORMAT) \
+ $(NULL)
+
+ifdef USE_EXTENSION_MANIFEST
+MAKE_JARS_FLAGS += -e
+endif
+
+ifdef BOTH_MANIFESTS
+MAKE_JARS_FLAGS += --both-manifests
+endif
+
+TAR_CREATE_FLAGS = -cvhf
+
+ifeq ($(OS_ARCH),BSD_OS)
+TAR_CREATE_FLAGS = -cvLf
+endif
+
+ifeq ($(OS_ARCH),OS2)
+TAR_CREATE_FLAGS = -cvf
+endif
+
+#
+# Personal makefile customizations go in these optional make include files.
+#
+MY_CONFIG := $(DEPTH)/config/myconfig.mk
+MY_RULES := $(DEPTH)/config/myrules.mk
+
+#
+# Default command macros; can be overridden in <arch>.mk.
+#
+CCC = $(CXX)
+NFSPWD = $(CONFIG_TOOLS)/nfspwd
+PURIFY = purify $(PURIFYOPTIONS)
+QUANTIFY = quantify $(QUANTIFYOPTIONS)
+ifdef CROSS_COMPILE
+XPIDL_COMPILE = $(CYGWIN_WRAPPER) $(LIBXUL_DIST)/host/bin/host_xpidl$(HOST_BIN_SUFFIX)
+XPIDL_LINK = $(CYGWIN_WRAPPER) $(LIBXUL_DIST)/host/bin/host_xpt_link$(HOST_BIN_SUFFIX)
+else
+XPIDL_COMPILE = $(CYGWIN_WRAPPER) $(LIBXUL_DIST)/bin/xpidl$(BIN_SUFFIX)
+XPIDL_LINK = $(CYGWIN_WRAPPER) $(LIBXUL_DIST)/bin/xpt_link$(BIN_SUFFIX)
+endif
+
+# Java macros
+JAVA_GEN_DIR = _javagen
+JAVA_DIST_DIR = $(DEPTH)/$(JAVA_GEN_DIR)
+JAVA_IFACES_PKG_NAME = org/mozilla/interfaces
+
+REQ_INCLUDES = -I$(srcdir) -I. $(foreach d,$(REQUIRES),-I$(DIST)/include/$d) -I$(DIST)/include
+ifdef LIBXUL_SDK
+REQ_INCLUDES_SDK = $(foreach d,$(REQUIRES),-I$(LIBXUL_SDK)/include/$d) -I$(LIBXUL_SDK)/include
+endif
+
+INCLUDES = $(LOCAL_INCLUDES) $(REQ_INCLUDES) $(REQ_INCLUDES_SDK) -I$(PUBLIC) $(OS_INCLUDES)
+
+ifndef MOZILLA_INTERNAL_API
+INCLUDES += -I$(LIBXUL_DIST)/sdk/include
+endif
+
+# The entire tree should be subject to static analysis using the XPCOM
+# script. Additional scripts may be added by specific subdirectories.
+
+DEHYDRA_SCRIPT = $(topsrcdir)/xpcom/analysis/static-checking.js
+
+DEHYDRA_MODULES = \
+ $(topsrcdir)/xpcom/analysis/final.js \
+ $(NULL)
+
+TREEHYDRA_MODULES = \
+ $(topsrcdir)/xpcom/analysis/outparams.js \
+ $(topsrcdir)/xpcom/analysis/stack.js \
+ $(topsrcdir)/xpcom/analysis/flow.js \
+ $(NULL)
+
+DEHYDRA_ARGS = \
+ --topsrcdir=$(topsrcdir) \
+ --objdir=$(DEPTH) \
+ --dehydra-modules=$(subst $(NULL) ,$(COMMA),$(strip $(DEHYDRA_MODULES))) \
+ --treehydra-modules=$(subst $(NULL) ,$(COMMA),$(strip $(TREEHYDRA_MODULES))) \
+ $(NULL)
+
+DEHYDRA_FLAGS = -fplugin=$(DEHYDRA_PATH) -fplugin-arg='$(DEHYDRA_SCRIPT) $(DEHYDRA_ARGS)'
+
+ifdef DEHYDRA_PATH
+OS_CXXFLAGS += $(DEHYDRA_FLAGS)
+endif
+
+CFLAGS = $(OS_CFLAGS)
+CXXFLAGS = $(OS_CXXFLAGS)
+LDFLAGS = $(OS_LDFLAGS) $(MOZ_FIX_LINK_PATHS)
+
+# Allow each module to override the *default* optimization settings
+# by setting MODULE_OPTIMIZE_FLAGS if the developer has not given
+# arguments to --enable-optimize
+ifdef MOZ_OPTIMIZE
+ifeq (1,$(MOZ_OPTIMIZE))
+ifdef MODULE_OPTIMIZE_FLAGS
+CFLAGS += $(MODULE_OPTIMIZE_FLAGS)
+CXXFLAGS += $(MODULE_OPTIMIZE_FLAGS)
+else
+CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+endif # MODULE_OPTIMIZE_FLAGS
+else
+CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+endif # MOZ_OPTIMIZE == 1
+LDFLAGS += $(MOZ_OPTIMIZE_LDFLAGS)
+endif # MOZ_OPTIMIZE
+
+ifdef CROSS_COMPILE
+HOST_CFLAGS += $(HOST_OPTIMIZE_FLAGS)
+else
+ifdef MOZ_OPTIMIZE
+ifeq (1,$(MOZ_OPTIMIZE))
+ifdef MODULE_OPTIMIZE_FLAGS
+HOST_CFLAGS += $(MODULE_OPTIMIZE_FLAGS)
+else
+HOST_CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+endif # MODULE_OPTIMIZE_FLAGS
+else
+HOST_CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+endif # MOZ_OPTIMIZE == 1
+endif # MOZ_OPTIMIZE
+endif # CROSS_COMPILE
+
+
+ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
+#// Currently, unless USE_STATIC_LIBS is defined, the multithreaded
+#// DLL version of the RTL is used...
+#//
+#//------------------------------------------------------------------------
+ifdef USE_STATIC_LIBS
+RTL_FLAGS=-MT # Statically linked multithreaded RTL
+ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
+ifndef MOZ_NO_DEBUG_RTL
+RTL_FLAGS=-MTd # Statically linked multithreaded MSVC4.0 debug RTL
+endif
+endif # MOZ_DEBUG || NS_TRACE_MALLOC
+
+else # !USE_STATIC_LIBS
+
+RTL_FLAGS=-MD # Dynamically linked, multithreaded RTL
+ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
+ifndef MOZ_NO_DEBUG_RTL
+RTL_FLAGS=-MDd # Dynamically linked, multithreaded MSVC4.0 debug RTL
+endif
+endif # MOZ_DEBUG || NS_TRACE_MALLOC
+endif # USE_STATIC_LIBS
+endif # WINNT && !GNU_CC
+
+ifeq ($(OS_ARCH),Darwin)
+# Darwin doesn't cross-compile, so just set both types of flags here.
+HOST_CMFLAGS += -fobjc-exceptions
+HOST_CMMFLAGS += -fobjc-exceptions
+OS_COMPILE_CMFLAGS += -fobjc-exceptions
+OS_COMPILE_CMMFLAGS += -fobjc-exceptions
+endif
+
+COMPILE_CFLAGS = $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS) $(PROFILER_CFLAGS) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(CFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CFLAGS)
+COMPILE_CXXFLAGS = $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS) $(PROFILER_CFLAGS) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(CXXFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CXXFLAGS)
+COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS)
+COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS)
+
+ifndef CROSS_COMPILE
+HOST_CFLAGS += $(RTL_FLAGS)
+endif
+
+#
+# Name of the binary code directories
+#
+# Override defaults
+
+# We need to know where to find the libraries we
+# put on the link line for binaries, and should
+# we link statically or dynamic? Assuming dynamic for now.
+
+ifneq (WINNT_,$(OS_ARCH)_$(GNU_CC))
+ifneq (,$(filter-out WINCE,$(OS_ARCH)))
+LIBS_DIR = -L$(DIST)/bin -L$(DIST)/lib
+ifdef LIBXUL_SDK
+LIBS_DIR += -L$(LIBXUL_SDK)/bin -L$(LIBXUL_SDK)/lib
+endif
+endif
+endif
+
+# Default location of include files
+IDL_DIR = $(DIST)/idl
+ifdef MODULE
+PUBLIC = $(DIST)/include/$(MODULE)
+else
+PUBLIC = $(DIST)/include
+endif
+
+XPIDL_FLAGS = -I$(srcdir) -I$(IDL_DIR)
+ifdef LIBXUL_SDK
+XPIDL_FLAGS += -I$(LIBXUL_SDK)/idl
+endif
+
+SDK_PUBLIC = $(DIST)/sdk/include
+SDK_IDL_DIR = $(DIST)/sdk/idl
+SDK_LIB_DIR = $(DIST)/sdk/lib
+SDK_BIN_DIR = $(DIST)/sdk/bin
+
+DEPENDENCIES = .md
+
+MOZ_COMPONENT_LIBS=$(XPCOM_LIBS) $(MOZ_COMPONENT_NSPR_LIBS)
+
+ifdef GC_LEAK_DETECTOR
+XPCOM_LIBS += -lboehm
+endif
+
+ifeq (xpconnect, $(findstring xpconnect, $(BUILD_MODULES)))
+DEFINES += -DXPCONNECT_STANDALONE
+endif
+
+ifeq ($(OS_ARCH),OS2)
+ELF_DYNSTR_GC = echo
+else
+ELF_DYNSTR_GC = :
+endif
+
+ifndef CROSS_COMPILE
+ifdef USE_ELF_DYNSTR_GC
+ifdef MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS
+ELF_DYNSTR_GC = $(DEPTH)/config/elf-dynstr-gc
+endif
+endif
+endif
+
+ifeq ($(OS_ARCH),Darwin)
+ifdef NEXT_ROOT
+export NEXT_ROOT
+PBBUILD = NEXT_ROOT= $(PBBUILD_BIN)
+else # NEXT_ROOT
+PBBUILD = $(PBBUILD_BIN)
+endif # NEXT_ROOT
+PBBUILD_SETTINGS = GCC_VERSION="$(GCC_VERSION)" SYMROOT=build ARCHS="$(OS_TEST)"
+ifdef MACOS_SDK_DIR
+PBBUILD_SETTINGS += SDKROOT="$(MACOS_SDK_DIR)"
+endif # MACOS_SDK_DIR
+ifdef MACOSX_DEPLOYMENT_TARGET
+export MACOSX_DEPLOYMENT_TARGET
+PBBUILD_SETTINGS += MACOSX_DEPLOYMENT_TARGET="$(MACOSX_DEPLOYMENT_TARGET)"
+endif # MACOSX_DEPLOYMENT_TARGET
+ifdef MOZ_OPTIMIZE
+ifeq (2,$(MOZ_OPTIMIZE))
+# Only override project defaults if the config specified explicit settings
+PBBUILD_SETTINGS += GCC_MODEL_TUNING= OPTIMIZATION_CFLAGS="$(MOZ_OPTIMIZE_FLAGS)"
+endif # MOZ_OPTIMIZE=2
+endif # MOZ_OPTIMIZE
+ifeq (1,$(HAS_XCODE_2_1))
+# Xcode 2.1 puts its build products in a directory corresponding to the
+# selected build style/configuration.
+XCODE_PRODUCT_DIR = build/$(BUILDSTYLE)
+else
+XCODE_PRODUCT_DIR = build
+endif # HAS_XCODE_2_1=1
+endif # OS_ARCH=Darwin
+
+
+ifdef MOZ_NATIVE_MAKEDEPEND
+MKDEPEND_DIR =
+MKDEPEND = $(CYGWIN_WRAPPER) $(MOZ_NATIVE_MAKEDEPEND)
+else
+MKDEPEND_DIR = $(CONFIG_TOOLS)/mkdepend
+MKDEPEND = $(CYGWIN_WRAPPER) $(MKDEPEND_DIR)/mkdepend$(BIN_SUFFIX)
+endif
+
+# Set link flags according to whether we want a console.
+ifdef MOZ_WINCONSOLE
+ifeq ($(MOZ_WINCONSOLE),1)
+ifeq ($(OS_ARCH),OS2)
+BIN_FLAGS += -Zlinker -PM:VIO
+endif
+ifeq ($(OS_ARCH),WINNT)
+ifdef GNU_CC
+WIN32_EXE_LDFLAGS += -mconsole
+else
+WIN32_EXE_LDFLAGS += -SUBSYSTEM:CONSOLE
+endif
+endif
+else # MOZ_WINCONSOLE
+ifeq ($(OS_ARCH),OS2)
+BIN_FLAGS += -Zlinker -PM:PM
+endif
+ifeq ($(OS_ARCH),WINNT)
+ifdef GNU_CC
+WIN32_EXE_LDFLAGS += -mwindows
+else
+WIN32_EXE_LDFLAGS += -SUBSYSTEM:WINDOWS
+endif
+endif
+endif
+endif
+
+# Flags needed to link against the component library
+ifdef MOZ_COMPONENTLIB
+MOZ_COMPONENTLIB_EXTRA_DSO_LIBS = mozcomps xpcom_compat
+
+# Tell the linker where NSS is, if we're building crypto
+ifeq ($(OS_ARCH),Darwin)
+ifeq (,$(findstring crypto,$(MOZ_META_COMPONENTS)))
+MOZ_COMPONENTLIB_EXTRA_LIBS = $(foreach library, $(patsubst -l%, $(LIB_PREFIX)%$(DLL_SUFFIX), $(filter -l%, $(NSS_LIBS))), -dylib_file @executable_path/$(library):$(DIST)/bin/$(library))
+endif
+endif
+endif
+
+# If we're building a component on MSVC, we don't want to generate an
+# import lib, because that import lib will collide with the name of a
+# static version of the same library.
+ifeq ($(GNU_LD)$(OS_ARCH),WINNT)
+ifdef IS_COMPONENT
+LDFLAGS += -IMPLIB:fake.lib
+DELETE_AFTER_LINK = fake.lib fake.exp
+endif
+endif
+
+#
+# Include any personal overrides the user might think are needed.
+#
+-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-config.mk
+-include $(MY_CONFIG)
+
+######################################################################
+# Now test variables that might have been set or overridden by $(MY_CONFIG).
+
+DEFINES += -DOSTYPE=\"$(OS_CONFIG)\"
+DEFINES += -DOSARCH=$(OS_ARCH)
+
+# For profiling
+ifdef ENABLE_EAZEL_PROFILER
+ifndef INTERNAL_TOOLS
+ifneq ($(LIBRARY_NAME), xpt)
+ifneq (, $(findstring $(shell $(topsrcdir)/build/unix/print-depth-path.sh | awk -F/ '{ print $$2; }'), $(MOZ_PROFILE_MODULES)))
+PROFILER_CFLAGS = $(EAZEL_PROFILER_CFLAGS) -DENABLE_EAZEL_PROFILER
+PROFILER_LIBS = $(EAZEL_PROFILER_LIBS)
+endif
+endif
+endif
+endif
+
+######################################################################
+
+GARBAGE += $(DEPENDENCIES) $(MKDEPENDENCIES) $(MKDEPENDENCIES).bak core $(wildcard core.[0-9]*) $(wildcard *.err) $(wildcard *.pure) $(wildcard *_pure_*.o) Templates.DB
+
+ifeq ($(OS_ARCH),Darwin)
+ifndef NSDISTMODE
+NSDISTMODE=absolute_symlink
+endif
+PWD := $(shell pwd)
+endif
+
+ifdef NSINSTALL_BIN
+NSINSTALL = $(CYGWIN_WRAPPER) $(NSINSTALL_BIN)
+else
+ifeq (WINNT,$(CROSS_COMPILE)$(OS_ARCH))
+NSINSTALL = $(CYGWIN_WRAPPER) $(MOZ_TOOLS_DIR)/bin/nsinstall
+else
+ifeq (OS2,$(CROSS_COMPILE)$(OS_ARCH))
+NSINSTALL = $(MOZ_TOOLS_DIR)/nsinstall
+else
+NSINSTALL = $(CONFIG_TOOLS)/nsinstall
+endif # OS2
+endif # WINNT
+endif # NSINSTALL_BIN
+
+
+ifeq (,$(CROSS_COMPILE)$(filter-out WINNT OS2, $(OS_ARCH)))
+INSTALL = $(NSINSTALL)
+else
+ifeq ($(NSDISTMODE),copy)
+# copy files, but preserve source mtime
+INSTALL = $(NSINSTALL) -t
+else
+ifeq ($(NSDISTMODE),absolute_symlink)
+# install using absolute symbolic links
+ifeq ($(OS_ARCH),Darwin)
+INSTALL = $(NSINSTALL) -L $(PWD)
+else
+INSTALL = $(NSINSTALL) -L `$(NFSPWD)`
+endif # Darwin
+else
+# install using relative symbolic links
+INSTALL = $(NSINSTALL) -R
+endif # absolute_symlink
+endif # copy
+endif # WINNT/OS2
+
+ifeq (,$(filter-out WINCE,$(OS_ARCH)))
+NSINSTALL = $(CYGWIN_WRAPPER) nsinstall
+INSTALL = $(CYGWIN_WRAPPER) nsinstall
+endif
+
+# Use nsinstall in copy mode to install files on the system
+SYSINSTALL = $(NSINSTALL) -t
+
+ifeq ($(OS_ARCH),WINNT)
+ifneq (,$(CYGDRIVE_MOUNT))
+export CYGDRIVE_MOUNT
+endif
+endif
+
+#
+# Localization build automation
+#
+
+# Because you might wish to "make locales AB_CD=ab-CD", we don't hardcode
+# MOZ_UI_LOCALE directly, but use an intermediate variable that can be
+# overridden by the command line. (Besides, AB_CD is prettier).
+AB_CD = $(MOZ_UI_LOCALE)
+
+ifndef L10NBASEDIR
+L10NBASEDIR = $(error L10NBASEDIR not defined by configure)
+endif
+
+EXPAND_LOCALE_SRCDIR = $(if $(filter en-US,$(AB_CD)),$(topsrcdir)/$(1)/en-US,$(L10NBASEDIR)/$(AB_CD)/$(subst /locales,,$(1)))
+
+ifdef relativesrcdir
+LOCALE_SRCDIR = $(call EXPAND_LOCALE_SRCDIR,$(relativesrcdir))
+endif
+
+ifdef LOCALE_SRCDIR
+# if LOCALE_MERGEDIR is set, use mergedir first, then the localization,
+# and finally en-US
+ifdef LOCALE_MERGEDIR
+MAKE_JARS_FLAGS += -c $(LOCALE_MERGEDIR)/$(subst /locales,,$(relativesrcdir))
+endif
+MAKE_JARS_FLAGS += -c $(LOCALE_SRCDIR)
+ifdef LOCALE_MERGEDIR
+MAKE_JARS_FLAGS += -c $(topsrcdir)/$(relativesrcdir)/en-US
+endif
+endif
+
+ifeq (,$(filter WINCE WINNT OS2,$(OS_ARCH)))
+RUN_TEST_PROGRAM = $(DIST)/bin/run-mozilla.sh
+endif
+
+#
+# Java macros
+#
+
+# Make sure any compiled classes work with at least JVM 1.4
+JAVAC_FLAGS += -source 1.4
+
+ifdef MOZ_DEBUG
+JAVAC_FLAGS += -g
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/fastcwd.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/fastcwd.pl
new file mode 100644
index 0000000..c327ccf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/fastcwd.pl
@@ -0,0 +1,66 @@
+#!perl5
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+sub fastcwd {
+ local($odev, $oino, $cdev, $cino, $tdev, $tino);
+ local(@path, $path);
+ local(*DIR);
+
+ ($cdev, $cino) = stat('.');
+ for (;;) {
+ ($odev, $oino) = ($cdev, $cino);
+ chdir('..');
+ ($cdev, $cino) = stat('.');
+ last if $odev == $cdev && $oino == $cino;
+ opendir(DIR, '.');
+ for (;;) {
+ $_ = readdir(DIR);
+ next if $_ eq '.';
+ next if $_ eq '..';
+
+ last unless $_;
+ ($tdev, $tino) = lstat($_);
+ last unless $tdev != $odev || $tino != $oino;
+ }
+ closedir(DIR);
+ unshift(@path, $_);
+ }
+ chdir($path = '/' . join('/', @path));
+ $path;
+}
+1;
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/gcc_hidden.h b/tools/node_modules/expresso/deps/jscoverage/js/config/gcc_hidden.h
new file mode 100644
index 0000000..58140c1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/gcc_hidden.h
@@ -0,0 +1,2 @@
+/* Begin all files as hidden visibility */
+#pragma GCC visibility push(hidden)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/insure.mk b/tools/node_modules/expresso/deps/jscoverage/js/config/insure.mk
new file mode 100644
index 0000000..fc796eb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/insure.mk
@@ -0,0 +1,53 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+INCLUDED_INSURE_MK = 1
+
+INSURE_MATCH_SCRIPT=$(topsrcdir)/build/autoconf/match-dir.sh
+
+INSURE_EXCLUDE=$(shell $(INSURE_MATCH_SCRIPT) $(MOZ_INSURE_EXCLUDE_DIRS))
+
+INSURE_INCLUDE=$(shell $(INSURE_MATCH_SCRIPT) $(MOZ_INSURE_DIRS))
+
+ifeq ($(INSURE_EXCLUDE),0)
+
+ifeq ($(INSURE_INCLUDE),1)
+CC := $(MOZ_INSURE)
+CXX := $(MOZ_INSURE)
+endif # INSURE_INCLUDE == 1
+
+endif # INSURE_EXCLUDE == 0
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/make-system-wrappers.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/make-system-wrappers.pl
new file mode 100644
index 0000000..31c9af4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/make-system-wrappers.pl
@@ -0,0 +1,59 @@
+#!/usr/bin/perl
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# IBM Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Brian Ryner <bryner@brianryner.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+$output_dir = shift;
+
+while (<STDIN>) {
+ chomp;
+ if (-e "$output_dir/$_") {
+ next;
+ }
+
+ if (/(.*)\/[^\/*]/) {
+ mkdir "$output_dir/$1";
+ }
+
+ open OUT, ">$output_dir/$_";
+ print OUT "#pragma GCC system_header\n"; # suppress include_next warning
+ print OUT "#pragma GCC visibility push(default)\n";
+ print OUT "#include_next \<$_\>\n";
+ print OUT "#pragma GCC visibility pop\n";
+ close OUT;
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.pl
new file mode 100644
index 0000000..e3cee2a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.pl
@@ -0,0 +1,112 @@
+#!/usr/bin/perl -w
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Win32 Version System.
+#
+# The Initial Developer of the Original Code is Netscape Communications Corporation
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+use Getopt::Long;
+
+use strict;
+use vars qw(
+ $OBJDIR
+ $SRCDIR
+ $TOPSRCDIR
+ $SCRIPTDIR
+ @TEMPLATE_FILE
+ $MILESTONE_FILE
+ $MILESTONE
+ $MILESTONE_NUM
+ @MILESTONE_PARTS
+ $MINI_VERSION
+ $MICRO_VERSION
+ $opt_debug
+ $opt_template
+ $opt_help
+ );
+
+$SCRIPTDIR = $0;
+$SCRIPTDIR =~ s/[^\/]*$//;
+push(@INC,$SCRIPTDIR);
+
+require "Moz/Milestone.pm";
+
+&GetOptions('topsrcdir=s' => \$TOPSRCDIR, 'srcdir=s' => \$SRCDIR, 'objdir=s' => \$OBJDIR, 'debug', 'help', 'template');
+
+if (defined($opt_help)) {
+ &usage();
+ exit;
+}
+
+if (defined($opt_template)) {
+ @TEMPLATE_FILE = @ARGV;
+ if ($opt_debug) {
+ print("TEMPLATE_FILE = --@TEMPLATE_FILE--\n");
+ }
+}
+
+if (!defined($SRCDIR)) { $SRCDIR = '.'; }
+if (!defined($OBJDIR)) { $OBJDIR = '.'; }
+
+$MILESTONE_FILE = "$TOPSRCDIR/config/milestone.txt";
+@MILESTONE_PARTS = (0, 0, 0, 0);
+
+#
+# Grab milestone (top line of $MILESTONE_FILE that starts with a digit)
+#
+my $milestone = Moz::Milestone::getOfficialMilestone($MILESTONE_FILE);
+
+if (defined(@TEMPLATE_FILE)) {
+ my $TFILE;
+
+ foreach $TFILE (@TEMPLATE_FILE) {
+ my $BUILT_FILE = "$OBJDIR/$TFILE";
+ $TFILE = "$SRCDIR/$TFILE.tmpl";
+
+ if (-e $TFILE) {
+
+ Moz::Milestone::build_file($TFILE,$BUILT_FILE);
+
+ } else {
+ warn("$0: No such file $TFILE!\n");
+ }
+ }
+} else {
+ print "$milestone\n";
+}
+
+sub usage() {
+ print <<END
+`milestone.pl [--topsrcdir TOPSRCDIR] [--objdir OBJDIR] [--srcdir SRCDIR] --template [file list]` # will build file list from .tmpl files
+END
+ ;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.txt b/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.txt
new file mode 100644
index 0000000..f3b9fdf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.txt
@@ -0,0 +1,13 @@
+# Holds the current milestone.
+# Should be in the format of
+#
+# x.x.x
+# x.x.x.x
+# x.x.x+
+#
+# Referenced by milestone.pl.
+# Hopefully I'll be able to automate replacement of *all*
+# hardcoded milestones in the tree from these two files.
+#--------------------------------------------------------
+
+1.9.1b2
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/Makefile.in b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/Makefile.in
new file mode 100644
index 0000000..2e0fc2a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/Makefile.in
@@ -0,0 +1,84 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+# undefine (as best we can, thanks gmake!) so we don't need build_number
+MOZILLA_OFFICIAL =
+BUILD_OFFICIAL =
+MODULE = mkdepend
+HOST_PROGRAM = mkdepend$(BIN_SUFFIX)
+ifdef GNU_CC
+MODULE_OPTIMIZE_FLAGS = -O3
+else
+ifeq ($(OS_ARCH),SunOS)
+MODULE_OPTIMIZE_FLAGS = -fast
+endif
+endif
+
+ifeq ($(OS_ARCH),WINNT)
+ifndef GNU_CC
+MODULE_OPTIMIZE_FLAGS = -Ox
+endif
+endif
+
+HOST_CSRCS = \
+ cppsetup.c \
+ ifparser.c \
+ include.c \
+ main.c \
+ parse.c \
+ pr.c \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+HOST_CFLAGS += -DINCLUDEDIR=\"/usr/include\" -DOBJSUFFIX=\".$(OBJ_SUFFIX)\"
+
+ifdef GNU_CC
+_GCCDIR = $(shell $(CC) -print-file-name=include)
+HOST_CFLAGS += -DPREINCDIR=\"$(_GCCDIR)\"
+endif
+
+export:: $(HOST_PROGRAM)
+
+$(HOST_OBJS): def.h ifparser.h imakemdep.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/cppsetup.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/cppsetup.c
new file mode 100644
index 0000000..49a746a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/cppsetup.c
@@ -0,0 +1,233 @@
+/* $Xorg: cppsetup.c,v 1.5 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/cppsetup.c,v 3.11 2001/12/17 20:52:22 dawes Exp $ */
+
+#include "def.h"
+
+#ifdef CPP
+/*
+ * This file is strictly for the sake of cpy.y and yylex.c (if
+ * you indeed have the source for cpp).
+ */
+#define IB 1
+#define SB 2
+#define NB 4
+#define CB 8
+#define QB 16
+#define WB 32
+#define SALT '#'
+#if defined(pdp11) || defined(vax) || defined(ns16000) || defined(mc68000) || defined(ibm032)
+#define COFF 128
+#else
+#define COFF 0
+#endif
+/*
+ * These variables used by cpy.y and yylex.c
+ */
+extern char *outp, *inp, *newp, *pend;
+extern char *ptrtab;
+extern char fastab[];
+extern char slotab[];
+
+/*
+ * cppsetup
+ */
+struct filepointer *currentfile;
+struct inclist *currentinc;
+
+int
+cppsetup(char *line, struct filepointer *filep, struct inclist *inc)
+{
+ char *p, savec;
+ static boolean setupdone = FALSE;
+ boolean value;
+
+ if (!setupdone) {
+ cpp_varsetup();
+ setupdone = TRUE;
+ }
+
+ currentfile = filep;
+ currentinc = inc;
+ inp = newp = line;
+ for (p=newp; *p; p++)
+ ;
+
+ /*
+ * put a newline back on the end, and set up pend, etc.
+ */
+ *p++ = '\n';
+ savec = *p;
+ *p = '\0';
+ pend = p;
+
+ ptrtab = slotab+COFF;
+ *--inp = SALT;
+ outp=inp;
+ value = yyparse();
+ *p = savec;
+ return(value);
+}
+
+struct symtab **lookup(symbol)
+ char *symbol;
+{
+ static struct symtab *undefined;
+ struct symtab **sp;
+
+ sp = isdefined(symbol, currentinc, NULL);
+ if (sp == NULL) {
+ sp = &undefined;
+ (*sp)->s_value = NULL;
+ }
+ return (sp);
+}
+
+pperror(tag, x0,x1,x2,x3,x4)
+ int tag,x0,x1,x2,x3,x4;
+{
+ warning("\"%s\", line %d: ", currentinc->i_file, currentfile->f_line);
+ warning(x0,x1,x2,x3,x4);
+}
+
+
+yyerror(s)
+ register char *s;
+{
+ fatalerr("Fatal error: %s\n", s);
+}
+#else /* not CPP */
+
+#include "ifparser.h"
+struct _parse_data {
+ struct filepointer *filep;
+ struct inclist *inc;
+ char *filename;
+ const char *line;
+};
+
+static const char *
+my_if_errors (IfParser *ip, const char *cp, const char *expecting)
+{
+ struct _parse_data *pd = (struct _parse_data *) ip->data;
+ int lineno = pd->filep->f_line;
+ char *filename = pd->filename;
+ char prefix[300];
+ int prefixlen;
+ int i;
+
+ sprintf (prefix, "\"%s\":%d", filename, lineno);
+ prefixlen = strlen(prefix);
+ fprintf (stderr, "%s: %s", prefix, pd->line);
+ i = cp - pd->line;
+ if (i > 0 && pd->line[i-1] != '\n') {
+ putc ('\n', stderr);
+ }
+ for (i += prefixlen + 3; i > 0; i--) {
+ putc (' ', stderr);
+ }
+ fprintf (stderr, "^--- expecting %s\n", expecting);
+ return NULL;
+}
+
+
+#define MAXNAMELEN 256
+
+static struct symtab **
+lookup_variable (IfParser *ip, const char *var, int len)
+{
+ char tmpbuf[MAXNAMELEN + 1];
+ struct _parse_data *pd = (struct _parse_data *) ip->data;
+
+ if (len > MAXNAMELEN)
+ return 0;
+
+ strncpy (tmpbuf, var, len);
+ tmpbuf[len] = '\0';
+ return isdefined (tmpbuf, pd->inc, NULL);
+}
+
+
+static int
+my_eval_defined (IfParser *ip, const char *var, int len)
+{
+ if (lookup_variable (ip, var, len))
+ return 1;
+ else
+ return 0;
+}
+
+#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
+
+static long
+my_eval_variable (IfParser *ip, const char *var, int len)
+{
+ long val;
+ struct symtab **s;
+
+ s = lookup_variable (ip, var, len);
+ if (!s)
+ return 0;
+ do {
+ var = (*s)->s_value;
+ if (!isvarfirstletter(*var) || !strcmp((*s)->s_name, var))
+ break;
+ s = lookup_variable (ip, var, strlen(var));
+ } while (s);
+
+ var = ParseIfExpression(ip, var, &val);
+ if (var && *var) debug(4, ("extraneous: '%s'\n", var));
+ return val;
+}
+
+int
+cppsetup(char *filename,
+ char *line,
+ struct filepointer *filep,
+ struct inclist *inc)
+{
+ IfParser ip;
+ struct _parse_data pd;
+ long val = 0;
+
+ pd.filep = filep;
+ pd.inc = inc;
+ pd.line = line;
+ pd.filename = filename;
+ ip.funcs.handle_error = my_if_errors;
+ ip.funcs.eval_defined = my_eval_defined;
+ ip.funcs.eval_variable = my_eval_variable;
+ ip.data = (char *) &pd;
+
+ (void) ParseIfExpression (&ip, line, &val);
+ if (val)
+ return IF;
+ else
+ return IFFALSE;
+}
+#endif /* CPP */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/def.h b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/def.h
new file mode 100644
index 0000000..d6e5f89
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/def.h
@@ -0,0 +1,184 @@
+/* $Xorg: def.h,v 1.4 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/def.h,v 3.14 2003/01/17 17:09:49 tsi Exp $ */
+
+#ifndef NO_X11
+#include <X11/Xos.h>
+#include <X11/Xfuncproto.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#if 0
+#ifndef X_NOT_POSIX
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE
+#endif
+#endif
+#endif
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#define MAXDEFINES 512
+#define MAXFILES 1024
+#define MAXINCFILES 256 /* "-include" files */
+#define MAXDIRS 1024
+#define SYMTABINC 10 /* must be > 1 for define() to work right */
+#define TRUE 1
+#define FALSE 0
+
+/* the following must match the directives table in main.c */
+#define IF 0
+#define IFDEF 1
+#define IFNDEF 2
+#define ELSE 3
+#define ENDIF 4
+#define DEFINE 5
+#define UNDEF 6
+#define INCLUDE 7
+#define LINE 8
+#define PRAGMA 9
+#define ERROR 10
+#define IDENT 11
+#define SCCS 12
+#define ELIF 13
+#define EJECT 14
+#define WARNING 15
+#define INCLUDENEXT 16
+#define IFFALSE 17 /* pseudo value --- never matched */
+#define ELIFFALSE 18 /* pseudo value --- never matched */
+#define INCLUDEDOT 19 /* pseudo value --- never matched */
+#define IFGUESSFALSE 20 /* pseudo value --- never matched */
+#define ELIFGUESSFALSE 21 /* pseudo value --- never matched */
+#define INCLUDENEXTDOT 22 /* pseudo value --- never matched */
+
+#ifdef DEBUG
+extern int _debugmask;
+/*
+ * debug levels are:
+ *
+ * 0 show ifn*(def)*,endif
+ * 1 trace defined/!defined
+ * 2 show #include
+ * 3 show #include SYMBOL
+ * 4-6 unused
+ */
+#define debug(level,arg) { if (_debugmask & (1 << level)) warning arg; }
+#else
+#define debug(level,arg) /**/
+#endif /* DEBUG */
+
+typedef unsigned char boolean;
+
+struct symtab {
+ char *s_name;
+ char *s_value;
+};
+
+/* possible i_flag */
+#define DEFCHECKED (1<<0) /* whether defines have been checked */
+#define NOTIFIED (1<<1) /* whether we have revealed includes */
+#define MARKED (1<<2) /* whether it's in the makefile */
+#define SEARCHED (1<<3) /* whether we have read this */
+#define FINISHED (1<<4) /* whether we are done reading this */
+#define INCLUDED_SYM (1<<5) /* whether #include SYMBOL was found
+ Can't use i_list if TRUE */
+struct inclist {
+ char *i_incstring; /* string from #include line */
+ char *i_file; /* path name of the include file */
+ struct inclist **i_list; /* list of files it itself includes */
+ int i_listlen; /* length of i_list */
+ struct symtab **i_defs; /* symbol table for this file and its
+ children when merged */
+ int i_ndefs; /* current # defines */
+ boolean *i_merged; /* whether we have merged child
+ defines */
+ unsigned char i_flags;
+};
+
+struct filepointer {
+ char *f_name;
+ char *f_p;
+ char *f_base;
+ char *f_end;
+ long f_len;
+ long f_line;
+ long cmdinc_count;
+ char **cmdinc_list;
+ long cmdinc_line;
+};
+
+#include <stdlib.h>
+#if defined(macII) && !defined(__STDC__) /* stdlib.h fails to define these */
+char *malloc(), *realloc();
+#endif /* macII */
+
+char *copy(char *str);
+int match(char *str, char **list);
+char *base_name(char *file);
+char *getnextline(struct filepointer *fp);
+struct symtab **slookup(char *symbol, struct inclist *file);
+struct symtab **isdefined(char *symbol, struct inclist *file,
+ struct inclist **srcfile);
+struct symtab **fdefined(char *symbol, struct inclist *file,
+ struct inclist **srcfile);
+struct filepointer *getfile(char *file);
+void included_by(struct inclist *ip,
+ struct inclist *newfile);
+struct inclist *newinclude(char *newfile, char *incstring);
+void inc_clean (void);
+struct inclist *inc_path(char *file, char *include, int type);
+
+void freefile(struct filepointer *fp);
+
+void define2(char *name, char *val, struct inclist *file);
+void define(char *def, struct inclist *file);
+void undefine(char *symbol, struct inclist *file);
+int find_includes(struct filepointer *filep,
+ struct inclist *file,
+ struct inclist *file_red,
+ int recursion, boolean failOK);
+
+void recursive_pr_include(struct inclist *head,
+ char *file, char *base);
+void add_include(struct filepointer *filep,
+ struct inclist *file,
+ struct inclist *file_red,
+ char *include, int type,
+ boolean failOK);
+
+int cppsetup(char *filename,
+ char *line,
+ struct filepointer *filep,
+ struct inclist *inc);
+
+
+extern void fatalerr(char *, ...);
+extern void warning(char *, ...);
+extern void warning1(char *, ...);
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.c
new file mode 100644
index 0000000..d8d9e76
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.c
@@ -0,0 +1,549 @@
+/*
+ * $Xorg: ifparser.c,v 1.3 2000/08/17 19:41:50 cpqbld Exp $
+ *
+ * Copyright 1992 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Network Computing Devices may not be
+ * used in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Network Computing Devices makes
+ * no representations about the suitability of this software for any purpose.
+ * It is provided ``as is'' without express or implied warranty.
+ *
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Jim Fulton
+ * Network Computing Devices, Inc.
+ *
+ * Simple if statement processor
+ *
+ * This module can be used to evaluate string representations of C language
+ * if constructs. It accepts the following grammar:
+ *
+ * EXPRESSION := VALUE
+ * | VALUE BINOP EXPRESSION
+ * | VALUE '?' EXPRESSION ':' EXPRESSION
+ *
+ * VALUE := '(' EXPRESSION ')'
+ * | '!' VALUE
+ * | '-' VALUE
+ * | '+' VALUE
+ * | '~' VALUE
+ * | 'defined' '(' variable ')'
+ * | 'defined' variable
+ * | # variable '(' variable-list ')'
+ * | variable
+ * | number
+ *
+ * BINOP := '*' | '/' | '%'
+ * | '+' | '-'
+ * | '<<' | '>>'
+ * | '<' | '>' | '<=' | '>='
+ * | '==' | '!='
+ * | '&' | '^' | '|'
+ * | '&&' | '||'
+ *
+ * The normal C order of precedence is supported.
+ *
+ *
+ * External Entry Points:
+ *
+ * ParseIfExpression parse a string for #if
+ */
+/* $XFree86: xc/config/makedepend/ifparser.c,v 3.11 2002/09/23 01:48:08 tsi Exp $ */
+
+#include "ifparser.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+/****************************************************************************
+ Internal Macros and Utilities for Parser
+ ****************************************************************************/
+
+#define DO(val) if (!(val)) return NULL
+#define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
+#define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
+#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
+
+
+static const char *
+parse_variable (IfParser *g, const char *cp, const char **varp)
+{
+ SKIPSPACE (cp);
+
+ if (!isvarfirstletter (*cp))
+ return CALLFUNC(g, handle_error) (g, cp, "variable name");
+
+ *varp = cp;
+ /* EMPTY */
+ for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
+ return cp;
+}
+
+
+static const char *
+parse_number (IfParser *g, const char *cp, long *valp)
+{
+ long base = 10;
+ SKIPSPACE (cp);
+
+ if (!isdigit(*cp))
+ return CALLFUNC(g, handle_error) (g, cp, "number");
+
+ *valp = 0;
+
+ if (*cp == '0') {
+ cp++;
+ if ((*cp == 'x') || (*cp == 'X')) {
+ base = 16;
+ cp++;
+ } else {
+ base = 8;
+ }
+ }
+
+ /* Ignore overflows and assume ASCII, what source is usually written in */
+ while (1) {
+ int increment = -1;
+ if (base == 8) {
+ if ((*cp >= '0') && (*cp <= '7'))
+ increment = *cp++ - '0';
+ } else if (base == 16) {
+ if ((*cp >= '0') && (*cp <= '9'))
+ increment = *cp++ - '0';
+ else if ((*cp >= 'A') && (*cp <= 'F'))
+ increment = *cp++ - ('A' - 10);
+ else if ((*cp >= 'a') && (*cp <= 'f'))
+ increment = *cp++ - ('a' - 10);
+ } else { /* Decimal */
+ if ((*cp >= '0') && (*cp <= '9'))
+ increment = *cp++ - '0';
+ }
+ if (increment < 0)
+ break;
+ *valp = (*valp * base) + increment;
+ }
+
+ /* Skip trailing qualifiers */
+ while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
+ return cp;
+}
+
+static const char *
+parse_character (IfParser *g, const char *cp, long *valp)
+{
+ char val;
+
+ SKIPSPACE (cp);
+ if (*cp == '\\')
+ switch (cp[1]) {
+ case 'n': val = '\n'; break;
+ case 't': val = '\t'; break;
+ case 'v': val = '\v'; break;
+ case 'b': val = '\b'; break;
+ case 'r': val = '\r'; break;
+ case 'f': val = '\f'; break;
+ case 'a': val = '\a'; break;
+ case '\\': val = '\\'; break;
+ case '?': val = '\?'; break;
+ case '\'': val = '\''; break;
+ case '\"': val = '\"'; break;
+ case 'x': val = (char) strtol (cp + 2, NULL, 16); break;
+ default: val = (char) strtol (cp + 1, NULL, 8); break;
+ }
+ else
+ val = *cp;
+ while (*cp != '\'') cp++;
+ *valp = (long) val;
+ return cp;
+}
+
+static const char *
+parse_value (IfParser *g, const char *cp, long *valp)
+{
+ const char *var, *varend;
+
+ *valp = 0;
+
+ SKIPSPACE (cp);
+ if (!*cp)
+ return cp;
+
+ switch (*cp) {
+ case '(':
+ DO (cp = ParseIfExpression (g, cp + 1, valp));
+ SKIPSPACE (cp);
+ if (*cp != ')')
+ return CALLFUNC(g, handle_error) (g, cp, ")");
+
+ return cp + 1; /* skip the right paren */
+
+ case '!':
+ DO (cp = parse_value (g, cp + 1, valp));
+ *valp = !(*valp);
+ return cp;
+
+ case '-':
+ DO (cp = parse_value (g, cp + 1, valp));
+ *valp = -(*valp);
+ return cp;
+
+ case '+':
+ DO (cp = parse_value (g, cp + 1, valp));
+ return cp;
+
+ case '~':
+ DO (cp = parse_value (g, cp + 1, valp));
+ *valp = ~(*valp);
+ return cp;
+
+ case '#':
+ DO (cp = parse_variable (g, cp + 1, &var));
+ SKIPSPACE (cp);
+ if (*cp != '(')
+ return CALLFUNC(g, handle_error) (g, cp, "(");
+ do {
+ DO (cp = parse_variable (g, cp + 1, &var));
+ SKIPSPACE (cp);
+ } while (*cp && *cp != ')');
+ if (*cp != ')')
+ return CALLFUNC(g, handle_error) (g, cp, ")");
+ *valp = 1; /* XXX */
+ return cp + 1;
+
+ case '\'':
+ DO (cp = parse_character (g, cp + 1, valp));
+ if (*cp != '\'')
+ return CALLFUNC(g, handle_error) (g, cp, "'");
+ return cp + 1;
+
+ case 'd':
+ if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
+ int paren = 0;
+ int len;
+
+ cp += 7;
+ SKIPSPACE (cp);
+ if (*cp == '(') {
+ paren = 1;
+ cp++;
+ }
+ DO (cp = parse_variable (g, cp, &var));
+ len = cp - var;
+ SKIPSPACE (cp);
+ if (paren && *cp != ')')
+ return CALLFUNC(g, handle_error) (g, cp, ")");
+ *valp = (*(g->funcs.eval_defined)) (g, var, len);
+ return cp + paren; /* skip the right paren */
+ }
+ /* fall out */
+ }
+
+ if (isdigit(*cp)) {
+ DO (cp = parse_number (g, cp, valp));
+ } else if (!isvarfirstletter(*cp))
+ return CALLFUNC(g, handle_error) (g, cp, "variable or number");
+ else {
+ DO (cp = parse_variable (g, cp, &var));
+ varend = cp;
+ SKIPSPACE(cp);
+ if (*cp != '(') {
+ *valp = (*(g->funcs.eval_variable)) (g, var, varend - var);
+ } else {
+ do {
+ long dummy;
+ DO (cp = ParseIfExpression (g, cp + 1, &dummy));
+ SKIPSPACE(cp);
+ if (*cp == ')')
+ break;
+ if (*cp != ',')
+ return CALLFUNC(g, handle_error) (g, cp, ",");
+ } while (1);
+
+ *valp = 1; /* XXX */
+ cp++;
+ }
+ }
+
+ return cp;
+}
+
+
+
+static const char *
+parse_product (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_value (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '*':
+ DO (cp = parse_product (g, cp + 1, &rightval));
+ *valp = (*valp * rightval);
+ break;
+
+ case '/':
+ DO (cp = parse_product (g, cp + 1, &rightval));
+ *valp = (*valp / rightval);
+ break;
+
+ case '%':
+ DO (cp = parse_product (g, cp + 1, &rightval));
+ *valp = (*valp % rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_sum (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_product (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '+':
+ DO (cp = parse_sum (g, cp + 1, &rightval));
+ *valp = (*valp + rightval);
+ break;
+
+ case '-':
+ DO (cp = parse_sum (g, cp + 1, &rightval));
+ *valp = (*valp - rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_shift (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_sum (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '<':
+ if (cp[1] == '<') {
+ DO (cp = parse_shift (g, cp + 2, &rightval));
+ *valp = (*valp << rightval);
+ }
+ break;
+
+ case '>':
+ if (cp[1] == '>') {
+ DO (cp = parse_shift (g, cp + 2, &rightval));
+ *valp = (*valp >> rightval);
+ }
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_inequality (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_shift (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '<':
+ if (cp[1] == '=') {
+ DO (cp = parse_inequality (g, cp + 2, &rightval));
+ *valp = (*valp <= rightval);
+ } else {
+ DO (cp = parse_inequality (g, cp + 1, &rightval));
+ *valp = (*valp < rightval);
+ }
+ break;
+
+ case '>':
+ if (cp[1] == '=') {
+ DO (cp = parse_inequality (g, cp + 2, &rightval));
+ *valp = (*valp >= rightval);
+ } else {
+ DO (cp = parse_inequality (g, cp + 1, &rightval));
+ *valp = (*valp > rightval);
+ }
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_equality (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_inequality (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '=':
+ if (cp[1] == '=')
+ cp++;
+ DO (cp = parse_equality (g, cp + 1, &rightval));
+ *valp = (*valp == rightval);
+ break;
+
+ case '!':
+ if (cp[1] != '=')
+ break;
+ DO (cp = parse_equality (g, cp + 2, &rightval));
+ *valp = (*valp != rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_band (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_equality (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '&':
+ if (cp[1] != '&') {
+ DO (cp = parse_band (g, cp + 1, &rightval));
+ *valp = (*valp & rightval);
+ }
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_bxor (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_band (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '^':
+ DO (cp = parse_bxor (g, cp + 1, &rightval));
+ *valp = (*valp ^ rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_bor (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_bxor (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '|':
+ if (cp[1] != '|') {
+ DO (cp = parse_bor (g, cp + 1, &rightval));
+ *valp = (*valp | rightval);
+ }
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_land (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_bor (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '&':
+ if (cp[1] != '&')
+ return CALLFUNC(g, handle_error) (g, cp, "&&");
+ DO (cp = parse_land (g, cp + 2, &rightval));
+ *valp = (*valp && rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_lor (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_land (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '|':
+ if (cp[1] != '|')
+ return CALLFUNC(g, handle_error) (g, cp, "||");
+ DO (cp = parse_lor (g, cp + 2, &rightval));
+ *valp = (*valp || rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_cond(IfParser *g, const char *cp, long *valp)
+{
+ long trueval, falseval;
+
+ DO (cp = parse_lor (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '?':
+ DO (cp = parse_cond (g, cp + 1, &trueval));
+ SKIPSPACE (cp);
+ if (*cp != ':')
+ return CALLFUNC(g, handle_error) (g, cp, ":");
+ DO (cp = parse_cond (g, cp + 1, &falseval));
+ *valp = (*valp ? trueval : falseval);
+ break;
+ }
+ return cp;
+}
+
+
+/****************************************************************************
+ External Entry Points
+ ****************************************************************************/
+
+const char *
+ParseIfExpression (IfParser *g, const char *cp, long *valp)
+{
+ return parse_cond (g, cp, valp);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.h b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.h
new file mode 100644
index 0000000..89d2a2f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.h
@@ -0,0 +1,83 @@
+/*
+ * $Xorg: ifparser.h,v 1.3 2000/08/17 19:41:51 cpqbld Exp $
+ *
+ * Copyright 1992 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Network Computing Devices may not be
+ * used in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Network Computing Devices makes
+ * no representations about the suitability of this software for any purpose.
+ * It is provided ``as is'' without express or implied warranty.
+ *
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Jim Fulton
+ * Network Computing Devices, Inc.
+ *
+ * Simple if statement processor
+ *
+ * This module can be used to evaluate string representations of C language
+ * if constructs. It accepts the following grammar:
+ *
+ * EXPRESSION := VALUE
+ * | VALUE BINOP EXPRESSION
+ * | VALUE '?' EXPRESSION ':' EXPRESSION
+ *
+ * VALUE := '(' EXPRESSION ')'
+ * | '!' VALUE
+ * | '-' VALUE
+ * | '~' VALUE
+ * | 'defined' '(' variable ')'
+ * | variable
+ * | number
+ *
+ * BINOP := '*' | '/' | '%'
+ * | '+' | '-'
+ * | '<<' | '>>'
+ * | '<' | '>' | '<=' | '>='
+ * | '==' | '!='
+ * | '&' | '^' | '|'
+ * | '&&' | '||'
+ *
+ * The normal C order of precedence is supported.
+ *
+ *
+ * External Entry Points:
+ *
+ * ParseIfExpression parse a string for #if
+ */
+
+/* $XFree86: xc/config/makedepend/ifparser.h,v 3.5 2001/07/25 15:04:40 dawes Exp $ */
+
+#include <stdio.h>
+
+typedef int Bool;
+#define False 0
+#define True 1
+
+typedef struct _if_parser {
+ struct { /* functions */
+ const char *(*handle_error) (struct _if_parser *, const char *,
+ const char *);
+ long (*eval_variable) (struct _if_parser *, const char *, int);
+ int (*eval_defined) (struct _if_parser *, const char *, int);
+ } funcs;
+ char *data;
+} IfParser;
+
+const char *ParseIfExpression (
+ IfParser *,
+ const char *,
+ long *
+);
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/imakemdep.h b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/imakemdep.h
new file mode 100644
index 0000000..5c58351
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/imakemdep.h
@@ -0,0 +1,733 @@
+
+/* $XConsortium: imakemdep.h,v 1.83 95/04/07 19:47:46 kaleb Exp $ */
+/* $XFree86: xc/config/imake/imakemdep.h,v 3.12 1995/07/08 10:22:17 dawes Exp $ */
+/*
+
+Copyright (c) 1993, 1994 X Consortium
+
+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
+X CONSORTIUM 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.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+
+/*
+ * This file contains machine-dependent constants for the imake utility.
+ * When porting imake, read each of the steps below and add in any necessary
+ * definitions. In general you should *not* edit ccimake.c or imake.c!
+ */
+
+#ifdef CCIMAKE
+/*
+ * Step 1: imake_ccflags
+ * Define any special flags that will be needed to get imake.c to compile.
+ * These will be passed to the compile along with the contents of the
+ * make variable BOOTSTRAPCFLAGS.
+ */
+#ifdef hpux
+#ifdef hp9000s800
+#define imake_ccflags "-DSYSV"
+#else
+#define imake_ccflags "-Wc,-Nd4000,-Ns3000 -DSYSV"
+#endif
+#endif
+
+#if defined(macII) || defined(_AUX_SOURCE)
+#define imake_ccflags "-DmacII -DSYSV"
+#endif
+
+#ifdef stellar
+#define imake_ccflags "-DSYSV"
+#endif
+
+#if defined(USL) || defined(Oki) || defined(NCR)
+#define imake_ccflags "-Xc -DSVR4"
+#endif
+
+#ifdef sony
+#if defined(SYSTYPE_SYSV) || defined(_SYSTYPE_SYSV)
+#define imake_ccflags "-DSVR4"
+#else
+#include <sys/param.h>
+#if NEWSOS < 41
+#define imake_ccflags "-Dbsd43 -DNOSTDHDRS"
+#else
+#if NEWSOS < 42
+#define imake_ccflags "-Dbsd43"
+#endif
+#endif
+#endif
+#endif
+
+#ifdef _CRAY
+#define imake_ccflags "-DSYSV -DUSG"
+#endif
+
+#if defined(_IBMR2) || defined(aix)
+#define imake_ccflags "-Daix -DSYSV"
+#endif
+
+#ifdef Mips
+# if defined(SYSTYPE_BSD) || defined(BSD) || defined(BSD43)
+# define imake_ccflags "-DBSD43"
+# else
+# define imake_ccflags "-DSYSV"
+# endif
+#endif
+
+#ifdef is68k
+#define imake_ccflags "-Dluna -Duniosb"
+#endif
+
+#ifdef SYSV386
+# ifdef SVR4
+# define imake_ccflags "-Xc -DSVR4"
+# else
+# define imake_ccflags "-DSYSV"
+# endif
+#endif
+
+#ifdef SVR4
+# ifdef i386
+# define imake_ccflags "-Xc -DSVR4"
+# endif
+#endif
+
+#ifdef SYSV
+# ifdef i386
+# define imake_ccflags "-DSYSV"
+# endif
+#endif
+
+#ifdef __convex__
+#define imake_ccflags "-fn -tm c1"
+#endif
+
+#ifdef apollo
+#define imake_ccflags "-DX_NOT_POSIX"
+#endif
+
+#ifdef WIN32
+#define imake_ccflags "-nologo -batch -D__STDC__"
+#endif
+
+#ifdef __uxp__
+#define imake_ccflags "-DSVR4 -DANSICPP"
+#endif
+
+#ifdef __sxg__
+#define imake_ccflags "-DSYSV -DUSG -DNOSTDHDRS"
+#endif
+
+#ifdef sequent
+#define imake_ccflags "-DX_NOT_STDC_ENV -DX_NOT_POSIX"
+#endif
+
+#ifdef _SEQUENT_
+#define imake_ccflags "-DSYSV -DUSG"
+#endif
+
+#if defined(SX) || defined(PC_UX)
+#define imake_ccflags "-DSYSV"
+#endif
+
+#ifdef nec_ews_svr2
+#define imake_ccflags "-DUSG"
+#endif
+
+#if defined(nec_ews_svr4) || defined(_nec_ews_svr4) || defined(_nec_up) || defined(_nec_ft)
+#define imake_ccflags "-DSVR4"
+#endif
+
+#ifdef MACH
+#define imake_ccflags "-DNOSTDHDRS"
+#endif
+
+/* this is for OS/2 under EMX. This won't work with DOS */
+#if defined(__EMX__)
+#define imake_ccflags "-DBSD43"
+#endif
+
+#else /* not CCIMAKE */
+#ifndef MAKEDEPEND
+/*
+ * Step 2: dup2
+ * If your OS doesn't have a dup2() system call to duplicate one file
+ * descriptor onto another, define such a mechanism here (if you don't
+ * already fall under the existing category(ies).
+ */
+#if defined(SYSV) && !defined(_CRAY) && !defined(Mips) && !defined(_SEQUENT_)
+#define dup2(fd1,fd2) ((fd1 == fd2) ? fd1 : (close(fd2), \
+ fcntl(fd1, F_DUPFD, fd2)))
+#endif
+
+
+/*
+ * Step 3: FIXUP_CPP_WHITESPACE
+ * If your cpp collapses tabs macro expansions into a single space and
+ * replaces escaped newlines with a space, define this symbol. This will
+ * cause imake to attempt to patch up the generated Makefile by looking
+ * for lines that have colons in them (this is why the rules file escapes
+ * all colons). One way to tell if you need this is to see whether or not
+ * your Makefiles have no tabs in them and lots of @@ strings.
+ */
+#if defined(sun) || defined(SYSV) || defined(SVR4) || defined(hcx) || defined(WIN32) || (defined(AMOEBA) && defined(CROSS_COMPILE))
+#define FIXUP_CPP_WHITESPACE
+#endif
+#ifdef WIN32
+#define REMOVE_CPP_LEADSPACE
+#define INLINE_SYNTAX
+#define MAGIC_MAKE_VARS
+#endif
+#ifdef __minix_vmd
+#define FIXUP_CPP_WHITESPACE
+#endif
+
+/*
+ * Step 4: USE_CC_E, DEFAULT_CC, DEFAULT_CPP
+ * If you want to use cc -E instead of cpp, define USE_CC_E.
+ * If use cc -E but want a different compiler, define DEFAULT_CC.
+ * If the cpp you need is not in /lib/cpp, define DEFAULT_CPP.
+ */
+#ifdef hpux
+#define USE_CC_E
+#endif
+#ifdef WIN32
+#define USE_CC_E
+#define DEFAULT_CC "cl"
+#endif
+#ifdef apollo
+#define DEFAULT_CPP "/usr/lib/cpp"
+#endif
+#if defined(_IBMR2) && !defined(DEFAULT_CPP)
+#define DEFAULT_CPP "/usr/lpp/X11/Xamples/util/cpp/cpp"
+#endif
+#if defined(sun) && defined(SVR4)
+#define DEFAULT_CPP "/usr/ccs/lib/cpp"
+#endif
+#ifdef __bsdi__
+#define DEFAULT_CPP "/usr/bin/cpp"
+#endif
+#ifdef __uxp__
+#define DEFAULT_CPP "/usr/ccs/lib/cpp"
+#endif
+#ifdef __sxg__
+#define DEFAULT_CPP "/usr/lib/cpp"
+#endif
+#ifdef _CRAY
+#define DEFAULT_CPP "/lib/pcpp"
+#endif
+#if defined(__386BSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+#define DEFAULT_CPP "/usr/libexec/cpp"
+#endif
+#ifdef MACH
+#define USE_CC_E
+#endif
+#ifdef __minix_vmd
+#define DEFAULT_CPP "/usr/lib/cpp"
+#endif
+#if defined(__EMX__)
+/* expects cpp in PATH */
+#define DEFAULT_CPP "cpp"
+#endif
+
+/*
+ * Step 5: cpp_argv
+ * The following table contains the flags that should be passed
+ * whenever a Makefile is being generated. If your preprocessor
+ * doesn't predefine any unique symbols, choose one and add it to the
+ * end of this table. Then, do the following:
+ *
+ * a. Use this symbol in Imake.tmpl when setting MacroFile.
+ * b. Put this symbol in the definition of BootstrapCFlags in your
+ * <platform>.cf file.
+ * c. When doing a make World, always add "BOOTSTRAPCFLAGS=-Dsymbol"
+ * to the end of the command line.
+ *
+ * Note that you may define more than one symbol (useful for platforms
+ * that support multiple operating systems).
+ */
+
+#define ARGUMENTS 50 /* number of arguments in various arrays */
+char *cpp_argv[ARGUMENTS] = {
+ "cc", /* replaced by the actual program to exec */
+ "-I.", /* add current directory to include path */
+#ifdef unix
+ "-Uunix", /* remove unix symbol so that filename unix.c okay */
+#endif
+#if defined(__386BSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(MACH)
+# ifdef __i386__
+ "-D__i386__",
+# endif
+# ifdef __x86_64__
+ "-D__x86_64__",
+# endif
+# ifdef __GNUC__
+ "-traditional",
+# endif
+#endif
+#ifdef M4330
+ "-DM4330", /* Tektronix */
+#endif
+#ifdef M4310
+ "-DM4310", /* Tektronix */
+#endif
+#if defined(macII) || defined(_AUX_SOURCE)
+ "-DmacII", /* Apple A/UX */
+#endif
+#ifdef USL
+ "-DUSL", /* USL */
+#endif
+#ifdef sony
+ "-Dsony", /* Sony */
+#if !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV) && NEWSOS < 42
+ "-Dbsd43",
+#endif
+#endif
+#ifdef _IBMR2
+ "-D_IBMR2", /* IBM RS-6000 (we ensured that aix is defined above */
+#ifndef aix
+#define aix /* allow BOOTSTRAPCFLAGS="-D_IBMR2" */
+#endif
+#endif /* _IBMR2 */
+#ifdef aix
+ "-Daix", /* AIX instead of AOS */
+#ifndef ibm
+#define ibm /* allow BOOTSTRAPCFLAGS="-Daix" */
+#endif
+#endif /* aix */
+#ifdef ibm
+ "-Dibm", /* IBM PS/2 and RT under both AOS and AIX */
+#endif
+#ifdef luna
+ "-Dluna", /* OMRON luna 68K and 88K */
+#ifdef luna1
+ "-Dluna1",
+#endif
+#ifdef luna88k /* need not on UniOS-Mach Vers. 1.13 */
+ "-traditional", /* for some older version */
+#endif /* instead of "-DXCOMM=\\#" */
+#ifdef uniosb
+ "-Duniosb",
+#endif
+#ifdef uniosu
+ "-Duniosu",
+#endif
+#endif /* luna */
+#ifdef _CRAY /* Cray */
+ "-Ucray",
+#endif
+#ifdef Mips
+ "-DMips", /* Define and use Mips for Mips Co. OS/mach. */
+# if defined(SYSTYPE_BSD) || defined(BSD) || defined(BSD43)
+ "-DBSD43", /* Mips RISCOS supports two environments */
+# else
+ "-DSYSV", /* System V environment is the default */
+# endif
+#endif /* Mips */
+#ifdef MOTOROLA
+ "-DMOTOROLA", /* Motorola Delta Systems */
+# ifdef SYSV
+ "-DSYSV",
+# endif
+# ifdef SVR4
+ "-DSVR4",
+# endif
+#endif /* MOTOROLA */
+#ifdef i386
+ "-Di386",
+# ifdef SVR4
+ "-DSVR4",
+# endif
+# ifdef SYSV
+ "-DSYSV",
+# ifdef ISC
+ "-DISC",
+# ifdef ISC40
+ "-DISC40", /* ISC 4.0 */
+# else
+# ifdef ISC202
+ "-DISC202", /* ISC 2.0.2 */
+# else
+# ifdef ISC30
+ "-DISC30", /* ISC 3.0 */
+# else
+ "-DISC22", /* ISC 2.2.1 */
+# endif
+# endif
+# endif
+# endif
+# ifdef SCO
+ "-DSCO",
+# ifdef SCO324
+ "-DSCO324",
+# endif
+# endif
+# endif
+# ifdef ESIX
+ "-DESIX",
+# endif
+# ifdef ATT
+ "-DATT",
+# endif
+# ifdef DELL
+ "-DDELL",
+# endif
+#endif
+#ifdef SYSV386 /* System V/386 folks, obsolete */
+ "-Di386",
+# ifdef SVR4
+ "-DSVR4",
+# endif
+# ifdef ISC
+ "-DISC",
+# ifdef ISC40
+ "-DISC40", /* ISC 4.0 */
+# else
+# ifdef ISC202
+ "-DISC202", /* ISC 2.0.2 */
+# else
+# ifdef ISC30
+ "-DISC30", /* ISC 3.0 */
+# else
+ "-DISC22", /* ISC 2.2.1 */
+# endif
+# endif
+# endif
+# endif
+# ifdef SCO
+ "-DSCO",
+# ifdef SCO324
+ "-DSCO324",
+# endif
+# endif
+# ifdef ESIX
+ "-DESIX",
+# endif
+# ifdef ATT
+ "-DATT",
+# endif
+# ifdef DELL
+ "-DDELL",
+# endif
+#endif
+#ifdef __osf__
+ "-D__osf__",
+# ifdef __mips__
+ "-D__mips__",
+# endif
+# ifdef __alpha
+ "-D__alpha",
+# endif
+# ifdef __i386__
+ "-D__i386__",
+# endif
+# ifdef __GNUC__
+ "-traditional",
+# endif
+#endif
+#ifdef Oki
+ "-DOki",
+#endif
+#ifdef sun
+#ifdef SVR4
+ "-DSVR4",
+#endif
+#endif
+#ifdef WIN32
+ "-DWIN32",
+ "-nologo",
+ "-batch",
+ "-D__STDC__",
+#endif
+#ifdef NCR
+ "-DNCR", /* NCR */
+#endif
+#ifdef linux
+ "-traditional",
+ "-Dlinux",
+#endif
+#ifdef __uxp__
+ "-D__uxp__",
+#endif
+#ifdef __sxg__
+ "-D__sxg__",
+#endif
+#ifdef nec_ews_svr2
+ "-Dnec_ews_svr2",
+#endif
+#ifdef AMOEBA
+ "-DAMOEBA",
+# ifdef CROSS_COMPILE
+ "-DCROSS_COMPILE",
+# ifdef CROSS_i80386
+ "-Di80386",
+# endif
+# ifdef CROSS_sparc
+ "-Dsparc",
+# endif
+# ifdef CROSS_mc68000
+ "-Dmc68000",
+# endif
+# else
+# ifdef i80386
+ "-Di80386",
+# endif
+# ifdef sparc
+ "-Dsparc",
+# endif
+# ifdef mc68000
+ "-Dmc68000",
+# endif
+# endif
+#endif
+#ifdef __minix_vmd
+ "-Dminix",
+#endif
+
+#if defined(__EMX__)
+ "-traditional",
+ "-Demxos2",
+#endif
+
+};
+#else /* else MAKEDEPEND */
+/*
+ * Step 6: predefs
+ * If your compiler and/or preprocessor define any specific symbols, add
+ * them to the the following table. The definition of struct symtab is
+ * in util/makedepend/def.h.
+ */
+struct symtab predefs[] = {
+#ifdef apollo
+ {"apollo", "1"},
+#endif
+#ifdef ibm032
+ {"ibm032", "1"},
+#endif
+#ifdef ibm
+ {"ibm", "1"},
+#endif
+#ifdef aix
+ {"aix", "1"},
+#endif
+#ifdef sun
+ {"sun", "1"},
+#endif
+#ifdef sun2
+ {"sun2", "1"},
+#endif
+#ifdef sun3
+ {"sun3", "1"},
+#endif
+#ifdef sun4
+ {"sun4", "1"},
+#endif
+#ifdef sparc
+ {"sparc", "1"},
+#endif
+#ifdef __sparc__
+ {"__sparc__", "1"},
+#endif
+#ifdef hpux
+ {"hpux", "1"},
+#endif
+#ifdef __hpux
+ {"__hpux", "1"},
+#endif
+#ifdef __hp9000s800
+ {"__hp9000s800", "1"},
+#endif
+#ifdef __hp9000s700
+ {"__hp9000s700", "1"},
+#endif
+#ifdef vax
+ {"vax", "1"},
+#endif
+#ifdef VMS
+ {"VMS", "1"},
+#endif
+#ifdef cray
+ {"cray", "1"},
+#endif
+#ifdef CRAY
+ {"CRAY", "1"},
+#endif
+#ifdef _CRAY
+ {"_CRAY", "1"},
+#endif
+#ifdef att
+ {"att", "1"},
+#endif
+#ifdef mips
+ {"mips", "1"},
+#endif
+#ifdef __mips__
+ {"__mips__", "1"},
+#endif
+#ifdef ultrix
+ {"ultrix", "1"},
+#endif
+#ifdef stellar
+ {"stellar", "1"},
+#endif
+#ifdef mc68000
+ {"mc68000", "1"},
+#endif
+#ifdef mc68020
+ {"mc68020", "1"},
+#endif
+#ifdef __GNUC__
+ {"__GNUC__", "1"},
+#endif
+#if __STDC__
+ {"__STDC__", "1"},
+#endif
+#ifdef __HIGHC__
+ {"__HIGHC__", "1"},
+#endif
+#ifdef CMU
+ {"CMU", "1"},
+#endif
+#ifdef luna
+ {"luna", "1"},
+#ifdef luna1
+ {"luna1", "1"},
+#endif
+#ifdef luna2
+ {"luna2", "1"},
+#endif
+#ifdef luna88k
+ {"luna88k", "1"},
+#endif
+#ifdef uniosb
+ {"uniosb", "1"},
+#endif
+#ifdef uniosu
+ {"uniosu", "1"},
+#endif
+#endif
+#ifdef ieeep754
+ {"ieeep754", "1"},
+#endif
+#ifdef is68k
+ {"is68k", "1"},
+#endif
+#ifdef m68k
+ {"m68k", "1"},
+#endif
+#ifdef m88k
+ {"m88k", "1"},
+#endif
+#ifdef __m88k__
+ {"__m88k__", "1"},
+#endif
+#ifdef bsd43
+ {"bsd43", "1"},
+#endif
+#ifdef hcx
+ {"hcx", "1"},
+#endif
+#ifdef sony
+ {"sony", "1"},
+#ifdef SYSTYPE_SYSV
+ {"SYSTYPE_SYSV", "1"},
+#endif
+#ifdef _SYSTYPE_SYSV
+ {"_SYSTYPE_SYSV", "1"},
+#endif
+#endif
+#ifdef __OSF__
+ {"__OSF__", "1"},
+#endif
+#ifdef __osf__
+ {"__osf__", "1"},
+#endif
+#ifdef __alpha
+ {"__alpha", "1"},
+#endif
+#ifdef __DECC
+ {"__DECC", "1"},
+#endif
+#ifdef __decc
+ {"__decc", "1"},
+#endif
+#ifdef __uxp__
+ {"__uxp__", "1"},
+#endif
+#ifdef __sxg__
+ {"__sxg__", "1"},
+#endif
+#ifdef _SEQUENT_
+ {"_SEQUENT_", "1"},
+ {"__STDC__", "1"},
+#endif
+#ifdef __bsdi__
+ {"__bsdi__", "1"},
+#endif
+#ifdef nec_ews_svr2
+ {"nec_ews_svr2", "1"},
+#endif
+#ifdef nec_ews_svr4
+ {"nec_ews_svr4", "1"},
+#endif
+#ifdef _nec_ews_svr4
+ {"_nec_ews_svr4", "1"},
+#endif
+#ifdef _nec_up
+ {"_nec_up", "1"},
+#endif
+#ifdef SX
+ {"SX", "1"},
+#endif
+#ifdef nec
+ {"nec", "1"},
+#endif
+#ifdef _nec_ft
+ {"_nec_ft", "1"},
+#endif
+#ifdef PC_UX
+ {"PC_UX", "1"},
+#endif
+#ifdef sgi
+ {"sgi", "1"},
+#endif
+#ifdef __sgi
+ {"__sgi", "1"},
+#endif
+#ifdef __FreeBSD__
+ {"__FreeBSD__", "1"},
+#endif
+#ifdef __NetBSD__
+ {"__NetBSD__", "1"},
+#endif
+#ifdef __OpenBSD__
+ {"__OpenBSD__", "1"},
+#endif
+#ifdef __EMX__
+ {"__EMX__", "1"},
+#endif
+ /* add any additional symbols before this line */
+ {NULL, NULL}
+};
+
+#endif /* MAKEDEPEND */
+#endif /* CCIMAKE */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/include.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/include.c
new file mode 100644
index 0000000..3b89f26
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/include.c
@@ -0,0 +1,337 @@
+/* $Xorg: include.c,v 1.4 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/include.c,v 3.7 2001/12/14 19:53:20 dawes Exp $ */
+
+
+#include "def.h"
+
+#ifdef _MSC_VER
+#include <windows.h>
+static int
+does_file_exist(char *file)
+{
+ WIN32_FILE_ATTRIBUTE_DATA data;
+ BOOL b = GetFileAttributesExA(file, GetFileExInfoStandard, &data);
+ if (!b)
+ return 0;
+ return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
+}
+#else
+static int
+does_file_exist(char *file)
+{
+ struct stat sb;
+ return stat(file, &sb) == 0 && !S_ISDIR(sb.st_mode);
+}
+#endif
+
+extern struct inclist inclist[ MAXFILES ],
+ *inclistp, *inclistnext;
+extern char *includedirs[ ],
+ **includedirsnext;
+extern char *notdotdot[ ];
+extern boolean show_where_not;
+extern boolean warn_multiple;
+
+static boolean
+isdot(char *p)
+{
+ if(p && *p++ == '.' && *p++ == '\0')
+ return(TRUE);
+ return(FALSE);
+}
+
+static boolean
+isdotdot(char *p)
+{
+ if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0')
+ return(TRUE);
+ return(FALSE);
+}
+
+static boolean
+issymbolic(char *dir, char *component)
+{
+#ifdef S_IFLNK
+ struct stat st;
+ char buf[ BUFSIZ ], **pp;
+
+ sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component);
+ for (pp=notdotdot; *pp; pp++)
+ if (strcmp(*pp, buf) == 0)
+ return (TRUE);
+ if (lstat(buf, &st) == 0
+ && (st.st_mode & S_IFMT) == S_IFLNK) {
+ *pp++ = copy(buf);
+ if (pp >= &notdotdot[ MAXDIRS ])
+ fatalerr("out of .. dirs, increase MAXDIRS\n");
+ return(TRUE);
+ }
+#endif
+ return(FALSE);
+}
+
+/*
+ * Occasionally, pathnames are created that look like .../x/../y
+ * Any of the 'x/..' sequences within the name can be eliminated.
+ * (but only if 'x' is not a symbolic link!!)
+ */
+static void
+remove_dotdot(char *path)
+{
+ register char *end, *from, *to, **cp;
+ char *components[ MAXFILES ],
+ newpath[ BUFSIZ ];
+ boolean component_copied;
+
+ /*
+ * slice path up into components.
+ */
+ to = newpath;
+ if (*path == '/')
+ *to++ = '/';
+ *to = '\0';
+ cp = components;
+ for (from=end=path; *end; end++)
+ if (*end == '/') {
+ while (*end == '/')
+ *end++ = '\0';
+ if (*from)
+ *cp++ = from;
+ from = end;
+ }
+ *cp++ = from;
+ *cp = NULL;
+
+ /*
+ * Recursively remove all 'x/..' component pairs.
+ */
+ cp = components;
+ while(*cp) {
+ if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))
+ && !issymbolic(newpath, *cp))
+ {
+ char **fp = cp + 2;
+ char **tp = cp;
+
+ do
+ *tp++ = *fp; /* move all the pointers down */
+ while (*fp++);
+ if (cp != components)
+ cp--; /* go back and check for nested ".." */
+ } else {
+ cp++;
+ }
+ }
+ /*
+ * Concatenate the remaining path elements.
+ */
+ cp = components;
+ component_copied = FALSE;
+ while(*cp) {
+ if (component_copied)
+ *to++ = '/';
+ component_copied = TRUE;
+ for (from = *cp; *from; )
+ *to++ = *from++;
+ *to = '\0';
+ cp++;
+ }
+ *to++ = '\0';
+
+ /*
+ * copy the reconstituted path back to our pointer.
+ */
+ strcpy(path, newpath);
+}
+
+/*
+ * Add an include file to the list of those included by 'file'.
+ */
+struct inclist *
+newinclude(char *newfile, char *incstring)
+{
+ register struct inclist *ip;
+
+ /*
+ * First, put this file on the global list of include files.
+ */
+ ip = inclistp++;
+ if (inclistp == inclist + MAXFILES - 1)
+ fatalerr("out of space: increase MAXFILES\n");
+ ip->i_file = copy(newfile);
+
+ if (incstring == NULL)
+ ip->i_incstring = ip->i_file;
+ else
+ ip->i_incstring = copy(incstring);
+
+ inclistnext = inclistp;
+ return(ip);
+}
+
+void
+included_by(struct inclist *ip, struct inclist *newfile)
+{
+ register int i;
+
+ if (ip == NULL)
+ return;
+ /*
+ * Put this include file (newfile) on the list of files included
+ * by 'file'. If 'file' is NULL, then it is not an include
+ * file itself (i.e. was probably mentioned on the command line).
+ * If it is already on the list, don't stick it on again.
+ */
+ if (ip->i_list == NULL) {
+ ip->i_list = (struct inclist **)
+ malloc(sizeof(struct inclist *) * ++ip->i_listlen);
+ ip->i_merged = (boolean *)
+ malloc(sizeof(boolean) * ip->i_listlen);
+ } else {
+ for (i=0; i<ip->i_listlen; i++)
+ if (ip->i_list[ i ] == newfile) {
+ i = strlen(newfile->i_file);
+ if (!(ip->i_flags & INCLUDED_SYM) &&
+ !(i > 2 &&
+ newfile->i_file[i-1] == 'c' &&
+ newfile->i_file[i-2] == '.'))
+ {
+ /* only bitch if ip has */
+ /* no #include SYMBOL lines */
+ /* and is not a .c file */
+ if (warn_multiple)
+ {
+ warning("%s includes %s more than once!\n",
+ ip->i_file, newfile->i_file);
+ warning1("Already have\n");
+ for (i=0; i<ip->i_listlen; i++)
+ warning1("\t%s\n", ip->i_list[i]->i_file);
+ }
+ }
+ return;
+ }
+ ip->i_list = (struct inclist **) realloc(ip->i_list,
+ sizeof(struct inclist *) * ++ip->i_listlen);
+ ip->i_merged = (boolean *)
+ realloc(ip->i_merged, sizeof(boolean) * ip->i_listlen);
+ }
+ ip->i_list[ ip->i_listlen-1 ] = newfile;
+ ip->i_merged[ ip->i_listlen-1 ] = FALSE;
+}
+
+void
+inc_clean (void)
+{
+ register struct inclist *ip;
+
+ for (ip = inclist; ip < inclistp; ip++) {
+ ip->i_flags &= ~MARKED;
+ }
+}
+
+struct inclist *
+inc_path(char *file, char *include, int type)
+{
+ static char path[ BUFSIZ ];
+ register char **pp, *p;
+ register struct inclist *ip;
+
+ /*
+ * Check all previously found include files for a path that
+ * has already been expanded.
+ */
+ if ((type == INCLUDE) || (type == INCLUDEDOT))
+ inclistnext = inclist;
+ ip = inclistnext;
+
+ for (; ip->i_file; ip++) {
+ if ((strcmp(ip->i_incstring, include) == 0) &&
+ !(ip->i_flags & INCLUDED_SYM)) {
+ inclistnext = ip + 1;
+ return ip;
+ }
+ }
+
+ if (inclistnext == inclist) {
+ /*
+ * If the path was surrounded by "" or is an absolute path,
+ * then check the exact path provided.
+ */
+ if ((type == INCLUDEDOT) ||
+ (type == INCLUDENEXTDOT) ||
+ (*include == '/')) {
+ if (does_file_exist(include))
+ return newinclude(include, include);
+ if (show_where_not)
+ warning1("\tnot in %s\n", include);
+ }
+
+ /*
+ * If the path was surrounded by "" see if this include file is
+ * in the directory of the file being parsed.
+ */
+ if ((type == INCLUDEDOT) || (type == INCLUDENEXTDOT)) {
+ for (p=file+strlen(file); p>file; p--)
+ if (*p == '/')
+ break;
+ if (p == file) {
+ strcpy(path, include);
+ } else {
+ strncpy(path, file, (p-file) + 1);
+ path[ (p-file) + 1 ] = '\0';
+ strcpy(path + (p-file) + 1, include);
+ }
+ remove_dotdot(path);
+ if (does_file_exist(path))
+ return newinclude(path, include);
+ if (show_where_not)
+ warning1("\tnot in %s\n", path);
+ }
+ }
+
+ /*
+ * Check the include directories specified. Standard include dirs
+ * should be at the end.
+ */
+ if ((type == INCLUDE) || (type == INCLUDEDOT))
+ includedirsnext = includedirs;
+ pp = includedirsnext;
+
+ for (; *pp; pp++) {
+ sprintf(path, "%s/%s", *pp, include);
+ remove_dotdot(path);
+ if (does_file_exist(path)) {
+ includedirsnext = pp + 1;
+ return newinclude(path, include);
+ }
+ if (show_where_not)
+ warning1("\tnot in %s\n", path);
+ }
+
+ return NULL;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/main.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/main.c
new file mode 100644
index 0000000..a86866f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/main.c
@@ -0,0 +1,860 @@
+/* $Xorg: main.c,v 1.5 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+THE OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/main.c,v 3.32 2003/03/26 20:43:48 tsi Exp $ */
+
+#include "def.h"
+#ifdef hpux
+#define sigvec sigvector
+#endif /* hpux */
+
+#ifdef X_POSIX_C_SOURCE
+#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
+#include <signal.h>
+#undef _POSIX_C_SOURCE
+#else
+#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
+#include <signal.h>
+#else
+#define _POSIX_SOURCE
+#include <signal.h>
+#undef _POSIX_SOURCE
+#endif
+#endif
+
+#include <stdarg.h>
+
+#ifdef MINIX
+#define USE_CHMOD 1
+#endif
+
+#ifdef DEBUG
+int _debugmask;
+#endif
+
+/* #define DEBUG_DUMP */
+#ifdef DEBUG_DUMP
+#define DBG_PRINT(file, fmt, args) fprintf(file, fmt, args)
+#else
+#define DBG_PRINT(file, fmt, args) /* empty */
+#endif
+
+#define DASH_INC_PRE "#include \""
+#define DASH_INC_POST "\""
+
+char *ProgramName;
+
+char *directives[] = {
+ "if",
+ "ifdef",
+ "ifndef",
+ "else",
+ "endif",
+ "define",
+ "undef",
+ "include",
+ "line",
+ "pragma",
+ "error",
+ "ident",
+ "sccs",
+ "elif",
+ "eject",
+ "warning",
+ "include_next",
+ NULL
+};
+
+#define MAKEDEPEND
+#include "imakemdep.h" /* from config sources */
+#undef MAKEDEPEND
+
+struct inclist inclist[ MAXFILES ],
+ *inclistp = inclist,
+ *inclistnext = inclist,
+ maininclist;
+
+static char *filelist[ MAXFILES ];
+char *includedirs[ MAXDIRS + 1 ],
+ **includedirsnext = includedirs;
+char *notdotdot[ MAXDIRS ];
+static int cmdinc_count = 0;
+static char *cmdinc_list[ 2 * MAXINCFILES ];
+char *objprefix = "";
+char *objsuffix = OBJSUFFIX;
+static char *startat = "# DO NOT DELETE";
+int width = 78;
+static boolean append = FALSE;
+boolean printed = FALSE;
+boolean verbose = FALSE;
+boolean show_where_not = FALSE;
+/* Warn on multiple includes of same file */
+boolean warn_multiple = FALSE;
+
+static void setfile_cmdinc(struct filepointer *filep, long count, char **list);
+static void redirect(char *line, char *makefile);
+
+static
+#ifdef SIGNALRETURNSINT
+int
+#else
+void
+#endif
+catch (int sig)
+{
+ fflush (stdout);
+ fatalerr ("got signal %d\n", sig);
+}
+
+#if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(__UNIXOS2__) || defined(Lynx_22) || defined(__CYGWIN__)
+#define USGISH
+#endif
+
+#ifndef USGISH
+#ifdef X_NOT_POSIX
+#define sigaction sigvec
+#define sa_handler sv_handler
+#define sa_mask sv_mask
+#define sa_flags sv_flags
+#endif
+struct sigaction sig_act;
+#endif /* USGISH */
+
+int
+main(int argc, char *argv[])
+{
+ char **fp = filelist;
+ char **incp = includedirs;
+ char *p;
+ struct inclist *ip;
+ char *makefile = NULL;
+ struct filepointer *filecontent;
+ struct symtab *psymp = predefs;
+ char *endmarker = NULL;
+ char *defincdir = NULL;
+ char **undeflist = NULL;
+ int numundefs = 0, i;
+ register char offset;
+
+ ProgramName = argv[0];
+
+ while (psymp->s_name)
+ {
+ define2(psymp->s_name, psymp->s_value, &maininclist);
+ psymp++;
+ }
+ if (argc == 2 && argv[1][0] == '@') {
+ struct stat ast;
+ int afd;
+ char *args;
+ char **nargv;
+ int nargc;
+ char quotechar = '\0';
+
+ nargc = 1;
+ if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
+ fatalerr("cannot open \"%s\"\n", argv[1]+1);
+ fstat(afd, &ast);
+ args = (char *)malloc(ast.st_size + 1);
+ if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
+ fatalerr("failed to read %s\n", argv[1]+1);
+ args[ast.st_size] = '\0';
+ close(afd);
+ for (p = args; *p; p++) {
+ if (quotechar) {
+ if (quotechar == '\\' ||
+ (*p == quotechar && p[-1] != '\\'))
+ quotechar = '\0';
+ continue;
+ }
+ switch (*p) {
+ case '\\':
+ case '"':
+ case '\'':
+ quotechar = *p;
+ break;
+ case ' ':
+ case '\n':
+ *p = '\0';
+ if (p > args && p[-1])
+ nargc++;
+ break;
+ }
+ }
+ if (p[-1])
+ nargc++;
+ nargv = (char **)malloc(nargc * sizeof(char *));
+ nargv[0] = argv[0];
+ argc = 1;
+ for (p = args; argc < nargc; p += strlen(p) + 1)
+ if (*p) nargv[argc++] = p;
+ argv = nargv;
+ }
+ for(argc--, argv++; argc; argc--, argv++) {
+ /* if looking for endmarker then check before parsing */
+ if (endmarker && strcmp (endmarker, *argv) == 0) {
+ endmarker = NULL;
+ continue;
+ }
+ if (**argv != '-') {
+ /* treat +thing as an option for C++ */
+ if (endmarker && **argv == '+')
+ continue;
+ *fp++ = argv[0];
+ continue;
+ }
+ switch(argv[0][1]) {
+ case '-':
+ endmarker = &argv[0][2];
+ if (endmarker[0] == '\0') endmarker = "--";
+ break;
+ case 'D':
+ offset = 2;
+ if (argv[0][2] == '\0') {
+ argv++;
+ argc--;
+ offset = 0;
+ }
+ /* offset +1 here since first def letter
+ * cannot be `=`
+ */
+ for (p = argv[0] + offset + 1; *p; p++)
+ if (*p == '=') {
+ *p = ' ';
+ break;
+ }
+ define(argv[0] + offset, &maininclist);
+ break;
+ case 'I':
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = argv[0]+2;
+ if (**(incp-1) == '\0') {
+ *(incp-1) = *(++argv);
+ argc--;
+ }
+ break;
+ case 'U':
+ /* Undef's override all -D's so save them up */
+ numundefs++;
+ if (numundefs == 1)
+ undeflist = malloc(sizeof(char *));
+ else
+ undeflist = realloc(undeflist,
+ numundefs * sizeof(char *));
+ offset = 2;
+ if (argv[0][2] == '\0') {
+ argv++;
+ argc--;
+ offset = 0;
+ }
+ undeflist[numundefs - 1] = argv[0] + offset;
+ break;
+ case 'Y':
+ defincdir = argv[0]+2;
+ break;
+ /* do not use if endmarker processing */
+ case 'a':
+ if (endmarker) break;
+ append = TRUE;
+ break;
+ case 'w':
+ if (endmarker) break;
+ if (argv[0][2] == '\0') {
+ argv++;
+ argc--;
+ width = atoi(argv[0]);
+ } else
+ width = atoi(argv[0]+2);
+ break;
+ case 'o':
+ if (endmarker) break;
+ if (argv[0][2] == '\0') {
+ argv++;
+ argc--;
+ objsuffix = argv[0];
+ } else
+ objsuffix = argv[0]+2;
+ break;
+ case 'p':
+ if (endmarker) break;
+ if (argv[0][2] == '\0') {
+ argv++;
+ argc--;
+ objprefix = argv[0];
+ } else
+ objprefix = argv[0]+2;
+ break;
+ case 'v':
+ if (endmarker) break;
+ verbose = TRUE;
+#ifdef DEBUG
+ if (argv[0][2])
+ _debugmask = atoi(argv[0]+2);
+#endif
+ break;
+ case 's':
+ if (endmarker) break;
+ startat = argv[0]+2;
+ if (*startat == '\0') {
+ startat = *(++argv);
+ argc--;
+ }
+ if (*startat != '#')
+ fatalerr("-s flag's value should start %s\n",
+ "with '#'.");
+ break;
+ case 'f':
+ if (endmarker) break;
+ makefile = argv[0]+2;
+ if (*makefile == '\0') {
+ makefile = *(++argv);
+ argc--;
+ }
+ break;
+
+ case 'm':
+ warn_multiple = TRUE;
+ break;
+
+ /* Ignore -O, -g so we can just pass ${CFLAGS} to
+ makedepend
+ */
+ case 'O':
+ case 'g':
+ break;
+ case 'i':
+ if (strcmp(&argv[0][1],"include") == 0) {
+ char *buf;
+ if (argc<2)
+ fatalerr("option -include is a "
+ "missing its parameter\n");
+ if (cmdinc_count >= MAXINCFILES)
+ fatalerr("Too many -include flags.\n");
+ argc--;
+ argv++;
+ buf = malloc(strlen(DASH_INC_PRE) +
+ strlen(argv[0]) +
+ strlen(DASH_INC_POST) + 1);
+ if(!buf)
+ fatalerr("out of memory at "
+ "-include string\n");
+ cmdinc_list[2 * cmdinc_count + 0] = argv[0];
+ cmdinc_list[2 * cmdinc_count + 1] = buf;
+ cmdinc_count++;
+ break;
+ }
+ /* intentional fall through */
+ default:
+ if (endmarker) break;
+ /* fatalerr("unknown opt = %s\n", argv[0]); */
+ warning("ignoring option %s\n", argv[0]);
+ }
+ }
+ /* Now do the undefs from the command line */
+ for (i = 0; i < numundefs; i++)
+ undefine(undeflist[i], &maininclist);
+ if (numundefs > 0)
+ free(undeflist);
+
+ if (!defincdir) {
+#ifdef PREINCDIR
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = PREINCDIR;
+#endif
+#ifdef __UNIXOS2__
+ {
+ char *emxinc = getenv("C_INCLUDE_PATH");
+ /* can have more than one component */
+ if (emxinc) {
+ char *beg, *end;
+ beg= (char*)strdup(emxinc);
+ for (;;) {
+ end = (char*)strchr(beg,';');
+ if (end) *end = 0;
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many include dirs\n");
+ *incp++ = beg;
+ if (!end) break;
+ beg = end+1;
+ }
+ }
+ }
+#else /* !__UNIXOS2__, does not use INCLUDEDIR at all */
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = INCLUDEDIR;
+#endif
+
+#ifdef EXTRAINCDIR
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = EXTRAINCDIR;
+#endif
+
+#ifdef POSTINCDIR
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = POSTINCDIR;
+#endif
+ } else if (*defincdir) {
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = defincdir;
+ }
+
+ redirect(startat, makefile);
+
+ /*
+ * catch signals.
+ */
+#ifdef USGISH
+/* should really reset SIGINT to SIG_IGN if it was. */
+#ifdef SIGHUP
+ signal (SIGHUP, catch);
+#endif
+ signal (SIGINT, catch);
+#ifdef SIGQUIT
+ signal (SIGQUIT, catch);
+#endif
+ signal (SIGILL, catch);
+#ifdef SIGBUS
+ signal (SIGBUS, catch);
+#endif
+ signal (SIGSEGV, catch);
+#ifdef SIGSYS
+ signal (SIGSYS, catch);
+#endif
+#else
+ sig_act.sa_handler = catch;
+#if defined(_POSIX_SOURCE) || !defined(X_NOT_POSIX)
+ sigemptyset(&sig_act.sa_mask);
+ sigaddset(&sig_act.sa_mask, SIGINT);
+ sigaddset(&sig_act.sa_mask, SIGQUIT);
+#ifdef SIGBUS
+ sigaddset(&sig_act.sa_mask, SIGBUS);
+#endif
+ sigaddset(&sig_act.sa_mask, SIGILL);
+ sigaddset(&sig_act.sa_mask, SIGSEGV);
+ sigaddset(&sig_act.sa_mask, SIGHUP);
+ sigaddset(&sig_act.sa_mask, SIGPIPE);
+#ifdef SIGSYS
+ sigaddset(&sig_act.sa_mask, SIGSYS);
+#endif
+#else
+ sig_act.sa_mask = ((1<<(SIGINT -1))
+ |(1<<(SIGQUIT-1))
+#ifdef SIGBUS
+ |(1<<(SIGBUS-1))
+#endif
+ |(1<<(SIGILL-1))
+ |(1<<(SIGSEGV-1))
+ |(1<<(SIGHUP-1))
+ |(1<<(SIGPIPE-1))
+#ifdef SIGSYS
+ |(1<<(SIGSYS-1))
+#endif
+ );
+#endif /* _POSIX_SOURCE */
+ sig_act.sa_flags = 0;
+ sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
+ sigaction(SIGINT, &sig_act, (struct sigaction *)0);
+ sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
+ sigaction(SIGILL, &sig_act, (struct sigaction *)0);
+#ifdef SIGBUS
+ sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
+#endif
+ sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
+#ifdef SIGSYS
+ sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
+#endif
+#endif /* USGISH */
+
+ /*
+ * now peruse through the list of files.
+ */
+ for(fp=filelist; *fp; fp++) {
+ DBG_PRINT(stderr,"file: %s\n",*fp);
+ filecontent = getfile(*fp);
+ setfile_cmdinc(filecontent, cmdinc_count, cmdinc_list);
+ ip = newinclude(*fp, (char *)NULL);
+
+ find_includes(filecontent, ip, ip, 0, FALSE);
+ freefile(filecontent);
+ recursive_pr_include(ip, ip->i_file, base_name(*fp));
+ inc_clean();
+ }
+ if (printed)
+ printf("\n");
+ return 0;
+}
+
+#ifdef __UNIXOS2__
+/*
+ * eliminate \r chars from file
+ */
+static int
+elim_cr(char *buf, int sz)
+{
+ int i,wp;
+ for (i= wp = 0; i<sz; i++) {
+ if (buf[i] != '\r')
+ buf[wp++] = buf[i];
+ }
+ return wp;
+}
+#endif
+
+struct filepointer *
+getfile(char *file)
+{
+ int fd;
+ struct filepointer *content;
+ struct stat st;
+
+ content = (struct filepointer *)malloc(sizeof(struct filepointer));
+ content->f_name = file;
+ if ((fd = open(file, O_RDONLY)) < 0) {
+ warning("cannot open \"%s\"\n", file);
+ content->f_p = content->f_base = content->f_end = (char *)malloc(1);
+ *content->f_p = '\0';
+ return(content);
+ }
+ fstat(fd, &st);
+ content->f_base = (char *)malloc(st.st_size+1);
+ if (content->f_base == NULL)
+ fatalerr("cannot allocate mem\n");
+ if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
+ fatalerr("failed to read %s\n", file);
+#ifdef __UNIXOS2__
+ st.st_size = elim_cr(content->f_base,st.st_size);
+#endif
+ close(fd);
+ content->f_len = st.st_size+1;
+ content->f_p = content->f_base;
+ content->f_end = content->f_base + st.st_size;
+ *content->f_end = '\0';
+ content->f_line = 0;
+ content->cmdinc_count = 0;
+ content->cmdinc_list = NULL;
+ content->cmdinc_line = 0;
+ return(content);
+}
+
+void
+setfile_cmdinc(struct filepointer* filep, long count, char** list)
+{
+ filep->cmdinc_count = count;
+ filep->cmdinc_list = list;
+ filep->cmdinc_line = 0;
+}
+
+void
+freefile(struct filepointer *fp)
+{
+ free(fp->f_base);
+ free(fp);
+}
+
+char *copy(char *str)
+{
+ char *p = (char *)malloc(strlen(str) + 1);
+
+ strcpy(p, str);
+ return(p);
+}
+
+int
+match(char *str, char **list)
+{
+ int i;
+
+ for (i=0; *list; i++, list++)
+ if (strcmp(str, *list) == 0)
+ return(i);
+ return(-1);
+}
+
+/*
+ * Get the next line. We only return lines beginning with '#' since that
+ * is all this program is ever interested in.
+ */
+char *getnextline(struct filepointer *filep)
+{
+ char *p, /* walking pointer */
+ *eof, /* end of file pointer */
+ *bol; /* beginning of line pointer */
+ int lineno; /* line number */
+ boolean whitespace = FALSE;
+
+ /*
+ * Fake the "-include" line files in form of #include to the
+ * start of each file.
+ */
+ if (filep->cmdinc_line < filep->cmdinc_count) {
+ char *inc = filep->cmdinc_list[2 * filep->cmdinc_line + 0];
+ char *buf = filep->cmdinc_list[2 * filep->cmdinc_line + 1];
+ filep->cmdinc_line++;
+ sprintf(buf,"%s%s%s",DASH_INC_PRE,inc,DASH_INC_POST);
+ DBG_PRINT(stderr,"%s\n",buf);
+ return(buf);
+ }
+
+ p = filep->f_p;
+ eof = filep->f_end;
+ if (p >= eof)
+ return((char *)NULL);
+ lineno = filep->f_line;
+
+ for (bol = p--; ++p < eof; ) {
+ if ((bol == p) && ((*p == ' ') || (*p == '\t')))
+ {
+ /* Consume leading white-spaces for this line */
+ while (((p+1) < eof) && ((*p == ' ') || (*p == '\t')))
+ {
+ p++;
+ bol++;
+ }
+ whitespace = TRUE;
+ }
+
+ if (*p == '/' && (p+1) < eof && *(p+1) == '*') {
+ /* Consume C comments */
+ *(p++) = ' ';
+ *(p++) = ' ';
+ while (p < eof && *p) {
+ if (*p == '*' && (p+1) < eof && *(p+1) == '/') {
+ *(p++) = ' ';
+ *(p++) = ' ';
+ break;
+ }
+ if (*p == '\n')
+ lineno++;
+ *(p++) = ' ';
+ }
+ --p;
+ }
+ else if (*p == '/' && (p+1) < eof && *(p+1) == '/') {
+ /* Consume C++ comments */
+ *(p++) = ' ';
+ *(p++) = ' ';
+ while (p < eof && *p) {
+ if (*p == '\\' && (p+1) < eof &&
+ *(p+1) == '\n') {
+ *(p++) = ' ';
+ lineno++;
+ }
+ else if (*p == '?' && (p+3) < eof &&
+ *(p+1) == '?' &&
+ *(p+2) == '/' &&
+ *(p+3) == '\n') {
+ *(p++) = ' ';
+ *(p++) = ' ';
+ *(p++) = ' ';
+ lineno++;
+ }
+ else if (*p == '\n')
+ break; /* to process end of line */
+ *(p++) = ' ';
+ }
+ --p;
+ }
+ else if (*p == '\\' && (p+1) < eof && *(p+1) == '\n') {
+ /* Consume backslash line terminations */
+ *(p++) = ' ';
+ *p = ' ';
+ lineno++;
+ }
+ else if (*p == '?' && (p+3) < eof &&
+ *(p+1) == '?' && *(p+2) == '/' && *(p+3) == '\n') {
+ /* Consume trigraph'ed backslash line terminations */
+ *(p++) = ' ';
+ *(p++) = ' ';
+ *(p++) = ' ';
+ *p = ' ';
+ lineno++;
+ }
+ else if (*p == '\n') {
+ lineno++;
+ if (*bol == '#') {
+ char *cp;
+
+ *(p++) = '\0';
+ /* punt lines with just # (yacc generated) */
+ for (cp = bol+1;
+ *cp && (*cp == ' ' || *cp == '\t'); cp++);
+ if (*cp) goto done;
+ --p;
+ }
+ bol = p+1;
+ whitespace = FALSE;
+ }
+ }
+ if (*bol != '#')
+ bol = NULL;
+done:
+ if (bol && whitespace) {
+ warning("%s: non-portable whitespace encountered at line %d\n",
+ filep->f_name, lineno);
+ }
+ filep->f_p = p;
+ filep->f_line = lineno;
+#ifdef DEBUG_DUMP
+ if (bol)
+ DBG_PRINT(stderr,"%s\n",bol);
+#endif
+ return(bol);
+}
+
+/*
+ * Strip the file name down to what we want to see in the Makefile.
+ * It will have objprefix and objsuffix around it.
+ */
+char *base_name(char *file)
+{
+ char *p;
+
+ file = copy(file);
+ for(p=file+strlen(file); p>file && *p != '.'; p--) ;
+
+ if (*p == '.')
+ *p = '\0';
+ return(file);
+}
+
+#if defined(USG) && !defined(CRAY) && !defined(SVR4) && !defined(__UNIXOS2__) && !defined(clipper) && !defined(__clipper__)
+int rename (char *from, char *to)
+{
+ (void) unlink (to);
+ if (link (from, to) == 0) {
+ unlink (from);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+#endif /* USGISH */
+
+void
+redirect(char *line, char *makefile)
+{
+ struct stat st;
+ FILE *fdin, *fdout;
+ char backup[ BUFSIZ ],
+ buf[ BUFSIZ ];
+ boolean found = FALSE;
+ int len;
+
+ /*
+ * if makefile is "-" then let it pour onto stdout.
+ */
+ if (makefile && *makefile == '-' && *(makefile+1) == '\0') {
+ puts(line);
+ return;
+ }
+
+ /*
+ * use a default makefile is not specified.
+ */
+ if (!makefile) {
+ if (stat("Makefile", &st) == 0)
+ makefile = "Makefile";
+ else if (stat("makefile", &st) == 0)
+ makefile = "makefile";
+ else
+ fatalerr("[mM]akefile is not present\n");
+ }
+ else
+ stat(makefile, &st);
+ if ((fdin = fopen(makefile, "r")) == NULL)
+ fatalerr("cannot open \"%s\"\n", makefile);
+ sprintf(backup, "%s.bak", makefile);
+ unlink(backup);
+#if defined(WIN32) || defined(__UNIXOS2__) || defined(__CYGWIN__)
+ fclose(fdin);
+#endif
+ if (rename(makefile, backup) < 0)
+ fatalerr("cannot rename %s to %s\n", makefile, backup);
+#if defined(WIN32) || defined(__UNIXOS2__) || defined(__CYGWIN__)
+ if ((fdin = fopen(backup, "r")) == NULL)
+ fatalerr("cannot open \"%s\"\n", backup);
+#endif
+ if ((fdout = freopen(makefile, "w", stdout)) == NULL)
+ fatalerr("cannot open \"%s\"\n", backup);
+ len = strlen(line);
+ while (!found && fgets(buf, BUFSIZ, fdin)) {
+ if (*buf == '#' && strncmp(line, buf, len) == 0)
+ found = TRUE;
+ fputs(buf, fdout);
+ }
+ if (!found) {
+ if (verbose)
+ warning("Adding new delimiting line \"%s\" and dependencies...\n",
+ line);
+ puts(line); /* same as fputs(fdout); but with newline */
+ } else if (append) {
+ while (fgets(buf, BUFSIZ, fdin)) {
+ fputs(buf, fdout);
+ }
+ }
+ fflush(fdout);
+#if defined(USGISH) || defined(_SEQUENT_) || defined(USE_CHMOD)
+ chmod(makefile, st.st_mode);
+#else
+ fchmod(fileno(fdout), st.st_mode);
+#endif /* USGISH */
+}
+
+void
+fatalerr(char *msg, ...)
+{
+ va_list args;
+ fprintf(stderr, "%s: error: ", ProgramName);
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ exit (1);
+}
+
+void
+warning(char *msg, ...)
+{
+ va_list args;
+ fprintf(stderr, "%s: warning: ", ProgramName);
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+}
+
+void
+warning1(char *msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/mkdepend.man b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/mkdepend.man
new file mode 100644
index 0000000..595c87e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/mkdepend.man
@@ -0,0 +1,382 @@
+.\" $Xorg: mkdepend.man,v 1.5 2001/02/09 02:03:16 xorgcvs Exp $
+.\" Copyright (c) 1993, 1994, 1998 The Open Group
+.\"
+.\" Permission to use, copy, modify, distribute, and sell this software and its
+.\" documentation for any purpose is hereby granted without fee, provided that
+.\" the above copyright notice appear in all copies and that both that
+.\" copyright notice and this permission notice appear in supporting
+.\" documentation.
+.\"
+.\" 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 OPEN GROUP 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.
+.\"
+.\" Except as contained in this notice, the name of The Open Group shall not
+.\" be used in advertising or otherwise to promote the sale, use or other
+.\" dealing in this Software without prior written authorization from The
+.\" Open Group.
+.\"
+.\" $XFree86: xc/config/makedepend/mkdepend.man,v 1.7 2002/12/14 02:39:45 dawes Exp $
+.\"
+.TH MAKEDEPEND 1 __xorgversion__
+.UC 4
+.SH NAME
+makedepend \- create dependencies in makefiles
+.SH SYNOPSIS
+.B makedepend
+[
+.BI \-D name\fB=\fPdef
+] [
+.BI \-D name
+] [
+.BI \-I includedir
+] [
+.BI \-Y includedir
+] [
+.B \-a
+] [
+.BI \-f makefile
+] [
+.BI \-include \ file
+] [
+.BI \-o objsuffix
+] [
+.BI \-p objprefix
+] [
+.BI \-s string
+] [
+.BI \-w width
+] [
+.B \-v
+] [
+.B \-m
+] [
+\-\^\-
+.I otheroptions
+\-\^\-
+]
+.I sourcefile
+\&.\|.\|.
+.br
+.SH DESCRIPTION
+The
+.B makedepend
+program reads each
+.I sourcefile
+in sequence and parses it like a C-preprocessor,
+processing all
+.I #include,
+.I #define,
+.I #undef,
+.I #ifdef,
+.I #ifndef,
+.I #endif,
+.I #if,
+.I #elif
+and
+.I #else
+directives so that it can correctly tell which
+.I #include,
+directives would be used in a compilation.
+Any
+.I #include,
+directives can reference files having other
+.I #include
+directives, and parsing will occur in these files as well.
+.PP
+Every file that a
+.I sourcefile
+includes,
+directly or indirectly,
+is what
+.B makedepend
+calls a \fIdependency.\fP
+These dependencies are then written to a
+.I makefile
+in such a way that
+.B make(1)
+will know which object files must be recompiled when a dependency has changed.
+.PP
+By default,
+.B makedepend
+places its output in the file named
+.I makefile
+if it exists, otherwise
+.I Makefile.
+An alternate makefile may be specified with the
+.B \-f
+option.
+It first searches the makefile for
+the line
+.sp
+\& # DO NOT DELETE THIS LINE \-\^\- make depend depends on it.
+.sp
+or one provided with the
+.B \-s
+option,
+as a delimiter for the dependency output.
+If it finds it, it will delete everything
+following this to the end of the makefile
+and put the output after this line.
+If it doesn't find it, the program
+will append the string to the end of the makefile
+and place the output following that.
+For each
+.I sourcefile
+appearing on the command line,
+.B makedepend
+puts lines in the makefile of the form
+.sp
+ sourcefile.o:\0dfile .\|.\|.
+.sp
+Where \fIsourcefile.o\fP is the name from the command
+line with its suffix replaced with ``.o'',
+and \fIdfile\fP is a dependency discovered in a
+.I #include
+directive while parsing
+.I sourcefile
+or one of the files it included.
+.SH EXAMPLE
+Normally,
+.B makedepend
+will be used in a makefile target so that typing ``make depend'' will
+bring the dependencies up to date for the makefile.
+For example,
+.nf
+ SRCS\0=\0file1.c\0file2.c\0.\|.\|.
+ CFLAGS\0=\0\-O\0\-DHACK\0\-I\^.\^.\^/foobar\0\-xyz
+ depend:
+ makedepend\0\-\^\-\0$(CFLAGS)\0\-\^\-\0$(SRCS)
+.fi
+.SH OPTIONS
+The program
+will ignore any option that it does not understand so that you may use
+the same arguments that you would for
+.B cc(1).
+.TP 5
+.B \-D\fIname\fP=\fIdef\fP \fRor\fP \-D\fIname\fP
+Define.
+This places a definition for
+.I name
+in
+.B makedepend's
+symbol table.
+Without
+.I =def\|
+the symbol becomes defined as ``1''.
+.TP 5
+.B \-I\fIincludedir\fP
+Include directory.
+This option tells
+.B makedepend
+to prepend
+.I includedir
+to its list of directories to search when it encounters
+a
+.I #include
+directive.
+By default,
+.B makedepend
+only searches the standard include directories (usually /usr/include
+and possibly a compiler-dependent directory).
+.TP 5
+.B \-Y\fIincludedir\fP
+Replace all of the standard include directories with the single specified
+include directory; you can omit the
+.I includedir
+to simply prevent searching the standard include directories.
+.TP 5
+.B \-a
+Append the dependencies to the end of the file instead of replacing them.
+.TP 5
+.B \-f\fImakefile\fP
+Filename.
+This allows you to specify an alternate makefile in which
+.B makedepend
+can place its output.
+Specifying ``\-'' as the file name (i.e., \fB\-f\-\fP) sends the
+output to standard output instead of modifying an existing file.
+.TP 5
+.B \-include \fIfile\fP
+Process file as input, and include all the resulting output
+before processing the regular input file. This has the same
+affect as if the specified file is an include statement that
+appears before the very first line of the regular input file.
+.TP 5
+.B \-o\fIobjsuffix\fP
+Object file suffix.
+Some systems may have object files whose suffix is something other
+than ``.o''.
+This option allows you to specify another suffix, such as
+``.b'' with
+.I \-o.b
+or ``:obj''
+with
+.I \-o:obj
+and so forth.
+.TP 5
+.B \-p\fIobjprefix\fP
+Object file prefix.
+The prefix is prepended to the name of the object file. This is
+usually used to designate a different directory for the object file.
+The default is the empty string.
+.TP 5
+.B \-s\fIstring\fP
+Starting string delimiter.
+This option permits you to specify
+a different string for
+.B makedepend
+to look for in the makefile.
+.TP 5
+.B \-w\fIwidth\fP
+Line width.
+Normally,
+.B makedepend
+will ensure that every output line that it writes will be no wider than
+78 characters for the sake of readability.
+This option enables you to change this width.
+.TP 5
+.B \-v
+Verbose operation.
+This option causes
+.B makedepend
+to emit the list of files included by each input file.
+.TP 5
+.B \-m
+Warn about multiple inclusion.
+This option causes
+.B makedepend
+to produce a warning if any input file includes another file more than
+once. In previous versions of
+.B makedepend
+this was the default behavior; the default has been changed to better
+match the behavior of the C compiler, which does not consider multiple
+inclusion to be an error. This option is provided for backward
+compatibility, and to aid in debugging problems related to multiple
+inclusion.
+.TP 5
+.B "\-\^\- \fIoptions\fP \-\^\-"
+If
+.B makedepend
+encounters a double hyphen (\-\^\-) in the argument list,
+then any unrecognized argument following it
+will be silently ignored; a second double hyphen terminates this
+special treatment.
+In this way,
+.B makedepend
+can be made to safely ignore esoteric compiler arguments that might
+normally be found in a CFLAGS
+.B make
+macro (see the
+.B EXAMPLE
+section above).
+All options that
+.B makedepend
+recognizes and appear between the pair of double hyphens
+are processed normally.
+.SH ALGORITHM
+The approach used in this program enables it to run an order of magnitude
+faster than any other ``dependency generator'' I have ever seen.
+Central to this performance are two assumptions:
+that all files compiled by a single
+makefile will be compiled with roughly the same
+.I \-I
+and
+.I \-D
+options;
+and that most files in a single directory will include largely the
+same files.
+.PP
+Given these assumptions,
+.B makedepend
+expects to be called once for each makefile, with
+all source files that are maintained by the
+makefile appearing on the command line.
+It parses each source and include
+file exactly once, maintaining an internal symbol table
+for each.
+Thus, the first file on the command line will take an amount of time
+proportional to the amount of time that a normal C preprocessor takes.
+But on subsequent files, if it encounters an include file
+that it has already parsed, it does not parse it again.
+.PP
+For example,
+imagine you are compiling two files,
+.I file1.c
+and
+.I file2.c,
+they each include the header file
+.I header.h,
+and the file
+.I header.h
+in turn includes the files
+.I def1.h
+and
+.I def2.h.
+When you run the command
+.sp
+ makedepend\0file1.c\0file2.c
+.sp
+.B makedepend
+will parse
+.I file1.c
+and consequently,
+.I header.h
+and then
+.I def1.h
+and
+.I def2.h.
+It then decides that the dependencies for this file are
+.sp
+ file1.o:\0header.h\0def1.h\0def2.h
+.sp
+But when the program parses
+.I file2.c
+and discovers that it, too, includes
+.I header.h,
+it does not parse the file,
+but simply adds
+.I header.h,
+.I def1.h
+and
+.I def2.h
+to the list of dependencies for
+.I file2.o.
+.SH "SEE ALSO"
+cc(1), make(1)
+.SH BUGS
+.B makedepend
+parses, but does not currently evaluate, the SVR4 #predicate(token-list)
+preprocessor expression; such expressions are simply assumed to be true.
+This may cause the wrong
+.I #include
+directives to be evaluated.
+.PP
+Imagine you are parsing two files,
+say
+.I file1.c
+and
+.I file2.c,
+each includes the file
+.I def.h.
+The list of files that
+.I def.h
+includes might truly be different when
+.I def.h
+is included by
+.I file1.c
+than when it is included by
+.I file2.c.
+But once
+.B makedepend
+arrives at a list of dependencies for a file,
+it is cast in concrete.
+.SH AUTHOR
+Todd Brunhoff, Tektronix, Inc. and MIT Project Athena
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/parse.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/parse.c
new file mode 100644
index 0000000..968d2c4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/parse.c
@@ -0,0 +1,686 @@
+/* $Xorg: parse.c,v 1.6 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/parse.c,v 1.12 2002/02/26 05:09:10 tsi Exp $ */
+
+#include "def.h"
+
+extern char *directives[];
+extern struct inclist inclist[ MAXFILES ],
+ *inclistnext,
+ maininclist;
+extern char *includedirs[ ],
+ **includedirsnext;
+
+static int deftype (char *line, struct filepointer *filep,
+ struct inclist *file_red, struct inclist *file,
+ int parse_it);
+static int zero_value(char *filename, char *exp, struct filepointer *filep,
+ struct inclist *file_red);
+static int merge2defines(struct inclist *file1, struct inclist *file2);
+
+static int
+gobble(struct filepointer *filep, struct inclist *file,
+ struct inclist *file_red)
+{
+ char *line;
+ int type;
+
+ while ((line = getnextline(filep))) {
+ switch(type = deftype(line, filep, file_red, file, FALSE)) {
+ case IF:
+ case IFFALSE:
+ case IFGUESSFALSE:
+ case IFDEF:
+ case IFNDEF:
+ type = gobble(filep, file, file_red);
+ while ((type == ELIF) || (type == ELIFFALSE) ||
+ (type == ELIFGUESSFALSE))
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ (void)gobble(filep, file, file_red);
+ break;
+ case ELSE:
+ case ENDIF:
+ debug(0,("%s, line %d: #%s\n",
+ file->i_file, filep->f_line,
+ directives[type]));
+ return(type);
+ case DEFINE:
+ case UNDEF:
+ case INCLUDE:
+ case INCLUDEDOT:
+ case PRAGMA:
+ case ERROR:
+ case IDENT:
+ case SCCS:
+ case EJECT:
+ case WARNING:
+ case INCLUDENEXT:
+ case INCLUDENEXTDOT:
+ break;
+ case ELIF:
+ case ELIFFALSE:
+ case ELIFGUESSFALSE:
+ return(type);
+ case -1:
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: unknown directive == \"%s\"\n",
+ filep->f_line, line);
+ break;
+ }
+ }
+ return(-1);
+}
+
+/*
+ * Decide what type of # directive this line is.
+ */
+static int
+deftype (char *line, struct filepointer *filep,
+ struct inclist *file_red, struct inclist *file, int parse_it)
+{
+ register char *p;
+ char *directive, savechar, *q;
+ register int ret;
+
+ /*
+ * Parse the directive...
+ */
+ directive=line+1;
+ while (*directive == ' ' || *directive == '\t')
+ directive++;
+
+ p = directive;
+ while ((*p == '_') || (*p >= 'a' && *p <= 'z'))
+ p++;
+ savechar = *p;
+ *p = '\0';
+ ret = match(directive, directives);
+ *p = savechar;
+
+ /* If we don't recognize this compiler directive or we happen to just
+ * be gobbling up text while waiting for an #endif or #elif or #else
+ * in the case of an #elif we must check the zero_value and return an
+ * ELIF or an ELIFFALSE.
+ */
+
+ if (ret == ELIF && !parse_it)
+ {
+ while (*p == ' ' || *p == '\t')
+ p++;
+ /*
+ * parse an expression.
+ */
+ debug(0,("%s, line %d: #elif %s ",
+ file->i_file, filep->f_line, p));
+ ret = zero_value(file->i_file, p, filep, file_red);
+ if (ret != IF)
+ {
+ debug(0,("false...\n"));
+ if (ret == IFFALSE)
+ return(ELIFFALSE);
+ else
+ return(ELIFGUESSFALSE);
+ }
+ else
+ {
+ debug(0,("true...\n"));
+ return(ELIF);
+ }
+ }
+
+ if (ret < 0 || ! parse_it)
+ return(ret);
+
+ /*
+ * now decide how to parse the directive, and do it.
+ */
+ while (*p == ' ' || *p == '\t')
+ p++;
+ q = p + strlen(p);
+ do {
+ q--;
+ } while (*q == ' ' || *q == '\t');
+ q[1] = '\0';
+ switch (ret) {
+ case IF:
+ /*
+ * parse an expression.
+ */
+ ret = zero_value(file->i_file, p, filep, file_red);
+ debug(0,("%s, line %d: %s #if %s\n",
+ file->i_file, filep->f_line, ret?"false":"true", p));
+ break;
+ case IFDEF:
+ case IFNDEF:
+ debug(0,("%s, line %d: #%s %s\n",
+ file->i_file, filep->f_line, directives[ret], p));
+ case UNDEF:
+ /*
+ * separate the name of a single symbol.
+ */
+ while (isalnum(*p) || *p == '_')
+ *line++ = *p++;
+ *line = '\0';
+ break;
+ case INCLUDE:
+ case INCLUDENEXT:
+ debug(2,("%s, line %d: #include%s %s\n",
+ file->i_file, filep->f_line,
+ (ret == INCLUDE) ? "" : "_next", p));
+
+ /* Support ANSI macro substitution */
+ while (1) {
+ struct symtab **sym;
+
+ if (!*p || *p == '"' || *p == '<')
+ break;
+
+ sym = isdefined(p, file_red, NULL);
+ if (!sym)
+ break;
+
+ p = (*sym)->s_value;
+ debug(3,("%s : #includes SYMBOL %s = %s\n",
+ file->i_incstring,
+ (*sym) -> s_name,
+ (*sym) -> s_value));
+ /* mark file as having included a 'soft include' */
+ file->i_flags |= INCLUDED_SYM;
+ }
+
+ /*
+ * Separate the name of the include file.
+ */
+ while (*p && *p != '"' && *p != '<')
+ p++;
+ if (! *p)
+ return(-2);
+ if (*p++ == '"') {
+ if (ret == INCLUDE)
+ ret = INCLUDEDOT;
+ else
+ ret = INCLUDENEXTDOT;
+ while (*p && *p != '"')
+ *line++ = *p++;
+ } else
+ while (*p && *p != '>')
+ *line++ = *p++;
+ *line = '\0';
+ break;
+ case DEFINE:
+ /*
+ * copy the definition back to the beginning of the line.
+ */
+ strcpy (line, p);
+ break;
+ case ELSE:
+ case ENDIF:
+ case ELIF:
+ case PRAGMA:
+ case ERROR:
+ case IDENT:
+ case SCCS:
+ case EJECT:
+ case WARNING:
+ debug(0,("%s, line %d: #%s\n",
+ file->i_file, filep->f_line, directives[ret]));
+ /*
+ * nothing to do.
+ */
+ break;
+ }
+ return(ret);
+}
+
+struct symtab **
+fdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
+{
+ struct inclist **ip;
+ struct symtab **val;
+ int i;
+ static int recurse_lvl = 0;
+
+ if (file->i_flags & DEFCHECKED)
+ return(NULL);
+ debug(2,("Looking for %s in %s\n", symbol, file->i_file));
+ file->i_flags |= DEFCHECKED;
+ if ((val = slookup(symbol, file)))
+ debug(1,("%s defined in %s as %s\n",
+ symbol, file->i_file, (*val)->s_value));
+ if (val == NULL && file->i_list)
+ {
+ for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
+ if (file->i_merged[i]==FALSE) {
+ val = fdefined(symbol, *ip, srcfile);
+ file->i_merged[i]=merge2defines(file,*ip);
+ if (val!=NULL) break;
+ }
+ }
+ else if (val != NULL && srcfile != NULL) *srcfile = file;
+ recurse_lvl--;
+ file->i_flags &= ~DEFCHECKED;
+
+ return(val);
+}
+
+struct symtab **
+isdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
+{
+ struct symtab **val;
+
+ if ((val = slookup(symbol, &maininclist))) {
+ debug(1,("%s defined on command line\n", symbol));
+ if (srcfile != NULL) *srcfile = &maininclist;
+ return(val);
+ }
+ if ((val = fdefined(symbol, file, srcfile)))
+ return(val);
+ debug(1,("%s not defined in %s\n", symbol, file->i_file));
+ return(NULL);
+}
+
+/*
+ * Return type based on if the #if expression evaluates to 0
+ */
+static int
+zero_value(char *filename,
+ char *exp,
+ struct filepointer *filep,
+ struct inclist *file_red)
+{
+ if (cppsetup(filename, exp, filep, file_red))
+ return(IFFALSE);
+ else
+ return(IF);
+}
+
+void
+define2(char *name, char *val, struct inclist *file)
+{
+ int first, last, below;
+ register struct symtab **sp = NULL, **dest;
+ struct symtab *stab;
+
+ /* Make space if it's needed */
+ if (file->i_defs == NULL)
+ {
+ file->i_defs = (struct symtab **)
+ malloc(sizeof (struct symtab*) * SYMTABINC);
+ file->i_ndefs = 0;
+ }
+ else if (!(file->i_ndefs % SYMTABINC))
+ file->i_defs = (struct symtab **)
+ realloc(file->i_defs,
+ sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
+
+ if (file->i_defs == NULL)
+ fatalerr("malloc()/realloc() failure in insert_defn()\n");
+
+ below = first = 0;
+ last = file->i_ndefs - 1;
+ while (last >= first)
+ {
+ /* Fast inline binary search */
+ register char *s1;
+ register char *s2;
+ register int middle = (first + last) / 2;
+
+ /* Fast inline strchr() */
+ s1 = name;
+ s2 = file->i_defs[middle]->s_name;
+ while (*s1++ == *s2++)
+ if (s2[-1] == '\0') break;
+
+ /* If exact match, set sp and break */
+ if (*--s1 == *--s2)
+ {
+ sp = file->i_defs + middle;
+ break;
+ }
+
+ /* If name > i_defs[middle] ... */
+ if (*s1 > *s2)
+ {
+ below = first;
+ first = middle + 1;
+ }
+ /* else ... */
+ else
+ {
+ below = last = middle - 1;
+ }
+ }
+
+ /* Search is done. If we found an exact match to the symbol name,
+ just replace its s_value */
+ if (sp != NULL)
+ {
+ debug(1,("redefining %s from %s to %s in file %s\n",
+ name, (*sp)->s_value, val, file->i_file));
+ free((*sp)->s_value);
+ (*sp)->s_value = copy(val);
+ return;
+ }
+
+ sp = file->i_defs + file->i_ndefs++;
+ dest = file->i_defs + below + 1;
+ while (sp > dest)
+ {
+ *sp = sp[-1];
+ sp--;
+ }
+ stab = (struct symtab *) malloc(sizeof (struct symtab));
+ if (stab == NULL)
+ fatalerr("malloc()/realloc() failure in insert_defn()\n");
+
+ debug(1,("defining %s to %s in file %s\n", name, val, file->i_file));
+ stab->s_name = copy(name);
+ stab->s_value = copy(val);
+ *sp = stab;
+}
+
+void
+define(char *def, struct inclist *file)
+{
+ char *val;
+
+ /* Separate symbol name and its value */
+ val = def;
+ while (isalnum(*val) || *val == '_')
+ val++;
+ if (*val)
+ *val++ = '\0';
+ while (*val == ' ' || *val == '\t')
+ val++;
+
+ if (!*val)
+ val = "1";
+ define2(def, val, file);
+}
+
+struct symtab **
+slookup(char *symbol, struct inclist *file)
+{
+ register int first = 0;
+ register int last = file->i_ndefs - 1;
+
+ if (file) while (last >= first)
+ {
+ /* Fast inline binary search */
+ register char *s1;
+ register char *s2;
+ register int middle = (first + last) / 2;
+
+ /* Fast inline strchr() */
+ s1 = symbol;
+ s2 = file->i_defs[middle]->s_name;
+ while (*s1++ == *s2++)
+ if (s2[-1] == '\0') break;
+
+ /* If exact match, we're done */
+ if (*--s1 == *--s2)
+ {
+ return file->i_defs + middle;
+ }
+
+ /* If symbol > i_defs[middle] ... */
+ if (*s1 > *s2)
+ {
+ first = middle + 1;
+ }
+ /* else ... */
+ else
+ {
+ last = middle - 1;
+ }
+ }
+ return(NULL);
+}
+
+static int
+merge2defines(struct inclist *file1, struct inclist *file2)
+{
+ int i;
+
+ if ((file1==NULL) || (file2==NULL) ||
+ !(file2->i_flags & FINISHED))
+ return 0;
+
+ for (i=0; i < file2->i_listlen; i++)
+ if (file2->i_merged[i]==FALSE)
+ return 0;
+
+ {
+ int first1 = 0;
+ int last1 = file1->i_ndefs - 1;
+
+ int first2 = 0;
+ int last2 = file2->i_ndefs - 1;
+
+ int first=0;
+ struct symtab** i_defs = NULL;
+ int deflen=file1->i_ndefs+file2->i_ndefs;
+
+ debug(2,("merging %s into %s\n",
+ file2->i_file, file1->i_file));
+
+ if (deflen>0)
+ {
+ /* make sure deflen % SYMTABINC == 0 is still true */
+ deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
+ i_defs=(struct symtab**)
+ malloc(deflen*sizeof(struct symtab*));
+ if (i_defs==NULL) return 0;
+ }
+
+ while ((last1 >= first1) && (last2 >= first2))
+ {
+ char *s1=file1->i_defs[first1]->s_name;
+ char *s2=file2->i_defs[first2]->s_name;
+
+ if (strcmp(s1,s2) < 0)
+ i_defs[first++]=file1->i_defs[first1++];
+ else if (strcmp(s1,s2) > 0)
+ i_defs[first++]=file2->i_defs[first2++];
+ else /* equal */
+ {
+ i_defs[first++]=file2->i_defs[first2++];
+ first1++;
+ }
+ }
+ while (last1 >= first1)
+ {
+ i_defs[first++]=file1->i_defs[first1++];
+ }
+ while (last2 >= first2)
+ {
+ i_defs[first++]=file2->i_defs[first2++];
+ }
+
+ if (file1->i_defs) free(file1->i_defs);
+ file1->i_defs=i_defs;
+ file1->i_ndefs=first;
+
+ return 1;
+ }
+}
+
+void
+undefine(char *symbol, struct inclist *file)
+{
+ register struct symtab **ptr;
+ struct inclist *srcfile;
+ while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
+ {
+ srcfile->i_ndefs--;
+ for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
+ *ptr = ptr[1];
+ }
+}
+
+int
+find_includes(struct filepointer *filep, struct inclist *file,
+ struct inclist *file_red, int recursion, boolean failOK)
+{
+ struct inclist *inclistp;
+ char **includedirsp;
+ register char *line;
+ register int type;
+ boolean recfailOK;
+
+ while ((line = getnextline(filep))) {
+ switch(type = deftype(line, filep, file_red, file, TRUE)) {
+ case IF:
+ doif:
+ type = find_includes(filep, file,
+ file_red, recursion+1, failOK);
+ while ((type == ELIF) || (type == ELIFFALSE) ||
+ (type == ELIFGUESSFALSE))
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ gobble(filep, file, file_red);
+ break;
+ case IFFALSE:
+ case IFGUESSFALSE:
+ doiffalse:
+ if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
+ recfailOK = TRUE;
+ else
+ recfailOK = failOK;
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ find_includes(filep, file,
+ file_red, recursion+1, recfailOK);
+ else
+ if (type == ELIF)
+ goto doif;
+ else
+ if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
+ goto doiffalse;
+ break;
+ case IFDEF:
+ case IFNDEF:
+ if ((type == IFDEF && isdefined(line, file_red, NULL))
+ || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
+ debug(1,(type == IFNDEF ?
+ "line %d: %s !def'd in %s via %s%s\n" : "",
+ filep->f_line, line,
+ file->i_file, file_red->i_file, ": doit"));
+ type = find_includes(filep, file,
+ file_red, recursion+1, failOK);
+ while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ gobble(filep, file, file_red);
+ }
+ else {
+ debug(1,(type == IFDEF ?
+ "line %d: %s !def'd in %s via %s%s\n" : "",
+ filep->f_line, line,
+ file->i_file, file_red->i_file, ": gobble"));
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ find_includes(filep, file,
+ file_red, recursion+1, failOK);
+ else if (type == ELIF)
+ goto doif;
+ else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
+ goto doiffalse;
+ }
+ break;
+ case ELSE:
+ case ELIFFALSE:
+ case ELIFGUESSFALSE:
+ case ELIF:
+ if (!recursion)
+ gobble(filep, file, file_red);
+ case ENDIF:
+ if (recursion)
+ return(type);
+ case DEFINE:
+ define(line, file);
+ break;
+ case UNDEF:
+ if (!*line) {
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: incomplete undef == \"%s\"\n",
+ filep->f_line, line);
+ break;
+ }
+ undefine(line, file_red);
+ break;
+ case INCLUDE:
+ case INCLUDEDOT:
+ case INCLUDENEXT:
+ case INCLUDENEXTDOT:
+ inclistp = inclistnext;
+ includedirsp = includedirsnext;
+ debug(2,("%s, reading %s, includes %s\n",
+ file_red->i_file, file->i_file, line));
+ add_include(filep, file, file_red, line, type, failOK);
+ inclistnext = inclistp;
+ includedirsnext = includedirsp;
+ break;
+ case ERROR:
+ case WARNING:
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: %s\n",
+ filep->f_line, line);
+ break;
+
+ case PRAGMA:
+ case IDENT:
+ case SCCS:
+ case EJECT:
+ break;
+ case -1:
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: unknown directive == \"%s\"\n",
+ filep->f_line, line);
+ break;
+ case -2:
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: incomplete include == \"%s\"\n",
+ filep->f_line, line);
+ break;
+ }
+ }
+ file->i_flags |= FINISHED;
+ debug(2,("finished with %s\n", file->i_file));
+ return(-1);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/pr.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/pr.c
new file mode 100644
index 0000000..e864793
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/pr.c
@@ -0,0 +1,124 @@
+/* $Xorg: pr.c,v 1.4 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/pr.c,v 1.5 2001/12/14 19:53:21 dawes Exp $ */
+
+#include "def.h"
+
+extern struct inclist inclist[ MAXFILES ],
+ *inclistp;
+extern char *objprefix;
+extern char *objsuffix;
+extern int width;
+extern boolean printed;
+extern boolean verbose;
+extern boolean show_where_not;
+
+void
+add_include(struct filepointer *filep, struct inclist *file,
+ struct inclist *file_red, char *include, int type,
+ boolean failOK)
+{
+ register struct inclist *newfile;
+ register struct filepointer *content;
+
+ /*
+ * First decide what the pathname of this include file really is.
+ */
+ newfile = inc_path(file->i_file, include, type);
+ if (newfile == NULL) {
+ if (failOK)
+ return;
+ if (file != file_red)
+ warning("%s (reading %s, line %d): ",
+ file_red->i_file, file->i_file, filep->f_line);
+ else
+ warning("%s, line %d: ", file->i_file, filep->f_line);
+ warning1("cannot find include file \"%s\"\n", include);
+ show_where_not = TRUE;
+ newfile = inc_path(file->i_file, include, type);
+ show_where_not = FALSE;
+ }
+
+ if (newfile) {
+ included_by(file, newfile);
+ if (!(newfile->i_flags & SEARCHED)) {
+ newfile->i_flags |= SEARCHED;
+ content = getfile(newfile->i_file);
+ find_includes(content, newfile, file_red, 0, failOK);
+ freefile(content);
+ }
+ }
+}
+
+static void
+pr(struct inclist *ip, char *file, char *base)
+{
+ static char *lastfile;
+ static int current_len;
+ register int len, i;
+ char buf[ BUFSIZ ];
+
+ printed = TRUE;
+ len = strlen(ip->i_file)+1;
+ if (current_len + len > width || file != lastfile) {
+ lastfile = file;
+ sprintf(buf, "\n%s%s%s: %s", objprefix, base, objsuffix,
+ ip->i_file);
+ len = current_len = strlen(buf);
+ }
+ else {
+ buf[0] = ' ';
+ strcpy(buf+1, ip->i_file);
+ current_len += len;
+ }
+ fwrite(buf, len, 1, stdout);
+
+ /*
+ * If verbose is set, then print out what this file includes.
+ */
+ if (! verbose || ip->i_list == NULL || ip->i_flags & NOTIFIED)
+ return;
+ ip->i_flags |= NOTIFIED;
+ lastfile = NULL;
+ printf("\n# %s includes:", ip->i_file);
+ for (i=0; i<ip->i_listlen; i++)
+ printf("\n#\t%s", ip->i_list[ i ]->i_incstring);
+}
+
+void
+recursive_pr_include(struct inclist *head, char *file, char *base)
+{
+ int i;
+
+ if (head->i_flags & MARKED)
+ return;
+ head->i_flags |= MARKED;
+ if (head->i_file != file)
+ pr(head, file, base);
+ for (i=0; i<head->i_listlen; i++)
+ recursive_pr_include(head->i_list[ i ], file, base);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/nfspwd.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/nfspwd.pl
new file mode 100644
index 0000000..2f0e4fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/nfspwd.pl
@@ -0,0 +1,50 @@
+#! perl
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+require "fastcwd.pl";
+
+$_ = &fastcwd;
+if (m@^/[uh]/@o || s@^/tmp_mnt/@/@o) {
+ print("$_\n");
+} elsif ((($user, $rest) = m@^/usr/people/(\w+)/(.*)@o)
+ && readlink("/u/$user") eq "/usr/people/$user") {
+ print("/u/$user/$rest\n");
+} else {
+ chop($host = `hostname`);
+ print("/h/$host$_\n");
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.c b/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.c
new file mode 100644
index 0000000..b6ca0e3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.c
@@ -0,0 +1,481 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+** Netscape portable install command.
+**
+** Brendan Eich, 7/20/95
+*/
+#include <stdio.h> /* OSF/1 requires this before grp.h, so put it first */
+#include <assert.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <limits.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utime.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "pathsub.h"
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+#ifdef SUNOS4
+#include "sunos4.h"
+#endif
+
+#ifdef NEXTSTEP
+#include <bsd/libc.h>
+#endif
+
+#ifdef __QNX__
+#include <unix.h>
+#endif
+
+#ifdef NEED_S_ISLNK
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+#define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK)
+#endif
+#endif
+
+#ifndef _DIRECTORY_SEPARATOR
+#define _DIRECTORY_SEPARATOR "/"
+#endif /* _DIRECTORY_SEPARATOR */
+
+#ifdef NEED_FCHMOD_PROTO
+extern int fchmod(int fildes, mode_t mode);
+#endif
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n"
+ " %*s [-DdltR] file [file ...] directory\n",
+ program, (int) strlen(program), "");
+ exit(2);
+}
+
+static int
+mkdirs(char *path, mode_t mode)
+{
+ char *cp;
+ struct stat sb;
+ int res;
+ int l;
+
+ /* strip trailing "/." */
+ l = strlen(path);
+ if(l > 1 && path[l - 1] == '.' && path[l - 2] == '/')
+ path[l - 2] = 0;
+
+ while (*path == '/' && path[1] == '/')
+ path++;
+ for (cp = strrchr(path, '/'); cp && cp != path && *(cp - 1) == '/'; cp--);
+ if (cp && cp != path) {
+ *cp = '\0';
+ if ((lstat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
+ mkdirs(path, mode) < 0) {
+ return -1;
+ }
+ *cp = '/';
+ }
+
+ res = mkdir(path, mode);
+ if ((res != 0) && (errno == EEXIST))
+ return 0;
+ else
+ return res;
+}
+
+static uid_t
+touid(char *owner)
+{
+ struct passwd *pw;
+ uid_t uid;
+ char *cp;
+
+ pw = getpwnam(owner);
+ if (pw)
+ return pw->pw_uid;
+ uid = strtol(owner, &cp, 0);
+ if (uid == 0 && cp == owner)
+ fail("cannot find uid for %s", owner);
+ return uid;
+}
+
+static gid_t
+togid(char *group)
+{
+ struct group *gr;
+ gid_t gid;
+ char *cp;
+
+ gr = getgrnam(group);
+ if (gr)
+ return gr->gr_gid;
+ gid = strtol(group, &cp, 0);
+ if (gid == 0 && cp == group)
+ fail("cannot find gid for %s", group);
+ return gid;
+}
+
+static void
+copyfile( char *name, char *toname, mode_t mode, char *group, char *owner,
+ int dotimes, uid_t uid, gid_t gid )
+{
+ int fromfd, tofd = -1, cc, wc, exists;
+ char buf[BUFSIZ], *bp;
+ struct stat sb, tosb;
+ struct utimbuf utb;
+
+ exists = (lstat(toname, &tosb) == 0);
+
+ fromfd = open(name, O_RDONLY);
+ if (fromfd < 0 || fstat(fromfd, &sb) < 0)
+ fail("cannot access %s", name);
+ if (exists) {
+ if (S_ISREG(tosb.st_mode)) {
+ /* See if we can open it. This is more reliable than 'access'. */
+ tofd = open(toname, O_CREAT | O_WRONLY, 0666);
+ }
+ if (tofd < 0) {
+ (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
+ }
+ }
+ if (tofd < 0) {
+ tofd = open(toname, O_CREAT | O_WRONLY, 0666);
+ if (tofd < 0)
+ fail("cannot create %s", toname);
+ }
+
+ bp = buf;
+ while ((cc = read(fromfd, bp, sizeof buf)) > 0)
+ {
+ while ((wc = write(tofd, bp, (unsigned int)cc)) > 0)
+ {
+ if ((cc -= wc) == 0)
+ break;
+ bp += wc;
+ }
+ if (wc < 0)
+ fail("cannot write to %s", toname);
+ }
+ if (cc < 0)
+ fail("cannot read from %s", name);
+
+ if (ftruncate(tofd, sb.st_size) < 0)
+ fail("cannot truncate %s", toname);
+#if !defined(VMS)
+ if (dotimes)
+ {
+ utb.actime = sb.st_atime;
+ utb.modtime = sb.st_mtime;
+ if (utime(toname, &utb) < 0)
+ fail("cannot set times of %s", toname);
+ }
+#ifdef HAVE_FCHMOD
+ if (fchmod(tofd, mode) < 0)
+#else
+ if (chmod(toname, mode) < 0)
+#endif
+ fail("cannot change mode of %s", toname);
+#endif
+ if ((owner || group) && fchown(tofd, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+
+ /* Must check for delayed (NFS) write errors on close. */
+ if (close(tofd) < 0)
+ fail("cannot write to %s", toname);
+ close(fromfd);
+#if defined(VMS)
+ if (chmod(toname, (mode & (S_IREAD | S_IWRITE))) < 0)
+ fail("cannot change mode of %s", toname);
+ if (dotimes)
+ {
+ utb.actime = sb.st_atime;
+ utb.modtime = sb.st_mtime;
+ if (utime(toname, &utb) < 0)
+ fail("cannot set times of %s", toname);
+ }
+#endif
+}
+
+static void
+copydir( char *from, char *to, mode_t mode, char *group, char *owner,
+ int dotimes, uid_t uid, gid_t gid)
+{
+ int i;
+ DIR *dir;
+ struct dirent *ep;
+ struct stat sb;
+ char *base, *destdir, *direntry, *destentry;
+
+ base = xbasename(from);
+
+ /* create destination directory */
+ destdir = xmalloc((unsigned int)(strlen(to) + 1 + strlen(base) + 1));
+ sprintf(destdir, "%s%s%s", to, _DIRECTORY_SEPARATOR, base);
+ if (mkdirs(destdir, mode) != 0) {
+ fail("cannot make directory %s\n", destdir);
+ return;
+ }
+
+ dir = opendir(from);
+
+ direntry = xmalloc((unsigned int)PATH_MAX);
+ destentry = xmalloc((unsigned int)PATH_MAX);
+
+ while ((ep = readdir(dir)))
+ {
+ if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
+ continue;
+
+ sprintf(direntry, "%s/%s", from, ep->d_name);
+ sprintf(destentry, "%s%s%s", destdir, _DIRECTORY_SEPARATOR, ep->d_name);
+
+ if (stat(direntry, &sb) == 0 && S_ISDIR(sb.st_mode))
+ copydir( direntry, destdir, mode, group, owner, dotimes, uid, gid );
+ else
+ copyfile( direntry, destentry, mode, group, owner, dotimes, uid, gid );
+ }
+
+ free(direntry);
+ free(destentry);
+ closedir(dir);
+}
+
+int
+main(int argc, char **argv)
+{
+ int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists, fromfd, tofd, cc, wc;
+ mode_t mode = 0755;
+ char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, *bp, buf[BUFSIZ];
+ uid_t uid;
+ gid_t gid;
+ struct stat sb, tosb, fromsb;
+ struct utimbuf utb;
+
+ program = argv[0];
+ cwd = linkname = linkprefix = owner = group = 0;
+ onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0;
+
+ while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) {
+ switch (opt) {
+ case 'C':
+ cwd = optarg;
+ break;
+ case 'D':
+ onlydir = 1;
+ break;
+ case 'd':
+ dodir = 1;
+ break;
+ case 'l':
+ dolink = 1;
+ break;
+ case 'L':
+ linkprefix = optarg;
+ lplen = strlen(linkprefix);
+ dolink = 1;
+ break;
+ case 'R':
+ dolink = dorelsymlink = 1;
+ break;
+ case 'm':
+ mode = strtoul(optarg, &cp, 8);
+ if (mode == 0 && cp == optarg)
+ usage();
+ break;
+ case 'o':
+ owner = optarg;
+ break;
+ case 'g':
+ group = optarg;
+ break;
+ case 't':
+ dotimes = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 2 - onlydir)
+ usage();
+
+ todir = argv[argc-1];
+ if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
+ mkdirs(todir, 0777) < 0) {
+ fail("cannot make directory %s", todir);
+ }
+ if (onlydir)
+ return 0;
+
+ if (!cwd) {
+#ifndef NEEDS_GETCWD
+#ifndef GETCWD_CANT_MALLOC
+ cwd = getcwd(0, PATH_MAX);
+#else
+ cwd = malloc(PATH_MAX + 1);
+ cwd = getcwd(cwd, PATH_MAX);
+#endif
+#else
+ cwd = malloc(PATH_MAX + 1);
+ cwd = getwd(cwd);
+#endif
+ }
+
+ xchdir(todir);
+#ifndef NEEDS_GETCWD
+#ifndef GETCWD_CANT_MALLOC
+ todir = getcwd(0, PATH_MAX);
+#else
+ todir = malloc(PATH_MAX + 1);
+ todir = getcwd(todir, PATH_MAX);
+#endif
+#else
+ todir = malloc(PATH_MAX + 1);
+ todir = getwd(todir);
+#endif
+ tdlen = strlen(todir);
+ xchdir(cwd);
+ tdlen = strlen(todir);
+
+ uid = owner ? touid(owner) : (uid_t)(-1);
+ gid = group ? togid(group) : (gid_t)(-1);
+
+ while (--argc > 0) {
+ name = *argv++;
+ len = strlen(name);
+ base = xbasename(name);
+ bnlen = strlen(base);
+ toname = xmalloc((unsigned int)(tdlen + 1 + bnlen + 1));
+ sprintf(toname, "%s%s%s", todir, _DIRECTORY_SEPARATOR, base);
+ exists = (lstat(toname, &tosb) == 0);
+
+ if (dodir) {
+ /* -d means create a directory, always */
+ if (exists && !S_ISDIR(tosb.st_mode)) {
+ (void) unlink(toname);
+ exists = 0;
+ }
+ if (!exists && mkdir(toname, mode) < 0)
+ fail("cannot make directory %s", toname);
+ if ((owner || group) && chown(toname, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+ } else if (dolink) {
+ if (access(name, R_OK) != 0) {
+ fail("cannot access %s", name);
+ }
+ if (*name == '/') {
+ /* source is absolute pathname, link to it directly */
+ linkname = 0;
+ } else {
+ if (linkprefix) {
+ /* -L implies -l and prefixes names with a $cwd arg. */
+ len += lplen + 1;
+ linkname = xmalloc((unsigned int)(len + 1));
+ sprintf(linkname, "%s/%s", linkprefix, name);
+ } else if (dorelsymlink) {
+ /* Symlink the relative path from todir to source name. */
+ linkname = xmalloc(PATH_MAX);
+
+ if (*todir == '/') {
+ /* todir is absolute: skip over common prefix. */
+ lplen = relatepaths(todir, cwd, linkname);
+ strcpy(linkname + lplen, name);
+ } else {
+ /* todir is named by a relative path: reverse it. */
+ reversepath(todir, name, len, linkname);
+ xchdir(cwd);
+ }
+
+ len = strlen(linkname);
+ }
+ name = linkname;
+ }
+
+ /* Check for a pre-existing symlink with identical content. */
+ if ((exists && (!S_ISLNK(tosb.st_mode) ||
+ readlink(toname, buf, sizeof buf) != len ||
+ strncmp(buf, name, (unsigned int)len) != 0)) ||
+ ((stat(name, &fromsb) == 0) &&
+ (fromsb.st_mtime > tosb.st_mtime))) {
+ (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
+ exists = 0;
+ }
+ if (!exists && symlink(name, toname) < 0)
+ fail("cannot make symbolic link %s", toname);
+#ifdef HAVE_LCHOWN
+ if ((owner || group) && lchown(toname, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+#endif
+
+ if (linkname) {
+ free(linkname);
+ linkname = 0;
+ }
+ } else {
+ /* Copy from name to toname, which might be the same file. */
+ if( stat(name, &sb) == 0 && S_IFDIR & sb.st_mode )
+ {
+ /* then is directory: must explicitly create destination dir */
+ /* and manually copy files over */
+ copydir( name, todir, mode, group, owner, dotimes, uid, gid );
+ }
+ else
+ {
+ copyfile(name, toname, mode, group, owner, dotimes, uid, gid);
+ }
+ }
+
+ free(toname);
+ }
+
+ free(cwd);
+ free(todir);
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.py b/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.py
new file mode 100644
index 0000000..fd4e253
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.py
@@ -0,0 +1,139 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla.
+#
+# The Initial Developer of the Original Code is
+# the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Axel Hecht <axel@pike.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# This is a partial python port of nsinstall.
+# It's intended to be used when there's no natively compile nsinstall
+# available, and doesn't intend to be fully equivalent.
+# Its major use is for l10n repackaging on systems that don't have
+# a full build environment set up.
+# The basic limitation is, it doesn't even try to link and ignores
+# all related options.
+
+from optparse import OptionParser
+import os
+import os.path
+import sys
+import shutil
+
+usage = "usage: %prog [options] arg1 [arg2 ...] target-directory"
+p = OptionParser(usage=usage)
+
+p.add_option('-D', action="store_true",
+ help="Create a single directory only")
+p.add_option('-t', action="store_true",
+ help="Preserve time stamp")
+p.add_option('-m', action="store",
+ help="Set mode", metavar="mode")
+p.add_option('-d', action="store_true",
+ help="Create directories in target")
+p.add_option('-R', action="store_true",
+ help="Use relative symbolic links (ignored)")
+p.add_option('-l', action="store_true",
+ help="Create link (ignored)")
+p.add_option('-L', action="store", metavar="linkprefix",
+ help="Link prefix (ignored)")
+
+# The remaining arguments are not used in our tree, thus they're not
+# implented.
+def BadArg(option, opt, value, parser):
+ parser.error('option not supported: %s' % opt)
+
+p.add_option('-C', action="callback", metavar="CWD",
+ callback=BadArg,
+ help="NOT SUPPORTED")
+p.add_option('-o', action="callback", callback=BadArg,
+ help="Set owner (NOT SUPPORTED)", metavar="owner")
+p.add_option('-g', action="callback", callback=BadArg,
+ help="Set group (NOT SUPPORTED)", metavar="group")
+
+(options, args) = p.parse_args()
+
+if options.m:
+ # mode is specified
+ try:
+ options.m = int(options.m, 8)
+ except:
+ sys.stderr.write('nsinstall: ' + options.m + ' is not a valid mode\n')
+ sys.exit(1)
+
+# just create one directory?
+if options.D:
+ if len(args) != 1:
+ sys.exit(1)
+ if os.path.exists(args[0]):
+ if not os.path.isdir(args[0]):
+ sys.stderr.write('nsinstall: ' + args[0] + ' is not a directory\n')
+ sys.exit(1)
+ if options.m:
+ os.chmod(args[0], options.m)
+ sys.exit()
+ if options.m:
+ os.makedirs(args[0], options.m)
+ else:
+ os.makedirs(args[0])
+ sys.exit()
+
+# nsinstall arg1 [...] directory
+if len(args) < 2:
+ p.error('not enough arguments')
+
+# set up handler
+if options.d:
+ # we're supposed to create directories
+ def handleTarget(srcpath, targetpath):
+ # target directory was already created, just use mkdir
+ os.mkdir(dest)
+else:
+ # we're supposed to copy files
+ def handleTarget(srcpath, targetpath):
+ if options.t:
+ shutil.copy2(srcpath, targetpath)
+ else:
+ shutil.copy(srcpath, targetpath)
+
+# the last argument is the target directory
+target = args.pop()
+# ensure target directory
+if not os.path.isdir(target):
+ os.makedirs(target)
+
+for f in args:
+ dest = os.path.join(target,
+ os.path.basename(os.path.normpath(f)))
+ handleTarget(f, dest)
+ if options.m:
+ os.chmod(dest, options.m)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.c b/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.c
new file mode 100644
index 0000000..8384e5f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.c
@@ -0,0 +1,247 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+** Pathname subroutines.
+**
+** Brendan Eich, 8/29/95
+*/
+#include <assert.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "pathsub.h"
+
+#ifdef USE_REENTRANT_LIBC
+#include <libc_r.h>
+#endif
+
+#ifdef SUNOS4
+#include "sunos4.h"
+#endif
+
+#ifndef D_INO
+#define D_INO d_ino
+#endif
+
+char *program;
+
+void
+fail(char *format, ...)
+{
+ int error;
+ va_list ap;
+
+#ifdef USE_REENTRANT_LIBC
+ R_STRERROR_INIT_R();
+#endif
+
+ error = errno;
+ fprintf(stderr, "%s: ", program);
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ if (error) {
+
+#ifdef USE_REENTRANT_LIBC
+ R_STRERROR_R(errno);
+ fprintf(stderr, ": %s", r_strerror_r);
+#else
+ fprintf(stderr, ": %s", strerror(errno));
+#endif
+ }
+
+ putc('\n', stderr);
+ exit(1);
+}
+
+char *
+getcomponent(char *path, char *name)
+{
+ if (*path == '\0')
+ return 0;
+ if (*path == '/') {
+ *name++ = '/';
+ } else {
+ do {
+ *name++ = *path++;
+ } while (*path != '/' && *path != '\0');
+ }
+ *name = '\0';
+ while (*path == '/')
+ path++;
+ return path;
+}
+
+#ifdef LAME_READDIR
+#include <sys/param.h>
+/*
+** The static buffer in Unixware's readdir is too small.
+*/
+struct dirent *readdir(DIR *d)
+{
+ static struct dirent *buf = NULL;
+
+ if(buf == NULL)
+ buf = (struct dirent *) malloc(sizeof(struct dirent) + MAXPATHLEN);
+ return(readdir_r(d, buf));
+}
+#endif
+
+char *
+ino2name(ino_t ino, char *dir)
+{
+ DIR *dp;
+ struct dirent *ep;
+ char *name;
+
+ dp = opendir("..");
+ if (!dp)
+ fail("cannot read parent directory");
+ for (;;) {
+ if (!(ep = readdir(dp)))
+ fail("cannot find current directory");
+ if (ep->D_INO == ino)
+ break;
+ }
+ name = xstrdup(ep->d_name);
+ closedir(dp);
+ return name;
+}
+
+void *
+xmalloc(size_t size)
+{
+ void *p = malloc(size);
+ if (!p)
+ fail("cannot allocate %u bytes", size);
+ return p;
+}
+
+char *
+xstrdup(char *s)
+{
+ return strcpy(xmalloc(strlen(s) + 1), s);
+}
+
+char *
+xbasename(char *path)
+{
+ char *cp;
+
+ while ((cp = strrchr(path, '/')) && cp[1] == '\0')
+ *cp = '\0';
+ if (!cp) return path;
+ return cp + 1;
+}
+
+void
+xchdir(char *dir)
+{
+ if (chdir(dir) < 0)
+ fail("cannot change directory to %s", dir);
+}
+
+int
+relatepaths(char *from, char *to, char *outpath)
+{
+ char *cp, *cp2;
+ int len;
+ char buf[NAME_MAX];
+
+ assert(*from == '/' && *to == '/');
+ for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
+ if (*cp == '\0')
+ break;
+ while (cp[-1] != '/')
+ cp--, cp2--;
+ if (cp - 1 == to) {
+ /* closest common ancestor is /, so use full pathname */
+ len = strlen(strcpy(outpath, to));
+ if (outpath[len] != '/') {
+ outpath[len++] = '/';
+ outpath[len] = '\0';
+ }
+ } else {
+ len = 0;
+ while ((cp2 = getcomponent(cp2, buf)) != 0) {
+ strcpy(outpath + len, "../");
+ len += 3;
+ }
+ while ((cp = getcomponent(cp, buf)) != 0) {
+ sprintf(outpath + len, "%s/", buf);
+ len += strlen(outpath + len);
+ }
+ }
+ return len;
+}
+
+void
+reversepath(char *inpath, char *name, int len, char *outpath)
+{
+ char *cp, *cp2;
+ char buf[NAME_MAX];
+ struct stat sb;
+
+ cp = strcpy(outpath + PATH_MAX - (len + 1), name);
+ cp2 = inpath;
+ while ((cp2 = getcomponent(cp2, buf)) != 0) {
+ if (strcmp(buf, ".") == 0)
+ continue;
+ if (strcmp(buf, "..") == 0) {
+ if (stat(".", &sb) < 0)
+ fail("cannot stat current directory");
+ name = ino2name(sb.st_ino, "..");
+ len = strlen(name);
+ cp -= len + 1;
+ strcpy(cp, name);
+ cp[len] = '/';
+ free(name);
+ xchdir("..");
+ } else {
+ cp -= 3;
+ strncpy(cp, "../", 3);
+ xchdir(buf);
+ }
+ }
+ strcpy(outpath, cp);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.h b/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.h
new file mode 100644
index 0000000..ab1a7fe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef pathsub_h___
+#define pathsub_h___
+/*
+** Pathname subroutines.
+**
+** Brendan Eich, 8/29/95
+*/
+#include <limits.h>
+#include <sys/types.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+/*
+ * Just prevent stupidity
+ */
+#undef NAME_MAX
+#define NAME_MAX 256
+
+extern char *program;
+
+extern void fail(char *format, ...);
+extern char *getcomponent(char *path, char *name);
+extern char *ino2name(ino_t ino, char *dir);
+extern void *xmalloc(size_t size);
+extern char *xstrdup(char *s);
+extern char *xbasename(char *path);
+extern void xchdir(char *dir);
+
+/* Relate absolute pathnames from and to returning the result in outpath. */
+extern int relatepaths(char *from, char *to, char *outpath);
+
+/* XXX changes current working directory -- caveat emptor */
+extern void reversepath(char *inpath, char *name, int len, char *outpath);
+
+#endif /* pathsub_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/preprocessor.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/preprocessor.pl
new file mode 100644
index 0000000..3da6654
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/preprocessor.pl
@@ -0,0 +1,671 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil; -*-
+#
+# Preprocessor
+# Version 1.1
+#
+# Copyright (c) 2002, 2003, 2004 by Ian Hickson
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# Thanks to bryner and bsmedberg for suggestions.
+# Thanks to jon rekai for a patch to not require File::Spec 0.8.
+
+use strict;
+
+# takes as arguments the files to process
+# defaults to stdin
+# output to stdout
+
+my $stack = new stack;
+my $marker = '#';
+
+# command line arguments
+my @includes;
+while ($_ = $ARGV[0], defined($_) && /^-./) {
+ shift;
+ last if /^--$/os;
+ if (/^-D(.*)$/os) {
+ for ($1) {
+ if (/^([\w\.]+)=(.*)$/os) {
+ $stack->define($1, $2);
+ } elsif (/^([\w\.]+)$/os) {
+ $stack->define($1, 1);
+ } else {
+ die "$0: invalid argument to -D: $_\n";
+ }
+ }
+ } elsif (/^-F(.*)$/os) {
+ for ($1) {
+ if (/^(\w+)$/os) {
+ $stack->filter($1, 1);
+ } else {
+ die "$0: invalid argument to -F: $_\n";
+ }
+ }
+ } elsif (/^-I(.*)$/os) {
+ push(@includes, $1);
+ } elsif (/^-E$/os) {
+ foreach (keys %ENV) {
+ # define all variables that have valid names
+ $stack->define($_, $ENV{$_}) unless m/\W/;
+ }
+ } elsif (/^-d$/os) {
+ $stack->{'dependencies'} = 1;
+ } elsif (/^--line-endings=crlf$/os) {
+ $stack->{'lineEndings'} = "\x0D\x0A";
+ } elsif (/^--line-endings=cr$/os) {
+ $stack->{'lineEndings'} = "\x0D";
+ } elsif (/^--line-endings=lf$/os) {
+ $stack->{'lineEndings'} = "\x0A";
+ } elsif (/^--line-endings=(.+)$/os) {
+ die "$0: unrecognised line ending: $1\n";
+ } elsif (/^--marker=(.)$/os) {
+ $marker = $1;
+ } else {
+ die "$0: invalid argument: $_\n";
+ }
+}
+unshift(@ARGV, '-') unless @ARGV;
+unshift(@ARGV, @includes);
+
+# do the work
+foreach (@ARGV) { include($stack, $_); }
+exit(0);
+
+########################################################################
+
+package main;
+use File::Spec;
+use File::Spec::Unix; # on all platforms, because the #include syntax is unix-based
+
+# Note: Ideally we would use File::Spec 0.8. When this becomes
+# possible, add "0.8" to the first "use" line above, then replace
+# occurrences of "::_0_8::" with "->" below. And remove the code for
+# File::Spec 0.8 much lower down the file.
+
+sub include {
+ my($stack, $filename) = @_;
+ my $directory = $stack->{'variables'}->{'DIRECTORY'};
+ if ($filename ne '-') {
+ $filename = File::Spec::_0_8::rel2abs($filename, $directory);
+ # splitpath expects forward-slash paths on windows, so we have to
+ # change the slashes if using Activestate Perl.
+ $filename =~ s?\\?/?g if "$^O" eq "MSWin32";
+ my($volume, $path) = File::Spec::_0_8::splitpath($filename);
+ $directory = File::Spec::_0_8::catpath($volume, $path, '');
+ }
+ local $stack->{'variables'}->{'DIRECTORY'} = $directory;
+ local $stack->{'variables'}->{'FILE'} = $filename;
+ local $stack->{'variables'}->{'LINE'} = 0;
+ local *FILE;
+ open(FILE, $filename) or die "Couldn't open $filename: $!\n";
+ my $lineout = 0;
+ while (<FILE>) {
+ # on cygwin, line endings are screwed up, so normalise them.
+ s/[\x0D\x0A]+$/\n/os if ($^O eq 'msys' || $^O eq 'cygwin' || "$^O" eq "MSWin32");
+ $stack->newline;
+ if (/^\Q$marker\E([a-z]+)\n?$/os) { # argumentless processing instruction
+ process($stack, $1);
+ } elsif (/^\Q$marker\E([a-z]+)\s(.*?)\n?$/os) { # processing instruction with arguments
+ process($stack, $1, $2);
+ } elsif (/^\Q$marker\E/os) { # comment
+ # ignore it
+ } elsif ($stack->enabled) {
+ next if $stack->{'dependencies'};
+
+ # set the current line number in JavaScript if necessary
+ my $linein = $stack->{'variables'}->{'LINE'};
+ if (++$lineout != $linein) {
+ if ($filename =~ /\.js(|\.in)$/o) {
+ $stack->print("//\@line $linein \"$filename\"\n")
+ }
+ $lineout = $linein;
+ }
+
+ # print it, including any newlines
+ $stack->print(filtered($stack, $_));
+ }
+ }
+ close(FILE);
+}
+
+sub process {
+ my($stack, $instruction, @arguments) = @_;
+ my $method = 'preprocessor'->can($instruction);
+ if (not defined($method)) {
+ fatal($stack, 'unknown instruction', $instruction);
+ }
+ eval { &$method($stack, @arguments) };
+ if ($@) {
+ fatal($stack, "error evaluating $instruction:", $@);
+ }
+}
+
+sub filtered {
+ my($stack, $text) = @_;
+ foreach my $filter (sort keys %{$stack->{'filters'}}) {
+ next unless $stack->{'filters'}->{$filter};
+ my $method = 'filter'->can($filter);
+ if (not defined($method)) {
+ fatal($stack, 'unknown filter', $filter);
+ }
+ $text = eval { &$method($stack, $text) };
+ if ($@) {
+ fatal($stack, "error using $filter:", $@);
+ }
+ }
+ return $text;
+}
+
+sub fatal {
+ my $stack = shift;
+ my $filename = $stack->{'variables'}->{'FILE'};
+ local $" = ' ';
+ print STDERR "$0:$filename:$.: @_\n";
+ exit(1);
+}
+
+
+########################################################################
+
+package stack;
+
+# condition evaluated just prior to this context was false
+use constant COND_FALSE => 0;
+
+# condition evaluated just prior to this context was true
+use constant COND_TRUE => 1;
+
+# some prior condition at this level already evaluated to true (or a
+# parent condition evaluated to false or must be ignored), so we're
+# ignoring all remaining conditions at current level (and nested
+# conditions, too)
+use constant COND_COMPLETED => 2;
+
+sub new {
+ return bless {
+ 'variables' => {
+ # %ENV,
+ 'LINE' => 0, # the line number in the source file
+ 'DIRECTORY' => '', # current directory
+ 'FILE' => '', # source filename
+ '1' => 1, # for convenience (the constant '1' is thus true)
+ },
+ 'filters' => {
+ # filters
+ },
+ 'values' => [], # the value of the last condition evaluated at the nth level
+ 'lastConditionState' => [], # whether the condition in the nth-level context was true, false, or not applicable
+ 'conditionState' => COND_TRUE,
+ 'dependencies' => 0, # whether we are showing dependencies
+ 'lineEndings' => "\n", # default to platform conventions
+ };
+}
+
+sub newline {
+ my $self = shift;
+ $self->{'variables'}->{'LINE'}++;
+}
+
+sub define {
+ my $self = shift;
+ my($variable, $value) = @_;
+ die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
+ $self->{'variables'}->{$variable} = $value;
+}
+
+sub defined {
+ my $self = shift;
+ my($variable) = @_;
+ die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
+ return defined($self->{'variables'}->{$variable});
+}
+
+sub undefine {
+ my $self = shift;
+ my($variable) = @_;
+ die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
+ delete($self->{'variables'}->{$variable});
+}
+
+sub get {
+ my $self = shift;
+ my($variable, $required) = @_;
+ die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
+ my $value = $self->{'variables'}->{$variable};
+ if (defined($value)) {
+ return $value;
+ } else {
+ die "variable '$variable' is not defined\n" if $required;
+ return '';
+ }
+}
+
+sub replace {
+ my $self = shift;
+ my ($value) = @_;
+
+ ${$self->{'values'}}[-1] = $value;
+ $self->{'conditionState'} = $self->{'conditionState'} != COND_FALSE
+ ? COND_COMPLETED
+ : $value ? COND_TRUE : COND_FALSE;
+}
+
+sub push {
+ my $self = shift;
+ my($value) = @_;
+
+ push(@{$self->{'values'}}, $value);
+ my $lastCondition = $self->{'conditionState'};
+ push(@{$self->{'lastConditionState'}}, $lastCondition);
+ $self->{'conditionState'} = $lastCondition != COND_TRUE
+ ? COND_COMPLETED
+ : $value ? COND_TRUE : COND_FALSE;
+}
+
+sub pop {
+ my $self = shift;
+ $self->{'conditionState'} = pop(@{$self->{'lastConditionState'}});
+ return pop(@{$self->{'values'}});
+}
+
+sub enabled {
+ my $self = shift;
+ return $self->{'conditionState'} == COND_TRUE;
+}
+
+sub disabled {
+ my $self = shift;
+ return $self->{'conditionState'} != COND_TRUE;
+}
+
+sub filter {
+ my $self = shift;
+ my($filter, $value) = @_;
+ die "not a valid filter name: '$filter'\n" if $filter =~ m/\W/;
+ $self->{'filters'}->{$filter} = $value;
+}
+
+sub expand {
+ my $self = shift;
+ my($line) = @_;
+ $line =~ s/__(\w+)__/$self->get($1)/gose;
+ return $line;
+}
+
+sub print {
+ my $self = shift;
+ return if $self->{'dependencies'};
+ foreach my $line (@_) {
+ if (chomp $line) {
+ CORE::print("$line$self->{'lineEndings'}");
+ } else {
+ CORE::print($line);
+ }
+ }
+}
+
+sub visit {
+ my $self = shift;
+ my($filename) = @_;
+ my $directory = $stack->{'variables'}->{'DIRECTORY'};
+ $filename = File::Spec::_0_8::abs2rel(File::Spec::_0_8::rel2abs($filename, $directory));
+ CORE::print("$filename\n");
+}
+
+########################################################################
+
+package preprocessor;
+
+sub define {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ my $argument = shift;
+ for ($argument) {
+ /^(\w+)\s(.*)$/os && do {
+ return $stack->define($1, $2);
+ };
+ /^(\w+)$/os && do {
+ return $stack->define($1, 1);
+ };
+ die "invalid argument: '$_'\n";
+ }
+}
+
+sub undef {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ $stack->undefine(@_);
+}
+
+sub ifdef {
+ my $stack = shift;
+ my $variable = shift;
+ my $replace = defined(shift);
+ die "argument expected\n" unless defined($variable);
+ if ($replace) {
+ $stack->replace($stack->defined($variable));
+ } else {
+ $stack->push($stack->defined($variable));
+ }
+}
+
+sub ifndef {
+ my $stack = shift;
+ my $variable = shift;
+ my $replace = defined(shift);
+ die "argument expected\n" unless defined($variable);
+ if ($replace) {
+ $stack->replace(not $stack->defined($variable));
+ } else {
+ $stack->push(not $stack->defined($variable));
+ }
+}
+
+sub if {
+ my $stack = shift;
+ die "argument expected\n" unless @_;
+ my $argument = shift;
+ my $replace = defined(shift);
+ for ($argument) {
+ /^(\w+)==(.*)$/os && do {
+ # equality
+ if ($replace) {
+ return $stack->replace($stack->get($1) eq $2);
+ } else {
+ return $stack->push($stack->get($1) eq $2);
+ }
+ };
+ /^(\w+)!=(.*)$/os && do {
+ # inequality
+ if ($replace) {
+ return $stack->replace($stack->get($1) ne $2);
+ } else {
+ return $stack->push($stack->get($1) ne $2);
+ }
+ };
+ /^(\w+)$/os && do {
+ # true value
+ if ($replace) {
+ return $stack->replace($stack->get($1));
+ } else {
+ return $stack->push($stack->get($1));
+ }
+ };
+ /^!(\w+)$/os && do {
+ # false value
+ if ($replace) {
+ return $stack->replace(not $stack->get($1));
+ } else {
+ return $stack->push(not $stack->get($1));
+ }
+ };
+ die "invalid argument: '$_'\n";
+ }
+}
+
+sub else {
+ my $stack = shift;
+ die "argument unexpected\n" if @_;
+ $stack->replace(1);
+}
+
+sub elif {
+ my $stack = shift;
+ die "argument expected\n" unless @_;
+ &if($stack, @_, 1);
+}
+
+sub elifdef {
+ my $stack = shift;
+ die "argument expected\n" unless @_;
+ &ifdef($stack, @_, 1);
+}
+
+sub elifndef {
+ my $stack = shift;
+ die "argument expected\n" unless @_;
+ &ifndef($stack, @_, 1);
+}
+
+sub endif {
+ my $stack = shift;
+ die "argument unexpected\n" if @_;
+ $stack->pop;
+}
+
+sub error {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ my $line = $stack->expand(@_);
+ die "$line\n";
+}
+
+sub expand {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ my $line = $stack->expand(@_);
+ $stack->print("$line\n");
+}
+
+sub literal {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ my $line = shift;
+ $stack->print("$line\n");
+}
+
+sub include {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ my $filename = File::Spec::_0_8::catpath(File::Spec::_0_8::splitpath(@_));
+ if ($stack->{'dependencies'}) {
+ $stack->visit($filename);
+ } else {
+ main::include($stack, $filename);
+ }
+}
+
+sub includesubst {
+ my ($stack, $filename) = @_;
+ return if $stack->disabled;
+ die "argument expected\n" unless $filename;
+ $filename =~ s/@(\w+)@/$stack->get($1, 1)/gose;
+ $filename = File::Spec::_0_8::catpath(File::Spec::_0_8::splitpath($filename));
+ if ($stack->{'dependencies'}) {
+ $stack->visit($filename);
+ } else {
+ main::include($stack, $filename);
+ }
+}
+
+sub filter {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ foreach (split(/\s/os, shift)) {
+ $stack->filter($_, 1);
+ }
+}
+
+sub unfilter {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ foreach (split(/\s/os, shift)) {
+ $stack->filter($_, 0);
+ }
+}
+
+
+########################################################################
+
+package filter;
+
+sub emptyLines {
+ my($stack, $text) = @_;
+ $text = "" if $text eq "\n";
+ return $text;
+}
+
+sub spaces {
+ my($stack, $text) = @_;
+ $text =~ s/ +/ /gos; # middle spaces
+ $text =~ s/^ //gos; # start spaces
+ $text =~ s/ (\n?)$/$1/gos; # end spaces
+ return $text;
+}
+
+sub slashslash {
+ my($stack, $text) = @_;
+ $text =~ s|//.*?(\n?)$|$1|gos;
+ return $text;
+}
+
+sub substitution {
+ my($stack, $text) = @_;
+ $text =~ s/@(\w+)@/$stack->get($1, 1)/gose;
+ return $text;
+}
+
+sub attemptSubstitution {
+ my($stack, $text) = @_;
+ $text =~ s/@(\w+)@/$stack->get($1, 0)/gose;
+ return $text;
+}
+
+########################################################################
+
+########################################################################
+# This code is from File::Spec::Unix 0.8.
+# It is not considered a part of the preprocessor.pl source file
+# This code is licensed under the same license as File::Spec itself.
+
+package File::Spec::_0_8;
+
+use Cwd;
+
+sub rel2abs {
+ my ($path, $base) = @_;
+ if ( ! File::Spec->file_name_is_absolute( $path ) ) {
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = cwd() ;
+ } elsif ( ! File::Spec->file_name_is_absolute( $base ) ) {
+ $base = rel2abs( $base );
+ } else {
+ $base = File::Spec->canonpath( $base );
+ }
+ $path = File::Spec->catdir( $base, $path );
+ }
+ return File::Spec->canonpath( $path );
+}
+
+sub splitdir {
+ return split m|/|, $_[1], -1; # Preserve trailing fields
+}
+
+sub splitpath {
+ my ($path, $nofile) = @_;
+
+ my ($volume,$directory,$file) = ('','','');
+
+ if ( $nofile ) {
+ $directory = $path;
+ }
+ else {
+ $path =~ m|^ ( (?: .* / (?: \.\.?\Z(?!\n) )? )? ) ([^/]*) |xs;
+ $directory = $1;
+ $file = $2;
+ }
+
+ return ($volume,$directory,$file);
+}
+
+sub catpath {
+ my ($volume,$directory,$file) = @_;
+
+ if ( $directory ne '' &&
+ $file ne '' &&
+ substr( $directory, -1 ) ne '/' &&
+ substr( $file, 0, 1 ) ne '/'
+ ) {
+ $directory .= "/$file" ;
+ }
+ else {
+ $directory .= $file ;
+ }
+
+ return $directory ;
+}
+
+sub abs2rel {
+ my($path,$base) = @_;
+
+ # Clean up $path
+ if ( ! File::Spec->file_name_is_absolute( $path ) ) {
+ $path = rel2abs( $path ) ;
+ }
+ else {
+ $path = File::Spec->canonpath( $path ) ;
+ }
+
+ # Figure out the effective $base and clean it up.
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = cwd();
+ }
+ elsif ( ! File::Spec->file_name_is_absolute( $base ) ) {
+ $base = rel2abs( $base ) ;
+ }
+ else {
+ $base = File::Spec->canonpath( $base ) ;
+ }
+
+ # Now, remove all leading components that are the same
+ my @pathchunks = File::Spec::_0_8::splitdir( $path);
+ my @basechunks = File::Spec::_0_8::splitdir( $base);
+
+ while (@pathchunks && @basechunks && $pathchunks[0] eq $basechunks[0]) {
+ shift @pathchunks ;
+ shift @basechunks ;
+ }
+
+ $path = CORE::join( '/', @pathchunks );
+ $base = CORE::join( '/', @basechunks );
+
+ # $base now contains the directories the resulting relative path
+ # must ascend out of before it can descend to $path_directory. So,
+ # replace all names with $parentDir
+ $base =~ s|[^/]+|..|g ;
+
+ # Glue the two together, using a separator if necessary, and preventing an
+ # empty result.
+ if ( $path ne '' && $base ne '' ) {
+ $path = "$base/$path" ;
+ } else {
+ $path = "$base$path" ;
+ }
+
+ return File::Spec->canonpath( $path ) ;
+}
+
+# End code from File::Spec::Unix 0.8.
+########################################################################
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth-nt.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth-nt.pl
new file mode 100644
index 0000000..8853268
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth-nt.pl
@@ -0,0 +1,48 @@
+#! perl
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+require "/ns/config/fastcwd.pl";
+
+$cur = &fastcwd;
+chdir($ARGV[0]);
+$newcur = &fastcwd;
+$newcurlen = length($newcur);
+
+# Skip common separating / unless $newcur is "/"
+$cur = substr($cur, $newcurlen + ($newcurlen > 1));
+print $cur;
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth.pl
new file mode 100644
index 0000000..3ec4272
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth.pl
@@ -0,0 +1,51 @@
+#! perl
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+unshift(@INC, '/usr/lib/perl');
+unshift(@INC, '/usr/local/lib/perl');
+
+require "fastcwd.pl";
+
+$cur = &fastcwd;
+chdir($ARGV[0]);
+$newcur = &fastcwd;
+$newcurlen = length($newcur);
+
+# Skip common separating / unless $newcur is "/"
+$cur = substr($cur, $newcurlen + ($newcurlen > 1));
+print $cur;
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/rules.mk b/tools/node_modules/expresso/deps/jscoverage/js/config/rules.mk
new file mode 100644
index 0000000..6168216
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/rules.mk
@@ -0,0 +1,2269 @@
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Chase Phillips <chase@mozilla.org>
+# Benjamin Smedberg <benjamin@smedbergs.us>
+# Jeff Walden <jwalden+code@mit.edu>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+NO_DIST_INSTALL = 1
+
+ifndef topsrcdir
+topsrcdir = $(DEPTH)
+endif
+
+ifndef MOZILLA_DIR
+MOZILLA_DIR = $(topsrcdir)
+endif
+
+ifndef INCLUDED_CONFIG_MK
+include $(topsrcdir)/config/config.mk
+endif
+
+ifndef INCLUDED_VERSION_MK
+include $(topsrcdir)/config/version.mk
+endif
+
+REPORT_BUILD = @echo $(notdir $<)
+
+ifeq ($(OS_ARCH),OS2)
+EXEC =
+else
+EXEC = exec
+endif
+
+# ELOG prints out failed command when building silently (gmake -s).
+ifneq (,$(findstring -s,$(MAKEFLAGS)))
+ ELOG := $(EXEC) sh $(BUILD_TOOLS)/print-failed-commands.sh
+else
+ ELOG :=
+endif
+
+ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
+ifndef GNU_CC
+_LIBNAME_RELATIVE_PATHS=1
+endif
+endif
+
+ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
+PWD := $(shell pwd)
+_VPATH_SRCS = $(if $(filter /%,$<),$<,$(PWD)/$<)
+else
+_VPATH_SRCS = $<
+endif
+
+# Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed
+VPATH += $(DIST)/lib
+ifdef LIBXUL_SDK
+VPATH += $(LIBXUL_SDK)/lib
+endif
+
+# EXPAND_LIBNAME - $(call EXPAND_LIBNAME,foo)
+# expands to foo.lib on platforms with import libs and -lfoo otherwise
+
+# EXPAND_LIBNAME_PATH - $(call EXPAND_LIBNAME_PATH,foo,dir)
+# expands to dir/foo.lib on platforms with import libs and
+# -Ldir -lfoo otherwise
+
+# EXPAND_MOZLIBNAME - $(call EXPAND_MOZLIBNAME,foo)
+# expands to $(DIST)/lib/foo.lib on platforms with import libs and
+# -lfoo otherwise
+
+ifdef _LIBNAME_RELATIVE_PATHS
+EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+else
+EXPAND_LIBNAME = $(addprefix -l,$(1))
+EXPAND_LIBNAME_PATH = -L$(2) $(addprefix -l,$(1))
+EXPAND_MOZLIBNAME = $(addprefix -l,$(1))
+endif
+
+ifdef EXTRA_DSO_LIBS
+EXTRA_DSO_LIBS := $(call EXPAND_MOZLIBNAME,$(EXTRA_DSO_LIBS))
+endif
+
+#
+# Library rules
+#
+# If BUILD_STATIC_LIBS or FORCE_STATIC_LIB is set, build a static library.
+# Otherwise, build a shared library.
+#
+
+ifndef LIBRARY
+ifdef LIBRARY_NAME
+ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
+ifdef SHORT_LIBNAME
+LIBRARY_NAME := $(SHORT_LIBNAME)
+endif
+endif
+LIBRARY := $(LIB_PREFIX)$(LIBRARY_NAME).$(LIB_SUFFIX)
+endif
+endif
+
+ifndef HOST_LIBRARY
+ifdef HOST_LIBRARY_NAME
+HOST_LIBRARY := $(LIB_PREFIX)$(HOST_LIBRARY_NAME).$(LIB_SUFFIX)
+endif
+endif
+
+ifdef LIBRARY
+ifneq (_1,$(FORCE_SHARED_LIB)_$(BUILD_STATIC_LIBS))
+ifdef MKSHLIB
+
+ifdef LIB_IS_C_ONLY
+MKSHLIB = $(MKCSHLIB)
+endif
+
+ifdef MAKE_FRAMEWORK
+SHARED_LIBRARY := $(LIBRARY_NAME)
+else
+SHARED_LIBRARY := $(DLL_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX)
+endif
+
+ifeq ($(OS_ARCH),OS2)
+DEF_FILE := $(SHARED_LIBRARY:.dll=.def)
+endif
+
+ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
+IMPORT_LIBRARY := $(LIB_PREFIX)$(LIBRARY_NAME).$(IMPORT_LIB_SUFFIX)
+endif
+
+ifdef MOZ_ENABLE_LIBXUL
+EMBED_MANIFEST_AT=2
+endif
+
+endif # MKSHLIB
+endif # FORCE_SHARED_LIB && !BUILD_STATIC_LIBS
+endif # LIBRARY
+
+ifeq (,$(BUILD_STATIC_LIBS)$(FORCE_STATIC_LIB))
+LIBRARY := $(NULL)
+endif
+
+ifeq (_1,$(FORCE_SHARED_LIB)_$(BUILD_STATIC_LIBS))
+SHARED_LIBRARY := $(NULL)
+DEF_FILE := $(NULL)
+IMPORT_LIBRARY := $(NULL)
+endif
+
+ifdef FORCE_STATIC_LIB
+ifndef FORCE_SHARED_LIB
+SHARED_LIBRARY := $(NULL)
+DEF_FILE := $(NULL)
+IMPORT_LIBRARY := $(NULL)
+endif
+endif
+
+ifdef FORCE_SHARED_LIB
+ifndef FORCE_STATIC_LIB
+LIBRARY := $(NULL)
+endif
+endif
+
+ifdef JAVA_LIBRARY_NAME
+JAVA_LIBRARY := $(JAVA_LIBRARY_NAME).jar
+endif
+
+ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
+ifndef GNU_CC
+
+#
+# All C++ files share a PDB file per directory. For parallel builds, this PDB
+# file is shared and locked by MSPDBSRV.EXE, starting with MSVC8 SP1. If
+# you're using MSVC 7.1 or MSVC8 without SP1, don't do parallel builds.
+#
+# The final PDB for libraries and programs is created by the linker and uses
+# a different name from the single PDB file created by the compiler. See
+# bug 462740.
+#
+COMPILE_PDBFILE = generated.pdb
+LINK_PDBFILE = $(basename $(@F)).pdb
+ifdef MOZ_DEBUG
+CODFILE=$(basename $(@F)).cod
+endif
+
+ifdef MOZ_MAPINFO
+ifdef LIBRARY_NAME
+MAPFILE=$(LIBRARY_NAME).map
+else
+MAPFILE=$(basename $(@F)).map
+endif # LIBRARY_NAME
+endif # MOZ_MAPINFO
+
+ifdef DEFFILE
+OS_LDFLAGS += -DEF:$(DEFFILE)
+EXTRA_DEPS += $(DEFFILE)
+endif
+
+ifdef MAPFILE
+OS_LDFLAGS += -MAP:$(MAPFILE)
+#CFLAGS += -Fm$(MAPFILE)
+#CXXFLAGS += -Fm$(MAPFILE)
+endif
+
+#ifdef CODFILE
+#CFLAGS += -Fa$(CODFILE) -FAsc
+#CFLAGS += -Fa$(CODFILE) -FAsc
+#endif
+
+endif # !GNU_CC
+
+ifdef ENABLE_CXX_EXCEPTIONS
+ifdef GNU_CC
+CXXFLAGS += -fexceptions
+else
+ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER)))
+CXXFLAGS += -GX
+else
+CXXFLAGS += -EHsc
+endif # _MSC_VER
+endif # GNU_CC
+endif # ENABLE_CXX_EXCEPTIONS
+endif # WINNT
+
+ifeq (,$(filter-out WINNT WINCE,$(HOST_OS_ARCH)))
+HOST_PDBFILE=$(basename $(@F)).pdb
+endif
+
+ifndef TARGETS
+TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
+endif
+
+ifndef OBJS
+_OBJS = \
+ $(JRI_STUB_CFILES) \
+ $(addsuffix .$(OBJ_SUFFIX), $(JMC_GEN)) \
+ $(CSRCS:.c=.$(OBJ_SUFFIX)) \
+ $(patsubst %.cc,%.$(OBJ_SUFFIX),$(CPPSRCS:.cpp=.$(OBJ_SUFFIX))) \
+ $(CMSRCS:.m=.$(OBJ_SUFFIX)) \
+ $(CMMSRCS:.mm=.$(OBJ_SUFFIX)) \
+ $(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX))
+OBJS = $(strip $(_OBJS))
+endif
+
+ifndef HOST_OBJS
+_HOST_OBJS = \
+ $(addprefix host_,$(HOST_CSRCS:.c=.$(OBJ_SUFFIX))) \
+ $(addprefix host_,$(patsubst %.cc,%.$(OBJ_SUFFIX),$(HOST_CPPSRCS:.cpp=.$(OBJ_SUFFIX)))) \
+ $(addprefix host_,$(HOST_CMSRCS:.m=.$(OBJ_SUFFIX))) \
+ $(addprefix host_,$(HOST_CMMSRCS:.mm=.$(OBJ_SUFFIX)))
+HOST_OBJS = $(strip $(_HOST_OBJS))
+endif
+
+LIBOBJS := $(addprefix \", $(OBJS))
+LIBOBJS := $(addsuffix \", $(LIBOBJS))
+
+ifndef MOZ_AUTO_DEPS
+ifneq (,$(OBJS)$(XPIDLSRCS)$(SDK_XPIDLSRCS)$(SIMPLE_PROGRAMS))
+MDDEPFILES = $(addprefix $(MDDEPDIR)/,$(OBJS:.$(OBJ_SUFFIX)=.pp))
+ifndef NO_GEN_XPT
+MDDEPFILES += $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.xpt)) \
+ $(addprefix $(MDDEPDIR)/,$(SDK_XPIDLSRCS:.idl=.xpt))
+endif
+endif
+endif
+
+ALL_TRASH = \
+ $(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
+ $(filter-out $(ASFILES),$(OBJS:.$(OBJ_SUFFIX)=.s)) $(OBJS:.$(OBJ_SUFFIX)=.ii) \
+ $(OBJS:.$(OBJ_SUFFIX)=.i) \
+ $(HOST_PROGOBJS) $(HOST_OBJS) $(IMPORT_LIBRARY) $(DEF_FILE)\
+ $(EXE_DEF_FILE) so_locations _gen _stubs $(wildcard *.res) $(wildcard *.RES) \
+ $(wildcard *.pdb) $(CODFILE) $(MAPFILE) $(IMPORT_LIBRARY) \
+ $(SHARED_LIBRARY:$(DLL_SUFFIX)=.exp) $(wildcard *.ilk) \
+ $(PROGRAM:$(BIN_SUFFIX)=.exp) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.exp) \
+ $(PROGRAM:$(BIN_SUFFIX)=.lib) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.lib) \
+ $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.$(OBJ_SUFFIX)) \
+ $(wildcard gts_tmp_*) $(LIBRARY:%.a=.%.timestamp)
+ALL_TRASH_DIRS = \
+ $(GARBAGE_DIRS) /no-such-file
+
+ifdef QTDIR
+GARBAGE += $(MOCSRCS)
+endif
+
+ifdef SIMPLE_PROGRAMS
+GARBAGE += $(SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX))
+endif
+
+ifdef HOST_SIMPLE_PROGRAMS
+GARBAGE += $(HOST_SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX))
+endif
+
+#
+# the Solaris WorkShop template repository cache. it occasionally can get
+# out of sync, so targets like clobber should kill it.
+#
+ifeq ($(OS_ARCH),SunOS)
+ifeq ($(GNU_CXX),)
+GARBAGE_DIRS += SunWS_cache
+endif
+endif
+
+ifeq ($(OS_ARCH),OpenVMS)
+GARBAGE += $(wildcard *.*_defines)
+ifdef SHARED_LIBRARY
+VMS_SYMVEC_FILE = $(SHARED_LIBRARY:$(DLL_SUFFIX)=_symvec.opt)
+ifdef MOZ_DEBUG
+VMS_SYMVEC_FILE_MODULE = $(topsrcdir)/build/unix/vms/$(notdir $(SHARED_LIBRARY:$(DLL_SUFFIX)=_dbg_symvec.opt))
+else
+VMS_SYMVEC_FILE_MODULE = $(topsrcdir)/build/unix/vms/$(notdir $(SHARED_LIBRARY:$(DLL_SUFFIX)=_symvec.opt))
+endif
+VMS_SYMVEC_FILE_COMP = $(topsrcdir)/build/unix/vms/component_symvec.opt
+GARBAGE += $(VMS_SYMVEC_FILE)
+ifdef IS_COMPONENT
+DSO_LDOPTS := $(filter-out -auto_symvec,$(DSO_LDOPTS)) $(VMS_SYMVEC_FILE)
+endif
+endif
+endif
+
+XPIDL_GEN_DIR = _xpidlgen
+
+ifdef MOZ_UPDATE_XTERM
+# Its good not to have a newline at the end of the titlebar string because it
+# makes the make -s output easier to read. Echo -n does not work on all
+# platforms, but we can trick sed into doing it.
+UPDATE_TITLE = sed -e "s!Y!$@ in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$(dir)!" $(MOZILLA_DIR)/config/xterm.str;
+UPDATE_TITLE_export = sed -e "s!Y!export in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$*!" $(MOZILLA_DIR)/config/xterm.str;
+UPDATE_TITLE_libs = sed -e "s!Y!libs in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$*!" $(MOZILLA_DIR)/config/xterm.str;
+UPDATE_TITLE_tools = sed -e "s!Y!tools in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$*!" $(MOZILLA_DIR)/config/xterm.str;
+endif
+
+LOOP_OVER_DIRS = \
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(DIRS),$(UPDATE_TITLE) $(MAKE) -C $(dir) $@; ) true
+
+# we only use this for the makefiles target and other stuff that doesn't matter
+LOOP_OVER_PARALLEL_DIRS = \
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(PARALLEL_DIRS),$(UPDATE_TITLE) $(MAKE) -C $(dir) $@; ) true
+
+LOOP_OVER_STATIC_DIRS = \
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(STATIC_DIRS),$(UPDATE_TITLE) $(MAKE) -C $(dir) $@; ) true
+
+LOOP_OVER_TOOL_DIRS = \
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(TOOL_DIRS),$(UPDATE_TITLE) $(MAKE) -C $(dir) $@; ) true
+
+ifdef PARALLEL_DIRS
+# create a bunch of fake targets for order-only processing
+PARALLEL_DIRS_export = $(addsuffix _export,$(PARALLEL_DIRS))
+PARALLEL_DIRS_libs = $(addsuffix _libs,$(PARALLEL_DIRS))
+PARALLEL_DIRS_tools = $(addsuffix _tools,$(PARALLEL_DIRS))
+
+.PHONY: $(PARALLEL_DIRS_export) $(PARALLEL_DIRS_libs) $(PARALLEL_DIRS_tools)
+endif
+
+#
+# Now we can differentiate between objects used to build a library, and
+# objects used to build an executable in the same directory.
+#
+ifndef PROGOBJS
+PROGOBJS = $(OBJS)
+endif
+
+ifndef HOST_PROGOBJS
+HOST_PROGOBJS = $(HOST_OBJS)
+endif
+
+# MAKE_DIRS: List of directories to build while looping over directories.
+# A Makefile that needs $(MDDEPDIR) created but doesn't set any of these
+# variables we know to check can just set NEED_MDDEPDIR explicitly.
+ifneq (,$(OBJS)$(XPIDLSRCS)$(SDK_XPIDLSRCS)$(SIMPLE_PROGRAMS)$(NEED_MDDEPDIR))
+MAKE_DIRS += $(CURDIR)/$(MDDEPDIR)
+GARBAGE_DIRS += $(MDDEPDIR)
+endif
+
+#
+# Tags: emacs (etags), vi (ctags)
+# TAG_PROGRAM := ctags -L -
+#
+TAG_PROGRAM = xargs etags -a
+
+#
+# Turn on C++ linking if we have any .cpp or .mm files
+# (moved this from config.mk so that config.mk can be included
+# before the CPPSRCS are defined)
+#
+ifneq ($(CPPSRCS)$(CMMSRCS),)
+CPP_PROG_LINK = 1
+endif
+
+#
+# Make sure to wrap static libs inside linker specific flags to turn on & off
+# inclusion of all symbols inside the static libs
+#
+ifndef NO_LD_ARCHIVE_FLAGS
+ifdef SHARED_LIBRARY_LIBS
+EXTRA_DSO_LDOPTS := $(MKSHLIB_FORCE_ALL) $(SHARED_LIBRARY_LIBS) $(MKSHLIB_UNFORCE_ALL) $(EXTRA_DSO_LDOPTS)
+endif
+endif
+
+#
+# This will strip out symbols that the component should not be
+# exporting from the .dynsym section.
+#
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS)
+endif # IS_COMPONENT
+
+#
+# Enforce the requirement that MODULE_NAME must be set
+# for components in static builds
+#
+ifdef IS_COMPONENT
+ifdef EXPORT_LIBRARY
+ifndef FORCE_SHARED_LIB
+ifndef MODULE_NAME
+$(error MODULE_NAME is required for components which may be used in static builds)
+endif
+endif
+endif
+endif
+
+#
+# MacOS X specific stuff
+#
+
+ifeq ($(OS_ARCH),Darwin)
+ifdef SHARED_LIBRARY
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -bundle
+else
+EXTRA_DSO_LDOPTS += -dynamiclib -install_name @executable_path/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module
+endif
+endif
+endif
+
+#
+# On NetBSD a.out systems, use -Bsymbolic. This fixes what would otherwise be
+# fatal symbol name clashes between components.
+#
+ifeq ($(OS_ARCH),NetBSD)
+ifeq ($(DLL_SUFFIX),.so.1.0)
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+endif
+endif
+endif
+
+ifeq ($(OS_ARCH),FreeBSD)
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+endif
+endif
+
+ifeq ($(OS_ARCH),NetBSD)
+ifneq (,$(filter arc cobalt hpcmips mipsco newsmips pmax sgimips,$(OS_TEST)))
+ifeq ($(MODULE),layout)
+OS_CFLAGS += -Wa,-xgot
+OS_CXXFLAGS += -Wa,-xgot
+endif
+endif
+endif
+
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(filter mips mipsel,$(OS_TEST)))
+ifeq ($(MODULE),layout)
+OS_CFLAGS += -Wa,-xgot
+OS_CXXFLAGS += -Wa,-xgot
+endif
+endif
+endif
+
+#
+# HP-UXBeOS specific section: for COMPONENTS only, add -Bsymbolic flag
+# which uses internal symbols first
+#
+ifeq ($(OS_ARCH),HP-UX)
+ifdef IS_COMPONENT
+ifeq ($(GNU_CC)$(GNU_CXX),)
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+ifneq ($(HAS_EXTRAEXPORTS),1)
+MKSHLIB += -Wl,+eNSGetModule -Wl,+eerrno
+MKCSHLIB += +eNSGetModule +eerrno
+ifneq ($(OS_TEST),ia64)
+MKSHLIB += -Wl,+e_shlInit
+MKCSHLIB += +e_shlInit
+endif # !ia64
+endif # !HAS_EXTRAEXPORTS
+endif # non-gnu compilers
+endif # IS_COMPONENT
+endif # HP-UX
+
+ifeq ($(OS_ARCH),AIX)
+ifdef IS_COMPONENT
+ifneq ($(HAS_EXTRAEXPORTS),1)
+MKSHLIB += -bE:$(MOZILLA_DIR)/build/unix/aix.exp -bnoexpall
+MKCSHLIB += -bE:$(MOZILLA_DIR)/build/unix/aix.exp -bnoexpall
+endif # HAS_EXTRAEXPORTS
+endif # IS_COMPONENT
+endif # AIX
+
+#
+# OSF1: add -B symbolic flag for components
+#
+ifeq ($(OS_ARCH),OSF1)
+ifdef IS_COMPONENT
+ifeq ($(GNU_CC)$(GNU_CXX),)
+EXTRA_DSO_LDOPTS += -B symbolic
+endif
+endif
+endif
+
+#
+# Linux: add -Bsymbolic flag for components
+#
+ifeq ($(OS_ARCH),Linux)
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+endif
+endif
+
+#
+# MINGW32
+#
+ifeq ($(OS_ARCH),WINNT)
+ifdef GNU_CC
+ifndef IS_COMPONENT
+DSO_LDOPTS += -Wl,--out-implib -Wl,$(IMPORT_LIBRARY)
+endif
+endif
+endif
+
+ifeq ($(USE_TVFS),1)
+IFLAGS1 = -rb
+IFLAGS2 = -rb
+else
+IFLAGS1 = -m 644
+IFLAGS2 = -m 755
+endif
+
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+OUTOPTION = -Fo# eol
+else
+OUTOPTION = -o # eol
+endif # WINNT && !GNU_CC
+ifneq (,$(filter WINCE,$(OS_ARCH)))
+OUTOPTION = -Fo# eol
+endif
+
+ifeq ($(OS_TARGET), WINCE)
+OUTOPTION = -Fo# eol
+HOST_OUTOPTION = -Fo# eol
+else
+
+ifeq (,$(CROSS_COMPILE))
+HOST_OUTOPTION = $(OUTOPTION)
+else
+HOST_OUTOPTION = -o # eol
+endif
+
+endif
+################################################################################
+
+# SUBMAKEFILES: List of Makefiles for next level down.
+# This is used to update or create the Makefiles before invoking them.
+SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS))
+
+# The root makefile doesn't want to do a plain export/libs, because
+# of the tiers and because of libxul. Suppress the default rules in favor
+# of something else. Makefiles which use this var *must* provide a sensible
+# default rule before including rules.mk
+ifndef SUPPRESS_DEFAULT_RULES
+ifdef TIERS
+
+DIRS += $(foreach tier,$(TIERS),$(tier_$(tier)_dirs))
+STATIC_DIRS += $(foreach tier,$(TIERS),$(tier_$(tier)_staticdirs))
+
+default all alldep::
+ $(EXIT_ON_ERROR) \
+ $(foreach tier,$(TIERS),$(MAKE) tier_$(tier); ) true
+
+else
+
+default all::
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(STATIC_DIRS),$(MAKE) -C $(dir); ) true
+ $(MAKE) export
+ $(MAKE) libs
+ $(MAKE) tools
+
+# Do depend as well
+alldep::
+ $(MAKE) export
+ $(MAKE) depend
+ $(MAKE) libs
+ $(MAKE) tools
+
+endif # TIERS
+endif # SUPPRESS_DEFAULT_RULES
+
+ifeq ($(filter s,$(MAKEFLAGS)),)
+ECHO := echo
+QUIET :=
+else
+ECHO := true
+QUIET := -q
+endif
+
+MAKE_TIER_SUBMAKEFILES = +$(if $(tier_$*_dirs),$(MAKE) $(addsuffix /Makefile,$(tier_$*_dirs)))
+
+export_tier_%:
+ @$(ECHO) "$@"
+ @$(MAKE_TIER_SUBMAKEFILES)
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(tier_$*_dirs),$(MAKE) -C $(dir) export; ) true
+
+libs_tier_%:
+ @$(ECHO) "$@"
+ @$(MAKE_TIER_SUBMAKEFILES)
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(tier_$*_dirs),$(MAKE) -C $(dir) libs; ) true
+
+tools_tier_%:
+ @$(ECHO) "$@"
+ @$(MAKE_TIER_SUBMAKEFILES)
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(tier_$*_dirs),$(MAKE) -C $(dir) tools; ) true
+
+$(foreach tier,$(TIERS),tier_$(tier))::
+ @$(ECHO) "$@: $($@_staticdirs) $($@_dirs)"
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$($@_staticdirs),$(MAKE) -C $(dir); ) true
+ $(MAKE) export_$@
+ $(MAKE) libs_$@
+
+# Do everything from scratch
+everything::
+ $(MAKE) clean
+ $(MAKE) alldep
+
+# Add dummy depend target for tinderboxes
+depend::
+
+ifdef ALL_PLATFORMS
+all_platforms:: $(NFSPWD)
+ @d=`$(NFSPWD)`; \
+ if test ! -d LOGS; then rm -rf LOGS; mkdir LOGS; else true; fi; \
+ for h in $(PLATFORM_HOSTS); do \
+ echo "On $$h: $(MAKE) $(ALL_PLATFORMS) >& LOGS/$$h.log";\
+ rsh $$h -n "(chdir $$d; \
+ $(MAKE) $(ALL_PLATFORMS) >& LOGS/$$h.log; \
+ echo DONE) &" 2>&1 > LOGS/$$h.pid & \
+ sleep 1; \
+ done
+
+$(NFSPWD):
+ cd $(@D); $(MAKE) $(@F)
+endif
+
+# Target to only regenerate makefiles
+makefiles: $(SUBMAKEFILES)
+ifneq (,$(DIRS)$(TOOL_DIRS)$(PARALLEL_DIRS))
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+endif
+
+ifdef PARALLEL_DIRS
+export:: $(PARALLEL_DIRS_export)
+
+$(PARALLEL_DIRS_export): %_export: %/Makefile
+ +@$(UPDATE_TITLE_export) $(MAKE) -C $* export
+endif
+
+export:: $(SUBMAKEFILES) $(MAKE_DIRS) $(if $(EXPORTS)$(XPIDLSRCS)$(SDK_HEADERS)$(SDK_XPIDLSRCS),$(PUBLIC)) $(if $(SDK_HEADERS)$(SDK_XPIDLSRCS),$(SDK_PUBLIC)) $(if $(XPIDLSRCS),$(IDL_DIR)) $(if $(SDK_XPIDLSRCS),$(SDK_IDL_DIR))
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+
+ifdef PARALLEL_DIRS
+tools:: $(PARALLEL_DIRS_tools)
+
+$(PARALLEL_DIRS_tools): %_tools: %/Makefile
+ +@$(UPDATE_TITLE_tools) $(MAKE) -C $* tools
+endif
+
+tools:: $(SUBMAKEFILES) $(MAKE_DIRS)
+ +$(LOOP_OVER_DIRS)
+ifdef TOOL_DIRS
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(TOOL_DIRS),$(UPDATE_TITLE) $(MAKE) -C $(dir) libs; ) true
+endif
+
+#
+# Rule to create list of libraries for final link
+#
+export::
+ifdef LIBRARY_NAME
+ifdef EXPORT_LIBRARY
+ifdef IS_COMPONENT
+ifdef BUILD_STATIC_LIBS
+ @$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMPS) $(LIBRARY_NAME)
+ifdef MODULE_NAME
+ @$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMP_NAMES) $(MODULE_NAME)
+endif
+endif
+else
+ $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_LIBS) $(LIBRARY_NAME)
+endif # IS_COMPONENT
+endif # EXPORT_LIBRARY
+endif # LIBRARY_NAME
+
+# Create dependencies on static (and shared EXTRA_DSO_LIBS) libraries
+LIBS_DEPS = $(filter %.$(LIB_SUFFIX), $(LIBS))
+HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX), $(HOST_LIBS))
+DSO_LDOPTS_DEPS = $(EXTRA_DSO_LIBS) $(filter %.$(LIB_SUFFIX), $(EXTRA_DSO_LDOPTS))
+
+##############################################
+ifdef PARALLEL_DIRS
+libs:: $(PARALLEL_DIRS_libs)
+
+$(PARALLEL_DIRS_libs): %_libs: %/Makefile
+ +@$(UPDATE_TITLE_libs) $(MAKE) -C $* libs
+endif
+
+libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
+ifndef NO_DIST_INSTALL
+ifdef LIBRARY
+ifdef EXPORT_LIBRARY # Stage libs that will be linked into a static build
+ifdef IS_COMPONENT
+ $(INSTALL) $(IFLAGS1) $(LIBRARY) $(DEPTH)/staticlib/components
+else
+ $(INSTALL) $(IFLAGS1) $(LIBRARY) $(DEPTH)/staticlib
+endif
+endif # EXPORT_LIBRARY
+ifdef DIST_INSTALL
+ifdef IS_COMPONENT
+ $(error Shipping static component libs makes no sense.)
+else
+ $(INSTALL) $(IFLAGS1) $(LIBRARY) $(DIST)/lib
+endif
+endif # DIST_INSTALL
+endif # LIBRARY
+ifdef SHARED_LIBRARY
+ifdef IS_COMPONENT
+ $(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
+ $(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
+ifdef BEOS_ADDON_WORKAROUND
+ ( cd $(FINAL_TARGET)/components && $(CC) -nostart -o $(SHARED_LIBRARY).stub $(SHARED_LIBRARY) )
+endif
+else # ! IS_COMPONENT
+ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
+ $(INSTALL) $(IFLAGS2) $(IMPORT_LIBRARY) $(DIST)/lib
+else
+ $(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DIST)/lib
+endif
+ $(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)
+ifdef BEOS_ADDON_WORKAROUND
+ ( cd $(FINAL_TARGET) && $(CC) -nostart -o $(SHARED_LIBRARY).stub $(SHARED_LIBRARY) )
+endif
+endif # IS_COMPONENT
+endif # SHARED_LIBRARY
+ifdef PROGRAM
+ $(INSTALL) $(IFLAGS2) $(PROGRAM) $(FINAL_TARGET)
+endif
+ifdef SIMPLE_PROGRAMS
+ $(INSTALL) $(IFLAGS2) $(SIMPLE_PROGRAMS) $(FINAL_TARGET)
+endif
+ifdef HOST_PROGRAM
+ $(INSTALL) $(IFLAGS2) $(HOST_PROGRAM) $(DIST)/host/bin
+endif
+ifdef HOST_SIMPLE_PROGRAMS
+ $(INSTALL) $(IFLAGS2) $(HOST_SIMPLE_PROGRAMS) $(DIST)/host/bin
+endif
+ifdef HOST_LIBRARY
+ $(INSTALL) $(IFLAGS1) $(HOST_LIBRARY) $(DIST)/host/lib
+endif
+ifdef JAVA_LIBRARY
+ifdef IS_COMPONENT
+ $(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)/components
+else
+ $(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)
+endif
+endif # JAVA_LIBRARY
+endif # !NO_DIST_INSTALL
+ +$(LOOP_OVER_DIRS)
+
+##############################################
+
+ifndef NO_PROFILE_GUIDED_OPTIMIZE
+ifneq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
+ifeq ($(OS_ARCH)_$(GNU_CC)$(INTERNAL_TOOLS), WINNT_)
+# Force re-linking when building with PGO, since
+# the MSVC linker does all the work. We force re-link
+# in both stages so you can do depend builds with PGO.
+ifdef SHARED_LIBRARY
+$(SHARED_LIBRARY): FORCE
+BINARY_BASENAME = $(SHARED_LIBRARY:$(DLL_SUFFIX)=)
+endif
+ifdef PROGRAM
+$(PROGRAM): FORCE
+BINARY_BASENAME = $(PROGRAM:$(BIN_SUFFIX)=)
+endif
+
+ifdef MOZ_PROFILE_USE
+# In the second pass, we need to merge the pgc files into the pgd file.
+# The compiler would do this for us automatically if they were in the right
+# place, but they're in dist/bin.
+ifdef BINARY_BASENAME
+export::
+ $(PYTHON) $(topsrcdir)/build/win32/pgomerge.py \
+ $(BINARY_BASENAME) $(DIST)/bin
+endif
+endif # MOZ_PROFILE_USE
+endif # WINNT_
+endif # MOZ_PROFILE_GENERATE || MOZ_PROFILE_USE
+endif # NO_PROFILE_GUIDED_OPTIMIZE
+
+##############################################
+
+checkout:
+ $(MAKE) -C $(topsrcdir) -f client.mk checkout
+
+run_viewer: $(FINAL_TARGET)/viewer
+ cd $(FINAL_TARGET); \
+ MOZILLA_FIVE_HOME=`pwd` \
+ LD_LIBRARY_PATH=".:$(LIBS_PATH):$$LD_LIBRARY_PATH" \
+ viewer
+
+clean clobber realclean clobber_all:: $(SUBMAKEFILES)
+ -rm -f $(ALL_TRASH)
+ -rm -rf $(ALL_TRASH_DIRS)
+ +-$(LOOP_OVER_PARALLEL_DIRS)
+ +-$(LOOP_OVER_DIRS)
+ +-$(LOOP_OVER_STATIC_DIRS)
+ +-$(LOOP_OVER_TOOL_DIRS)
+
+distclean:: $(SUBMAKEFILES)
+ +-$(LOOP_OVER_PARALLEL_DIRS)
+ +-$(LOOP_OVER_DIRS)
+ +-$(LOOP_OVER_STATIC_DIRS)
+ +-$(LOOP_OVER_TOOL_DIRS)
+ -rm -rf $(ALL_TRASH_DIRS)
+ -rm -f $(ALL_TRASH) \
+ Makefile .HSancillary \
+ $(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \
+ $(wildcard *.$(LIB_SUFFIX)) $(wildcard *$(DLL_SUFFIX)) \
+ $(wildcard *.$(IMPORT_LIB_SUFFIX))
+ifeq ($(OS_ARCH),OS2)
+ -rm -f $(PROGRAM:.exe=.map)
+endif
+
+alltags:
+ rm -f TAGS
+ find $(topsrcdir) -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' -o -name '*.idl' \) -print | $(TAG_PROGRAM)
+
+#
+# PROGRAM = Foo
+# creates OBJS, links with LIBS to create Foo
+#
+$(PROGRAM): $(PROGOBJS) $(LIBS_DEPS) $(EXTRA_DEPS) $(EXE_DEF_FILE) $(RESFILE) Makefile Makefile.in
+ifeq (WINCE,$(OS_ARCH))
+ $(LD) -NOLOGO -OUT:$@ $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(PROGOBJS) $(RESFILE) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+else
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+ $(LD) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(PROGOBJS) $(RESFILE) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+ifdef MSMANIFEST_TOOL
+ @if test -f $@.manifest; then \
+ if test -f "$(srcdir)/$@.manifest"; then \
+ mt.exe -NOLOGO -MANIFEST "$(win_srcdir)/$@.manifest" $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ else \
+ mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ fi; \
+ rm -f $@.manifest; \
+ fi
+endif # MSVC with manifest tool
+else
+ifeq ($(CPP_PROG_LINK),1)
+ $(CCC) -o $@ $(CXXFLAGS) $(WRAP_MALLOC_CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(WRAP_MALLOC_LIB) $(PROFILER_LIBS) $(EXE_DEF_FILE)
+else # ! CPP_PROG_LINK
+ $(CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
+endif # CPP_PROG_LINK
+endif # WINNT && !GNU_CC
+endif # WINCE
+
+ifdef ENABLE_STRIP
+ $(STRIP) $@
+endif
+ifdef MOZ_POST_PROGRAM_COMMAND
+ $(MOZ_POST_PROGRAM_COMMAND) $@
+endif
+ifeq ($(OS_ARCH),BeOS)
+ifdef BEOS_PROGRAM_RESOURCE
+ xres -o $@ $(BEOS_PROGRAM_RESOURCE)
+ mimeset $@
+endif
+endif # BeOS
+
+$(HOST_PROGRAM): $(HOST_PROGOBJS) $(HOST_LIBS_DEPS) $(HOST_EXTRA_DEPS) Makefile Makefile.in
+ifeq (WINCE,$(OS_ARCH))
+ $(HOST_LD) -NOLOGO -OUT:$@ $(HOST_OBJS) $(WIN32_EXE_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ifeq (_WINNT,$(GNU_CC)_$(HOST_OS_ARCH))
+ $(HOST_LD) -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $(HOST_OBJS) $(WIN32_EXE_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+ifdef MSMANIFEST_TOOL
+ @if test -f $@.manifest; then \
+ mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ rm -f $@.manifest; \
+ fi
+endif # MSVC with manifest tool
+else
+ifeq ($(CPP_PROG_LINK),1)
+ $(HOST_CXX) -o $@ $(HOST_CXXFLAGS) $(HOST_LDFLAGS) $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ $(HOST_CC) -o $@ $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+endif # CPP_PROG_LINK
+endif
+endif
+
+#
+# This is an attempt to support generation of multiple binaries
+# in one directory, it assumes everything to compile Foo is in
+# Foo.o (from either Foo.c or Foo.cpp).
+#
+# SIMPLE_PROGRAMS = Foo Bar
+# creates Foo.o Bar.o, links with LIBS to create Foo, Bar.
+#
+$(SIMPLE_PROGRAMS): %$(BIN_SUFFIX): %.$(OBJ_SUFFIX) $(LIBS_DEPS) $(EXTRA_DEPS) Makefile Makefile.in
+ifeq (WINCE,$(OS_ARCH))
+ $(LD) -nologo -entry:main -out:$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+else
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+ $(LD) -nologo -out:$@ -pdb:$(LINK_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+ifdef MSMANIFEST_TOOL
+ @if test -f $@.manifest; then \
+ mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ rm -f $@.manifest; \
+ fi
+endif # MSVC with manifest tool
+else
+ifeq ($(CPP_PROG_LINK),1)
+ $(CCC) $(WRAP_MALLOC_CFLAGS) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(PROFILER_LIBS) $(BIN_FLAGS)
+else
+ $(CC) $(WRAP_MALLOC_CFLAGS) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(PROFILER_LIBS) $(BIN_FLAGS)
+endif # CPP_PROG_LINK
+endif # WINNT && !GNU_CC
+endif # WINCE
+
+ifdef ENABLE_STRIP
+ $(STRIP) $@
+endif
+ifdef MOZ_POST_PROGRAM_COMMAND
+ $(MOZ_POST_PROGRAM_COMMAND) $@
+endif
+
+$(HOST_SIMPLE_PROGRAMS): host_%$(HOST_BIN_SUFFIX): host_%.$(OBJ_SUFFIX) $(HOST_LIBS_DEPS) $(HOST_EXTRA_DEPS) Makefile Makefile.in
+ifeq (WINCE,$(OS_ARCH))
+ $(HOST_LD) -NOLOGO -OUT:$@ $(WIN32_EXE_LDFLAGS) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ifeq (WINNT_,$(HOST_OS_ARCH)_$(GNU_CC))
+ $(HOST_LD) -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ifneq (,$(HOST_CPPSRCS)$(USE_HOST_CXX))
+ $(HOST_CXX) $(HOST_OUTOPTION)$@ $(HOST_CXXFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ $(HOST_CC) $(HOST_OUTOPTION)$@ $(HOST_CFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+endif
+endif
+endif
+
+#
+# Purify target. Solaris/sparc only to start.
+# Purify does not recognize "egcs" or "c++" so we go with
+# "gcc" and "g++" for now.
+#
+pure: $(PROGRAM)
+ifeq ($(CPP_PROG_LINK),1)
+ $(PURIFY) $(CCC) -o $^.pure $(CXXFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS)
+else
+ $(PURIFY) $(CC) -o $^.pure $(CFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS)
+endif
+ifndef NO_DIST_INSTALL
+ $(INSTALL) $(IFLAGS2) $^.pure $(FINAL_TARGET)
+endif
+
+quantify: $(PROGRAM)
+ifeq ($(CPP_PROG_LINK),1)
+ $(QUANTIFY) $(CCC) -o $^.quantify $(CXXFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS)
+else
+ $(QUANTIFY) $(CC) -o $^.quantify $(CFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS)
+endif
+ifndef NO_DIST_INSTALL
+ $(INSTALL) $(IFLAGS2) $^.quantify $(FINAL_TARGET)
+endif
+
+#
+# This allows us to create static versions of the shared libraries
+# that are built using other static libraries. Confused...?
+#
+ifdef SHARED_LIBRARY_LIBS
+ifeq (,$(GNU_LD)$(filter-out OS2 WINNT WINCE, $(OS_ARCH)))
+ifneq (,$(BUILD_STATIC_LIBS)$(FORCE_STATIC_LIB))
+LOBJS += $(SHARED_LIBRARY_LIBS)
+endif
+else
+ifneq (,$(filter OSF1 BSD_OS FreeBSD NetBSD OpenBSD SunOS Darwin,$(OS_ARCH)))
+CLEANUP1 := | egrep -v '(________64ELEL_|__.SYMDEF)'
+CLEANUP2 := rm -f ________64ELEL_ __.SYMDEF
+else
+CLEANUP2 := true
+endif
+SUB_LOBJS = $(shell for lib in $(SHARED_LIBRARY_LIBS); do $(AR_LIST) $${lib} $(CLEANUP1); done;)
+endif
+endif
+ifdef MOZILLA_PROBE_LIBS
+PROBE_LOBJS = $(shell for lib in $(MOZILLA_PROBE_LIBS); do $(AR_LIST) $${lib} $(CLEANUP1); done;)
+endif
+ifdef DTRACE_PROBE_OBJ
+EXTRA_DEPS += $(DTRACE_PROBE_OBJ)
+endif
+
+$(LIBRARY): $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DEPS) Makefile Makefile.in
+ rm -f $@
+ifneq (,$(GNU_LD)$(filter-out OS2 WINNT WINCE, $(OS_ARCH)))
+ifdef SHARED_LIBRARY_LIBS
+ @rm -f $(SUB_LOBJS)
+ @for lib in $(SHARED_LIBRARY_LIBS); do $(AR_EXTRACT) $${lib}; $(CLEANUP2); done
+endif
+endif
+ $(AR) $(AR_FLAGS) $(OBJS) $(LOBJS) $(SUB_LOBJS)
+ $(RANLIB) $@
+ @rm -f foodummyfilefoo $(SUB_LOBJS)
+
+ifeq (,$(filter-out WINNT WINCE, $(OS_ARCH)))
+$(IMPORT_LIBRARY): $(SHARED_LIBRARY)
+endif
+
+ifeq ($(OS_ARCH),OS2)
+$(DEF_FILE): $(OBJS) $(SHARED_LIBRARY_LIBS)
+ rm -f $@
+ echo LIBRARY $(LIBRARY_NAME) INITINSTANCE TERMINSTANCE > $@
+ echo PROTMODE >> $@
+ echo CODE LOADONCALL MOVEABLE DISCARDABLE >> $@
+ echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@
+ echo EXPORTS >> $@
+ifeq ($(IS_COMPONENT),1)
+ifeq ($(HAS_EXTRAEXPORTS),1)
+ifndef MOZ_OS2_USE_DECLSPEC
+ $(FILTER) $(OBJS) $(SHARED_LIBRARY_LIBS) >> $@
+endif
+else
+ echo _NSGetModule >> $@
+endif
+else
+ifndef MOZ_OS2_USE_DECLSPEC
+ $(FILTER) $(OBJS) $(SHARED_LIBRARY_LIBS) >> $@
+endif
+endif
+ $(ADD_TO_DEF_FILE)
+
+ifdef MOZ_OS2_USE_DECLSPEC
+$(IMPORT_LIBRARY): $(SHARED_LIBRARY)
+else
+$(IMPORT_LIBRARY): $(DEF_FILE)
+endif
+ rm -f $@
+ $(IMPLIB) $@ $^
+ $(RANLIB) $@
+endif # OS/2
+
+$(HOST_LIBRARY): $(HOST_OBJS) Makefile
+ rm -f $@
+ $(HOST_AR) $(HOST_AR_FLAGS) $(HOST_OBJS)
+ $(HOST_RANLIB) $@
+
+ifdef NO_LD_ARCHIVE_FLAGS
+SUB_SHLOBJS = $(SUB_LOBJS)
+endif
+
+ifdef HAVE_DTRACE
+ifndef XP_MACOSX
+ifdef DTRACE_PROBE_OBJ
+ifndef DTRACE_LIB_DEPENDENT
+$(DTRACE_PROBE_OBJ): $(OBJS)
+ dtrace -G -C -32 -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(OBJS)
+endif
+endif
+endif
+endif
+
+# On Darwin (Mac OS X), dwarf2 debugging uses debug info left in .o files,
+# so instead of deleting .o files after repacking them into a dylib, we make
+# symlinks back to the originals. The symlinks are a no-op for stabs debugging,
+# so no need to conditionalize on OS version or debugging format.
+
+$(SHARED_LIBRARY): $(OBJS) $(LOBJS) $(DEF_FILE) $(RESFILE) $(SHARED_LIBRARY_LIBS) $(EXTRA_DEPS) $(DSO_LDOPTS_DEPS) Makefile Makefile.in
+ifndef INCREMENTAL_LINKER
+ rm -f $@
+endif
+ifeq ($(OS_ARCH),OpenVMS)
+ @if test ! -f $(VMS_SYMVEC_FILE); then \
+ if test -f $(VMS_SYMVEC_FILE_MODULE); then \
+ echo Creating specific component options file $(VMS_SYMVEC_FILE); \
+ cp $(VMS_SYMVEC_FILE_MODULE) $(VMS_SYMVEC_FILE); \
+ fi; \
+ fi
+ifdef IS_COMPONENT
+ @if test ! -f $(VMS_SYMVEC_FILE); then \
+ echo Creating generic component options file $(VMS_SYMVEC_FILE); \
+ cp $(VMS_SYMVEC_FILE_COMP) $(VMS_SYMVEC_FILE); \
+ fi
+endif
+endif # OpenVMS
+ifdef NO_LD_ARCHIVE_FLAGS
+ifdef SHARED_LIBRARY_LIBS
+ @rm -f $(SUB_SHLOBJS)
+ @for lib in $(SHARED_LIBRARY_LIBS); do $(AR_EXTRACT) $${lib}; $(CLEANUP2); done
+ifeq ($(OS_ARCH),Darwin)
+ @echo Making symlinks to the original object files in the archive libraries $(SHARED_LIBRARY_LIBS)
+ @for lib in $(SHARED_LIBRARY_LIBS); do \
+ libdir=`echo $$lib|sed -e 's,/[^/]*\.a,,'`; \
+ ofiles=`$(AR_LIST) $${lib}`; \
+ for ofile in $$ofiles; do \
+ if [ -f $$libdir/$$ofile ]; then \
+ rm -f $$ofile; \
+ ln -s $$libdir/$$ofile $$ofile; \
+ fi; \
+ done; \
+ done
+endif
+endif # SHARED_LIBRARY_LIBS
+endif # NO_LD_ARCHIVE_FLAGS
+ifdef DTRACE_LIB_DEPENDENT
+ @rm -f $(PROBE_LOBJS)
+ @for lib in $(MOZILLA_PROBE_LIBS); do $(AR_EXTRACT) $${lib}; $(CLEANUP2); done
+ifndef XP_MACOSX
+ dtrace -G -C -32 -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(PROBE_LOBJS)
+endif
+ @for lib in $(MOZILLA_PROBE_LIBS); do \
+ ofiles=`$(AR_LIST) $${lib}`; \
+ $(AR_DELETE) $${lib} $$ofiles; \
+ done
+ $(MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(PROBE_LOBJS) $(RESFILE) $(LDFLAGS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
+ @rm -f $(PROBE_LOBJS)
+ @rm -f $(DTRACE_PROBE_OBJ)
+ @for lib in $(MOZILLA_PROBE_LIBS); do \
+ if [ -L $${lib} ]; then rm -f `readlink $${lib}`; fi; \
+ done
+ @rm -f $(MOZILLA_PROBE_LIBS)
+
+else # ! DTRACE_LIB_DEPENDENT
+ $(MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(DTRACE_PROBE_OBJ) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
+endif # DTRACE_LIB_DEPENDENT
+
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+ifdef MSMANIFEST_TOOL
+ifdef EMBED_MANIFEST_AT
+ @if test -f $@.manifest; then \
+ mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
+ rm -f $@.manifest; \
+ fi
+endif # EMBED_MANIFEST_AT
+endif # MSVC with manifest tool
+endif # WINNT && !GCC
+ifeq ($(OS_ARCH),Darwin)
+else # non-Darwin
+ @rm -f $(SUB_SHLOBJS)
+endif # Darwin
+ @rm -f foodummyfilefoo $(DELETE_AFTER_LINK)
+ chmod +x $@
+ifdef ENABLE_STRIP
+ $(STRIP) $@
+endif
+ifdef MOZ_POST_DSO_LIB_COMMAND
+ $(MOZ_POST_DSO_LIB_COMMAND) $@
+endif
+
+ifdef MOZ_AUTO_DEPS
+ifdef COMPILER_DEPEND
+ifeq (__SunOS,$(GNU_CC)_$(GNU_CXX)_$(OS_ARCH))
+_MDDEPFILE = $(MDDEPDIR)/$(@F).pp
+
+define MAKE_DEPS_AUTO_CC
+if test -d $(@D); then \
+ echo "Building deps for $< using Sun Studio cc"; \
+ $(CC) $(COMPILE_CFLAGS) -xM $< >$(_MDDEPFILE) ; \
+fi
+endef
+define MAKE_DEPS_AUTO_CXX
+if test -d $(@D); then \
+ echo "Building deps for $< using Sun Studio CC"; \
+ $(CXX) $(COMPILE_CXXFLAGS) -xM $< >$(_MDDEPFILE) ; \
+fi
+endef
+endif # Sun Studio on Solaris
+else # COMPILER_DEPEND
+#
+# Generate dependencies on the fly
+#
+_MDDEPFILE = $(MDDEPDIR)/$(@F).pp
+
+define MAKE_DEPS_AUTO
+if test -d $(@D); then \
+ echo "Building deps for $<"; \
+ $(MKDEPEND) -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $(_MDDEPFILE) ; \
+fi
+endef
+
+MAKE_DEPS_AUTO_CC = $(MAKE_DEPS_AUTO)
+MAKE_DEPS_AUTO_CXX = $(MAKE_DEPS_AUTO)
+
+endif # COMPILER_DEPEND
+
+endif # MOZ_AUTO_DEPS
+
+ifdef MOZ_MEMORY
+ifeq ($(OS_ARCH),SunOS)
+SOLARIS_JEMALLOC_LDFLAGS = $(call EXPAND_LIBNAME_PATH,jemalloc,$(DIST)/lib)
+endif
+endif
+
+# Rules for building native targets must come first because of the host_ prefix
+host_%.$(OBJ_SUFFIX): %.c Makefile Makefile.in
+ $(REPORT_BUILD)
+ $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+host_%.$(OBJ_SUFFIX): %.cpp Makefile Makefile.in
+ $(REPORT_BUILD)
+ $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+host_%.$(OBJ_SUFFIX): %.cc Makefile Makefile.in
+ $(REPORT_BUILD)
+ $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+host_%.$(OBJ_SUFFIX): %.m Makefile Makefile.in
+ $(REPORT_BUILD)
+ $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+host_%.$(OBJ_SUFFIX): %.mm Makefile Makefile.in
+ $(REPORT_BUILD)
+ $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+%: %.c Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CC)
+ $(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
+
+%.$(OBJ_SUFFIX): %.c Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CC)
+ $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
+
+moc_%.cpp: %.h Makefile Makefile.in
+ $(MOC) $< $(OUTOPTION)$@
+
+ifdef ASFILES
+# The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
+# a '-c' flag.
+%.$(OBJ_SUFFIX): %.$(ASM_SUFFIX) Makefile Makefile.in
+ $(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
+endif
+
+%.$(OBJ_SUFFIX): %.S Makefile Makefile.in
+ $(AS) -o $@ $(ASFLAGS) -c $<
+
+%: %.cpp Makefile Makefile.in
+ @$(MAKE_DEPS_AUTO_CXX)
+ $(CCC) $(OUTOPTION)$@ $(CXXFLAGS) $(_VPATH_SRCS) $(LDFLAGS)
+
+#
+# Please keep the next two rules in sync.
+#
+%.$(OBJ_SUFFIX): %.cc Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CXX)
+ $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+
+%.$(OBJ_SUFFIX): %.cpp Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CXX)
+ifdef STRICT_CPLUSPLUS_SUFFIX
+ echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc
+ $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) t_$*.cc
+ rm -f t_$*.cc
+else
+ $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+endif #STRICT_CPLUSPLUS_SUFFIX
+
+$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CXX)
+ $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
+
+$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CC)
+ $(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
+
+%.s: %.cpp
+ $(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+
+%.s: %.cc
+ $(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+
+%.s: %.c
+ $(CC) -S $(COMPILE_CFLAGS) $(_VPATH_SRCS)
+
+%.i: %.cpp
+ $(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
+
+%.i: %.cc
+ $(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
+
+%.i: %.c
+ $(CC) -C -E $(COMPILE_CFLAGS) $(_VPATH_SRCS) > $*.i
+
+%.i: %.mm
+ $(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) > $*.i
+
+%.res: %.rc
+ @echo Creating Resource file: $@
+ifeq ($(OS_ARCH),OS2)
+ $(RC) $(RCFLAGS:-D%=-d %) -i $(subst /,\,$(srcdir)) -r $< $@
+else
+ifdef GNU_CC
+ $(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) $(OUTOPTION)$@ $(_VPATH_SRCS)
+else
+ $(RC) $(RCFLAGS) -r $(DEFINES) $(INCLUDES) $(OUTOPTION)$@ $(_VPATH_SRCS)
+endif
+endif
+
+# need 3 separate lines for OS/2
+%: %.pl
+ rm -f $@
+ cp $< $@
+ chmod +x $@
+
+%: %.sh
+ rm -f $@; cp $< $@; chmod +x $@
+
+# Cancel these implicit rules
+#
+%: %,v
+
+%: RCS/%,v
+
+%: s.%
+
+%: SCCS/s.%
+
+###############################################################################
+# Java rules
+###############################################################################
+ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
+SEP := ;
+else
+SEP := :
+endif
+
+EMPTY :=
+SPACE := $(EMPTY) $(EMPTY)
+
+# Cygwin and MSYS have their own special path form, but javac expects the source
+# and class paths to be in the DOS form (i.e. e:/builds/...). This function
+# does the appropriate conversion on Windows, but is a noop on other systems.
+ifeq (,$(filter-out WINNT WINCE, $(HOST_OS_ARCH)))
+ifdef CYGWIN_WRAPPER
+normalizepath = $(foreach p,$(1),$(shell cygpath -m $(p)))
+else
+# assume MSYS
+# We use 'pwd -W' to get DOS form of the path. However, since the given path
+# could be a file or a non-existent path, we cannot call 'pwd -W' directly
+# on the path. Instead, we extract the root path (i.e. "c:/"), call 'pwd -W'
+# on it, then merge with the rest of the path.
+root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\1|")
+non-root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\2|")
+normalizepath = $(foreach p,$(1),$(if $(filter /%,$(1)),$(shell cd $(call root-path,$(1)) && pwd -W)$(call non-root-path,$(1)),$(1)))
+endif
+else
+normalizepath = $(1)
+endif
+
+_srcdir = $(call normalizepath,$(srcdir))
+ifdef JAVA_SOURCEPATH
+SP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_SOURCEPATH))))
+_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)$(SEP)$(SP)"
+else
+_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)"
+endif
+
+ifdef JAVA_CLASSPATH
+CP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_CLASSPATH))))
+_JAVA_CLASSPATH = ".$(SEP)$(CP)"
+else
+_JAVA_CLASSPATH = .
+endif
+
+_JAVA_DIR = _java
+$(_JAVA_DIR)::
+ $(NSINSTALL) -D $@
+
+$(_JAVA_DIR)/%.class: %.java Makefile Makefile.in $(_JAVA_DIR)
+ $(CYGWIN_WRAPPER) $(JAVAC) $(JAVAC_FLAGS) -classpath $(_JAVA_CLASSPATH) \
+ -sourcepath $(_JAVA_SOURCEPATH) -d $(_JAVA_DIR) $(_VPATH_SRCS)
+
+$(JAVA_LIBRARY): $(addprefix $(_JAVA_DIR)/,$(JAVA_SRCS:.java=.class)) Makefile Makefile.in
+ $(JAR) cf $@ -C $(_JAVA_DIR) .
+
+GARBAGE_DIRS += $(_JAVA_DIR)
+
+###############################################################################
+# Update Makefiles
+###############################################################################
+
+# In GNU make 3.80, makefiles must use the /cygdrive syntax, even if we're
+# processing them with AS perl. See bug 232003
+ifdef AS_PERL
+CYGWIN_TOPSRCDIR = -nowrap -p $(topsrcdir) -wrap
+endif
+
+# Note: Passing depth to make-makefile is optional.
+# It saves the script some work, though.
+Makefile: Makefile.in
+ @$(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH) $(CYGWIN_TOPSRCDIR)
+
+ifdef SUBMAKEFILES
+# VPATH does not work on some machines in this case, so add $(srcdir)
+$(SUBMAKEFILES): % : $(srcdir)/%.in
+ $(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH) $(CYGWIN_TOPSRCDIR) $@
+endif
+
+ifdef AUTOUPDATE_CONFIGURE
+$(topsrcdir)/configure: $(topsrcdir)/configure.in
+ (cd $(topsrcdir) && $(AUTOCONF)) && (cd $(DEPTH) && ./config.status --recheck)
+endif
+
+###############################################################################
+# Bunch of things that extend the 'export' rule (in order):
+###############################################################################
+
+################################################################################
+# Copy each element of EXPORTS to $(PUBLIC)
+
+ifneq ($(EXPORTS)$(XPIDLSRCS)$(SDK_HEADERS)$(SDK_XPIDLSRCS),)
+$(SDK_PUBLIC) $(PUBLIC)::
+ $(NSINSTALL) -D $@
+endif
+
+ifdef MOZ_JAVAXPCOM
+ifneq ($(XPIDLSRCS)$(SDK_XPIDLSRCS),)
+$(JAVA_DIST_DIR)::
+ $(NSINSTALL) -D $@
+endif
+endif
+
+ifneq ($(XPI_NAME),)
+$(FINAL_TARGET):
+ $(NSINSTALL) -D $@
+
+export:: $(FINAL_TARGET)
+endif
+
+ifndef NO_DIST_INSTALL
+ifneq ($(EXPORTS),)
+export:: $(EXPORTS) $(PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+endif
+
+ifneq ($(SDK_HEADERS),)
+export:: $(SDK_HEADERS) $(SDK_PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+
+export:: $(SDK_HEADERS) $(PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+endif
+endif # NO_DIST_INSTALL
+
+################################################################################
+# Copy each element of PREF_JS_EXPORTS
+
+ifdef GRE_MODULE
+PREF_DIR = greprefs
+else
+ifneq (,$(XPI_NAME)$(LIBXUL_SDK))
+PREF_DIR = defaults/preferences
+else
+PREF_DIR = defaults/pref
+endif
+endif
+
+ifneq ($(PREF_JS_EXPORTS),)
+# on win32, pref files need CRLF line endings... see bug 206029
+ifeq (WINNT,$(OS_ARCH))
+PREF_PPFLAGS = --line-endings=crlf
+endif
+
+ifndef NO_DIST_INSTALL
+$(FINAL_TARGET)/$(PREF_DIR):
+ $(NSINSTALL) -D $@
+
+libs:: $(FINAL_TARGET)/$(PREF_DIR) $(PREF_JS_EXPORTS)
+ $(EXIT_ON_ERROR) \
+ for i in $(PREF_JS_EXPORTS); do \
+ dest=$(FINAL_TARGET)/$(PREF_DIR)/`basename $$i`; \
+ $(RM) -f $$dest; \
+ $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \
+ done
+endif
+endif
+
+################################################################################
+# Copy each element of AUTOCFG_JS_EXPORTS to $(FINAL_TARGET)/defaults/autoconfig
+
+ifneq ($(AUTOCFG_JS_EXPORTS),)
+$(FINAL_TARGET)/defaults/autoconfig::
+ $(NSINSTALL) -D $@
+
+ifndef NO_DIST_INSTALL
+export:: $(AUTOCFG_JS_EXPORTS) $(FINAL_TARGET)/defaults/autoconfig
+ $(INSTALL) $(IFLAGS1) $^
+endif
+
+endif
+################################################################################
+# Export the elements of $(XPIDLSRCS) & $(SDK_XPIDLSRCS),
+# generating .h and .xpt files and moving them to the appropriate places.
+
+ifneq ($(XPIDLSRCS)$(SDK_XPIDLSRCS),)
+
+export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS))
+
+ifndef XPIDL_MODULE
+XPIDL_MODULE = $(MODULE)
+endif
+
+ifeq ($(XPIDL_MODULE),) # we need $(XPIDL_MODULE) to make $(XPIDL_MODULE).xpt
+export:: FORCE
+ @echo
+ @echo "*** Error processing XPIDLSRCS:"
+ @echo "Please define MODULE or XPIDL_MODULE when defining XPIDLSRCS,"
+ @echo "so we have a module name to use when creating MODULE.xpt."
+ @echo; sleep 2; false
+endif
+
+$(SDK_IDL_DIR) $(IDL_DIR)::
+ $(NSINSTALL) -D $@
+
+# generate .h files from into $(XPIDL_GEN_DIR), then export to $(PUBLIC);
+# warn against overriding existing .h file.
+$(XPIDL_GEN_DIR)/.done:
+ @if test ! -d $(XPIDL_GEN_DIR); then echo Creating $(XPIDL_GEN_DIR)/.done; rm -rf $(XPIDL_GEN_DIR); mkdir $(XPIDL_GEN_DIR); fi
+ @touch $@
+
+# don't depend on $(XPIDL_GEN_DIR), because the modification date changes
+# with any addition to the directory, regenerating all .h files -> everything.
+
+$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done
+ $(REPORT_BUILD)
+ $(ELOG) $(XPIDL_COMPILE) -m header -w $(XPIDL_FLAGS) -o $(XPIDL_GEN_DIR)/$* $(_VPATH_SRCS)
+ @if test -n "$(findstring $*.h, $(EXPORTS) $(SDK_HEADERS))"; \
+ then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
+
+ifndef NO_GEN_XPT
+# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
+# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
+$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done
+ $(REPORT_BUILD)
+ $(ELOG) $(XPIDL_COMPILE) -m typelib -w $(XPIDL_FLAGS) -e $@ -d $(MDDEPDIR)/$*.pp $(_VPATH_SRCS)
+
+# no need to link together if XPIDLSRCS contains only XPIDL_MODULE
+ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
+$(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS) $(SDK_XPIDLSRCS)) Makefile.in Makefile $(XPIDL_LINK)
+ $(XPIDL_LINK) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS) $(SDK_XPIDLSRCS))
+endif # XPIDL_MODULE.xpt != XPIDLSRCS
+
+libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt
+ifndef NO_DIST_INSTALL
+ $(INSTALL) $(IFLAGS1) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(FINAL_TARGET)/components
+endif
+
+endif # NO_GEN_XPT
+
+GARBAGE_DIRS += $(XPIDL_GEN_DIR)
+
+endif # XPIDLSRCS || SDK_XPIDLSRCS
+
+ifneq ($(XPIDLSRCS),)
+# export .idl files to $(IDL_DIR)
+ifndef NO_DIST_INSTALL
+export:: $(XPIDLSRCS) $(IDL_DIR)
+ $(INSTALL) $(IFLAGS1) $^
+
+export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS)) $(PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+endif # NO_DIST_INSTALL
+
+endif # XPIDLSRCS
+
+
+
+#
+# General rules for exporting idl files.
+#
+# WORK-AROUND ONLY, for mozilla/tools/module-deps/bootstrap.pl build.
+# Bug to fix idl dependency problems w/o this extra build pass is
+# http://bugzilla.mozilla.org/show_bug.cgi?id=145777
+#
+$(IDL_DIR)::
+ $(NSINSTALL) -D $@
+
+export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS)
+
+ifneq ($(XPIDLSRCS)$(SDK_XPIDLSRCS),)
+ifndef NO_DIST_INSTALL
+export-idl:: $(XPIDLSRCS) $(SDK_XPIDLSRCS) $(IDL_DIR)
+ $(INSTALL) $(IFLAGS1) $^
+endif
+endif
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+
+
+
+
+ifneq ($(SDK_XPIDLSRCS),)
+# export .idl files to $(IDL_DIR) & $(SDK_IDL_DIR)
+ifndef NO_DIST_INSTALL
+export:: $(SDK_XPIDLSRCS) $(IDL_DIR)
+ $(INSTALL) $(IFLAGS1) $^
+
+export:: $(SDK_XPIDLSRCS) $(SDK_IDL_DIR)
+ $(INSTALL) $(IFLAGS1) $^
+
+export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(SDK_XPIDLSRCS)) $(PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+
+export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(SDK_XPIDLSRCS)) $(SDK_PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+endif
+
+endif # SDK_XPIDLSRCS
+
+
+
+ifdef MOZ_JAVAXPCOM
+ifneq ($(XPIDLSRCS)$(SDK_XPIDLSRCS),)
+
+JAVA_XPIDLSRCS = $(XPIDLSRCS) $(SDK_XPIDLSRCS)
+
+# A single IDL file can contain multiple interfaces, which result in multiple
+# Java interface files. So use hidden dependency files.
+JAVADEPFILES = $(addprefix $(JAVA_GEN_DIR)/.,$(JAVA_XPIDLSRCS:.idl=.java.pp))
+
+$(JAVA_GEN_DIR):
+ $(NSINSTALL) -D $@
+GARBAGE_DIRS += $(JAVA_GEN_DIR)
+
+# generate .java files into _javagen/[package name dirs]
+_JAVA_GEN_DIR = $(JAVA_GEN_DIR)/$(JAVA_IFACES_PKG_NAME)
+$(_JAVA_GEN_DIR):
+ $(NSINSTALL) -D $@
+
+$(JAVA_GEN_DIR)/.%.java.pp: %.idl $(XPIDL_COMPILE) $(_JAVA_GEN_DIR)
+ $(REPORT_BUILD)
+ $(ELOG) $(XPIDL_COMPILE) -m java -w -I$(srcdir) -I$(IDL_DIR) -o $(_JAVA_GEN_DIR)/$* $(_VPATH_SRCS)
+ @touch $@
+
+# "Install" generated Java interfaces. We segregate them based on the XPI_NAME.
+# If XPI_NAME is not set, install into the "default" directory.
+ifneq ($(XPI_NAME),)
+JAVA_INSTALL_DIR = $(JAVA_DIST_DIR)/$(XPI_NAME)
+else
+JAVA_INSTALL_DIR = $(JAVA_DIST_DIR)/default
+endif
+
+$(JAVA_INSTALL_DIR):
+ $(NSINSTALL) -D $@
+
+export:: $(JAVA_DIST_DIR) $(JAVADEPFILES) $(JAVA_INSTALL_DIR)
+ (cd $(JAVA_GEN_DIR) && tar $(TAR_CREATE_FLAGS) - .) | (cd $(JAVA_INSTALL_DIR) && tar -xf -)
+
+endif # XPIDLSRCS || SDK_XPIDLSRCS
+endif # MOZ_JAVAXPCOM
+
+################################################################################
+# Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components
+ifdef EXTRA_COMPONENTS
+libs:: $(EXTRA_COMPONENTS)
+ifndef NO_DIST_INSTALL
+ $(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/components
+endif
+
+endif
+
+ifdef EXTRA_PP_COMPONENTS
+libs:: $(EXTRA_PP_COMPONENTS)
+ifndef NO_DIST_INSTALL
+ $(EXIT_ON_ERROR) \
+ $(NSINSTALL) -D $(FINAL_TARGET)/components; \
+ for i in $^; do \
+ dest=$(FINAL_TARGET)/components/`basename $$i`; \
+ $(RM) -f $$dest; \
+ $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \
+ done
+endif
+
+endif
+
+################################################################################
+# Copy each element of EXTRA_JS_MODULES to $(FINAL_TARGET)/modules
+ifdef EXTRA_JS_MODULES
+libs:: $(EXTRA_JS_MODULES)
+ifndef NO_DIST_INSTALL
+ $(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/modules
+endif
+
+endif
+
+ifdef EXTRA_PP_JS_MODULES
+libs:: $(EXTRA_PP_JS_MODULES)
+ifndef NO_DIST_INSTALL
+ $(EXIT_ON_ERROR) \
+ $(NSINSTALL) -D $(FINAL_TARGET)/modules; \
+ for i in $^; do \
+ dest=$(FINAL_TARGET)/modules/`basename $$i`; \
+ $(RM) -f $$dest; \
+ $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \
+ done
+endif
+
+endif
+
+################################################################################
+# SDK
+
+ifneq (,$(SDK_LIBRARY))
+$(SDK_LIB_DIR)::
+ $(NSINSTALL) -D $@
+
+ifndef NO_DIST_INSTALL
+libs:: $(SDK_LIBRARY) $(SDK_LIB_DIR)
+ $(INSTALL) $(IFLAGS2) $^
+endif
+
+endif # SDK_LIBRARY
+
+ifneq (,$(SDK_BINARY))
+$(SDK_BIN_DIR)::
+ $(NSINSTALL) -D $@
+
+ifndef NO_DIST_INSTALL
+libs:: $(SDK_BINARY) $(SDK_BIN_DIR)
+ $(INSTALL) $(IFLAGS2) $^
+endif
+
+endif # SDK_BINARY
+
+################################################################################
+# CHROME PACKAGING
+
+JAR_MANIFEST := $(srcdir)/jar.mn
+
+chrome::
+ $(MAKE) realchrome
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+
+$(FINAL_TARGET)/chrome:
+ $(NSINSTALL) -D $@
+
+# libs realchrome:: $(CHROME_DEPS) $(FINAL_TARGET)/chrome
+# ifndef NO_DIST_INSTALL
+# @$(EXIT_ON_ERROR) \
+# if test -f $(JAR_MANIFEST); then \
+# $(PYTHON) $(MOZILLA_DIR)/config/JarMaker.py \
+# $(QUIET) -j $(FINAL_TARGET)/chrome \
+# $(MAKE_JARS_FLAGS) $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \
+# $(JAR_MANIFEST); \
+# fi
+# endif
+
+ifneq ($(DIST_FILES),)
+libs:: $(DIST_FILES)
+ @$(EXIT_ON_ERROR) \
+ for f in $(DIST_FILES); do \
+ dest=$(FINAL_TARGET)/`basename $$f`; \
+ $(RM) -f $$dest; \
+ $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \
+ $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
+ $(srcdir)/$$f > $$dest; \
+ done
+endif
+
+ifneq ($(DIST_CHROME_FILES),)
+libs:: $(DIST_CHROME_FILES)
+ @$(EXIT_ON_ERROR) \
+ for f in $(DIST_CHROME_FILES); do \
+ dest=$(FINAL_TARGET)/chrome/`basename $$f`; \
+ $(RM) -f $$dest; \
+ $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \
+ $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
+ $(srcdir)/$$f > $$dest; \
+ done
+endif
+
+ifneq ($(XPI_PKGNAME),)
+libs realchrome::
+ifdef STRIP_XPI
+ifndef MOZ_DEBUG
+ @echo "Stripping $(XPI_PKGNAME) package directory..."
+ @echo $(FINAL_TARGET)
+ @cd $(FINAL_TARGET) && find . ! -type d \
+ ! -name "*.js" \
+ ! -name "*.xpt" \
+ ! -name "*.gif" \
+ ! -name "*.jpg" \
+ ! -name "*.png" \
+ ! -name "*.xpm" \
+ ! -name "*.txt" \
+ ! -name "*.rdf" \
+ ! -name "*.sh" \
+ ! -name "*.properties" \
+ ! -name "*.dtd" \
+ ! -name "*.html" \
+ ! -name "*.xul" \
+ ! -name "*.css" \
+ ! -name "*.xml" \
+ ! -name "*.jar" \
+ ! -name "*.dat" \
+ ! -name "*.tbl" \
+ ! -name "*.src" \
+ ! -name "*.reg" \
+ $(PLATFORM_EXCLUDE_LIST) \
+ -exec $(STRIP) $(STRIP_FLAGS) {} >/dev/null 2>&1 \;
+endif
+endif
+ @echo "Packaging $(XPI_PKGNAME).xpi..."
+ cd $(FINAL_TARGET) && $(ZIP) -qr ../$(XPI_PKGNAME).xpi *
+endif
+
+ifdef INSTALL_EXTENSION_ID
+ifndef XPI_NAME
+$(error XPI_NAME must be set for INSTALL_EXTENSION_ID)
+endif
+
+libs::
+ $(RM) -rf "$(DIST)/bin/extensions/$(INSTALL_EXTENSION_ID)"
+ $(NSINSTALL) -D "$(DIST)/bin/extensions/$(INSTALL_EXTENSION_ID)"
+ cd $(FINAL_TARGET) && tar $(TAR_CREATE_FLAGS) - . | (cd "../../bin/extensions/$(INSTALL_EXTENSION_ID)" && tar -xf -)
+
+endif
+
+ifneq (,$(filter flat symlink,$(MOZ_CHROME_FILE_FORMAT)))
+_JAR_REGCHROME_DISABLE_JAR=1
+else
+_JAR_REGCHROME_DISABLE_JAR=0
+endif
+
+REGCHROME = $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/add-chrome.pl \
+ $(if $(filter gtk2,$(MOZ_WIDGET_TOOLKIT)),-x) \
+ $(if $(CROSS_COMPILE),-o $(OS_ARCH)) $(FINAL_TARGET)/chrome/installed-chrome.txt \
+ $(_JAR_REGCHROME_DISABLE_JAR)
+
+REGCHROME_INSTALL = $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/add-chrome.pl \
+ $(if $(filter gtk2,$(MOZ_WIDGET_TOOLKIT)),-x) \
+ $(if $(CROSS_COMPILE),-o $(OS_ARCH)) $(DESTDIR)$(mozappdir)/chrome/installed-chrome.txt \
+ $(_JAR_REGCHROME_DISABLE_JAR)
+
+
+################################################################################
+# Testing frameworks support
+################################################################################
+
+ifdef ENABLE_TESTS
+
+ifdef XPCSHELL_TESTS
+ifndef MODULE
+$(error Must define MODULE when defining XPCSHELL_TESTS.)
+endif
+
+# Test file installation
+libs::
+ @$(EXIT_ON_ERROR) \
+ for testdir in $(XPCSHELL_TESTS); do \
+ $(INSTALL) \
+ $(srcdir)/$$testdir/*.js \
+ $(DEPTH)/_tests/xpcshell-simple/$(MODULE)/$$testdir; \
+ done
+
+# Path formats on Windows are hard. We require a topsrcdir formatted so that
+# it may be passed to nsILocalFile.initWithPath (in other words, an absolute
+# path of the form X:\path\to\topsrcdir), which we store in NATIVE_TOPSRCDIR.
+# We require a forward-slashed path to topsrcdir so that it may be combined
+# with a relative forward-slashed path for loading scripts, both dynamically
+# and statically for head/test/tail JS files. Of course, on non-Windows none
+# of this matters, and things will work correctly because everything's
+# forward-slashed, everywhere, always.
+ifdef CYGWIN_WRAPPER
+NATIVE_TOPSRCDIR := `cygpath -wa $(topsrcdir)`
+FWDSLASH_TOPSRCDIR := `cygpath -ma $(topsrcdir)`
+else
+FWDSLASH_TOPSRCDIR := $(topsrcdir)
+ifeq ($(HOST_OS_ARCH),WINNT)
+NATIVE_TOPSRCDIR := $(subst /,\\,$(WIN_TOP_SRC))
+else
+NATIVE_TOPSRCDIR := $(topsrcdir)
+endif
+endif # CYGWIN_WRAPPER
+
+# Test execution
+check::
+ @$(EXIT_ON_ERROR) \
+ for testdir in $(XPCSHELL_TESTS); do \
+ $(RUN_TEST_PROGRAM) \
+ $(topsrcdir)/tools/test-harness/xpcshell-simple/test_all.sh \
+ $(DIST)/bin/xpcshell \
+ $(FWDSLASH_TOPSRCDIR) \
+ $(NATIVE_TOPSRCDIR) \
+ $(DEPTH)/_tests/xpcshell-simple/$(MODULE)/$$testdir; \
+ done
+
+# Test execution
+check-interactive::
+ @$(EXIT_ON_ERROR) \
+ $(RUN_TEST_PROGRAM) \
+ $(topsrcdir)/tools/test-harness/xpcshell-simple/test_one.sh \
+ $(DIST)/bin/xpcshell \
+ $(FWDSLASH_TOPSRCDIR) \
+ $(NATIVE_TOPSRCDIR) \
+ $(DEPTH)/_tests/xpcshell-simple/$(MODULE)/$$testdir \
+ $(SOLO_FILE) 1;
+
+# Test execution
+check-one::
+ @$(EXIT_ON_ERROR) \
+ $(RUN_TEST_PROGRAM) \
+ $(topsrcdir)/tools/test-harness/xpcshell-simple/test_one.sh \
+ $(DIST)/bin/xpcshell \
+ $(FWDSLASH_TOPSRCDIR) \
+ $(NATIVE_TOPSRCDIR) \
+ $(DEPTH)/_tests/xpcshell-simple/$(MODULE)/$$testdir \
+ $(SOLO_FILE) 0;
+
+endif # XPCSHELL_TESTS
+
+endif # ENABLE_TESTS
+
+
+#############################################################################
+# Dependency system
+#############################################################################
+ifdef COMPILER_DEPEND
+depend::
+ @echo "$(MAKE): No need to run depend target.\
+ Using compiler-based depend." 1>&2
+ifeq ($(GNU_CC)$(GNU_CXX),)
+# Non-GNU compilers
+ @echo "`echo '$(MAKE):'|sed 's/./ /g'`"\
+ '(Compiler-based depend was turned on by "--enable-md".)' 1>&2
+else
+# GNU compilers
+ @space="`echo '$(MAKE): '|sed 's/./ /g'`";\
+ echo "$$space"'Since you are using a GNU compiler,\
+ it is on by default.' 1>&2; \
+ echo "$$space"'To turn it off, pass --disable-md to configure.' 1>&2
+endif
+
+else # ! COMPILER_DEPEND
+
+ifndef MOZ_AUTO_DEPS
+
+define MAKE_DEPS_NOAUTO
+ $(MKDEPEND) -w1024 -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $@
+endef
+
+$(MDDEPDIR)/%.pp: %.c
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_NOAUTO)
+
+$(MDDEPDIR)/%.pp: %.cpp
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_NOAUTO)
+
+$(MDDEPDIR)/%.pp: %.s
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_NOAUTO)
+
+ifneq (,$(OBJS)$(XPIDLSRCS)$(SDK_XPIDLSRCS)$(SIMPLE_PROGRAMS))
+depend:: $(SUBMAKEFILES) $(MAKE_DIRS) $(MDDEPFILES)
+else
+depend:: $(SUBMAKEFILES)
+endif
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+
+dependclean:: $(SUBMAKEFILES)
+ rm -f $(MDDEPFILES)
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+
+endif # MOZ_AUTO_DEPS
+
+endif # COMPILER_DEPEND
+
+
+#############################################################################
+# MDDEPDIR is the subdirectory where all the dependency files are placed.
+# This uses a make rule (instead of a macro) to support parallel
+# builds (-jN). If this were done in the LOOP_OVER_DIRS macro, two
+# processes could simultaneously try to create the same directory.
+#
+# We use $(CURDIR) in the rule's target to ensure that we don't find
+# a dependency directory in the source tree via VPATH (perhaps from
+# a previous build in the source tree) and thus neglect to create a
+# dependency directory in the object directory, where we really need
+# it.
+
+$(CURDIR)/$(MDDEPDIR):
+ @if test ! -d $@; then echo Creating $@; rm -rf $@; mkdir $@; else true; fi
+
+ifneq (,$(filter-out all chrome default export realchrome tools clean clobber clobber_all distclean realclean,$(MAKECMDGOALS)))
+ifneq (,$(OBJS)$(XPIDLSRCS)$(SDK_XPIDLSRCS)$(SIMPLE_PROGRAMS))
+MDDEPEND_FILES := $(strip $(wildcard $(MDDEPDIR)/*.pp))
+
+ifneq (,$(MDDEPEND_FILES))
+ifdef PERL
+# The script mddepend.pl checks the dependencies and writes to stdout
+# one rule to force out-of-date objects. For example,
+# foo.o boo.o: FORCE
+# The script has an advantage over including the *.pp files directly
+# because it handles the case when header files are removed from the build.
+# 'make' would complain that there is no way to build missing headers.
+ifeq (,$(MAKE_RESTARTS))
+$(MDDEPDIR)/.all.pp: FORCE
+ @$(PERL) $(BUILD_TOOLS)/mddepend.pl $@ $(MDDEPEND_FILES)
+endif
+-include $(MDDEPDIR)/.all.pp
+else
+include $(MDDEPEND_FILES)
+endif
+endif
+
+endif
+endif
+#############################################################################
+
+-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-rules.mk
+-include $(MY_RULES)
+
+#
+# This speeds up gmake's processing if these files don't exist.
+#
+$(MY_CONFIG) $(MY_RULES):
+ @touch $@
+
+#
+# Generate Emacs tags in a file named TAGS if ETAGS was set in $(MY_CONFIG)
+# or in $(MY_RULES)
+#
+ifdef ETAGS
+ifneq ($(CSRCS)$(CPPSRCS)$(HEADERS),)
+all:: TAGS
+TAGS:: $(CSRCS) $(CPPSRCS) $(HEADERS)
+ $(ETAGS) $(CSRCS) $(CPPSRCS) $(HEADERS)
+endif
+endif
+
+################################################################################
+# Special gmake rules.
+################################################################################
+
+
+#
+# Disallow parallel builds with MSVC < 8
+#
+ifneq (,$(filter 1200 1300 1310,$(_MSC_VER)))
+.NOTPARALLEL:
+endif
+
+#
+# Re-define the list of default suffixes, so gmake won't have to churn through
+# hundreds of built-in suffix rules for stuff we don't need.
+#
+.SUFFIXES:
+
+#
+# Fake targets. Always run these rules, even if a file/directory with that
+# name already exists.
+#
+.PHONY: all all_platforms alltags boot checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_viewer run_apprunner tools $(DIRS) $(TOOL_DIRS) FORCE check check-interactive check-one
+
+# Used as a dependency to force targets to rebuild
+FORCE:
+
+# Delete target if error occurs when building target
+.DELETE_ON_ERROR:
+
+# Properly set LIBPATTERNS for the platform
+.LIBPATTERNS = $(if $(IMPORT_LIB_SUFFIX),$(LIB_PREFIX)%.$(IMPORT_LIB_SUFFIX)) $(LIB_PREFIX)%.$(LIB_SUFFIX) $(DLL_PREFIX)%$(DLL_SUFFIX)
+
+tags: TAGS
+
+TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h)
+ -etags $(CSRCS) $(CPPSRCS) $(wildcard *.h)
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+
+echo-variable-%:
+ @echo $($*)
+
+echo-tiers:
+ @echo $(TIERS)
+
+echo-dirs:
+ @echo $(DIRS)
+
+echo-module:
+ @echo $(MODULE)
+
+echo-requires:
+ @echo $(REQUIRES)
+
+echo-requires-recursive::
+ifdef _REPORT_ALL_DIRS
+ @echo $(subst $(topsrcdir)/,,$(srcdir)): $(MODULE): $(REQUIRES)
+else
+ @$(if $(REQUIRES),echo $(subst $(topsrcdir)/,,$(srcdir)): $(MODULE): $(REQUIRES))
+endif
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+
+echo-depth-path:
+ @$(topsrcdir)/build/unix/print-depth-path.sh
+
+echo-module-name:
+ @$(topsrcdir)/build/package/rpm/print-module-name.sh
+
+echo-module-filelist:
+ @$(topsrcdir)/build/package/rpm/print-module-filelist.sh
+
+showtargs:
+ifneq (,$(filter $(PROGRAM) $(HOST_PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY),$(TARGETS)))
+ @echo --------------------------------------------------------------------------------
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "SIMPLE_PROGRAMS = $(SIMPLE_PROGRAMS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "SHARED_LIBRARY = $(SHARED_LIBRARY)"
+ @echo "SHARED_LIBRARY_LIBS = $(SHARED_LIBRARY_LIBS)"
+ @echo "LIBS = $(LIBS)"
+ @echo "DEF_FILE = $(DEF_FILE)"
+ @echo "IMPORT_LIBRARY = $(IMPORT_LIBRARY)"
+ @echo "STATIC_LIBS = $(STATIC_LIBS)"
+ @echo "SHARED_LIBS = $(SHARED_LIBS)"
+ @echo "EXTRA_DSO_LIBS = $(EXTRA_DSO_LIBS)"
+ @echo "EXTRA_DSO_LDOPTS = $(EXTRA_DSO_LDOPTS)"
+ @echo "DEPENDENT_LIBS = $(DEPENDENT_LIBS)"
+ @echo --------------------------------------------------------------------------------
+endif
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+
+showbuild:
+ @echo "MOZ_BUILD_ROOT = $(MOZ_BUILD_ROOT)"
+ @echo "MOZ_WIDGET_TOOLKIT = $(MOZ_WIDGET_TOOLKIT)"
+ @echo "CC = $(CC)"
+ @echo "CXX = $(CXX)"
+ @echo "CCC = $(CCC)"
+ @echo "CPP = $(CPP)"
+ @echo "LD = $(LD)"
+ @echo "AR = $(AR)"
+ @echo "IMPLIB = $(IMPLIB)"
+ @echo "FILTER = $(FILTER)"
+ @echo "MKSHLIB = $(MKSHLIB)"
+ @echo "MKCSHLIB = $(MKCSHLIB)"
+ @echo "RC = $(RC)"
+ @echo "CFLAGS = $(CFLAGS)"
+ @echo "OS_CFLAGS = $(OS_CFLAGS)"
+ @echo "COMPILE_CFLAGS = $(COMPILE_CFLAGS)"
+ @echo "CXXFLAGS = $(CXXFLAGS)"
+ @echo "OS_CXXFLAGS = $(OS_CXXFLAGS)"
+ @echo "COMPILE_CXXFLAGS = $(COMPILE_CXXFLAGS)"
+ @echo "COMPILE_CMFLAGS = $(COMPILE_CMFLAGS)"
+ @echo "COMPILE_CMMFLAGS = $(COMPILE_CMMFLAGS)"
+ @echo "LDFLAGS = $(LDFLAGS)"
+ @echo "OS_LDFLAGS = $(OS_LDFLAGS)"
+ @echo "DSO_LDOPTS = $(DSO_LDOPTS)"
+ @echo "OS_INCLUDES = $(OS_INCLUDES)"
+ @echo "OS_LIBS = $(OS_LIBS)"
+ @echo "EXTRA_LIBS = $(EXTRA_LIBS)"
+ @echo "BIN_FLAGS = $(BIN_FLAGS)"
+ @echo "INCLUDES = $(INCLUDES)"
+ @echo "DEFINES = $(DEFINES)"
+ @echo "ACDEFINES = $(ACDEFINES)"
+ @echo "BIN_SUFFIX = $(BIN_SUFFIX)"
+ @echo "LIB_SUFFIX = $(LIB_SUFFIX)"
+ @echo "DLL_SUFFIX = $(DLL_SUFFIX)"
+ @echo "IMPORT_LIB_SUFFIX = $(IMPORT_LIB_SUFFIX)"
+ @echo "INSTALL = $(INSTALL)"
+
+showhost:
+ @echo "HOST_CC = $(HOST_CC)"
+ @echo "HOST_CXX = $(HOST_CXX)"
+ @echo "HOST_CFLAGS = $(HOST_CFLAGS)"
+ @echo "HOST_LDFLAGS = $(HOST_LDFLAGS)"
+ @echo "HOST_LIBS = $(HOST_LIBS)"
+ @echo "HOST_EXTRA_LIBS = $(HOST_EXTRA_LIBS)"
+ @echo "HOST_EXTRA_DEPS = $(HOST_EXTRA_DEPS)"
+ @echo "HOST_PROGRAM = $(HOST_PROGRAM)"
+ @echo "HOST_OBJS = $(HOST_OBJS)"
+ @echo "HOST_PROGOBJS = $(HOST_PROGOBJS)"
+ @echo "HOST_LIBRARY = $(HOST_LIBRARY)"
+
+showbuildmods::
+ @echo "Build Modules = $(BUILD_MODULES)"
+ @echo "Module dirs = $(BUILD_MODULE_DIRS)"
+
+zipmakes:
+ifneq (,$(filter $(PROGRAM) $(SIMPLE_PROGRAMS) $(LIBRARY) $(SHARED_LIBRARY),$(TARGETS)))
+ zip $(DEPTH)/makefiles $(subst $(topsrcdir),$(MOZ_SRC)/mozilla,$(srcdir)/Makefile.in)
+endif
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+
+documentation:
+ @cd $(DEPTH)
+ $(DOXYGEN) $(DEPTH)/config/doxygen.cfg
+
+check:: $(SUBMAKEFILES) $(MAKE_DIRS)
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/system-headers b/tools/node_modules/expresso/deps/jscoverage/js/config/system-headers
new file mode 100644
index 0000000..9d61c0e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/system-headers
@@ -0,0 +1,1038 @@
+A4Stuff.h
+activscp.h
+AEDataModel.h
+AEObjects.h
+AEPackObject.h
+AERegistry.h
+AEUtils.h
+afxcmn.h
+afxcoll.h
+afxcview.h
+afxdisp.h
+afxdtctl.h
+afxext.h
+afxmt.h
+afxpriv.h
+afxtempl.h
+afxwin.h
+algorithm
+Aliases.h
+all.h
+alloca.h
+alloc.h
+alsa/asoundlib.h
+alsa/pcm.h
+alsa/mixer.h
+ansi_parms.h
+a.out.h
+app/Cursor.h
+Appearance.h
+AppFileInfo.h
+AppKit.h
+AppleEvents.h
+Application.h
+app/Message.h
+app/MessageRunner.h
+arpa/inet.h
+arpa/nameser.h
+asm/sigcontext.h
+asm/signal.h
+ASRegistry.h
+assert.h
+atk/atk.h
+atlbase.h
+atlcom.h
+atlconv.h
+atlctl.cpp
+atlctl.h
+ATLCTL.H
+atlhost.h
+atlimpl.cpp
+atlwin.cpp
+ATSTypes.h
+ATSUnicode.h
+Balloons.h
+base/pblock.h
+base/PCR_Base.h
+base/session.h
+basetyps.h
+be/app/Application.h
+Beep.h
+be/kernel/image.h
+be/kernel/OS.h
+bfd.h
+Bitmap.h
+bsd/libc.h
+bsd/syscall.h
+bstring.h
+builtin.h
+Button.h
+byteswap.h
+#if MOZ_ENABLE_LIBXUL!=1
+#define WRAP_CAIRO_HEADERS
+#endif
+#if MOZ_TREE_CAIRO!=1
+#define WRAP_CAIRO_HEADERS
+#endif
+#ifdef WRAP_CAIRO_HEADERS
+cairo.h
+cairo-atsui.h
+cairo-beos.h
+cairo-ft.h
+cairo-glitz.h
+cairo-os2.h
+cairo-pdf.h
+cairo-ps.h
+cairo-quartz.h
+cairo-win32.h
+cairo-xlib.h
+cairo-xlib-xrender.h
+cairo-directfb.h
+cairo-qpainter.h
+#endif
+dfiff.h
+fusion/reactor.h
+fusion/property.h
+fusion/conf.h
+fusion/build.h
+fusion/hash.h
+fusion/shm/shm.h
+fusion/shm/shm_internal.h
+fusion/shm/pool.h
+fusion/ref.h
+fusion/fusion_internal.h
+fusion/lock.h
+fusion/types.h
+fusion/vector.h
+fusion/call.h
+fusion/shmalloc.h
+fusion/protocol.h
+fusion/fusion.h
+fusion/arena.h
+fusion/object.h
+directfbgl.h
+directfb_version.h
+directfb.h
+directfb_util.h
+directfb_keynames.h
+dgiff.h
+direct/util.h
+direct/memcpy.h
+direct/interface.h
+direct/conf.h
+direct/tree.h
+direct/signals.h
+direct/build.h
+direct/interface_implementation.h
+direct/utf8.h
+direct/serial.h
+direct/hash.h
+direct/direct.h
+direct/clock.h
+direct/types.h
+direct/mem.h
+direct/thread.h
+direct/debug.h
+direct/stream.h
+direct/messages.h
+direct/trace.h
+direct/modules.h
+direct/log.h
+direct/system.h
+direct/list.h
+dfb_types.h
+directfb_strings.h
+directfb_keyboard.h
+callconv.h
+Carbon/Carbon.h
+CarbonEvents.h
+Carbon.h
+cassert
+c_asm.h
+cctype
+cderr.h
+cerrno
+cert.h
+CFBase.h
+CFBundle.h
+CFData.h
+CFDictionary.h
+cf.h
+CFNumber.h
+CFPlugIn.h
+CFPreferences.h
+CFString.h
+CFURL.h
+CGAffineTransform.h
+CheckBox.h
+climits
+Clipboard.h
+cmplrs/stsupport.h
+Cocoa/Cocoa.h
+CodeFragments.h
+comdef.h
+commctrl.h
+COMMCTRL.H
+commdlg.h
+compat.h
+condapi.h
+ConditionalMacros.h
+config.h
+conio.h
+console.h
+ControlDefinitions.h
+Controls.h
+CoreFoundation/CoreFoundation.h
+CoreServices/CoreServices.h
+CPalmRec.cpp
+Cpalmrec.h
+CPCatgry.cpp
+CPDbBMgr.h
+CPString.cpp
+CPString.h
+crtdbg.h
+crt_externs.h
+crypt.h
+cstdio
+cstdlib
+cstring
+ctime
+ctype.h
+curl/curl.h
+curl/easy.h
+curl/types.h
+curses.h
+cxxabi.h
+DateTimeUtils.h
+dbus/dbus.h
+dbus/dbus-glib.h
+dbus/dbus-glib-lowlevel.h
+ddeml.h
+Debug.h
+dem.h
+descrip.h
+Devices.h
+Dialogs.h
+direct.h
+dirent.h
+DiskInit.h
+dlfcn.h
+dlgs.h
+dl.h
+docobj.h
+dos/dosextens.h
+dos.h
+Drag.h
+DriverServices.h
+DriverSynchronization.h
+DropInPanel.h
+dvidef.h
+elf.h
+endian.h
+Entry.h
+errno.h
+Errors.h
+Events.h
+exdisp.h
+ExDisp.h
+exe386.h
+execinfo.h
+extras.h
+fabdef.h
+fcntl.h
+features.h
+fibdef.h
+File.h
+filehdr.h
+files.h
+Files.h
+FindDirectory.h
+Finder.h
+FinderRegistry.h
+FixMath.h
+float.h
+Folders.h
+fontconfig/fontconfig.h
+fontconfig/fcfreetype.h
+Font.h
+Fonts.h
+fp.h
+fpieee.h
+frame/log.h
+frame/req.h
+freetype/freetype.h
+freetype/ftcache.h
+freetype/ftglyph.h
+freetype/ftsynth.h
+freetype/ftoutln.h
+freetype/ttnameid.h
+freetype/tttables.h
+freetype/t1tables.h
+fribidi/fribidi.h
+FSp_fopen.h
+fstream.h
+ft2build.h
+gconf/gconf-client.h
+Gdiplus.h
+gdk/gdkevents.h
+gdk/gdk.h
+gdk/gdkkeysyms.h
+gdk/gdkpango.h
+gdk/gdkprivate.h
+gdk/gdkscreen.h
+gdk/gdkregion.h
+gdk/gdkwindow.h
+gdk/gdkx.h
+gdk/gdkdirectfb.h
+gdk-pixbuf/gdk-pixbuf.h
+Gestalt.h
+getopt.h
+glibconfig.h
+glib.h
+glib-object.h
+gmodule.h
+gnome.h
+gnu/libc-version.h
+grp.h
+gssapi_generic.h
+gssapi/gssapi_generic.h
+gssapi/gssapi.h
+gssapi.h
+gtk/gtkbindings.h
+gtk/gtkbutton.h
+gtk/gtkclipboard.h
+gtk/gtkcontainer.h
+gtk/gtkdialog.h
+gtk/gtkentry.h
+gtk/gtkfixed.h
+gtk/gtk.h
+gtk/gtkiconfactory.h
+gtk/gtkimage.h
+gtk/gtkimmulticontext.h
+gtk/gtkinvisible.h
+gtk/gtkmain.h
+gtk/gtkmessagedialog.h
+gtk/gtkobject.h
+gtk/gtkprinter.h
+gtk/gtkprintjob.h
+gtk/gtkprintunixdialog.h
+gtk/gtkprivate.h
+gtk/gtkselection.h
+gtk/gtksignal.h
+gtk/gtksocket.h
+gtk/gtkstock.h
+gtk/gtkstyle.h
+gtk/gtktextview.h
+gtk/gtkvscrollbar.h
+gtk/gtkwidget.h
+gtk/gtkwindow.h
+gtk/gtkversion.h
+HIToolbox/HIToolbox.h
+hlink.h
+htiface.h
+ia64/sys/inline.h
+Icons.h
+iconv.h
+IDL.h
+ieeefp.h
+ifaddrs.h
+image.h
+imagehlp.h
+imm.h
+initguid.h
+InterfaceDefs.h
+InternetConfig.h
+IntlResources.h
+ints.h
+intshcut.h
+inttypes.h
+iodef.h
+io.h
+IOKit/IOKitLib.h
+IOKit/IOMessage.h
+IOKit/pwr_mgt/IOPMLib.h
+iomanip
+iostream
+iostream.h
+jar.h
+JavaControl.h
+JavaEmbedding/JavaControl.h
+JavaVM/jni.h
+JManager.h
+JNIEnvTests.h
+jni.h
+#if MOZ_NATIVE_JPEG==1
+jpeglib.h
+#endif
+JVMManagerTests.h
+Kerberos/Kerberos.h
+kernel/image.h
+kernel/OS.h
+key.h
+keyt.h
+keythi.h
+LAction.h
+langinfo.h
+LApplication.h
+LArray.h
+LArrayIterator.h
+LAttachable.h
+LAttachment.h
+LaunchServices.h
+lber.h
+LBroadcaster.h
+LButton.h
+lcache.h
+LCaption.h
+LCheckBox.h
+LCicnButton.h
+LClipboard.h
+LCommander.h
+LComparator.h
+LControl.h
+ldap.h
+ldaplog.h
+ldappr.h
+ldap_ssl.h
+LDataStream.h
+ldfcn.h
+LDialogBox.h
+ldif.h
+LDocApplication.h
+LDocument.h
+LDragAndDrop.h
+LDragTask.h
+LEditField.h
+LEditText.h
+LEventDispatcher.h
+LFile.h
+LFileStream.h
+LFileTypeList.h
+LFocusBox.h
+LGrafPortView.h
+LHandleStream.h
+libc_r.h
+libelf.h
+libelf/libelf.h
+libgen.h
+libgnome/gnome-url.h
+libgnome/libgnome.h
+libgnomeui/gnome-icon-lookup.h
+libgnomeui/gnome-icon-theme.h
+libgnomeui/gnome-ui-init.h
+libgnomevfs/gnome-vfs-application-registry.h
+libgnomevfs/gnome-vfs-file-info.h
+libgnomevfs/gnome-vfs.h
+libgnomevfs/gnome-vfs-init.h
+libgnomevfs/gnome-vfs-mime.h
+libgnomevfs/gnome-vfs-mime-handlers.h
+libgnomevfs/gnome-vfs-mime-info.h
+libgnomevfs/gnome-vfs-mime-utils.h
+libgnomevfs/gnome-vfs-ops.h
+libgnomevfs/gnome-vfs-standard-callbacks.h
+libIDL/IDL.h
+lib$routines.h
+limits
+limits.h
+link.h
+linux/kernel.h
+linux/limits.h
+linux/rtc.h
+linux/version.h
+list
+List.h
+Lists.h
+LiveConnectManagerTests.h
+LListBox.h
+LListener.h
+LMenuBar.h
+LMenu.h
+LModelDirector.h
+LModelObject.h
+LModelProperty.h
+loader.h
+locale
+locale.h
+LOffscreenView.h
+logkeys.h
+logstrng.h
+Looper.h
+LowMem.h
+LPane.h
+LPeriodical.h
+LPicture.h
+LPlaceHolder.h
+LPrintout.h
+LProgressBar.h
+LPushButton.h
+LRadioGroup.h
+LRadioGroupView.h
+LRunArray.h
+LScroller.h
+LSharable.h
+LSingleDoc.h
+LStaticText.h
+LStdControl.h
+LStream.h
+LString.h
+LTabGroup.h
+LTabGroupView.h
+LTableArrayStorage.h
+LTableMonoGeometry.h
+LTableSingleSelector.h
+LTableView.h
+LTextEditView.h
+LTextTableView.h
+LUndoer.h
+LVariableArray.h
+LView.h
+LWindow.h
+m68881.h
+MacErrors.h
+MacHeadersCarbon.h
+machine/ansi.h
+machine/builtins.h
+machine/clock.h
+machine/endian.h
+machine/frame.h
+machine/inline.h
+machine/limits.h
+machine/signal.h
+machine/trap.h
+mach/mach_host.h
+mach/mach_init.h
+mach/mach_interface.h
+mach/mach_port.h
+mach-o/dyld.h
+MacLocales.h
+MacMemory.h
+MacTCP.h
+MacTypes.h
+MacWindows.h
+malloc.h
+map
+mapicode.h
+mapidefs.h
+mapiguid.h
+mapi.h
+mapitags.h
+mapiutil.h
+mapix.h
+Math64.h
+math.h
+mbstring.h
+mem.h
+memory
+memory.h
+Memory.h
+MenuBar.h
+Menu.h
+Menus.h
+Message.h
+Mime.h
+MixedMode.h
+mlang.h
+mmsystem.h
+model.h
+Movies.h
+mpw/errno.h
+mshtmhst.h
+mshtml.h
+mswsock.h
+Multiprocessing.h
+mutex.h
+Navigation.h
+ncompat.h
+ncurses.h
+netCore.h
+netdb.h
+net/if.h
+netinet/in.h
+netinet/in_systm.h
+netinet/tcp.h
+new
+newexe.h
+new.h
+nl_types.h
+NodeInfo.h
+nss.h
+nssilock.h
+objbase.h
+objidl.h
+Objsafe.h
+ojiapitests.h
+ole2.h
+oleidl.h
+OpenTptInternet.h
+OpenTransport.h
+os2.h
+OS.h
+osreldate.h
+OSUtils.h
+Packages.h
+Palettes.h
+PALM_CMN.H
+pango-engine.h
+pango-glyph.h
+pango-modules.h
+pango/pangocairo.h
+pango/pangofc-decoder.h
+pango/pangofc-font.h
+pango/pangofc-fontmap.h
+pango/pango-break.h
+pango/pango-fontmap.h
+pango/pango.h
+pango/pangoxft.h
+pango/pangox.h
+pango/pango-utils.h
+pango-types.h
+pascal.h
+Patches.h
+Path.h
+pcfs/pc_dir.h
+Pgenerr.h
+PGenErr.h
+Ph.h
+photon/Pg.h
+photon/PhProto.h
+photon/PhRender.h
+photon/PpProto.h
+photon/PtProgress.h
+photon/PtServer.h
+photon/PtWebClient.h
+photon/PxImage.h
+pk11func.h
+pk11pub.h
+pkcs11t.h
+PLStringFuncs.h
+PMApplication.h
+pmddim.h
+poll.h
+Polygon.h
+portable.h
+Power.h
+PP_ClassHeaders.cp
+PP_Constants.h
+PPCToolbox.h
+PP_DebugHeaders.cp
+PP_KeyCodes.h
+PP_Macros.h
+PP_Messages.h
+PP_Prefix.h
+PP_Resources.h
+PP_Types.h
+Printing.h
+Print/PMPrintingDialogExtensions.h
+private/qucomextra_p.h
+Processes.h
+process.h
+Process.h
+proto/dos.h
+proto/exec.h
+psap.h
+Pt.h
+pthread.h
+pwd.h
+Python.h
+QDOffscreen.h
+Quickdraw.h
+QuickDraw.h
+QuickTimeComponents.h
+quipu/attr.h
+rasdlg.h
+raserror.h
+ras.h
+regex.h
+Region.h
+resolv.h
+Resources.h
+Retrace.h
+rld_interface.h
+rmsdef.h
+Roster.h
+rpc.h
+rpcproxy.h
+rpc/types.h
+sane/sane.h
+sane/sanei.h
+sane/saneopts.h
+Scrap.h
+Screen.h
+Script.h
+ScrollBar.h
+seccomon.h
+sec.h
+secmod.h
+secmodt.h
+secrng.h
+security.h
+secutil.h
+semaphore.h
+servprov.h
+setjmp.h
+SFNTLayoutTypes.h
+SFNTTypes.h
+share.h
+shellapi.h
+shlguid.h
+shlobj.h
+sigcontext.h
+signal.h
+SimpleGameSound.h
+SIOUX.h
+size_t.h
+someincludefile.h
+Sound.h
+sqlite3.h
+ssdef.h
+sslerr.h
+ssl.h
+sslproto.h
+sstream
+stack
+StandardFile.h
+starlet.h
+stat.h
+statreg.cpp
+statreg.h
+stdarg.h
+stdbool.h
+stddef.h
+stdint.h
+stdio.h
+stdlib.h
+storage/FindDirectory.h
+StorageKit.h
+string
+StringCompare.h
+string.h
+String.h
+strings.h
+Strings.h
+StringView.h
+stropts.h
+strstrea.h
+structs.h
+stsdef.h
+SupportDefs.h
+support/String.h
+support/SupportDefs.h
+support/TLS.h
+svrcore.h
+symconst.h
+sym.h
+synch.h
+syncmgr.h
+sys/atomic_op.h
+sys/bitypes.h
+sys/byteorder.h
+syscall.h
+sys/cdefs.h
+sys/cfgodm.h
+sys/elf.h
+sys/endian.h
+sys/errno.h
+sys/fault.h
+sys/fcntl.h
+sys/file.h
+sys/filio.h
+sys/frame.h
+sys/immu.h
+sys/inttypes.h
+sys/ioccom.h
+sys/ioctl.h
+sys/ipc.h
+sys/ldr.h
+sys/link.h
+sys/locking.h
+syslog.h
+sys/lwp.h
+sys/machine.h
+sys/mman.h
+sys/mmu.h
+sys/mount.h
+sys/mpctl.h
+sys/param.h
+sys/pda.h
+sys/poll.h
+sys/ppc.h
+sys/prctl.h
+sys/priv.h
+sys/procfs.h
+sys/pstat.h
+sys/ptrace.h
+sys/queue.h
+sys/reg.h
+sys/regset.h
+sys/resource.h
+sys/sched.h
+sys/select.h
+sys/sem.h
+sys/sendfile.h
+sys/shm.h
+sys/siginfo.h
+sys/signal.h
+sys/socket.h
+sys/sockio.h
+sys/sparc/frame.h
+sys/stack.h
+sys/statfs.h
+sys/stat.h
+sys/statvfs.h
+sys/syscall.h
+sys/sysctl.h
+sys/sysinfo.h
+sys/sysmp.h
+sys/syssgi.h
+sys/systeminfo.h
+sys/timeb.h
+sys/time.h
+sys/times.h
+sys/ttycom.h
+sys/types.h
+sys/ucontext.h
+sys/uio.h
+sys/un.h
+sys/unistd.h
+sys/utsname.h
+sys/vfs.h
+sys/wait.h
+tables.h
+TArray.h
+TArrayIterator.h
+task.h
+tchar.h
+TCHAR.H
+termios.h
+TextCommon.h
+TextEdit.h
+TextEncodingConverter.h
+TextServices.h
+TextUtils.h
+TextView.h
+th/PCR_Th.h
+thread.h
+ThreadManagerTests.h
+Threads.h
+time.h
+Timer.h
+tlhelp32.h
+ToolUtils.h
+trace.h
+Traps.h
+typeinfo
+types.h
+Types.h
+UAppleEventsMgr.h
+UAttachments.h
+ucontext.h
+uconv.h
+UCursor.h
+ucx$inetdef.h
+UDebugging.h
+UDesktop.h
+UDrawingState.h
+UDrawingUtils.h
+UEnvironment.h
+UEventMgr.h
+UException.h
+UExtractFromAEDesc.h
+UGWorld.h
+UKeyFilters.h
+ulocks.h
+ulserrno.h
+UMemoryMgr.h
+UModalDialogs.h
+UNavServicesDialogs.h
+UnicodeBlockObjects.h
+UnicodeConverter.h
+UnicodeUtilities.h
+unidef.h
+unikbd.h
+unistd.h
+unix.h
+unixio.h
+unixlib.h
+unknwn.h
+UPrinting.h
+UQuickTime.h
+UReanimator.h
+URegions.h
+URegistrar.h
+UResourceMgr.h
+urlhist.h
+urlmon.h
+UScrap.h
+UScreenPort.h
+UTCUtils.h
+UTETextAction.h
+UTEViewTextAction.h
+UTextEdit.h
+UTextTraits.h
+utility
+utime.h
+UWindows.h
+values.h
+varargs.h
+vcclr.h
+vector
+View.h
+Volume.h
+wab.h
+wait.h
+wchar.h
+winbase.h
+win/compobj.h
+windef.h
+Window.h
+windows.h
+Windows.h
+windowsx.h
+Wininet.h
+winnls.h
+winperf.h
+winreg.h
+Winreg.h
+winsock2.h
+winsock.h
+winspool.h
+winsvc.h
+winuser.h
+winver.h
+wmem.h
+workbench/startup.h
+wtypes.h
+wx/image.h
+wx/listctrl.h
+wx/log.h
+wx/toolbar.h
+wx/wx.h
+wx/xrc/xmlres.h
+X11/cursorfont.h
+X11/extensions/Print.h
+X11/extensions/shape.h
+X11/extensions/XIElib.h
+X11/extensions/XShm.h
+X11/extensions/Xrender.h
+X11/Intrinsic.h
+X11/keysymdef.h
+X11/keysym.h
+X11/Shell.h
+X11/StringDefs.h
+X11/Xatom.h
+X11/Xft/Xft.h
+X11/Xfuncproto.h
+X11/X.h
+X11/XKBlib.h
+X11/Xlib.h
+X11/Xlibint.h
+X11/Xlocale.h
+X11/Xos.h
+X11/Xutil.h
+xpt_struct.h
+xpt_xdr.h
+zmouse.h
+sslt.h
+smime.h
+cms.h
+sechash.h
+secoidt.h
+certdb.h
+secerr.h
+nssb64.h
+secasn1.h
+secder.h
+certt.h
+ocsp.h
+keyhi.h
+cryptohi.h
+crmf.h
+pk11pqg.h
+cmmf.h
+base64.h
+secdert.h
+secitem.h
+secmime.h
+nssckbi.h
+pkcs12.h
+p12plcy.h
+pk11sdr.h
+nspr.h
+pratom.h
+prbit.h
+prclist.h
+prcmon.h
+prcountr.h
+prcvar.h
+prdtoa.h
+prenv.h
+prerr.h
+prerror.h
+prinet.h
+prinit.h
+prinrval.h
+prio.h
+pripcsem.h
+prlink.h
+prlock.h
+prlog.h
+prlong.h
+prmem.h
+prmon.h
+prmwait.h
+prnetdb.h
+prolock.h
+prpdce.h
+prprf.h
+prproces.h
+prrng.h
+prrwlock.h
+prshm.h
+prshma.h
+prsystem.h
+prthread.h
+prtime.h
+prtpool.h
+prtrace.h
+prtypes.h
+prvrsion.h
+plbase64.h
+plerror.h
+plgetopt.h
+plresolv.h
+plstr.h
+plarenas.h
+plarena.h
+plhash.h
+#if MOZ_NATIVE_PNG==1
+png.h
+#endif
+#if MOZ_NATIVE_ZLIB==1
+zlib.h
+#endif
+#if MOZ_ENABLE_LIBXUL!=1
+#if BUILD_STATIC_LIBS!=1
+#define WRAP_LCMS_HEADERS
+#endif
+#endif
+#if MOZ_NATIVE_LCMS==1
+#define WRAP_LCMS_HEADERS
+#endif
+#ifdef WRAP_LCMS_HEADERS
+icc34.h
+lcms.h
+#endif
+#ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
+libsn/sn.h
+libsn/sn-common.h
+libsn/sn-launchee.h
+libsn/sn-launcher.h
+libsn/sn-monitor.h
+libsn/sn-util.h
+#endif
+#if MOZ_NATIVE_HUNSPELL==1
+hunspell.hxx
+#endif
+#if MOZ_NATIVE_BZ2==1
+bzlib.h
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/version.mk b/tools/node_modules/expresso/deps/jscoverage/js/config/version.mk
new file mode 100644
index 0000000..3993b3f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/version.mk
@@ -0,0 +1,85 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Win32 Version System.
+#
+# The Initial Developer of the Original Code is Netscape Communications Corporation
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+ifndef INCLUDED_VERSION_MK
+INCLUDED_VERSION_MK=1
+
+# Windows gmake build:
+# Build default .rc file if $(RESFILE) isn't defined.
+# TODO:
+# PBI : Private build info. Not used currently.
+# Guessing the best way would be to set an env var.
+# BINARY : Binary name. Not used currently.
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+ifndef RESFILE
+RCFILE=./module.rc
+RESFILE=./module.res
+_RC_STRING = -QUIET 1 -DEPTH $(DEPTH) -TOPSRCDIR $(topsrcdir) -BITS $(MOZ_BITS) -OBJDIR . -SRCDIR $(srcdir) -DISPNAME $(MOZ_APP_DISPLAYNAME)
+ifneq ($(BUILD_OFFICIAL)_$(MOZILLA_OFFICIAL),_)
+_RC_STRING += -OFFICIAL 1
+endif
+ifdef MOZ_DEBUG
+_RC_STRING += -DEBUG 1
+endif
+ifdef MODULE
+_RC_STRING += -MODNAME $(MODULE)
+endif
+ifdef PROGRAM
+_RC_STRING += -BINARY $(PROGRAM)
+else
+ifdef _PROGRAM
+_RC_STRING += -BINARY $(_PROGRAM)
+else
+ifdef SHARED_LIBRARY
+_RC_STRING += -BINARY $(SHARED_LIBRARY)
+endif
+endif
+endif
+ifdef RCINCLUDE
+_RC_STRING += -RCINCLUDE $(srcdir)/$(RCINCLUDE)
+endif
+
+GARBAGE += $(RESFILE) $(RCFILE)
+
+#dummy target so $(RCFILE) doesn't become the default =P
+all::
+
+$(RCFILE): $(RCINCLUDE) $(topsrcdir)/config/version_win.pl
+ $(PERL) $(topsrcdir)/config/version_win.pl $(_RC_STRING)
+
+endif # RESFILE
+endif # Windows
+
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/version_win.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/version_win.pl
new file mode 100644
index 0000000..094530e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/version_win.pl
@@ -0,0 +1,423 @@
+#!/usr/bin/perl -w
+
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Win32 Version System.
+#
+# The Initial Developer of the Original Code is Brian Bober <netdemonz@yahoo.com>
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#use diagnostics;
+require strict;
+my $dir = $0;
+$dir =~ s/[^\/]*$//;
+push(@INC, "$dir");
+require "Moz/Milestone.pm";
+use Getopt::Long;
+use Getopt::Std;
+use POSIX;
+
+# Calculate the number of days since Jan. 1, 2000 from a buildid string
+sub daysFromBuildID
+{
+ my ($buildid,) = @_;
+
+ my ($y, $m, $d, $h) = ($buildid =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/);
+ $d || die("Unrecognized buildid string.");
+
+ my $secondstodays = 60 * 60 * 24;
+ return (POSIX::mktime(00, 00, 00, $d, $m, $y - 1900) -
+ POSIX::mktime(00, 00, 00, 01, 01, 100)) / $secondstodays;
+}
+
+#Creates version resource file
+
+#Paramaters are passed on the command line:
+
+#Example: -MODNAME nsToolkitCompsModule -DEBUG=1
+
+# DEBUG - Mozilla's global debug variable - tells if its debug version
+# OFFICIAL - tells Mozilla is building a milestone or nightly
+# MSTONE - tells which milestone is being built;
+# OBJDIR - Holds the object directory;
+# MODNAME - tells what the name of the module is like nsBMPModule
+# DEPTH - Holds the path to the root obj dir
+# TOPSRCDIR - Holds the path to the root mozilla dir
+# SRCDIR - Holds module.ver and source
+# BINARY - Holds the name of the binary file
+# DISPNAME - Holds the display name of the built application
+# BITS - 16 or 32 bit
+# RCINCLUDE - Holds the name of the RC File to include or ""
+# QUIET - Turns off output
+
+#Description and Comment come from module.ver
+#Bug 23560
+#http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/rc_7x2d.asp
+
+#Get next .ver file entry
+sub getNextEntry
+{
+ while (<VERFILE>)
+ {
+ my $mline = $_;
+ ($mline) = split(/#/,$mline);
+ my ($entry, $value)=split(/=/,$mline,2);
+ if (defined($entry))
+ {
+ if (defined($value))
+ {
+ $entry =~ s/^\s*(.*?)\s*$/$1/;
+ $value =~ s/^\s*(.*?)\s*$/$1/;
+ return ($entry,$value);
+ }
+ }
+ }
+ return undef;
+}
+
+my ($quiet,$objdir,$debug,$official,$milestone,$buildid,$module,$binary,$depth,$rcinclude,$bits,$srcdir,$fileversion,$productversion);
+
+GetOptions( "QUIET" => \$quiet,
+ "DEBUG=s" => \$debug,
+ "OFFICIAL=s" => \$official,
+ "MSTONE=s" => \$milestone,
+ "MODNAME=s" => \$module,
+ "BINARY=s" => \$binary,
+ "DISPNAME=s" => \$displayname,
+ "SRCDIR=s" => \$srcdir,
+ "TOPSRCDIR=s" => \$topsrcdir,
+ "DEPTH=s" => \$depth,
+ "RCINCLUDE=s" => \$rcinclude,
+ "OBJDIR=s" => \$objdir,
+ "BITS=s" => \$bits);
+if (!defined($debug)) {$debug="";}
+if (!defined($official)) {$official="";}
+if (!defined($milestone)) {$milestone="";}
+if (!defined($module)) {$module="";}
+if (!defined($binary)) {$binary="";}
+if (!defined($displayname)) {$displayname="Mozilla";}
+if (!defined($depth)) {$depth=".";}
+if (!defined($rcinclude)) {$rcinclude="";}
+if (!defined($objdir)) {$objdir=".";}
+if (!defined($srcdir)) {$srcdir=".";}
+if (!defined($topsrcdir)) {$topsrcdir=".";}
+if (!defined($bits)) {$bits="";}
+my $mfversion = "Personal";
+my $mpversion = "Personal";
+my @fileflags = ("0");
+my $comment="";
+my $description="";
+if (!defined($module))
+{
+ $module = $binary;
+ ($module) = split(/\./,$module);
+}
+
+my $fileos = "VOS__WINDOWS32";
+if ($bits eq "16") { $fileos="VOS__WINDOWS16"; }
+
+my $bufferstr=" ";
+
+my $MILESTONE_FILE = "$topsrcdir/config/milestone.txt";
+my $BUILDID_FILE = "$depth/config/buildid";
+
+#Read module.ver file
+#Version file overrides for WIN32:
+#WIN32_MODULE_COMMENT
+#WIN32_MODULE_DESCRIPTION
+#WIN32_MODULE_FILEVERSION
+#WIN32_MODULE_COMPANYNAME
+#WIN32_MODULE_FILEVERSION_STRING
+#WIN32_MODULE_NAME
+#WIN32_MODULE_COPYRIGHT
+#WIN32_MODULE_TRADEMARKS
+#WIN32_MODULE_ORIGINAL_FILENAME
+#WIN32_MODULE_PRODUCTNAME
+#WIN32_MODULE_PRODUCTVERSION
+#WIN32_MODULE_PRODUCTVERSION_STRING
+
+#Override values obtained from the .ver file
+my $override_comment;
+my $override_description;
+my $override_fileversion;
+my $override_company;
+my $override_mfversion;
+my $override_module;
+my $override_copyright;
+my $override_trademarks;
+my $override_filename;
+my $override_productname;
+my $override_productversion;
+my $override_mpversion;
+if (open(VERFILE, "<$srcdir/module.ver"))
+{
+
+ my ($a,$b) = getNextEntry();
+ while (defined($a))
+ {
+ if ($a eq "WIN32_MODULE_COMMENT") { $override_comment = $b; }
+ if ($a eq "WIN32_MODULE_DESCRIPTION") { $override_description = $b; }
+ if ($a eq "WIN32_MODULE_FILEVERSION") { $override_fileversion = $b; }
+ if ($a eq "WIN32_MODULE_COMPANYNAME") { $override_company = $b; }
+ if ($a eq "WIN32_MODULE_FILEVERSION_STRING") { $override_mfversion = $b; }
+ if ($a eq "WIN32_MODULE_NAME") { $override_module = $b; }
+ if ($a eq "WIN32_MODULE_COPYRIGHT") { $override_copyright = $b; }
+ if ($a eq "WIN32_MODULE_TRADEMARKS") { $override_trademarks = $b; }
+ if ($a eq "WIN32_MODULE_ORIGINAL_FILENAME") { $override_filename = $b; }
+ if ($a eq "WIN32_MODULE_PRODUCTNAME") { $override_productname = $b; }
+ if ($a eq "WIN32_MODULE_PRODUCTVERSION") { $override_productversion = $b; }
+ if ($a eq "WIN32_MODULE_PRODUCTVERSION_STRING") { $override_mpversion = $b; }
+ ($a,$b) = getNextEntry();
+ }
+ close(VERFILE)
+}
+else
+{
+ if (!$quiet || $quiet ne "1") { print "$bufferstr" . "WARNING: No module.ver file included ($module, $binary). Default values used\n"; }
+}
+#Get rid of trailing and leading whitespace
+$debug =~ s/^\s*(.*)\s*$/$1/;
+$comment =~ s/^\s*(.*)\s*$/$1/;
+$official =~ s/^\s*(.*)\s*$/$1/;
+$milestone =~ s/^\s*(.*)\s*$/$1/;
+$description =~ s/^\s*(.*)\s*$/$1/;
+$module =~ s/^\s*(.*)\s*$/$1/;
+$depth =~ s/^\s*(.*)\s*$/$1/;
+$binary =~ s/^\s*(.*)\s*$/$1/;
+$displayname =~ s/^\s*(.*)\s*$/$1/;
+
+open(BUILDID, "<", $BUILDID_FILE) || die("Couldn't open buildid file: $BUILDID_FILE");
+$buildid = <BUILDID>;
+$buildid =~ s/\s*$//;
+close BUILDID;
+
+my $daycount = daysFromBuildID($buildid);
+
+if ($milestone eq "") {
+ $milestone = Moz::Milestone::getOfficialMilestone($MILESTONE_FILE);
+}
+
+$mfversion = $mpversion = $milestone;
+
+if ($debug eq "1")
+{
+ push @fileflags, "VS_FF_DEBUG";
+ $mpversion .= " Debug";
+ $mfversion .= " Debug";
+}
+
+if ($official ne "1") {
+ push @fileflags, "VS_FF_PRIVATEBUILD";
+}
+
+if ($milestone =~ /[a-z]/) {
+ push @fileflags, "VS_FF_PRERELEASE";
+}
+
+my @mstone = split(/\./,$milestone);
+$mstone[1] =~s/\D.*$//;
+if (!$mstone[2]) {
+ $mstone[2] = "0";
+}
+else {
+ $mstone[2] =~s/\D.*$//;
+}
+$fileversion = $productversion="$mstone[0],$mstone[1],$mstone[2],$daycount";
+
+my $copyright = "License: MPL 1.1/GPL 2.0/LGPL 2.1";
+my $company = "Mozilla Foundation";
+my $trademarks = "Mozilla";
+my $productname = $displayname;
+
+
+if (defined($override_comment)){$override_comment =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $comment=$override_comment;}
+if (defined($override_description)){$override_description =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $description=$override_description;}
+if (defined($override_fileversion)){$fileversion=$override_fileversion;}
+if (defined($override_mfversion)){$mfversion=$override_mfversion;}
+if (defined($override_company)){$company=$override_company;}
+if (defined($override_module)){$override_module =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $module=$override_module;}
+if (defined($override_copyright)){$override_copyright =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $copyright=$override_copyright;}
+if (defined($override_trademarks)){$override_trademarks =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $trademarks=$override_trademarks;}
+if (defined($override_filename)){$binary=$override_filename;}
+if (defined($override_productname)){$override_productname =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $productname=$override_productname;}
+if (defined($override_productversion)){$productversion=$override_productversion;}
+if (defined($override_mpversion)){$mpversion=$override_mpversion;}
+
+
+#Override section
+
+open(RCFILE, ">$objdir/module.rc") || die("Can't edit module.rc - It must be locked.\n");
+print RCFILE qq{
+// ***** BEGIN LICENSE BLOCK *****
+// Version: MPL 1.1/GPL 2.0/LGPL 2.1
+//
+// The contents of this file are subject to the Mozilla Public License Version
+// 1.1 (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+// http://www.mozilla.org/MPL/
+//
+// Software distributed under the License is distributed on an "AS IS" basis,
+// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+// for the specific language governing rights and limitations under the
+// License.
+//
+// The Original Code is the Win32 Version System.
+//
+// The Initial Developer of the Original Code is Brian Bober <netdemonz\@yahoo.com>
+// Portions created by the Initial Developer are Copyright (C) 2001
+// the Initial Developer. All Rights Reserved.
+//
+// Contributor(s):
+//
+// Alternatively, the contents of this file may be used under the terms of
+// either the GNU General Public License Version 2 or later (the "GPL"), or
+// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+// in which case the provisions of the GPL or the LGPL are applicable instead
+// of those above. If you wish to allow use of your version of this file only
+// under the terms of either the GPL or the LGPL, and not to allow others to
+// use your version of this file under the terms of the MPL, indicate your
+// decision by deleting the provisions above and replace them with the notice
+// and other provisions required by the GPL or the LGPL. If you do not delete
+// the provisions above, a recipient may use your version of this file under
+// the terms of any one of the MPL, the GPL or the LGPL.
+//
+// ***** END LICENSE BLOCK *****
+
+#include<winver.h>
+
+// Note: if you contain versioning information in an included
+// RC script, it will be discarded
+// Use module.ver to explicitly set these values
+
+// Do not edit this file. Changes won't affect the build.
+
+};
+
+my $versionlevel=0;
+my $insideversion=0;
+if (open(RCINCLUDE, "<$rcinclude"))
+{
+ print RCFILE "// From included resource $rcinclude\n";
+# my $mstring="";
+ while (<RCINCLUDE>)
+ {
+ $_ =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g;
+ print RCFILE $_;
+# my $instr=$_;
+# chomp($instr);
+# $mstring .= "$instr\;";
+ }
+ close(RCINCLUDE);
+# $mstring =~ s/\/\*.*\*\///g;
+# my @mlines = split(/\;/,$mstring);
+# for(@mlines)
+# {
+# my ($nocomment)=split(/\/\//,$_);
+# if (defined($nocomment) && $nocomment ne "")
+# {
+# my ($firststring,$secondstring) = split(/\s+/,$nocomment);
+# if (!defined($firststring)) {$firststring="";}
+# if (!defined($secondstring)) {$secondstring="";}
+# if ($secondstring eq "VERSIONINFO")
+# {
+#if (!$quiet || $quiet ne "1") {
+# print "$bufferstr" . "WARNING: Included RC file ($rcinclude, $module, $binary)\n";
+# print "$bufferstr" . "WARNING: contains versioning information that will be discarded\n";
+# print "$bufferstr" . "WARNING: Remove it and use relevant overrides (in module.ver)\n";
+#}
+# $versionlevel = 0;
+# $insideversion = 1;
+# }
+# if ($firststring eq "BEGIN") { $versionlevel++; }
+# if ($secondstring eq "END")
+# {
+# $versionlevel--;
+# if ($insideversion==1 && $versionlevel==0) {$versionlevel=0;}
+# }
+# my $includecheck = $firststring . $secondstring;
+# $includecheck =~ s/<|>/"/g;
+# $includecheck = lc($includecheck);
+# if ($includecheck ne "#include\"winver.h\"")
+# {
+# if ($insideversion == 0 && $versionlevel == 0)
+# {
+# print RCFILE "$nocomment\n";
+# }
+# }
+# }
+# }
+
+}
+
+my $fileflags = join(' | ', @fileflags);
+
+print RCFILE qq{
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+1 VERSIONINFO
+ FILEVERSION $fileversion
+ PRODUCTVERSION $productversion
+ FILEFLAGSMASK 0x3fL
+ FILEFLAGS $fileflags
+ FILEOS $fileos
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "$comment"
+ VALUE "LegalCopyright", "$copyright"
+ VALUE "CompanyName", "$company"
+ VALUE "FileDescription", "$description"
+ VALUE "FileVersion", "$mfversion"
+ VALUE "ProductVersion", "$mpversion"
+ VALUE "InternalName", "$module"
+ VALUE "LegalTrademarks", "$trademarks"
+ VALUE "OriginalFilename", "$binary"
+ VALUE "ProductName", "$productname"
+ VALUE "BuildID", "$buildid"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+};
+close(RCFILE);
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/dtoa.c b/tools/node_modules/expresso/deps/jscoverage/js/dtoa.c
new file mode 100644
index 0000000..86e8adc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/dtoa.c
@@ -0,0 +1,3321 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+/* On a machine with IEEE extended-precision registers, it is
+ * necessary to specify double-precision (53-bit) rounding precision
+ * before invoking strtod or dtoa. If the machine uses (the equivalent
+ * of) Intel 80x87 arithmetic, the call
+ * _control87(PC_53, MCW_PC);
+ * does this with many compilers. Whether this or another call is
+ * appropriate depends on the compiler; for this to work, it may be
+ * necessary to #include "float.h" or another system-dependent header
+ * file.
+ */
+
+/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
+ *
+ * This strtod returns a nearest machine number to the input decimal
+ * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
+ * broken by the IEEE round-even rule. Otherwise ties are broken by
+ * biased rounding (add half and chop).
+ *
+ * Inspired loosely by William D. Clinger's paper "How to Read Floating
+ * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ *
+ * 1. We only require IEEE, IBM, or VAX double-precision
+ * arithmetic (not IEEE double-extended).
+ * 2. We get by with floating-point arithmetic in a case that
+ * Clinger missed -- when we're computing d * 10^n
+ * for a small integer d and the integer n is not too
+ * much larger than 22 (the maximum integer k for which
+ * we can represent 10^k exactly), we may be able to
+ * compute (d*10^k) * 10^(e-k) with just one roundoff.
+ * 3. Rather than a bit-at-a-time adjustment of the binary
+ * result in the hard case, we use floating-point
+ * arithmetic to determine the adjustment to within
+ * one bit; only in really hard cases do we need to
+ * compute a second residual.
+ * 4. Because of 3., we don't need a large table of powers of 10
+ * for ten-to-e (just some small tables, e.g. of 10^k
+ * for 0 <= k <= 22).
+ */
+
+/*
+ * #define IEEE_8087 for IEEE-arithmetic machines where the least
+ * significant byte has the lowest address.
+ * #define IEEE_MC68k for IEEE-arithmetic machines where the most
+ * significant byte has the lowest address.
+ * #define Long int on machines with 32-bit ints and 64-bit longs.
+ * #define IBM for IBM mainframe-style floating-point arithmetic.
+ * #define VAX for VAX-style floating-point arithmetic (D_floating).
+ * #define No_leftright to omit left-right logic in fast floating-point
+ * computation of dtoa.
+ * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
+ * and strtod and dtoa should round accordingly.
+ * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
+ * and Honor_FLT_ROUNDS is not #defined.
+ * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
+ * that use extended-precision instructions to compute rounded
+ * products and quotients) with IBM.
+ * #define ROUND_BIASED for IEEE-format with biased rounding.
+ * #define Inaccurate_Divide for IEEE-format with correctly rounded
+ * products but inaccurate quotients, e.g., for Intel i860.
+ * #define NO_LONG_LONG on machines that do not have a "long long"
+ * integer type (of >= 64 bits). On such machines, you can
+ * #define Just_16 to store 16 bits per 32-bit Long when doing
+ * high-precision integer arithmetic. Whether this speeds things
+ * up or slows things down depends on the machine and the number
+ * being converted. If long long is available and the name is
+ * something other than "long long", #define Llong to be the name,
+ * and if "unsigned Llong" does not work as an unsigned version of
+ * Llong, #define #ULLong to be the corresponding unsigned type.
+ * #define KR_headers for old-style C function headers.
+ * #define Bad_float_h if your system lacks a float.h or if it does not
+ * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
+ * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
+ * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
+ * if memory is available and otherwise does something you deem
+ * appropriate. If MALLOC is undefined, malloc will be invoked
+ * directly -- and assumed always to succeed.
+ * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
+ * memory allocations from a private pool of memory when possible.
+ * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
+ * unless #defined to be a different length. This default length
+ * suffices to get rid of MALLOC calls except for unusual cases,
+ * such as decimal-to-binary conversion of a very long string of
+ * digits. The longest string dtoa can return is about 751 bytes
+ * long. For conversions by strtod of strings of 800 digits and
+ * all dtoa conversions in single-threaded executions with 8-byte
+ * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte
+ * pointers, PRIVATE_MEM >= 7112 appears adequate.
+ * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK
+ * #defined automatically on IEEE systems. On such systems,
+ * when INFNAN_CHECK is #defined, strtod checks
+ * for Infinity and NaN (case insensitively). On some systems
+ * (e.g., some HP systems), it may be necessary to #define NAN_WORD0
+ * appropriately -- to the most significant word of a quiet NaN.
+ * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
+ * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
+ * strtod also accepts (case insensitively) strings of the form
+ * NaN(x), where x is a string of hexadecimal digits and spaces;
+ * if there is only one string of hexadecimal digits, it is taken
+ * for the 52 fraction bits of the resulting NaN; if there are two
+ * or more strings of hex digits, the first is for the high 20 bits,
+ * the second and subsequent for the low 32 bits, with intervening
+ * white space ignored; but if this results in none of the 52
+ * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
+ * and NAN_WORD1 are used instead.
+ * #define MULTIPLE_THREADS if the system offers preemptively scheduled
+ * multiple threads. In this case, you must provide (or suitably
+ * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
+ * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed
+ * in pow5mult, ensures lazy evaluation of only one copy of high
+ * powers of 5; omitting this lock would introduce a small
+ * probability of wasting memory, but would otherwise be harmless.)
+ * You must also invoke freedtoa(s) to free the value s returned by
+ * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined.
+ * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
+ * avoids underflows on inputs whose result does not underflow.
+ * If you #define NO_IEEE_Scale on a machine that uses IEEE-format
+ * floating-point numbers and flushes underflows to zero rather
+ * than implementing gradual underflow, then you must also #define
+ * Sudden_Underflow.
+ * #define USE_LOCALE to use the current locale's decimal_point value.
+ * #define SET_INEXACT if IEEE arithmetic is being used and extra
+ * computation should be done to set the inexact flag when the
+ * result is inexact and avoid setting inexact when the result
+ * is exact. In this case, dtoa.c must be compiled in
+ * an environment, perhaps provided by #include "dtoa.c" in a
+ * suitable wrapper, that defines two functions,
+ * int get_inexact(void);
+ * void clear_inexact(void);
+ * such that get_inexact() returns a nonzero value if the
+ * inexact bit is already set, and clear_inexact() sets the
+ * inexact bit to 0. When SET_INEXACT is #defined, strtod
+ * also does extra computations to set the underflow and overflow
+ * flags when appropriate (i.e., when the result is tiny and
+ * inexact or when it is a numeric value rounded to +-infinity).
+ * #define NO_ERRNO if strtod should not assign errno = ERANGE when
+ * the result overflows to +-Infinity or underflows to 0.
+ */
+
+#ifndef Long
+#define Long long
+#endif
+#ifndef ULong
+typedef unsigned Long ULong;
+#endif
+
+#ifdef DEBUG
+#include "stdio.h"
+#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
+#endif
+
+#include "stdlib.h"
+#include "string.h"
+
+#ifdef USE_LOCALE
+#include "locale.h"
+#endif
+
+#ifdef MALLOC
+#ifdef KR_headers
+extern char *MALLOC();
+#else
+extern void *MALLOC(size_t);
+#endif
+#else
+#define MALLOC malloc
+#endif
+
+#ifndef Omit_Private_Memory
+#ifndef PRIVATE_MEM
+#define PRIVATE_MEM 2304
+#endif
+#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
+static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
+#endif
+
+#undef IEEE_Arith
+#undef Avoid_Underflow
+#ifdef IEEE_MC68k
+#define IEEE_Arith
+#endif
+#ifdef IEEE_8087
+#define IEEE_Arith
+#endif
+
+#ifdef IEEE_Arith
+#ifndef NO_INFNAN_CHECK
+#undef INFNAN_CHECK
+#define INFNAN_CHECK
+#endif
+#else
+#undef INFNAN_CHECK
+#endif
+
+#include "errno.h"
+
+#ifdef Bad_float_h
+
+#ifdef IEEE_Arith
+#define DBL_DIG 15
+#define DBL_MAX_10_EXP 308
+#define DBL_MAX_EXP 1024
+#define FLT_RADIX 2
+#endif /*IEEE_Arith*/
+
+#ifdef IBM
+#define DBL_DIG 16
+#define DBL_MAX_10_EXP 75
+#define DBL_MAX_EXP 63
+#define FLT_RADIX 16
+#define DBL_MAX 7.2370055773322621e+75
+#endif
+
+#ifdef VAX
+#define DBL_DIG 16
+#define DBL_MAX_10_EXP 38
+#define DBL_MAX_EXP 127
+#define FLT_RADIX 2
+#define DBL_MAX 1.7014118346046923e+38
+#endif
+
+#ifndef LONG_MAX
+#define LONG_MAX 2147483647
+#endif
+
+#else /* ifndef Bad_float_h */
+#include "float.h"
+#endif /* Bad_float_h */
+
+#ifndef __MATH_H__
+#include "math.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef CONST
+#ifdef KR_headers
+#define CONST /* blank */
+#else
+#define CONST const
+#endif
+#endif
+
+#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1
+Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
+#endif
+
+typedef union { double d; ULong L[2]; } U;
+
+#define dval(x) ((x).d)
+#ifdef IEEE_8087
+#define word0(x) ((x).L[1])
+#define word1(x) ((x).L[0])
+#else
+#define word0(x) ((x).L[0])
+#define word1(x) ((x).L[1])
+#endif
+
+/* The following definition of Storeinc is appropriate for MIPS processors.
+ * An alternative that might be better on some machines is
+ * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
+ */
+#if defined(IEEE_8087) + defined(VAX)
+#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
+((unsigned short *)a)[0] = (unsigned short)c, a++)
+#else
+#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
+((unsigned short *)a)[1] = (unsigned short)c, a++)
+#endif
+
+/* #define P DBL_MANT_DIG */
+/* Ten_pmax = floor(P*log(2)/log(5)) */
+/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
+/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
+/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
+
+#ifdef IEEE_Arith
+#define Exp_shift 20
+#define Exp_shift1 20
+#define Exp_msk1 0x100000
+#define Exp_msk11 0x100000
+#define Exp_mask 0x7ff00000
+#define P 53
+#define Bias 1023
+#define Emin (-1022)
+#define Exp_1 0x3ff00000
+#define Exp_11 0x3ff00000
+#define Ebits 11
+#define Frac_mask 0xfffff
+#define Frac_mask1 0xfffff
+#define Ten_pmax 22
+#define Bletch 0x10
+#define Bndry_mask 0xfffff
+#define Bndry_mask1 0xfffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 1
+#define Tiny0 0
+#define Tiny1 1
+#define Quick_max 14
+#define Int_max 14
+#ifndef NO_IEEE_Scale
+#define Avoid_Underflow
+#ifdef Flush_Denorm /* debugging option */
+#undef Sudden_Underflow
+#endif
+#endif
+
+#ifndef Flt_Rounds
+#ifdef FLT_ROUNDS
+#define Flt_Rounds FLT_ROUNDS
+#else
+#define Flt_Rounds 1
+#endif
+#endif /*Flt_Rounds*/
+
+#ifdef Honor_FLT_ROUNDS
+#define Rounding rounding
+#undef Check_FLT_ROUNDS
+#define Check_FLT_ROUNDS
+#else
+#define Rounding Flt_Rounds
+#endif
+
+#else /* ifndef IEEE_Arith */
+#undef Check_FLT_ROUNDS
+#undef Honor_FLT_ROUNDS
+#undef SET_INEXACT
+#undef Sudden_Underflow
+#define Sudden_Underflow
+#ifdef IBM
+#undef Flt_Rounds
+#define Flt_Rounds 0
+#define Exp_shift 24
+#define Exp_shift1 24
+#define Exp_msk1 0x1000000
+#define Exp_msk11 0x1000000
+#define Exp_mask 0x7f000000
+#define P 14
+#define Bias 65
+#define Exp_1 0x41000000
+#define Exp_11 0x41000000
+#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
+#define Frac_mask 0xffffff
+#define Frac_mask1 0xffffff
+#define Bletch 4
+#define Ten_pmax 22
+#define Bndry_mask 0xefffff
+#define Bndry_mask1 0xffffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 4
+#define Tiny0 0x100000
+#define Tiny1 0
+#define Quick_max 14
+#define Int_max 15
+#else /* VAX */
+#undef Flt_Rounds
+#define Flt_Rounds 1
+#define Exp_shift 23
+#define Exp_shift1 7
+#define Exp_msk1 0x80
+#define Exp_msk11 0x800000
+#define Exp_mask 0x7f80
+#define P 56
+#define Bias 129
+#define Exp_1 0x40800000
+#define Exp_11 0x4080
+#define Ebits 8
+#define Frac_mask 0x7fffff
+#define Frac_mask1 0xffff007f
+#define Ten_pmax 24
+#define Bletch 2
+#define Bndry_mask 0xffff007f
+#define Bndry_mask1 0xffff007f
+#define LSB 0x10000
+#define Sign_bit 0x8000
+#define Log2P 1
+#define Tiny0 0x80
+#define Tiny1 0
+#define Quick_max 15
+#define Int_max 15
+#endif /* IBM, VAX */
+#endif /* IEEE_Arith */
+
+#ifndef IEEE_Arith
+#define ROUND_BIASED
+#endif
+
+#ifdef RND_PRODQUOT
+#define rounded_product(a,b) a = rnd_prod(a, b)
+#define rounded_quotient(a,b) a = rnd_quot(a, b)
+#ifdef KR_headers
+extern double rnd_prod(), rnd_quot();
+#else
+extern double rnd_prod(double, double), rnd_quot(double, double);
+#endif
+#else
+#define rounded_product(a,b) a *= b
+#define rounded_quotient(a,b) a /= b
+#endif
+
+#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
+#define Big1 0xffffffff
+
+#ifndef Pack_32
+#define Pack_32
+#endif
+
+#ifdef KR_headers
+#define FFFFFFFF ((((unsigned long)0xffff)<<16)|(unsigned long)0xffff)
+#else
+#define FFFFFFFF 0xffffffffUL
+#endif
+
+#ifdef NO_LONG_LONG
+#undef ULLong
+#ifdef Just_16
+#undef Pack_32
+/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
+ * This makes some inner loops simpler and sometimes saves work
+ * during multiplications, but it often seems to make things slightly
+ * slower. Hence the default is now to store 32 bits per Long.
+ */
+#endif
+#else /* long long available */
+#ifndef Llong
+#define Llong long long
+#endif
+#ifndef ULLong
+#define ULLong unsigned Llong
+#endif
+#endif /* NO_LONG_LONG */
+
+#ifndef MULTIPLE_THREADS
+#define ACQUIRE_DTOA_LOCK(n) /*nothing*/
+#define FREE_DTOA_LOCK(n) /*nothing*/
+#endif
+
+#define Kmax 15
+
+ struct
+Bigint {
+ struct Bigint *next;
+ int k, maxwds, sign, wds;
+ ULong x[1];
+ };
+
+ typedef struct Bigint Bigint;
+
+ static Bigint *freelist[Kmax+1];
+
+ static Bigint *
+Balloc
+#ifdef KR_headers
+ (k) int k;
+#else
+ (int k)
+#endif
+{
+ int x;
+ Bigint *rv;
+#ifndef Omit_Private_Memory
+ size_t len;
+#endif
+
+ ACQUIRE_DTOA_LOCK(0);
+ if ((rv = freelist[k])) {
+ freelist[k] = rv->next;
+ }
+ else {
+ x = 1 << k;
+#ifdef Omit_Private_Memory
+ rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
+#else
+ len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
+ /sizeof(double);
+ if (pmem_next - private_mem + len <= PRIVATE_mem) {
+ rv = (Bigint*)pmem_next;
+ pmem_next += len;
+ }
+ else
+ rv = (Bigint*)MALLOC(len*sizeof(double));
+#endif
+ rv->k = k;
+ rv->maxwds = x;
+ }
+ FREE_DTOA_LOCK(0);
+ rv->sign = rv->wds = 0;
+ return rv;
+ }
+
+ static void
+Bfree
+#ifdef KR_headers
+ (v) Bigint *v;
+#else
+ (Bigint *v)
+#endif
+{
+ if (v) {
+ ACQUIRE_DTOA_LOCK(0);
+ v->next = freelist[v->k];
+ freelist[v->k] = v;
+ FREE_DTOA_LOCK(0);
+ }
+ }
+
+#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
+y->wds*sizeof(Long) + 2*sizeof(int))
+
+ static Bigint *
+multadd
+#ifdef KR_headers
+ (b, m, a) Bigint *b; int m, a;
+#else
+ (Bigint *b, int m, int a) /* multiply by m and add a */
+#endif
+{
+ int i, wds;
+#ifdef ULLong
+ ULong *x;
+ ULLong carry, y;
+#else
+ ULong carry, *x, y;
+#ifdef Pack_32
+ ULong xi, z;
+#endif
+#endif
+ Bigint *b1;
+
+ wds = b->wds;
+ x = b->x;
+ i = 0;
+ carry = a;
+ do {
+#ifdef ULLong
+ y = *x * (ULLong)m + carry;
+ carry = y >> 32;
+ *x++ = (ULong) y & FFFFFFFF;
+#else
+#ifdef Pack_32
+ xi = *x;
+ y = (xi & 0xffff) * m + carry;
+ z = (xi >> 16) * m + (y >> 16);
+ carry = z >> 16;
+ *x++ = (z << 16) + (y & 0xffff);
+#else
+ y = *x * m + carry;
+ carry = y >> 16;
+ *x++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(++i < wds);
+ if (carry) {
+ if (wds >= b->maxwds) {
+ b1 = Balloc(b->k+1);
+ Bcopy(b1, b);
+ Bfree(b);
+ b = b1;
+ }
+ b->x[wds++] = (ULong) carry;
+ b->wds = wds;
+ }
+ return b;
+ }
+
+ static Bigint *
+s2b
+#ifdef KR_headers
+ (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
+#else
+ (CONST char *s, int nd0, int nd, ULong y9)
+#endif
+{
+ Bigint *b;
+ int i, k;
+ Long x, y;
+
+ x = (nd + 8) / 9;
+ for(k = 0, y = 1; x > y; y <<= 1, k++) ;
+#ifdef Pack_32
+ b = Balloc(k);
+ b->x[0] = y9;
+ b->wds = 1;
+#else
+ b = Balloc(k+1);
+ b->x[0] = y9 & 0xffff;
+ b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
+#endif
+
+ i = 9;
+ if (9 < nd0) {
+ s += 9;
+ do b = multadd(b, 10, *s++ - '0');
+ while(++i < nd0);
+ s++;
+ }
+ else
+ s += 10;
+ for(; i < nd; i++)
+ b = multadd(b, 10, *s++ - '0');
+ return b;
+ }
+
+ static int
+hi0bits
+#ifdef KR_headers
+ (x) register ULong x;
+#else
+ (register ULong x)
+#endif
+{
+ register int k = 0;
+
+ if (!(x & 0xffff0000)) {
+ k = 16;
+ x <<= 16;
+ }
+ if (!(x & 0xff000000)) {
+ k += 8;
+ x <<= 8;
+ }
+ if (!(x & 0xf0000000)) {
+ k += 4;
+ x <<= 4;
+ }
+ if (!(x & 0xc0000000)) {
+ k += 2;
+ x <<= 2;
+ }
+ if (!(x & 0x80000000)) {
+ k++;
+ if (!(x & 0x40000000))
+ return 32;
+ }
+ return k;
+ }
+
+ static int
+lo0bits
+#ifdef KR_headers
+ (y) ULong *y;
+#else
+ (ULong *y)
+#endif
+{
+ register int k;
+ register ULong x = *y;
+
+ if (x & 7) {
+ if (x & 1)
+ return 0;
+ if (x & 2) {
+ *y = x >> 1;
+ return 1;
+ }
+ *y = x >> 2;
+ return 2;
+ }
+ k = 0;
+ if (!(x & 0xffff)) {
+ k = 16;
+ x >>= 16;
+ }
+ if (!(x & 0xff)) {
+ k += 8;
+ x >>= 8;
+ }
+ if (!(x & 0xf)) {
+ k += 4;
+ x >>= 4;
+ }
+ if (!(x & 0x3)) {
+ k += 2;
+ x >>= 2;
+ }
+ if (!(x & 1)) {
+ k++;
+ x >>= 1;
+ if (!x)
+ return 32;
+ }
+ *y = x;
+ return k;
+ }
+
+ static Bigint *
+i2b
+#ifdef KR_headers
+ (i) int i;
+#else
+ (int i)
+#endif
+{
+ Bigint *b;
+
+ b = Balloc(1);
+ b->x[0] = i;
+ b->wds = 1;
+ return b;
+ }
+
+ static Bigint *
+mult
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ Bigint *c;
+ int k, wa, wb, wc;
+ ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+ ULong y;
+#ifdef ULLong
+ ULLong carry, z;
+#else
+ ULong carry, z;
+#ifdef Pack_32
+ ULong z2;
+#endif
+#endif
+
+ if (a->wds < b->wds) {
+ c = a;
+ a = b;
+ b = c;
+ }
+ k = a->k;
+ wa = a->wds;
+ wb = b->wds;
+ wc = wa + wb;
+ if (wc > a->maxwds)
+ k++;
+ c = Balloc(k);
+ for(x = c->x, xa = x + wc; x < xa; x++)
+ *x = 0;
+ xa = a->x;
+ xae = xa + wa;
+ xb = b->x;
+ xbe = xb + wb;
+ xc0 = c->x;
+#ifdef ULLong
+ for(; xb < xbe; xc0++) {
+ if ((y = *xb++)) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * (ULLong)y + *xc + carry;
+ carry = z >> 32;
+ *xc++ = (ULong) z & FFFFFFFF;
+ }
+ while(x < xae);
+ *xc = (ULong) carry;
+ }
+ }
+#else
+#ifdef Pack_32
+ for(; xb < xbe; xb++, xc0++) {
+ if (y = *xb & 0xffff) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
+ carry = z >> 16;
+ z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
+ carry = z2 >> 16;
+ Storeinc(xc, z2, z);
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ if (y = *xb >> 16) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ z2 = *xc;
+ do {
+ z = (*x & 0xffff) * y + (*xc >> 16) + carry;
+ carry = z >> 16;
+ Storeinc(xc, z, z2);
+ z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
+ carry = z2 >> 16;
+ }
+ while(x < xae);
+ *xc = z2;
+ }
+ }
+#else
+ for(; xb < xbe; xc0++) {
+ if (y = *xb++) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * y + *xc + carry;
+ carry = z >> 16;
+ *xc++ = z & 0xffff;
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ }
+#endif
+#endif
+ for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
+ c->wds = wc;
+ return c;
+ }
+
+ static Bigint *p5s;
+
+ static Bigint *
+pow5mult
+#ifdef KR_headers
+ (b, k) Bigint *b; int k;
+#else
+ (Bigint *b, int k)
+#endif
+{
+ Bigint *b1, *p5, *p51;
+ int i;
+ static int p05[3] = { 5, 25, 125 };
+
+ if ((i = k & 3))
+ b = multadd(b, p05[i-1], 0);
+
+ if (!(k >>= 2))
+ return b;
+ if (!(p5 = p5s)) {
+ /* first time */
+#ifdef MULTIPLE_THREADS
+ ACQUIRE_DTOA_LOCK(1);
+ if (!(p5 = p5s)) {
+ p5 = p5s = i2b(625);
+ p5->next = 0;
+ }
+ FREE_DTOA_LOCK(1);
+#else
+ p5 = p5s = i2b(625);
+ p5->next = 0;
+#endif
+ }
+ for(;;) {
+ if (k & 1) {
+ b1 = mult(b, p5);
+ Bfree(b);
+ b = b1;
+ }
+ if (!(k >>= 1))
+ break;
+ if (!(p51 = p5->next)) {
+#ifdef MULTIPLE_THREADS
+ ACQUIRE_DTOA_LOCK(1);
+ if (!(p51 = p5->next)) {
+ p51 = p5->next = mult(p5,p5);
+ p51->next = 0;
+ }
+ FREE_DTOA_LOCK(1);
+#else
+ p51 = p5->next = mult(p5,p5);
+ p51->next = 0;
+#endif
+ }
+ p5 = p51;
+ }
+ return b;
+ }
+
+ static Bigint *
+lshift
+#ifdef KR_headers
+ (b, k) Bigint *b; int k;
+#else
+ (Bigint *b, int k)
+#endif
+{
+ int i, k1, n, n1;
+ Bigint *b1;
+ ULong *x, *x1, *xe, z;
+
+#ifdef Pack_32
+ n = k >> 5;
+#else
+ n = k >> 4;
+#endif
+ k1 = b->k;
+ n1 = n + b->wds + 1;
+ for(i = b->maxwds; n1 > i; i <<= 1)
+ k1++;
+ b1 = Balloc(k1);
+ x1 = b1->x;
+ for(i = 0; i < n; i++)
+ *x1++ = 0;
+ x = b->x;
+ xe = x + b->wds;
+#ifdef Pack_32
+ if (k &= 0x1f) {
+ k1 = 32 - k;
+ z = 0;
+ do {
+ *x1++ = *x << k | z;
+ z = *x++ >> k1;
+ }
+ while(x < xe);
+ if ((*x1 = z))
+ ++n1;
+ }
+#else
+ if (k &= 0xf) {
+ k1 = 16 - k;
+ z = 0;
+ do {
+ *x1++ = *x << k & 0xffff | z;
+ z = *x++ >> k1;
+ }
+ while(x < xe);
+ if (*x1 = z)
+ ++n1;
+ }
+#endif
+ else do
+ *x1++ = *x++;
+ while(x < xe);
+ b1->wds = n1 - 1;
+ Bfree(b);
+ return b1;
+ }
+
+ static int
+cmp
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ ULong *xa, *xa0, *xb, *xb0;
+ int i, j;
+
+ i = a->wds;
+ j = b->wds;
+#ifdef DEBUG
+ if (i > 1 && !a->x[i-1])
+ Bug("cmp called with a->x[a->wds-1] == 0");
+ if (j > 1 && !b->x[j-1])
+ Bug("cmp called with b->x[b->wds-1] == 0");
+#endif
+ if (i -= j)
+ return i;
+ xa0 = a->x;
+ xa = xa0 + j;
+ xb0 = b->x;
+ xb = xb0 + j;
+ for(;;) {
+ if (*--xa != *--xb)
+ return *xa < *xb ? -1 : 1;
+ if (xa <= xa0)
+ break;
+ }
+ return 0;
+ }
+
+ static Bigint *
+diff
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ Bigint *c;
+ int i, wa, wb;
+ ULong *xa, *xae, *xb, *xbe, *xc;
+#ifdef ULLong
+ ULLong borrow, y;
+#else
+ ULong borrow, y;
+#ifdef Pack_32
+ ULong z;
+#endif
+#endif
+
+ i = cmp(a,b);
+ if (!i) {
+ c = Balloc(0);
+ c->wds = 1;
+ c->x[0] = 0;
+ return c;
+ }
+ if (i < 0) {
+ c = a;
+ a = b;
+ b = c;
+ i = 1;
+ }
+ else
+ i = 0;
+ c = Balloc(a->k);
+ c->sign = i;
+ wa = a->wds;
+ xa = a->x;
+ xae = xa + wa;
+ wb = b->wds;
+ xb = b->x;
+ xbe = xb + wb;
+ xc = c->x;
+ borrow = 0;
+#ifdef ULLong
+ do {
+ y = (ULLong)*xa++ - *xb++ - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *xc++ = (ULong) y & FFFFFFFF;
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = *xa++ - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *xc++ = (ULong) y & FFFFFFFF;
+ }
+#else
+#ifdef Pack_32
+ do {
+ y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = (*xa & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*xa++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+#else
+ do {
+ y = *xa++ - *xb++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = *xa++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+#endif
+#endif
+ while(!*--xc)
+ wa--;
+ c->wds = wa;
+ return c;
+ }
+
+ static double
+ulp
+#ifdef KR_headers
+ (x) U x;
+#else
+ (U x)
+#endif
+{
+ register Long L;
+ U a;
+
+ L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
+#ifndef Avoid_Underflow
+#ifndef Sudden_Underflow
+ if (L > 0) {
+#endif
+#endif
+#ifdef IBM
+ L |= Exp_msk1 >> 4;
+#endif
+ word0(a) = L;
+ word1(a) = 0;
+#ifndef Avoid_Underflow
+#ifndef Sudden_Underflow
+ }
+ else {
+ L = -L >> Exp_shift;
+ if (L < Exp_shift) {
+ word0(a) = 0x80000 >> L;
+ word1(a) = 0;
+ }
+ else {
+ word0(a) = 0;
+ L -= Exp_shift;
+ word1(a) = L >= 31 ? 1 : 1 << 31 - L;
+ }
+ }
+#endif
+#endif
+ return dval(a);
+ }
+
+ static double
+b2d
+#ifdef KR_headers
+ (a, e) Bigint *a; int *e;
+#else
+ (Bigint *a, int *e)
+#endif
+{
+ ULong *xa, *xa0, w, y, z;
+ int k;
+ U d;
+#ifdef VAX
+ ULong d0, d1;
+#else
+#define d0 word0(d)
+#define d1 word1(d)
+#endif
+
+ xa0 = a->x;
+ xa = xa0 + a->wds;
+ y = *--xa;
+#ifdef DEBUG
+ if (!y) Bug("zero y in b2d");
+#endif
+ k = hi0bits(y);
+ *e = 32 - k;
+#ifdef Pack_32
+ if (k < Ebits) {
+ d0 = Exp_1 | y >> (Ebits - k);
+ w = xa > xa0 ? *--xa : 0;
+ d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ if (k -= Ebits) {
+ d0 = Exp_1 | y << k | z >> (32 - k);
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k | y >> (32 - k);
+ }
+ else {
+ d0 = Exp_1 | y;
+ d1 = z;
+ }
+#else
+ if (k < Ebits + 16) {
+ z = xa > xa0 ? *--xa : 0;
+ d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
+ w = xa > xa0 ? *--xa : 0;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ w = xa > xa0 ? *--xa : 0;
+ k -= Ebits + 16;
+ d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = w << k + 16 | y << k;
+#endif
+ ret_d:
+#ifdef VAX
+ word0(d) = d0 >> 16 | d0 << 16;
+ word1(d) = d1 >> 16 | d1 << 16;
+#else
+#undef d0
+#undef d1
+#endif
+ return dval(d);
+ }
+
+ static Bigint *
+d2b
+#ifdef KR_headers
+ (d, e, bits) U d; int *e, *bits;
+#else
+ (U d, int *e, int *bits)
+#endif
+{
+ Bigint *b;
+ int de, k;
+ ULong *x, y, z;
+#ifndef Sudden_Underflow
+ int i;
+#endif
+#ifdef VAX
+ ULong d0, d1;
+ d0 = word0(d) >> 16 | word0(d) << 16;
+ d1 = word1(d) >> 16 | word1(d) << 16;
+#else
+#define d0 word0(d)
+#define d1 word1(d)
+#endif
+
+#ifdef Pack_32
+ b = Balloc(1);
+#else
+ b = Balloc(2);
+#endif
+ x = b->x;
+
+ z = d0 & Frac_mask;
+ d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
+#ifdef Sudden_Underflow
+ de = (int)(d0 >> Exp_shift);
+#ifndef IBM
+ z |= Exp_msk11;
+#endif
+#else
+ if ((de = (int)(d0 >> Exp_shift)))
+ z |= Exp_msk1;
+#endif
+#ifdef Pack_32
+ if ((y = d1)) {
+ if ((k = lo0bits(&y))) {
+ x[0] = y | z << (32 - k);
+ z >>= k;
+ }
+ else
+ x[0] = y;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = (x[1] = z) ? 2 : 1;
+ }
+ else {
+#ifdef DEBUG
+ if (!z)
+ Bug("Zero passed to d2b");
+#endif
+ k = lo0bits(&z);
+ x[0] = z;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = 1;
+ k += 32;
+ }
+#else
+ if (y = d1) {
+ if (k = lo0bits(&y))
+ if (k >= 16) {
+ x[0] = y | z << 32 - k & 0xffff;
+ x[1] = z >> k - 16 & 0xffff;
+ x[2] = z >> k;
+ i = 2;
+ }
+ else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16 | z << 16 - k & 0xffff;
+ x[2] = z >> k & 0xffff;
+ x[3] = z >> k+16;
+ i = 3;
+ }
+ else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16;
+ x[2] = z & 0xffff;
+ x[3] = z >> 16;
+ i = 3;
+ }
+ }
+ else {
+#ifdef DEBUG
+ if (!z)
+ Bug("Zero passed to d2b");
+#endif
+ k = lo0bits(&z);
+ if (k >= 16) {
+ x[0] = z;
+ i = 0;
+ }
+ else {
+ x[0] = z & 0xffff;
+ x[1] = z >> 16;
+ i = 1;
+ }
+ k += 32;
+ }
+ while(!x[i])
+ --i;
+ b->wds = i + 1;
+#endif
+#ifndef Sudden_Underflow
+ if (de) {
+#endif
+#ifdef IBM
+ *e = (de - Bias - (P-1) << 2) + k;
+ *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
+#else
+ *e = de - Bias - (P-1) + k;
+ *bits = P - k;
+#endif
+#ifndef Sudden_Underflow
+ }
+ else {
+ *e = de - Bias - (P-1) + 1 + k;
+#ifdef Pack_32
+ *bits = 32*i - hi0bits(x[i-1]);
+#else
+ *bits = (i+2)*16 - hi0bits(x[i]);
+#endif
+ }
+#endif
+ return b;
+ }
+#undef d0
+#undef d1
+
+ static double
+ratio
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ U da, db;
+ int k, ka, kb;
+
+ dval(da) = b2d(a, &ka);
+ dval(db) = b2d(b, &kb);
+#ifdef Pack_32
+ k = ka - kb + 32*(a->wds - b->wds);
+#else
+ k = ka - kb + 16*(a->wds - b->wds);
+#endif
+#ifdef IBM
+ if (k > 0) {
+ word0(da) += (k >> 2)*Exp_msk1;
+ if (k &= 3)
+ dval(da) *= 1 << k;
+ }
+ else {
+ k = -k;
+ word0(db) += (k >> 2)*Exp_msk1;
+ if (k &= 3)
+ dval(db) *= 1 << k;
+ }
+#else
+ if (k > 0)
+ word0(da) += k*Exp_msk1;
+ else {
+ k = -k;
+ word0(db) += k*Exp_msk1;
+ }
+#endif
+ return dval(da) / dval(db);
+ }
+
+ static CONST double
+tens[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ 1e20, 1e21, 1e22
+#ifdef VAX
+ , 1e23, 1e24
+#endif
+ };
+
+ static CONST double
+#ifdef IEEE_Arith
+bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
+static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
+#ifdef Avoid_Underflow
+ 9007199254740992.*9007199254740992.e-256
+ /* = 2^106 * 1e-53 */
+#else
+ 1e-256
+#endif
+ };
+/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
+/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
+#define Scale_Bit 0x10
+#define n_bigtens 5
+#else
+#ifdef IBM
+bigtens[] = { 1e16, 1e32, 1e64 };
+static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
+#define n_bigtens 3
+#else
+bigtens[] = { 1e16, 1e32 };
+static CONST double tinytens[] = { 1e-16, 1e-32 };
+#define n_bigtens 2
+#endif
+#endif
+
+#ifdef INFNAN_CHECK
+
+#ifndef NAN_WORD0
+#define NAN_WORD0 0x7ff80000
+#endif
+
+#ifndef NAN_WORD1
+#define NAN_WORD1 0
+#endif
+
+ static int
+match
+#ifdef KR_headers
+ (sp, t) char **sp, *t;
+#else
+ (CONST char **sp, CONST char *t)
+#endif
+{
+ int c, d;
+ CONST char *s = *sp;
+
+ while((d = *t++)) {
+ if ((c = *++s) >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != d)
+ return 0;
+ }
+ *sp = s + 1;
+ return 1;
+ }
+
+#ifndef No_Hex_NaN
+ static void
+hexnan
+#ifdef KR_headers
+ (rvp, sp) U *rvp; CONST char **sp;
+#else
+ (U *rvp, CONST char **sp)
+#endif
+{
+ ULong c, x[2];
+ CONST char *s;
+ int havedig, udx0, xshift;
+
+ x[0] = x[1] = 0;
+ havedig = xshift = 0;
+ udx0 = 1;
+ s = *sp;
+ /* allow optional initial 0x or 0X */
+ while((c = *(CONST unsigned char*)(s+1)) && c <= ' ')
+ ++s;
+ if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X'))
+ s += 2;
+ while((c = *(CONST unsigned char*)++s)) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c += 10 - 'a';
+ else if (c >= 'A' && c <= 'F')
+ c += 10 - 'A';
+ else if (c <= ' ') {
+ if (udx0 && havedig) {
+ udx0 = 0;
+ xshift = 1;
+ }
+ continue;
+ }
+#ifdef GDTOA_NON_PEDANTIC_NANCHECK
+ else if (/*(*/ c == ')' && havedig) {
+ *sp = s + 1;
+ break;
+ }
+ else
+ return; /* invalid form: don't change *sp */
+#else
+ else {
+ do {
+ if (/*(*/ c == ')') {
+ *sp = s + 1;
+ break;
+ }
+ } while((c = *++s));
+ break;
+ }
+#endif
+ havedig = 1;
+ if (xshift) {
+ xshift = 0;
+ x[0] = x[1];
+ x[1] = 0;
+ }
+ if (udx0)
+ x[0] = (x[0] << 4) | (x[1] >> 28);
+ x[1] = (x[1] << 4) | c;
+ }
+ if ((x[0] &= 0xfffff) || x[1]) {
+ word0(*rvp) = Exp_mask | x[0];
+ word1(*rvp) = x[1];
+ }
+ }
+#endif /*No_Hex_NaN*/
+#endif /* INFNAN_CHECK */
+
+ static double
+_strtod
+#ifdef KR_headers
+ (s00, se) CONST char *s00; char **se;
+#else
+ (CONST char *s00, char **se)
+#endif
+{
+#ifdef Avoid_Underflow
+ int scale;
+#endif
+ int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
+ e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
+ CONST char *s, *s0, *s1;
+ double aadj, adj;
+ U aadj1, rv, rv0;
+ Long L;
+ ULong y, z;
+ Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
+#ifdef SET_INEXACT
+ int inexact, oldinexact;
+#endif
+#ifdef Honor_FLT_ROUNDS
+ int rounding;
+#endif
+#ifdef USE_LOCALE
+ CONST char *s2;
+#endif
+
+#ifdef __GNUC__
+ delta = bb = bd = bs = 0;
+#endif
+
+ sign = nz0 = nz = 0;
+ dval(rv) = 0.;
+ for(s = s00;;s++) switch(*s) {
+ case '-':
+ sign = 1;
+ /* no break */
+ case '+':
+ if (*++s)
+ goto break2;
+ /* no break */
+ case 0:
+ goto ret0;
+ case '\t':
+ case '\n':
+ case '\v':
+ case '\f':
+ case '\r':
+ case ' ':
+ continue;
+ default:
+ goto break2;
+ }
+ break2:
+ if (*s == '0') {
+ nz0 = 1;
+ while(*++s == '0') ;
+ if (!*s)
+ goto ret;
+ }
+ s0 = s;
+ y = z = 0;
+ for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
+ if (nd < 9)
+ y = 10*y + c - '0';
+ else if (nd < 16)
+ z = 10*z + c - '0';
+ nd0 = nd;
+#ifdef USE_LOCALE
+ s1 = localeconv()->decimal_point;
+ if (c == *s1) {
+ c = '.';
+ if (*++s1) {
+ s2 = s;
+ for(;;) {
+ if (*++s2 != *s1) {
+ c = 0;
+ break;
+ }
+ if (!*++s1) {
+ s = s2;
+ break;
+ }
+ }
+ }
+ }
+#endif
+ if (c == '.') {
+ c = *++s;
+ if (!nd) {
+ for(; c == '0'; c = *++s)
+ nz++;
+ if (c > '0' && c <= '9') {
+ s0 = s;
+ nf += nz;
+ nz = 0;
+ goto have_dig;
+ }
+ goto dig_done;
+ }
+ for(; c >= '0' && c <= '9'; c = *++s) {
+ have_dig:
+ nz++;
+ if (c -= '0') {
+ nf += nz;
+ for(i = 1; i < nz; i++)
+ if (nd++ < 9)
+ y *= 10;
+ else if (nd <= DBL_DIG + 1)
+ z *= 10;
+ if (nd++ < 9)
+ y = 10*y + c;
+ else if (nd <= DBL_DIG + 1)
+ z = 10*z + c;
+ nz = 0;
+ }
+ }
+ }
+ dig_done:
+ e = 0;
+ if (c == 'e' || c == 'E') {
+ if (!nd && !nz && !nz0) {
+ goto ret0;
+ }
+ s00 = s;
+ esign = 0;
+ switch(c = *++s) {
+ case '-':
+ esign = 1;
+ case '+':
+ c = *++s;
+ }
+ if (c >= '0' && c <= '9') {
+ while(c == '0')
+ c = *++s;
+ if (c > '0' && c <= '9') {
+ L = c - '0';
+ s1 = s;
+ while((c = *++s) >= '0' && c <= '9')
+ L = 10*L + c - '0';
+ if (s - s1 > 8 || L > 19999)
+ /* Avoid confusion from exponents
+ * so large that e might overflow.
+ */
+ e = 19999; /* safe for 16 bit ints */
+ else
+ e = (int)L;
+ if (esign)
+ e = -e;
+ }
+ else
+ e = 0;
+ }
+ else
+ s = s00;
+ }
+ if (!nd) {
+ if (!nz && !nz0) {
+#ifdef INFNAN_CHECK
+ /* Check for Nan and Infinity */
+ switch(c) {
+ case 'i':
+ case 'I':
+ if (match(&s,"nf")) {
+ --s;
+ if (!match(&s,"inity"))
+ ++s;
+ word0(rv) = 0x7ff00000;
+ word1(rv) = 0;
+ goto ret;
+ }
+ break;
+ case 'n':
+ case 'N':
+ if (match(&s, "an")) {
+ word0(rv) = NAN_WORD0;
+ word1(rv) = NAN_WORD1;
+#ifndef No_Hex_NaN
+ if (*s == '(') /*)*/
+ hexnan(&rv, &s);
+#endif
+ goto ret;
+ }
+ }
+#endif /* INFNAN_CHECK */
+ ret0:
+ s = s00;
+ sign = 0;
+ }
+ goto ret;
+ }
+ e1 = e -= nf;
+
+ /* Now we have nd0 digits, starting at s0, followed by a
+ * decimal point, followed by nd-nd0 digits. The number we're
+ * after is the integer represented by those digits times
+ * 10**e */
+
+ if (!nd0)
+ nd0 = nd;
+ k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
+ dval(rv) = y;
+ if (k > 9) {
+#ifdef SET_INEXACT
+ if (k > DBL_DIG)
+ oldinexact = get_inexact();
+#endif
+ dval(rv) = tens[k - 9] * dval(rv) + z;
+ }
+ bd0 = 0;
+ if (nd <= DBL_DIG
+#ifndef RND_PRODQUOT
+#ifndef Honor_FLT_ROUNDS
+ && Flt_Rounds == 1
+#endif
+#endif
+ ) {
+ if (!e)
+ goto ret;
+ if (e > 0) {
+ if (e <= Ten_pmax) {
+#ifdef VAX
+ goto vax_ovfl_check;
+#else
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv = -rv;
+ sign = 0;
+ }
+#endif
+ /* rv = */ rounded_product(dval(rv), tens[e]);
+ goto ret;
+#endif
+ }
+ i = DBL_DIG - nd;
+ if (e <= Ten_pmax + i) {
+ /* A fancier test would sometimes let us do
+ * this for larger i values.
+ */
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv = -rv;
+ sign = 0;
+ }
+#endif
+ e -= i;
+ dval(rv) *= tens[i];
+#ifdef VAX
+ /* VAX exponent range is so narrow we must
+ * worry about overflow here...
+ */
+ vax_ovfl_check:
+ word0(rv) -= P*Exp_msk1;
+ /* rv = */ rounded_product(dval(rv), tens[e]);
+ if ((word0(rv) & Exp_mask)
+ > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
+ goto ovfl;
+ word0(rv) += P*Exp_msk1;
+#else
+ /* rv = */ rounded_product(dval(rv), tens[e]);
+#endif
+ goto ret;
+ }
+ }
+#ifndef Inaccurate_Divide
+ else if (e >= -Ten_pmax) {
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv = -rv;
+ sign = 0;
+ }
+#endif
+ /* rv = */ rounded_quotient(dval(rv), tens[-e]);
+ goto ret;
+ }
+#endif
+ }
+ e1 += nd - k;
+
+#ifdef IEEE_Arith
+#ifdef SET_INEXACT
+ inexact = 1;
+ if (k <= DBL_DIG)
+ oldinexact = get_inexact();
+#endif
+#ifdef Avoid_Underflow
+ scale = 0;
+#endif
+#ifdef Honor_FLT_ROUNDS
+ if ((rounding = Flt_Rounds) >= 2) {
+ if (sign)
+ rounding = rounding == 2 ? 0 : 2;
+ else
+ if (rounding != 2)
+ rounding = 0;
+ }
+#endif
+#endif /*IEEE_Arith*/
+
+ /* Get starting approximation = rv * 10**e1 */
+
+ if (e1 > 0) {
+ if ((i = e1 & 15))
+ dval(rv) *= tens[i];
+ if (e1 &= ~15) {
+ if (e1 > DBL_MAX_10_EXP) {
+ ovfl:
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ /* Can't trust HUGE_VAL */
+#ifdef IEEE_Arith
+#ifdef Honor_FLT_ROUNDS
+ switch(rounding) {
+ case 0: /* toward 0 */
+ case 3: /* toward -infinity */
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ break;
+ default:
+ word0(rv) = Exp_mask;
+ word1(rv) = 0;
+ }
+#else /*Honor_FLT_ROUNDS*/
+ word0(rv) = Exp_mask;
+ word1(rv) = 0;
+#endif /*Honor_FLT_ROUNDS*/
+#ifdef SET_INEXACT
+ /* set overflow bit */
+ dval(rv0) = 1e300;
+ dval(rv0) *= dval(rv0);
+#endif
+#else /*IEEE_Arith*/
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+#endif /*IEEE_Arith*/
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+ e1 >>= 4;
+ for(j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= bigtens[j];
+ /* The last multiplication could overflow. */
+ word0(rv) -= P*Exp_msk1;
+ dval(rv) *= bigtens[j];
+ if ((z = word0(rv) & Exp_mask)
+ > Exp_msk1*(DBL_MAX_EXP+Bias-P))
+ goto ovfl;
+ if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
+ /* set to largest number */
+ /* (Can't trust DBL_MAX) */
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ }
+ else
+ word0(rv) += P*Exp_msk1;
+ }
+ }
+ else if (e1 < 0) {
+ e1 = -e1;
+ if ((i = e1 & 15))
+ dval(rv) /= tens[i];
+ if (e1 >>= 4) {
+ if (e1 >= 1 << n_bigtens)
+ goto undfl;
+#ifdef Avoid_Underflow
+ if (e1 & Scale_Bit)
+ scale = 2*P;
+ for(j = 0; e1 > 0; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= tinytens[j];
+ if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
+ >> Exp_shift)) > 0) {
+ /* scaled rv is denormal; zap j low bits */
+ if (j >= 32) {
+ word1(rv) = 0;
+ if (j >= 53)
+ word0(rv) = (P+2)*Exp_msk1;
+ else
+ word0(rv) &= 0xffffffff << (j-32);
+ }
+ else
+ word1(rv) &= 0xffffffff << j;
+ }
+#else
+ for(j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= tinytens[j];
+ /* The last multiplication could underflow. */
+ dval(rv0) = dval(rv);
+ dval(rv) *= tinytens[j];
+ if (!dval(rv)) {
+ dval(rv) = 2.*dval(rv0);
+ dval(rv) *= tinytens[j];
+#endif
+ if (!dval(rv)) {
+ undfl:
+ dval(rv) = 0.;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+#ifndef Avoid_Underflow
+ word0(rv) = Tiny0;
+ word1(rv) = Tiny1;
+ /* The refinement below will clean
+ * this approximation up.
+ */
+ }
+#endif
+ }
+ }
+
+ /* Now the hard part -- adjusting rv to the correct value.*/
+
+ /* Put digits into bd: true value = bd * 10^e */
+
+ bd0 = s2b(s0, nd0, nd, y);
+
+ for(;;) {
+ bd = Balloc(bd0->k);
+ Bcopy(bd, bd0);
+ bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
+ bs = i2b(1);
+
+ if (e >= 0) {
+ bb2 = bb5 = 0;
+ bd2 = bd5 = e;
+ }
+ else {
+ bb2 = bb5 = -e;
+ bd2 = bd5 = 0;
+ }
+ if (bbe >= 0)
+ bb2 += bbe;
+ else
+ bd2 -= bbe;
+ bs2 = bb2;
+#ifdef Honor_FLT_ROUNDS
+ if (rounding != 1)
+ bs2++;
+#endif
+#ifdef Avoid_Underflow
+ j = bbe - scale;
+ i = j + bbbits - 1; /* logb(rv) */
+ if (i < Emin) /* denormal */
+ j += P - Emin;
+ else
+ j = P + 1 - bbbits;
+#else /*Avoid_Underflow*/
+#ifdef Sudden_Underflow
+#ifdef IBM
+ j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
+#else
+ j = P + 1 - bbbits;
+#endif
+#else /*Sudden_Underflow*/
+ j = bbe;
+ i = j + bbbits - 1; /* logb(rv) */
+ if (i < Emin) /* denormal */
+ j += P - Emin;
+ else
+ j = P + 1 - bbbits;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ bb2 += j;
+ bd2 += j;
+#ifdef Avoid_Underflow
+ bd2 += scale;
+#endif
+ i = bb2 < bd2 ? bb2 : bd2;
+ if (i > bs2)
+ i = bs2;
+ if (i > 0) {
+ bb2 -= i;
+ bd2 -= i;
+ bs2 -= i;
+ }
+ if (bb5 > 0) {
+ bs = pow5mult(bs, bb5);
+ bb1 = mult(bs, bb);
+ Bfree(bb);
+ bb = bb1;
+ }
+ if (bb2 > 0)
+ bb = lshift(bb, bb2);
+ if (bd5 > 0)
+ bd = pow5mult(bd, bd5);
+ if (bd2 > 0)
+ bd = lshift(bd, bd2);
+ if (bs2 > 0)
+ bs = lshift(bs, bs2);
+ delta = diff(bb, bd);
+ dsign = delta->sign;
+ delta->sign = 0;
+ i = cmp(delta, bs);
+#ifdef Honor_FLT_ROUNDS
+ if (rounding != 1) {
+ if (i < 0) {
+ /* Error is less than an ulp */
+ if (!delta->x[0] && delta->wds <= 1) {
+ /* exact */
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ if (rounding) {
+ if (dsign) {
+ adj = 1.;
+ goto apply_adj;
+ }
+ }
+ else if (!dsign) {
+ adj = -1.;
+ if (!word1(rv)
+ && !(word0(rv) & Frac_mask)) {
+ y = word0(rv) & Exp_mask;
+#ifdef Avoid_Underflow
+ if (!scale || y > 2*P*Exp_msk1)
+#else
+ if (y)
+#endif
+ {
+ delta = lshift(delta,Log2P);
+ if (cmp(delta, bs) <= 0)
+ adj = -0.5;
+ }
+ }
+ apply_adj:
+#ifdef Avoid_Underflow
+ if (scale && (y = word0(rv) & Exp_mask)
+ <= 2*P*Exp_msk1)
+ word0(adj) += (2*P+1)*Exp_msk1 - y;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(rv) & Exp_mask) <=
+ P*Exp_msk1) {
+ word0(rv) += P*Exp_msk1;
+ dval(rv) += adj*ulp(rv);
+ word0(rv) -= P*Exp_msk1;
+ }
+ else
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ dval(rv) += adj*ulp(rv);
+ }
+ break;
+ }
+ adj = ratio(delta, bs);
+ if (adj < 1.)
+ adj = 1.;
+ if (adj <= 0x7ffffffe) {
+ /* adj = rounding ? ceil(adj) : floor(adj); */
+ y = adj;
+ if (y != adj) {
+ if (!((rounding>>1) ^ dsign))
+ y++;
+ adj = y;
+ }
+ }
+#ifdef Avoid_Underflow
+ if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+ word0(adj) += (2*P+1)*Exp_msk1 - y;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
+ word0(rv) += P*Exp_msk1;
+ adj *= ulp(rv);
+ if (dsign)
+ dval(rv) += adj;
+ else
+ dval(rv) -= adj;
+ word0(rv) -= P*Exp_msk1;
+ goto cont;
+ }
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ adj *= ulp(rv);
+ if (dsign)
+ dval(rv) += adj;
+ else
+ dval(rv) -= adj;
+ goto cont;
+ }
+#endif /*Honor_FLT_ROUNDS*/
+
+ if (i < 0) {
+ /* Error is less than half an ulp -- check for
+ * special case of mantissa a power of two.
+ */
+ if (dsign || word1(rv) || word0(rv) & Bndry_mask
+#ifdef IEEE_Arith
+#ifdef Avoid_Underflow
+ || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
+#else
+ || (word0(rv) & Exp_mask) <= Exp_msk1
+#endif
+#endif
+ ) {
+#ifdef SET_INEXACT
+ if (!delta->x[0] && delta->wds <= 1)
+ inexact = 0;
+#endif
+ break;
+ }
+ if (!delta->x[0] && delta->wds <= 1) {
+ /* exact result */
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ delta = lshift(delta,Log2P);
+ if (cmp(delta, bs) > 0)
+ goto drop_down;
+ break;
+ }
+ if (i == 0) {
+ /* exactly half-way between */
+ if (dsign) {
+ if ((word0(rv) & Bndry_mask1) == Bndry_mask1
+ && word1(rv) == (
+#ifdef Avoid_Underflow
+ (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+ ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
+#endif
+ 0xffffffff)) {
+ /*boundary case -- increment exponent*/
+ word0(rv) = (word0(rv) & Exp_mask)
+ + Exp_msk1
+#ifdef IBM
+ | Exp_msk1 >> 4
+#endif
+ ;
+ word1(rv) = 0;
+#ifdef Avoid_Underflow
+ dsign = 0;
+#endif
+ break;
+ }
+ }
+ else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
+ drop_down:
+ /* boundary case -- decrement exponent */
+#ifdef Sudden_Underflow /*{{*/
+ L = word0(rv) & Exp_mask;
+#ifdef IBM
+ if (L < Exp_msk1)
+#else
+#ifdef Avoid_Underflow
+ if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
+#else
+ if (L <= Exp_msk1)
+#endif /*Avoid_Underflow*/
+#endif /*IBM*/
+ goto undfl;
+ L -= Exp_msk1;
+#else /*Sudden_Underflow}{*/
+#ifdef Avoid_Underflow
+ if (scale) {
+ L = word0(rv) & Exp_mask;
+ if (L <= (2*P+1)*Exp_msk1) {
+ if (L > (P+2)*Exp_msk1)
+ /* round even ==> */
+ /* accept rv */
+ break;
+ /* rv = smallest denormal */
+ goto undfl;
+ }
+ }
+#endif /*Avoid_Underflow*/
+ L = (word0(rv) & Exp_mask) - Exp_msk1;
+#endif /*Sudden_Underflow}}*/
+ word0(rv) = L | Bndry_mask1;
+ word1(rv) = 0xffffffff;
+#ifdef IBM
+ goto cont;
+#else
+ break;
+#endif
+ }
+#ifndef ROUND_BIASED
+ if (!(word1(rv) & LSB))
+ break;
+#endif
+ if (dsign)
+ dval(rv) += ulp(rv);
+#ifndef ROUND_BIASED
+ else {
+ dval(rv) -= ulp(rv);
+#ifndef Sudden_Underflow
+ if (!dval(rv))
+ goto undfl;
+#endif
+ }
+#ifdef Avoid_Underflow
+ dsign = 1 - dsign;
+#endif
+#endif
+ break;
+ }
+ if ((aadj = ratio(delta, bs)) <= 2.) {
+ if (dsign)
+ aadj = dval(aadj1) = 1.;
+ else if (word1(rv) || word0(rv) & Bndry_mask) {
+#ifndef Sudden_Underflow
+ if (word1(rv) == Tiny1 && !word0(rv))
+ goto undfl;
+#endif
+ aadj = 1.;
+ dval(aadj1) = -1.;
+ }
+ else {
+ /* special case -- power of FLT_RADIX to be */
+ /* rounded down... */
+
+ if (aadj < 2./FLT_RADIX)
+ aadj = 1./FLT_RADIX;
+ else
+ aadj *= 0.5;
+ dval(aadj1) = -aadj;
+ }
+ }
+ else {
+ aadj *= 0.5;
+ dval(aadj1) = dsign ? aadj : -aadj;
+#ifdef Check_FLT_ROUNDS
+ switch(Rounding) {
+ case 2: /* towards +infinity */
+ dval(aadj1) -= 0.5;
+ break;
+ case 0: /* towards 0 */
+ case 3: /* towards -infinity */
+ dval(aadj1) += 0.5;
+ }
+#else
+ if (Flt_Rounds == 0)
+ dval(aadj1) += 0.5;
+#endif /*Check_FLT_ROUNDS*/
+ }
+ y = word0(rv) & Exp_mask;
+
+ /* Check for overflow */
+
+ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
+ dval(rv0) = dval(rv);
+ word0(rv) -= P*Exp_msk1;
+ adj = dval(aadj1) * ulp(rv);
+ dval(rv) += adj;
+ if ((word0(rv) & Exp_mask) >=
+ Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
+ if (word0(rv0) == Big0 && word1(rv0) == Big1)
+ goto ovfl;
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ goto cont;
+ }
+ else
+ word0(rv) += P*Exp_msk1;
+ }
+ else {
+#ifdef Avoid_Underflow
+ if (scale && y <= 2*P*Exp_msk1) {
+ if (aadj <= 0x7fffffff) {
+ if ((z = (ULong) aadj) <= 0)
+ z = 1;
+ aadj = z;
+ dval(aadj1) = dsign ? aadj : -aadj;
+ }
+ word0(aadj1) += (2*P+1)*Exp_msk1 - y;
+ }
+ adj = dval(aadj1) * ulp(rv);
+ dval(rv) += adj;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
+ dval(rv0) = dval(rv);
+ word0(rv) += P*Exp_msk1;
+ adj = dval(aadj1) * ulp(rv);
+ dval(rv) += adj;
+#ifdef IBM
+ if ((word0(rv) & Exp_mask) < P*Exp_msk1)
+#else
+ if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
+#endif
+ {
+ if (word0(rv0) == Tiny0
+ && word1(rv0) == Tiny1)
+ goto undfl;
+ word0(rv) = Tiny0;
+ word1(rv) = Tiny1;
+ goto cont;
+ }
+ else
+ word0(rv) -= P*Exp_msk1;
+ }
+ else {
+ adj = dval(aadj1) * ulp(rv);
+ dval(rv) += adj;
+ }
+#else /*Sudden_Underflow*/
+ /* Compute adj so that the IEEE rounding rules will
+ * correctly round rv + adj in some half-way cases.
+ * If rv * ulp(rv) is denormalized (i.e.,
+ * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
+ * trouble from bits lost to denormalization;
+ * example: 1.2e-307 .
+ */
+ if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
+ dval(aadj1) = (double)(int)(aadj + 0.5);
+ if (!dsign)
+ dval(aadj1) = -dval(aadj1);
+ }
+ adj = dval(aadj1) * ulp(rv);
+ dval(rv) += adj;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ }
+ z = word0(rv) & Exp_mask;
+#ifndef SET_INEXACT
+#ifdef Avoid_Underflow
+ if (!scale)
+#endif
+ if (y == z) {
+ /* Can we stop now? */
+ L = (Long)aadj;
+ aadj -= L;
+ /* The tolerances below are conservative. */
+ if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
+ if (aadj < .4999999 || aadj > .5000001)
+ break;
+ }
+ else if (aadj < .4999999/FLT_RADIX)
+ break;
+ }
+#endif
+ cont:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(delta);
+ }
+#ifdef SET_INEXACT
+ if (inexact) {
+ if (!oldinexact) {
+ word0(rv0) = Exp_1 + (70 << Exp_shift);
+ word1(rv0) = 0;
+ dval(rv0) += 1.;
+ }
+ }
+ else if (!oldinexact)
+ clear_inexact();
+#endif
+#ifdef Avoid_Underflow
+ if (scale) {
+ word0(rv0) = Exp_1 - 2*P*Exp_msk1;
+ word1(rv0) = 0;
+ dval(rv) *= dval(rv0);
+#ifndef NO_ERRNO
+ /* try to avoid the bug of testing an 8087 register value */
+ if (word0(rv) == 0 && word1(rv) == 0)
+ errno = ERANGE;
+#endif
+ }
+#endif /* Avoid_Underflow */
+#ifdef SET_INEXACT
+ if (inexact && !(word0(rv) & Exp_mask)) {
+ /* set underflow bit */
+ dval(rv0) = 1e-300;
+ dval(rv0) *= dval(rv0);
+ }
+#endif
+ retfree:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
+ ret:
+ if (se)
+ *se = (char *)s;
+ return sign ? -dval(rv) : dval(rv);
+ }
+
+ static int
+quorem
+#ifdef KR_headers
+ (b, S) Bigint *b, *S;
+#else
+ (Bigint *b, Bigint *S)
+#endif
+{
+ int n;
+ ULong *bx, *bxe, q, *sx, *sxe;
+#ifdef ULLong
+ ULLong borrow, carry, y, ys;
+#else
+ ULong borrow, carry, y, ys;
+#ifdef Pack_32
+ ULong si, z, zs;
+#endif
+#endif
+
+ n = S->wds;
+#ifdef DEBUG
+ /*debug*/ if (b->wds > n)
+ /*debug*/ Bug("oversize b in quorem");
+#endif
+ if (b->wds < n)
+ return 0;
+ sx = S->x;
+ sxe = sx + --n;
+ bx = b->x;
+ bxe = bx + n;
+ q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
+#ifdef DEBUG
+ /*debug*/ if (q > 9)
+ /*debug*/ Bug("oversized quotient in quorem");
+#endif
+ if (q) {
+ borrow = 0;
+ carry = 0;
+ do {
+#ifdef ULLong
+ ys = *sx++ * (ULLong)q + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & FFFFFFFF) - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *bx++ = (ULong) y & FFFFFFFF;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) * q + carry;
+ zs = (si >> 16) * q + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ * q + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(sx <= sxe);
+ if (!*bxe) {
+ bx = b->x;
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ if (cmp(b, S) >= 0) {
+ q++;
+ borrow = 0;
+ carry = 0;
+ bx = b->x;
+ sx = S->x;
+ do {
+#ifdef ULLong
+ ys = *sx++ + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & FFFFFFFF) - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *bx++ = (ULong) y & FFFFFFFF;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) + carry;
+ zs = (si >> 16) + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(sx <= sxe);
+ bx = b->x;
+ bxe = bx + n;
+ if (!*bxe) {
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ return q;
+ }
+
+#ifndef MULTIPLE_THREADS
+ static char *dtoa_result;
+#endif
+
+ static char *
+#ifdef KR_headers
+rv_alloc(i) int i;
+#else
+rv_alloc(int i)
+#endif
+{
+ int j, k, *r;
+
+ j = sizeof(ULong);
+ for(k = 0;
+ sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (unsigned) i;
+ j <<= 1)
+ k++;
+ r = (int*)Balloc(k);
+ *r = k;
+ return
+#ifndef MULTIPLE_THREADS
+ dtoa_result =
+#endif
+ (char *)(r+1);
+ }
+
+ static char *
+#ifdef KR_headers
+nrv_alloc(s, rve, n) char *s, **rve; int n;
+#else
+nrv_alloc(CONST char *s, char **rve, int n)
+#endif
+{
+ char *rv, *t;
+
+ t = rv = rv_alloc(n);
+ while((*t = *s++)) t++;
+ if (rve)
+ *rve = t;
+ return rv;
+ }
+
+/* freedtoa(s) must be used to free values s returned by dtoa
+ * when MULTIPLE_THREADS is #defined. It should be used in all cases,
+ * but for consistency with earlier versions of dtoa, it is optional
+ * when MULTIPLE_THREADS is not defined.
+ */
+
+ void
+#ifdef KR_headers
+freedtoa(s) char *s;
+#else
+freedtoa(char *s)
+#endif
+{
+ Bigint *b = (Bigint *)((int *)s - 1);
+ b->maxwds = 1 << (b->k = *(int*)b);
+ Bfree(b);
+#ifndef MULTIPLE_THREADS
+ if (s == dtoa_result)
+ dtoa_result = 0;
+#endif
+ }
+
+/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+ *
+ * Inspired by "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
+ *
+ * Modifications:
+ * 1. Rather than iterating, we use a simple numeric overestimate
+ * to determine k = floor(log10(d)). We scale relevant
+ * quantities using O(log2(k)) rather than O(k) multiplications.
+ * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ * try to generate digits strictly left to right. Instead, we
+ * compute with fewer bits and propagate the carry if necessary
+ * when rounding the final digit up. This is often faster.
+ * 3. Under the assumption that input will be rounded nearest,
+ * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ * That is, we allow equality in stopping tests when the
+ * round-nearest rule will give the same floating-point value
+ * as would satisfaction of the stopping test with strict
+ * inequality.
+ * 4. We remove common factors of powers of 2 from relevant
+ * quantities.
+ * 5. When converting floating-point integers less than 1e16,
+ * we use floating-point arithmetic rather than resorting
+ * to multiple-precision integers.
+ * 6. When asked to produce fewer than 15 digits, we first try
+ * to get by with floating-point arithmetic; we resort to
+ * multiple-precision integer arithmetic only if we cannot
+ * guarantee that the floating-point calculation has given
+ * the correctly rounded result. For k requested digits and
+ * "uniformly" distributed input, the probability is
+ * something like 10^(k-15) that we must resort to the Long
+ * calculation.
+ */
+
+ static char *
+dtoa
+#ifdef KR_headers
+ (d, mode, ndigits, decpt, sign, rve)
+ U d; int mode, ndigits, *decpt, *sign; char **rve;
+#else
+ (U d, int mode, int ndigits, int *decpt, int *sign, char **rve)
+#endif
+{
+ /* Arguments ndigits, decpt, sign are similar to those
+ of ecvt and fcvt; trailing zeros are suppressed from
+ the returned string. If not null, *rve is set to point
+ to the end of the return value. If d is +-Infinity or NaN,
+ then *decpt is set to 9999.
+
+ mode:
+ 0 ==> shortest string that yields d when read in
+ and rounded to nearest.
+ 1 ==> like 0, but with Steele & White stopping rule;
+ e.g. with IEEE P754 arithmetic , mode 0 gives
+ 1e23 whereas mode 1 gives 9.999999999999999e22.
+ 2 ==> max(1,ndigits) significant digits. This gives a
+ return value similar to that of ecvt, except
+ that trailing zeros are suppressed.
+ 3 ==> through ndigits past the decimal point. This
+ gives a return value similar to that from fcvt,
+ except that trailing zeros are suppressed, and
+ ndigits can be negative.
+ 4,5 ==> similar to 2 and 3, respectively, but (in
+ round-nearest mode) with the tests of mode 0 to
+ possibly return a shorter string that rounds to d.
+ With IEEE arithmetic and compilation with
+ -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
+ as modes 2 and 3 when FLT_ROUNDS != 1.
+ 6-9 ==> Debugging modes similar to mode - 4: don't try
+ fast floating-point estimate (if applicable).
+
+ Values of mode other than 0-9 are treated as mode 0.
+
+ Sufficient space is allocated to the return value
+ to hold the suppressed trailing zeros.
+ */
+
+ int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
+ j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
+ spec_case, try_quick;
+ Long L;
+#ifndef Sudden_Underflow
+ int denorm;
+ ULong x;
+#endif
+ Bigint *b, *b1, *delta, *mlo, *mhi, *S;
+ U d2, eps;
+ double ds;
+ char *s, *s0;
+#ifdef Honor_FLT_ROUNDS
+ int rounding;
+#endif
+#ifdef SET_INEXACT
+ int inexact, oldinexact;
+#endif
+
+#ifdef __GNUC__
+ ilim = ilim1 = 0;
+ mlo = NULL;
+#endif
+
+#ifndef MULTIPLE_THREADS
+ if (dtoa_result) {
+ freedtoa(dtoa_result);
+ dtoa_result = 0;
+ }
+#endif
+
+ if (word0(d) & Sign_bit) {
+ /* set sign for everything, including 0's and NaNs */
+ *sign = 1;
+ word0(d) &= ~Sign_bit; /* clear sign bit */
+ }
+ else
+ *sign = 0;
+
+#if defined(IEEE_Arith) + defined(VAX)
+#ifdef IEEE_Arith
+ if ((word0(d) & Exp_mask) == Exp_mask)
+#else
+ if (word0(d) == 0x8000)
+#endif
+ {
+ /* Infinity or NaN */
+ *decpt = 9999;
+#ifdef IEEE_Arith
+ if (!word1(d) && !(word0(d) & 0xfffff))
+ return nrv_alloc("Infinity", rve, 8);
+#endif
+ return nrv_alloc("NaN", rve, 3);
+ }
+#endif
+#ifdef IBM
+ dval(d) += 0; /* normalize */
+#endif
+ if (!dval(d)) {
+ *decpt = 1;
+ return nrv_alloc("0", rve, 1);
+ }
+
+#ifdef SET_INEXACT
+ try_quick = oldinexact = get_inexact();
+ inexact = 1;
+#endif
+#ifdef Honor_FLT_ROUNDS
+ if ((rounding = Flt_Rounds) >= 2) {
+ if (*sign)
+ rounding = rounding == 2 ? 0 : 2;
+ else
+ if (rounding != 2)
+ rounding = 0;
+ }
+#endif
+
+ b = d2b(d, &be, &bbits);
+#ifdef Sudden_Underflow
+ i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
+#else
+ if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) {
+#endif
+ dval(d2) = dval(d);
+ word0(d2) &= Frac_mask1;
+ word0(d2) |= Exp_11;
+#ifdef IBM
+ if (j = 11 - hi0bits(word0(d2) & Frac_mask))
+ dval(d2) /= 1 << j;
+#endif
+
+ /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
+ * log10(x) = log(x) / log(10)
+ * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+ * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+ *
+ * This suggests computing an approximation k to log10(d) by
+ *
+ * k = (i - Bias)*0.301029995663981
+ * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+ *
+ * We want k to be too large rather than too small.
+ * The error in the first-order Taylor series approximation
+ * is in our favor, so we just round up the constant enough
+ * to compensate for any error in the multiplication of
+ * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+ * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+ * adding 1e-13 to the constant term more than suffices.
+ * Hence we adjust the constant term to 0.1760912590558.
+ * (We could get a more accurate k by invoking log10,
+ * but this is probably not worthwhile.)
+ */
+
+ i -= Bias;
+#ifdef IBM
+ i <<= 2;
+ i += j;
+#endif
+#ifndef Sudden_Underflow
+ denorm = 0;
+ }
+ else {
+ /* d is denormalized */
+
+ i = bbits + be + (Bias + (P-1) - 1);
+ x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32)
+ : word1(d) << (32 - i);
+ dval(d2) = x;
+ word0(d2) -= 31*Exp_msk1; /* adjust exponent */
+ i -= (Bias + (P-1) - 1) + 1;
+ denorm = 1;
+ }
+#endif
+ ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ k = (int)ds;
+ if (ds < 0. && ds != k)
+ k--; /* want k = floor(ds) */
+ k_check = 1;
+ if (k >= 0 && k <= Ten_pmax) {
+ if (dval(d) < tens[k])
+ k--;
+ k_check = 0;
+ }
+ j = bbits - i - 1;
+ if (j >= 0) {
+ b2 = 0;
+ s2 = j;
+ }
+ else {
+ b2 = -j;
+ s2 = 0;
+ }
+ if (k >= 0) {
+ b5 = 0;
+ s5 = k;
+ s2 += k;
+ }
+ else {
+ b2 -= k;
+ b5 = -k;
+ s5 = 0;
+ }
+ if (mode < 0 || mode > 9)
+ mode = 0;
+
+#ifndef SET_INEXACT
+#ifdef Check_FLT_ROUNDS
+ try_quick = Rounding == 1;
+#else
+ try_quick = 1;
+#endif
+#endif /*SET_INEXACT*/
+
+ if (mode > 5) {
+ mode -= 4;
+ try_quick = 0;
+ }
+ leftright = 1;
+ switch(mode) {
+ case 0:
+ case 1:
+ ilim = ilim1 = -1;
+ i = 18;
+ ndigits = 0;
+ break;
+ case 2:
+ leftright = 0;
+ /* no break */
+ case 4:
+ if (ndigits <= 0)
+ ndigits = 1;
+ ilim = ilim1 = i = ndigits;
+ break;
+ case 3:
+ leftright = 0;
+ /* no break */
+ case 5:
+ i = ndigits + k + 1;
+ ilim = i;
+ ilim1 = i - 1;
+ if (i <= 0)
+ i = 1;
+ }
+ s = s0 = rv_alloc(i);
+
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1 && rounding != 1)
+ leftright = 0;
+#endif
+
+ if (ilim >= 0 && ilim <= Quick_max && try_quick) {
+
+ /* Try to get by with floating-point arithmetic. */
+
+ i = 0;
+ dval(d2) = dval(d);
+ k0 = k;
+ ilim0 = ilim;
+ ieps = 2; /* conservative */
+ if (k > 0) {
+ ds = tens[k&0xf];
+ j = k >> 4;
+ if (j & Bletch) {
+ /* prevent overflows */
+ j &= Bletch - 1;
+ dval(d) /= bigtens[n_bigtens-1];
+ ieps++;
+ }
+ for(; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ ds *= bigtens[i];
+ }
+ dval(d) /= ds;
+ }
+ else if ((j1 = -k)) {
+ dval(d) *= tens[j1 & 0xf];
+ for(j = j1 >> 4; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ dval(d) *= bigtens[i];
+ }
+ }
+ if (k_check && dval(d) < 1. && ilim > 0) {
+ if (ilim1 <= 0)
+ goto fast_failed;
+ ilim = ilim1;
+ k--;
+ dval(d) *= 10.;
+ ieps++;
+ }
+ dval(eps) = ieps*dval(d) + 7.;
+ word0(eps) -= (P-1)*Exp_msk1;
+ if (ilim == 0) {
+ S = mhi = 0;
+ dval(d) -= 5.;
+ if (dval(d) > dval(eps))
+ goto one_digit;
+ if (dval(d) < -dval(eps))
+ goto no_digits;
+ goto fast_failed;
+ }
+#ifndef No_leftright
+ if (leftright) {
+ /* Use Steele & White method of only
+ * generating digits needed.
+ */
+ dval(eps) = 0.5/tens[ilim-1] - dval(eps);
+ for(i = 0;;) {
+ L = (ULong) dval(d);
+ dval(d) -= L;
+ *s++ = '0' + (int)L;
+ if (dval(d) < dval(eps))
+ goto ret1;
+ if (1. - dval(d) < dval(eps))
+ goto bump_up;
+ if (++i >= ilim)
+ break;
+ dval(eps) *= 10.;
+ dval(d) *= 10.;
+ }
+ }
+ else {
+#endif
+ /* Generate ilim digits, then fix them up. */
+ dval(eps) *= tens[ilim-1];
+ for(i = 1;; i++, dval(d) *= 10.) {
+ L = (Long)(dval(d));
+ if (!(dval(d) -= L))
+ ilim = i;
+ *s++ = '0' + (int)L;
+ if (i == ilim) {
+ if (dval(d) > 0.5 + dval(eps))
+ goto bump_up;
+ else if (dval(d) < 0.5 - dval(eps)) {
+ while(*--s == '0');
+ s++;
+ goto ret1;
+ }
+ break;
+ }
+ }
+#ifndef No_leftright
+ }
+#endif
+ fast_failed:
+ s = s0;
+ dval(d) = dval(d2);
+ k = k0;
+ ilim = ilim0;
+ }
+
+ /* Do we have a "small" integer? */
+
+ if (be >= 0 && k <= Int_max) {
+ /* Yes. */
+ ds = tens[k];
+ if (ndigits < 0 && ilim <= 0) {
+ S = mhi = 0;
+ if (ilim < 0 || dval(d) <= 5*ds)
+ goto no_digits;
+ goto one_digit;
+ }
+ for(i = 1;; i++, dval(d) *= 10.) {
+ L = (Long)(dval(d) / ds);
+ dval(d) -= L*ds;
+#ifdef Check_FLT_ROUNDS
+ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
+ if (dval(d) < 0) {
+ L--;
+ dval(d) += ds;
+ }
+#endif
+ *s++ = '0' + (int)L;
+ if (!dval(d)) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ if (i == ilim) {
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1)
+ switch(rounding) {
+ case 0: goto ret1;
+ case 2: goto bump_up;
+ }
+#endif
+ dval(d) += dval(d);
+ if (dval(d) > ds || (dval(d) == ds && L & 1)) {
+ bump_up:
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s = '0';
+ break;
+ }
+ ++*s++;
+ }
+ break;
+ }
+ }
+ goto ret1;
+ }
+
+ m2 = b2;
+ m5 = b5;
+ mhi = mlo = 0;
+ if (leftright) {
+ i =
+#ifndef Sudden_Underflow
+ denorm ? be + (Bias + (P-1) - 1 + 1) :
+#endif
+#ifdef IBM
+ 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
+#else
+ 1 + P - bbits;
+#endif
+ b2 += i;
+ s2 += i;
+ mhi = i2b(1);
+ }
+ if (m2 > 0 && s2 > 0) {
+ i = m2 < s2 ? m2 : s2;
+ b2 -= i;
+ m2 -= i;
+ s2 -= i;
+ }
+ if (b5 > 0) {
+ if (leftright) {
+ if (m5 > 0) {
+ mhi = pow5mult(mhi, m5);
+ b1 = mult(mhi, b);
+ Bfree(b);
+ b = b1;
+ }
+ if ((j = b5 - m5))
+ b = pow5mult(b, j);
+ }
+ else
+ b = pow5mult(b, b5);
+ }
+ S = i2b(1);
+ if (s5 > 0)
+ S = pow5mult(S, s5);
+
+ /* Check for special case that d is a normalized power of 2. */
+
+ spec_case = 0;
+ if ((mode < 2 || leftright)
+#ifdef Honor_FLT_ROUNDS
+ && rounding == 1
+#endif
+ ) {
+ if (!word1(d) && !(word0(d) & Bndry_mask)
+#ifndef Sudden_Underflow
+ && word0(d) & (Exp_mask & ~Exp_msk1)
+#endif
+ ) {
+ /* The special case */
+ b2 += Log2P;
+ s2 += Log2P;
+ spec_case = 1;
+ }
+ }
+
+ /* Arrange for convenient computation of quotients:
+ * shift left if necessary so divisor has 4 leading 0 bits.
+ *
+ * Perhaps we should just compute leading 28 bits of S once
+ * and for all and pass them and a shift to quorem, so it
+ * can do shifts and ors to compute the numerator for q.
+ */
+#ifdef Pack_32
+ if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f))
+ i = 32 - i;
+#else
+ if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
+ i = 16 - i;
+#endif
+ if (i > 4) {
+ i -= 4;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ else if (i < 4) {
+ i += 28;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ if (b2 > 0)
+ b = lshift(b, b2);
+ if (s2 > 0)
+ S = lshift(S, s2);
+ if (k_check) {
+ if (cmp(b,S) < 0) {
+ k--;
+ b = multadd(b, 10, 0); /* we botched the k estimate */
+ if (leftright)
+ mhi = multadd(mhi, 10, 0);
+ ilim = ilim1;
+ }
+ }
+ if (ilim <= 0 && (mode == 3 || mode == 5)) {
+ if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
+ /* no digits, fcvt style */
+ no_digits:
+ /* MOZILLA CHANGE: Always return a non-empty string. */
+ *s++ = '0';
+ k = 0;
+ goto ret;
+ }
+ one_digit:
+ *s++ = '1';
+ k++;
+ goto ret;
+ }
+ if (leftright) {
+ if (m2 > 0)
+ mhi = lshift(mhi, m2);
+
+ /* Compute mlo -- check for special case
+ * that d is a normalized power of 2.
+ */
+
+ mlo = mhi;
+ if (spec_case) {
+ mhi = Balloc(mhi->k);
+ Bcopy(mhi, mlo);
+ mhi = lshift(mhi, Log2P);
+ }
+
+ for(i = 1;;i++) {
+ dig = quorem(b,S) + '0';
+ /* Do we yet have the shortest decimal string
+ * that will round to d?
+ */
+ j = cmp(b, mlo);
+ delta = diff(S, mhi);
+ j1 = delta->sign ? 1 : cmp(b, delta);
+ Bfree(delta);
+#ifndef ROUND_BIASED
+ if (j1 == 0 && mode != 1 && !(word1(d) & 1)
+#ifdef Honor_FLT_ROUNDS
+ && rounding >= 1
+#endif
+ ) {
+ if (dig == '9')
+ goto round_9_up;
+ if (j > 0)
+ dig++;
+#ifdef SET_INEXACT
+ else if (!b->x[0] && b->wds <= 1)
+ inexact = 0;
+#endif
+ *s++ = dig;
+ goto ret;
+ }
+#endif
+ if (j < 0 || (j == 0 && mode != 1
+#ifndef ROUND_BIASED
+ && !(word1(d) & 1)
+#endif
+ )) {
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto accept_dig;
+ }
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1)
+ switch(rounding) {
+ case 0: goto accept_dig;
+ case 2: goto keep_dig;
+ }
+#endif /*Honor_FLT_ROUNDS*/
+ if (j1 > 0) {
+ b = lshift(b, 1);
+ j1 = cmp(b, S);
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
+ && dig++ == '9')
+ goto round_9_up;
+ }
+ accept_dig:
+ *s++ = dig;
+ goto ret;
+ }
+ if (j1 > 0) {
+#ifdef Honor_FLT_ROUNDS
+ if (!rounding)
+ goto accept_dig;
+#endif
+ if (dig == '9') { /* possible if i == 1 */
+ round_9_up:
+ *s++ = '9';
+ goto roundoff;
+ }
+ *s++ = dig + 1;
+ goto ret;
+ }
+#ifdef Honor_FLT_ROUNDS
+ keep_dig:
+#endif
+ *s++ = dig;
+ if (i == ilim)
+ break;
+ b = multadd(b, 10, 0);
+ if (mlo == mhi)
+ mlo = mhi = multadd(mhi, 10, 0);
+ else {
+ mlo = multadd(mlo, 10, 0);
+ mhi = multadd(mhi, 10, 0);
+ }
+ }
+ }
+ else
+ for(i = 1;; i++) {
+ *s++ = dig = quorem(b,S) + '0';
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto ret;
+ }
+ if (i >= ilim)
+ break;
+ b = multadd(b, 10, 0);
+ }
+
+ /* Round off last digit */
+
+#ifdef Honor_FLT_ROUNDS
+ switch(rounding) {
+ case 0: goto trimzeros;
+ case 2: goto roundoff;
+ }
+#endif
+ b = lshift(b, 1);
+ j = cmp(b, S);
+ if (j > 0 || (j == 0 && dig & 1)) {
+ roundoff:
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s++ = '1';
+ goto ret;
+ }
+ ++*s++;
+ }
+ else {
+#ifdef Honor_FLT_ROUNDS
+ trimzeros:
+#endif
+ while(*--s == '0');
+ s++;
+ }
+ ret:
+ Bfree(S);
+ if (mhi) {
+ if (mlo && mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ }
+ ret1:
+#ifdef SET_INEXACT
+ if (inexact) {
+ if (!oldinexact) {
+ word0(d) = Exp_1 + (70 << Exp_shift);
+ word1(d) = 0;
+ dval(d) += 1.;
+ }
+ }
+ else if (!oldinexact)
+ clear_inexact();
+#endif
+ Bfree(b);
+ *s = 0;
+ *decpt = k + 1;
+ if (rve)
+ *rve = s;
+ return s0;
+ }
+#ifdef __cplusplus
+}
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/Makefile.ref b/tools/node_modules/expresso/deps/jscoverage/js/editline/Makefile.ref
new file mode 100644
index 0000000..c902c88
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/Makefile.ref
@@ -0,0 +1,143 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Simmule Turner and Rich Salz.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+#
+# This software is not subject to any license of the American Telephone
+# and Telegraph Company or of the Regents of the University of California.
+#
+# Permission is granted to anyone to use this software for any purpose on
+# any computer system, and to alter it and redistribute it freely, subject
+# to the following restrictions:
+# 1. The authors are not responsible for the consequences of use of this
+# software, no matter how awful, even if they arise from flaws in it.
+# 2. The origin of this software must not be misrepresented, either by
+# explicit claim or by omission. Since few users ever read sources,
+# credits must appear in the documentation.
+# 3. Altered versions must be plainly marked as such, and must not be
+# misrepresented as being the original software. Since few users
+# ever read sources, credits must appear in the documentation.
+# 4. This notice may not be removed or altered.
+#
+
+#
+# Unix makefile for editline library.
+#
+
+## Set your options:
+## -DANSI_ARROWS ANSI arrows keys work like emacs.
+## -DHAVE_STDLIB Have <stdlib.h>.
+## -DHAVE_TCGETATTR Have tcgetattr(), tcsetattr().
+## -DHAVE_TERMIO Have "struct termio" and <termio.h>
+## (If neither of above two, we use <sgttyb.h> and BSD ioctl's)
+## -DHIDE Make static functions static (non debug).
+## -DHIST_SIZE=n History size.
+## -DNEED_STRDUP Don't have strdup().
+## -DUNIQUE_HISTORY Don't save command if same as last one.
+## -DUSE_DIRENT Use <dirent.h>, not <sys/dir.h>?
+## -DUSE_TERMCAP Use the termcap library for terminal size
+## see LDFLAGS, below, if you set this.
+## -DNEED_PERROR Don't have perror() (used in testit)
+
+## If you have -DUSE_TERMCAP, set this as appropriate:
+#LDFLAGS = -ltermlib
+#LDFLAGS = -ltermcap
+
+DEFS = -DANSI_ARROWS -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT -DSYS_UNIX \
+ -DHAVE_STDLIB -DUNIQUE_HISTORY
+
+DEPTH = ..
+
+include $(DEPTH)/config.mk
+
+LOCAL_OBJDIR = $(OBJDIR)/editline
+
+#
+# Default IEEE libm
+#
+CFLAGS += -DXP_UNIX $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \
+ -DJSFILE $(XCFLAGS) $(DEFS)
+
+INCFILES = editline.h
+.INIT: $(INCFILES)
+.KEEP_STATE:
+EDITLINE_CFILES = editline.c sysunix.c
+
+EDITLINE_OBJS = $(addprefix $(LOCAL_OBJDIR)/, $(EDITLINE_CFILES:.c=.o))
+
+LIBRARY = $(LOCAL_OBJDIR)/libedit.a
+
+all: $(LIBRARY)
+
+export:
+
+# make objects to depen on $(LOCAL_OBJDIR) only when it exists
+$(EDITLINE_OBJS) : $(filter-out $(wildcard $(LOCAL_OBJDIR)), $(LOCAL_OBJDIR))
+
+$(LOCAL_OBJDIR) :
+ mkdir -p $@
+
+$(LOCAL_OBJDIR)/%: %.c
+ $(CC) -o $@ $(CFLAGS) $*.c $(LDFLAGS)
+
+$(LOCAL_OBJDIR)/%.o: %.c
+ $(CC) -o $@ -c $(CFLAGS) $*.c
+
+$(LOCAL_OBJDIR)/%.o: %.s
+ $(AS) -o $@ $(ASFLAGS) $*.s
+
+$(LIBRARY): $(EDITLINE_OBJS)
+ $(AR) rv $@ $?
+ $(RANLIB) $@
+
+#libedit.a : $(EDITLINE_OBJS)
+# $(AR) cru $(LOCAL_OBJDIR)/libedit.a $(EDITLINE_OBJS)
+# $(RANLIB) $(LOCAL_OBJDIR)/libedit.a
+
+clean:
+ rm -rf $(EDITLINE_OBJS) $(EDITLINE_OBJS:.o=.d)
+
+clobber: clean
+ rm -rf $(LIBRARY) $(DEPENDENCIES)
+ if test -d $(LOCAL_OBJDIR); then rmdir $(LOCAL_OBJDIR); fi
+
+SUFFIXES: .i
+%.i: %.c
+ $(CC) -C -E $(CFLAGS) $< > $*.i
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/README b/tools/node_modules/expresso/deps/jscoverage/js/editline/README
new file mode 100644
index 0000000..53ec359
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/README
@@ -0,0 +1,83 @@
+The files in this directory provide simple line-editing and history
+support for the standalone javascript engine, through the 'editline'
+library.
+
+editline has only been enabled for those platforms on which it is
+known to build; to try it on a different platform, define JS_EDITLINE
+before building. Line editing (and js.c) is not a supported feature
+of the javascript library, so your mileage my vary.
+
+The editline API is a compatible subset of the FSF readline API; if
+you have readline installed and would like to link to that instead,
+define JS_READLINE. Note that the readline library is distributed
+under the GPL, so any resulting binaries are not legally
+distributable.
+
+The editline files used here have been modified to work with the js
+build system and to quiet some compiler warnings, and also to remove
+filename-completion support.
+
+If anyone knows of a more recent version of these files, or a site on
+which they are being maintained, please let me know!
+
+Mike McCabe, mccabe@netscape.com
+
+
+The original README file distributed with the editline library follows.
+
+
+
+This is a line-editing library. It can be linked into almost any
+program to provide command-line editing and recall.
+
+It is call-compatible with the FSF readline library, but it is a
+fraction of the size (and offers fewer features). It does not use
+standard I/O. It is distributed under a "C News-like" copyright.
+
+Configuration is done in the Makefile. Type "make testit" to get
+a small slow shell for testing.
+
+An earlier version was distributed with Byron's rc. Principal
+changes over that version include:
+ Faster.
+ Is eight-bit clean (thanks to brendan@cs.widener.edu)
+ Written in K&R C, but ANSI compliant (gcc all warnings)
+ Propagates EOF properly; rc trip test now passes
+ Doesn't need or use or provide memmove.
+ More robust
+ Calling sequence changed to be compatible with readline.
+ Test program, new manpage, better configuration
+ More system-independant; includes Unix and OS-9 support.
+
+This contains some changes since the posting to comp.sources.misc:
+ Bugfix for completion on absolute pathnames.
+ Better handling of M-n versus showing raw 8bit chars.
+ Better signal handling.
+ Now supports termios/termio/sgttyb ioctl's.
+ Add M-m command to toggle how 8bit data is displayed.
+
+There is one known bug:
+ History-searching redraws the line wrong if the text
+ retrieved is shorter then the prompt.
+
+Enjoy,
+ Rich $alz
+ <rsalz@osf.org>
+
+ Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+
+ This software is not subject to any license of the American Telephone
+ and Telegraph Company or of the Regents of the University of California.
+
+ Permission is granted to anyone to use this software for any purpose on
+ any computer system, and to alter it and redistribute it freely, subject
+ to the following restrictions:
+ 1. The authors are not responsible for the consequences of use of this
+ software, no matter how awful, even if they arise from flaws in it.
+ 2. The origin of this software must not be misrepresented, either by
+ explicit claim or by omission. Since few users ever read sources,
+ credits must appear in the documentation.
+ 3. Altered versions must be plainly marked as such, and must not be
+ misrepresented as being the original software. Since few users
+ ever read sources, credits must appear in the documentation.
+ 4. This notice may not be removed or altered.
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.3 b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.3
new file mode 100644
index 0000000..21a72ca
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.3
@@ -0,0 +1,175 @@
+.TH EDITLINE 3
+.SH NAME
+editline \- command-line editing library with history
+.SH SYNOPSIS
+.nf
+.B "char *"
+.B "readline(prompt)"
+.B " char *prompt;"
+
+.B "void"
+.B "add_history(line)"
+.B " char *line;"
+.fi
+.SH DESCRIPTION
+.I Editline
+is a library that provides an line-editing interface with text recall.
+It is intended to be compatible with the
+.I readline
+library provided by the Free Software Foundation, but much smaller.
+The bulk of this manual page describes the user interface.
+.PP
+The
+.I readline
+routine returns a line of text with the trailing newline removed.
+The data is returned in a buffer allocated with
+.IR malloc (3),
+so the space should be released with
+.IR free (3)
+when the calling program is done with it.
+Before accepting input from the user, the specified
+.I prompt
+is displayed on the terminal.
+.PP
+The
+.I add_history
+routine makes a copy of the specified
+.I line
+and adds it to the internal history list.
+.SS "User Interface"
+A program that uses this library provides a simple emacs-like editing
+interface to its users.
+A line may be edited before it is sent to the calling program by typing either
+control characters or escape sequences.
+A control character, shown as a caret followed by a letter, is typed by
+holding down the ``control'' key while the letter is typed.
+For example, ``^A'' is a control-A.
+An escape sequence is entered by typing the ``escape'' key followed by one or
+more characters.
+The escape key is abbreviated as ``ESC.''
+Note that unlike control keys, case matters in escape sequences; ``ESC\ F''
+is not the same as ``ESC\ f''.
+.PP
+An editing command may be typed anywhere on the line, not just at the
+beginning.
+In addition, a return may also be typed anywhere on the line, not just at
+the end.
+.PP
+Most editing commands may be given a repeat count,
+.IR n ,
+where
+.I n
+is a number.
+To enter a repeat count, type the escape key, the number, and then
+the command to execute.
+For example, ``ESC\ 4\ ^f'' moves forward four characters.
+If a command may be given a repeat count then the text ``[n]'' is given at the
+end of its description.
+.PP
+The following control characters are accepted:
+.RS
+.nf
+.ta \w'ESC DEL 'u
+^A Move to the beginning of the line
+^B Move left (backwards) [n]
+^D Delete character [n]
+^E Move to end of line
+^F Move right (forwards) [n]
+^G Ring the bell
+^H Delete character before cursor (backspace key) [n]
+^I Complete filename (tab key); see below
+^J Done with line (return key)
+^K Kill to end of line (or column [n])
+^L Redisplay line
+^M Done with line (alternate return key)
+^N Get next line from history [n]
+^P Get previous line from history [n]
+^R Search backward (forward if [n]) through history for text;
+\& must start line if text begins with an uparrow
+^T Transpose characters
+^V Insert next character, even if it is an edit command
+^W Wipe to the mark
+^X^X Exchange current location and mark
+^Y Yank back last killed text
+^[ Start an escape sequence (escape key)
+^]c Move forward to next character ``c''
+^? Delete character before cursor (delete key) [n]
+.fi
+.RE
+.PP
+The following escape sequences are provided.
+.RS
+.nf
+.ta \w'ESC DEL 'u
+ESC\ ^H Delete previous word (backspace key) [n]
+ESC\ DEL Delete previous word (delete key) [n]
+ESC\ SP Set the mark (space key); see ^X^X and ^Y above
+ESC\ \. Get the last (or [n]'th) word from previous line
+ESC\ \? Show possible completions; see below
+ESC\ < Move to start of history
+ESC\ > Move to end of history
+ESC\ b Move backward a word [n]
+ESC\ d Delete word under cursor [n]
+ESC\ f Move forward a word [n]
+ESC\ l Make word lowercase [n]
+ESC\ m Toggle if 8bit chars display normally or with ``M\-'' prefix
+ESC\ u Make word uppercase [n]
+ESC\ y Yank back last killed text
+ESC\ v Show library version
+ESC\ w Make area up to mark yankable
+ESC\ nn Set repeat count to the number nn
+ESC\ C Read from environment variable ``_C_'', where C is
+\& an uppercase letter
+.fi
+.RE
+.PP
+The
+.I editline
+library has a small macro facility.
+If you type the escape key followed by an uppercase letter,
+.IR C ,
+then the contents of the environment variable
+.I _C_
+are read in as if you had typed them at the keyboard.
+For example, if the variable
+.I _L_
+contains the following:
+.RS
+^A^Kecho '^V^[[H^V^[[2J'^M
+.RE
+Then typing ``ESC L'' will move to the beginning of the line, kill the
+entire line, enter the echo command needed to clear the terminal (if your
+terminal is like a VT-100), and send the line back to the shell.
+.PP
+The
+.I editline
+library also does filename completion.
+Suppose the root directory has the following files in it:
+.RS
+.nf
+.ta \w'core 'u
+bin vmunix
+core vmunix.old
+.fi
+.RE
+If you type ``rm\ /v'' and then the tab key.
+.I Editline
+will then finish off as much of the name as possible by adding ``munix''.
+Because the name is not unique, it will then beep.
+If you type the escape key and a question mark, it will display the
+two choices.
+If you then type a period and a tab, the library will finish off the filename
+for you:
+.RS
+.nf
+.RI "rm /v[TAB]" munix .TAB old
+.fi
+.RE
+The tab key is shown by ``[TAB]'' and the automatically-entered text
+is shown in italics.
+.SH "BUGS AND LIMITATIONS"
+Cannot handle lines more than 80 columns.
+.SH AUTHORS
+Simmule R. Turner <uunet.uu.net!capitol!sysgo!simmy>
+and Rich $alz <rsalz@osf.org>.
+Original manual page by DaviD W. Sanderson <dws@ssec.wisc.edu>.
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.c b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.c
new file mode 100644
index 0000000..8ca93b3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.c
@@ -0,0 +1,1368 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Simmule Turner and Rich Salz.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+ *
+ * This software is not subject to any license of the American Telephone
+ * and Telegraph Company or of the Regents of the University of California.
+ *
+ * Permission is granted to anyone to use this software for any purpose on
+ * any computer system, and to alter it and redistribute it freely, subject
+ * to the following restrictions:
+ * 1. The authors are not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits must appear in the documentation.
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits must appear in the documentation.
+ * 4. This notice may not be removed or altered.
+ */
+
+
+/*
+** Main editing routines for editline library.
+*/
+#include "editline.h"
+#include <signal.h>
+#include <ctype.h>
+#include <unistd.h>
+
+/*
+** Manifest constants.
+*/
+#define SCREEN_WIDTH 80
+#define SCREEN_ROWS 24
+#define NO_ARG (-1)
+#define DEL 127
+#define CTL(x) ((x) & 0x1F)
+#define ISCTL(x) ((x) && (x) < ' ')
+#define UNCTL(x) ((x) + 64)
+#define META(x) ((x) | 0x80)
+#define ISMETA(x) ((x) & 0x80)
+#define UNMETA(x) ((x) & 0x7F)
+#if !defined(HIST_SIZE)
+#define HIST_SIZE 20
+#endif /* !defined(HIST_SIZE) */
+
+/*
+** Command status codes.
+*/
+typedef enum _STATUS {
+ CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal
+} STATUS;
+
+/*
+** The type of case-changing to perform.
+*/
+typedef enum _CASE {
+ TOupper, TOlower
+} CASE;
+
+/*
+** Key to command mapping.
+*/
+typedef struct _KEYMAP {
+ CHAR Key;
+ STATUS (*Function)();
+} KEYMAP;
+
+/*
+** Command history structure.
+*/
+typedef struct _HISTORY {
+ int Size;
+ int Pos;
+ CHAR *Lines[HIST_SIZE];
+} HISTORY;
+
+/*
+** Globals.
+*/
+int rl_eof;
+int rl_erase;
+int rl_intr;
+int rl_kill;
+int rl_quit;
+
+STATIC CHAR NIL[] = "";
+STATIC CONST CHAR *Input = NIL;
+STATIC CHAR *Line;
+STATIC CONST char *Prompt;
+STATIC CHAR *Yanked;
+STATIC char *Screen;
+STATIC char NEWLINE[]= CRLF;
+STATIC HISTORY H;
+STATIC int Repeat;
+STATIC int End;
+STATIC int Mark;
+STATIC int OldPoint;
+STATIC int Point;
+STATIC int PushBack;
+STATIC int Pushed;
+STATIC int Signal;
+FORWARD KEYMAP Map[32];
+FORWARD KEYMAP MetaMap[16];
+STATIC SIZE_T Length;
+STATIC SIZE_T ScreenCount;
+STATIC SIZE_T ScreenSize;
+STATIC char *backspace;
+STATIC int TTYwidth;
+STATIC int TTYrows;
+
+/* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
+int rl_meta_chars = 0;
+
+/*
+** Declarations.
+*/
+STATIC CHAR *editinput();
+#if defined(USE_TERMCAP)
+#include <stdlib.h>
+#include <curses.h>
+#include <term.h>
+#endif /* defined(USE_TERMCAP) */
+
+/*
+** TTY input/output functions.
+*/
+
+STATIC void
+TTYflush()
+{
+ if (ScreenCount) {
+ (void)write(1, Screen, ScreenCount);
+ ScreenCount = 0;
+ }
+}
+
+STATIC void
+TTYput(c)
+ CHAR c;
+{
+ Screen[ScreenCount] = c;
+ if (++ScreenCount >= ScreenSize - 1) {
+ ScreenSize += SCREEN_INC;
+ RENEW(Screen, char, ScreenSize);
+ }
+}
+
+STATIC void
+TTYputs(p)
+ CHAR *p;
+{
+ while (*p)
+ TTYput(*p++);
+}
+
+STATIC void
+TTYshow(c)
+ CHAR c;
+{
+ if (c == DEL) {
+ TTYput('^');
+ TTYput('?');
+ }
+ else if (ISCTL(c)) {
+ TTYput('^');
+ TTYput(UNCTL(c));
+ }
+ else if (rl_meta_chars && ISMETA(c)) {
+ TTYput('M');
+ TTYput('-');
+ TTYput(UNMETA(c));
+ }
+ else
+ TTYput(c);
+}
+
+STATIC void
+TTYstring(p)
+ CHAR *p;
+{
+ while (*p)
+ TTYshow(*p++);
+}
+
+STATIC unsigned int
+TTYget()
+{
+ CHAR c;
+
+ TTYflush();
+ if (Pushed) {
+ Pushed = 0;
+ return PushBack;
+ }
+ if (*Input)
+ return *Input++;
+ return read(0, &c, (SIZE_T)1) == 1 ? c : EOF;
+}
+
+#define TTYback() (backspace ? TTYputs((CHAR *)backspace) : TTYput('\b'))
+
+STATIC void
+TTYbackn(n)
+ int n;
+{
+ while (--n >= 0)
+ TTYback();
+}
+
+STATIC void
+TTYinfo()
+{
+ static int init;
+#if defined(USE_TERMCAP)
+ char *term;
+ char buff[2048];
+ char *bp, *p;
+#endif /* defined(USE_TERMCAP) */
+#if defined(TIOCGWINSZ)
+ struct winsize W;
+#endif /* defined(TIOCGWINSZ) */
+
+ if (init) {
+#if defined(TIOCGWINSZ)
+ /* Perhaps we got resized. */
+ if (ioctl(0, TIOCGWINSZ, &W) >= 0
+ && W.ws_col > 0 && W.ws_row > 0) {
+ TTYwidth = (int)W.ws_col;
+ TTYrows = (int)W.ws_row;
+ }
+#endif /* defined(TIOCGWINSZ) */
+ return;
+ }
+ init++;
+
+ TTYwidth = TTYrows = 0;
+#if defined(USE_TERMCAP)
+ bp = &buff[0];
+ if ((term = getenv("TERM")) == NULL)
+ term = "dumb";
+ if (tgetent(buff, term) < 0) {
+ TTYwidth = SCREEN_WIDTH;
+ TTYrows = SCREEN_ROWS;
+ return;
+ }
+ p = tgetstr("le", &bp);
+ backspace = p ? strdup(p) : NULL;
+ TTYwidth = tgetnum("co");
+ TTYrows = tgetnum("li");
+#endif /* defined(USE_TERMCAP) */
+
+#if defined(TIOCGWINSZ)
+ if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
+ TTYwidth = (int)W.ws_col;
+ TTYrows = (int)W.ws_row;
+ }
+#endif /* defined(TIOCGWINSZ) */
+
+ if (TTYwidth <= 0 || TTYrows <= 0) {
+ TTYwidth = SCREEN_WIDTH;
+ TTYrows = SCREEN_ROWS;
+ }
+}
+
+
+STATIC void
+reposition()
+{
+ int i;
+ CHAR *p;
+
+ TTYput('\r');
+ TTYputs((CONST CHAR *)Prompt);
+ for (i = Point, p = Line; --i >= 0; p++)
+ TTYshow(*p);
+}
+
+STATIC void
+left(Change)
+ STATUS Change;
+{
+ TTYback();
+ if (Point) {
+ if (ISCTL(Line[Point - 1]))
+ TTYback();
+ else if (rl_meta_chars && ISMETA(Line[Point - 1])) {
+ TTYback();
+ TTYback();
+ }
+ }
+ if (Change == CSmove)
+ Point--;
+}
+
+STATIC void
+right(Change)
+ STATUS Change;
+{
+ TTYshow(Line[Point]);
+ if (Change == CSmove)
+ Point++;
+}
+
+STATIC STATUS
+ring_bell()
+{
+ TTYput('\07');
+ TTYflush();
+ return CSstay;
+}
+
+STATIC STATUS
+do_macro(c)
+ unsigned int c;
+{
+ CHAR name[4];
+
+ name[0] = '_';
+ name[1] = c;
+ name[2] = '_';
+ name[3] = '\0';
+
+ if ((Input = (CHAR *)getenv((char *)name)) == NULL) {
+ Input = NIL;
+ return ring_bell();
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+do_forward(move)
+ STATUS move;
+{
+ int i;
+ CHAR *p;
+
+ i = 0;
+ do {
+ p = &Line[Point];
+ for ( ; Point < End && (*p == ' ' || !isalnum(*p)); Point++, p++)
+ if (move == CSmove)
+ right(CSstay);
+
+ for (; Point < End && isalnum(*p); Point++, p++)
+ if (move == CSmove)
+ right(CSstay);
+
+ if (Point == End)
+ break;
+ } while (++i < Repeat);
+
+ return CSstay;
+}
+
+STATIC STATUS
+do_case(type)
+ CASE type;
+{
+ int i;
+ int end;
+ int count;
+ CHAR *p;
+
+ (void)do_forward(CSstay);
+ if (OldPoint != Point) {
+ if ((count = Point - OldPoint) < 0)
+ count = -count;
+ Point = OldPoint;
+ if ((end = Point + count) > End)
+ end = End;
+ for (i = Point, p = &Line[i]; i < end; i++, p++) {
+ if (type == TOupper) {
+ if (islower(*p))
+ *p = toupper(*p);
+ }
+ else if (isupper(*p))
+ *p = tolower(*p);
+ right(CSmove);
+ }
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+case_down_word()
+{
+ return do_case(TOlower);
+}
+
+STATIC STATUS
+case_up_word()
+{
+ return do_case(TOupper);
+}
+
+STATIC void
+ceol()
+{
+ int extras;
+ int i;
+ CHAR *p;
+
+ for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
+ TTYput(' ');
+ if (ISCTL(*p)) {
+ TTYput(' ');
+ extras++;
+ }
+ else if (rl_meta_chars && ISMETA(*p)) {
+ TTYput(' ');
+ TTYput(' ');
+ extras += 2;
+ }
+ }
+
+ for (i += extras; i > Point; i--)
+ TTYback();
+}
+
+STATIC void
+clear_line()
+{
+ Point = -strlen(Prompt);
+ TTYput('\r');
+ ceol();
+ Point = 0;
+ End = 0;
+ Line[0] = '\0';
+}
+
+STATIC STATUS
+insert_string(p)
+ CHAR *p;
+{
+ SIZE_T len;
+ int i;
+ CHAR *new;
+ CHAR *q;
+
+ len = strlen((char *)p);
+ if (End + len >= Length) {
+ if ((new = NEW(CHAR, Length + len + MEM_INC)) == NULL)
+ return CSstay;
+ if (Length) {
+ COPYFROMTO(new, Line, Length);
+ DISPOSE(Line);
+ }
+ Line = new;
+ Length += len + MEM_INC;
+ }
+
+ for (q = &Line[Point], i = End - Point; --i >= 0; )
+ q[len + i] = q[i];
+ COPYFROMTO(&Line[Point], p, len);
+ End += len;
+ Line[End] = '\0';
+ TTYstring(&Line[Point]);
+ Point += len;
+
+ return Point == End ? CSstay : CSmove;
+}
+
+STATIC STATUS
+redisplay()
+{
+ TTYputs((CONST CHAR *)NEWLINE);
+ TTYputs((CONST CHAR *)Prompt);
+ TTYstring(Line);
+ return CSmove;
+}
+
+STATIC STATUS
+toggle_meta_mode()
+{
+ rl_meta_chars = ! rl_meta_chars;
+ return redisplay();
+}
+
+
+STATIC CHAR *
+next_hist()
+{
+ return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
+}
+
+STATIC CHAR *
+prev_hist()
+{
+ return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
+}
+
+STATIC STATUS
+do_insert_hist(p)
+ CHAR *p;
+{
+ if (p == NULL)
+ return ring_bell();
+ Point = 0;
+ reposition();
+ ceol();
+ End = 0;
+ return insert_string(p);
+}
+
+STATIC STATUS
+do_hist(move)
+ CHAR *(*move)();
+{
+ CHAR *p;
+ int i;
+
+ i = 0;
+ do {
+ if ((p = (*move)()) == NULL)
+ return ring_bell();
+ } while (++i < Repeat);
+ return do_insert_hist(p);
+}
+
+STATIC STATUS
+h_next()
+{
+ return do_hist(next_hist);
+}
+
+STATIC STATUS
+h_prev()
+{
+ return do_hist(prev_hist);
+}
+
+STATIC STATUS
+h_first()
+{
+ return do_insert_hist(H.Lines[H.Pos = 0]);
+}
+
+STATIC STATUS
+h_last()
+{
+ return do_insert_hist(H.Lines[H.Pos = H.Size - 1]);
+}
+
+/*
+** Return zero if pat appears as a substring in text.
+*/
+STATIC int
+substrcmp(text, pat, len)
+ char *text;
+ char *pat;
+ int len;
+{
+ char c;
+
+ if ((c = *pat) == '\0')
+ return *text == '\0';
+ for ( ; *text; text++)
+ if (*text == c && strncmp(text, pat, len) == 0)
+ return 0;
+ return 1;
+}
+
+STATIC CHAR *
+search_hist(search, move)
+ CHAR *search;
+ CHAR *(*move)();
+{
+ static CHAR *old_search;
+ int len;
+ int pos;
+ int (*match)();
+ char *pat;
+
+ /* Save or get remembered search pattern. */
+ if (search && *search) {
+ if (old_search)
+ DISPOSE(old_search);
+ old_search = (CHAR *)strdup((char *)search);
+ }
+ else {
+ if (old_search == NULL || *old_search == '\0')
+ return NULL;
+ search = old_search;
+ }
+
+ /* Set up pattern-finder. */
+ if (*search == '^') {
+ match = strncmp;
+ pat = (char *)(search + 1);
+ }
+ else {
+ match = substrcmp;
+ pat = (char *)search;
+ }
+ len = strlen(pat);
+
+ for (pos = H.Pos; (*move)() != NULL; )
+ if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0)
+ return H.Lines[H.Pos];
+ H.Pos = pos;
+ return NULL;
+}
+
+STATIC STATUS
+h_search()
+{
+ static int Searching;
+ CONST char *old_prompt;
+ CHAR *(*move)();
+ CHAR *p;
+
+ if (Searching)
+ return ring_bell();
+ Searching = 1;
+
+ clear_line();
+ old_prompt = Prompt;
+ Prompt = "Search: ";
+ TTYputs((CONST CHAR *)Prompt);
+ move = Repeat == NO_ARG ? prev_hist : next_hist;
+ p = editinput();
+ Prompt = old_prompt;
+ Searching = 0;
+ TTYputs((CONST CHAR *)Prompt);
+ if (p == NULL && Signal > 0) {
+ Signal = 0;
+ clear_line();
+ return redisplay();
+ }
+ p = search_hist(p, move);
+ clear_line();
+ if (p == NULL) {
+ (void)ring_bell();
+ return redisplay();
+ }
+ return do_insert_hist(p);
+}
+
+STATIC STATUS
+fd_char()
+{
+ int i;
+
+ i = 0;
+ do {
+ if (Point >= End)
+ break;
+ right(CSmove);
+ } while (++i < Repeat);
+ return CSstay;
+}
+
+STATIC void
+save_yank(begin, i)
+ int begin;
+ int i;
+{
+ if (Yanked) {
+ DISPOSE(Yanked);
+ Yanked = NULL;
+ }
+
+ if (i < 1)
+ return;
+
+ if ((Yanked = NEW(CHAR, (SIZE_T)i + 1)) != NULL) {
+ COPYFROMTO(Yanked, &Line[begin], i);
+ Yanked[i] = '\0';
+ }
+}
+
+STATIC STATUS
+delete_string(count)
+ int count;
+{
+ int i;
+ CHAR *p;
+
+ if (count <= 0 || End == Point)
+ return ring_bell();
+
+ if (count == 1 && Point == End - 1) {
+ /* Optimize common case of delete at end of line. */
+ End--;
+ p = &Line[Point];
+ i = 1;
+ TTYput(' ');
+ if (ISCTL(*p)) {
+ i = 2;
+ TTYput(' ');
+ }
+ else if (rl_meta_chars && ISMETA(*p)) {
+ i = 3;
+ TTYput(' ');
+ TTYput(' ');
+ }
+ TTYbackn(i);
+ *p = '\0';
+ return CSmove;
+ }
+ if (Point + count > End && (count = End - Point) <= 0)
+ return CSstay;
+
+ if (count > 1)
+ save_yank(Point, count);
+
+ for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++)
+ p[0] = p[count];
+ ceol();
+ End -= count;
+ TTYstring(&Line[Point]);
+ return CSmove;
+}
+
+STATIC STATUS
+bk_char()
+{
+ int i;
+
+ i = 0;
+ do {
+ if (Point == 0)
+ break;
+ left(CSmove);
+ } while (++i < Repeat);
+
+ return CSstay;
+}
+
+STATIC STATUS
+bk_del_char()
+{
+ int i;
+
+ i = 0;
+ do {
+ if (Point == 0)
+ break;
+ left(CSmove);
+ } while (++i < Repeat);
+
+ return delete_string(i);
+}
+
+STATIC STATUS
+kill_line()
+{
+ int i;
+
+ if (Repeat != NO_ARG) {
+ if (Repeat < Point) {
+ i = Point;
+ Point = Repeat;
+ reposition();
+ (void)delete_string(i - Point);
+ }
+ else if (Repeat > Point) {
+ right(CSmove);
+ (void)delete_string(Repeat - Point - 1);
+ }
+ return CSmove;
+ }
+
+ save_yank(Point, End - Point);
+ Line[Point] = '\0';
+ ceol();
+ End = Point;
+ return CSstay;
+}
+
+STATIC STATUS
+insert_char(c)
+ int c;
+{
+ STATUS s;
+ CHAR buff[2];
+ CHAR *p;
+ CHAR *q;
+ int i;
+
+ if (Repeat == NO_ARG || Repeat < 2) {
+ buff[0] = c;
+ buff[1] = '\0';
+ return insert_string(buff);
+ }
+
+ if ((p = NEW(CHAR, Repeat + 1)) == NULL)
+ return CSstay;
+ for (i = Repeat, q = p; --i >= 0; )
+ *q++ = c;
+ *q = '\0';
+ Repeat = 0;
+ s = insert_string(p);
+ DISPOSE(p);
+ return s;
+}
+
+STATIC STATUS
+meta()
+{
+ unsigned int c;
+ KEYMAP *kp;
+
+ if ((c = TTYget()) == EOF)
+ return CSeof;
+#if defined(ANSI_ARROWS)
+ /* Also include VT-100 arrows. */
+ if (c == '[' || c == 'O')
+ switch (c = TTYget()) {
+ default: return ring_bell();
+ case EOF: return CSeof;
+ case 'A': return h_prev();
+ case 'B': return h_next();
+ case 'C': return fd_char();
+ case 'D': return bk_char();
+ }
+#endif /* defined(ANSI_ARROWS) */
+
+ if (isdigit(c)) {
+ for (Repeat = c - '0'; (c = TTYget()) != EOF && isdigit(c); )
+ Repeat = Repeat * 10 + c - '0';
+ Pushed = 1;
+ PushBack = c;
+ return CSstay;
+ }
+
+ if (isupper(c))
+ return do_macro(c);
+ for (OldPoint = Point, kp = MetaMap; kp->Function; kp++)
+ if (kp->Key == c)
+ return (*kp->Function)();
+
+ return ring_bell();
+}
+
+STATIC STATUS
+emacs(c)
+ unsigned int c;
+{
+ STATUS s;
+ KEYMAP *kp;
+
+ if (rl_meta_chars && ISMETA(c)) {
+ Pushed = 1;
+ PushBack = UNMETA(c);
+ return meta();
+ }
+ for (kp = Map; kp->Function; kp++)
+ if (kp->Key == c)
+ break;
+ s = kp->Function ? (*kp->Function)() : insert_char((int)c);
+ if (!Pushed)
+ /* No pushback means no repeat count; hacky, but true. */
+ Repeat = NO_ARG;
+ return s;
+}
+
+STATIC STATUS
+TTYspecial(c)
+ unsigned int c;
+{
+ if (ISMETA(c))
+ return CSdispatch;
+
+ if (c == rl_erase || c == DEL)
+ return bk_del_char();
+ if (c == rl_kill) {
+ if (Point != 0) {
+ Point = 0;
+ reposition();
+ }
+ Repeat = NO_ARG;
+ return kill_line();
+ }
+ if (c == rl_eof && Point == 0 && End == 0)
+ return CSeof;
+ if (c == rl_intr) {
+ Signal = SIGINT;
+ return CSsignal;
+ }
+ if (c == rl_quit) {
+ Signal = SIGQUIT;
+ return CSeof;
+ }
+
+ return CSdispatch;
+}
+
+STATIC CHAR *
+editinput()
+{
+ unsigned int c;
+
+ Repeat = NO_ARG;
+ OldPoint = Point = Mark = End = 0;
+ Line[0] = '\0';
+
+ Signal = -1;
+ while ((c = TTYget()) != EOF)
+ switch (TTYspecial(c)) {
+ case CSdone:
+ return Line;
+ case CSeof:
+ return NULL;
+ case CSsignal:
+ return (CHAR *)"";
+ case CSmove:
+ reposition();
+ break;
+ case CSdispatch:
+ switch (emacs(c)) {
+ case CSdone:
+ return Line;
+ case CSeof:
+ return NULL;
+ case CSsignal:
+ return (CHAR *)"";
+ case CSmove:
+ reposition();
+ break;
+ case CSdispatch:
+ case CSstay:
+ break;
+ }
+ break;
+ case CSstay:
+ break;
+ }
+ return NULL;
+}
+
+STATIC void
+hist_add(p)
+ CHAR *p;
+{
+ int i;
+
+ if ((p = (CHAR *)strdup((char *)p)) == NULL)
+ return;
+ if (H.Size < HIST_SIZE)
+ H.Lines[H.Size++] = p;
+ else {
+ DISPOSE(H.Lines[0]);
+ for (i = 0; i < HIST_SIZE - 1; i++)
+ H.Lines[i] = H.Lines[i + 1];
+ H.Lines[i] = p;
+ }
+ H.Pos = H.Size - 1;
+}
+
+/*
+** For compatibility with FSF readline.
+*/
+/* ARGSUSED0 */
+void
+rl_reset_terminal(p)
+ char *p;
+{
+}
+
+void
+rl_initialize()
+{
+}
+
+char *
+readline(prompt)
+ CONST char *prompt;
+{
+ CHAR *line;
+ int s;
+
+ if (Line == NULL) {
+ Length = MEM_INC;
+ if ((Line = NEW(CHAR, Length)) == NULL)
+ return NULL;
+ }
+
+ TTYinfo();
+ rl_ttyset(0);
+ hist_add(NIL);
+ ScreenSize = SCREEN_INC;
+ Screen = NEW(char, ScreenSize);
+ Prompt = prompt ? prompt : (char *)NIL;
+ TTYputs((CONST CHAR *)Prompt);
+ if ((line = editinput()) != NULL) {
+ line = (CHAR *)strdup((char *)line);
+ TTYputs((CHAR *)NEWLINE);
+ TTYflush();
+ }
+ rl_ttyset(1);
+ DISPOSE(Screen);
+ DISPOSE(H.Lines[--H.Size]);
+ if (Signal > 0) {
+ s = Signal;
+ Signal = 0;
+ (void)kill(getpid(), s);
+ }
+ return (char *)line;
+}
+
+void
+add_history(p)
+ char *p;
+{
+ if (p == NULL || *p == '\0')
+ return;
+
+#if defined(UNIQUE_HISTORY)
+ if (H.Size && strcmp(p, H.Lines[H.Size - 1]) == 0)
+ return;
+#endif /* defined(UNIQUE_HISTORY) */
+ hist_add((CHAR *)p);
+}
+
+
+STATIC STATUS
+beg_line()
+{
+ if (Point) {
+ Point = 0;
+ return CSmove;
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+del_char()
+{
+ return delete_string(Repeat == NO_ARG ? 1 : Repeat);
+}
+
+STATIC STATUS
+end_line()
+{
+ if (Point != End) {
+ Point = End;
+ return CSmove;
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+accept_line()
+{
+ Line[End] = '\0';
+ return CSdone;
+}
+
+STATIC STATUS
+transpose()
+{
+ CHAR c;
+
+ if (Point) {
+ if (Point == End)
+ left(CSmove);
+ c = Line[Point - 1];
+ left(CSstay);
+ Line[Point - 1] = Line[Point];
+ TTYshow(Line[Point - 1]);
+ Line[Point++] = c;
+ TTYshow(c);
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+quote()
+{
+ unsigned int c;
+
+ return (c = TTYget()) == EOF ? CSeof : insert_char((int)c);
+}
+
+STATIC STATUS
+wipe()
+{
+ int i;
+
+ if (Mark > End)
+ return ring_bell();
+
+ if (Point > Mark) {
+ i = Point;
+ Point = Mark;
+ Mark = i;
+ reposition();
+ }
+
+ return delete_string(Mark - Point);
+}
+
+STATIC STATUS
+mk_set()
+{
+ Mark = Point;
+ return CSstay;
+}
+
+STATIC STATUS
+exchange()
+{
+ unsigned int c;
+
+ if ((c = TTYget()) != CTL('X'))
+ return c == EOF ? CSeof : ring_bell();
+
+ if ((c = Mark) <= End) {
+ Mark = Point;
+ Point = c;
+ return CSmove;
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+yank()
+{
+ if (Yanked && *Yanked)
+ return insert_string(Yanked);
+ return CSstay;
+}
+
+STATIC STATUS
+copy_region()
+{
+ if (Mark > End)
+ return ring_bell();
+
+ if (Point > Mark)
+ save_yank(Mark, Point - Mark);
+ else
+ save_yank(Point, Mark - Point);
+
+ return CSstay;
+}
+
+STATIC STATUS
+move_to_char()
+{
+ unsigned int c;
+ int i;
+ CHAR *p;
+
+ if ((c = TTYget()) == EOF)
+ return CSeof;
+ for (i = Point + 1, p = &Line[i]; i < End; i++, p++)
+ if (*p == c) {
+ Point = i;
+ return CSmove;
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+fd_word()
+{
+ return do_forward(CSmove);
+}
+
+STATIC STATUS
+fd_kill_word()
+{
+ int i;
+
+ (void)do_forward(CSstay);
+ if (OldPoint != Point) {
+ i = Point - OldPoint;
+ Point = OldPoint;
+ return delete_string(i);
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+bk_word()
+{
+ int i;
+ CHAR *p;
+
+ i = 0;
+ do {
+ for (p = &Line[Point]; p > Line && !isalnum(p[-1]); p--)
+ left(CSmove);
+
+ for (; p > Line && p[-1] != ' ' && isalnum(p[-1]); p--)
+ left(CSmove);
+
+ if (Point == 0)
+ break;
+ } while (++i < Repeat);
+
+ return CSstay;
+}
+
+STATIC STATUS
+bk_kill_word()
+{
+ (void)bk_word();
+ if (OldPoint != Point)
+ return delete_string(OldPoint - Point);
+ return CSstay;
+}
+
+STATIC int
+argify(line, avp)
+ CHAR *line;
+ CHAR ***avp;
+{
+ CHAR *c;
+ CHAR **p;
+ CHAR **new;
+ int ac;
+ int i;
+
+ i = MEM_INC;
+ if ((*avp = p = NEW(CHAR*, i))== NULL)
+ return 0;
+
+ for (c = line; isspace(*c); c++)
+ continue;
+ if (*c == '\n' || *c == '\0')
+ return 0;
+
+ for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
+ if (isspace(*c)) {
+ *c++ = '\0';
+ if (*c && *c != '\n') {
+ if (ac + 1 == i) {
+ new = NEW(CHAR*, i + MEM_INC);
+ if (new == NULL) {
+ p[ac] = NULL;
+ return ac;
+ }
+ COPYFROMTO(new, p, i * sizeof (char **));
+ i += MEM_INC;
+ DISPOSE(p);
+ *avp = p = new;
+ }
+ p[ac++] = c;
+ }
+ }
+ else
+ c++;
+ }
+ *c = '\0';
+ p[ac] = NULL;
+ return ac;
+}
+
+STATIC STATUS
+last_argument()
+{
+ CHAR **av;
+ CHAR *p;
+ STATUS s;
+ int ac;
+
+ if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL)
+ return ring_bell();
+
+ if ((p = (CHAR *)strdup((char *)p)) == NULL)
+ return CSstay;
+ ac = argify(p, &av);
+
+ if (Repeat != NO_ARG)
+ s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell();
+ else
+ s = ac ? insert_string(av[ac - 1]) : CSstay;
+
+ if (ac)
+ DISPOSE(av);
+ DISPOSE(p);
+ return s;
+}
+
+STATIC KEYMAP Map[32] = {
+ { CTL('@'), ring_bell },
+ { CTL('A'), beg_line },
+ { CTL('B'), bk_char },
+ { CTL('D'), del_char },
+ { CTL('E'), end_line },
+ { CTL('F'), fd_char },
+ { CTL('G'), ring_bell },
+ { CTL('H'), bk_del_char },
+ { CTL('J'), accept_line },
+ { CTL('K'), kill_line },
+ { CTL('L'), redisplay },
+ { CTL('M'), accept_line },
+ { CTL('N'), h_next },
+ { CTL('O'), ring_bell },
+ { CTL('P'), h_prev },
+ { CTL('Q'), ring_bell },
+ { CTL('R'), h_search },
+ { CTL('S'), ring_bell },
+ { CTL('T'), transpose },
+ { CTL('U'), ring_bell },
+ { CTL('V'), quote },
+ { CTL('W'), wipe },
+ { CTL('X'), exchange },
+ { CTL('Y'), yank },
+ { CTL('Z'), ring_bell },
+ { CTL('['), meta },
+ { CTL(']'), move_to_char },
+ { CTL('^'), ring_bell },
+ { CTL('_'), ring_bell },
+ { 0, NULL }
+};
+
+STATIC KEYMAP MetaMap[16]= {
+ { CTL('H'), bk_kill_word },
+ { DEL, bk_kill_word },
+ { ' ', mk_set },
+ { '.', last_argument },
+ { '<', h_first },
+ { '>', h_last },
+ { 'b', bk_word },
+ { 'd', fd_kill_word },
+ { 'f', fd_word },
+ { 'l', case_down_word },
+ { 'm', toggle_meta_mode },
+ { 'u', case_up_word },
+ { 'y', yank },
+ { 'w', copy_region },
+ { 0, NULL }
+};
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.h b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.h
new file mode 100644
index 0000000..e820049
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.h
@@ -0,0 +1,135 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Simmule Turner and Rich Salz.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+ *
+ * This software is not subject to any license of the American Telephone
+ * and Telegraph Company or of the Regents of the University of California.
+ *
+ * Permission is granted to anyone to use this software for any purpose on
+ * any computer system, and to alter it and redistribute it freely, subject
+ * to the following restrictions:
+ * 1. The authors are not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits must appear in the documentation.
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits must appear in the documentation.
+ * 4. This notice may not be removed or altered.
+ */
+
+/*
+** Internal header file for editline library.
+*/
+#include <stdio.h>
+#if defined(HAVE_STDLIB)
+#include <stdlib.h>
+#include <string.h>
+#endif /* defined(HAVE_STDLIB) */
+#if defined(SYS_UNIX)
+#include "unix.h"
+#endif /* defined(SYS_UNIX) */
+#if defined(SYS_OS9)
+#include "os9.h"
+#endif /* defined(SYS_OS9) */
+
+#if !defined(SIZE_T)
+#define SIZE_T unsigned int
+#endif /* !defined(SIZE_T) */
+
+typedef unsigned char CHAR;
+
+#if defined(HIDE)
+#define STATIC static
+#else
+#define STATIC /* NULL */
+#endif /* !defined(HIDE) */
+
+#if !defined(CONST)
+#if defined(__STDC__)
+#define CONST const
+#else
+#define CONST
+#endif /* defined(__STDC__) */
+#endif /* !defined(CONST) */
+
+
+#define MEM_INC 64
+#define SCREEN_INC 256
+
+#define DISPOSE(p) free((char *)(p))
+#define NEW(T, c) \
+ ((T *)malloc((unsigned int)(sizeof (T) * (c))))
+#define RENEW(p, T, c) \
+ (p = (T *)realloc((char *)(p), (unsigned int)(sizeof (T) * (c))))
+#define COPYFROMTO(new, p, len) \
+ (void)memcpy((char *)(new), (char *)(p), (int)(len))
+
+
+/*
+** Variables and routines internal to this package.
+*/
+extern int rl_eof;
+extern int rl_erase;
+extern int rl_intr;
+extern int rl_kill;
+extern int rl_quit;
+extern char *rl_complete();
+extern int rl_list_possib();
+extern void rl_ttyset();
+extern void rl_add_slash();
+
+#if !defined(HAVE_STDLIB)
+extern char *getenv();
+extern char *malloc();
+extern char *realloc();
+extern char *memcpy();
+extern char *strcat();
+extern char *strchr();
+extern char *strrchr();
+extern char *strcpy();
+extern char *strdup();
+extern int strcmp();
+extern int strlen();
+extern int strncmp();
+#endif /* !defined(HAVE_STDLIB) */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/sysunix.c b/tools/node_modules/expresso/deps/jscoverage/js/editline/sysunix.c
new file mode 100644
index 0000000..17227ea
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/sysunix.c
@@ -0,0 +1,182 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Simmule Turner and Rich Salz.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+ *
+ * This software is not subject to any license of the American Telephone
+ * and Telegraph Company or of the Regents of the University of California.
+ *
+ * Permission is granted to anyone to use this software for any purpose on
+ * any computer system, and to alter it and redistribute it freely, subject
+ * to the following restrictions:
+ * 1. The authors are not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits must appear in the documentation.
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits must appear in the documentation.
+ * 4. This notice may not be removed or altered.
+ */
+
+
+/*
+** Unix system-dependant routines for editline library.
+*/
+#include "editline.h"
+
+#if defined(HAVE_TCGETATTR)
+#include <termios.h>
+
+void
+rl_ttyset(Reset)
+ int Reset;
+{
+ static struct termios old;
+ struct termios new;
+
+ if (Reset == 0) {
+ (void)tcgetattr(0, &old);
+ rl_erase = old.c_cc[VERASE];
+ rl_kill = old.c_cc[VKILL];
+ rl_eof = old.c_cc[VEOF];
+ rl_intr = old.c_cc[VINTR];
+ rl_quit = old.c_cc[VQUIT];
+
+ new = old;
+ new.c_cc[VINTR] = -1;
+ new.c_cc[VQUIT] = -1;
+ new.c_lflag &= ~(ECHO | ICANON);
+ new.c_iflag &= ~(ISTRIP | INPCK);
+ new.c_cc[VMIN] = 1;
+ new.c_cc[VTIME] = 0;
+ (void)tcsetattr(0, TCSADRAIN, &new);
+ }
+ else
+ (void)tcsetattr(0, TCSADRAIN, &old);
+}
+
+#else
+#if defined(HAVE_TERMIO)
+#include <termio.h>
+
+void
+rl_ttyset(Reset)
+ int Reset;
+{
+ static struct termio old;
+ struct termio new;
+
+ if (Reset == 0) {
+ (void)ioctl(0, TCGETA, &old);
+ rl_erase = old.c_cc[VERASE];
+ rl_kill = old.c_cc[VKILL];
+ rl_eof = old.c_cc[VEOF];
+ rl_intr = old.c_cc[VINTR];
+ rl_quit = old.c_cc[VQUIT];
+
+ new = old;
+ new.c_cc[VINTR] = -1;
+ new.c_cc[VQUIT] = -1;
+ new.c_lflag &= ~(ECHO | ICANON);
+ new.c_iflag &= ~(ISTRIP | INPCK);
+ new.c_cc[VMIN] = 1;
+ new.c_cc[VTIME] = 0;
+ (void)ioctl(0, TCSETAW, &new);
+ }
+ else
+ (void)ioctl(0, TCSETAW, &old);
+}
+
+#else
+#include <sgtty.h>
+
+void
+rl_ttyset(Reset)
+ int Reset;
+{
+ static struct sgttyb old_sgttyb;
+ static struct tchars old_tchars;
+ struct sgttyb new_sgttyb;
+ struct tchars new_tchars;
+
+ if (Reset == 0) {
+ (void)ioctl(0, TIOCGETP, &old_sgttyb);
+ rl_erase = old_sgttyb.sg_erase;
+ rl_kill = old_sgttyb.sg_kill;
+
+ (void)ioctl(0, TIOCGETC, &old_tchars);
+ rl_eof = old_tchars.t_eofc;
+ rl_intr = old_tchars.t_intrc;
+ rl_quit = old_tchars.t_quitc;
+
+ new_sgttyb = old_sgttyb;
+ new_sgttyb.sg_flags &= ~ECHO;
+ new_sgttyb.sg_flags |= RAW;
+#if defined(PASS8)
+ new_sgttyb.sg_flags |= PASS8;
+#endif /* defined(PASS8) */
+ (void)ioctl(0, TIOCSETP, &new_sgttyb);
+
+ new_tchars = old_tchars;
+ new_tchars.t_intrc = -1;
+ new_tchars.t_quitc = -1;
+ (void)ioctl(0, TIOCSETC, &new_tchars);
+ }
+ else {
+ (void)ioctl(0, TIOCSETP, &old_sgttyb);
+ (void)ioctl(0, TIOCSETC, &old_tchars);
+ }
+}
+#endif /* defined(HAVE_TERMIO) */
+#endif /* defined(HAVE_TCGETATTR) */
+
+void
+rl_add_slash(path, p)
+ char *path;
+ char *p;
+{
+ struct stat Sb;
+
+ if (stat(path, &Sb) >= 0)
+ (void)strcat(p, S_ISDIR(Sb.st_mode) ? "/" : " ");
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/unix.h b/tools/node_modules/expresso/deps/jscoverage/js/editline/unix.h
new file mode 100644
index 0000000..c99b729
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/unix.h
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Simmule Turner and Rich Salz.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+ *
+ * This software is not subject to any license of the American Telephone
+ * and Telegraph Company or of the Regents of the University of California.
+ *
+ * Permission is granted to anyone to use this software for any purpose on
+ * any computer system, and to alter it and redistribute it freely, subject
+ * to the following restrictions:
+ * 1. The authors are not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits must appear in the documentation.
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits must appear in the documentation.
+ * 4. This notice may not be removed or altered.
+ */
+
+
+/*
+** Editline system header file for Unix.
+*/
+
+#define CRLF "\r\n"
+#define FORWARD STATIC
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(USE_DIRENT)
+#include <dirent.h>
+typedef struct dirent DIRENTRY;
+#else
+#include <sys/dir.h>
+typedef struct direct DIRENTRY;
+#endif /* defined(USE_DIRENT) */
+
+#if !defined(S_ISDIR)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif /* !defined(S_ISDIR) */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/javascript-trace.d b/tools/node_modules/expresso/deps/jscoverage/js/javascript-trace.d
new file mode 100644
index 0000000..258c6cd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/javascript-trace.d
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Copyright (C) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * javascript provider probes
+ *
+ * function-entry (filename, classname, funcname)
+ * function-info (filename, classname, funcname, lineno,
+ * runfilename, runlineno)
+ * function-args (filename, classname, funcname, argc, argv, argv0,
+ * argv1, argv2, argv3, argv4)
+ * function-rval (filename, classname, funcname, lineno, rval, rval0)
+ * function-return (filename, classname, funcname)
+ * object-create-start (filename, classname)
+ * object-create (filename, classname, *object, rlineno)
+ * object-create-done (filename, classname)
+ * object-finalize (NULL, classname, *object)
+ * execute-start (filename, lineno)
+ * execute-done (filename, lineno)
+ */
+
+provider javascript {
+ probe function__entry(char *, char *, char *);
+ probe function__info(char *, char *, char *, int, char *, int);
+ probe function__args(char *, char *, char *, int, void *, void *, void *,
+ void *, void *, void *);
+ probe function__rval(char *, char *, char *, int, void *, void *);
+ probe function__return(char *, char *, char *);
+ probe object__create__start(char *, char *);
+ probe object__create__done(char *, char *);
+ /* XXX must use unsigned longs here instead of uintptr_t for OS X
+ (Apple radar: 5194316 & 5565198) */
+ probe object__create(char *, char *, unsigned long, int);
+ probe object__finalize(char *, char *, unsigned long);
+ probe execute__start(char *, int);
+ probe execute__done(char *, int);
+};
+
+/*
+#pragma D attributes Unstable/Unstable/Common provider mozilla provider
+#pragma D attributes Private/Private/Unknown provider mozilla module
+#pragma D attributes Private/Private/Unknown provider mozilla function
+#pragma D attributes Unstable/Unstable/Common provider mozilla name
+#pragma D attributes Unstable/Unstable/Common provider mozilla args
+*/
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jitstats.tbl b/tools/node_modules/expresso/deps/jscoverage/js/jitstats.tbl
new file mode 100644
index 0000000..047d390
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jitstats.tbl
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=0 ft=C:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * June 22, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Brian Crowder <crowder@fiverocks.com>
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+JITSTAT(recorderStarted)
+JITSTAT(recorderAborted)
+JITSTAT(traceCompleted)
+JITSTAT(sideExitIntoInterpreter)
+JITSTAT(typeMapMismatchAtEntry)
+JITSTAT(returnToDifferentLoopHeader)
+JITSTAT(traceTriggered)
+JITSTAT(globalShapeMismatchAtEntry)
+JITSTAT(treesTrashed)
+JITSTAT(slotPromoted)
+JITSTAT(unstableLoopVariable)
+JITSTAT(breakLoopExits)
+JITSTAT(returnLoopExits)
+JITSTAT(mergedLoopExits)
+JITSTAT(noCompatInnerTrees)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js-config.h.in b/tools/node_modules/expresso/deps/jscoverage/js/js-config.h.in
new file mode 100644
index 0000000..600253e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js-config.h.in
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef js_config_h___
+#define js_config_h___
+
+/* Definitions set at build time that affect SpiderMonkey's public API.
+ This header file is generated by the SpiderMonkey configure script,
+ and installed along with jsapi.h. */
+
+/* Define to 1 if SpiderMonkey should support multi-threaded clients. */
+#undef JS_THREADSAFE
+
+/* Define to 1 if SpiderMonkey should support the ability to perform
+ entirely too much GC. */
+#undef JS_GC_ZEAL
+
+#endif /* js_config_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js-config.in b/tools/node_modules/expresso/deps/jscoverage/js/js-config.in
new file mode 100644
index 0000000..59b4719
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js-config.in
@@ -0,0 +1,111 @@
+#!/bin/sh
+
+prefix='@prefix@'
+mozilla_version='@MOZILLA_VERSION@'
+LIBRARY_NAME='@LIBRARY_NAME@'
+NSPR_CFLAGS='@NSPR_CFLAGS@'
+JS_CONFIG_LIBS='@JS_CONFIG_LIBS@'
+MOZ_JS_LIBS='@MOZ_JS_LIBS@'
+
+usage()
+{
+ cat <<EOF
+Usage: js-config [OPTIONS]
+Options:
+ [--prefix[=DIR]]
+ [--exec-prefix[=DIR]]
+ [--includedir[=DIR]]
+ [--libdir[=DIR]]
+ [--version]
+ [--libs]
+ [--cflags]
+ [--lib-filenames]
+EOF
+ exit $1
+}
+
+if test $# -eq 0; then
+ usage 1 1>&2
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case $1 in
+ --prefix=*)
+ prefix=$optarg
+ ;;
+ --prefix)
+ echo_prefix=yes
+ ;;
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ ;;
+ --exec-prefix)
+ echo_exec_prefix=yes
+ ;;
+ --includedir=*)
+ includedir=$optarg
+ ;;
+ --includedir)
+ echo_includedir=yes
+ ;;
+ --libdir=*)
+ libdir=$optarg
+ ;;
+ --libdir)
+ echo_libdir=yes
+ ;;
+ --version)
+ echo "$mozilla_version"
+ ;;
+ --cflags)
+ echo_cflags=yes
+ ;;
+ --libs)
+ echo_libs=yes
+ ;;
+ *)
+ usage 1 1>&2
+ ;;
+ esac
+ shift
+done
+
+# Set variables that may be dependent upon other variables
+if test -z "$exec_prefix"; then
+ exec_prefix=@exec_prefix@
+fi
+if test -z "$includedir"; then
+ includedir=@includedir@
+fi
+if test -z "$libdir"; then
+ libdir=@libdir@
+fi
+
+if test "$echo_prefix" = "yes"; then
+ echo $prefix
+fi
+
+if test "$echo_exec_prefix" = "yes"; then
+ echo $exec_prefix
+fi
+
+if test "$echo_includedir" = "yes"; then
+ echo $includedir
+fi
+
+if test "$echo_libdir" = "yes"; then
+ echo $libdir
+fi
+
+if test "$echo_cflags" = "yes"; then
+ echo "-I$includedir/js $NSPR_CFLAGS"
+fi
+
+if test "$echo_libs" = "yes"; then
+ echo "$MOZ_JS_LIBS $JS_CONFIG_LIBS"
+fi
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js.cpp b/tools/node_modules/expresso/deps/jscoverage/js/js.cpp
new file mode 100644
index 0000000..9ffc847
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js.cpp
@@ -0,0 +1,4050 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS shell.
+ */
+#include "jsstddef.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include "jstypes.h"
+#include "jsarena.h"
+#include "jsutil.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsparse.h"
+#include "jsscope.h"
+#include "jsscript.h"
+
+#ifdef LIVECONNECT
+#include "jsjava.h"
+#endif
+
+#ifdef JSDEBUGGER
+#include "jsdebug.h"
+#ifdef JSDEBUGGER_JAVA_UI
+#include "jsdjava.h"
+#endif /* JSDEBUGGER_JAVA_UI */
+#ifdef JSDEBUGGER_C_UI
+#include "jsdb.h"
+#endif /* JSDEBUGGER_C_UI */
+#endif /* JSDEBUGGER */
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#endif
+
+#if defined(XP_WIN) || defined(XP_OS2)
+#include <io.h> /* for isatty() */
+#endif
+
+typedef enum JSShellExitCode {
+ EXITCODE_RUNTIME_ERROR = 3,
+ EXITCODE_FILE_NOT_FOUND = 4,
+ EXITCODE_OUT_OF_MEMORY = 5
+} JSShellExitCode;
+
+size_t gStackChunkSize = 8192;
+
+/* Assume that we can not use more than 5e5 bytes of C stack by default. */
+static size_t gMaxStackSize = 500000;
+static jsuword gStackBase;
+
+static size_t gScriptStackQuota = JS_DEFAULT_SCRIPT_STACK_QUOTA;
+
+static JSBool gEnableBranchCallback = JS_FALSE;
+static uint32 gBranchCount;
+static uint32 gBranchLimit;
+
+int gExitCode = 0;
+JSBool gQuitting = JS_FALSE;
+FILE *gErrFile = NULL;
+FILE *gOutFile = NULL;
+
+static JSBool reportWarnings = JS_TRUE;
+static JSBool compileOnly = JS_FALSE;
+
+typedef enum JSShellErrNum {
+#define MSG_DEF(name, number, count, exception, format) \
+ name = number,
+#include "jsshell.msg"
+#undef MSG_DEF
+ JSShellErr_Limit
+#undef MSGDEF
+} JSShellErrNum;
+
+static const JSErrorFormatString *
+my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
+static JSObject *
+split_setup(JSContext *cx);
+
+#ifdef EDITLINE
+JS_BEGIN_EXTERN_C
+extern char *readline(const char *prompt);
+extern void add_history(char *line);
+JS_END_EXTERN_C
+#endif
+
+static JSBool
+GetLine(JSContext *cx, char *bufp, FILE *file, const char *prompt) {
+#ifdef EDITLINE
+ /*
+ * Use readline only if file is stdin, because there's no way to specify
+ * another handle. Are other filehandles interactive?
+ */
+ if (file == stdin) {
+ char *linep = readline(prompt);
+ if (!linep)
+ return JS_FALSE;
+ if (linep[0] != '\0')
+ add_history(linep);
+ strcpy(bufp, linep);
+ JS_free(cx, linep);
+ bufp += strlen(bufp);
+ *bufp++ = '\n';
+ *bufp = '\0';
+ } else
+#endif
+ {
+ char line[256];
+ fprintf(gOutFile, prompt);
+ fflush(gOutFile);
+ if (!fgets(line, sizeof line, file))
+ return JS_FALSE;
+ strcpy(bufp, line);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+my_BranchCallback(JSContext *cx, JSScript *script)
+{
+ if (++gBranchCount == gBranchLimit) {
+ if (script) {
+ if (script->filename)
+ fprintf(gErrFile, "%s:", script->filename);
+ fprintf(gErrFile, "%u: script branch callback (%u callbacks)\n",
+ script->lineno, gBranchLimit);
+ } else {
+ fprintf(gErrFile, "native branch callback (%u callbacks)\n",
+ gBranchLimit);
+ }
+ gBranchCount = 0;
+ return JS_FALSE;
+ }
+#ifdef JS_THREADSAFE
+ if ((gBranchCount & 0xff) == 1) {
+#endif
+ if ((gBranchCount & 0x3fff) == 1)
+ JS_MaybeGC(cx);
+#ifdef JS_THREADSAFE
+ else
+ JS_YieldRequest(cx);
+ }
+#endif
+ return JS_TRUE;
+}
+
+static void
+SetContextOptions(JSContext *cx)
+{
+ jsuword stackLimit;
+
+ if (gMaxStackSize == 0) {
+ /*
+ * Disable checking for stack overflow if limit is zero.
+ */
+ stackLimit = 0;
+ } else {
+#if JS_STACK_GROWTH_DIRECTION > 0
+ stackLimit = gStackBase + gMaxStackSize;
+#else
+ stackLimit = gStackBase - gMaxStackSize;
+#endif
+ }
+ JS_SetThreadStackLimit(cx, stackLimit);
+ JS_SetScriptStackQuota(cx, gScriptStackQuota);
+ if (gEnableBranchCallback) {
+ JS_SetBranchCallback(cx, my_BranchCallback);
+ JS_ToggleOptions(cx, JSOPTION_NATIVE_BRANCH_CALLBACK);
+ }
+}
+
+static void
+Process(JSContext *cx, JSObject *obj, char *filename, JSBool forceTTY)
+{
+ JSBool ok, hitEOF;
+ JSScript *script;
+ jsval result;
+ JSString *str;
+ char buffer[4096];
+ char *bufp;
+ int lineno;
+ int startline;
+ FILE *file;
+ uint32 oldopts;
+
+ if (forceTTY || !filename || strcmp(filename, "-") == 0) {
+ file = stdin;
+ } else {
+ file = fopen(filename, "r");
+ if (!file) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+ JSSMSG_CANT_OPEN, filename, strerror(errno));
+ gExitCode = EXITCODE_FILE_NOT_FOUND;
+ return;
+ }
+ }
+
+ SetContextOptions(cx);
+
+ if (!forceTTY && !isatty(fileno(file))) {
+ /*
+ * It's not interactive - just execute it.
+ *
+ * Support the UNIX #! shell hack; gobble the first line if it starts
+ * with '#'. TODO - this isn't quite compatible with sharp variables,
+ * as a legal js program (using sharp variables) might start with '#'.
+ * But that would require multi-character lookahead.
+ */
+ int ch = fgetc(file);
+ if (ch == '#') {
+ while((ch = fgetc(file)) != EOF) {
+ if (ch == '\n' || ch == '\r')
+ break;
+ }
+ }
+ ungetc(ch, file);
+
+ oldopts = JS_GetOptions(cx);
+ JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+ script = JS_CompileFileHandle(cx, obj, filename, file);
+ JS_SetOptions(cx, oldopts);
+ if (script) {
+ if (!compileOnly)
+ (void)JS_ExecuteScript(cx, obj, script, NULL);
+ JS_DestroyScript(cx, script);
+ }
+
+ if (file != stdin)
+ fclose(file);
+ return;
+ }
+
+ /* It's an interactive filehandle; drop into read-eval-print loop. */
+ lineno = 1;
+ hitEOF = JS_FALSE;
+ do {
+ bufp = buffer;
+ *bufp = '\0';
+
+ /*
+ * Accumulate lines until we get a 'compilable unit' - one that either
+ * generates an error (before running out of source) or that compiles
+ * cleanly. This should be whenever we get a complete statement that
+ * coincides with the end of a line.
+ */
+ startline = lineno;
+ do {
+ if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
+ hitEOF = JS_TRUE;
+ break;
+ }
+ bufp += strlen(bufp);
+ lineno++;
+ } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
+
+ /* Clear any pending exception from previous failed compiles. */
+ JS_ClearPendingException(cx);
+ script = JS_CompileScript(cx, obj, buffer, strlen(buffer), "typein",
+ startline);
+ if (script) {
+ if (!compileOnly) {
+ ok = JS_ExecuteScript(cx, obj, script, &result);
+ if (ok && !JSVAL_IS_VOID(result)) {
+ str = JS_ValueToString(cx, result);
+ if (str)
+ fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
+ else
+ ok = JS_FALSE;
+ }
+ }
+ JS_DestroyScript(cx, script);
+ }
+ } while (!hitEOF && !gQuitting);
+ fprintf(gOutFile, "\n");
+ if (file != stdin)
+ fclose(file);
+ return;
+}
+
+static int
+usage(void)
+{
+ fprintf(gErrFile, "%s\n", JS_GetImplementationVersion());
+ fprintf(gErrFile, "usage: js [-zKPswWxCi] [-b branchlimit] [-c stackchunksize] [-o option] [-v version] [-f scriptfile] [-e script] [-S maxstacksize] "
+#ifdef JS_GC_ZEAL
+"[-Z gczeal] "
+#endif
+"[scriptfile] [scriptarg...]\n");
+ return 2;
+}
+
+static struct {
+ const char *name;
+ uint32 flag;
+} js_options[] = {
+ {"strict", JSOPTION_STRICT},
+ {"werror", JSOPTION_WERROR},
+ {"atline", JSOPTION_ATLINE},
+ {"xml", JSOPTION_XML},
+ {"relimit", JSOPTION_RELIMIT},
+ {"anonfunfix", JSOPTION_ANONFUNFIX},
+ {"jit", JSOPTION_JIT},
+ {NULL, 0}
+};
+
+extern JSClass global_class;
+
+static int
+ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
+{
+ int i, j, length;
+ JSObject *argsObj;
+ char *filename = NULL;
+ JSBool isInteractive = JS_TRUE;
+ JSBool forceTTY = JS_FALSE;
+
+ /*
+ * Scan past all optional arguments so we can create the arguments object
+ * before processing any -f options, which must interleave properly with
+ * -v and -w options. This requires two passes, and without getopt, we'll
+ * have to keep the option logic here and in the second for loop in sync.
+ */
+ for (i = 0; i < argc; i++) {
+ if (argv[i][0] != '-' || argv[i][1] == '\0') {
+ ++i;
+ break;
+ }
+ switch (argv[i][1]) {
+ case 'b':
+ case 'c':
+ case 'f':
+ case 'e':
+ case 'v':
+ case 'S':
+#ifdef JS_GC_ZEAL
+ case 'Z':
+#endif
+ ++i;
+ break;
+ default:;
+ }
+ }
+
+ /*
+ * Create arguments early and define it to root it, so it's safe from any
+ * GC calls nested below, and so it is available to -f <file> arguments.
+ */
+ argsObj = JS_NewArrayObject(cx, 0, NULL);
+ if (!argsObj)
+ return 1;
+ if (!JS_DefineProperty(cx, obj, "arguments", OBJECT_TO_JSVAL(argsObj),
+ NULL, NULL, 0)) {
+ return 1;
+ }
+
+ length = argc - i;
+ for (j = 0; j < length; j++) {
+ JSString *str = JS_NewStringCopyZ(cx, argv[i++]);
+ if (!str)
+ return 1;
+ if (!JS_DefineElement(cx, argsObj, j, STRING_TO_JSVAL(str),
+ NULL, NULL, JSPROP_ENUMERATE)) {
+ return 1;
+ }
+ }
+
+ for (i = 0; i < argc; i++) {
+ if (argv[i][0] != '-' || argv[i][1] == '\0') {
+ filename = argv[i++];
+ isInteractive = JS_FALSE;
+ break;
+ }
+
+ switch (argv[i][1]) {
+ case 'v':
+ if (++i == argc)
+ return usage();
+
+ JS_SetVersion(cx, (JSVersion) atoi(argv[i]));
+ break;
+
+#ifdef JS_GC_ZEAL
+ case 'Z':
+ if (++i == argc)
+ return usage();
+ JS_SetGCZeal(cx, atoi(argv[i]));
+ break;
+#endif
+
+ case 'w':
+ reportWarnings = JS_TRUE;
+ break;
+
+ case 'W':
+ reportWarnings = JS_FALSE;
+ break;
+
+ case 's':
+ JS_ToggleOptions(cx, JSOPTION_STRICT);
+ break;
+
+ case 'E':
+ JS_ToggleOptions(cx, JSOPTION_RELIMIT);
+ break;
+
+ case 'x':
+ JS_ToggleOptions(cx, JSOPTION_XML);
+ break;
+
+ case 'j':
+ JS_ToggleOptions(cx, JSOPTION_JIT);
+#if defined(JS_TRACER) && defined(DEBUG)
+extern struct JSClass jitstats_class;
+extern void js_InitJITStatsClass(JSContext *cx, JSObject *glob);
+ js_InitJITStatsClass(cx, JS_GetGlobalObject(cx));
+ JS_DefineObject(cx, JS_GetGlobalObject(cx), "tracemonkey",
+ &jitstats_class, NULL, 0);
+#endif
+ break;
+
+ case 'o':
+ if (++i == argc)
+ return usage();
+
+ for (j = 0; js_options[j].name; ++j) {
+ if (strcmp(js_options[j].name, argv[i]) == 0) {
+ JS_ToggleOptions(cx, js_options[j].flag);
+ break;
+ }
+ }
+ break;
+
+ case 'P':
+ if (JS_GET_CLASS(cx, JS_GetPrototype(cx, obj)) != &global_class) {
+ JSObject *gobj;
+
+ if (!JS_SealObject(cx, obj, JS_TRUE))
+ return JS_FALSE;
+ gobj = JS_NewObject(cx, &global_class, NULL, NULL);
+ if (!gobj)
+ return JS_FALSE;
+ if (!JS_SetPrototype(cx, gobj, obj))
+ return JS_FALSE;
+ JS_SetParent(cx, gobj, NULL);
+ JS_SetGlobalObject(cx, gobj);
+ obj = gobj;
+ }
+ break;
+
+ case 'b':
+ gBranchLimit = atoi(argv[++i]);
+ gEnableBranchCallback = (gBranchLimit != 0);
+ break;
+
+ case 'c':
+ /* set stack chunk size */
+ gStackChunkSize = atoi(argv[++i]);
+ break;
+
+ case 'f':
+ if (++i == argc)
+ return usage();
+
+ Process(cx, obj, argv[i], JS_FALSE);
+
+ /*
+ * XXX: js -f foo.js should interpret foo.js and then
+ * drop into interactive mode, but that breaks the test
+ * harness. Just execute foo.js for now.
+ */
+ isInteractive = JS_FALSE;
+ break;
+
+ case 'e':
+ {
+ jsval rval;
+
+ if (++i == argc)
+ return usage();
+
+ /* Pass a filename of -e to imitate PERL */
+ JS_EvaluateScript(cx, obj, argv[i], strlen(argv[i]),
+ "-e", 1, &rval);
+
+ isInteractive = JS_FALSE;
+ break;
+
+ }
+ case 'C':
+ compileOnly = JS_TRUE;
+ isInteractive = JS_FALSE;
+ break;
+
+ case 'i':
+ isInteractive = forceTTY = JS_TRUE;
+ break;
+
+ case 'S':
+ if (++i == argc)
+ return usage();
+
+ /* Set maximum stack size. */
+ gMaxStackSize = atoi(argv[i]);
+ break;
+
+ case 'z':
+ obj = split_setup(cx);
+ if (!obj)
+ return gExitCode;
+ break;
+#ifdef MOZ_SHARK
+ case 'k':
+ JS_ConnectShark();
+ break;
+#endif
+ default:
+ return usage();
+ }
+ }
+
+ if (filename || isInteractive)
+ Process(cx, obj, filename, forceTTY);
+ return gExitCode;
+}
+
+static JSBool
+Version(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if (argc > 0 && JSVAL_IS_INT(argv[0]))
+ *rval = INT_TO_JSVAL(JS_SetVersion(cx, (JSVersion) JSVAL_TO_INT(argv[0])));
+ else
+ *rval = INT_TO_JSVAL(JS_GetVersion(cx));
+ return JS_TRUE;
+}
+
+static JSBool
+Options(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uint32 optset, flag;
+ uintN i, j, found;
+ JSString *str;
+ const char *opt;
+ char *names;
+
+ optset = 0;
+ for (i = 0; i < argc; i++) {
+ str = JS_ValueToString(cx, argv[i]);
+ if (!str)
+ return JS_FALSE;
+ opt = JS_GetStringBytes(str);
+ for (j = 0; js_options[j].name; j++) {
+ if (strcmp(js_options[j].name, opt) == 0) {
+ optset |= js_options[j].flag;
+ break;
+ }
+ }
+ }
+ optset = JS_ToggleOptions(cx, optset);
+
+ names = NULL;
+ found = 0;
+ while (optset != 0) {
+ flag = optset;
+ optset &= optset - 1;
+ flag &= ~optset;
+ for (j = 0; js_options[j].name; j++) {
+ if (js_options[j].flag == flag) {
+ names = JS_sprintf_append(names, "%s%s",
+ names ? "," : "", js_options[j].name);
+ found++;
+ break;
+ }
+ }
+ }
+ if (!found)
+ names = strdup("");
+ if (!names) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ str = JS_NewString(cx, names, strlen(names));
+ if (!str) {
+ free(names);
+ return JS_FALSE;
+ }
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uintN i;
+ JSString *str;
+ const char *filename;
+ JSScript *script;
+ JSBool ok;
+ uint32 oldopts;
+
+ for (i = 0; i < argc; i++) {
+ str = JS_ValueToString(cx, argv[i]);
+ if (!str)
+ return JS_FALSE;
+ argv[i] = STRING_TO_JSVAL(str);
+ filename = JS_GetStringBytes(str);
+ errno = 0;
+ oldopts = JS_GetOptions(cx);
+ JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+ script = JS_CompileFile(cx, obj, filename);
+ JS_SetOptions(cx, oldopts);
+ if (!script) {
+ ok = JS_FALSE;
+ } else {
+ ok = !compileOnly
+ ? JS_ExecuteScript(cx, obj, script, NULL)
+ : JS_TRUE;
+ JS_DestroyScript(cx, script);
+ }
+ if (!ok)
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+/*
+ * function readline()
+ * Provides a hook for scripts to read a line from stdin.
+ */
+static JSBool
+ReadLine(JSContext *cx, uintN argc, jsval *vp)
+{
+#define BUFSIZE 256
+ FILE *from;
+ char *buf, *tmp;
+ size_t bufsize, buflength, gotlength;
+ JSBool sawNewline;
+ JSString *str;
+
+ from = stdin;
+ buflength = 0;
+ bufsize = BUFSIZE;
+ buf = (char *) JS_malloc(cx, bufsize);
+ if (!buf)
+ return JS_FALSE;
+
+ sawNewline = JS_FALSE;
+ while ((gotlength =
+ js_fgets(buf + buflength, bufsize - buflength, from)) > 0) {
+ buflength += gotlength;
+
+ /* Are we done? */
+ if (buf[buflength - 1] == '\n') {
+ buf[buflength - 1] = '\0';
+ sawNewline = JS_TRUE;
+ break;
+ } else if (buflength < bufsize - 1) {
+ break;
+ }
+
+ /* Else, grow our buffer for another pass. */
+ bufsize *= 2;
+ if (bufsize > buflength) {
+ tmp = (char *) JS_realloc(cx, buf, bufsize);
+ } else {
+ JS_ReportOutOfMemory(cx);
+ tmp = NULL;
+ }
+
+ if (!tmp) {
+ JS_free(cx, buf);
+ return JS_FALSE;
+ }
+
+ buf = tmp;
+ }
+
+ /* Treat the empty string specially. */
+ if (buflength == 0) {
+ *vp = feof(from) ? JSVAL_NULL : JS_GetEmptyStringValue(cx);
+ JS_free(cx, buf);
+ return JS_TRUE;
+ }
+
+ /* Shrink the buffer to the real size. */
+ tmp = (char *) JS_realloc(cx, buf, buflength);
+ if (!tmp) {
+ JS_free(cx, buf);
+ return JS_FALSE;
+ }
+
+ buf = tmp;
+
+ /*
+ * Turn buf into a JSString. Note that buflength includes the trailing null
+ * character.
+ */
+ str = JS_NewString(cx, buf, sawNewline ? buflength - 1 : buflength);
+ if (!str) {
+ JS_free(cx, buf);
+ return JS_FALSE;
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static jsval JS_FASTCALL
+Print_tn(JSContext *cx, JSString *str)
+{
+ char *bytes = JS_EncodeString(cx, str);
+ if (!bytes)
+ return JSVAL_ERROR_COOKIE;
+ fprintf(gOutFile, "%s\n", bytes);
+ JS_free(cx, bytes);
+ fflush(gOutFile);
+ return JSVAL_VOID;
+}
+#endif
+
+static JSBool
+Print(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv;
+ uintN i;
+ JSString *str;
+ char *bytes;
+
+ argv = JS_ARGV(cx, vp);
+ for (i = 0; i < argc; i++) {
+ str = JS_ValueToString(cx, argv[i]);
+ if (!str)
+ return JS_FALSE;
+ bytes = JS_EncodeString(cx, str);
+ if (!bytes)
+ return JS_FALSE;
+ fprintf(gOutFile, "%s%s", i ? " " : "", bytes);
+ JS_free(cx, bytes);
+ }
+
+ fputc('\n', gOutFile);
+ fflush(gOutFile);
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
+}
+
+static JSBool
+Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+static JSBool
+Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+#ifdef LIVECONNECT
+ JSJ_SimpleShutdown();
+#endif
+
+ JS_ConvertArguments(cx, argc, argv,"/ i", &gExitCode);
+
+ gQuitting = JS_TRUE;
+ return JS_FALSE;
+}
+
+static JSBool
+GC(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSRuntime *rt;
+ uint32 preBytes;
+
+ rt = cx->runtime;
+ preBytes = rt->gcBytes;
+ JS_GC(cx);
+
+ fprintf(gOutFile, "before %lu, after %lu, break %08lx\n",
+ (unsigned long)preBytes, (unsigned long)rt->gcBytes,
+#ifdef XP_UNIX
+ (unsigned long)sbrk(0)
+#else
+ 0
+#endif
+ );
+#ifdef JS_GCMETER
+ js_DumpGCStats(rt, stdout);
+#endif
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool
+GCParameter(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ const char *paramName;
+ JSGCParamKey param;
+ uint32 value;
+
+ if (argc == 0) {
+ str = JS_ValueToString(cx, JSVAL_VOID);
+ JS_ASSERT(str);
+ } else {
+ str = JS_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(str);
+ }
+ paramName = JS_GetStringBytes(str);
+ if (!paramName)
+ return JS_FALSE;
+ if (strcmp(paramName, "maxBytes") == 0) {
+ param = JSGC_MAX_BYTES;
+ } else if (strcmp(paramName, "maxMallocBytes") == 0) {
+ param = JSGC_MAX_MALLOC_BYTES;
+ } else {
+ JS_ReportError(cx,
+ "the first argument argument must be either maxBytes "
+ "or maxMallocBytes");
+ return JS_FALSE;
+ }
+
+ if (!JS_ValueToECMAUint32(cx, argc < 2 ? JSVAL_VOID : vp[3], &value))
+ return JS_FALSE;
+ if (value == 0) {
+ JS_ReportError(cx,
+ "the second argument must be convertable to uint32 with "
+ "non-zero value");
+ return JS_FALSE;
+ }
+ JS_SetGCParameter(cx->runtime, param, value);
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+#ifdef JS_GC_ZEAL
+static JSBool
+GCZeal(JSContext *cx, uintN argc, jsval *vp)
+{
+ uint32 zeal;
+
+ if (!JS_ValueToECMAUint32(cx, argc == 0 ? JSVAL_VOID : vp[2], &zeal))
+ return JS_FALSE;
+ JS_SetGCZeal(cx, (uint8)zeal);
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+}
+#endif /* JS_GC_ZEAL */
+
+typedef struct JSCountHeapNode JSCountHeapNode;
+
+struct JSCountHeapNode {
+ void *thing;
+ int32 kind;
+ JSCountHeapNode *next;
+};
+
+typedef struct JSCountHeapTracer {
+ JSTracer base;
+ JSDHashTable visited;
+ JSBool ok;
+ JSCountHeapNode *traceList;
+ JSCountHeapNode *recycleList;
+} JSCountHeapTracer;
+
+static void
+CountHeapNotify(JSTracer *trc, void *thing, uint32 kind)
+{
+ JSCountHeapTracer *countTracer;
+ JSDHashEntryStub *entry;
+ JSCountHeapNode *node;
+
+ JS_ASSERT(trc->callback == CountHeapNotify);
+ countTracer = (JSCountHeapTracer *)trc;
+ if (!countTracer->ok)
+ return;
+
+ entry = (JSDHashEntryStub *)
+ JS_DHashTableOperate(&countTracer->visited, thing, JS_DHASH_ADD);
+ if (!entry) {
+ JS_ReportOutOfMemory(trc->context);
+ countTracer->ok = JS_FALSE;
+ return;
+ }
+ if (entry->key)
+ return;
+ entry->key = thing;
+
+ node = countTracer->recycleList;
+ if (node) {
+ countTracer->recycleList = node->next;
+ } else {
+ node = (JSCountHeapNode *) JS_malloc(trc->context, sizeof *node);
+ if (!node) {
+ countTracer->ok = JS_FALSE;
+ return;
+ }
+ }
+ node->thing = thing;
+ node->kind = kind;
+ node->next = countTracer->traceList;
+ countTracer->traceList = node;
+}
+
+static JSBool
+CountHeap(JSContext *cx, uintN argc, jsval *vp)
+{
+ void* startThing;
+ int32 startTraceKind;
+ jsval v;
+ int32 traceKind, i;
+ JSString *str;
+ char *bytes;
+ JSCountHeapTracer countTracer;
+ JSCountHeapNode *node;
+ size_t counter;
+
+ static const struct {
+ const char *name;
+ int32 kind;
+ } traceKindNames[] = {
+ { "all", -1 },
+ { "object", JSTRACE_OBJECT },
+ { "double", JSTRACE_DOUBLE },
+ { "string", JSTRACE_STRING },
+#if JS_HAS_XML_SUPPORT
+ { "xml", JSTRACE_XML },
+#endif
+ };
+
+ startThing = NULL;
+ startTraceKind = 0;
+ if (argc > 0) {
+ v = JS_ARGV(cx, vp)[0];
+ if (JSVAL_IS_TRACEABLE(v)) {
+ startThing = JSVAL_TO_TRACEABLE(v);
+ startTraceKind = JSVAL_TRACE_KIND(v);
+ } else if (v != JSVAL_NULL) {
+ JS_ReportError(cx,
+ "the first argument is not null or a heap-allocated "
+ "thing");
+ return JS_FALSE;
+ }
+ }
+
+ traceKind = -1;
+ if (argc > 1) {
+ str = JS_ValueToString(cx, JS_ARGV(cx, vp)[1]);
+ if (!str)
+ return JS_FALSE;
+ bytes = JS_GetStringBytes(str);
+ if (!bytes)
+ return JS_FALSE;
+ for (i = 0; ;) {
+ if (strcmp(bytes, traceKindNames[i].name) == 0) {
+ traceKind = traceKindNames[i].kind;
+ break;
+ }
+ if (++i == JS_ARRAY_LENGTH(traceKindNames)) {
+ JS_ReportError(cx, "trace kind name '%s' is unknown", bytes);
+ return JS_FALSE;
+ }
+ }
+ }
+
+ JS_TRACER_INIT(&countTracer.base, cx, CountHeapNotify);
+ if (!JS_DHashTableInit(&countTracer.visited, JS_DHashGetStubOps(),
+ NULL, sizeof(JSDHashEntryStub),
+ JS_DHASH_DEFAULT_CAPACITY(100))) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ countTracer.ok = JS_TRUE;
+ countTracer.traceList = NULL;
+ countTracer.recycleList = NULL;
+
+ if (!startThing) {
+ JS_TraceRuntime(&countTracer.base);
+ } else {
+ JS_SET_TRACING_NAME(&countTracer.base, "root");
+ JS_CallTracer(&countTracer.base, startThing, startTraceKind);
+ }
+
+ counter = 0;
+ while ((node = countTracer.traceList) != NULL) {
+ if (traceKind == -1 || node->kind == traceKind)
+ counter++;
+ countTracer.traceList = node->next;
+ node->next = countTracer.recycleList;
+ countTracer.recycleList = node;
+ JS_TraceChildren(&countTracer.base, node->thing, node->kind);
+ }
+ while ((node = countTracer.recycleList) != NULL) {
+ countTracer.recycleList = node->next;
+ JS_free(cx, node);
+ }
+ JS_DHashTableFinish(&countTracer.visited);
+
+ return countTracer.ok && JS_NewNumberValue(cx, (jsdouble) counter, vp);
+}
+
+static JSScript *
+ValueToScript(JSContext *cx, jsval v)
+{
+ JSScript *script;
+ JSFunction *fun;
+
+ if (!JSVAL_IS_PRIMITIVE(v) &&
+ JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_ScriptClass) {
+ script = (JSScript *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ } else {
+ fun = JS_ValueToFunction(cx, v);
+ if (!fun)
+ return NULL;
+ script = FUN_SCRIPT(fun);
+ }
+
+ if (!script) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+ JSSMSG_SCRIPTS_ONLY);
+ }
+
+ return script;
+}
+
+static JSBool
+GetTrapArgs(JSContext *cx, uintN argc, jsval *argv, JSScript **scriptp,
+ int32 *ip)
+{
+ jsval v;
+ uintN intarg;
+ JSScript *script;
+
+ *scriptp = cx->fp->down->script;
+ *ip = 0;
+ if (argc != 0) {
+ v = argv[0];
+ intarg = 0;
+ if (!JSVAL_IS_PRIMITIVE(v) &&
+ (JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass ||
+ JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_ScriptClass)) {
+ script = ValueToScript(cx, v);
+ if (!script)
+ return JS_FALSE;
+ *scriptp = script;
+ intarg++;
+ }
+ if (argc > intarg) {
+ if (!JS_ValueToInt32(cx, argv[intarg], ip))
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSTrapStatus
+TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
+ void *closure)
+{
+ JSString *str;
+ JSStackFrame *caller;
+
+ str = (JSString *) closure;
+ caller = JS_GetScriptedCaller(cx, NULL);
+ if (!JS_EvaluateScript(cx, caller->scopeChain,
+ JS_GetStringBytes(str), JS_GetStringLength(str),
+ caller->script->filename, caller->script->lineno,
+ rval)) {
+ return JSTRAP_ERROR;
+ }
+ if (!JSVAL_IS_VOID(*rval))
+ return JSTRAP_RETURN;
+ return JSTRAP_CONTINUE;
+}
+
+static JSBool
+Trap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+ JSScript *script;
+ int32 i;
+
+ if (argc == 0) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_TRAP_USAGE);
+ return JS_FALSE;
+ }
+ argc--;
+ str = JS_ValueToString(cx, argv[argc]);
+ if (!str)
+ return JS_FALSE;
+ argv[argc] = STRING_TO_JSVAL(str);
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
+ return JS_FALSE;
+ return JS_SetTrap(cx, script, script->code + i, TrapHandler, str);
+}
+
+static JSBool
+Untrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSScript *script;
+ int32 i;
+
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
+ return JS_FALSE;
+ JS_ClearTrap(cx, script, script->code + i, NULL, NULL);
+ return JS_TRUE;
+}
+
+static JSBool
+LineToPC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSScript *script;
+ int32 i;
+ uintN lineno;
+ jsbytecode *pc;
+
+ if (argc == 0) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_LINE2PC_USAGE);
+ return JS_FALSE;
+ }
+ script = cx->fp->down->script;
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
+ return JS_FALSE;
+ lineno = (i == 0) ? script->lineno : (uintN)i;
+ pc = JS_LineNumberToPC(cx, script, lineno);
+ if (!pc)
+ return JS_FALSE;
+ *rval = INT_TO_JSVAL(PTRDIFF(pc, script->code, jsbytecode));
+ return JS_TRUE;
+}
+
+static JSBool
+PCToLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSScript *script;
+ int32 i;
+ uintN lineno;
+
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
+ return JS_FALSE;
+ lineno = JS_PCToLineNumber(cx, script, script->code + i);
+ if (!lineno)
+ return JS_FALSE;
+ *rval = INT_TO_JSVAL(lineno);
+ return JS_TRUE;
+}
+
+#ifdef DEBUG
+
+static void
+UpdateSwitchTableBounds(JSScript *script, uintN offset,
+ uintN *start, uintN *end)
+{
+ jsbytecode *pc;
+ JSOp op;
+ ptrdiff_t jmplen;
+ jsint low, high, n;
+
+ pc = script->code + offset;
+ op = (JSOp) *pc;
+ switch (op) {
+ case JSOP_TABLESWITCHX:
+ jmplen = JUMPX_OFFSET_LEN;
+ goto jump_table;
+ case JSOP_TABLESWITCH:
+ jmplen = JUMP_OFFSET_LEN;
+ jump_table:
+ pc += jmplen;
+ low = GET_JUMP_OFFSET(pc);
+ pc += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc);
+ pc += JUMP_OFFSET_LEN;
+ n = high - low + 1;
+ break;
+
+ case JSOP_LOOKUPSWITCHX:
+ jmplen = JUMPX_OFFSET_LEN;
+ goto lookup_table;
+ case JSOP_LOOKUPSWITCH:
+ jmplen = JUMP_OFFSET_LEN;
+ lookup_table:
+ pc += jmplen;
+ n = GET_INDEX(pc);
+ pc += INDEX_LEN;
+ jmplen += JUMP_OFFSET_LEN;
+ break;
+
+ default:
+ /* [condswitch] switch does not have any jump or lookup tables. */
+ JS_ASSERT(op == JSOP_CONDSWITCH);
+ return;
+ }
+
+ *start = (uintN)(pc - script->code);
+ *end = *start + (uintN)(n * jmplen);
+}
+
+static void
+SrcNotes(JSContext *cx, JSScript *script)
+{
+ uintN offset, delta, caseOff, switchTableStart, switchTableEnd;
+ jssrcnote *notes, *sn;
+ JSSrcNoteType type;
+ const char *name;
+ uint32 index;
+ JSAtom *atom;
+ JSString *str;
+
+ fprintf(gOutFile, "\nSource notes:\n");
+ offset = 0;
+ notes = SCRIPT_NOTES(script);
+ switchTableEnd = switchTableStart = 0;
+ for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
+ delta = SN_DELTA(sn);
+ offset += delta;
+ type = (JSSrcNoteType) SN_TYPE(sn);
+ name = js_SrcNoteSpec[type].name;
+ if (type == SRC_LABEL) {
+ /* Check if the source note is for a switch case. */
+ if (switchTableStart <= offset && offset < switchTableEnd) {
+ name = "case";
+ } else {
+ JS_ASSERT(script->code[offset] == JSOP_NOP);
+ }
+ }
+ fprintf(gOutFile, "%3u: %5u [%4u] %-8s",
+ (uintN) PTRDIFF(sn, notes, jssrcnote), offset, delta, name);
+ switch (type) {
+ case SRC_SETLINE:
+ fprintf(gOutFile, " lineno %u", (uintN) js_GetSrcNoteOffset(sn, 0));
+ break;
+ case SRC_FOR:
+ fprintf(gOutFile, " cond %u update %u tail %u",
+ (uintN) js_GetSrcNoteOffset(sn, 0),
+ (uintN) js_GetSrcNoteOffset(sn, 1),
+ (uintN) js_GetSrcNoteOffset(sn, 2));
+ break;
+ case SRC_IF_ELSE:
+ fprintf(gOutFile, " else %u elseif %u",
+ (uintN) js_GetSrcNoteOffset(sn, 0),
+ (uintN) js_GetSrcNoteOffset(sn, 1));
+ break;
+ case SRC_COND:
+ case SRC_WHILE:
+ case SRC_PCBASE:
+ case SRC_PCDELTA:
+ case SRC_DECL:
+ case SRC_BRACE:
+ fprintf(gOutFile, " offset %u", (uintN) js_GetSrcNoteOffset(sn, 0));
+ break;
+ case SRC_LABEL:
+ case SRC_LABELBRACE:
+ case SRC_BREAK2LABEL:
+ case SRC_CONT2LABEL:
+ index = js_GetSrcNoteOffset(sn, 0);
+ JS_GET_SCRIPT_ATOM(script, index, atom);
+ JS_ASSERT(ATOM_IS_STRING(atom));
+ str = ATOM_TO_STRING(atom);
+ fprintf(gOutFile, " atom %u (", index);
+ js_FileEscapedString(gOutFile, str, 0);
+ putc(')', gOutFile);
+ break;
+ case SRC_FUNCDEF: {
+ const char *bytes;
+ JSObject *obj;
+ JSFunction *fun;
+
+ index = js_GetSrcNoteOffset(sn, 0);
+ JS_GET_SCRIPT_OBJECT(script, index, obj);
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
+ str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
+ bytes = str ? JS_GetStringBytes(str) : "N/A";
+ fprintf(gOutFile, " function %u (%s)", index, bytes);
+ break;
+ }
+ case SRC_SWITCH:
+ fprintf(gOutFile, " length %u", (uintN) js_GetSrcNoteOffset(sn, 0));
+ caseOff = (uintN) js_GetSrcNoteOffset(sn, 1);
+ if (caseOff)
+ fprintf(gOutFile, " first case offset %u", caseOff);
+ UpdateSwitchTableBounds(script, offset,
+ &switchTableStart, &switchTableEnd);
+ break;
+ case SRC_CATCH:
+ delta = (uintN) js_GetSrcNoteOffset(sn, 0);
+ if (delta) {
+ if (script->main[offset] == JSOP_LEAVEBLOCK)
+ fprintf(gOutFile, " stack depth %u", delta);
+ else
+ fprintf(gOutFile, " guard delta %u", delta);
+ }
+ break;
+ default:;
+ }
+ fputc('\n', gOutFile);
+ }
+}
+
+static JSBool
+Notes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uintN i;
+ JSScript *script;
+
+ for (i = 0; i < argc; i++) {
+ script = ValueToScript(cx, argv[i]);
+ if (!script)
+ continue;
+
+ SrcNotes(cx, script);
+ }
+ return JS_TRUE;
+}
+
+JS_STATIC_ASSERT(JSTRY_CATCH == 0);
+JS_STATIC_ASSERT(JSTRY_FINALLY == 1);
+JS_STATIC_ASSERT(JSTRY_ITER == 2);
+
+static const char* const TryNoteNames[] = { "catch", "finally", "iter" };
+
+static JSBool
+TryNotes(JSContext *cx, JSScript *script)
+{
+ JSTryNote *tn, *tnlimit;
+
+ if (script->trynotesOffset == 0)
+ return JS_TRUE;
+
+ tn = JS_SCRIPT_TRYNOTES(script)->vector;
+ tnlimit = tn + JS_SCRIPT_TRYNOTES(script)->length;
+ fprintf(gOutFile, "\nException table:\n"
+ "kind stack start end\n");
+ do {
+ JS_ASSERT(tn->kind < JS_ARRAY_LENGTH(TryNoteNames));
+ fprintf(gOutFile, " %-7s %6u %8u %8u\n",
+ TryNoteNames[tn->kind], tn->stackDepth,
+ tn->start, tn->start + tn->length);
+ } while (++tn != tnlimit);
+ return JS_TRUE;
+}
+
+static JSBool
+Disassemble(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSBool lines;
+ uintN i;
+ JSScript *script;
+
+ if (argc > 0 &&
+ JSVAL_IS_STRING(argv[0]) &&
+ !strcmp(JS_GetStringBytes(JSVAL_TO_STRING(argv[0])), "-l")) {
+ lines = JS_TRUE;
+ argv++, argc--;
+ } else {
+ lines = JS_FALSE;
+ }
+ for (i = 0; i < argc; i++) {
+ script = ValueToScript(cx, argv[i]);
+ if (!script)
+ return JS_FALSE;
+ if (VALUE_IS_FUNCTION(cx, argv[i])) {
+ JSFunction *fun = JS_ValueToFunction(cx, argv[i]);
+ if (fun && (fun->flags & JSFUN_FLAGS_MASK)) {
+ uint16 flags = fun->flags;
+ fputs("flags:", stdout);
+
+#define SHOW_FLAG(flag) if (flags & JSFUN_##flag) fputs(" " #flag, stdout);
+
+ SHOW_FLAG(LAMBDA);
+ SHOW_FLAG(SETTER);
+ SHOW_FLAG(GETTER);
+ SHOW_FLAG(BOUND_METHOD);
+ SHOW_FLAG(HEAVYWEIGHT);
+ SHOW_FLAG(THISP_STRING);
+ SHOW_FLAG(THISP_NUMBER);
+ SHOW_FLAG(THISP_BOOLEAN);
+ SHOW_FLAG(EXPR_CLOSURE);
+ SHOW_FLAG(INTERPRETED);
+
+#undef SHOW_FLAG
+ putchar('\n');
+ }
+ }
+
+ if (!js_Disassemble(cx, script, lines, stdout))
+ return JS_FALSE;
+ SrcNotes(cx, script);
+ TryNotes(cx, script);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+DisassFile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+ const char *filename;
+ JSScript *script;
+ JSBool ok;
+ uint32 oldopts;
+
+ if (!argc)
+ return JS_TRUE;
+
+ str = JS_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(str);
+
+ filename = JS_GetStringBytes(str);
+ oldopts = JS_GetOptions(cx);
+ JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+ script = JS_CompileFile(cx, obj, filename);
+ JS_SetOptions(cx, oldopts);
+ if (!script)
+ return JS_FALSE;
+
+ obj = JS_NewScriptObject(cx, script);
+ if (!obj)
+ return JS_FALSE;
+
+ *rval = OBJECT_TO_JSVAL(obj); /* I like to root it, root it. */
+ ok = Disassemble(cx, obj, 1, rval, rval); /* gross, but works! */
+ *rval = JSVAL_VOID;
+
+ return ok;
+}
+
+static JSBool
+DisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+#define LINE_BUF_LEN 512
+ uintN i, len, line1, line2, bupline;
+ JSScript *script;
+ FILE *file;
+ char linebuf[LINE_BUF_LEN];
+ jsbytecode *pc, *end;
+ JSBool ok;
+ static char sep[] = ";-------------------------";
+
+ ok = JS_TRUE;
+ for (i = 0; ok && i < argc; i++) {
+ script = ValueToScript(cx, argv[i]);
+ if (!script)
+ return JS_FALSE;
+
+ if (!script->filename) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+ JSSMSG_FILE_SCRIPTS_ONLY);
+ return JS_FALSE;
+ }
+
+ file = fopen(script->filename, "r");
+ if (!file) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+ JSSMSG_CANT_OPEN, script->filename,
+ strerror(errno));
+ return JS_FALSE;
+ }
+
+ pc = script->code;
+ end = pc + script->length;
+
+ /* burn the leading lines */
+ line2 = JS_PCToLineNumber(cx, script, pc);
+ for (line1 = 0; line1 < line2 - 1; line1++)
+ fgets(linebuf, LINE_BUF_LEN, file);
+
+ bupline = 0;
+ while (pc < end) {
+ line2 = JS_PCToLineNumber(cx, script, pc);
+
+ if (line2 < line1) {
+ if (bupline != line2) {
+ bupline = line2;
+ fprintf(gOutFile, "%s %3u: BACKUP\n", sep, line2);
+ }
+ } else {
+ if (bupline && line1 == line2)
+ fprintf(gOutFile, "%s %3u: RESTORE\n", sep, line2);
+ bupline = 0;
+ while (line1 < line2) {
+ if (!fgets(linebuf, LINE_BUF_LEN, file)) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+ JSSMSG_UNEXPECTED_EOF,
+ script->filename);
+ ok = JS_FALSE;
+ goto bail;
+ }
+ line1++;
+ fprintf(gOutFile, "%s %3u: %s", sep, line1, linebuf);
+ }
+ }
+
+ len = js_Disassemble1(cx, script, pc,
+ PTRDIFF(pc, script->code, jsbytecode),
+ JS_TRUE, stdout);
+ if (!len) {
+ ok = JS_FALSE;
+ goto bail;
+ }
+ pc += len;
+ }
+
+ bail:
+ fclose(file);
+ }
+ return ok;
+#undef LINE_BUF_LEN
+}
+
+static JSBool
+Tracing(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSBool bval;
+ JSString *str;
+
+#if JS_THREADED_INTERP
+ JS_ReportError(cx, "tracing not supported in JS_THREADED_INTERP builds");
+ return JS_FALSE;
+#else
+ if (argc == 0) {
+ *rval = BOOLEAN_TO_JSVAL(cx->tracefp != 0);
+ return JS_TRUE;
+ }
+
+ switch (JS_TypeOfValue(cx, argv[0])) {
+ case JSTYPE_NUMBER:
+ bval = JSVAL_IS_INT(argv[0])
+ ? JSVAL_TO_INT(argv[0])
+ : (jsint) *JSVAL_TO_DOUBLE(argv[0]);
+ break;
+ case JSTYPE_BOOLEAN:
+ bval = JSVAL_TO_BOOLEAN(argv[0]);
+ break;
+ default:
+ str = JS_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ JS_ReportError(cx, "tracing: illegal argument %s",
+ JS_GetStringBytes(str));
+ return JS_FALSE;
+ }
+ cx->tracefp = bval ? stderr : NULL;
+ return JS_TRUE;
+#endif
+}
+
+static void
+DumpScope(JSContext *cx, JSObject *obj, FILE *fp)
+{
+ uintN i;
+ JSScope *scope;
+ JSScopeProperty *sprop;
+ jsval v;
+ JSString *str;
+
+ i = 0;
+ scope = OBJ_SCOPE(obj);
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
+ if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop))
+ continue;
+ fprintf(fp, "%3u %p ", i, (void *)sprop);
+
+ v = ID_TO_VALUE(sprop->id);
+ if (JSID_IS_INT(sprop->id)) {
+ fprintf(fp, "[%ld]", (long)JSVAL_TO_INT(v));
+ } else {
+ if (JSID_IS_ATOM(sprop->id)) {
+ str = JSVAL_TO_STRING(v);
+ } else {
+ JS_ASSERT(JSID_IS_OBJECT(sprop->id));
+ str = js_ValueToString(cx, v);
+ fputs("object ", fp);
+ }
+ if (!str)
+ fputs("<error>", fp);
+ else
+ js_FileEscapedString(fp, str, '"');
+ }
+#define DUMP_ATTR(name) if (sprop->attrs & JSPROP_##name) fputs(" " #name, fp)
+ DUMP_ATTR(ENUMERATE);
+ DUMP_ATTR(READONLY);
+ DUMP_ATTR(PERMANENT);
+ DUMP_ATTR(GETTER);
+ DUMP_ATTR(SETTER);
+#undef DUMP_ATTR
+
+ fprintf(fp, " slot %lu flags %x shortid %d\n",
+ (unsigned long)sprop->slot, sprop->flags, sprop->shortid);
+ }
+}
+
+static JSBool
+DumpStats(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uintN i;
+ JSString *str;
+ const char *bytes;
+ jsid id;
+ JSObject *obj2;
+ JSProperty *prop;
+ jsval value;
+
+ for (i = 0; i < argc; i++) {
+ str = JS_ValueToString(cx, argv[i]);
+ if (!str)
+ return JS_FALSE;
+ argv[i] = STRING_TO_JSVAL(str);
+ bytes = JS_GetStringBytes(str);
+ if (strcmp(bytes, "arena") == 0) {
+#ifdef JS_ARENAMETER
+ JS_DumpArenaStats(stdout);
+#endif
+ } else if (strcmp(bytes, "atom") == 0) {
+ js_DumpAtoms(cx, gOutFile);
+ } else if (strcmp(bytes, "global") == 0) {
+ DumpScope(cx, cx->globalObject, stdout);
+ } else {
+ if (!JS_ValueToId(cx, STRING_TO_JSVAL(str), &id))
+ return JS_FALSE;
+ if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
+ return JS_FALSE;
+ if (prop) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &value))
+ return JS_FALSE;
+ }
+ if (!prop || !JSVAL_IS_OBJECT(value)) {
+ fprintf(gErrFile, "js: invalid stats argument %s\n",
+ bytes);
+ continue;
+ }
+ obj = JSVAL_TO_OBJECT(value);
+ if (obj)
+ DumpScope(cx, obj, stdout);
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+DumpHeap(JSContext *cx, uintN argc, jsval *vp)
+{
+ char *fileName;
+ jsval v;
+ void* startThing;
+ uint32 startTraceKind;
+ const char *badTraceArg;
+ void *thingToFind;
+ size_t maxDepth;
+ void *thingToIgnore;
+ FILE *dumpFile;
+ JSBool ok;
+
+ fileName = NULL;
+ if (argc > 0) {
+ v = JS_ARGV(cx, vp)[0];
+ if (v != JSVAL_NULL) {
+ JSString *str;
+
+ str = JS_ValueToString(cx, v);
+ if (!str)
+ return JS_FALSE;
+ JS_ARGV(cx, vp)[0] = STRING_TO_JSVAL(str);
+ fileName = JS_GetStringBytes(str);
+ }
+ }
+
+ startThing = NULL;
+ startTraceKind = 0;
+ if (argc > 1) {
+ v = JS_ARGV(cx, vp)[1];
+ if (JSVAL_IS_TRACEABLE(v)) {
+ startThing = JSVAL_TO_TRACEABLE(v);
+ startTraceKind = JSVAL_TRACE_KIND(v);
+ } else if (v != JSVAL_NULL) {
+ badTraceArg = "start";
+ goto not_traceable_arg;
+ }
+ }
+
+ thingToFind = NULL;
+ if (argc > 2) {
+ v = JS_ARGV(cx, vp)[2];
+ if (JSVAL_IS_TRACEABLE(v)) {
+ thingToFind = JSVAL_TO_TRACEABLE(v);
+ } else if (v != JSVAL_NULL) {
+ badTraceArg = "toFind";
+ goto not_traceable_arg;
+ }
+ }
+
+ maxDepth = (size_t)-1;
+ if (argc > 3) {
+ v = JS_ARGV(cx, vp)[3];
+ if (v != JSVAL_NULL) {
+ uint32 depth;
+
+ if (!JS_ValueToECMAUint32(cx, v, &depth))
+ return JS_FALSE;
+ maxDepth = depth;
+ }
+ }
+
+ thingToIgnore = NULL;
+ if (argc > 4) {
+ v = JS_ARGV(cx, vp)[4];
+ if (JSVAL_IS_TRACEABLE(v)) {
+ thingToIgnore = JSVAL_TO_TRACEABLE(v);
+ } else if (v != JSVAL_NULL) {
+ badTraceArg = "toIgnore";
+ goto not_traceable_arg;
+ }
+ }
+
+ if (!fileName) {
+ dumpFile = stdout;
+ } else {
+ dumpFile = fopen(fileName, "w");
+ if (!dumpFile) {
+ JS_ReportError(cx, "can't open %s: %s", fileName, strerror(errno));
+ return JS_FALSE;
+ }
+ }
+
+ ok = JS_DumpHeap(cx, dumpFile, startThing, startTraceKind, thingToFind,
+ maxDepth, thingToIgnore);
+ if (dumpFile != stdout)
+ fclose(dumpFile);
+ return ok;
+
+ not_traceable_arg:
+ JS_ReportError(cx, "argument '%s' is not null or a heap-allocated thing",
+ badTraceArg);
+ return JS_FALSE;
+}
+
+#endif /* DEBUG */
+
+#ifdef TEST_CVTARGS
+#include <ctype.h>
+
+static const char *
+EscapeWideString(jschar *w)
+{
+ static char enuf[80];
+ static char hex[] = "0123456789abcdef";
+ jschar u;
+ unsigned char b, c;
+ int i, j;
+
+ if (!w)
+ return "";
+ for (i = j = 0; i < sizeof enuf - 1; i++, j++) {
+ u = w[j];
+ if (u == 0)
+ break;
+ b = (unsigned char)(u >> 8);
+ c = (unsigned char)(u);
+ if (b) {
+ if (i >= sizeof enuf - 6)
+ break;
+ enuf[i++] = '\\';
+ enuf[i++] = 'u';
+ enuf[i++] = hex[b >> 4];
+ enuf[i++] = hex[b & 15];
+ enuf[i++] = hex[c >> 4];
+ enuf[i] = hex[c & 15];
+ } else if (!isprint(c)) {
+ if (i >= sizeof enuf - 4)
+ break;
+ enuf[i++] = '\\';
+ enuf[i++] = 'x';
+ enuf[i++] = hex[c >> 4];
+ enuf[i] = hex[c & 15];
+ } else {
+ enuf[i] = (char)c;
+ }
+ }
+ enuf[i] = 0;
+ return enuf;
+}
+
+#include <stdarg.h>
+
+static JSBool
+ZZ_formatter(JSContext *cx, const char *format, JSBool fromJS, jsval **vpp,
+ va_list *app)
+{
+ jsval *vp;
+ va_list ap;
+ jsdouble re, im;
+
+ printf("entering ZZ_formatter");
+ vp = *vpp;
+ ap = *app;
+ if (fromJS) {
+ if (!JS_ValueToNumber(cx, vp[0], &re))
+ return JS_FALSE;
+ if (!JS_ValueToNumber(cx, vp[1], &im))
+ return JS_FALSE;
+ *va_arg(ap, jsdouble *) = re;
+ *va_arg(ap, jsdouble *) = im;
+ } else {
+ re = va_arg(ap, jsdouble);
+ im = va_arg(ap, jsdouble);
+ if (!JS_NewNumberValue(cx, re, &vp[0]))
+ return JS_FALSE;
+ if (!JS_NewNumberValue(cx, im, &vp[1]))
+ return JS_FALSE;
+ }
+ *vpp = vp + 2;
+ *app = ap;
+ printf("leaving ZZ_formatter");
+ return JS_TRUE;
+}
+
+static JSBool
+ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSBool b = JS_FALSE;
+ jschar c = 0;
+ int32 i = 0, j = 0;
+ uint32 u = 0;
+ jsdouble d = 0, I = 0, re = 0, im = 0;
+ char *s = NULL;
+ JSString *str = NULL;
+ jschar *w = NULL;
+ JSObject *obj2 = NULL;
+ JSFunction *fun = NULL;
+ jsval v = JSVAL_VOID;
+ JSBool ok;
+
+ if (!JS_AddArgumentFormatter(cx, "ZZ", ZZ_formatter))
+ return JS_FALSE;;
+ ok = JS_ConvertArguments(cx, argc, argv, "b/ciujdIsSWofvZZ*",
+ &b, &c, &i, &u, &j, &d, &I, &s, &str, &w, &obj2,
+ &fun, &v, &re, &im);
+ JS_RemoveArgumentFormatter(cx, "ZZ");
+ if (!ok)
+ return JS_FALSE;
+ fprintf(gOutFile,
+ "b %u, c %x (%c), i %ld, u %lu, j %ld\n",
+ b, c, (char)c, i, u, j);
+ fprintf(gOutFile,
+ "d %g, I %g, s %s, S %s, W %s, obj %s, fun %s\n"
+ "v %s, re %g, im %g\n",
+ d, I, s, str ? JS_GetStringBytes(str) : "", EscapeWideString(w),
+ JS_GetStringBytes(JS_ValueToString(cx, OBJECT_TO_JSVAL(obj2))),
+ fun ? JS_GetStringBytes(JS_DecompileFunction(cx, fun, 4)) : "",
+ JS_GetStringBytes(JS_ValueToString(cx, v)), re, im);
+ return JS_TRUE;
+}
+#endif
+
+static JSBool
+BuildDate(JSContext *cx, uintN argc, jsval *vp)
+{
+ char version[20] = "\n";
+#if JS_VERSION < 150
+ sprintf(version, " for version %d\n", JS_VERSION);
+#endif
+ fprintf(gOutFile, "built on %s at %s%s", __DATE__, __TIME__, version);
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool
+Clear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if (argc != 0 && !JS_ValueToObject(cx, argv[0], &obj))
+ return JS_FALSE;
+ JS_ClearScope(cx, obj);
+ return JS_TRUE;
+}
+
+static JSBool
+Intern(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = JS_ValueToString(cx, argc == 0 ? JSVAL_VOID : vp[2]);
+ if (!str)
+ return JS_FALSE;
+ if (!JS_InternUCStringN(cx, JS_GetStringChars(str),
+ JS_GetStringLength(str))) {
+ return JS_FALSE;
+ }
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool
+Clone(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFunction *fun;
+ JSObject *funobj, *parent, *clone;
+
+ fun = JS_ValueToFunction(cx, argv[0]);
+ if (!fun)
+ return JS_FALSE;
+ funobj = JS_GetFunctionObject(fun);
+ if (argc > 1) {
+ if (!JS_ValueToObject(cx, argv[1], &parent))
+ return JS_FALSE;
+ } else {
+ parent = JS_GetParent(cx, funobj);
+ }
+ clone = JS_CloneFunctionObject(cx, funobj, parent);
+ if (!clone)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(clone);
+ return JS_TRUE;
+}
+
+static JSBool
+Seal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSObject *target;
+ JSBool deep = JS_FALSE;
+
+ if (!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
+ return JS_FALSE;
+ if (!target)
+ return JS_TRUE;
+ return JS_SealObject(cx, target, deep);
+}
+
+static JSBool
+GetPDA(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *vobj, *aobj, *pdobj;
+ JSBool ok;
+ JSPropertyDescArray pda;
+ JSPropertyDesc *pd;
+ uint32 i;
+ jsval v;
+
+ if (!JS_ValueToObject(cx, argc == 0 ? JSVAL_VOID : vp[2], &vobj))
+ return JS_FALSE;
+ if (!vobj)
+ return JS_TRUE;
+
+ aobj = JS_NewArrayObject(cx, 0, NULL);
+ if (!aobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(aobj);
+
+ ok = JS_GetPropertyDescArray(cx, vobj, &pda);
+ if (!ok)
+ return JS_FALSE;
+ pd = pda.array;
+ for (i = 0; i < pda.length; i++) {
+ pdobj = JS_NewObject(cx, NULL, NULL, NULL);
+ if (!pdobj) {
+ ok = JS_FALSE;
+ break;
+ }
+
+ /* Protect pdobj from GC by setting it as an element of aobj now */
+ v = OBJECT_TO_JSVAL(pdobj);
+ ok = JS_SetElement(cx, aobj, i, &v);
+ if (!ok)
+ break;
+
+ ok = JS_SetProperty(cx, pdobj, "id", &pd->id) &&
+ JS_SetProperty(cx, pdobj, "value", &pd->value) &&
+ (v = INT_TO_JSVAL(pd->flags),
+ JS_SetProperty(cx, pdobj, "flags", &v)) &&
+ (v = INT_TO_JSVAL(pd->slot),
+ JS_SetProperty(cx, pdobj, "slot", &v)) &&
+ JS_SetProperty(cx, pdobj, "alias", &pd->alias);
+ if (!ok)
+ break;
+ }
+ JS_PutPropertyDescArray(cx, &pda);
+ return ok;
+}
+
+static JSBool
+GetSLX(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSScript *script;
+
+ script = ValueToScript(cx, argc == 0 ? JSVAL_VOID : vp[2]);
+ if (!script)
+ return JS_FALSE;
+ *vp = INT_TO_JSVAL(js_GetScriptLineExtent(script));
+ return JS_TRUE;
+}
+
+static JSBool
+ToInt32(JSContext *cx, uintN argc, jsval *vp)
+{
+ int32 i;
+
+ if (!JS_ValueToInt32(cx, argc == 0 ? JSVAL_VOID : vp[2], &i))
+ return JS_FALSE;
+ return JS_NewNumberValue(cx, i, vp);
+}
+
+static JSBool
+StringsAreUTF8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ *rval = JS_CStringsAreUTF8() ? JSVAL_TRUE : JSVAL_FALSE;
+ return JS_TRUE;
+}
+
+static JSBool
+StackQuota(JSContext *cx, uintN argc, jsval *vp)
+{
+ uint32 n;
+
+ if (argc == 0)
+ return JS_NewNumberValue(cx, (double) gScriptStackQuota, vp);
+ if (!JS_ValueToECMAUint32(cx, JS_ARGV(cx, vp)[0], &n))
+ return JS_FALSE;
+ gScriptStackQuota = n;
+ JS_SetScriptStackQuota(cx, gScriptStackQuota);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
+}
+
+static const char* badUTF8 = "...\xC0...";
+static const char* bigUTF8 = "...\xFB\xBF\xBF\xBF\xBF...";
+static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
+
+static JSBool
+TestUTF8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ int32 mode = 1;
+ jschar chars[20];
+ size_t charsLength = 5;
+ char bytes[20];
+ size_t bytesLength = 20;
+ if (argc && !JS_ValueToInt32(cx, *argv, &mode))
+ return JS_FALSE;
+
+ /* The following throw errors if compiled with UTF-8. */
+ switch (mode) {
+ /* mode 1: malformed UTF-8 string. */
+ case 1:
+ JS_NewStringCopyZ(cx, badUTF8);
+ break;
+ /* mode 2: big UTF-8 character. */
+ case 2:
+ JS_NewStringCopyZ(cx, bigUTF8);
+ break;
+ /* mode 3: bad surrogate character. */
+ case 3:
+ JS_EncodeCharacters(cx, badSurrogate, 6, bytes, &bytesLength);
+ break;
+ /* mode 4: use a too small buffer. */
+ case 4:
+ JS_DecodeBytes(cx, "1234567890", 10, chars, &charsLength);
+ break;
+ default:
+ JS_ReportError(cx, "invalid mode parameter");
+ return JS_FALSE;
+ }
+ return !JS_IsExceptionPending (cx);
+}
+
+static JSBool
+ThrowError(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JS_ReportError(cx, "This is an error");
+ return JS_FALSE;
+}
+
+#define LAZY_STANDARD_CLASSES
+
+/* A class for easily testing the inner/outer object callbacks. */
+typedef struct ComplexObject {
+ JSBool isInner;
+ JSBool frozen;
+ JSObject *inner;
+ JSObject *outer;
+} ComplexObject;
+
+static JSObject *
+split_create_outer(JSContext *cx);
+
+static JSObject *
+split_create_inner(JSContext *cx, JSObject *outer);
+
+static ComplexObject *
+split_get_private(JSContext *cx, JSObject *obj);
+
+static JSBool
+split_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ ComplexObject *cpx;
+ jsid asId;
+
+ cpx = split_get_private(cx, obj);
+ if (!cpx)
+ return JS_TRUE;
+ if (!cpx->isInner && cpx->inner) {
+ /* Make sure to define this property on the inner object. */
+ if (!JS_ValueToId(cx, *vp, &asId))
+ return JS_FALSE;
+ return OBJ_DEFINE_PROPERTY(cx, cpx->inner, asId, *vp, NULL, NULL,
+ JSPROP_ENUMERATE, NULL);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+split_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ ComplexObject *cpx;
+
+ cpx = split_get_private(cx, obj);
+ if (!cpx)
+ return JS_TRUE;
+ if (!cpx->isInner && cpx->inner) {
+ if (JSVAL_IS_STRING(id)) {
+ JSString *str;
+
+ str = JSVAL_TO_STRING(id);
+ return JS_GetUCProperty(cx, cpx->inner, JS_GetStringChars(str),
+ JS_GetStringLength(str), vp);
+ }
+ if (JSVAL_IS_INT(id))
+ return JS_GetElement(cx, cpx->inner, JSVAL_TO_INT(id), vp);
+ return JS_TRUE;
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+split_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ ComplexObject *cpx;
+
+ cpx = split_get_private(cx, obj);
+ if (!cpx)
+ return JS_TRUE;
+ if (!cpx->isInner && cpx->inner) {
+ if (JSVAL_IS_STRING(id)) {
+ JSString *str;
+
+ str = JSVAL_TO_STRING(id);
+ return JS_SetUCProperty(cx, cpx->inner, JS_GetStringChars(str),
+ JS_GetStringLength(str), vp);
+ }
+ if (JSVAL_IS_INT(id))
+ return JS_SetElement(cx, cpx->inner, JSVAL_TO_INT(id), vp);
+ return JS_TRUE;
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+split_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ ComplexObject *cpx;
+ jsid asId;
+
+ cpx = split_get_private(cx, obj);
+ if (!cpx)
+ return JS_TRUE;
+ if (!cpx->isInner && cpx->inner) {
+ /* Make sure to define this property on the inner object. */
+ if (!JS_ValueToId(cx, *vp, &asId))
+ return JS_FALSE;
+ return OBJ_DELETE_PROPERTY(cx, cpx->inner, asId, vp);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+split_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ ComplexObject *cpx;
+ JSObject *iterator;
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+
+ if (!cpx->isInner && cpx->inner)
+ obj = cpx->inner;
+
+ iterator = JS_NewPropertyIterator(cx, obj);
+ if (!iterator)
+ return JS_FALSE;
+
+ *statep = OBJECT_TO_JSVAL(iterator);
+ if (idp)
+ *idp = JSVAL_ZERO;
+ break;
+
+ case JSENUMERATE_NEXT:
+ iterator = (JSObject*)JSVAL_TO_OBJECT(*statep);
+ if (!JS_NextProperty(cx, iterator, idp))
+ return JS_FALSE;
+
+ if (!JSVAL_IS_VOID(*idp))
+ break;
+ /* Fall through. */
+
+ case JSENUMERATE_DESTROY:
+ /* Let GC at our iterator object. */
+ *statep = JSVAL_NULL;
+ break;
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+split_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ ComplexObject *cpx;
+
+ cpx = split_get_private(cx, obj);
+ if (!cpx)
+ return JS_TRUE;
+ if (!cpx->isInner && cpx->inner) {
+ jsid asId;
+ JSProperty *prop;
+
+ if (!JS_ValueToId(cx, id, &asId))
+ return JS_FALSE;
+
+ if (!OBJ_LOOKUP_PROPERTY(cx, cpx->inner, asId, objp, &prop))
+ return JS_FALSE;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, cpx->inner, prop);
+
+ return JS_TRUE;
+ }
+
+#ifdef LAZY_STANDARD_CLASSES
+ if (!(flags & JSRESOLVE_ASSIGNING)) {
+ JSBool resolved;
+
+ if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
+ return JS_FALSE;
+
+ if (resolved) {
+ *objp = obj;
+ return JS_TRUE;
+ }
+ }
+#endif
+
+ /* XXX For additional realism, let's resolve some random property here. */
+ return JS_TRUE;
+}
+
+static void
+split_finalize(JSContext *cx, JSObject *obj)
+{
+ JS_free(cx, JS_GetPrivate(cx, obj));
+}
+
+static uint32
+split_mark(JSContext *cx, JSObject *obj, void *arg)
+{
+ ComplexObject *cpx;
+
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+
+ if (!cpx->isInner && cpx->inner) {
+ /* Mark the inner object. */
+ JS_MarkGCThing(cx, cpx->inner, "ComplexObject.inner", arg);
+ }
+
+ return 0;
+}
+
+static JSObject *
+split_outerObject(JSContext *cx, JSObject *obj)
+{
+ ComplexObject *cpx;
+
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+ return cpx->isInner ? cpx->outer : obj;
+}
+
+static JSObject *
+split_innerObject(JSContext *cx, JSObject *obj)
+{
+ ComplexObject *cpx;
+
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+ if (cpx->frozen) {
+ JS_ASSERT(!cpx->isInner);
+ return obj;
+ }
+ return !cpx->isInner ? cpx->inner : obj;
+}
+
+static JSExtendedClass split_global_class = {
+ {"split_global",
+ JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_HAS_PRIVATE |
+ JSCLASS_GLOBAL_FLAGS | JSCLASS_IS_EXTENDED,
+ split_addProperty, split_delProperty,
+ split_getProperty, split_setProperty,
+ (JSEnumerateOp)split_enumerate,
+ (JSResolveOp)split_resolve,
+ JS_ConvertStub, split_finalize,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ split_mark, NULL},
+ NULL, split_outerObject, split_innerObject,
+ NULL, NULL, NULL, NULL, NULL
+};
+
+JSObject *
+split_create_outer(JSContext *cx)
+{
+ ComplexObject *cpx;
+ JSObject *obj;
+
+ cpx = (ComplexObject *) JS_malloc(cx, sizeof *obj);
+ if (!cpx)
+ return NULL;
+ cpx->isInner = JS_FALSE;
+ cpx->frozen = JS_TRUE;
+ cpx->inner = NULL;
+ cpx->outer = NULL;
+
+ obj = JS_NewObject(cx, &split_global_class.base, NULL, NULL);
+ if (!obj || !JS_SetParent(cx, obj, NULL)) {
+ JS_free(cx, cpx);
+ return NULL;
+ }
+
+ if (!JS_SetPrivate(cx, obj, cpx)) {
+ JS_free(cx, cpx);
+ return NULL;
+ }
+
+ return obj;
+}
+
+static JSObject *
+split_create_inner(JSContext *cx, JSObject *outer)
+{
+ ComplexObject *cpx, *outercpx;
+ JSObject *obj;
+
+ JS_ASSERT(JS_GET_CLASS(cx, outer) == &split_global_class.base);
+
+ cpx = (ComplexObject *) JS_malloc(cx, sizeof *cpx);
+ if (!cpx)
+ return NULL;
+ cpx->isInner = JS_TRUE;
+ cpx->frozen = JS_FALSE;
+ cpx->inner = NULL;
+ cpx->outer = outer;
+
+ obj = JS_NewObject(cx, &split_global_class.base, NULL, NULL);
+ if (!obj || !JS_SetParent(cx, obj, NULL) || !JS_SetPrivate(cx, obj, cpx)) {
+ JS_free(cx, cpx);
+ return NULL;
+ }
+
+ outercpx = (ComplexObject *) JS_GetPrivate(cx, outer);
+ outercpx->inner = obj;
+ outercpx->frozen = JS_FALSE;
+
+ return obj;
+}
+
+static ComplexObject *
+split_get_private(JSContext *cx, JSObject *obj)
+{
+ do {
+ if (JS_GET_CLASS(cx, obj) == &split_global_class.base)
+ return (ComplexObject *) JS_GetPrivate(cx, obj);
+ obj = JS_GetParent(cx, obj);
+ } while (obj);
+
+ return NULL;
+}
+
+static JSBool
+sandbox_enumerate(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+ JSBool b;
+
+ if (!JS_GetProperty(cx, obj, "lazy", &v) || !JS_ValueToBoolean(cx, v, &b))
+ return JS_FALSE;
+ return !b || JS_EnumerateStandardClasses(cx, obj);
+}
+
+static JSBool
+sandbox_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ jsval v;
+ JSBool b, resolved;
+
+ if (!JS_GetProperty(cx, obj, "lazy", &v) || !JS_ValueToBoolean(cx, v, &b))
+ return JS_FALSE;
+ if (b && (flags & JSRESOLVE_ASSIGNING) == 0) {
+ if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
+ return JS_FALSE;
+ if (resolved) {
+ *objp = obj;
+ return JS_TRUE;
+ }
+ }
+ *objp = NULL;
+ return JS_TRUE;
+}
+
+static JSClass sandbox_class = {
+ "sandbox",
+ JSCLASS_NEW_RESOLVE,
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, JS_PropertyStub,
+ sandbox_enumerate, (JSResolveOp)sandbox_resolve,
+ JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+EvalInContext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSString *str;
+ JSObject *sobj;
+ JSContext *scx;
+ const jschar *src;
+ size_t srclen;
+ JSBool lazy, ok;
+ jsval v;
+ JSStackFrame *fp;
+
+ sobj = NULL;
+ if (!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sobj))
+ return JS_FALSE;
+
+ scx = JS_NewContext(JS_GetRuntime(cx), gStackChunkSize);
+ if (!scx) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+#ifdef JS_THREADSAFE
+ JS_BeginRequest(scx);
+#endif
+ src = JS_GetStringChars(str);
+ srclen = JS_GetStringLength(str);
+ lazy = JS_FALSE;
+ if (srclen == 4 &&
+ src[0] == 'l' && src[1] == 'a' && src[2] == 'z' && src[3] == 'y') {
+ lazy = JS_TRUE;
+ srclen = 0;
+ }
+
+ if (!sobj) {
+ sobj = JS_NewObject(scx, &sandbox_class, NULL, NULL);
+ if (!sobj || (!lazy && !JS_InitStandardClasses(scx, sobj))) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ v = BOOLEAN_TO_JSVAL(lazy);
+ ok = JS_SetProperty(cx, sobj, "lazy", &v);
+ if (!ok)
+ goto out;
+ }
+
+ if (srclen == 0) {
+ *rval = OBJECT_TO_JSVAL(sobj);
+ ok = JS_TRUE;
+ } else {
+ fp = JS_GetScriptedCaller(cx, NULL);
+ JS_SetGlobalObject(scx, sobj);
+ JS_ToggleOptions(scx, JSOPTION_DONT_REPORT_UNCAUGHT);
+ ok = JS_EvaluateUCScript(scx, sobj, src, srclen,
+ fp->script->filename,
+ JS_PCToLineNumber(cx, fp->script,
+ fp->regs->pc),
+ rval);
+ if (!ok) {
+ if (JS_GetPendingException(scx, &v))
+ JS_SetPendingException(cx, v);
+ else
+ JS_ReportOutOfMemory(cx);
+ }
+ }
+
+out:
+#ifdef JS_THREADSAFE
+ JS_EndRequest(scx);
+#endif
+ JS_DestroyContext(scx);
+ return ok;
+}
+
+static int32 JS_FASTCALL
+ShapeOf_tn(JSObject *obj)
+{
+ if (!obj)
+ return 0;
+ if (!OBJ_IS_NATIVE(obj))
+ return -1;
+ return OBJ_SHAPE(obj);
+}
+
+static JSBool
+ShapeOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v = JS_ARGV(cx, vp)[0];
+ if (!JSVAL_IS_OBJECT(v)) {
+ JS_ReportError(cx, "shapeOf: object expected");
+ return JS_FALSE;
+ }
+ return JS_NewNumberValue(cx, ShapeOf_tn(JSVAL_TO_OBJECT(v)), vp);
+}
+
+#ifdef JS_THREADSAFE
+
+static JSBool
+Sleep_fn(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble t_secs;
+ PRUint32 t_ticks;
+ jsrefcount rc;
+
+ if (!JS_ValueToNumber(cx, argc == 0 ? JSVAL_VOID : vp[2], &t_secs))
+ return JS_FALSE;
+
+ if (t_secs < 0 || JSDOUBLE_IS_NaN(t_secs))
+ t_secs = 0;
+
+ rc = JS_SuspendRequest(cx);
+ t_ticks = (PRUint32)(PR_TicksPerSecond() * t_secs);
+ if (PR_Sleep(t_ticks) == PR_SUCCESS)
+ *vp = JSVAL_TRUE;
+ else
+ *vp = JSVAL_FALSE;
+ JS_ResumeRequest(cx, rc);
+ return JS_TRUE;
+}
+
+typedef struct ScatterThreadData ScatterThreadData;
+typedef struct ScatterData ScatterData;
+
+typedef enum ScatterStatus {
+ SCATTER_WAIT,
+ SCATTER_GO,
+ SCATTER_CANCEL
+} ScatterStatus;
+
+struct ScatterData {
+ ScatterThreadData *threads;
+ jsval *results;
+ PRLock *lock;
+ PRCondVar *cvar;
+ ScatterStatus status;
+};
+
+struct ScatterThreadData {
+ jsint index;
+ ScatterData *shared;
+ PRThread *thr;
+ JSContext *cx;
+ jsval fn;
+};
+
+static void
+DoScatteredWork(JSContext *cx, ScatterThreadData *td)
+{
+ jsval *rval = &td->shared->results[td->index];
+
+ if (!JS_CallFunctionValue(cx, NULL, td->fn, 0, NULL, rval)) {
+ *rval = JSVAL_VOID;
+ JS_GetPendingException(cx, rval);
+ JS_ClearPendingException(cx);
+ }
+}
+
+static void
+RunScatterThread(void *arg)
+{
+ ScatterThreadData *td;
+ ScatterStatus st;
+ JSContext *cx;
+
+ td = (ScatterThreadData *)arg;
+ cx = td->cx;
+
+ /* Wait for go signal. */
+ PR_Lock(td->shared->lock);
+ while ((st = td->shared->status) == SCATTER_WAIT)
+ PR_WaitCondVar(td->shared->cvar, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(td->shared->lock);
+
+ if (st == SCATTER_CANCEL)
+ return;
+
+ /* We are go. */
+ JS_SetContextThread(cx);
+ JS_SetThreadStackLimit(cx, 0);
+ JS_BeginRequest(cx);
+ DoScatteredWork(cx, td);
+ JS_EndRequest(cx);
+ JS_ClearContextThread(cx);
+}
+
+/*
+ * scatter(fnArray) - Call each function in `fnArray` without arguments, each
+ * in a different thread. When all threads have finished, return an array: the
+ * return values. Errors are not propagated; if any of the function calls
+ * fails, the corresponding element in the results array gets the exception
+ * object, if any, else (undefined).
+ */
+static JSBool
+Scatter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsuint i;
+ jsuint n; /* number of threads */
+ JSObject *inArr;
+ JSObject *arr;
+ ScatterData sd;
+ JSBool ok;
+ jsrefcount rc;
+
+ if (!gEnableBranchCallback) {
+ /* Enable the branch callback, for periodic scope-sharing. */
+ gEnableBranchCallback = JS_TRUE;
+ JS_SetBranchCallback(cx, my_BranchCallback);
+ JS_ToggleOptions(cx, JSOPTION_NATIVE_BRANCH_CALLBACK);
+ }
+
+ sd.lock = NULL;
+ sd.cvar = NULL;
+ sd.results = NULL;
+ sd.threads = NULL;
+ sd.status = SCATTER_WAIT;
+
+ if (argc == 0 || JSVAL_IS_PRIMITIVE(JS_ARGV(cx, vp)[0])) {
+ JS_ReportError(cx, "the first argument must be an object");
+ goto fail;
+ }
+
+ inArr = JSVAL_TO_OBJECT(JS_ARGV(cx, vp)[0]);
+ ok = JS_GetArrayLength(cx, inArr, &n);
+ if (!ok)
+ goto out;
+ if (n == 0)
+ goto success;
+
+ sd.lock = PR_NewLock();
+ if (!sd.lock)
+ goto fail;
+
+ sd.cvar = PR_NewCondVar(sd.lock);
+ if (!sd.cvar)
+ goto fail;
+
+ sd.results = (jsval *) malloc(n * sizeof(jsval));
+ if (!sd.results)
+ goto fail;
+ for (i = 0; i < n; i++) {
+ sd.results[i] = JSVAL_VOID;
+ ok = JS_AddRoot(cx, &sd.results[i]);
+ if (!ok) {
+ while (i-- > 0)
+ JS_RemoveRoot(cx, &sd.results[i]);
+ free(sd.results);
+ sd.results = NULL;
+ goto fail;
+ }
+ }
+
+ sd.threads = (ScatterThreadData *) malloc(n * sizeof(ScatterThreadData));
+ if (!sd.threads)
+ goto fail;
+ for (i = 0; i < n; i++) {
+ sd.threads[i].index = i;
+ sd.threads[i].shared = &sd;
+ sd.threads[i].thr = NULL;
+ sd.threads[i].cx = NULL;
+ sd.threads[i].fn = JSVAL_NULL;
+
+ ok = JS_AddRoot(cx, &sd.threads[i].fn);
+ if (ok && !JS_GetElement(cx, inArr, (jsint) i, &sd.threads[i].fn)) {
+ JS_RemoveRoot(cx, &sd.threads[i].fn);
+ ok = JS_FALSE;
+ }
+ if (!ok) {
+ while (i-- > 0)
+ JS_RemoveRoot(cx, &sd.threads[i].fn);
+ free(sd.threads);
+ sd.threads = NULL;
+ goto fail;
+ }
+ }
+
+ for (i = 1; i < n; i++) {
+ JSContext *newcx = JS_NewContext(JS_GetRuntime(cx), 8192);
+ if (!newcx)
+ goto fail;
+ JS_SetGlobalObject(newcx, JS_GetGlobalObject(cx));
+ JS_ClearContextThread(newcx);
+ sd.threads[i].cx = newcx;
+ }
+
+ for (i = 1; i < n; i++) {
+ PRThread *t = PR_CreateThread(PR_USER_THREAD,
+ RunScatterThread,
+ &sd.threads[i],
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!t) {
+ /* Failed to start thread. */
+ PR_Lock(sd.lock);
+ sd.status = SCATTER_CANCEL;
+ PR_NotifyAllCondVar(sd.cvar);
+ PR_Unlock(sd.lock);
+ while (i-- > 1)
+ PR_JoinThread(sd.threads[i].thr);
+ goto fail;
+ }
+
+ sd.threads[i].thr = t;
+ }
+ PR_Lock(sd.lock);
+ sd.status = SCATTER_GO;
+ PR_NotifyAllCondVar(sd.cvar);
+ PR_Unlock(sd.lock);
+
+ DoScatteredWork(cx, &sd.threads[0]);
+
+ rc = JS_SuspendRequest(cx);
+ for (i = 1; i < n; i++) {
+ PR_JoinThread(sd.threads[i].thr);
+ }
+ JS_ResumeRequest(cx, rc);
+
+success:
+ arr = JS_NewArrayObject(cx, n, sd.results);
+ if (!arr)
+ goto fail;
+ *vp = OBJECT_TO_JSVAL(arr);
+ ok = JS_TRUE;
+
+out:
+ if (sd.threads) {
+ JSContext *acx;
+
+ for (i = 0; i < n; i++) {
+ JS_RemoveRoot(cx, &sd.threads[i].fn);
+ acx = sd.threads[i].cx;
+ if (acx) {
+ JS_SetContextThread(acx);
+ JS_DestroyContext(acx);
+ }
+ }
+ free(sd.threads);
+ }
+ if (sd.results) {
+ for (i = 0; i < n; i++)
+ JS_RemoveRoot(cx, &sd.results[i]);
+ free(sd.results);
+ }
+ if (sd.cvar)
+ PR_DestroyCondVar(sd.cvar);
+ if (sd.lock)
+ PR_DestroyLock(sd.lock);
+
+ return ok;
+
+fail:
+ ok = JS_FALSE;
+ goto out;
+}
+
+#endif
+
+JS_DEFINE_TRCINFO_1(Print, (2, (static, JSVAL_FAIL, Print_tn, CONTEXT, STRING, 0, 0)))
+JS_DEFINE_TRCINFO_1(ShapeOf, (1, (static, INT32, ShapeOf_tn, OBJECT, 0, 0)))
+
+/* We use a mix of JS_FS and JS_FN to test both kinds of natives. */
+static JSFunctionSpec shell_functions[] = {
+ JS_FS("version", Version, 0,0,0),
+ JS_FS("options", Options, 0,0,0),
+ JS_FS("load", Load, 1,0,0),
+ JS_FN("readline", ReadLine, 0,0),
+ JS_TN("print", Print, 0,0, Print_trcinfo),
+ JS_FS("help", Help, 0,0,0),
+ JS_FS("quit", Quit, 0,0,0),
+ JS_FN("gc", GC, 0,0),
+ JS_FN("gcparam", GCParameter, 2,0),
+ JS_FN("countHeap", CountHeap, 0,0),
+#ifdef JS_GC_ZEAL
+ JS_FN("gczeal", GCZeal, 1,0),
+#endif
+ JS_FS("trap", Trap, 3,0,0),
+ JS_FS("untrap", Untrap, 2,0,0),
+ JS_FS("line2pc", LineToPC, 0,0,0),
+ JS_FS("pc2line", PCToLine, 0,0,0),
+ JS_FN("stackQuota", StackQuota, 0,0),
+ JS_FS("stringsAreUTF8", StringsAreUTF8, 0,0,0),
+ JS_FS("testUTF8", TestUTF8, 1,0,0),
+ JS_FS("throwError", ThrowError, 0,0,0),
+#ifdef DEBUG
+ JS_FS("dis", Disassemble, 1,0,0),
+ JS_FS("disfile", DisassFile, 1,0,0),
+ JS_FS("dissrc", DisassWithSrc, 1,0,0),
+ JS_FN("dumpHeap", DumpHeap, 0,0),
+ JS_FS("notes", Notes, 1,0,0),
+ JS_FS("tracing", Tracing, 0,0,0),
+ JS_FS("stats", DumpStats, 1,0,0),
+#endif
+#ifdef TEST_CVTARGS
+ JS_FS("cvtargs", ConvertArgs, 0,0,12),
+#endif
+ JS_FN("build", BuildDate, 0,0),
+ JS_FS("clear", Clear, 0,0,0),
+ JS_FN("intern", Intern, 1,0),
+ JS_FS("clone", Clone, 1,0,0),
+ JS_FS("seal", Seal, 1,0,1),
+ JS_FN("getpda", GetPDA, 1,0),
+ JS_FN("getslx", GetSLX, 1,0),
+ JS_FN("toint32", ToInt32, 1,0),
+ JS_FS("evalcx", EvalInContext, 1,0,0),
+ JS_TN("shapeOf", ShapeOf, 1,0, ShapeOf_trcinfo),
+#ifdef MOZ_SHARK
+ JS_FS("startShark", js_StartShark, 0,0,0),
+ JS_FS("stopShark", js_StopShark, 0,0,0),
+ JS_FS("connectShark", js_ConnectShark, 0,0,0),
+ JS_FS("disconnectShark", js_DisconnectShark, 0,0,0),
+#endif
+#ifdef MOZ_CALLGRIND
+ JS_FS("startCallgrind", js_StartCallgrind, 0,0,0),
+ JS_FS("stopCallgrind", js_StopCallgrind, 0,0,0),
+ JS_FS("dumpCallgrind", js_DumpCallgrind, 1,0,0),
+#endif
+#ifdef MOZ_VTUNE
+ JS_FS("startVtune", js_StartVtune, 1,0,0),
+ JS_FS("stopVtune", js_StopVtune, 0,0,0),
+ JS_FS("pauseVtune", js_PauseVtune, 0,0,0),
+ JS_FS("resumeVtune", js_ResumeVtune, 0,0,0),
+#endif
+#ifdef DEBUG_ARRAYS
+ JS_FS("arrayInfo", js_ArrayInfo, 1,0,0),
+#endif
+#ifdef JS_THREADSAFE
+ JS_FN("sleep", Sleep_fn, 1,0),
+ JS_FN("scatter", Scatter, 1,0),
+#endif
+ JS_FS_END
+};
+
+static const char shell_help_header[] =
+"Command Description\n"
+"======= ===========\n";
+
+static const char *const shell_help_messages[] = {
+"version([number]) Get or set JavaScript version number",
+"options([option ...]) Get or toggle JavaScript options",
+"load(['foo.js' ...]) Load files named by string arguments",
+"readline() Read a single line from stdin",
+"print([exp ...]) Evaluate and print expressions",
+"help([name ...]) Display usage and help messages",
+"quit() Quit the shell",
+"gc() Run the garbage collector",
+"gcparam(name, value)\n"
+" Wrapper for JS_SetGCParameter. The name must be either 'maxBytes' or\n"
+" 'maxMallocBytes' and the value must be convertable to a positive uint32",
+"countHeap([start[, kind]])\n"
+" Count the number of live GC things in the heap or things reachable from\n"
+" start when it is given and is not null. kind is either 'all' (default) to\n"
+" count all things or one of 'object', 'double', 'string', 'function',\n"
+" 'qname', 'namespace', 'xml' to count only things of that kind",
+#ifdef JS_GC_ZEAL
+"gczeal(level) How zealous the garbage collector should be",
+#endif
+"trap([fun, [pc,]] exp) Trap bytecode execution",
+"untrap(fun[, pc]) Remove a trap",
+"line2pc([fun,] line) Map line number to PC",
+"pc2line(fun[, pc]) Map PC to line number",
+"stackQuota([number]) Query/set script stack quota",
+"stringsAreUTF8() Check if strings are UTF-8 encoded",
+"testUTF8(mode) Perform UTF-8 tests (modes are 1 to 4)",
+"throwError() Throw an error from JS_ReportError",
+#ifdef DEBUG
+"dis([fun]) Disassemble functions into bytecodes",
+"disfile('foo.js') Disassemble script file into bytecodes",
+"dissrc([fun]) Disassemble functions with source lines",
+"dumpHeap([fileName[, start[, toFind[, maxDepth[, toIgnore]]]]])\n"
+" Interface to JS_DumpHeap with output sent to file",
+"notes([fun]) Show source notes for functions",
+"tracing([toggle]) Turn tracing on or off",
+"stats([string ...]) Dump 'arena', 'atom', 'global' stats",
+#endif
+#ifdef TEST_CVTARGS
+"cvtargs(arg1..., arg12) Test argument formatter",
+#endif
+"build() Show build date and time",
+"clear([obj]) Clear properties of object",
+"intern(str) Internalize str in the atom table",
+"clone(fun[, scope]) Clone function object",
+"seal(obj[, deep]) Seal object, or object graph if deep",
+"getpda(obj) Get the property descriptors for obj",
+"getslx(obj) Get script line extent",
+"toint32(n) Testing hook for JS_ValueToInt32",
+"evalcx(s[, o])\n"
+" Evaluate s in optional sandbox object o\n"
+" if (s == '' && !o) return new o with eager standard classes\n"
+" if (s == 'lazy' && !o) return new o with lazy standard classes",
+"shapeOf(obj) Get the shape of obj (an implementation detail)",
+#ifdef MOZ_SHARK
+"startShark() Start a Shark session.\n"
+" Shark must be running with programatic sampling.",
+"stopShark() Stop a running Shark session.",
+"connectShark() Connect to Shark.\n"
+" The -k switch does this automatically.",
+"disconnectShark() Disconnect from Shark.",
+#endif
+#ifdef MOZ_CALLGRIND
+"startCallgrind() Start callgrind instrumentation.\n",
+"stopCallgrind() Stop callgrind instumentation.",
+"dumpCallgrind([name]) Dump callgrind counters.\n",
+#endif
+#ifdef MOZ_VTUNE
+"startVtune([filename]) Start vtune instrumentation.\n",
+"stopVtune() Stop vtune instumentation.",
+"pauseVtune() Pause vtune collection.\n",
+"resumeVtune() Resume vtune collection.\n",
+#endif
+#ifdef DEBUG_ARRAYS
+"arrayInfo(a1, a2, ...) Report statistics about arrays.",
+#endif
+#ifdef JS_THREADSAFE
+"sleep(dt) Sleep for dt seconds",
+"scatter(fns) Call functions concurrently (ignoring errors)",
+#endif
+};
+
+/* Help messages must match shell functions. */
+JS_STATIC_ASSERT(JS_ARRAY_LENGTH(shell_help_messages) + 1 ==
+ JS_ARRAY_LENGTH(shell_functions));
+
+#ifdef DEBUG
+static void
+CheckHelpMessages()
+{
+ const char *const *m;
+ const char *lp;
+
+ /* Each message must begin with "function_name(" prefix. */
+ for (m = shell_help_messages; m != JS_ARRAY_END(shell_help_messages); ++m) {
+ lp = strchr(*m, '(');
+ JS_ASSERT(lp);
+ JS_ASSERT(memcmp(shell_functions[m - shell_help_messages].name,
+ *m, lp - *m) == 0);
+ }
+}
+#else
+# define CheckHelpMessages() ((void) 0)
+#endif
+
+static JSBool
+Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uintN i, j;
+ int did_header, did_something;
+ JSType type;
+ JSFunction *fun;
+ JSString *str;
+ const char *bytes;
+
+ fprintf(gOutFile, "%s\n", JS_GetImplementationVersion());
+ if (argc == 0) {
+ fputs(shell_help_header, gOutFile);
+ for (i = 0; shell_functions[i].name; i++)
+ fprintf(gOutFile, "%s\n", shell_help_messages[i]);
+ } else {
+ did_header = 0;
+ for (i = 0; i < argc; i++) {
+ did_something = 0;
+ type = JS_TypeOfValue(cx, argv[i]);
+ if (type == JSTYPE_FUNCTION) {
+ fun = JS_ValueToFunction(cx, argv[i]);
+ str = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
+ } else if (type == JSTYPE_STRING) {
+ str = JSVAL_TO_STRING(argv[i]);
+ } else {
+ str = NULL;
+ }
+ if (str) {
+ bytes = JS_GetStringBytes(str);
+ for (j = 0; shell_functions[j].name; j++) {
+ if (!strcmp(bytes, shell_functions[j].name)) {
+ if (!did_header) {
+ did_header = 1;
+ fputs(shell_help_header, gOutFile);
+ }
+ did_something = 1;
+ fprintf(gOutFile, "%s\n", shell_help_messages[j]);
+ break;
+ }
+ }
+ }
+ if (!did_something) {
+ str = JS_ValueToString(cx, argv[i]);
+ if (!str)
+ return JS_FALSE;
+ fprintf(gErrFile, "Sorry, no help for %s\n",
+ JS_GetStringBytes(str));
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSObject *
+split_setup(JSContext *cx)
+{
+ JSObject *outer, *inner, *arguments;
+
+ outer = split_create_outer(cx);
+ if (!outer)
+ return NULL;
+ JS_SetGlobalObject(cx, outer);
+
+ inner = split_create_inner(cx, outer);
+ if (!inner)
+ return NULL;
+
+ if (!JS_DefineFunctions(cx, inner, shell_functions))
+ return NULL;
+ JS_ClearScope(cx, outer);
+
+ /* Create a dummy arguments object. */
+ arguments = JS_NewArrayObject(cx, 0, NULL);
+ if (!arguments ||
+ !JS_DefineProperty(cx, inner, "arguments", OBJECT_TO_JSVAL(arguments),
+ NULL, NULL, 0)) {
+ return NULL;
+ }
+
+#ifndef LAZY_STANDARD_CLASSES
+ if (!JS_InitStandardClasses(cx, inner))
+ return NULL;
+#endif
+
+ return inner;
+}
+
+/*
+ * Define a JS object called "it". Give it class operations that printf why
+ * they're being called for tutorial purposes.
+ */
+enum its_tinyid {
+ ITS_COLOR, ITS_HEIGHT, ITS_WIDTH, ITS_FUNNY, ITS_ARRAY, ITS_RDONLY
+};
+
+static JSPropertySpec its_props[] = {
+ {"color", ITS_COLOR, JSPROP_ENUMERATE, NULL, NULL},
+ {"height", ITS_HEIGHT, JSPROP_ENUMERATE, NULL, NULL},
+ {"width", ITS_WIDTH, JSPROP_ENUMERATE, NULL, NULL},
+ {"funny", ITS_FUNNY, JSPROP_ENUMERATE, NULL, NULL},
+ {"array", ITS_ARRAY, JSPROP_ENUMERATE, NULL, NULL},
+ {"rdonly", ITS_RDONLY, JSPROP_READONLY, NULL, NULL},
+ {NULL,0,0,NULL,NULL}
+};
+
+static JSBool
+its_item(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ *rval = OBJECT_TO_JSVAL(obj);
+ if (argc != 0)
+ JS_SetCallReturnValue2(cx, argv[0]);
+ return JS_TRUE;
+}
+
+static JSBool
+its_bindMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ char *name;
+ JSObject *method;
+
+ if (!JS_ConvertArguments(cx, argc, argv, "so", &name, &method))
+ return JS_FALSE;
+
+ *rval = OBJECT_TO_JSVAL(method);
+
+ if (JS_TypeOfValue(cx, *rval) != JSTYPE_FUNCTION) {
+ JSString *valstr = JS_ValueToString(cx, *rval);
+ if (valstr) {
+ JS_ReportError(cx, "can't bind method %s to non-callable object %s",
+ name, JS_GetStringBytes(valstr));
+ }
+ return JS_FALSE;
+ }
+
+ if (!JS_DefineProperty(cx, obj, name, *rval, NULL, NULL, JSPROP_ENUMERATE))
+ return JS_FALSE;
+
+ return JS_SetParent(cx, method, obj);
+}
+
+static JSFunctionSpec its_methods[] = {
+ {"item", its_item, 0,0,0},
+ {"bindMethod", its_bindMethod, 2,0,0},
+ {NULL,NULL,0,0,0}
+};
+
+#ifdef JSD_LOWLEVEL_SOURCE
+/*
+ * This facilitates sending source to JSD (the debugger system) in the shell
+ * where the source is loaded using the JSFILE hack in jsscan. The function
+ * below is used as a callback for the jsdbgapi JS_SetSourceHandler hook.
+ * A more normal embedding (e.g. mozilla) loads source itself and can send
+ * source directly to JSD without using this hook scheme.
+ */
+static void
+SendSourceToJSDebugger(const char *filename, uintN lineno,
+ jschar *str, size_t length,
+ void **listenerTSData, JSDContext* jsdc)
+{
+ JSDSourceText *jsdsrc = (JSDSourceText *) *listenerTSData;
+
+ if (!jsdsrc) {
+ if (!filename)
+ filename = "typein";
+ if (1 == lineno) {
+ jsdsrc = JSD_NewSourceText(jsdc, filename);
+ } else {
+ jsdsrc = JSD_FindSourceForURL(jsdc, filename);
+ if (jsdsrc && JSD_SOURCE_PARTIAL !=
+ JSD_GetSourceStatus(jsdc, jsdsrc)) {
+ jsdsrc = NULL;
+ }
+ }
+ }
+ if (jsdsrc) {
+ jsdsrc = JSD_AppendUCSourceText(jsdc,jsdsrc, str, length,
+ JSD_SOURCE_PARTIAL);
+ }
+ *listenerTSData = jsdsrc;
+}
+#endif /* JSD_LOWLEVEL_SOURCE */
+
+static JSBool its_noisy; /* whether to be noisy when finalizing it */
+static JSBool its_enum_fail;/* whether to fail when enumerating it */
+
+static JSBool
+its_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ if (its_noisy) {
+ fprintf(gOutFile, "adding its property %s,",
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
+ fprintf(gOutFile, " initial value %s\n",
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+its_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ if (its_noisy) {
+ fprintf(gOutFile, "deleting its property %s,",
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
+ fprintf(gOutFile, " current value %s\n",
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+its_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ if (its_noisy) {
+ fprintf(gOutFile, "getting its property %s,",
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
+ fprintf(gOutFile, " current value %s\n",
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+its_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ char *str;
+ if (its_noisy) {
+ fprintf(gOutFile, "setting its property %s,",
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
+ fprintf(gOutFile, " new value %s\n",
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+ }
+
+ if (!JSVAL_IS_STRING(id))
+ return JS_TRUE;
+
+ str = JS_GetStringBytes(JSVAL_TO_STRING(id));
+ if (!strcmp(str, "noisy"))
+ return JS_ValueToBoolean(cx, *vp, &its_noisy);
+ else if (!strcmp(str, "enum_fail"))
+ return JS_ValueToBoolean(cx, *vp, &its_enum_fail);
+
+ return JS_TRUE;
+}
+
+/*
+ * Its enumerator, implemented using the "new" enumerate API,
+ * see class flags.
+ */
+static JSBool
+its_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ JSObject *iterator;
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ if (its_noisy)
+ fprintf(gOutFile, "enumerate its properties\n");
+
+ iterator = JS_NewPropertyIterator(cx, obj);
+ if (!iterator)
+ return JS_FALSE;
+
+ *statep = OBJECT_TO_JSVAL(iterator);
+ if (idp)
+ *idp = JSVAL_ZERO;
+ break;
+
+ case JSENUMERATE_NEXT:
+ if (its_enum_fail) {
+ JS_ReportError(cx, "its enumeration failed");
+ return JS_FALSE;
+ }
+
+ iterator = (JSObject *) JSVAL_TO_OBJECT(*statep);
+ if (!JS_NextProperty(cx, iterator, idp))
+ return JS_FALSE;
+
+ if (!JSVAL_IS_VOID(*idp))
+ break;
+ /* Fall through. */
+
+ case JSENUMERATE_DESTROY:
+ /* Allow our iterator object to be GC'd. */
+ *statep = JSVAL_NULL;
+ break;
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+its_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ if (its_noisy) {
+ fprintf(gOutFile, "resolving its property %s, flags {%s,%s,%s}\n",
+ JS_GetStringBytes(JS_ValueToString(cx, id)),
+ (flags & JSRESOLVE_QUALIFIED) ? "qualified" : "",
+ (flags & JSRESOLVE_ASSIGNING) ? "assigning" : "",
+ (flags & JSRESOLVE_DETECTING) ? "detecting" : "");
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+its_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+{
+ if (its_noisy)
+ fprintf(gOutFile, "converting it to %s type\n", JS_GetTypeName(cx, type));
+ return JS_TRUE;
+}
+
+static void
+its_finalize(JSContext *cx, JSObject *obj)
+{
+ if (its_noisy)
+ fprintf(gOutFile, "finalizing it\n");
+}
+
+static JSClass its_class = {
+ "It", JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE,
+ its_addProperty, its_delProperty, its_getProperty, its_setProperty,
+ (JSEnumerateOp)its_enumerate, (JSResolveOp)its_resolve,
+ its_convert, its_finalize,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+JSErrorFormatString jsShell_ErrorFormatString[JSErr_Limit] = {
+#define MSG_DEF(name, number, count, exception, format) \
+ { format, count, JSEXN_ERR } ,
+#include "jsshell.msg"
+#undef MSG_DEF
+};
+
+static const JSErrorFormatString *
+my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
+{
+ if ((errorNumber > 0) && (errorNumber < JSShellErr_Limit))
+ return &jsShell_ErrorFormatString[errorNumber];
+ return NULL;
+}
+
+static void
+my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
+{
+ int i, j, k, n;
+ char *prefix, *tmp;
+ const char *ctmp;
+
+ if (!report) {
+ fprintf(gErrFile, "%s\n", message);
+ return;
+ }
+
+ /* Conditionally ignore reported warnings. */
+ if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
+ return;
+
+ prefix = NULL;
+ if (report->filename)
+ prefix = JS_smprintf("%s:", report->filename);
+ if (report->lineno) {
+ tmp = prefix;
+ prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
+ JS_free(cx, tmp);
+ }
+ if (JSREPORT_IS_WARNING(report->flags)) {
+ tmp = prefix;
+ prefix = JS_smprintf("%s%swarning: ",
+ tmp ? tmp : "",
+ JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
+ JS_free(cx, tmp);
+ }
+
+ /* embedded newlines -- argh! */
+ while ((ctmp = strchr(message, '\n')) != 0) {
+ ctmp++;
+ if (prefix)
+ fputs(prefix, gErrFile);
+ fwrite(message, 1, ctmp - message, gErrFile);
+ message = ctmp;
+ }
+
+ /* If there were no filename or lineno, the prefix might be empty */
+ if (prefix)
+ fputs(prefix, gErrFile);
+ fputs(message, gErrFile);
+
+ if (!report->linebuf) {
+ fputc('\n', gErrFile);
+ goto out;
+ }
+
+ /* report->linebuf usually ends with a newline. */
+ n = strlen(report->linebuf);
+ fprintf(gErrFile, ":\n%s%s%s%s",
+ prefix,
+ report->linebuf,
+ (n > 0 && report->linebuf[n-1] == '\n') ? "" : "\n",
+ prefix);
+ n = PTRDIFF(report->tokenptr, report->linebuf, char);
+ for (i = j = 0; i < n; i++) {
+ if (report->linebuf[i] == '\t') {
+ for (k = (j + 8) & ~7; j < k; j++) {
+ fputc('.', gErrFile);
+ }
+ continue;
+ }
+ fputc('.', gErrFile);
+ j++;
+ }
+ fputs("^\n", gErrFile);
+ out:
+ if (!JSREPORT_IS_WARNING(report->flags)) {
+ if (report->errorNumber == JSMSG_OUT_OF_MEMORY) {
+ gExitCode = EXITCODE_OUT_OF_MEMORY;
+ } else {
+ gExitCode = EXITCODE_RUNTIME_ERROR;
+ }
+ }
+ JS_free(cx, prefix);
+}
+
+#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
+static JSBool
+Exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFunction *fun;
+ const char *name, **nargv;
+ uintN i, nargc;
+ JSString *str;
+ pid_t pid;
+ int status;
+
+ fun = JS_ValueToFunction(cx, argv[-2]);
+ if (!fun)
+ return JS_FALSE;
+ if (!fun->atom)
+ return JS_TRUE;
+ name = JS_GetStringBytes(ATOM_TO_STRING(fun->atom));
+ nargc = 1 + argc;
+ nargv = JS_malloc(cx, (nargc + 1) * sizeof(char *));
+ if (!nargv)
+ return JS_FALSE;
+ nargv[0] = name;
+ for (i = 1; i < nargc; i++) {
+ str = JS_ValueToString(cx, argv[i-1]);
+ if (!str) {
+ JS_free(cx, nargv);
+ return JS_FALSE;
+ }
+ nargv[i] = JS_GetStringBytes(str);
+ }
+ nargv[nargc] = 0;
+ pid = fork();
+ switch (pid) {
+ case -1:
+ perror("js");
+ break;
+ case 0:
+ (void) execvp(name, (char **)nargv);
+ perror("js");
+ exit(127);
+ default:
+ while (waitpid(pid, &status, 0) < 0 && errno == EINTR)
+ continue;
+ break;
+ }
+ JS_free(cx, nargv);
+ return JS_TRUE;
+}
+#endif
+
+static JSBool
+global_enumerate(JSContext *cx, JSObject *obj)
+{
+#ifdef LAZY_STANDARD_CLASSES
+ return JS_EnumerateStandardClasses(cx, obj);
+#else
+ return JS_TRUE;
+#endif
+}
+
+static JSBool
+global_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+#ifdef LAZY_STANDARD_CLASSES
+ if ((flags & JSRESOLVE_ASSIGNING) == 0) {
+ JSBool resolved;
+
+ if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
+ return JS_FALSE;
+ if (resolved) {
+ *objp = obj;
+ return JS_TRUE;
+ }
+ }
+#endif
+
+#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
+ if ((flags & (JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING)) == 0) {
+ /*
+ * Do this expensive hack only for unoptimized Unix builds, which are
+ * not used for benchmarking.
+ */
+ char *path, *comp, *full;
+ const char *name;
+ JSBool ok, found;
+ JSFunction *fun;
+
+ if (!JSVAL_IS_STRING(id))
+ return JS_TRUE;
+ path = getenv("PATH");
+ if (!path)
+ return JS_TRUE;
+ path = JS_strdup(cx, path);
+ if (!path)
+ return JS_FALSE;
+ name = JS_GetStringBytes(JSVAL_TO_STRING(id));
+ ok = JS_TRUE;
+ for (comp = strtok(path, ":"); comp; comp = strtok(NULL, ":")) {
+ if (*comp != '\0') {
+ full = JS_smprintf("%s/%s", comp, name);
+ if (!full) {
+ JS_ReportOutOfMemory(cx);
+ ok = JS_FALSE;
+ break;
+ }
+ } else {
+ full = (char *)name;
+ }
+ found = (access(full, X_OK) == 0);
+ if (*comp != '\0')
+ free(full);
+ if (found) {
+ fun = JS_DefineFunction(cx, obj, name, Exec, 0,
+ JSPROP_ENUMERATE);
+ ok = (fun != NULL);
+ if (ok)
+ *objp = obj;
+ break;
+ }
+ }
+ JS_free(cx, path);
+ return ok;
+ }
+#else
+ return JS_TRUE;
+#endif
+}
+
+JSClass global_class = {
+ "global", JSCLASS_NEW_RESOLVE | JSCLASS_GLOBAL_FLAGS,
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, JS_PropertyStub,
+ global_enumerate, (JSResolveOp) global_resolve,
+ JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+env_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+/* XXX porting may be easy, but these don't seem to supply setenv by default */
+#if !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS
+ JSString *idstr, *valstr;
+ const char *name, *value;
+ int rv;
+
+ idstr = JS_ValueToString(cx, id);
+ valstr = JS_ValueToString(cx, *vp);
+ if (!idstr || !valstr)
+ return JS_FALSE;
+ name = JS_GetStringBytes(idstr);
+ value = JS_GetStringBytes(valstr);
+#if defined XP_WIN || defined HPUX || defined OSF1 || defined IRIX
+ {
+ char *waste = JS_smprintf("%s=%s", name, value);
+ if (!waste) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ rv = putenv(waste);
+#ifdef XP_WIN
+ /*
+ * HPUX9 at least still has the bad old non-copying putenv.
+ *
+ * Per mail from <s.shanmuganathan@digital.com>, OSF1 also has a putenv
+ * that will crash if you pass it an auto char array (so it must place
+ * its argument directly in the char *environ[] array).
+ */
+ free(waste);
+#endif
+ }
+#else
+ rv = setenv(name, value, 1);
+#endif
+ if (rv < 0) {
+ JS_ReportError(cx, "can't set envariable %s to %s", name, value);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(valstr);
+#endif /* !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS */
+ return JS_TRUE;
+}
+
+static JSBool
+env_enumerate(JSContext *cx, JSObject *obj)
+{
+ static JSBool reflected;
+ char **evp, *name, *value;
+ JSString *valstr;
+ JSBool ok;
+
+ if (reflected)
+ return JS_TRUE;
+
+ for (evp = (char **)JS_GetPrivate(cx, obj); (name = *evp) != NULL; evp++) {
+ value = strchr(name, '=');
+ if (!value)
+ continue;
+ *value++ = '\0';
+ valstr = JS_NewStringCopyZ(cx, value);
+ if (!valstr) {
+ ok = JS_FALSE;
+ } else {
+ ok = JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
+ NULL, NULL, JSPROP_ENUMERATE);
+ }
+ value[-1] = '=';
+ if (!ok)
+ return JS_FALSE;
+ }
+
+ reflected = JS_TRUE;
+ return JS_TRUE;
+}
+
+static JSBool
+env_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ JSString *idstr, *valstr;
+ const char *name, *value;
+
+ if (flags & JSRESOLVE_ASSIGNING)
+ return JS_TRUE;
+
+ idstr = JS_ValueToString(cx, id);
+ if (!idstr)
+ return JS_FALSE;
+ name = JS_GetStringBytes(idstr);
+ value = getenv(name);
+ if (value) {
+ valstr = JS_NewStringCopyZ(cx, value);
+ if (!valstr)
+ return JS_FALSE;
+ if (!JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
+ NULL, NULL, JSPROP_ENUMERATE)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ }
+ return JS_TRUE;
+}
+
+static JSClass env_class = {
+ "environment", JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, env_setProperty,
+ env_enumerate, (JSResolveOp) env_resolve,
+ JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+#ifdef NARCISSUS
+
+static JSBool
+defineProperty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSString *str;
+ jsval value;
+ JSBool dontDelete, readOnly, dontEnum;
+ const jschar *chars;
+ size_t length;
+ uintN attrs;
+
+ dontDelete = readOnly = dontEnum = JS_FALSE;
+ if (!JS_ConvertArguments(cx, argc, argv, "Sv/bbb",
+ &str, &value, &dontDelete, &readOnly, &dontEnum)) {
+ return JS_FALSE;
+ }
+ chars = JS_GetStringChars(str);
+ length = JS_GetStringLength(str);
+ attrs = dontEnum ? 0 : JSPROP_ENUMERATE;
+ if (dontDelete)
+ attrs |= JSPROP_PERMANENT;
+ if (readOnly)
+ attrs |= JSPROP_READONLY;
+ return JS_DefineUCProperty(cx, obj, chars, length, value, NULL, NULL,
+ attrs);
+}
+
+static JSBool
+Evaluate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ /* function evaluate(source, filename, lineno) { ... } */
+ JSString *source;
+ const char *filename = "";
+ jsuint lineno = 0;
+ uint32 oldopts;
+ JSBool ok;
+
+ if (argc == 0) {
+ *rval = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ if (!JS_ConvertArguments(cx, argc, argv, "S/su",
+ &source, &filename, &lineno)) {
+ return JS_FALSE;
+ }
+
+ oldopts = JS_GetOptions(cx);
+ JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO);
+ ok = JS_EvaluateUCScript(cx, obj, JS_GetStringChars(source),
+ JS_GetStringLength(source), filename,
+ lineno, rval);
+ JS_SetOptions(cx, oldopts);
+
+ return ok;
+}
+
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/*
+ * Returns a JS_malloc'd string (that the caller needs to JS_free)
+ * containing the directory (non-leaf) part of |from| prepended to |leaf|.
+ * If |from| is empty or a leaf, MakeAbsolutePathname returns a copy of leaf.
+ * Returns NULL to indicate an error.
+ */
+static char *
+MakeAbsolutePathname(JSContext *cx, const char *from, const char *leaf)
+{
+ size_t dirlen;
+ char *dir;
+ const char *slash = NULL, *cp;
+
+ cp = from;
+ while (*cp) {
+ if (*cp == '/'
+#ifdef XP_WIN
+ || *cp == '\\'
+#endif
+ ) {
+ slash = cp;
+ }
+
+ ++cp;
+ }
+
+ if (!slash) {
+ /* We were given a leaf or |from| was empty. */
+ return JS_strdup(cx, leaf);
+ }
+
+ /* Else, we were given a real pathname, return that + the leaf. */
+ dirlen = slash - from + 1;
+ dir = (char*) JS_malloc(cx, dirlen + strlen(leaf) + 1);
+ if (!dir)
+ return NULL;
+
+ strncpy(dir, from, dirlen);
+ strcpy(dir + dirlen, leaf); /* Note: we can't use strcat here. */
+
+ return dir;
+}
+
+static JSBool
+snarf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+ const char *filename;
+ char *pathname;
+ JSStackFrame *fp;
+ JSBool ok;
+ off_t cc, len;
+ char *buf;
+ FILE *file;
+
+ str = JS_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ filename = JS_GetStringBytes(str);
+
+ /* Get the currently executing script's name. */
+ fp = JS_GetScriptedCaller(cx, NULL);
+ JS_ASSERT(fp && fp->script->filename);
+ pathname = MakeAbsolutePathname(cx, fp->script->filename, filename);
+ if (!pathname)
+ return JS_FALSE;
+
+ ok = JS_FALSE;
+ len = 0;
+ buf = NULL;
+ file = fopen(pathname, "rb");
+ if (!file) {
+ JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
+ } else {
+ if (fseek(file, 0, SEEK_END) == EOF) {
+ JS_ReportError(cx, "can't seek end of %s", pathname);
+ } else {
+ len = ftell(file);
+ if (len == -1 || fseek(file, 0, SEEK_SET) == EOF) {
+ JS_ReportError(cx, "can't seek start of %s", pathname);
+ } else {
+ buf = (char*) JS_malloc(cx, len + 1);
+ if (buf) {
+ cc = fread(buf, 1, len, file);
+ if (cc != len) {
+ JS_free(cx, buf);
+ JS_ReportError(cx, "can't read %s: %s", pathname,
+ (cc < 0) ? strerror(errno)
+ : "short read");
+ } else {
+ len = (size_t)cc;
+ ok = JS_TRUE;
+ }
+ }
+ }
+ }
+ fclose(file);
+ }
+ JS_free(cx, pathname);
+ if (!ok) {
+ JS_free(cx, buf);
+ return ok;
+ }
+
+ buf[len] = '\0';
+ str = JS_NewString(cx, buf, len);
+ if (!str) {
+ JS_free(cx, buf);
+ return JS_FALSE;
+ }
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#endif /* NARCISSUS */
+
+static JSBool
+ContextCallback(JSContext *cx, uintN contextOp)
+{
+ if (contextOp == JSCONTEXT_NEW) {
+ JS_SetErrorReporter(cx, my_ErrorReporter);
+ JS_SetVersion(cx, JSVERSION_LATEST);
+ SetContextOptions(cx);
+ }
+ return JS_TRUE;
+}
+
+int
+main(int argc, char **argv, char **envp)
+{
+ int stackDummy;
+ JSRuntime *rt;
+ JSContext *cx;
+ JSObject *glob, *it, *envobj;
+ int result;
+#ifdef LIVECONNECT
+ JavaVM *java_vm = NULL;
+#endif
+#ifdef JSDEBUGGER
+ JSDContext *jsdc;
+#ifdef JSDEBUGGER_JAVA_UI
+ JNIEnv *java_env;
+ JSDJContext *jsdjc;
+#endif
+#ifdef JSDEBUGGER_C_UI
+ JSBool jsdbc;
+#endif /* JSDEBUGGER_C_UI */
+#endif /* JSDEBUGGER */
+
+ CheckHelpMessages();
+ setlocale(LC_ALL, "");
+
+ gStackBase = (jsuword)&stackDummy;
+
+#ifdef XP_OS2
+ /* these streams are normally line buffered on OS/2 and need a \n, *
+ * so we need to unbuffer then to get a reasonable prompt */
+ setbuf(stdout,0);
+ setbuf(stderr,0);
+#endif
+
+ gErrFile = stderr;
+ gOutFile = stdout;
+
+ argc--;
+ argv++;
+
+ rt = JS_NewRuntime(64L * 1024L * 1024L);
+ if (!rt)
+ return 1;
+ JS_SetContextCallback(rt, ContextCallback);
+
+ cx = JS_NewContext(rt, gStackChunkSize);
+ if (!cx)
+ return 1;
+
+#ifdef JS_THREADSAFE
+ JS_BeginRequest(cx);
+#endif
+
+ glob = JS_NewObject(cx, &global_class, NULL, NULL);
+ if (!glob)
+ return 1;
+#ifdef LAZY_STANDARD_CLASSES
+ JS_SetGlobalObject(cx, glob);
+#else
+ if (!JS_InitStandardClasses(cx, glob))
+ return 1;
+#endif
+ if (!JS_DefineFunctions(cx, glob, shell_functions))
+ return 1;
+
+ it = JS_DefineObject(cx, glob, "it", &its_class, NULL, 0);
+ if (!it)
+ return 1;
+ if (!JS_DefineProperties(cx, it, its_props))
+ return 1;
+ if (!JS_DefineFunctions(cx, it, its_methods))
+ return 1;
+
+#ifdef JSDEBUGGER
+ /*
+ * XXX A command line option to enable debugging (or not) would be good
+ */
+ jsdc = JSD_DebuggerOnForUser(rt, NULL, NULL);
+ if (!jsdc)
+ return 1;
+ JSD_JSContextInUse(jsdc, cx);
+#ifdef JSD_LOWLEVEL_SOURCE
+ JS_SetSourceHandler(rt, SendSourceToJSDebugger, jsdc);
+#endif /* JSD_LOWLEVEL_SOURCE */
+#ifdef JSDEBUGGER_JAVA_UI
+ jsdjc = JSDJ_CreateContext();
+ if (! jsdjc)
+ return 1;
+ JSDJ_SetJSDContext(jsdjc, jsdc);
+ java_env = JSDJ_CreateJavaVMAndStartDebugger(jsdjc);
+#ifdef LIVECONNECT
+ if (java_env)
+ (*java_env)->GetJavaVM(java_env, &java_vm);
+#endif
+ /*
+ * XXX This would be the place to wait for the debugger to start.
+ * Waiting would be nice in general, but especially when a js file
+ * is passed on the cmd line.
+ */
+#endif /* JSDEBUGGER_JAVA_UI */
+#ifdef JSDEBUGGER_C_UI
+ jsdbc = JSDB_InitDebugger(rt, jsdc, 0);
+#endif /* JSDEBUGGER_C_UI */
+#endif /* JSDEBUGGER */
+
+#ifdef LIVECONNECT
+ if (!JSJ_SimpleInit(cx, glob, java_vm, getenv("CLASSPATH")))
+ return 1;
+#endif
+
+ envobj = JS_DefineObject(cx, glob, "environment", &env_class, NULL, 0);
+ if (!envobj || !JS_SetPrivate(cx, envobj, envp))
+ return 1;
+
+#ifdef NARCISSUS
+ {
+ jsval v;
+ static const char Object_prototype[] = "Object.prototype";
+
+ if (!JS_DefineFunction(cx, glob, "snarf", snarf, 1, 0))
+ return 1;
+ if (!JS_DefineFunction(cx, glob, "evaluate", Evaluate, 3, 0))
+ return 1;
+
+ if (!JS_EvaluateScript(cx, glob,
+ Object_prototype, sizeof Object_prototype - 1,
+ NULL, 0, &v)) {
+ return 1;
+ }
+ if (!JS_DefineFunction(cx, JSVAL_TO_OBJECT(v), "__defineProperty__",
+ defineProperty, 5, 0)) {
+ return 1;
+ }
+ }
+#endif
+
+ result = ProcessArgs(cx, glob, argv, argc);
+
+#ifdef JSDEBUGGER
+ if (jsdc) {
+#ifdef JSDEBUGGER_C_UI
+ if (jsdbc)
+ JSDB_TermDebugger(jsdc);
+#endif /* JSDEBUGGER_C_UI */
+ JSD_DebuggerOff(jsdc);
+ }
+#endif /* JSDEBUGGER */
+
+#ifdef JS_THREADSAFE
+ JS_EndRequest(cx);
+#endif
+
+ JS_DestroyContext(cx);
+ JS_DestroyRuntime(rt);
+ JS_ShutDown();
+ return result;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js.mdp b/tools/node_modules/expresso/deps/jscoverage/js/js.mdp
new file mode 100644
index 0000000..8da64fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js.mdp
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js.msg b/tools/node_modules/expresso/deps/jscoverage/js/js.msg
new file mode 100644
index 0000000..f3a711b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js.msg
@@ -0,0 +1,309 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * This is the JavaScript error message file.
+ *
+ * The format for each JS error message is:
+ *
+ * MSG_DEF(<SYMBOLIC_NAME>, <ERROR_NUMBER>, <ARGUMENT_COUNT>, <EXCEPTION_NAME>,
+ * <FORMAT_STRING>)
+ *
+ * where ;
+ * <SYMBOLIC_NAME> is a legal C identifer that will be used in the
+ * JS engine source.
+ *
+ * <ERROR_NUMBER> is an unique integral value identifying this error.
+ *
+ * <ARGUMENT_COUNT> is an integer literal specifying the total number of
+ * replaceable arguments in the following format string.
+ *
+ * <EXCEPTION_NAME> is an exception index from the enum in jsexn.c;
+ * JSEXN_NONE for none. The given exception index will be raised by the
+ * engine when the corresponding error occurs.
+ *
+ * <FORMAT_STRING> is a string literal, optionally containing sequences
+ * {X} where X is an integer representing the argument number that will
+ * be replaced with a string value when the error is reported.
+ *
+ * e.g.
+ *
+ * MSG_DEF(JSMSG_NOT_A_SUBSPECIES, 73, JSEXN_NONE, 2,
+ * "{0} is not a member of the {1} family")
+ *
+ * can be used:
+ *
+ * JS_ReportErrorNumber(JSMSG_NOT_A_SUBSPECIES, "Rhino", "Monkey");
+ *
+ * to report:
+ *
+ * "Rhino is not a member of the Monkey family"
+ *
+ * Before adding a new MSG_DEF at the end, look for JSMSG_UNUSED<n> free
+ * index placeholders in the middle of the list.
+ */
+
+MSG_DEF(JSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
+MSG_DEF(JSMSG_NOT_DEFINED, 1, 1, JSEXN_REFERENCEERR, "{0} is not defined")
+MSG_DEF(JSMSG_INACTIVE, 2, 0, JSEXN_INTERNALERR, "nothing active on context")
+MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, 3, JSEXN_TYPEERR, "{0} requires more than {1} argument{2}")
+MSG_DEF(JSMSG_BAD_CHAR, 4, 1, JSEXN_INTERNALERR, "invalid format character {0}")
+MSG_DEF(JSMSG_BAD_TYPE, 5, 1, JSEXN_TYPEERR, "unknown type {0}")
+MSG_DEF(JSMSG_ALLOC_OVERFLOW, 6, 0, JSEXN_INTERNALERR, "allocation size overflow")
+MSG_DEF(JSMSG_CANT_UNLOCK, 7, 0, JSEXN_INTERNALERR, "can't unlock memory")
+MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 8, 3, JSEXN_TYPEERR, "{0}.prototype.{1} called on incompatible {2}")
+MSG_DEF(JSMSG_NO_CONSTRUCTOR, 9, 1, JSEXN_TYPEERR, "{0} has no constructor")
+MSG_DEF(JSMSG_CANT_ALIAS, 10, 3, JSEXN_TYPEERR, "can't alias {0} to {1} in class {2}")
+MSG_DEF(JSMSG_NOT_SCRIPTED_FUNCTION, 11, 1, JSEXN_TYPEERR, "{0} is not a scripted function")
+MSG_DEF(JSMSG_BAD_SORT_ARG, 12, 0, JSEXN_TYPEERR, "invalid Array.prototype.sort argument")
+MSG_DEF(JSMSG_BAD_ATOMIC_NUMBER, 13, 1, JSEXN_INTERNALERR, "internal error: no index for atom {0}")
+MSG_DEF(JSMSG_TOO_MANY_LITERALS, 14, 0, JSEXN_INTERNALERR, "too many literals")
+MSG_DEF(JSMSG_CANT_WATCH, 15, 1, JSEXN_TYPEERR, "can't watch non-native objects of class {0}")
+MSG_DEF(JSMSG_STACK_UNDERFLOW, 16, 2, JSEXN_INTERNALERR, "internal error compiling {0}: stack underflow at pc {1}")
+MSG_DEF(JSMSG_NEED_DIET, 17, 1, JSEXN_INTERNALERR, "{0} too large")
+MSG_DEF(JSMSG_TOO_MANY_LOCAL_ROOTS, 18, 0, JSEXN_ERR, "out of local root space")
+MSG_DEF(JSMSG_READ_ONLY, 19, 1, JSEXN_ERR, "{0} is read-only")
+MSG_DEF(JSMSG_BAD_FORMAL, 20, 0, JSEXN_SYNTAXERR, "malformed formal parameter")
+MSG_DEF(JSMSG_BAD_ITERATOR, 21, 3, JSEXN_TYPEERR, "{0} has invalid {1} value {2}")
+MSG_DEF(JSMSG_NOT_FUNCTION, 22, 1, JSEXN_TYPEERR, "{0} is not a function")
+MSG_DEF(JSMSG_NOT_CONSTRUCTOR, 23, 1, JSEXN_TYPEERR, "{0} is not a constructor")
+MSG_DEF(JSMSG_SCRIPT_STACK_QUOTA, 24, 0, JSEXN_INTERNALERR, "script stack space quota is exhausted")
+MSG_DEF(JSMSG_TOO_DEEP, 25, 1, JSEXN_INTERNALERR, "{0} nested too deeply")
+MSG_DEF(JSMSG_OVER_RECURSED, 26, 0, JSEXN_INTERNALERR, "too much recursion")
+MSG_DEF(JSMSG_IN_NOT_OBJECT, 27, 1, JSEXN_TYPEERR, "invalid 'in' operand {0}")
+MSG_DEF(JSMSG_BAD_NEW_RESULT, 28, 1, JSEXN_TYPEERR, "invalid new expression result {0}")
+MSG_DEF(JSMSG_BAD_SHARP_DEF, 29, 1, JSEXN_ERR, "invalid sharp variable definition #{0}=")
+MSG_DEF(JSMSG_BAD_SHARP_USE, 30, 1, JSEXN_ERR, "invalid sharp variable use #{0}#")
+MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 31, 1, JSEXN_TYPEERR, "invalid 'instanceof' operand {0}")
+MSG_DEF(JSMSG_BAD_BYTECODE, 32, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
+MSG_DEF(JSMSG_BAD_RADIX, 33, 1, JSEXN_ERR, "illegal radix {0}")
+MSG_DEF(JSMSG_PAREN_BEFORE_LET, 34, 0, JSEXN_SYNTAXERR, "missing ( before let head")
+MSG_DEF(JSMSG_CANT_CONVERT, 35, 1, JSEXN_ERR, "can't convert {0} to an integer")
+MSG_DEF(JSMSG_CYCLIC_VALUE, 36, 1, JSEXN_ERR, "cyclic {0} value")
+MSG_DEF(JSMSG_COMPILE_EXECED_SCRIPT, 37, 0, JSEXN_TYPEERR, "cannot compile over a script that is currently executing")
+MSG_DEF(JSMSG_CANT_CONVERT_TO, 38, 2, JSEXN_TYPEERR, "can't convert {0} to {1}")
+MSG_DEF(JSMSG_NO_PROPERTIES, 39, 1, JSEXN_TYPEERR, "{0} has no properties")
+MSG_DEF(JSMSG_CANT_FIND_CLASS, 40, 1, JSEXN_TYPEERR, "can't find class id {0}")
+MSG_DEF(JSMSG_CANT_XDR_CLASS, 41, 1, JSEXN_TYPEERR, "can't XDR class {0}")
+MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 42, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})")
+MSG_DEF(JSMSG_UNKNOWN_FORMAT, 43, 1, JSEXN_INTERNALERR, "unknown bytecode format {0}")
+MSG_DEF(JSMSG_TOO_MANY_CON_ARGS, 44, 0, JSEXN_SYNTAXERR, "too many constructor arguments")
+MSG_DEF(JSMSG_TOO_MANY_FUN_ARGS, 45, 0, JSEXN_SYNTAXERR, "too many function arguments")
+MSG_DEF(JSMSG_BAD_QUANTIFIER, 46, 1, JSEXN_SYNTAXERR, "invalid quantifier {0}")
+MSG_DEF(JSMSG_MIN_TOO_BIG, 47, 1, JSEXN_SYNTAXERR, "overlarge minimum {0}")
+MSG_DEF(JSMSG_MAX_TOO_BIG, 48, 1, JSEXN_SYNTAXERR, "overlarge maximum {0}")
+MSG_DEF(JSMSG_OUT_OF_ORDER, 49, 1, JSEXN_SYNTAXERR, "maximum {0} less than minimum")
+MSG_DEF(JSMSG_BAD_DESTRUCT_DECL, 50, 0, JSEXN_SYNTAXERR, "missing = in destructuring declaration")
+MSG_DEF(JSMSG_BAD_DESTRUCT_ASS, 51, 0, JSEXN_SYNTAXERR, "invalid destructuring assignment operator")
+MSG_DEF(JSMSG_PAREN_AFTER_LET, 52, 0, JSEXN_SYNTAXERR, "missing ) after let head")
+MSG_DEF(JSMSG_CURLY_AFTER_LET, 53, 0, JSEXN_SYNTAXERR, "missing } after let block")
+MSG_DEF(JSMSG_MISSING_PAREN, 54, 0, JSEXN_SYNTAXERR, "unterminated parenthetical")
+MSG_DEF(JSMSG_UNTERM_CLASS, 55, 1, JSEXN_SYNTAXERR, "unterminated character class {0}")
+MSG_DEF(JSMSG_TRAILING_SLASH, 56, 0, JSEXN_SYNTAXERR, "trailing \\ in regular expression")
+MSG_DEF(JSMSG_BAD_CLASS_RANGE, 57, 0, JSEXN_SYNTAXERR, "invalid range in character class")
+MSG_DEF(JSMSG_BAD_FLAG, 58, 1, JSEXN_SYNTAXERR, "invalid regular expression flag {0}")
+MSG_DEF(JSMSG_NO_INPUT, 59, 5, JSEXN_SYNTAXERR, "no input for /{0}/{1}{2}{3}{4}")
+MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_ERR, "can't open {0}: {1}")
+MSG_DEF(JSMSG_BAD_STRING_MASK, 61, 1, JSEXN_ERR, "invalid string escape mask {0}")
+MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
+MSG_DEF(JSMSG_END_OF_DATA, 63, 0, JSEXN_INTERNALERR, "unexpected end of data")
+MSG_DEF(JSMSG_SEEK_BEYOND_START, 64, 0, JSEXN_INTERNALERR, "illegal seek beyond start")
+MSG_DEF(JSMSG_SEEK_BEYOND_END, 65, 0, JSEXN_INTERNALERR, "illegal seek beyond end")
+MSG_DEF(JSMSG_END_SEEK, 66, 0, JSEXN_INTERNALERR, "illegal end-based seek")
+MSG_DEF(JSMSG_WHITHER_WHENCE, 67, 1, JSEXN_INTERNALERR, "unknown seek whence: {0}")
+MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 68, 0, JSEXN_INTERNALERR, "bad script XDR magic number")
+MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 69, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters")
+MSG_DEF(JSMSG_MISSING_FORMAL, 70, 0, JSEXN_SYNTAXERR, "missing formal parameter")
+MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 71, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters")
+MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 72, 0, JSEXN_SYNTAXERR, "missing { before function body")
+MSG_DEF(JSMSG_CURLY_AFTER_BODY, 73, 0, JSEXN_SYNTAXERR, "missing } after function body")
+MSG_DEF(JSMSG_PAREN_BEFORE_COND, 74, 0, JSEXN_SYNTAXERR, "missing ( before condition")
+MSG_DEF(JSMSG_PAREN_AFTER_COND, 75, 0, JSEXN_SYNTAXERR, "missing ) after condition")
+MSG_DEF(JSMSG_UNUSED76, 76, 0, JSEXN_NONE, "unused76")
+MSG_DEF(JSMSG_NAME_AFTER_DOT, 77, 0, JSEXN_SYNTAXERR, "missing name after . operator")
+MSG_DEF(JSMSG_BRACKET_IN_INDEX, 78, 0, JSEXN_SYNTAXERR, "missing ] in index expression")
+MSG_DEF(JSMSG_UNUSED79, 79, 0, JSEXN_NONE, "unused79")
+MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 80, 0, JSEXN_SYNTAXERR, "missing ( before switch expression")
+MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 81, 0, JSEXN_SYNTAXERR, "missing ) after switch expression")
+MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 82, 0, JSEXN_SYNTAXERR, "missing { before switch body")
+MSG_DEF(JSMSG_COLON_AFTER_CASE, 83, 0, JSEXN_SYNTAXERR, "missing : after case label")
+MSG_DEF(JSMSG_WHILE_AFTER_DO, 84, 0, JSEXN_SYNTAXERR, "missing while after do-loop body")
+MSG_DEF(JSMSG_PAREN_AFTER_FOR, 85, 0, JSEXN_SYNTAXERR, "missing ( after for")
+MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 86, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
+MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 87, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition")
+MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL, 88, 0, JSEXN_SYNTAXERR, "missing ) after for-loop control")
+MSG_DEF(JSMSG_CURLY_BEFORE_TRY, 89, 0, JSEXN_SYNTAXERR, "missing { before try block")
+MSG_DEF(JSMSG_CURLY_AFTER_TRY, 90, 0, JSEXN_SYNTAXERR, "missing } after try block")
+MSG_DEF(JSMSG_PAREN_BEFORE_CATCH, 91, 0, JSEXN_SYNTAXERR, "missing ( before catch")
+MSG_DEF(JSMSG_CATCH_IDENTIFIER, 92, 0, JSEXN_SYNTAXERR, "missing identifier in catch")
+MSG_DEF(JSMSG_PAREN_AFTER_CATCH, 93, 0, JSEXN_SYNTAXERR, "missing ) after catch")
+MSG_DEF(JSMSG_CURLY_BEFORE_CATCH, 94, 0, JSEXN_SYNTAXERR, "missing { before catch block")
+MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 95, 0, JSEXN_SYNTAXERR, "missing } after catch block")
+MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY, 96, 0, JSEXN_SYNTAXERR, "missing { before finally block")
+MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 97, 0, JSEXN_SYNTAXERR, "missing } after finally block")
+MSG_DEF(JSMSG_CATCH_OR_FINALLY, 98, 0, JSEXN_SYNTAXERR, "missing catch or finally after try")
+MSG_DEF(JSMSG_PAREN_BEFORE_WITH, 99, 0, JSEXN_SYNTAXERR, "missing ( before with-statement object")
+MSG_DEF(JSMSG_PAREN_AFTER_WITH, 100, 0, JSEXN_SYNTAXERR, "missing ) after with-statement object")
+MSG_DEF(JSMSG_CURLY_IN_COMPOUND, 101, 0, JSEXN_SYNTAXERR, "missing } in compound statement")
+MSG_DEF(JSMSG_NO_VARIABLE_NAME, 102, 0, JSEXN_SYNTAXERR, "missing variable name")
+MSG_DEF(JSMSG_COLON_IN_COND, 103, 0, JSEXN_SYNTAXERR, "missing : in conditional expression")
+MSG_DEF(JSMSG_PAREN_AFTER_ARGS, 104, 0, JSEXN_SYNTAXERR, "missing ) after argument list")
+MSG_DEF(JSMSG_BRACKET_AFTER_LIST, 105, 0, JSEXN_SYNTAXERR, "missing ] after element list")
+MSG_DEF(JSMSG_COLON_AFTER_ID, 106, 0, JSEXN_SYNTAXERR, "missing : after property id")
+MSG_DEF(JSMSG_CURLY_AFTER_LIST, 107, 0, JSEXN_SYNTAXERR, "missing } after property list")
+MSG_DEF(JSMSG_PAREN_IN_PAREN, 108, 0, JSEXN_SYNTAXERR, "missing ) in parenthetical")
+MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 109, 0, JSEXN_SYNTAXERR, "missing ; before statement")
+MSG_DEF(JSMSG_NO_RETURN_VALUE, 110, 1, JSEXN_TYPEERR, "function {0} does not always return a value")
+MSG_DEF(JSMSG_DUPLICATE_FORMAL, 111, 1, JSEXN_TYPEERR, "duplicate formal argument {0}")
+MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 112, 1, JSEXN_SYNTAXERR, "test for equality (==) mistyped as assignment (=)?{0}")
+MSG_DEF(JSMSG_UNUSED113, 113, 0, JSEXN_NONE, "unused113")
+MSG_DEF(JSMSG_TOO_MANY_DEFAULTS, 114, 0, JSEXN_SYNTAXERR, "more than one switch default")
+MSG_DEF(JSMSG_TOO_MANY_CASES, 115, 0, JSEXN_INTERNALERR, "too many switch cases")
+MSG_DEF(JSMSG_BAD_SWITCH, 116, 0, JSEXN_SYNTAXERR, "invalid switch statement")
+MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 117, 0, JSEXN_SYNTAXERR, "invalid for/in left-hand side")
+MSG_DEF(JSMSG_CATCH_AFTER_GENERAL, 118, 0, JSEXN_SYNTAXERR, "catch after unconditional catch")
+MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 119, 0, JSEXN_SYNTAXERR, "catch without try")
+MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 120, 0, JSEXN_SYNTAXERR, "finally without try")
+MSG_DEF(JSMSG_LABEL_NOT_FOUND, 121, 0, JSEXN_SYNTAXERR, "label not found")
+MSG_DEF(JSMSG_TOUGH_BREAK, 122, 0, JSEXN_SYNTAXERR, "unlabeled break must be inside loop or switch")
+MSG_DEF(JSMSG_BAD_CONTINUE, 123, 0, JSEXN_SYNTAXERR, "continue must be inside loop")
+MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD, 124, 1, JSEXN_SYNTAXERR, "{0} not in function")
+MSG_DEF(JSMSG_BAD_LABEL, 125, 0, JSEXN_SYNTAXERR, "invalid label")
+MSG_DEF(JSMSG_DUPLICATE_LABEL, 126, 0, JSEXN_SYNTAXERR, "duplicate label")
+MSG_DEF(JSMSG_VAR_HIDES_ARG, 127, 1, JSEXN_TYPEERR, "variable {0} redeclares argument")
+MSG_DEF(JSMSG_BAD_VAR_INIT, 128, 0, JSEXN_SYNTAXERR, "invalid variable initialization")
+MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 129, 0, JSEXN_SYNTAXERR, "invalid assignment left-hand side")
+MSG_DEF(JSMSG_BAD_OPERAND, 130, 1, JSEXN_SYNTAXERR, "invalid {0} operand")
+MSG_DEF(JSMSG_BAD_PROP_ID, 131, 0, JSEXN_SYNTAXERR, "invalid property id")
+MSG_DEF(JSMSG_RESERVED_ID, 132, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier")
+MSG_DEF(JSMSG_SYNTAX_ERROR, 133, 0, JSEXN_SYNTAXERR, "syntax error")
+MSG_DEF(JSMSG_BAD_SHARP_VAR_DEF, 134, 0, JSEXN_SYNTAXERR, "invalid sharp variable definition")
+MSG_DEF(JSMSG_BAD_PROTOTYPE, 135, 1, JSEXN_TYPEERR, "'prototype' property of {0} is not an object")
+MSG_DEF(JSMSG_MISSING_EXPONENT, 136, 0, JSEXN_SYNTAXERR, "missing exponent")
+MSG_DEF(JSMSG_OUT_OF_MEMORY, 137, 0, JSEXN_ERR, "out of memory")
+MSG_DEF(JSMSG_UNTERMINATED_STRING, 138, 0, JSEXN_SYNTAXERR, "unterminated string literal")
+MSG_DEF(JSMSG_TOO_MANY_PARENS, 139, 0, JSEXN_INTERNALERR, "too many parentheses in regular expression")
+MSG_DEF(JSMSG_UNTERMINATED_COMMENT, 140, 0, JSEXN_SYNTAXERR, "unterminated comment")
+MSG_DEF(JSMSG_UNTERMINATED_REGEXP, 141, 0, JSEXN_SYNTAXERR, "unterminated regular expression literal")
+MSG_DEF(JSMSG_BAD_REGEXP_FLAG, 142, 0, JSEXN_SYNTAXERR, "invalid flag after regular expression")
+MSG_DEF(JSMSG_SHARPVAR_TOO_BIG, 143, 0, JSEXN_SYNTAXERR, "overlarge sharp variable number")
+MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 144, 0, JSEXN_SYNTAXERR, "illegal character")
+MSG_DEF(JSMSG_BAD_OCTAL, 145, 1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant")
+MSG_DEF(JSMSG_BAD_INDIRECT_CALL, 146, 1, JSEXN_EVALERR, "function {0} must be called directly, and not by way of a function of another name")
+MSG_DEF(JSMSG_UNCAUGHT_EXCEPTION, 147, 1, JSEXN_INTERNALERR, "uncaught exception: {0}")
+MSG_DEF(JSMSG_INVALID_BACKREF, 148, 0, JSEXN_SYNTAXERR, "non-octal digit in an escape sequence that doesn't match a back-reference")
+MSG_DEF(JSMSG_BAD_BACKREF, 149, 0, JSEXN_SYNTAXERR, "back-reference exceeds number of capturing parentheses")
+MSG_DEF(JSMSG_PRECISION_RANGE, 150, 1, JSEXN_RANGEERR, "precision {0} out of range")
+MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 151, 1, JSEXN_SYNTAXERR, "invalid {0} usage")
+MSG_DEF(JSMSG_BAD_ARRAY_LENGTH, 152, 0, JSEXN_RANGEERR, "invalid array length")
+MSG_DEF(JSMSG_CANT_DESCRIBE_PROPS, 153, 1, JSEXN_TYPEERR, "can't describe non-native properties of class {0}")
+MSG_DEF(JSMSG_BAD_APPLY_ARGS, 154, 1, JSEXN_TYPEERR, "second argument to Function.prototype.{0} must be an array")
+MSG_DEF(JSMSG_REDECLARED_VAR, 155, 2, JSEXN_TYPEERR, "redeclaration of {0} {1}")
+MSG_DEF(JSMSG_UNDECLARED_VAR, 156, 1, JSEXN_TYPEERR, "assignment to undeclared variable {0}")
+MSG_DEF(JSMSG_ANON_NO_RETURN_VALUE, 157, 0, JSEXN_TYPEERR, "anonymous function does not always return a value")
+MSG_DEF(JSMSG_DEPRECATED_USAGE, 158, 1, JSEXN_REFERENCEERR, "deprecated {0} usage")
+MSG_DEF(JSMSG_BAD_URI, 159, 0, JSEXN_URIERR, "malformed URI sequence")
+MSG_DEF(JSMSG_GETTER_ONLY, 160, 0, JSEXN_TYPEERR, "setting a property that has only a getter")
+MSG_DEF(JSMSG_TRAILING_COMMA, 161, 0, JSEXN_SYNTAXERR, "trailing comma is not legal in ECMA-262 object initializers")
+MSG_DEF(JSMSG_UNDEFINED_PROP, 162, 1, JSEXN_REFERENCEERR, "reference to undefined property {0}")
+MSG_DEF(JSMSG_USELESS_EXPR, 163, 0, JSEXN_TYPEERR, "useless expression")
+MSG_DEF(JSMSG_REDECLARED_PARAM, 164, 1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}")
+MSG_DEF(JSMSG_NEWREGEXP_FLAGGED, 165, 0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another")
+MSG_DEF(JSMSG_RESERVED_SLOT_RANGE, 166, 0, JSEXN_RANGEERR, "reserved slot index out of range")
+MSG_DEF(JSMSG_CANT_DECODE_PRINCIPALS, 167, 0, JSEXN_INTERNALERR, "can't decode JSPrincipals")
+MSG_DEF(JSMSG_CANT_SEAL_OBJECT, 168, 1, JSEXN_ERR, "can't seal {0} objects")
+MSG_DEF(JSMSG_TOO_MANY_CATCH_VARS, 169, 0, JSEXN_SYNTAXERR, "too many catch variables")
+MSG_DEF(JSMSG_BAD_XML_MARKUP, 170, 0, JSEXN_SYNTAXERR, "invalid XML markup")
+MSG_DEF(JSMSG_BAD_XML_CHARACTER, 171, 0, JSEXN_SYNTAXERR, "illegal XML character")
+MSG_DEF(JSMSG_BAD_DEFAULT_XML_NAMESPACE,172,0,JSEXN_SYNTAXERR, "invalid default XML namespace")
+MSG_DEF(JSMSG_BAD_XML_NAME_SYNTAX, 173, 0, JSEXN_SYNTAXERR, "invalid XML name")
+MSG_DEF(JSMSG_BRACKET_AFTER_ATTR_EXPR,174, 0, JSEXN_SYNTAXERR, "missing ] after attribute expression")
+MSG_DEF(JSMSG_NESTING_GENERATOR, 175, 1, JSEXN_TYPEERR, "already executing generator {0}")
+MSG_DEF(JSMSG_CURLY_IN_XML_EXPR, 176, 0, JSEXN_SYNTAXERR, "missing } in XML expression")
+MSG_DEF(JSMSG_BAD_XML_NAMESPACE, 177, 1, JSEXN_TYPEERR, "invalid XML namespace {0}")
+MSG_DEF(JSMSG_BAD_XML_ATTR_NAME, 178, 1, JSEXN_TYPEERR, "invalid XML attribute name {0}")
+MSG_DEF(JSMSG_BAD_XML_NAME, 179, 1, JSEXN_TYPEERR, "invalid XML name {0}")
+MSG_DEF(JSMSG_BAD_XML_CONVERSION, 180, 1, JSEXN_TYPEERR, "can't convert {0} to XML")
+MSG_DEF(JSMSG_BAD_XMLLIST_CONVERSION, 181, 1, JSEXN_TYPEERR, "can't convert {0} to XMLList")
+MSG_DEF(JSMSG_BAD_GENERATOR_SEND, 182, 1, JSEXN_TYPEERR, "attempt to send {0} to newborn generator")
+MSG_DEF(JSMSG_NO_ASSIGN_IN_XML_ATTR, 183, 0, JSEXN_SYNTAXERR, "missing = in XML attribute")
+MSG_DEF(JSMSG_BAD_XML_ATTR_VALUE, 184, 0, JSEXN_SYNTAXERR, "invalid XML attribute value")
+MSG_DEF(JSMSG_XML_TAG_NAME_MISMATCH, 185, 1, JSEXN_SYNTAXERR, "XML tag name mismatch (expected {0})")
+MSG_DEF(JSMSG_BAD_XML_TAG_SYNTAX, 186, 0, JSEXN_SYNTAXERR, "invalid XML tag syntax")
+MSG_DEF(JSMSG_BAD_XML_LIST_SYNTAX, 187, 0, JSEXN_SYNTAXERR, "invalid XML list syntax")
+MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 188, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}")
+MSG_DEF(JSMSG_CANT_SET_XML_ATTRS, 189, 0, JSEXN_INTERNALERR, "can't set XML property attributes")
+MSG_DEF(JSMSG_END_OF_XML_SOURCE, 190, 0, JSEXN_SYNTAXERR, "unexpected end of XML source")
+MSG_DEF(JSMSG_END_OF_XML_ENTITY, 191, 0, JSEXN_SYNTAXERR, "unexpected end of XML entity")
+MSG_DEF(JSMSG_BAD_XML_QNAME, 192, 0, JSEXN_SYNTAXERR, "invalid XML qualified name")
+MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 193, 0, JSEXN_SYNTAXERR, "invalid for each loop")
+MSG_DEF(JSMSG_BAD_XMLLIST_PUT, 194, 1, JSEXN_TYPEERR, "can't set property {0} in XMLList")
+MSG_DEF(JSMSG_UNKNOWN_XML_ENTITY, 195, 1, JSEXN_TYPEERR, "unknown XML entity {0}")
+MSG_DEF(JSMSG_BAD_XML_NCR, 196, 1, JSEXN_TYPEERR, "malformed XML character {0}")
+MSG_DEF(JSMSG_UNDEFINED_XML_NAME, 197, 1, JSEXN_REFERENCEERR, "reference to undefined XML name {0}")
+MSG_DEF(JSMSG_DUPLICATE_XML_ATTR, 198, 1, JSEXN_TYPEERR, "duplicate XML attribute {0}")
+MSG_DEF(JSMSG_TOO_MANY_LOCALS, 199, 0, JSEXN_SYNTAXERR, "too many local variables")
+MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 200, 0, JSEXN_INTERNALERR, "array initialiser too large")
+MSG_DEF(JSMSG_REGEXP_TOO_COMPLEX, 201, 0, JSEXN_INTERNALERR, "regular expression too complex")
+MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 202, 0, JSEXN_INTERNALERR, "buffer too small")
+MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 203, 1, JSEXN_TYPEERR, "bad surrogate character {0}")
+MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 204, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large")
+MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR, 205, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}")
+MSG_DEF(JSMSG_USER_DEFINED_ERROR, 206, 0, JSEXN_ERR, "JS_ReportError was called")
+MSG_DEF(JSMSG_WRONG_CONSTRUCTOR, 207, 1, JSEXN_TYPEERR, "wrong constructor called for {0}")
+MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 208, 1, JSEXN_TYPEERR, "generator function {0} returns a value")
+MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 209, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
+MSG_DEF(JSMSG_NAME_AFTER_FOR_PAREN, 210, 0, JSEXN_SYNTAXERR, "missing name after for (")
+MSG_DEF(JSMSG_IN_AFTER_FOR_NAME, 211, 0, JSEXN_SYNTAXERR, "missing in after for")
+MSG_DEF(JSMSG_BAD_ITERATOR_RETURN, 212, 2, JSEXN_TYPEERR, "{0}.{1} returned a primitive value")
+MSG_DEF(JSMSG_KEYWORD_NOT_NS, 213, 0, JSEXN_SYNTAXERR, "keyword is used as namespace")
+MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 214, 1, JSEXN_TYPEERR, "yield from closing generator {0}")
+MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX, 215, 1, JSEXN_SYNTAXERR, "{0} expression must be parenthesized")
+MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 216, 0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side")
+MSG_DEF(JSMSG_NON_XML_FILTER, 217, 1, JSEXN_TYPEERR, "XML filter is applied to non-XML value {0}")
+MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 218, 0, JSEXN_TYPEERR, "reduce of empty array with no initial value")
+MSG_DEF(JSMSG_NON_LIST_XML_METHOD, 219, 2, JSEXN_TYPEERR, "cannot call {0} method on an XML list with {1} elements")
+MSG_DEF(JSMSG_BAD_DELETE_OPERAND, 220, 0, JSEXN_SYNTAXERR, "invalid delete operand")
+MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 221, 0, JSEXN_SYNTAXERR, "invalid increment/decrement operand")
+MSG_DEF(JSMSG_NULL_OR_UNDEFINED, 222, 2, JSEXN_TYPEERR, "{0} is {1}")
+MSG_DEF(JSMSG_LET_DECL_NOT_IN_BLOCK, 223, 0, JSEXN_SYNTAXERR, "let declaration not directly within block")
+MSG_DEF(JSMSG_BAD_OBJECT_INIT, 224, 0, JSEXN_SYNTAXERR, "invalid object initializer")
+MSG_DEF(JSMSG_CANT_SET_ARRAY_ATTRS, 225, 0, JSEXN_INTERNALERR, "can't set attributes on indexed array properties")
+MSG_DEF(JSMSG_EVAL_ARITY, 226, 0, JSEXN_TYPEERR, "eval accepts only one parameter")
+MSG_DEF(JSMSG_MISSING_FUN_ARG, 227, 2, JSEXN_TYPEERR, "missing argument {0} when calling function {1}")
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js3240.rc b/tools/node_modules/expresso/deps/jscoverage/js/js3240.rc
new file mode 100644
index 0000000..1a9f62c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js3240.rc
@@ -0,0 +1,79 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winver.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 4,0,0,0
+ PRODUCTVERSION 4,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x10004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "Netscape Communications Corporation\0"
+ VALUE "FileDescription", "Netscape 32-bit JavaScript Module\0"
+ VALUE "FileVersion", "4.0\0"
+ VALUE "InternalName", "JS3240\0"
+ VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
+ VALUE "LegalTrademarks", "Netscape, Mozilla\0"
+ VALUE "OriginalFilename", "js3240.dll\0"
+ VALUE "ProductName", "NETSCAPE\0"
+ VALUE "ProductVersion", "4.0\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""winver.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+///////////////////////////////////////////////////////////////////////////// \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsOS240.def b/tools/node_modules/expresso/deps/jscoverage/js/jsOS240.def
new file mode 100644
index 0000000..8f27d64
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsOS240.def
@@ -0,0 +1,654 @@
+; ***** BEGIN LICENSE BLOCK *****
+; Version: MPL 1.1/GPL 2.0/LGPL 2.1
+;
+; The contents of this file are subject to the Mozilla Public License Version
+; 1.1 (the "License"); you may not use this file except in compliance with
+; the License. You may obtain a copy of the License at
+; http://www.mozilla.org/MPL/
+;
+; Software distributed under the License is distributed on an "AS IS" basis,
+; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+; for the specific language governing rights and limitations under the
+; License.
+;
+; The Original Code is Mozilla Communicator client code, released
+; March 31, 1998.
+;
+; The Initial Developer of the Original Code is
+; Netscape Communications Corporation.
+; Portions created by the Initial Developer are Copyright (C) 1998
+; the Initial Developer. All Rights Reserved.
+;
+; Contributor(s):
+;
+; Alternatively, the contents of this file may be used under the terms of
+; either of the GNU General Public License Version 2 or later (the "GPL"),
+; or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+; in which case the provisions of the GPL or the LGPL are applicable instead
+; of those above. If you wish to allow use of your version of this file only
+; under the terms of either the GPL or the LGPL, and not to allow others to
+; use your version of this file under the terms of the MPL, indicate your
+; decision by deleting the provisions above and replace them with the notice
+; and other provisions required by the GPL or the LGPL. If you do not delete
+; the provisions above, a recipient may use your version of this file under
+; the terms of any one of the MPL, the GPL or the LGPL.
+;
+; ***** END LICENSE BLOCK *****
+
+LIBRARY JS3240 INITINSTANCE TERMINSTANCE
+PROTMODE
+
+DESCRIPTION 'Netscape OS/2 JavaScript Library'
+
+
+CODE LOADONCALL MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE MULTIPLE NONSHARED
+
+
+EXPORTS
+;====================== win16 exports these at least... ===========
+; JS_Init = JS_Init @2
+; JS_Finish = JS_Finish @3
+; JS_GetNaNValue
+; JS_GetNegativeInfinityValue
+; JS_GetPositiveInfinityValue
+; JS_GetEmptyStringValue
+; JS_ConvertValue
+; JS_ValueToObject
+; JS_ValueToFunction
+; JS_ValueToString
+; JS_ValueToNumber
+; JS_ValueToBoolean
+; JS_TypeOfValue
+; JS_GetTypeName
+; JS_Lock
+; JS_Unlock
+; JS_NewContext
+; JS_DestroyContext
+; JS_ContextIterator
+; JS_GetGlobalObject
+; JS_SetGlobalObject
+; JS_InitStandardClasses
+;; JS_GetStaticLink
+; JS_malloc
+; JS_realloc
+; JS_free
+; JS_strdup
+; JS_NewDouble
+; JS_NewDoubleValue
+; JS_AddRoot
+; JS_RemoveRoot
+; JS_LockGCThing
+; JS_UnlockGCThing
+; JS_GC
+; JS_PropertyStub
+; JS_EnumerateStub
+; JS_ResolveStub
+; JS_ConvertStub
+; JS_FinalizeStub
+; JS_InitClass
+; JS_GetClass
+; JS_InstanceOf
+; JS_GetPrivate
+; JS_SetPrivate
+; JS_GetInstancePrivate
+; JS_GetPrototype
+; JS_GetParent
+; JS_SetParent
+; JS_GetConstructor
+; JS_NewObject
+; JS_DefineObject
+; JS_DefineConstDoubles
+; JS_DefineProperties
+; JS_DefineProperty
+; JS_DefinePropertyWithTinyId
+; JS_AliasProperty
+; JS_LookupProperty
+; JS_GetProperty
+; JS_SetProperty
+; JS_DeleteProperty
+; JS_NewArrayObject
+; JS_DefineElement
+; JS_AliasElement
+; JS_LookupElement
+; JS_GetElement
+; JS_SetElement
+; JS_DeleteElement
+; JS_ClearScope
+; JS_NewFunction
+; JS_GetFunctionObject
+; JS_GetFunctionName
+; JS_DefineFunctions
+; JS_DefineFunction
+; JS_CompileScript
+; JS_DestroyScript
+; JS_CompileFunction
+; JS_DecompileScript
+; JS_DecompileFunction
+; JS_DecompileFunctionBody
+; JS_ExecuteScript
+; JS_EvaluateScript
+; JS_CallFunction
+; JS_CallFunctionName
+; JS_CallFunctionValue
+; JS_SetBranchCallback
+; JS_IsRunning
+; JS_IsConstructing
+; JS_SetCallReturnValue2
+; JS_NewString
+; JS_NewStringCopyN
+; JS_NewStringCopyZ
+; JS_InternString
+; JS_GetStringBytes
+; JS_GetStringLength
+; JS_CompareStrings
+; JS_ReportError
+; JS_ReportOutOfMemory
+; JS_SetErrorReporter
+; JS_NewRegExpObject
+; JS_SetRegExpInput
+; JS_ClearRegExpStatics
+;=================================================
+
+
+;00001:jsstr (OFFSET:0x00002e17, SIZE:0x0000ae17):
+; - Public Definitions:
+; js_EmptySubString
+; js_CompareStrings
+; js_HashString
+; js_ValueToString
+; js_StringToObject
+; js_FinalizeString
+; js_NewStringCopyZ
+; js_NewString
+; js_InitStringClass
+; js_NewStringCopyN
+; js_BoyerMooreHorspool
+;
+;
+;00002:jsscript (OFFSET:0x0000dc2e, SIZE:0x00003abb):
+; - Public Definitions:
+; js_LineNumberToPC
+; js_PCToLineNumber
+; js_GetSrcNote
+; js_DestroyScript
+; js_NewScript
+;
+;
+;00003:jsscope (OFFSET:0x000116e9, SIZE:0x00004f82):
+; - Public Definitions:
+; js_hash_scope_ops
+; js_list_scope_ops
+; js_DestroyProperty
+; js_NewProperty
+; js_IdToValue
+; js_HashValue
+; js_DestroyScope
+; js_MutateScope
+; js_DropScope
+; js_HoldScope
+; js_NewScope
+; js_GetMutableScope
+; js_HoldProperty
+; js_DropProperty
+;
+;
+;00004:jsscan (OFFSET:0x0001666b, SIZE:0x00008890):
+; - Public Definitions:
+; js_MatchToken
+; js_FlushNewlines
+; js_PeekTokenSameLine
+; js_UngetToken
+; js_GetToken
+; js_PeekToken
+; js_ReportCompileError
+ js_CloseTokenStream
+ js_NewBufferTokenStream
+; js_NewTokenStream
+; js_InitScanner
+;
+;
+;00005:jsregexp (OFFSET:0x0001eefb, SIZE:0x0000eee4):
+; - Public Definitions:
+; js_RegExpClass
+; reopsize
+; js_NewRegExpObject
+; js_InitRegExpClass
+; js_FreeRegExpStatics
+; js_InitRegExpStatics
+; js_ExecuteRegExp
+; js_NewRegExpOpt
+; js_DestroyRegExp
+; js_NewRegExp
+;
+;
+;00006:jsparse (OFFSET:0x0002dddf, SIZE:0x00010b71):
+; - Public Definitions:
+; js_ParseFunctionBody
+ js_Parse
+;
+;
+;00007:jsopcode (OFFSET:0x0003e950, SIZE:0x0000d362):
+; - Public Definitions:
+; js_EscapeMap
+; js_NumCodeSpecs
+; js_CodeSpec
+; js_incop_str
+; js_true_str
+; js_false_str
+; js_this_str
+; js_null_str
+; js_void_str
+; js_typeof_str
+; js_delete_str
+; js_new_str
+; js_ValueToSource
+; js_DecompileScript
+; js_DecompileCode
+; js_DecompileFunction
+; js_puts
+; js_printf
+; js_GetPrinterOutput
+; js_DestroyPrinter
+; js_NewPrinter
+; js_EscapeString
+; js_Disassemble1
+; js_Disassemble
+;
+;00008:jsobj (OFFSET:0x0004bcb2, SIZE:0x000090a4):
+; - Public Definitions:
+; js_WithClass
+; js_ObjectClass
+; js_TryValueOf
+; js_ValueToNonNullObject
+; js_TryMethod
+; js_ObjectToString
+; js_SetClassPrototype
+; js_DeleteProperty2
+; js_DeleteProperty
+; js_SetProperty
+; js_GetProperty
+; js_FindVariableScope
+; js_FindVariable
+; js_FindProperty
+; js_LookupProperty
+; js_DefineProperty
+; js_FreeSlot
+; js_AllocSlot
+; js_FinalizeObject
+; js_GetClassPrototype
+; js_NewObject
+; js_InitObjectClass
+; js_ValueToObject
+; js_obj_toString
+; js_SetSlot
+; js_GetSlot
+;
+;
+;00009:jsnum (OFFSET:0x00054d56, SIZE:0x00004f29):
+; - Public Definitions:
+; js_ValueToInt32
+; js_NumberToObject
+; js_FinalizeDouble
+; js_InitNumberClass
+; js_NumberToString
+; js_NewDoubleValue
+; js_NewDouble
+; js_ValueToNumber
+;
+;
+;00010:jsmath (OFFSET:0x00059c7f, SIZE:0x000054b6):
+; - Public Definitions:
+; js_InitMathClass
+;
+;
+;00011:jsjava (OFFSET:0x0005f135, SIZE:0x00022aad):
+; - Public Definitions:
+; js_Hooks
+; MojaSrcLog
+; finalizeTask
+ JSJ_FindCurrentJSContext
+; JSJ_GetPrincipals
+ JSJ_IsSafeMethod
+ JSJ_InitContext
+ JSJ_Init
+ js_JSErrorToJException
+ js_JavaErrorReporter
+ js_RemoveReflection
+ js_ReflectJObjectToJSObject
+ js_convertJObjectToJSValue
+ js_convertJSValueToJObject
+ js_ReflectJSObjectToJObject
+; js_ReflectJClassToJSObject
+ JSJ_ExitJS
+ JSJ_EnterJS
+ JSJ_CurrentContext
+ JSJ_IsEnabled
+;added in GA code - DSR70297
+ JSJ_Finish
+ JSJ_IsCalledFromJava
+ js_GetJSPrincipalsFromJavaCaller
+
+;
+;
+;00012:jsinterp (OFFSET:0x00081be2, SIZE:0x00012274):
+; - Public Definitions:
+; js_Call
+; js_Interpret
+; js_SetLocalVariable
+; js_GetLocalVariable
+; js_SetArgument
+; js_GetArgument
+; js_FlushPropertyCacheByProp
+; js_FlushPropertyCache
+;
+;
+;00013:jsgc (OFFSET:0x00093e56, SIZE:0x00004f8d):
+; - Public Definitions:
+; js_ForceGC
+; js_UnlockGCThing
+; js_LockGCThing
+; js_GC
+; js_AllocGCThing
+; js_RemoveRoot
+; js_AddRoot
+; js_FinishGC
+; js_InitGC
+;
+;
+;00014:jsfun (OFFSET:0x00098de3, SIZE:0x0000977c):
+; - Public Definitions:
+; js_FunctionClass
+; js_ClosureClass
+; js_CallClass
+; js_DefineFunction
+; js_NewFunction
+; js_InitCallAndClosureClasses
+; js_InitFunctionClass
+; js_ValueToFunction
+; js_SetCallVariable
+; js_GetCallVariable
+; js_PutCallObject
+; js_GetCallObject
+;
+;
+;00015:jsemit (OFFSET:0x000a255f, SIZE:0x000077be):
+; - Public Definitions:
+; js_SrcNoteName
+; js_SrcNoteArity
+ js_FinishTakingSrcNotes
+; js_MoveSrcNotes
+; js_GetSrcNoteOffset
+; js_BumpSrcNoteDelta
+; js_NewSrcNote3
+; js_NewSrcNote2
+; js_PopStatement
+; js_EmitContinue
+; js_EmitBreak
+; js_SetSrcNoteOffset
+; js_NewSrcNote
+; js_PushStatement
+; js_MoveCode
+; js_SetJumpOffset
+; js_Emit3
+; js_Emit2
+; js_Emit1
+; js_UpdateDepth
+; js_SrcNoteLength
+; js_CancelLastOpcode
+ js_InitCodeGenerator
+;
+;
+;00016:jsdbgapi (OFFSET:0x000a9d1d, SIZE:0x000057db):
+; - Public Definitions:
+; js_watchpoint_list
+; js_trap_list
+; JS_SetAnnotationInFrame
+; JS_GetAnnotationFromFrame
+; JS_GetJSPrincipalArrayFromFrame
+; JS_NextJSFrame
+; JS_InitJSFrameIterator
+ JS_LineNumberToPC
+ JS_PCToLineNumber
+ JS_ClearAllWatchPoints
+ JS_ClearWatchPoint
+ JS_SetWatchPoint
+ JS_HandleTrap
+ JS_ClearAllTraps
+ JS_ClearScriptTraps
+ JS_ClearTrap
+ JS_GetTrapOpcode
+ JS_SetTrap
+;DSR070297 - added in GA code
+ JS_FrameIterator
+ JS_GetFrameAnnotation
+ JS_GetFramePrincipalArray
+ JS_GetFrameScript
+ JS_GetScriptFilename
+ JS_SetFrameAnnotation
+ JS_GetFramePC
+ JS_GetFunctionScript
+
+;
+;
+;00017:jsdate (OFFSET:0x000af4f8, SIZE:0x00009a8e):
+; - Public Definitions:
+ js_DateGetSeconds
+ js_DateGetMinutes
+ js_DateGetHours
+ js_DateGetDate
+ js_DateGetMonth
+ js_DateGetYear
+ js_NewDateObject
+; js_InitDateClass
+;
+;
+;00018:jscntxt (OFFSET:0x000b8f86, SIZE:0x00003732):
+; - Public Definitions:
+; js_InterpreterHooks
+; js_ReportIsNotDefined
+; js_ReportErrorAgain
+; js_ReportErrorVA
+; js_ContextIterator
+; js_DestroyContext
+; js_NewContext
+; js_SetInterpreterHooks
+;
+;
+;00019:jsbool (OFFSET:0x000bc6b8, SIZE:0x00003375):
+; - Public Definitions:
+; js_BooleanToString
+; js_BooleanToObject
+; js_InitBooleanClass
+; js_ValueToBoolean
+;
+;
+;00020:jsatom (OFFSET:0x000bfa2d, SIZE:0x000058d0):
+; - Public Definitions:
+; js_valueOf_str
+; js_toString_str
+; js_length_str
+; js_eval_str
+; js_constructor_str
+; js_class_prototype_str
+; js_assign_str
+; js_anonymous_str
+; js_Object_str
+; js_Array_str
+; js_type_str
+; js_DropUnmappedAtoms
+ js_FreeAtomMap
+ js_InitAtomMap
+; js_GetAtom
+; js_DropAtom
+; js_IndexAtom
+; js_ValueToStringAtom
+; js_AtomizeString
+; js_AtomizeDouble
+; js_AtomizeInt
+; js_AtomizeBoolean
+; js_AtomizeObject
+; js_HoldAtom
+; js_MarkAtomState
+; js_FreeAtomState
+; js_Atomize
+; js_InitAtomState
+;
+;
+;00021:jsarray (OFFSET:0x000c52fd, SIZE:0x00007c86):
+; - Public Definitions:
+; js_ArrayClass
+; js_SetArrayLength
+; js_GetArrayLength
+; js_InitArrayClass
+; js_NewArrayObject
+; PR_qsort
+;
+;
+;00022:jsapi (OFFSET:0x000ccf83, SIZE:0x0000de8c):
+; - Public Definitions:
+ JS_ClearRegExpStatics
+ JS_SetRegExpInput
+ JS_NewRegExpObject
+ JS_SetErrorReporter
+ JS_CompareStrings
+ JS_GetStringLength
+ JS_GetStringBytes
+ JS_InternString
+ JS_NewStringCopyZ
+ JS_NewStringCopyN
+ JS_NewString
+ JS_IsRunning
+ JS_SetBranchCallback
+ JS_CallFunctionValue
+ JS_CallFunctionName
+ JS_CallFunction
+ JS_EvaluateScriptForPrincipals
+ JS_EvaluateScript
+ JS_ExecuteScript
+ JS_DecompileFunctionBody
+ JS_DecompileFunction
+ JS_DecompileScript
+ JS_CompileFunctionForPrincipals
+ JS_CompileFunction
+ JS_DestroyScript
+ JS_CompileScriptForPrincipals
+ JS_CompileScript
+ JS_DefineFunction
+ JS_GetFunctionName
+ JS_GetFunctionObject
+ JS_NewFunction
+ JS_ClearScope
+ JS_DeleteElement
+ JS_SetElement
+ JS_GetElement
+ JS_LookupElement
+ JS_AliasElement
+ JS_DefineElement
+ JS_SetArrayLength
+ JS_GetArrayLength
+ JS_NewArrayObject
+ JS_DeleteProperty
+ JS_SetProperty
+ JS_GetProperty
+ JS_LookupProperty
+ JS_AliasProperty
+ JS_DefinePropertyWithTinyId
+ JS_DefineProperty
+ JS_DefineConstDoubles
+ JS_DefineObject
+ JS_NewObject
+ JS_GetConstructor
+ JS_SetParent
+ JS_GetParent
+ JS_SetPrototype
+ JS_GetPrototype
+ JS_GetInstancePrivate
+ JS_SetPrivate
+ JS_GetPrivate
+ JS_InstanceOf
+ JS_GetClass
+ JS_DefineFunctions
+ JS_DefineProperties
+ JS_InitClass
+ JS_FinalizeStub
+ JS_ConvertStub
+ JS_ResolveStub
+ JS_EnumerateStub
+ JS_PropertyStub
+ JS_GC
+ JS_UnlockGCThing
+ JS_LockGCThing
+ JS_RemoveRoot
+ JS_AddRoot
+ JS_NewDoubleValue
+ JS_NewDouble
+ JS_strdup
+ JS_free
+ JS_realloc
+ JS_ReportOutOfMemory
+ JS_malloc
+ JS_GetScopeChain
+ JS_InitStandardClasses
+ JS_SetGlobalObject
+ JS_GetGlobalObject
+ JS_SetVersion
+ JS_GetVersion
+ JS_ContextIterator
+ JS_GetTaskState
+ JS_DestroyContext
+ JS_NewContext
+ JS_Unlock
+ JS_Lock
+ JS_Finish
+ JS_Init
+ JS_GetTypeName
+ JS_TypeOfValue
+ JS_ValueToBoolean
+ JS_ValueToInt32
+ JS_ValueToNumber
+ JS_ValueToString
+ JS_ValueToFunction
+ JS_ValueToObject
+ JS_ReportError
+ JS_ConvertValue
+ JS_GetEmptyStringValue
+ JS_GetPositiveInfinityValue
+ JS_GetNegativeInfinityValue
+ JS_GetNaNValue
+;DSR062897 - added for GA code
+ JS_MaybeGC
+ JS_GetScriptPrincipals
+ JS_IsAssigning
+ JS_SetCharSetInfo
+;brendan@mozilla.org, 2-Sept-2000
+ JS_SetCallReturnValue2
+ JS_SetGCCallback
+ JS_SetGCCallbackRT
+ JS_AddExternalStringFinalizer
+ JS_RemoveExternalStringFinalizer
+ JS_NewExternalString
+;
+;
+;00023:prmjtime (OFFSET:0x000dae0f, SIZE:0x00008986):
+; - Public Definitions:
+ PRMJ_FormatTimeUSEnglish
+ PRMJ_gmtime
+ PRMJ_FormatTime
+ PRMJ_mktime
+ PRMJ_ComputeTime
+ PRMJ_localtime
+ PRMJ_ExplodeTime
+ PRMJ_ToLocal
+ PRMJ_ToGMT
+ PRMJ_NowLocal
+ PRMJ_DSTOffset
+ PRMJ_NowS
+ PRMJ_NowMS
+ PRMJ_Now
+ PRMJ_ToExtendedTime
+ PRMJ_ToBaseTime
+ PRMJ_setDST
+ PRMJ_LocalGMTDifference
+
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsapi.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsapi.cpp
new file mode 100644
index 0000000..db713c8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsapi.cpp
@@ -0,0 +1,6060 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JavaScript API.
+ */
+#include "jsstddef.h"
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsclist.h"
+#include "jsdhash.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdate.h"
+#include "jsdtoa.h"
+#include "jsemit.h"
+#include "jsexn.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jslock.h"
+#include "jsmath.h"
+#include "jsnum.h"
+#include "json.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsregexp.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "prmjtime.h"
+#include "jsstaticcheck.h"
+
+#if !defined JS_THREADSAFE && defined JS_TRACER
+#include "jstracer.h"
+#endif
+
+#if JS_HAS_FILE_OBJECT
+#include "jsfile.h"
+#endif
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#ifdef HAVE_VA_LIST_AS_ARRAY
+#define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
+#else
+#define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
+#endif
+
+#if defined(JS_THREADSAFE)
+#define CHECK_REQUEST(cx) \
+ JS_ASSERT((cx)->requestDepth || (cx)->thread == (cx)->runtime->gcThread)
+#else
+#define CHECK_REQUEST(cx) ((void)0)
+#endif
+
+JS_PUBLIC_API(int64)
+JS_Now()
+{
+ return PRMJ_Now();
+}
+
+JS_PUBLIC_API(jsval)
+JS_GetNaNValue(JSContext *cx)
+{
+ return DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+}
+
+JS_PUBLIC_API(jsval)
+JS_GetNegativeInfinityValue(JSContext *cx)
+{
+ return DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
+}
+
+JS_PUBLIC_API(jsval)
+JS_GetPositiveInfinityValue(JSContext *cx)
+{
+ return DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
+}
+
+JS_PUBLIC_API(jsval)
+JS_GetEmptyStringValue(JSContext *cx)
+{
+ return STRING_TO_JSVAL(cx->runtime->emptyString);
+}
+
+static JSBool
+TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS,
+ jsval **vpp, va_list *app)
+{
+ const char *format;
+ JSArgumentFormatMap *map;
+
+ format = *formatp;
+ for (map = cx->argumentFormatMap; map; map = map->next) {
+ if (!strncmp(format, map->format, map->length)) {
+ *formatp = format + map->length;
+ return map->formatter(cx, format, fromJS, vpp, app);
+ }
+ }
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format);
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
+ ...)
+{
+ va_list ap;
+ JSBool ok;
+
+ va_start(ap, format);
+ ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
+ va_end(ap);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
+ const char *format, va_list ap)
+{
+ jsval *sp;
+ JSBool required;
+ char c;
+ JSFunction *fun;
+ jsdouble d;
+ JSString *str;
+ JSObject *obj;
+
+ CHECK_REQUEST(cx);
+ sp = argv;
+ required = JS_TRUE;
+ while ((c = *format++) != '\0') {
+ if (isspace(c))
+ continue;
+ if (c == '/') {
+ required = JS_FALSE;
+ continue;
+ }
+ if (sp == argv + argc) {
+ if (required) {
+ fun = js_ValueToFunction(cx, &argv[-2], 0);
+ if (fun) {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_MORE_ARGS_NEEDED,
+ JS_GetFunctionName(fun), numBuf,
+ (argc == 1) ? "" : "s");
+ }
+ return JS_FALSE;
+ }
+ break;
+ }
+ switch (c) {
+ case 'b':
+ *va_arg(ap, JSBool *) = js_ValueToBoolean(*sp);
+ break;
+ case 'c':
+ if (!JS_ValueToUint16(cx, *sp, va_arg(ap, uint16 *)))
+ return JS_FALSE;
+ break;
+ case 'i':
+ if (!JS_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *)))
+ return JS_FALSE;
+ break;
+ case 'u':
+ if (!JS_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *)))
+ return JS_FALSE;
+ break;
+ case 'j':
+ if (!JS_ValueToInt32(cx, *sp, va_arg(ap, int32 *)))
+ return JS_FALSE;
+ break;
+ case 'd':
+ if (!JS_ValueToNumber(cx, *sp, va_arg(ap, jsdouble *)))
+ return JS_FALSE;
+ break;
+ case 'I':
+ if (!JS_ValueToNumber(cx, *sp, &d))
+ return JS_FALSE;
+ *va_arg(ap, jsdouble *) = js_DoubleToInteger(d);
+ break;
+ case 's':
+ case 'S':
+ case 'W':
+ str = js_ValueToString(cx, *sp);
+ if (!str)
+ return JS_FALSE;
+ *sp = STRING_TO_JSVAL(str);
+ if (c == 's') {
+ const char *bytes = js_GetStringBytes(cx, str);
+ if (!bytes)
+ return JS_FALSE;
+ *va_arg(ap, const char **) = bytes;
+ } else if (c == 'W') {
+ const jschar *chars = js_GetStringChars(cx, str);
+ if (!chars)
+ return JS_FALSE;
+ *va_arg(ap, const jschar **) = chars;
+ } else {
+ *va_arg(ap, JSString **) = str;
+ }
+ break;
+ case 'o':
+ if (!js_ValueToObject(cx, *sp, &obj))
+ return JS_FALSE;
+ *sp = OBJECT_TO_JSVAL(obj);
+ *va_arg(ap, JSObject **) = obj;
+ break;
+ case 'f':
+ obj = js_ValueToFunctionObject(cx, sp, 0);
+ if (!obj)
+ return JS_FALSE;
+ *sp = OBJECT_TO_JSVAL(obj);
+ *va_arg(ap, JSFunction **) = (JSFunction *) JS_GetPrivate(cx, obj);
+ break;
+ case 'v':
+ *va_arg(ap, jsval *) = *sp;
+ break;
+ case '*':
+ break;
+ default:
+ format--;
+ if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp,
+ JS_ADDRESSOF_VA_LIST(ap))) {
+ return JS_FALSE;
+ }
+ /* NB: the formatter already updated sp, so we continue here. */
+ continue;
+ }
+ sp++;
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(jsval *)
+JS_PushArguments(JSContext *cx, void **markp, const char *format, ...)
+{
+ va_list ap;
+ jsval *argv;
+
+ va_start(ap, format);
+ argv = JS_PushArgumentsVA(cx, markp, format, ap);
+ va_end(ap);
+ return argv;
+}
+
+JS_PUBLIC_API(jsval *)
+JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
+{
+ uintN argc;
+ jsval *argv, *sp;
+ char c;
+ const char *cp;
+ JSString *str;
+ JSFunction *fun;
+ JSStackHeader *sh;
+
+ CHECK_REQUEST(cx);
+ *markp = NULL;
+ argc = 0;
+ for (cp = format; (c = *cp) != '\0'; cp++) {
+ /*
+ * Count non-space non-star characters as individual jsval arguments.
+ * This may over-allocate stack, but we'll fix below.
+ */
+ if (isspace(c) || c == '*')
+ continue;
+ argc++;
+ }
+ sp = js_AllocStack(cx, argc, markp);
+ if (!sp)
+ return NULL;
+ argv = sp;
+ while ((c = *format++) != '\0') {
+ if (isspace(c) || c == '*')
+ continue;
+ switch (c) {
+ case 'b':
+ *sp = BOOLEAN_TO_JSVAL((JSBool) va_arg(ap, int));
+ break;
+ case 'c':
+ *sp = INT_TO_JSVAL((uint16) va_arg(ap, unsigned int));
+ break;
+ case 'i':
+ case 'j':
+ /*
+ * Use JS_New{Double,Number}Value here and in the next two cases,
+ * not js_New{Double,Number}InRootedValue, as sp may point to an
+ * unrooted location.
+ */
+ if (!JS_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp))
+ goto bad;
+ break;
+ case 'u':
+ if (!JS_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp))
+ goto bad;
+ break;
+ case 'd':
+ case 'I':
+ if (!JS_NewDoubleValue(cx, va_arg(ap, jsdouble), sp))
+ goto bad;
+ break;
+ case 's':
+ str = JS_NewStringCopyZ(cx, va_arg(ap, char *));
+ if (!str)
+ goto bad;
+ *sp = STRING_TO_JSVAL(str);
+ break;
+ case 'W':
+ str = JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *));
+ if (!str)
+ goto bad;
+ *sp = STRING_TO_JSVAL(str);
+ break;
+ case 'S':
+ str = va_arg(ap, JSString *);
+ *sp = STRING_TO_JSVAL(str);
+ break;
+ case 'o':
+ *sp = OBJECT_TO_JSVAL(va_arg(ap, JSObject *));
+ break;
+ case 'f':
+ fun = va_arg(ap, JSFunction *);
+ *sp = fun ? OBJECT_TO_JSVAL(FUN_OBJECT(fun)) : JSVAL_NULL;
+ break;
+ case 'v':
+ *sp = va_arg(ap, jsval);
+ break;
+ default:
+ format--;
+ if (!TryArgumentFormatter(cx, &format, JS_FALSE, &sp,
+ JS_ADDRESSOF_VA_LIST(ap))) {
+ goto bad;
+ }
+ /* NB: the formatter already updated sp, so we continue here. */
+ continue;
+ }
+ sp++;
+ }
+
+ /*
+ * We may have overallocated stack due to a multi-character format code
+ * handled by a JSArgumentFormatter. Give back that stack space!
+ */
+ JS_ASSERT(sp <= argv + argc);
+ if (sp < argv + argc) {
+ /* Return slots not pushed to the current stack arena. */
+ cx->stackPool.current->avail = (jsuword)sp;
+
+ /* Reduce the count of slots the GC will scan in this stack segment. */
+ sh = cx->stackHeaders;
+ JS_ASSERT(JS_STACK_SEGMENT(sh) + sh->nslots == argv + argc);
+ sh->nslots -= argc - (sp - argv);
+ }
+ return argv;
+
+bad:
+ js_FreeStack(cx, *markp);
+ return NULL;
+}
+
+JS_PUBLIC_API(void)
+JS_PopArguments(JSContext *cx, void *mark)
+{
+ CHECK_REQUEST(cx);
+ js_FreeStack(cx, mark);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddArgumentFormatter(JSContext *cx, const char *format,
+ JSArgumentFormatter formatter)
+{
+ size_t length;
+ JSArgumentFormatMap **mpp, *map;
+
+ length = strlen(format);
+ mpp = &cx->argumentFormatMap;
+ while ((map = *mpp) != NULL) {
+ /* Insert before any shorter string to match before prefixes. */
+ if (map->length < length)
+ break;
+ if (map->length == length && !strcmp(map->format, format))
+ goto out;
+ mpp = &map->next;
+ }
+ map = (JSArgumentFormatMap *) JS_malloc(cx, sizeof *map);
+ if (!map)
+ return JS_FALSE;
+ map->format = format;
+ map->length = length;
+ map->next = *mpp;
+ *mpp = map;
+out:
+ map->formatter = formatter;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(void)
+JS_RemoveArgumentFormatter(JSContext *cx, const char *format)
+{
+ size_t length;
+ JSArgumentFormatMap **mpp, *map;
+
+ length = strlen(format);
+ mpp = &cx->argumentFormatMap;
+ while ((map = *mpp) != NULL) {
+ if (map->length == length && !strcmp(map->format, format)) {
+ *mpp = map->next;
+ JS_free(cx, map);
+ return;
+ }
+ mpp = &map->next;
+ }
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
+{
+ JSBool ok;
+ JSObject *obj;
+ JSString *str;
+ jsdouble d, *dp;
+
+ CHECK_REQUEST(cx);
+ switch (type) {
+ case JSTYPE_VOID:
+ *vp = JSVAL_VOID;
+ ok = JS_TRUE;
+ break;
+ case JSTYPE_OBJECT:
+ ok = js_ValueToObject(cx, v, &obj);
+ if (ok)
+ *vp = OBJECT_TO_JSVAL(obj);
+ break;
+ case JSTYPE_FUNCTION:
+ *vp = v;
+ obj = js_ValueToFunctionObject(cx, vp, JSV2F_SEARCH_STACK);
+ ok = (obj != NULL);
+ break;
+ case JSTYPE_STRING:
+ str = js_ValueToString(cx, v);
+ ok = (str != NULL);
+ if (ok)
+ *vp = STRING_TO_JSVAL(str);
+ break;
+ case JSTYPE_NUMBER:
+ ok = JS_ValueToNumber(cx, v, &d);
+ if (ok) {
+ dp = js_NewWeaklyRootedDouble(cx, d);
+ ok = (dp != NULL);
+ if (ok)
+ *vp = DOUBLE_TO_JSVAL(dp);
+ }
+ break;
+ case JSTYPE_BOOLEAN:
+ *vp = BOOLEAN_TO_JSVAL(js_ValueToBoolean(v));
+ return JS_TRUE;
+ default: {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE,
+ numBuf);
+ ok = JS_FALSE;
+ break;
+ }
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
+{
+ CHECK_REQUEST(cx);
+ return js_ValueToObject(cx, v, objp);
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_ValueToFunction(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_ValueToConstructor(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_ValueToString(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ return js_ValueToString(cx, v);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_ValueToSource(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ return js_ValueToSource(cx, v);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
+{
+ JSTempValueRooter tvr;
+
+ CHECK_REQUEST(cx);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ *dp = js_ValueToNumber(cx, &tvr.u.value);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return !JSVAL_IS_NULL(tvr.u.value);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
+{
+ JSTempValueRooter tvr;
+
+ CHECK_REQUEST(cx);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ *ip = js_ValueToECMAInt32(cx, &tvr.u.value);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return !JSVAL_IS_NULL(tvr.u.value);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
+{
+ JSTempValueRooter tvr;
+
+ CHECK_REQUEST(cx);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ *ip = js_ValueToECMAUint32(cx, &tvr.u.value);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return !JSVAL_IS_NULL(tvr.u.value);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
+{
+ JSTempValueRooter tvr;
+
+ CHECK_REQUEST(cx);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ *ip = js_ValueToInt32(cx, &tvr.u.value);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return !JSVAL_IS_NULL(tvr.u.value);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip)
+{
+ JSTempValueRooter tvr;
+
+ CHECK_REQUEST(cx);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ *ip = js_ValueToUint16(cx, &tvr.u.value);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return !JSVAL_IS_NULL(tvr.u.value);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
+{
+ CHECK_REQUEST(cx);
+ *bp = js_ValueToBoolean(v);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSType)
+JS_TypeOfValue(JSContext *cx, jsval v)
+{
+ JSType type;
+ JSObject *obj;
+ JSObjectOps *ops;
+ JSClass *clasp;
+
+ CHECK_REQUEST(cx);
+ if (JSVAL_IS_OBJECT(v)) {
+ type = JSTYPE_OBJECT; /* XXXbe JSTYPE_NULL for JS2 */
+ obj = JSVAL_TO_OBJECT(v);
+ if (obj) {
+ JSObject *wrapped;
+
+ wrapped = js_GetWrappedObject(cx, obj);
+ if (wrapped)
+ obj = wrapped;
+
+ ops = obj->map->ops;
+#if JS_HAS_XML_SUPPORT
+ if (ops == &js_XMLObjectOps.base) {
+ type = JSTYPE_XML;
+ } else
+#endif
+ {
+ /*
+ * ECMA 262, 11.4.3 says that any native object that implements
+ * [[Call]] should be of type "function". Note that RegExp and
+ * Script are both of type "function" for compatibility with
+ * older SpiderMonkeys.
+ */
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if ((ops == &js_ObjectOps)
+ ? (clasp->call
+ ? clasp == &js_ScriptClass
+ : clasp == &js_FunctionClass)
+ : ops->call != NULL) {
+ type = JSTYPE_FUNCTION;
+ } else {
+#ifdef NARCISSUS
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+
+ if (!OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .__call__Atom),
+ &v)) {
+ JS_ClearPendingException(cx);
+ } else if (VALUE_IS_FUNCTION(cx, v)) {
+ type = JSTYPE_FUNCTION;
+ }
+#endif
+ }
+ }
+ }
+ } else if (JSVAL_IS_NUMBER(v)) {
+ type = JSTYPE_NUMBER;
+ } else if (JSVAL_IS_STRING(v)) {
+ type = JSTYPE_STRING;
+ } else if (JSVAL_IS_BOOLEAN(v)) {
+ type = JSTYPE_BOOLEAN;
+ } else {
+ type = JSTYPE_VOID;
+ }
+ return type;
+}
+
+JS_PUBLIC_API(const char *)
+JS_GetTypeName(JSContext *cx, JSType type)
+{
+ if ((uintN)type >= (uintN)JSTYPE_LIMIT)
+ return NULL;
+ return JS_TYPE_STR(type);
+}
+
+/************************************************************************/
+
+/*
+ * Has a new runtime ever been created? This flag is used to detect unsafe
+ * changes to js_CStringsAreUTF8 after a runtime has been created, and to
+ * ensure that "first checks" on runtime creation are run only once.
+ */
+#ifdef DEBUG
+static JSBool js_NewRuntimeWasCalled = JS_FALSE;
+#endif
+
+JS_PUBLIC_API(JSRuntime *)
+JS_NewRuntime(uint32 maxbytes)
+{
+ JSRuntime *rt;
+
+#ifdef DEBUG
+ if (!js_NewRuntimeWasCalled) {
+ /*
+ * This code asserts that the numbers associated with the error names
+ * in jsmsg.def are monotonically increasing. It uses values for the
+ * error names enumerated in jscntxt.c. It's not a compile-time check
+ * but it's better than nothing.
+ */
+ int errorNumber = 0;
+#define MSG_DEF(name, number, count, exception, format) \
+ JS_ASSERT(name == errorNumber++);
+#include "js.msg"
+#undef MSG_DEF
+
+#define MSG_DEF(name, number, count, exception, format) \
+ JS_BEGIN_MACRO \
+ uintN numfmtspecs = 0; \
+ const char *fmt; \
+ for (fmt = format; *fmt != '\0'; fmt++) { \
+ if (*fmt == '{' && isdigit(fmt[1])) \
+ ++numfmtspecs; \
+ } \
+ JS_ASSERT(count == numfmtspecs); \
+ JS_END_MACRO;
+#include "js.msg"
+#undef MSG_DEF
+
+ js_NewRuntimeWasCalled = JS_TRUE;
+ }
+#endif /* DEBUG */
+
+ rt = (JSRuntime *) malloc(sizeof(JSRuntime));
+ if (!rt)
+ return NULL;
+
+ /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
+ memset(rt, 0, sizeof(JSRuntime));
+ JS_INIT_CLIST(&rt->contextList);
+ JS_INIT_CLIST(&rt->trapList);
+ JS_INIT_CLIST(&rt->watchPointList);
+
+ if (!js_InitDtoa())
+ goto bad;
+ if (!js_InitGC(rt, maxbytes))
+ goto bad;
+ if (!js_InitAtomState(rt))
+ goto bad;
+ if (!js_InitDeflatedStringCache(rt))
+ goto bad;
+#ifdef JS_THREADSAFE
+ if (!js_InitThreadPrivateIndex(js_ThreadDestructorCB))
+ goto bad;
+ rt->gcLock = JS_NEW_LOCK();
+ if (!rt->gcLock)
+ goto bad;
+ rt->gcDone = JS_NEW_CONDVAR(rt->gcLock);
+ if (!rt->gcDone)
+ goto bad;
+ rt->requestDone = JS_NEW_CONDVAR(rt->gcLock);
+ if (!rt->requestDone)
+ goto bad;
+ /* this is asymmetric with JS_ShutDown: */
+ if (!js_SetupLocks(8, 16))
+ goto bad;
+ rt->rtLock = JS_NEW_LOCK();
+ if (!rt->rtLock)
+ goto bad;
+ rt->stateChange = JS_NEW_CONDVAR(rt->gcLock);
+ if (!rt->stateChange)
+ goto bad;
+ rt->titleSharingDone = JS_NEW_CONDVAR(rt->gcLock);
+ if (!rt->titleSharingDone)
+ goto bad;
+ rt->titleSharingTodo = NO_TITLE_SHARING_TODO;
+ rt->debuggerLock = JS_NEW_LOCK();
+ if (!rt->debuggerLock)
+ goto bad;
+#endif
+ if (!js_InitPropertyTree(rt))
+ goto bad;
+
+#if !defined JS_THREADSAFE && defined JS_TRACER
+ js_InitJIT(&rt->traceMonitor);
+#endif
+
+ return rt;
+
+bad:
+ JS_DestroyRuntime(rt);
+ return NULL;
+}
+
+JS_PUBLIC_API(void)
+JS_DestroyRuntime(JSRuntime *rt)
+{
+#ifdef DEBUG
+ /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
+ if (!JS_CLIST_IS_EMPTY(&rt->contextList)) {
+ JSContext *cx, *iter = NULL;
+ uintN cxcount = 0;
+ while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL) {
+ fprintf(stderr,
+"JS API usage error: found live context at %p\n",
+ cx);
+ cxcount++;
+ }
+ fprintf(stderr,
+"JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
+ cxcount, (cxcount == 1) ? "" : "s");
+ }
+#endif
+
+#if !defined JS_THREADSAFE && defined JS_TRACER
+ js_FinishJIT(&rt->traceMonitor);
+#endif
+
+ js_FreeRuntimeScriptState(rt);
+ js_FinishAtomState(rt);
+
+ /*
+ * Free unit string storage only after all strings have been finalized, so
+ * that js_FinalizeString can detect unit strings and avoid calling free
+ * on their chars storage.
+ */
+ js_FinishUnitStrings(rt);
+
+ /*
+ * Finish the deflated string cache after the last GC and after
+ * calling js_FinishAtomState, which finalizes strings.
+ */
+ js_FinishDeflatedStringCache(rt);
+ js_FinishGC(rt);
+#ifdef JS_THREADSAFE
+ if (rt->gcLock)
+ JS_DESTROY_LOCK(rt->gcLock);
+ if (rt->gcDone)
+ JS_DESTROY_CONDVAR(rt->gcDone);
+ if (rt->requestDone)
+ JS_DESTROY_CONDVAR(rt->requestDone);
+ if (rt->rtLock)
+ JS_DESTROY_LOCK(rt->rtLock);
+ if (rt->stateChange)
+ JS_DESTROY_CONDVAR(rt->stateChange);
+ if (rt->titleSharingDone)
+ JS_DESTROY_CONDVAR(rt->titleSharingDone);
+ if (rt->debuggerLock)
+ JS_DESTROY_LOCK(rt->debuggerLock);
+#else
+ GSN_CACHE_CLEAR(&rt->gsnCache);
+#endif
+ js_FinishPropertyTree(rt);
+ free(rt);
+}
+
+JS_PUBLIC_API(void)
+JS_ShutDown(void)
+{
+#ifdef JS_OPMETER
+ extern void js_DumpOpMeters();
+
+ js_DumpOpMeters();
+#endif
+
+ js_FinishDtoa();
+#ifdef JS_THREADSAFE
+ js_CleanupLocks();
+#endif
+ PRMJ_NowShutdown();
+}
+
+JS_PUBLIC_API(void *)
+JS_GetRuntimePrivate(JSRuntime *rt)
+{
+ return rt->data;
+}
+
+JS_PUBLIC_API(void)
+JS_SetRuntimePrivate(JSRuntime *rt, void *data)
+{
+ rt->data = data;
+}
+
+JS_PUBLIC_API(void)
+JS_BeginRequest(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ JSRuntime *rt;
+
+ JS_ASSERT(cx->thread->id == js_CurrentThreadId());
+ if (!cx->requestDepth) {
+ JS_ASSERT(cx->gcLocalFreeLists == &js_GCEmptyFreeListSet);
+
+ /* Wait until the GC is finished. */
+ rt = cx->runtime;
+ JS_LOCK_GC(rt);
+
+ /* NB: we use cx->thread here, not js_GetCurrentThread(). */
+ if (rt->gcThread != cx->thread) {
+ while (rt->gcLevel > 0)
+ JS_AWAIT_GC_DONE(rt);
+ }
+
+ /* Indicate that a request is running. */
+ rt->requestCount++;
+ cx->requestDepth = 1;
+ cx->outstandingRequests++;
+ JS_UNLOCK_GC(rt);
+ return;
+ }
+ cx->requestDepth++;
+ cx->outstandingRequests++;
+#endif
+}
+
+JS_PUBLIC_API(void)
+JS_EndRequest(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ JSRuntime *rt;
+ JSTitle *title, **todop;
+ JSBool shared;
+
+ CHECK_REQUEST(cx);
+ JS_ASSERT(cx->requestDepth > 0);
+ JS_ASSERT(cx->outstandingRequests > 0);
+ if (cx->requestDepth == 1) {
+ /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
+ rt = cx->runtime;
+ JS_LOCK_GC(rt);
+ cx->requestDepth = 0;
+ cx->outstandingRequests--;
+
+ /* See whether cx has any single-threaded titles to start sharing. */
+ todop = &rt->titleSharingTodo;
+ shared = JS_FALSE;
+ while ((title = *todop) != NO_TITLE_SHARING_TODO) {
+ if (title->ownercx != cx) {
+ todop = &title->u.link;
+ continue;
+ }
+ *todop = title->u.link;
+ title->u.link = NULL; /* null u.link for sanity ASAP */
+
+ /*
+ * If js_DropObjectMap returns null, we held the last ref to scope.
+ * The waiting thread(s) must have been killed, after which the GC
+ * collected the object that held this scope. Unlikely, because it
+ * requires that the GC ran (e.g., from an operation callback)
+ * during this request, but possible.
+ */
+ if (js_DropObjectMap(cx, TITLE_TO_MAP(title), NULL)) {
+ js_InitLock(&title->lock);
+ title->u.count = 0; /* NULL may not pun as 0 */
+ js_FinishSharingTitle(cx, title); /* set ownercx = NULL */
+ shared = JS_TRUE;
+ }
+ }
+ if (shared)
+ JS_NOTIFY_ALL_CONDVAR(rt->titleSharingDone);
+
+ js_RevokeGCLocalFreeLists(cx);
+
+ /* Give the GC a chance to run if this was the last request running. */
+ JS_ASSERT(rt->requestCount > 0);
+ rt->requestCount--;
+ if (rt->requestCount == 0)
+ JS_NOTIFY_REQUEST_DONE(rt);
+
+ JS_UNLOCK_GC(rt);
+ return;
+ }
+
+ cx->requestDepth--;
+ cx->outstandingRequests--;
+#endif
+}
+
+/* Yield to pending GC operations, regardless of request depth */
+JS_PUBLIC_API(void)
+JS_YieldRequest(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ JS_ASSERT(cx->thread);
+ CHECK_REQUEST(cx);
+ JS_ResumeRequest(cx, JS_SuspendRequest(cx));
+#endif
+}
+
+JS_PUBLIC_API(jsrefcount)
+JS_SuspendRequest(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ jsrefcount saveDepth = cx->requestDepth;
+
+ while (cx->requestDepth) {
+ cx->outstandingRequests++; /* compensate for JS_EndRequest */
+ JS_EndRequest(cx);
+ }
+ return saveDepth;
+#else
+ return 0;
+#endif
+}
+
+JS_PUBLIC_API(void)
+JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth)
+{
+#ifdef JS_THREADSAFE
+ JS_ASSERT(!cx->requestDepth);
+ while (--saveDepth >= 0) {
+ JS_BeginRequest(cx);
+ cx->outstandingRequests--; /* compensate for JS_BeginRequest */
+ }
+#endif
+}
+
+JS_PUBLIC_API(void)
+JS_Lock(JSRuntime *rt)
+{
+ JS_LOCK_RUNTIME(rt);
+}
+
+JS_PUBLIC_API(void)
+JS_Unlock(JSRuntime *rt)
+{
+ JS_UNLOCK_RUNTIME(rt);
+}
+
+JS_PUBLIC_API(JSContextCallback)
+JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback)
+{
+ JSContextCallback old;
+
+ old = rt->cxCallback;
+ rt->cxCallback = cxCallback;
+ return old;
+}
+
+JS_PUBLIC_API(JSContext *)
+JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
+{
+ return js_NewContext(rt, stackChunkSize);
+}
+
+JS_PUBLIC_API(void)
+JS_DestroyContext(JSContext *cx)
+{
+ js_DestroyContext(cx, JSDCM_FORCE_GC);
+}
+
+JS_PUBLIC_API(void)
+JS_DestroyContextNoGC(JSContext *cx)
+{
+ js_DestroyContext(cx, JSDCM_NO_GC);
+}
+
+JS_PUBLIC_API(void)
+JS_DestroyContextMaybeGC(JSContext *cx)
+{
+ js_DestroyContext(cx, JSDCM_MAYBE_GC);
+}
+
+JS_PUBLIC_API(void *)
+JS_GetContextPrivate(JSContext *cx)
+{
+ return cx->data;
+}
+
+JS_PUBLIC_API(void)
+JS_SetContextPrivate(JSContext *cx, void *data)
+{
+ cx->data = data;
+}
+
+JS_PUBLIC_API(JSRuntime *)
+JS_GetRuntime(JSContext *cx)
+{
+ return cx->runtime;
+}
+
+JS_PUBLIC_API(JSContext *)
+JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
+{
+ return js_ContextIterator(rt, JS_TRUE, iterp);
+}
+
+JS_PUBLIC_API(JSVersion)
+JS_GetVersion(JSContext *cx)
+{
+ return JSVERSION_NUMBER(cx);
+}
+
+JS_PUBLIC_API(JSVersion)
+JS_SetVersion(JSContext *cx, JSVersion version)
+{
+ JSVersion oldVersion;
+
+ JS_ASSERT(version != JSVERSION_UNKNOWN);
+ JS_ASSERT((version & ~JSVERSION_MASK) == 0);
+
+ oldVersion = JSVERSION_NUMBER(cx);
+ if (version == oldVersion)
+ return oldVersion;
+
+ /* We no longer support 1.4 or below. */
+ if (version != JSVERSION_DEFAULT && version <= JSVERSION_1_4)
+ return oldVersion;
+
+ cx->version = (cx->version & ~JSVERSION_MASK) | version;
+ js_OnVersionChange(cx);
+ return oldVersion;
+}
+
+static struct v2smap {
+ JSVersion version;
+ const char *string;
+} v2smap[] = {
+ {JSVERSION_1_0, "1.0"},
+ {JSVERSION_1_1, "1.1"},
+ {JSVERSION_1_2, "1.2"},
+ {JSVERSION_1_3, "1.3"},
+ {JSVERSION_1_4, "1.4"},
+ {JSVERSION_ECMA_3, "ECMAv3"},
+ {JSVERSION_1_5, "1.5"},
+ {JSVERSION_1_6, "1.6"},
+ {JSVERSION_1_7, "1.7"},
+ {JSVERSION_1_8, "1.8"},
+ {JSVERSION_DEFAULT, js_default_str},
+ {JSVERSION_UNKNOWN, NULL}, /* must be last, NULL is sentinel */
+};
+
+JS_PUBLIC_API(const char *)
+JS_VersionToString(JSVersion version)
+{
+ int i;
+
+ for (i = 0; v2smap[i].string; i++)
+ if (v2smap[i].version == version)
+ return v2smap[i].string;
+ return "unknown";
+}
+
+JS_PUBLIC_API(JSVersion)
+JS_StringToVersion(const char *string)
+{
+ int i;
+
+ for (i = 0; v2smap[i].string; i++)
+ if (strcmp(v2smap[i].string, string) == 0)
+ return v2smap[i].version;
+ return JSVERSION_UNKNOWN;
+}
+
+JS_PUBLIC_API(uint32)
+JS_GetOptions(JSContext *cx)
+{
+ return cx->options;
+}
+
+#define SYNC_OPTIONS_TO_VERSION(cx) \
+ JS_BEGIN_MACRO \
+ if ((cx)->options & JSOPTION_XML) \
+ (cx)->version |= JSVERSION_HAS_XML; \
+ else \
+ (cx)->version &= ~JSVERSION_HAS_XML; \
+ JS_END_MACRO
+
+JS_PUBLIC_API(uint32)
+JS_SetOptions(JSContext *cx, uint32 options)
+{
+ uint32 oldopts = cx->options;
+ cx->options = options;
+ SYNC_OPTIONS_TO_VERSION(cx);
+ return oldopts;
+}
+
+JS_PUBLIC_API(uint32)
+JS_ToggleOptions(JSContext *cx, uint32 options)
+{
+ uint32 oldopts = cx->options;
+ cx->options ^= options;
+ SYNC_OPTIONS_TO_VERSION(cx);
+ return oldopts;
+}
+
+JS_PUBLIC_API(const char *)
+JS_GetImplementationVersion(void)
+{
+ return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
+}
+
+
+JS_PUBLIC_API(JSObject *)
+JS_GetGlobalObject(JSContext *cx)
+{
+ return cx->globalObject;
+}
+
+JS_PUBLIC_API(void)
+JS_SetGlobalObject(JSContext *cx, JSObject *obj)
+{
+ cx->globalObject = obj;
+
+#if JS_HAS_XML_SUPPORT
+ cx->xmlSettingFlags = 0;
+#endif
+}
+
+JS_BEGIN_EXTERN_C
+
+JSObject *
+js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
+{
+ JSDHashTable *table;
+ JSBool resolving;
+ JSRuntime *rt;
+ JSResolvingKey key;
+ JSResolvingEntry *entry;
+ JSObject *fun_proto, *obj_proto;
+
+ /* If cx has no global object, use obj so prototypes can be found. */
+ if (!cx->globalObject)
+ JS_SetGlobalObject(cx, obj);
+
+ /* Record Function and Object in cx->resolvingTable, if we are resolving. */
+ table = cx->resolvingTable;
+ resolving = (table && table->entryCount);
+ rt = cx->runtime;
+ key.obj = obj;
+ if (resolving) {
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Function]);
+ entry = (JSResolvingEntry *)
+ JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
+ if (entry && entry->key.obj && (entry->flags & JSRESFLAG_LOOKUP)) {
+ /* Already resolving Function, record Object too. */
+ JS_ASSERT(entry->key.obj == obj);
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
+ entry = (JSResolvingEntry *)
+ JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
+ }
+ if (!entry) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ JS_ASSERT(!entry->key.obj && entry->flags == 0);
+ entry->key = key;
+ entry->flags = JSRESFLAG_LOOKUP;
+ } else {
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
+ if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry))
+ return NULL;
+
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Function]);
+ if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry)) {
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
+ JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
+ return NULL;
+ }
+
+ table = cx->resolvingTable;
+ }
+
+ /* Initialize the function class first so constructors can be made. */
+ if (!js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Function),
+ &fun_proto)) {
+ fun_proto = NULL;
+ goto out;
+ }
+ if (!fun_proto) {
+ fun_proto = js_InitFunctionClass(cx, obj);
+ if (!fun_proto)
+ goto out;
+ } else {
+ JSObject *ctor;
+
+ ctor = JS_GetConstructor(cx, fun_proto);
+ if (!ctor) {
+ fun_proto = NULL;
+ goto out;
+ }
+ OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(CLASS_ATOM(cx, Function)),
+ OBJECT_TO_JSVAL(ctor), 0, 0, 0, NULL);
+ }
+
+ /* Initialize the object class next so Object.prototype works. */
+ if (!js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object),
+ &obj_proto)) {
+ fun_proto = NULL;
+ goto out;
+ }
+ if (!obj_proto)
+ obj_proto = js_InitObjectClass(cx, obj);
+ if (!obj_proto) {
+ fun_proto = NULL;
+ goto out;
+ }
+
+ /* Function.prototype and the global object delegate to Object.prototype. */
+ OBJ_SET_PROTO(cx, fun_proto, obj_proto);
+ if (!OBJ_GET_PROTO(cx, obj))
+ OBJ_SET_PROTO(cx, obj, obj_proto);
+
+out:
+ /* If resolving, remove the other entry (Object or Function) from table. */
+ JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
+ if (!resolving) {
+ /* If not resolving, remove the first entry added above, for Object. */
+ JS_ASSERT(key.id == \
+ ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Function]));
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
+ JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
+ }
+ return fun_proto;
+}
+
+JS_END_EXTERN_C
+
+JS_PUBLIC_API(JSBool)
+JS_InitStandardClasses(JSContext *cx, JSObject *obj)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+
+ /* Define a top-level property 'undefined' with the undefined value. */
+ atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
+ NULL, NULL, JSPROP_PERMANENT, NULL)) {
+ return JS_FALSE;
+ }
+
+ /* Function and Object require cooperative bootstrapping magic. */
+ if (!js_InitFunctionAndObjectClasses(cx, obj))
+ return JS_FALSE;
+
+ /* Initialize the rest of the standard objects and functions. */
+ return js_InitArrayClass(cx, obj) &&
+ js_InitBlockClass(cx, obj) &&
+ js_InitBooleanClass(cx, obj) &&
+ js_InitCallClass(cx, obj) &&
+ js_InitExceptionClasses(cx, obj) &&
+ js_InitMathClass(cx, obj) &&
+ js_InitNumberClass(cx, obj) &&
+ js_InitJSONClass(cx, obj) &&
+ js_InitRegExpClass(cx, obj) &&
+ js_InitStringClass(cx, obj) &&
+ js_InitEval(cx, obj) &&
+#if JS_HAS_SCRIPT_OBJECT
+ js_InitScriptClass(cx, obj) &&
+#endif
+#if JS_HAS_XML_SUPPORT
+ js_InitXMLClasses(cx, obj) &&
+#endif
+#if JS_HAS_FILE_OBJECT
+ js_InitFileClass(cx, obj) &&
+#endif
+#if JS_HAS_GENERATORS
+ js_InitIteratorClasses(cx, obj) &&
+#endif
+ js_InitDateClass(cx, obj);
+}
+
+#define CLASP(name) (&js_##name##Class)
+#define EXT_CLASP(name) (&js_##name##Class.base)
+#define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
+#define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
+#define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
+#define EAGER_ATOM_AND_EXT_CLASP(name) EAGER_CLASS_ATOM(name), EXT_CLASP(name)
+#define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
+
+typedef struct JSStdName {
+ JSObjectOp init;
+ size_t atomOffset; /* offset of atom pointer in JSAtomState */
+ const char *name; /* null if atom is pre-pinned, else name */
+ JSClass *clasp;
+} JSStdName;
+
+static JSAtom *
+StdNameToAtom(JSContext *cx, JSStdName *stdn)
+{
+ size_t offset;
+ JSAtom *atom;
+ const char *name;
+
+ offset = stdn->atomOffset;
+ atom = OFFSET_TO_ATOM(cx->runtime, offset);
+ if (!atom) {
+ name = stdn->name;
+ if (name) {
+ atom = js_Atomize(cx, name, strlen(name), ATOM_PINNED);
+ OFFSET_TO_ATOM(cx->runtime, offset) = atom;
+ }
+ }
+ return atom;
+}
+
+/*
+ * Table of class initializers and their atom offsets in rt->atomState.
+ * If you add a "standard" class, remember to update this table.
+ */
+static JSStdName standard_class_atoms[] = {
+ {js_InitFunctionAndObjectClasses, EAGER_ATOM_AND_CLASP(Function)},
+ {js_InitFunctionAndObjectClasses, EAGER_ATOM_AND_CLASP(Object)},
+ {js_InitArrayClass, EAGER_ATOM_AND_CLASP(Array)},
+ {js_InitBlockClass, EAGER_ATOM_AND_CLASP(Block)},
+ {js_InitBooleanClass, EAGER_ATOM_AND_CLASP(Boolean)},
+ {js_InitDateClass, EAGER_ATOM_AND_CLASP(Date)},
+ {js_InitMathClass, EAGER_ATOM_AND_CLASP(Math)},
+ {js_InitNumberClass, EAGER_ATOM_AND_CLASP(Number)},
+ {js_InitStringClass, EAGER_ATOM_AND_CLASP(String)},
+ {js_InitCallClass, EAGER_ATOM_AND_CLASP(Call)},
+ {js_InitExceptionClasses, EAGER_ATOM_AND_CLASP(Error)},
+ {js_InitRegExpClass, EAGER_ATOM_AND_CLASP(RegExp)},
+#if JS_HAS_SCRIPT_OBJECT
+ {js_InitScriptClass, EAGER_ATOM_AND_CLASP(Script)},
+#endif
+#if JS_HAS_XML_SUPPORT
+ {js_InitXMLClass, EAGER_ATOM_AND_CLASP(XML)},
+ {js_InitNamespaceClass, EAGER_ATOM_AND_EXT_CLASP(Namespace)},
+ {js_InitQNameClass, EAGER_ATOM_AND_EXT_CLASP(QName)},
+#endif
+#if JS_HAS_FILE_OBJECT
+ {js_InitFileClass, EAGER_ATOM_AND_CLASP(File)},
+#endif
+#if JS_HAS_GENERATORS
+ {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(StopIteration)},
+#endif
+ {js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)},
+ {NULL, 0, NULL, NULL}
+};
+
+/*
+ * Table of top-level function and constant names and their init functions.
+ * If you add a "standard" global function or property, remember to update
+ * this table.
+ */
+static JSStdName standard_class_names[] = {
+ /* ECMA requires that eval be a direct property of the global object. */
+ {js_InitEval, EAGER_ATOM(eval), NULL},
+
+ /* Global properties and functions defined by the Number class. */
+ {js_InitNumberClass, LAZY_ATOM(NaN), NULL},
+ {js_InitNumberClass, LAZY_ATOM(Infinity), NULL},
+ {js_InitNumberClass, LAZY_ATOM(isNaN), NULL},
+ {js_InitNumberClass, LAZY_ATOM(isFinite), NULL},
+ {js_InitNumberClass, LAZY_ATOM(parseFloat), NULL},
+ {js_InitNumberClass, LAZY_ATOM(parseInt), NULL},
+
+ /* String global functions. */
+ {js_InitStringClass, LAZY_ATOM(escape), NULL},
+ {js_InitStringClass, LAZY_ATOM(unescape), NULL},
+ {js_InitStringClass, LAZY_ATOM(decodeURI), NULL},
+ {js_InitStringClass, LAZY_ATOM(encodeURI), NULL},
+ {js_InitStringClass, LAZY_ATOM(decodeURIComponent), NULL},
+ {js_InitStringClass, LAZY_ATOM(encodeURIComponent), NULL},
+#if JS_HAS_UNEVAL
+ {js_InitStringClass, LAZY_ATOM(uneval), NULL},
+#endif
+
+ /* Exception constructors. */
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(Error), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(InternalError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(EvalError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(RangeError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(ReferenceError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(SyntaxError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(TypeError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(URIError), CLASP(Error)},
+
+#if JS_HAS_XML_SUPPORT
+ {js_InitAnyNameClass, EAGER_ATOM_AND_CLASP(AnyName)},
+ {js_InitAttributeNameClass, EAGER_ATOM_AND_CLASP(AttributeName)},
+ {js_InitXMLClass, LAZY_ATOM(XMLList), &js_XMLClass},
+ {js_InitXMLClass, LAZY_ATOM(isXMLName), NULL},
+#endif
+
+#if JS_HAS_GENERATORS
+ {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(Iterator)},
+ {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(Generator)},
+#endif
+
+ {NULL, 0, NULL, NULL}
+};
+
+static JSStdName object_prototype_names[] = {
+ /* Object.prototype properties (global delegates to Object.prototype). */
+ {js_InitObjectClass, EAGER_ATOM(proto), NULL},
+ {js_InitObjectClass, EAGER_ATOM(parent), NULL},
+ {js_InitObjectClass, EAGER_ATOM(count), NULL},
+#if JS_HAS_TOSOURCE
+ {js_InitObjectClass, EAGER_ATOM(toSource), NULL},
+#endif
+ {js_InitObjectClass, EAGER_ATOM(toString), NULL},
+ {js_InitObjectClass, EAGER_ATOM(toLocaleString), NULL},
+ {js_InitObjectClass, EAGER_ATOM(valueOf), NULL},
+#if JS_HAS_OBJ_WATCHPOINT
+ {js_InitObjectClass, LAZY_ATOM(watch), NULL},
+ {js_InitObjectClass, LAZY_ATOM(unwatch), NULL},
+#endif
+ {js_InitObjectClass, LAZY_ATOM(hasOwnProperty), NULL},
+ {js_InitObjectClass, LAZY_ATOM(isPrototypeOf), NULL},
+ {js_InitObjectClass, LAZY_ATOM(propertyIsEnumerable), NULL},
+#if JS_HAS_GETTER_SETTER
+ {js_InitObjectClass, LAZY_ATOM(defineGetter), NULL},
+ {js_InitObjectClass, LAZY_ATOM(defineSetter), NULL},
+ {js_InitObjectClass, LAZY_ATOM(lookupGetter), NULL},
+ {js_InitObjectClass, LAZY_ATOM(lookupSetter), NULL},
+#endif
+
+ {NULL, 0, NULL, NULL}
+};
+
+JS_PUBLIC_API(JSBool)
+JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
+ JSBool *resolved)
+{
+ JSString *idstr;
+ JSRuntime *rt;
+ JSAtom *atom;
+ JSStdName *stdnm;
+ uintN i;
+
+ CHECK_REQUEST(cx);
+ *resolved = JS_FALSE;
+
+ rt = cx->runtime;
+ JS_ASSERT(rt->state != JSRTS_DOWN);
+ if (rt->state == JSRTS_LANDING || !JSVAL_IS_STRING(id))
+ return JS_TRUE;
+
+ idstr = JSVAL_TO_STRING(id);
+
+ /* Check whether we're resolving 'undefined', and define it if so. */
+ atom = rt->atomState.typeAtoms[JSTYPE_VOID];
+ if (idstr == ATOM_TO_STRING(atom)) {
+ *resolved = JS_TRUE;
+ return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
+ NULL, NULL, JSPROP_PERMANENT, NULL);
+ }
+
+ /* Try for class constructors/prototypes named by well-known atoms. */
+ stdnm = NULL;
+ for (i = 0; standard_class_atoms[i].init; i++) {
+ atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
+ if (idstr == ATOM_TO_STRING(atom)) {
+ stdnm = &standard_class_atoms[i];
+ break;
+ }
+ }
+
+ if (!stdnm) {
+ /* Try less frequently used top-level functions and constants. */
+ for (i = 0; standard_class_names[i].init; i++) {
+ atom = StdNameToAtom(cx, &standard_class_names[i]);
+ if (!atom)
+ return JS_FALSE;
+ if (idstr == ATOM_TO_STRING(atom)) {
+ stdnm = &standard_class_names[i];
+ break;
+ }
+ }
+
+ if (!stdnm && !OBJ_GET_PROTO(cx, obj)) {
+ /*
+ * Try even less frequently used names delegated from the global
+ * object to Object.prototype, but only if the Object class hasn't
+ * yet been initialized.
+ */
+ for (i = 0; object_prototype_names[i].init; i++) {
+ atom = StdNameToAtom(cx, &object_prototype_names[i]);
+ if (!atom)
+ return JS_FALSE;
+ if (idstr == ATOM_TO_STRING(atom)) {
+ stdnm = &standard_class_names[i];
+ break;
+ }
+ }
+ }
+ }
+
+ if (stdnm) {
+ /*
+ * If this standard class is anonymous and obj advertises itself as a
+ * global object (in order to reserve slots for standard class object
+ * pointers), then we don't want to resolve by name.
+ *
+ * If inversely, either id does not name a class, or id does not name
+ * an anonymous class, or the global does not reserve slots for class
+ * objects, then we must call the init hook here.
+ */
+ if (stdnm->clasp &&
+ (stdnm->clasp->flags & JSCLASS_IS_ANONYMOUS) &&
+ (OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL)) {
+ return JS_TRUE;
+ }
+
+ if (!stdnm->init(cx, obj))
+ return JS_FALSE;
+ *resolved = JS_TRUE;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom)
+{
+ JSScopeProperty *sprop;
+ JSScope *scope;
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom));
+ JS_UNLOCK_SCOPE(cx, scope);
+ return sprop != NULL;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
+{
+ JSRuntime *rt;
+ JSAtom *atom;
+ uintN i;
+
+ CHECK_REQUEST(cx);
+ rt = cx->runtime;
+
+ /* Check whether we need to bind 'undefined' and define it if so. */
+ atom = rt->atomState.typeAtoms[JSTYPE_VOID];
+ if (!AlreadyHasOwnProperty(cx, obj, atom) &&
+ !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
+ NULL, NULL, JSPROP_PERMANENT, NULL)) {
+ return JS_FALSE;
+ }
+
+ /* Initialize any classes that have not been resolved yet. */
+ for (i = 0; standard_class_atoms[i].init; i++) {
+ atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
+ if (!AlreadyHasOwnProperty(cx, obj, atom) &&
+ !standard_class_atoms[i].init(cx, obj)) {
+ return JS_FALSE;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSIdArray *
+NewIdArray(JSContext *cx, jsint length)
+{
+ JSIdArray *ida;
+
+ ida = (JSIdArray *)
+ JS_malloc(cx, offsetof(JSIdArray, vector) + length * sizeof(jsval));
+ if (ida)
+ ida->length = length;
+ return ida;
+}
+
+/*
+ * Unlike realloc(3), this function frees ida on failure.
+ */
+static JSIdArray *
+SetIdArrayLength(JSContext *cx, JSIdArray *ida, jsint length)
+{
+ JSIdArray *rida;
+
+ rida = (JSIdArray *)
+ JS_realloc(cx, ida,
+ offsetof(JSIdArray, vector) + length * sizeof(jsval));
+ if (!rida)
+ JS_DestroyIdArray(cx, ida);
+ else
+ rida->length = length;
+ return rida;
+}
+
+static JSIdArray *
+AddAtomToArray(JSContext *cx, JSAtom *atom, JSIdArray *ida, jsint *ip)
+{
+ jsint i, length;
+
+ i = *ip;
+ length = ida->length;
+ if (i >= length) {
+ ida = SetIdArrayLength(cx, ida, JS_MAX(length * 2, 8));
+ if (!ida)
+ return NULL;
+ JS_ASSERT(i < ida->length);
+ }
+ ida->vector[i] = ATOM_TO_JSID(atom);
+ *ip = i + 1;
+ return ida;
+}
+
+static JSIdArray *
+EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida,
+ jsint *ip, JSBool *foundp)
+{
+ *foundp = AlreadyHasOwnProperty(cx, obj, atom);
+ if (*foundp)
+ ida = AddAtomToArray(cx, atom, ida, ip);
+ return ida;
+}
+
+JS_PUBLIC_API(JSIdArray *)
+JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
+ JSIdArray *ida)
+{
+ JSRuntime *rt;
+ jsint i, j, k;
+ JSAtom *atom;
+ JSBool found;
+ JSObjectOp init;
+
+ CHECK_REQUEST(cx);
+ rt = cx->runtime;
+ if (ida) {
+ i = ida->length;
+ } else {
+ ida = NewIdArray(cx, 8);
+ if (!ida)
+ return NULL;
+ i = 0;
+ }
+
+ /* Check whether 'undefined' has been resolved and enumerate it if so. */
+ atom = rt->atomState.typeAtoms[JSTYPE_VOID];
+ ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
+ if (!ida)
+ return NULL;
+
+ /* Enumerate only classes that *have* been resolved. */
+ for (j = 0; standard_class_atoms[j].init; j++) {
+ atom = OFFSET_TO_ATOM(rt, standard_class_atoms[j].atomOffset);
+ ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
+ if (!ida)
+ return NULL;
+
+ if (found) {
+ init = standard_class_atoms[j].init;
+
+ for (k = 0; standard_class_names[k].init; k++) {
+ if (standard_class_names[k].init == init) {
+ atom = StdNameToAtom(cx, &standard_class_names[k]);
+ ida = AddAtomToArray(cx, atom, ida, &i);
+ if (!ida)
+ return NULL;
+ }
+ }
+
+ if (init == js_InitObjectClass) {
+ for (k = 0; object_prototype_names[k].init; k++) {
+ atom = StdNameToAtom(cx, &object_prototype_names[k]);
+ ida = AddAtomToArray(cx, atom, ida, &i);
+ if (!ida)
+ return NULL;
+ }
+ }
+ }
+ }
+
+ /* Trim to exact length. */
+ return SetIdArrayLength(cx, ida, i);
+}
+
+#undef CLASP
+#undef EAGER_ATOM
+#undef EAGER_CLASS_ATOM
+#undef EAGER_ATOM_CLASP
+#undef LAZY_ATOM
+
+JS_PUBLIC_API(JSBool)
+JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
+ JSObject **objp)
+{
+ CHECK_REQUEST(cx);
+ return js_GetClassObject(cx, obj, key, objp);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetScopeChain(JSContext *cx)
+{
+ JSStackFrame *fp;
+
+ CHECK_REQUEST(cx);
+ fp = cx->fp;
+ if (!fp) {
+ /*
+ * There is no code active on this context. In place of an actual
+ * scope chain, use the context's global object, which is set in
+ * js_InitFunctionAndObjectClasses, and which represents the default
+ * scope chain for the embedding. See also js_FindClassObject.
+ *
+ * For embeddings that use the inner and outer object hooks, the inner
+ * object represents the ultimate global object, with the outer object
+ * acting as a stand-in.
+ */
+ JSObject *obj = cx->globalObject;
+ if (!obj) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
+ return NULL;
+ }
+
+ OBJ_TO_INNER_OBJECT(cx, obj);
+ return obj;
+ }
+ return js_GetScopeChain(cx, fp);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
+{
+ JSObject *parent;
+
+ while ((parent = OBJ_GET_PARENT(cx, obj)) != NULL)
+ obj = parent;
+ return obj;
+}
+
+JS_PUBLIC_API(jsval)
+JS_ComputeThis(JSContext *cx, jsval *vp)
+{
+ if (!js_ComputeThis(cx, JS_FALSE, vp + 2))
+ return JSVAL_NULL;
+ return vp[1];
+}
+
+JS_PUBLIC_API(void *)
+JS_malloc(JSContext *cx, size_t nbytes)
+{
+ void *p;
+
+ JS_ASSERT(nbytes != 0);
+ JS_COUNT_OPERATION(cx, JSOW_ALLOCATION);
+ if (nbytes == 0)
+ nbytes = 1;
+
+ p = malloc(nbytes);
+ if (!p) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ js_UpdateMallocCounter(cx, nbytes);
+
+ return p;
+}
+
+JS_PUBLIC_API(void *)
+JS_realloc(JSContext *cx, void *p, size_t nbytes)
+{
+ JS_COUNT_OPERATION(cx, JSOW_ALLOCATION);
+ p = realloc(p, nbytes);
+ if (!p)
+ JS_ReportOutOfMemory(cx);
+ return p;
+}
+
+JS_PUBLIC_API(void)
+JS_free(JSContext *cx, void *p)
+{
+ if (p)
+ free(p);
+}
+
+JS_PUBLIC_API(char *)
+JS_strdup(JSContext *cx, const char *s)
+{
+ size_t n;
+ void *p;
+
+ n = strlen(s) + 1;
+ p = JS_malloc(cx, n);
+ if (!p)
+ return NULL;
+ return (char *)memcpy(p, s, n);
+}
+
+JS_PUBLIC_API(jsdouble *)
+JS_NewDouble(JSContext *cx, jsdouble d)
+{
+ CHECK_REQUEST(cx);
+ return js_NewWeaklyRootedDouble(cx, d);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
+{
+ jsdouble *dp;
+
+ CHECK_REQUEST(cx);
+ dp = js_NewWeaklyRootedDouble(cx, d);
+ if (!dp)
+ return JS_FALSE;
+ *rval = DOUBLE_TO_JSVAL(dp);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
+{
+ jsint i;
+
+ CHECK_REQUEST(cx);
+ if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
+ *rval = INT_TO_JSVAL(i);
+ return JS_TRUE;
+ }
+ return JS_NewDoubleValue(cx, d, rval);
+}
+
+#undef JS_AddRoot
+JS_PUBLIC_API(JSBool)
+JS_AddRoot(JSContext *cx, void *rp)
+{
+ CHECK_REQUEST(cx);
+ return js_AddRoot(cx, rp, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name)
+{
+ return js_AddRootRT(rt, rp, name);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_RemoveRoot(JSContext *cx, void *rp)
+{
+ CHECK_REQUEST(cx);
+ return js_RemoveRoot(cx->runtime, rp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_RemoveRootRT(JSRuntime *rt, void *rp)
+{
+ return js_RemoveRoot(rt, rp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddNamedRoot(JSContext *cx, void *rp, const char *name)
+{
+ CHECK_REQUEST(cx);
+ return js_AddRoot(cx, rp, name);
+}
+
+JS_PUBLIC_API(void)
+JS_ClearNewbornRoots(JSContext *cx)
+{
+ JS_CLEAR_WEAK_ROOTS(&cx->weakRoots);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EnterLocalRootScope(JSContext *cx)
+{
+ CHECK_REQUEST(cx);
+ return js_EnterLocalRootScope(cx);
+}
+
+JS_PUBLIC_API(void)
+JS_LeaveLocalRootScope(JSContext *cx)
+{
+ CHECK_REQUEST(cx);
+ js_LeaveLocalRootScope(cx);
+}
+
+JS_PUBLIC_API(void)
+JS_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
+{
+ CHECK_REQUEST(cx);
+ js_LeaveLocalRootScopeWithResult(cx, rval);
+}
+
+JS_PUBLIC_API(void)
+JS_ForgetLocalRoot(JSContext *cx, void *thing)
+{
+ CHECK_REQUEST(cx);
+ js_ForgetLocalRoot(cx, (jsval) thing);
+}
+
+#ifdef DEBUG
+
+JS_PUBLIC_API(void)
+JS_DumpNamedRoots(JSRuntime *rt,
+ void (*dump)(const char *name, void *rp, void *data),
+ void *data)
+{
+ js_DumpNamedRoots(rt, dump, data);
+}
+
+#endif /* DEBUG */
+
+JS_PUBLIC_API(uint32)
+JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
+{
+ return js_MapGCRoots(rt, map, data);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LockGCThing(JSContext *cx, void *thing)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ ok = js_LockGCThingRT(cx->runtime, thing);
+ if (!ok)
+ JS_ReportOutOfMemory(cx);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LockGCThingRT(JSRuntime *rt, void *thing)
+{
+ return js_LockGCThingRT(rt, thing);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_UnlockGCThing(JSContext *cx, void *thing)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ ok = js_UnlockGCThingRT(cx->runtime, thing);
+ if (!ok)
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_UNLOCK);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_UnlockGCThingRT(JSRuntime *rt, void *thing)
+{
+ return js_UnlockGCThingRT(rt, thing);
+}
+
+JS_PUBLIC_API(void)
+JS_SetExtraGCRoots(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
+{
+ rt->gcExtraRootsTraceOp = traceOp;
+ rt->gcExtraRootsData = data;
+}
+
+JS_PUBLIC_API(void)
+JS_TraceRuntime(JSTracer *trc)
+{
+ JSBool allAtoms = trc->context->runtime->gcKeepAtoms != 0;
+
+ js_TraceRuntime(trc, allAtoms);
+}
+
+#ifdef DEBUG
+
+#ifdef HAVE_XPCONNECT
+#include "dump_xpc.h"
+#endif
+
+JS_PUBLIC_API(void)
+JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
+ void *thing, uint32 kind, JSBool details)
+{
+ const char *name;
+ size_t n;
+
+ if (bufsize == 0)
+ return;
+
+ switch (kind) {
+ case JSTRACE_OBJECT:
+ {
+ JSObject *obj = (JSObject *)thing;
+ JSClass *clasp = STOBJ_GET_CLASS(obj);
+
+ name = clasp->name;
+#ifdef HAVE_XPCONNECT
+ if (clasp->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) {
+ jsval privateValue = STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
+
+ JS_ASSERT(clasp->flags & JSCLASS_HAS_PRIVATE);
+ if (!JSVAL_IS_VOID(privateValue)) {
+ void *privateThing = JSVAL_TO_PRIVATE(privateValue);
+ const char *xpcClassName = GetXPCObjectClassName(privateThing);
+
+ if (xpcClassName)
+ name = xpcClassName;
+ }
+ }
+#endif
+ break;
+ }
+
+ case JSTRACE_STRING:
+ name = JSSTRING_IS_DEPENDENT((JSString *)thing)
+ ? "substring"
+ : "string";
+ break;
+
+ case JSTRACE_DOUBLE:
+ name = "double";
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case JSTRACE_XML:
+ name = "xml";
+ break;
+#endif
+ default:
+ JS_ASSERT(0);
+ return;
+ break;
+ }
+
+ n = strlen(name);
+ if (n > bufsize - 1)
+ n = bufsize - 1;
+ memcpy(buf, name, n + 1);
+ buf += n;
+ bufsize -= n;
+
+ if (details && bufsize > 2) {
+ *buf++ = ' ';
+ bufsize--;
+
+ switch (kind) {
+ case JSTRACE_OBJECT:
+ {
+ JSObject *obj = (JSObject *)thing;
+ JSClass *clasp = STOBJ_GET_CLASS(obj);
+ if (clasp == &js_FunctionClass) {
+ JSFunction *fun = (JSFunction *)
+ JS_GetPrivate(trc->context, obj);
+
+ if (!fun) {
+ JS_snprintf(buf, bufsize, "<newborn>");
+ } else if (FUN_OBJECT(fun) != obj) {
+ JS_snprintf(buf, bufsize, "%p", fun);
+ } else {
+ if (fun->atom && ATOM_IS_STRING(fun->atom))
+ js_PutEscapedString(buf, bufsize,
+ ATOM_TO_STRING(fun->atom), 0);
+ }
+ } else if (clasp->flags & JSCLASS_HAS_PRIVATE) {
+ jsval privateValue = STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
+ void *privateThing = JSVAL_IS_VOID(privateValue)
+ ? NULL
+ : JSVAL_TO_PRIVATE(privateValue);
+
+ JS_snprintf(buf, bufsize, "%p", privateThing);
+ } else {
+ JS_snprintf(buf, bufsize, "<no private>");
+ }
+ break;
+ }
+
+ case JSTRACE_STRING:
+ js_PutEscapedString(buf, bufsize, (JSString *)thing, 0);
+ break;
+
+ case JSTRACE_DOUBLE:
+ JS_snprintf(buf, bufsize, "%g", *(jsdouble *)thing);
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case JSTRACE_XML:
+ {
+ extern const char *js_xml_class_str[];
+ JSXML *xml = (JSXML *)thing;
+
+ JS_snprintf(buf, bufsize, "%s", js_xml_class_str[xml->xml_class]);
+ break;
+ }
+#endif
+ default:
+ JS_ASSERT(0);
+ break;
+ }
+ }
+ buf[bufsize - 1] = '\0';
+}
+
+typedef struct JSHeapDumpNode JSHeapDumpNode;
+
+struct JSHeapDumpNode {
+ void *thing;
+ uint32 kind;
+ JSHeapDumpNode *next; /* next sibling */
+ JSHeapDumpNode *parent; /* node with the thing that refer to thing
+ from this node */
+ char edgeName[1]; /* name of the edge from parent->thing
+ into thing */
+};
+
+typedef struct JSDumpingTracer {
+ JSTracer base;
+ JSDHashTable visited;
+ JSBool ok;
+ void *startThing;
+ void *thingToFind;
+ void *thingToIgnore;
+ JSHeapDumpNode *parentNode;
+ JSHeapDumpNode **lastNodep;
+ char buffer[200];
+} JSDumpingTracer;
+
+static void
+DumpNotify(JSTracer *trc, void *thing, uint32 kind)
+{
+ JSDumpingTracer *dtrc;
+ JSContext *cx;
+ JSDHashEntryStub *entry;
+ JSHeapDumpNode *node;
+ const char *edgeName;
+ size_t edgeNameSize;
+
+ JS_ASSERT(trc->callback == DumpNotify);
+ dtrc = (JSDumpingTracer *)trc;
+
+ if (!dtrc->ok || thing == dtrc->thingToIgnore)
+ return;
+
+ cx = trc->context;
+
+ /*
+ * Check if we have already seen thing unless it is thingToFind to include
+ * it to the graph each time we reach it and print all live things that
+ * refer to thingToFind.
+ *
+ * This does not print all possible paths leading to thingToFind since
+ * when a thing A refers directly or indirectly to thingToFind and A is
+ * present several times in the graph, we will print only the first path
+ * leading to A and thingToFind, other ways to reach A will be ignored.
+ */
+ if (dtrc->thingToFind != thing) {
+ /*
+ * The startThing check allows to avoid putting startThing into the
+ * hash table before tracing startThing in JS_DumpHeap.
+ */
+ if (thing == dtrc->startThing)
+ return;
+ entry = (JSDHashEntryStub *)
+ JS_DHashTableOperate(&dtrc->visited, thing, JS_DHASH_ADD);
+ if (!entry) {
+ JS_ReportOutOfMemory(cx);
+ dtrc->ok = JS_FALSE;
+ return;
+ }
+ if (entry->key)
+ return;
+ entry->key = thing;
+ }
+
+ if (dtrc->base.debugPrinter) {
+ dtrc->base.debugPrinter(trc, dtrc->buffer, sizeof(dtrc->buffer));
+ edgeName = dtrc->buffer;
+ } else if (dtrc->base.debugPrintIndex != (size_t)-1) {
+ JS_snprintf(dtrc->buffer, sizeof(dtrc->buffer), "%s[%lu]",
+ (const char *)dtrc->base.debugPrintArg,
+ dtrc->base.debugPrintIndex);
+ edgeName = dtrc->buffer;
+ } else {
+ edgeName = (const char*)dtrc->base.debugPrintArg;
+ }
+
+ edgeNameSize = strlen(edgeName) + 1;
+ node = (JSHeapDumpNode *)
+ JS_malloc(cx, offsetof(JSHeapDumpNode, edgeName) + edgeNameSize);
+ if (!node) {
+ dtrc->ok = JS_FALSE;
+ return;
+ }
+
+ node->thing = thing;
+ node->kind = kind;
+ node->next = NULL;
+ node->parent = dtrc->parentNode;
+ memcpy(node->edgeName, edgeName, edgeNameSize);
+
+ JS_ASSERT(!*dtrc->lastNodep);
+ *dtrc->lastNodep = node;
+ dtrc->lastNodep = &node->next;
+}
+
+/* Dump node and the chain that leads to thing it contains. */
+static JSBool
+DumpNode(JSDumpingTracer *dtrc, FILE* fp, JSHeapDumpNode *node)
+{
+ JSHeapDumpNode *prev, *following;
+ size_t chainLimit;
+ JSBool ok;
+ enum { MAX_PARENTS_TO_PRINT = 10 };
+
+ JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
+ &dtrc->base, node->thing, node->kind, JS_TRUE);
+ if (fprintf(fp, "%p %-22s via ", node->thing, dtrc->buffer) < 0)
+ return JS_FALSE;
+
+ /*
+ * We need to print the parent chain in the reverse order. To do it in
+ * O(N) time where N is the chain length we first reverse the chain while
+ * searching for the top and then print each node while restoring the
+ * chain order.
+ */
+ chainLimit = MAX_PARENTS_TO_PRINT;
+ prev = NULL;
+ for (;;) {
+ following = node->parent;
+ node->parent = prev;
+ prev = node;
+ node = following;
+ if (!node)
+ break;
+ if (chainLimit == 0) {
+ if (fputs("...", fp) < 0)
+ return JS_FALSE;
+ break;
+ }
+ --chainLimit;
+ }
+
+ node = prev;
+ prev = following;
+ ok = JS_TRUE;
+ do {
+ /* Loop must continue even when !ok to restore the parent chain. */
+ if (ok) {
+ if (!prev) {
+ /* Print edge from some runtime root or startThing. */
+ if (fputs(node->edgeName, fp) < 0)
+ ok = JS_FALSE;
+ } else {
+ JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
+ &dtrc->base, prev->thing, prev->kind,
+ JS_FALSE);
+ if (fprintf(fp, "(%p %s).%s",
+ prev->thing, dtrc->buffer, node->edgeName) < 0) {
+ ok = JS_FALSE;
+ }
+ }
+ }
+ following = node->parent;
+ node->parent = prev;
+ prev = node;
+ node = following;
+ } while (node);
+
+ return ok && putc('\n', fp) >= 0;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, uint32 startKind,
+ void *thingToFind, size_t maxDepth, void *thingToIgnore)
+{
+ JSDumpingTracer dtrc;
+ JSHeapDumpNode *node, *children, *next, *parent;
+ size_t depth;
+ JSBool thingToFindWasTraced;
+
+ if (maxDepth == 0)
+ return JS_TRUE;
+
+ JS_TRACER_INIT(&dtrc.base, cx, DumpNotify);
+ if (!JS_DHashTableInit(&dtrc.visited, JS_DHashGetStubOps(),
+ NULL, sizeof(JSDHashEntryStub),
+ JS_DHASH_DEFAULT_CAPACITY(100))) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ dtrc.ok = JS_TRUE;
+ dtrc.startThing = startThing;
+ dtrc.thingToFind = thingToFind;
+ dtrc.thingToIgnore = thingToIgnore;
+ dtrc.parentNode = NULL;
+ node = NULL;
+ dtrc.lastNodep = &node;
+ if (!startThing) {
+ JS_ASSERT(startKind == 0);
+ JS_TraceRuntime(&dtrc.base);
+ } else {
+ JS_TraceChildren(&dtrc.base, startThing, startKind);
+ }
+
+ depth = 1;
+ if (!node)
+ goto dump_out;
+
+ thingToFindWasTraced = thingToFind && thingToFind == startThing;
+ for (;;) {
+ /*
+ * Loop must continue even when !dtrc.ok to free all nodes allocated
+ * so far.
+ */
+ if (dtrc.ok) {
+ if (thingToFind == NULL || thingToFind == node->thing)
+ dtrc.ok = DumpNode(&dtrc, fp, node);
+
+ /* Descend into children. */
+ if (dtrc.ok &&
+ depth < maxDepth &&
+ (thingToFind != node->thing || !thingToFindWasTraced)) {
+ dtrc.parentNode = node;
+ children = NULL;
+ dtrc.lastNodep = &children;
+ JS_TraceChildren(&dtrc.base, node->thing, node->kind);
+ if (thingToFind == node->thing)
+ thingToFindWasTraced = JS_TRUE;
+ if (children != NULL) {
+ ++depth;
+ node = children;
+ continue;
+ }
+ }
+ }
+
+ /* Move to next or parents next and free the node. */
+ for (;;) {
+ next = node->next;
+ parent = node->parent;
+ JS_free(cx, node);
+ node = next;
+ if (node)
+ break;
+ if (!parent)
+ goto dump_out;
+ JS_ASSERT(depth > 1);
+ --depth;
+ node = parent;
+ }
+ }
+
+ dump_out:
+ JS_ASSERT(depth == 1);
+ JS_DHashTableFinish(&dtrc.visited);
+ return dtrc.ok;
+}
+
+#endif /* DEBUG */
+
+JS_PUBLIC_API(void)
+JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg)
+{
+ JSTracer *trc;
+
+ trc = (JSTracer *)arg;
+ if (!trc)
+ trc = cx->runtime->gcMarkingTracer;
+ else
+ JS_ASSERT(trc == cx->runtime->gcMarkingTracer);
+
+#ifdef JS_THREADSAFE
+ JS_ASSERT(cx->runtime->gcThread == trc->context->thread);
+#endif
+ JS_SET_TRACING_NAME(trc, name ? name : "unknown");
+ js_CallValueTracerIfGCThing(trc, (jsval)thing);
+}
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsGCMarkingTracer(JSTracer *trc)
+{
+ return IS_GC_MARKING_TRACER(trc);
+}
+
+JS_PUBLIC_API(void)
+JS_GC(JSContext *cx)
+{
+ /* Don't nuke active arenas if executing or compiling. */
+ if (cx->stackPool.current == &cx->stackPool.first)
+ JS_FinishArenaPool(&cx->stackPool);
+ if (cx->tempPool.current == &cx->tempPool.first)
+ JS_FinishArenaPool(&cx->tempPool);
+ js_GC(cx, GC_NORMAL);
+}
+
+JS_PUBLIC_API(void)
+JS_MaybeGC(JSContext *cx)
+{
+ JSRuntime *rt;
+ uint32 bytes, lastBytes;
+
+ rt = cx->runtime;
+
+#ifdef JS_GC_ZEAL
+ if (rt->gcZeal > 0) {
+ JS_GC(cx);
+ return;
+ }
+#endif
+
+ bytes = rt->gcBytes;
+ lastBytes = rt->gcLastBytes;
+
+ /*
+ * We run the GC if we used all available free GC cells and had to
+ * allocate extra 1/3 of GC arenas since the last run of GC, or if
+ * we have malloc'd more bytes through JS_malloc than we were told
+ * to allocate by JS_NewRuntime.
+ *
+ * The reason for
+ * bytes > 4/3 lastBytes
+ * condition is the following. Bug 312238 changed bytes and lastBytes
+ * to mean the total amount of memory that the GC uses now and right
+ * after the last GC.
+ *
+ * Before the bug the variables meant the size of allocated GC things
+ * now and right after the last GC. That size did not include the
+ * memory taken by free GC cells and the condition was
+ * bytes > 3/2 lastBytes.
+ * That is, we run the GC if we have half again as many bytes of
+ * GC-things as the last time we GC'd. To be compatible we need to
+ * express that condition through the new meaning of bytes and
+ * lastBytes.
+ *
+ * We write the original condition as
+ * B*(1-F) > 3/2 Bl*(1-Fl)
+ * where B is the total memory size allocated by GC and F is the free
+ * cell density currently and Sl and Fl are the size and the density
+ * right after GC. The density by definition is memory taken by free
+ * cells divided by total amount of memory. In other words, B and Bl
+ * are bytes and lastBytes with the new meaning and B*(1-F) and
+ * Bl*(1-Fl) are bytes and lastBytes with the original meaning.
+ *
+ * Our task is to exclude F and Fl from the last statement. According
+ * to the stats from bug 331966 comment 23, Fl is about 10-25% for a
+ * typical run of the browser. It means that the original condition
+ * implied that we did not run GC unless we exhausted the pool of
+ * free cells. Indeed if we still have free cells, then B == Bl since
+ * we did not yet allocated any new arenas and the condition means
+ * 1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F
+ * That implies 3/2 Fl > 1/2 or Fl > 1/3. That can not be fulfilled
+ * for the state described by the stats. So we can write the original
+ * condition as:
+ * F == 0 && B > 3/2 Bl(1-Fl)
+ * Again using the stats we see that Fl is about 11% when the browser
+ * starts up and when we are far from hitting rt->gcMaxBytes. With
+ * this F we have
+ * F == 0 && B > 3/2 Bl(1-0.11)
+ * or approximately F == 0 && B > 4/3 Bl.
+ */
+ if ((bytes > 8192 && bytes > lastBytes + lastBytes / 3) ||
+ rt->gcMallocBytes >= rt->gcMaxMallocBytes) {
+ JS_GC(cx);
+ }
+}
+
+JS_PUBLIC_API(JSGCCallback)
+JS_SetGCCallback(JSContext *cx, JSGCCallback cb)
+{
+ CHECK_REQUEST(cx);
+ return JS_SetGCCallbackRT(cx->runtime, cb);
+}
+
+JS_PUBLIC_API(JSGCCallback)
+JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb)
+{
+ JSGCCallback oldcb;
+
+ oldcb = rt->gcCallback;
+ rt->gcCallback = cb;
+ return oldcb;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsAboutToBeFinalized(JSContext *cx, void *thing)
+{
+ JS_ASSERT(thing);
+ return js_IsAboutToBeFinalized(cx, thing);
+}
+
+JS_PUBLIC_API(void)
+JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value)
+{
+ switch (key) {
+ case JSGC_MAX_BYTES:
+ rt->gcMaxBytes = value;
+ break;
+ case JSGC_MAX_MALLOC_BYTES:
+ rt->gcMaxMallocBytes = value;
+ break;
+ case JSGC_STACKPOOL_LIFESPAN:
+ rt->gcEmptyArenaPoolLifespan = value;
+ break;
+ }
+}
+
+JS_PUBLIC_API(intN)
+JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
+{
+ return js_ChangeExternalStringFinalizer(NULL, finalizer);
+}
+
+JS_PUBLIC_API(intN)
+JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)
+{
+ return js_ChangeExternalStringFinalizer(finalizer, NULL);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
+{
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ JS_ASSERT((uintN) type < (uintN) (GCX_NTYPES - GCX_EXTERNAL_STRING));
+
+ str = (JSString *) js_NewGCThing(cx, (uintN) type + GCX_EXTERNAL_STRING,
+ sizeof(JSString));
+ if (!str)
+ return NULL;
+ JSFLATSTR_INIT(str, chars, length);
+ return str;
+}
+
+JS_PUBLIC_API(intN)
+JS_GetExternalStringGCType(JSRuntime *rt, JSString *str)
+{
+ return js_GetExternalStringGCType(str);
+}
+
+JS_PUBLIC_API(void)
+JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr)
+{
+#if JS_STACK_GROWTH_DIRECTION > 0
+ if (limitAddr == 0)
+ limitAddr = (jsuword)-1;
+#endif
+ cx->stackLimit = limitAddr;
+}
+
+JS_PUBLIC_API(void)
+JS_SetScriptStackQuota(JSContext *cx, size_t quota)
+{
+ cx->scriptStackQuota = quota;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(void)
+JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
+{
+ JS_free(cx, ida);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
+{
+ CHECK_REQUEST(cx);
+ if (JSVAL_IS_INT(v))
+ *idp = INT_JSVAL_TO_JSID(v);
+#if JS_HAS_XML_SUPPORT
+ else if (!JSVAL_IS_PRIMITIVE(v))
+ *idp = OBJECT_JSVAL_TO_JSID(v);
+#endif
+ else
+ return js_ValueToStringId(cx, v, idp);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ *vp = ID_TO_VALUE(id);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EnumerateStub(JSContext *cx, JSObject *obj)
+{
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id)
+{
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+{
+ return js_TryValueOf(cx, obj, type, vp);
+}
+
+JS_PUBLIC_API(void)
+JS_FinalizeStub(JSContext *cx, JSObject *obj)
+{
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
+ JSClass *clasp, JSNative constructor, uintN nargs,
+ JSPropertySpec *ps, JSFunctionSpec *fs,
+ JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
+{
+ JSAtom *atom;
+ JSProtoKey key;
+ JSObject *proto, *ctor;
+ JSTempValueRooter tvr;
+ jsval cval, rval;
+ JSBool named;
+ JSFunction *fun;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
+ if (!atom)
+ return NULL;
+
+ /*
+ * When initializing a standard class, if no parent_proto (grand-proto of
+ * instances of the class, parent-proto of the class's prototype object)
+ * is given, we must use Object.prototype if it is available. Otherwise,
+ * we could look up the wrong binding for a class name in obj. Example:
+ *
+ * String = Array;
+ * print("hi there".join);
+ *
+ * should print undefined, not Array.prototype.join. This is required by
+ * ECMA-262, alas. It might have been better to make String readonly and
+ * permanent in the global object, instead -- but that's too big a change
+ * to swallow at this point.
+ */
+ key = JSCLASS_CACHED_PROTO_KEY(clasp);
+ if (key != JSProto_Null &&
+ !parent_proto &&
+ !js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object),
+ &parent_proto)) {
+ return NULL;
+ }
+
+ /* Create a prototype object for this class. */
+ proto = js_NewObject(cx, clasp, parent_proto, obj, 0);
+ if (!proto)
+ return NULL;
+
+ /* After this point, control must exit via label bad or out. */
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, proto, &tvr);
+
+ if (!constructor) {
+ /*
+ * Lacking a constructor, name the prototype (e.g., Math) unless this
+ * class (a) is anonymous, i.e. for internal use only; (b) the class
+ * of obj (the global object) is has a reserved slot indexed by key;
+ * and (c) key is not the null key.
+ */
+ if ((clasp->flags & JSCLASS_IS_ANONYMOUS) &&
+ (OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL) &&
+ key != JSProto_Null) {
+ named = JS_FALSE;
+ } else {
+ named = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
+ OBJECT_TO_JSVAL(proto),
+ JS_PropertyStub, JS_PropertyStub,
+ (clasp->flags & JSCLASS_IS_ANONYMOUS)
+ ? JSPROP_READONLY | JSPROP_PERMANENT
+ : 0,
+ NULL);
+ if (!named)
+ goto bad;
+ }
+
+ ctor = proto;
+ } else {
+ /* Define the constructor function in obj's scope. */
+ fun = js_DefineFunction(cx, obj, atom, constructor, nargs,
+ JSFUN_STUB_GSOPS);
+ named = (fun != NULL);
+ if (!fun)
+ goto bad;
+
+ /*
+ * Remember the class this function is a constructor for so that
+ * we know to create an object of this class when we call the
+ * constructor.
+ */
+ FUN_CLASP(fun) = clasp;
+
+ /*
+ * Optionally construct the prototype object, before the class has
+ * been fully initialized. Allow the ctor to replace proto with a
+ * different object, as is done for operator new -- and as at least
+ * XML support requires.
+ */
+ ctor = FUN_OBJECT(fun);
+ if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
+ cval = OBJECT_TO_JSVAL(ctor);
+ if (!js_InternalConstruct(cx, proto, cval, 0, NULL, &rval))
+ goto bad;
+ if (!JSVAL_IS_PRIMITIVE(rval) && JSVAL_TO_OBJECT(rval) != proto)
+ proto = JSVAL_TO_OBJECT(rval);
+ }
+
+ /* Connect constructor and prototype by named properties. */
+ if (!js_SetClassPrototype(cx, ctor, proto,
+ JSPROP_READONLY | JSPROP_PERMANENT)) {
+ goto bad;
+ }
+
+ /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
+ if (OBJ_GET_CLASS(cx, ctor) == clasp) {
+ OBJ_SET_PROTO(cx, ctor, proto);
+ }
+ }
+
+ /* Add properties and methods to the prototype and the constructor. */
+ if ((ps && !JS_DefineProperties(cx, proto, ps)) ||
+ (fs && !JS_DefineFunctions(cx, proto, fs)) ||
+ (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) ||
+ (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) {
+ goto bad;
+ }
+
+ /* If this is a standard class, cache its prototype. */
+ if (key != JSProto_Null && !js_SetClassObject(cx, obj, key, ctor))
+ goto bad;
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return proto;
+
+bad:
+ if (named)
+ (void) OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &rval);
+ proto = NULL;
+ goto out;
+}
+
+#ifdef JS_THREADSAFE
+JS_PUBLIC_API(JSClass *)
+JS_GetClass(JSContext *cx, JSObject *obj)
+{
+ return OBJ_GET_CLASS(cx, obj);
+}
+#else
+JS_PUBLIC_API(JSClass *)
+JS_GetClass(JSObject *obj)
+{
+ return LOCKED_OBJ_GET_CLASS(obj);
+}
+#endif
+
+JS_PUBLIC_API(JSBool)
+JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
+{
+ JSFunction *fun;
+
+ CHECK_REQUEST(cx);
+ if (obj && OBJ_GET_CLASS(cx, obj) == clasp)
+ return JS_TRUE;
+ if (argv) {
+ fun = js_ValueToFunction(cx, &argv[-2], 0);
+ if (fun) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_INCOMPATIBLE_PROTO,
+ clasp->name, JS_GetFunctionName(fun),
+ obj
+ ? OBJ_GET_CLASS(cx, obj)->name
+ : js_null_str);
+ }
+ }
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ return js_HasInstance(cx, obj, v, bp);
+}
+
+JS_PUBLIC_API(void *)
+JS_GetPrivate(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
+ v = obj->fslots[JSSLOT_PRIVATE];
+ if (!JSVAL_IS_INT(v))
+ return NULL;
+ return JSVAL_TO_PRIVATE(v);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetPrivate(JSContext *cx, JSObject *obj, void *data)
+{
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
+ obj->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(data);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(void *)
+JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
+ jsval *argv)
+{
+ if (!JS_InstanceOf(cx, obj, clasp, argv))
+ return NULL;
+ return JS_GetPrivate(cx, obj);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetPrototype(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ CHECK_REQUEST(cx);
+ proto = OBJ_GET_PROTO(cx, obj);
+
+ /* Beware ref to dead object (we may be called from obj's finalizer). */
+ return proto && proto->map ? proto : NULL;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
+{
+ CHECK_REQUEST(cx);
+ JS_ASSERT(obj != proto);
+#ifdef DEBUG
+ /*
+ * FIXME: bug 408416. The cycle-detection required for script-writeable
+ * __proto__ lives in js_SetProtoOrParent over in jsobj.c, also known as
+ * js_ObjectOps.setProto. This hook must detect cycles, to prevent scripts
+ * from ilooping SpiderMonkey trivially. But the overhead of detecting
+ * cycles is high enough, and the threat from JS-API-calling C++ code is
+ * low enough, that it's not worth burdening the non-DEBUG callers. Same
+ * goes for JS_SetParent, below.
+ */
+ if (obj->map->ops->setProto)
+ return obj->map->ops->setProto(cx, obj, JSSLOT_PROTO, proto);
+#else
+ if (OBJ_IS_NATIVE(obj)) {
+ JS_LOCK_OBJ(cx, obj);
+ if (!js_GetMutableScope(cx, obj)) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+ }
+ LOCKED_OBJ_SET_PROTO(obj, proto);
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_TRUE;
+ }
+#endif
+ OBJ_SET_PROTO(cx, obj, proto);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetParent(JSContext *cx, JSObject *obj)
+{
+ JSObject *parent;
+
+ parent = OBJ_GET_PARENT(cx, obj);
+
+ /* Beware ref to dead object (we may be called from obj's finalizer). */
+ return parent && parent->map ? parent : NULL;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
+{
+ CHECK_REQUEST(cx);
+ JS_ASSERT(obj != parent);
+#ifdef DEBUG
+ /* FIXME: bug 408416, see JS_SetPrototype just above. */
+ if (obj->map->ops->setParent)
+ return obj->map->ops->setParent(cx, obj, JSSLOT_PARENT, parent);
+#endif
+ OBJ_SET_PARENT(cx, obj, parent);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetConstructor(JSContext *cx, JSObject *proto)
+{
+ jsval cval;
+
+ CHECK_REQUEST(cx);
+ {
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+
+ if (!OBJ_GET_PROPERTY(cx, proto,
+ ATOM_TO_JSID(cx->runtime->atomState.constructorAtom),
+ &cval)) {
+ return NULL;
+ }
+ }
+ if (!VALUE_IS_FUNCTION(cx, cval)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
+ OBJ_GET_CLASS(cx, proto)->name);
+ return NULL;
+ }
+ return JSVAL_TO_OBJECT(cval);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
+{
+ JS_ASSERT(JSID_IS_OBJECT(obj));
+ *idp = OBJECT_TO_JSID(obj);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
+{
+ CHECK_REQUEST(cx);
+ if (!clasp)
+ clasp = &js_ObjectClass; /* default class is Object */
+ return js_NewObject(cx, clasp, proto, parent, 0);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent)
+{
+ CHECK_REQUEST(cx);
+ if (!clasp)
+ clasp = &js_ObjectClass; /* default class is Object */
+ return js_NewObjectWithGivenProto(cx, clasp, proto, parent, 0);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep)
+{
+ JSScope *scope;
+ JSIdArray *ida;
+ uint32 nslots, i;
+ jsval v;
+
+ if (!OBJ_IS_NATIVE(obj)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_SEAL_OBJECT,
+ OBJ_GET_CLASS(cx, obj)->name);
+ return JS_FALSE;
+ }
+
+ scope = OBJ_SCOPE(obj);
+
+#if defined JS_THREADSAFE && defined DEBUG
+ /* Insist on scope being used exclusively by cx's thread. */
+ if (scope->title.ownercx != cx) {
+ JS_LOCK_OBJ(cx, obj);
+ JS_ASSERT(OBJ_SCOPE(obj) == scope);
+ JS_ASSERT(scope->title.ownercx == cx);
+ JS_UNLOCK_SCOPE(cx, scope);
+ }
+#endif
+
+ /* Nothing to do if obj's scope is already sealed. */
+ if (SCOPE_IS_SEALED(scope))
+ return JS_TRUE;
+
+ /* XXX Enumerate lazy properties now, as they can't be added later. */
+ ida = JS_Enumerate(cx, obj);
+ if (!ida)
+ return JS_FALSE;
+ JS_DestroyIdArray(cx, ida);
+
+ /* Ensure that obj has its own, mutable scope, and seal that scope. */
+ JS_LOCK_OBJ(cx, obj);
+ scope = js_GetMutableScope(cx, obj);
+ if (scope) {
+ SCOPE_SET_SEALED(scope);
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ if (!scope)
+ return JS_FALSE;
+
+ /* If we are not sealing an entire object graph, we're done. */
+ if (!deep)
+ return JS_TRUE;
+
+ /* Walk slots in obj and if any value is a non-null object, seal it. */
+ nslots = scope->map.freeslot;
+ for (i = 0; i != nslots; ++i) {
+ v = STOBJ_GET_SLOT(obj, i);
+ if (JSVAL_IS_PRIMITIVE(v))
+ continue;
+ if (!JS_SealObject(cx, JSVAL_TO_OBJECT(v), deep))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent)
+{
+ CHECK_REQUEST(cx);
+ if (!clasp)
+ clasp = &js_ObjectClass; /* default class is Object */
+ return js_ConstructObject(cx, clasp, proto, parent, 0, NULL);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN argc, jsval *argv)
+{
+ CHECK_REQUEST(cx);
+ if (!clasp)
+ clasp = &js_ObjectClass; /* default class is Object */
+ return js_ConstructObject(cx, clasp, proto, parent, argc, argv);
+}
+
+static JSBool
+DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ uintN flags, intN tinyid)
+{
+ if (flags != 0 && OBJ_IS_NATIVE(obj)) {
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
+ return js_DefineNativeProperty(cx, obj, id, value, getter, setter,
+ attrs, flags, tinyid, NULL);
+ }
+ return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs,
+ NULL);
+}
+
+static JSBool
+DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ uintN flags, intN tinyid)
+{
+ jsid id;
+ JSAtom *atom;
+
+ if (attrs & JSPROP_INDEX) {
+ id = INT_TO_JSID(JS_PTR_TO_INT32(name));
+ atom = NULL;
+ attrs &= ~JSPROP_INDEX;
+ } else {
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+ id = ATOM_TO_JSID(atom);
+ }
+ return DefinePropertyById(cx, obj, id, value, getter, setter, attrs,
+ flags, tinyid);
+}
+
+#define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
+
+static JSBool
+DefineUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ uintN flags, intN tinyid)
+{
+ JSAtom *atom;
+
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+ if (flags != 0 && OBJ_IS_NATIVE(obj)) {
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
+ return js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value,
+ getter, setter, attrs, flags, tinyid,
+ NULL);
+ }
+ return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), value,
+ getter, setter, attrs, NULL);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
+ JSObject *proto, uintN attrs)
+{
+ JSObject *nobj;
+
+ CHECK_REQUEST(cx);
+ if (!clasp)
+ clasp = &js_ObjectClass; /* default class is Object */
+ nobj = js_NewObject(cx, clasp, proto, obj, 0);
+ if (!nobj)
+ return NULL;
+ if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
+ 0, 0)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+ }
+ return nobj;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
+{
+ JSBool ok;
+ jsval value;
+ uintN attrs;
+
+ CHECK_REQUEST(cx);
+ for (ok = JS_TRUE; cds->name; cds++) {
+ ok = js_NewNumberInRootedValue(cx, cds->dval, &value);
+ if (!ok)
+ break;
+ attrs = cds->flags;
+ if (!attrs)
+ attrs = JSPROP_READONLY | JSPROP_PERMANENT;
+ ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, attrs, 0, 0);
+ if (!ok)
+ break;
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ for (ok = JS_TRUE; ps->name; ps++) {
+ ok = DefineProperty(cx, obj, ps->name, JSVAL_VOID,
+ ps->getter, ps->setter, ps->flags,
+ SPROP_HAS_SHORTID, ps->tinyid);
+ if (!ok)
+ break;
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
+{
+ CHECK_REQUEST(cx);
+ return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
+{
+ CHECK_REQUEST(cx);
+ return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
+ int8 tinyid, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs)
+{
+ CHECK_REQUEST(cx);
+ return DefineProperty(cx, obj, name, value, getter, setter, attrs,
+ SPROP_HAS_SHORTID, tinyid);
+}
+
+static JSBool
+LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
+ JSObject **objp, JSProperty **propp)
+{
+ JSAutoResolveFlags rf(cx, flags);
+ return OBJ_LOOKUP_PROPERTY(cx, obj, id, objp, propp);
+}
+
+static JSBool
+LookupProperty(JSContext *cx, JSObject *obj, const char *name, uintN flags,
+ JSObject **objp, JSProperty **propp)
+{
+ JSAtom *atom;
+
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+ return LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), flags, objp, propp);
+}
+
+static JSBool
+LookupUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, uintN flags,
+ JSObject **objp, JSProperty **propp)
+{
+ JSAtom *atom;
+
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+ return LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), flags, objp, propp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
+ const char *alias)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ JSAtom *atom;
+ JSBool ok;
+ JSScopeProperty *sprop;
+
+ CHECK_REQUEST(cx);
+ if (!LookupProperty(cx, obj, name, JSRESOLVE_QUALIFIED, &obj2, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ js_ReportIsNotDefined(cx, name);
+ return JS_FALSE;
+ }
+ if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
+ alias, name, OBJ_GET_CLASS(cx, obj2)->name);
+ return JS_FALSE;
+ }
+ atom = js_Atomize(cx, alias, strlen(alias), 0);
+ if (!atom) {
+ ok = JS_FALSE;
+ } else {
+ sprop = (JSScopeProperty *)prop;
+ ok = (js_AddNativeProperty(cx, obj, ATOM_TO_JSID(atom),
+ sprop->getter, sprop->setter, sprop->slot,
+ sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
+ sprop->shortid)
+ != NULL);
+ }
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+static jsval
+LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop)
+{
+ JSScopeProperty *sprop;
+ jsval rval;
+
+ if (!prop) {
+ /* XXX bad API: no way to tell "not defined" from "void value" */
+ return JSVAL_VOID;
+ }
+ if (OBJ_IS_NATIVE(obj2)) {
+ /* Peek at the native property's slot value, without doing a Get. */
+ sprop = (JSScopeProperty *)prop;
+ rval = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))
+ ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)
+ : JSVAL_TRUE;
+ } else {
+ /* XXX bad API: no way to return "defined but value unknown" */
+ rval = JSVAL_TRUE;
+ }
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return rval;
+}
+
+static JSBool
+GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
+ uintN *attrsp, JSBool *foundp,
+ JSPropertyOp *getterp, JSPropertyOp *setterp)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ JSBool ok;
+
+ if (!atom)
+ return JS_FALSE;
+ if (!LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), JSRESOLVE_QUALIFIED,
+ &obj2, &prop)) {
+ return JS_FALSE;
+ }
+
+ if (!prop || obj != obj2) {
+ *attrsp = 0;
+ *foundp = JS_FALSE;
+ if (getterp)
+ *getterp = NULL;
+ if (setterp)
+ *setterp = NULL;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return JS_TRUE;
+ }
+
+ *foundp = JS_TRUE;
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, attrsp);
+ if (ok && OBJ_IS_NATIVE(obj)) {
+ JSScopeProperty *sprop = (JSScopeProperty *) prop;
+
+ if (getterp)
+ *getterp = sprop->getter;
+ if (setterp)
+ *setterp = sprop->setter;
+ }
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+static JSBool
+SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
+ uintN attrs, JSBool *foundp)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ JSBool ok;
+
+ if (!atom)
+ return JS_FALSE;
+ if (!LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), JSRESOLVE_QUALIFIED,
+ &obj2, &prop)) {
+ return JS_FALSE;
+ }
+ if (!prop || obj != obj2) {
+ *foundp = JS_FALSE;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return JS_TRUE;
+ }
+
+ *foundp = JS_TRUE;
+ ok = OBJ_SET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs);
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+ uintN *attrsp, JSBool *foundp)
+{
+ CHECK_REQUEST(cx);
+ return GetPropertyAttributes(cx, obj,
+ js_Atomize(cx, name, strlen(name), 0),
+ attrsp, foundp, NULL, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+ const char *name,
+ uintN *attrsp, JSBool *foundp,
+ JSPropertyOp *getterp,
+ JSPropertyOp *setterp)
+{
+ CHECK_REQUEST(cx);
+ return GetPropertyAttributes(cx, obj,
+ js_Atomize(cx, name, strlen(name), 0),
+ attrsp, foundp, getterp, setterp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+ uintN attrs, JSBool *foundp)
+{
+ CHECK_REQUEST(cx);
+ return SetPropertyAttributes(cx, obj,
+ js_Atomize(cx, name, strlen(name), 0),
+ attrs, foundp);
+}
+
+static JSBool
+AlreadyHasOwnPropertyHelper(JSContext *cx, JSObject *obj, jsid id,
+ JSBool *foundp)
+{
+ JSScope *scope;
+
+ if (!OBJ_IS_NATIVE(obj)) {
+ JSObject *obj2;
+ JSProperty *prop;
+
+ if (!LookupPropertyById(cx, obj, id,
+ JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
+ &obj2, &prop)) {
+ return JS_FALSE;
+ }
+ *foundp = (obj == obj2);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return JS_TRUE;
+ }
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ *foundp = (scope->object == obj && SCOPE_GET_PROPERTY(scope, id));
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, const char *name,
+ JSBool *foundp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+ return AlreadyHasOwnPropertyHelper(cx, obj, ATOM_TO_JSID(atom), foundp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj, jsid id,
+ JSBool *foundp)
+{
+ CHECK_REQUEST(cx);
+ return AlreadyHasOwnPropertyHelper(cx, obj, id, foundp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupProperty(cx, obj, name,
+ JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
+ &obj2, &prop);
+ if (ok) {
+ *foundp = (prop != NULL);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupPropertyById(cx, obj, id,
+ JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
+ &obj2, &prop);
+ if (ok) {
+ *foundp = (prop != NULL);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupProperty(cx, obj, name, JSRESOLVE_QUALIFIED, &obj2, &prop);
+ if (ok)
+ *vp = LookupResult(cx, obj, obj2, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop);
+ if (ok)
+ *vp = LookupResult(cx, obj, obj2, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
+ uintN flags, jsval *vp)
+{
+ JSAtom *atom;
+ JSObject *obj2;
+
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ return atom &&
+ JS_LookupPropertyWithFlagsById(cx, obj, ATOM_TO_JSID(atom), flags,
+ &obj2, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj, jsid id,
+ uintN flags, JSObject **objp, jsval *vp)
+{
+ JSBool ok;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = OBJ_IS_NATIVE(obj)
+ ? js_LookupPropertyWithFlags(cx, obj, id, flags, objp, &prop) >= 0
+ : OBJ_LOOKUP_PROPERTY(cx, obj, id, objp, &prop);
+ if (ok)
+ *vp = LookupResult(cx, obj, *objp, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_GET_PROPERTY(cx, obj, id, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ jsval *vp)
+{
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+
+ CHECK_REQUEST(cx);
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ JSXMLObjectOps *ops;
+
+ ops = (JSXMLObjectOps *) obj->map->ops;
+ obj = ops->getMethod(cx, obj, id, vp);
+ if (!obj)
+ return JS_FALSE;
+ } else
+#endif
+ {
+ if (!OBJ_GET_PROPERTY(cx, obj, id, vp))
+ return JS_FALSE;
+ }
+
+ *objp = obj;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
+ jsval *vp)
+{
+ JSAtom *atom;
+
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+ return JS_GetMethodById(cx, obj, ATOM_TO_JSID(atom), objp, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
+ return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
+ return OBJ_SET_PROPERTY(cx, obj, id, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
+{
+ jsval junk;
+
+ return JS_DeleteProperty2(cx, obj, name, &junk);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name,
+ jsval *rval)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeletePropertyById(JSContext *cx, JSObject *obj, jsid id)
+{
+ jsval junk;
+
+ return JS_DeletePropertyById2(cx, obj, id, &junk);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
+{
+ CHECK_REQUEST(cx);
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_DELETE_PROPERTY(cx, obj, id, rval);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs)
+{
+ CHECK_REQUEST(cx);
+ return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
+ attrs, 0, 0);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN *attrsp, JSBool *foundp)
+{
+ CHECK_REQUEST(cx);
+ return GetPropertyAttributes(cx, obj,
+ js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
+ attrsp, foundp, NULL, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN *attrsp, JSBool *foundp,
+ JSPropertyOp *getterp,
+ JSPropertyOp *setterp)
+{
+ CHECK_REQUEST(cx);
+ return GetPropertyAttributes(cx, obj,
+ js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
+ attrsp, foundp, getterp, setterp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN attrs, JSBool *foundp)
+{
+ CHECK_REQUEST(cx);
+ return SetPropertyAttributes(cx, obj,
+ js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
+ attrs, foundp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ int8 tinyid, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs)
+{
+ CHECK_REQUEST(cx);
+ return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
+ attrs, SPROP_HAS_SHORTID, tinyid);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ JSBool *foundp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+ return AlreadyHasOwnPropertyHelper(cx, obj, ATOM_TO_JSID(atom), foundp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ JSBool *vp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupUCProperty(cx, obj, name, namelen,
+ JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
+ &obj2, &prop);
+ if (ok) {
+ *vp = (prop != NULL);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupUCProperty(cx, obj, name, namelen, JSRESOLVE_QUALIFIED,
+ &obj2, &prop);
+ if (ok)
+ *vp = LookupResult(cx, obj, obj2, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
+ return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteUCProperty2(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *rval)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector)
+{
+ CHECK_REQUEST(cx);
+ /* NB: jsuint cast does ToUint32. */
+ return js_NewArrayObject(cx, (jsuint)length, vector);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsArrayObject(JSContext *cx, JSObject *obj)
+{
+ return OBJ_IS_ARRAY(cx, obj);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
+{
+ CHECK_REQUEST(cx);
+ return js_GetLengthProperty(cx, obj, lengthp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length)
+{
+ CHECK_REQUEST(cx);
+ return js_SetLengthProperty(cx, obj, length);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
+{
+ CHECK_REQUEST(cx);
+ return js_HasLengthProperty(cx, obj, lengthp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
+{
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
+
+ CHECK_REQUEST(cx);
+ return OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(index), value,
+ getter, setter, attrs, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ if (!LookupProperty(cx, obj, name, JSRESOLVE_QUALIFIED, &obj2, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ js_ReportIsNotDefined(cx, name);
+ return JS_FALSE;
+ }
+ if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
+ char numBuf[12];
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
+ numBuf, name, OBJ_GET_CLASS(cx, obj2)->name);
+ return JS_FALSE;
+ }
+ sprop = (JSScopeProperty *)prop;
+ ok = (js_AddNativeProperty(cx, obj, INT_TO_JSID(alias),
+ sprop->getter, sprop->setter, sprop->slot,
+ sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
+ sprop->shortid)
+ != NULL);
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, jsint index,
+ JSBool *foundp)
+{
+ return AlreadyHasOwnPropertyHelper(cx, obj, INT_TO_JSID(index), foundp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupPropertyById(cx, obj, INT_TO_JSID(index),
+ JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
+ &obj2, &prop);
+ if (ok) {
+ *foundp = (prop != NULL);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupPropertyById(cx, obj, INT_TO_JSID(index), JSRESOLVE_QUALIFIED,
+ &obj2, &prop);
+ if (ok)
+ *vp = LookupResult(cx, obj, obj2, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
+{
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+
+ CHECK_REQUEST(cx);
+ return OBJ_GET_PROPERTY(cx, obj, INT_TO_JSID(index), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
+{
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
+
+ CHECK_REQUEST(cx);
+ return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(index), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index)
+{
+ jsval junk;
+
+ return JS_DeleteElement2(cx, obj, index, &junk);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval)
+{
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+
+ CHECK_REQUEST(cx);
+ return OBJ_DELETE_PROPERTY(cx, obj, INT_TO_JSID(index), rval);
+}
+
+JS_PUBLIC_API(void)
+JS_ClearScope(JSContext *cx, JSObject *obj)
+{
+ CHECK_REQUEST(cx);
+
+ if (obj->map->ops->clear)
+ obj->map->ops->clear(cx, obj);
+
+ /* Clear cached class objects on the global object. */
+ if (OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL) {
+ int key;
+
+ for (key = JSProto_Null; key < JSProto_LIMIT; key++)
+ JS_SetReservedSlot(cx, obj, key, JSVAL_VOID);
+ }
+}
+
+JS_PUBLIC_API(JSIdArray *)
+JS_Enumerate(JSContext *cx, JSObject *obj)
+{
+ jsint i, n;
+ jsval iter_state, num_properties;
+ jsid id;
+ JSIdArray *ida;
+ jsval *vector;
+
+ CHECK_REQUEST(cx);
+
+ ida = NULL;
+ iter_state = JSVAL_NULL;
+
+ /* Get the number of properties to enumerate. */
+ if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties))
+ goto error;
+ if (!JSVAL_IS_INT(num_properties)) {
+ JS_ASSERT(0);
+ goto error;
+ }
+
+ /* Grow as needed if we don't know the exact amount ahead of time. */
+ n = JSVAL_TO_INT(num_properties);
+ if (n <= 0)
+ n = 8;
+
+ /* Create an array of jsids large enough to hold all the properties */
+ ida = NewIdArray(cx, n);
+ if (!ida)
+ goto error;
+
+ i = 0;
+ vector = &ida->vector[0];
+ for (;;) {
+ if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &id))
+ goto error;
+
+ /* No more jsid's to enumerate ? */
+ if (iter_state == JSVAL_NULL)
+ break;
+
+ if (i == ida->length) {
+ ida = SetIdArrayLength(cx, ida, ida->length * 2);
+ if (!ida)
+ goto error;
+ vector = &ida->vector[0];
+ }
+ vector[i++] = id;
+ }
+ return SetIdArrayLength(cx, ida, i);
+
+error:
+ if (iter_state != JSVAL_NULL)
+ OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0);
+ if (ida)
+ JS_DestroyIdArray(cx, ida);
+ return NULL;
+}
+
+/*
+ * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
+ * prop_iterator_class somehow...
+ * + preserve the OBJ_ENUMERATE API while optimizing the native object case
+ * + native case here uses a JSScopeProperty *, but that iterates in reverse!
+ * + so we make non-native match, by reverse-iterating after JS_Enumerating
+ */
+#define JSSLOT_ITER_INDEX (JSSLOT_PRIVATE + 1)
+
+#if JSSLOT_ITER_INDEX >= JS_INITIAL_NSLOTS
+# error "JSSLOT_ITER_INDEX botch!"
+#endif
+
+static void
+prop_iter_finalize(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+ jsint i;
+ JSIdArray *ida;
+
+ v = obj->fslots[JSSLOT_ITER_INDEX];
+ if (JSVAL_IS_VOID(v))
+ return;
+
+ i = JSVAL_TO_INT(v);
+ if (i >= 0) {
+ /* Non-native case: destroy the ida enumerated when obj was created. */
+ ida = (JSIdArray *) JS_GetPrivate(cx, obj);
+ if (ida)
+ JS_DestroyIdArray(cx, ida);
+ }
+}
+
+static void
+prop_iter_trace(JSTracer *trc, JSObject *obj)
+{
+ jsval v;
+ jsint i, n;
+ JSScopeProperty *sprop;
+ JSIdArray *ida;
+ jsid id;
+
+ v = obj->fslots[JSSLOT_PRIVATE];
+ JS_ASSERT(!JSVAL_IS_VOID(v));
+
+ i = JSVAL_TO_INT(obj->fslots[JSSLOT_ITER_INDEX]);
+ if (i < 0) {
+ /* Native case: just mark the next property to visit. */
+ sprop = (JSScopeProperty *) JSVAL_TO_PRIVATE(v);
+ if (sprop)
+ TRACE_SCOPE_PROPERTY(trc, sprop);
+ } else {
+ /* Non-native case: mark each id in the JSIdArray private. */
+ ida = (JSIdArray *) JSVAL_TO_PRIVATE(v);
+ for (i = 0, n = ida->length; i < n; i++) {
+ id = ida->vector[i];
+ TRACE_ID(trc, id);
+ }
+ }
+}
+
+static JSClass prop_iter_class = {
+ "PropertyIterator",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
+ JSCLASS_MARK_IS_TRACE,
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, prop_iter_finalize,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, JS_CLASS_TRACE(prop_iter_trace), NULL
+};
+
+JS_PUBLIC_API(JSObject *)
+JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
+{
+ JSObject *iterobj;
+ JSScope *scope;
+ void *pdata;
+ jsint index;
+ JSIdArray *ida;
+
+ CHECK_REQUEST(cx);
+ iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj, 0);
+ if (!iterobj)
+ return NULL;
+
+ if (OBJ_IS_NATIVE(obj)) {
+ /* Native case: start with the last property in obj's own scope. */
+ scope = OBJ_SCOPE(obj);
+ pdata = (scope->object == obj) ? scope->lastProp : NULL;
+ index = -1;
+ } else {
+ JSTempValueRooter tvr;
+
+ /*
+ * Non-native case: enumerate a JSIdArray and keep it via private.
+ *
+ * Note: we have to make sure that we root obj around the call to
+ * JS_Enumerate to protect against multiple allocations under it.
+ */
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(iterobj), &tvr);
+ ida = JS_Enumerate(cx, obj);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ida)
+ goto bad;
+ pdata = ida;
+ index = ida->length;
+ }
+
+ /* iterobj can not escape to other threads here. */
+ STOBJ_SET_SLOT(iterobj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(pdata));
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(index));
+ return iterobj;
+
+bad:
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
+{
+ jsint i;
+ JSObject *obj;
+ JSScope *scope;
+ JSScopeProperty *sprop;
+ JSIdArray *ida;
+
+ CHECK_REQUEST(cx);
+ i = JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX));
+ if (i < 0) {
+ /* Native case: private data is a property tree node pointer. */
+ obj = OBJ_GET_PARENT(cx, iterobj);
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ scope = OBJ_SCOPE(obj);
+ JS_ASSERT(scope->object == obj);
+ sprop = (JSScopeProperty *) JS_GetPrivate(cx, iterobj);
+
+ /*
+ * If the next property mapped by scope in the property tree ancestor
+ * line is not enumerable, or it's an alias, or one or more properties
+ * were deleted from the "middle" of the scope-mapped ancestor line
+ * and the next property was among those deleted, skip it and keep on
+ * trying to find an enumerable property that is still in scope.
+ */
+ while (sprop &&
+ (!(sprop->attrs & JSPROP_ENUMERATE) ||
+ (sprop->flags & SPROP_IS_ALIAS) ||
+ (SCOPE_HAD_MIDDLE_DELETE(scope) &&
+ !SCOPE_HAS_PROPERTY(scope, sprop)))) {
+ sprop = sprop->parent;
+ }
+
+ if (!sprop) {
+ *idp = JSVAL_VOID;
+ } else {
+ if (!JS_SetPrivate(cx, iterobj, sprop->parent))
+ return JS_FALSE;
+ *idp = sprop->id;
+ }
+ } else {
+ /* Non-native case: use the ida enumerated when iterobj was created. */
+ ida = (JSIdArray *) JS_GetPrivate(cx, iterobj);
+ JS_ASSERT(i <= ida->length);
+ if (i == 0) {
+ *idp = JSVAL_VOID;
+ } else {
+ *idp = ida->vector[--i];
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(i));
+ }
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp)
+{
+ CHECK_REQUEST(cx);
+ return OBJ_CHECK_ACCESS(cx, obj, id, mode, vp, attrsp);
+}
+
+static JSBool
+ReservedSlotIndexOK(JSContext *cx, JSObject *obj, JSClass *clasp,
+ uint32 index, uint32 limit)
+{
+ /* Check the computed, possibly per-instance, upper bound. */
+ if (clasp->reserveSlots)
+ JS_LOCK_OBJ_VOID(cx, obj, limit += clasp->reserveSlots(cx, obj));
+ if (index >= limit) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_RESERVED_SLOT_RANGE);
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp)
+{
+ JSClass *clasp;
+ uint32 limit, slot;
+
+ CHECK_REQUEST(cx);
+ clasp = OBJ_GET_CLASS(cx, obj);
+ limit = JSCLASS_RESERVED_SLOTS(clasp);
+ if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
+ return JS_FALSE;
+ slot = JSSLOT_START(clasp) + index;
+ *vp = OBJ_GET_REQUIRED_SLOT(cx, obj, slot);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
+{
+ JSClass *clasp;
+ uint32 limit, slot;
+
+ CHECK_REQUEST(cx);
+ clasp = OBJ_GET_CLASS(cx, obj);
+ limit = JSCLASS_RESERVED_SLOTS(clasp);
+ if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
+ return JS_FALSE;
+ slot = JSSLOT_START(clasp) + index;
+ return OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v);
+}
+
+#ifdef JS_THREADSAFE
+JS_PUBLIC_API(jsrefcount)
+JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals)
+{
+ return JS_ATOMIC_INCREMENT(&principals->refcount);
+}
+
+JS_PUBLIC_API(jsrefcount)
+JS_DropPrincipals(JSContext *cx, JSPrincipals *principals)
+{
+ jsrefcount rc = JS_ATOMIC_DECREMENT(&principals->refcount);
+ if (rc == 0)
+ principals->destroy(cx, principals);
+ return rc;
+}
+#endif
+
+JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_SetRuntimeSecurityCallbacks(JSRuntime *rt, JSSecurityCallbacks *callbacks)
+{
+ JSSecurityCallbacks *oldcallbacks;
+
+ oldcallbacks = rt->securityCallbacks;
+ rt->securityCallbacks = callbacks;
+ return oldcallbacks;
+}
+
+JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_GetRuntimeSecurityCallbacks(JSRuntime *rt)
+{
+ return rt->securityCallbacks;
+}
+
+JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks)
+{
+ JSSecurityCallbacks *oldcallbacks;
+
+ oldcallbacks = cx->securityCallbacks;
+ cx->securityCallbacks = callbacks;
+ return oldcallbacks;
+}
+
+JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_GetSecurityCallbacks(JSContext *cx)
+{
+ return cx->securityCallbacks
+ ? cx->securityCallbacks
+ : cx->runtime->securityCallbacks;
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
+ JSObject *parent, const char *name)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+
+ if (!name) {
+ atom = NULL;
+ } else {
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return NULL;
+ }
+ return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
+{
+ CHECK_REQUEST(cx);
+ if (OBJ_GET_CLASS(cx, funobj) != &js_FunctionClass) {
+ /* Indicate we cannot clone this object. */
+ return funobj;
+ }
+ return js_CloneFunctionObject(cx, GET_FUNCTION_PRIVATE(cx, funobj), parent);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFunctionObject(JSFunction *fun)
+{
+ return FUN_OBJECT(fun);
+}
+
+JS_PUBLIC_API(const char *)
+JS_GetFunctionName(JSFunction *fun)
+{
+ return fun->atom
+ ? JS_GetStringBytes(ATOM_TO_STRING(fun->atom))
+ : js_anonymous_str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_GetFunctionId(JSFunction *fun)
+{
+ return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
+}
+
+JS_PUBLIC_API(uintN)
+JS_GetFunctionFlags(JSFunction *fun)
+{
+#ifdef MOZILLA_1_8_BRANCH
+ uintN flags = fun->flags;
+
+ return JSFUN_DISJOINT_FLAGS(flags) |
+ (JSFUN_GETTER_TEST(flags) ? JSFUN_GETTER : 0) |
+ (JSFUN_SETTER_TEST(flags) ? JSFUN_SETTER : 0) |
+ (JSFUN_BOUND_METHOD_TEST(flags) ? JSFUN_BOUND_METHOD : 0) |
+ (JSFUN_HEAVYWEIGHT_TEST(flags) ? JSFUN_HEAVYWEIGHT : 0);
+#else
+ return fun->flags;
+#endif
+}
+
+JS_PUBLIC_API(uint16)
+JS_GetFunctionArity(JSFunction *fun)
+{
+ return fun->nargs;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
+{
+ return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass;
+}
+
+JS_BEGIN_EXTERN_C
+static JSBool
+js_generic_fast_native_method_dispatcher(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval fsv;
+ JSFunctionSpec *fs;
+ JSObject *tmp;
+ JSFastNative native;
+
+ if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(*vp), 0, &fsv))
+ return JS_FALSE;
+ fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv);
+ JS_ASSERT((~fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) == 0);
+
+ /*
+ * We know that vp[2] is valid because JS_DefineFunctions, which is our
+ * only (indirect) referrer, defined us as requiring at least one argument
+ * (notice how it passes fs->nargs + 1 as the next-to-last argument to
+ * JS_DefineFunction).
+ */
+ if (JSVAL_IS_PRIMITIVE(vp[2])) {
+ /*
+ * Make sure that this is an object or null, as required by the generic
+ * functions.
+ */
+ if (!js_ValueToObject(cx, vp[2], &tmp))
+ return JS_FALSE;
+ vp[2] = OBJECT_TO_JSVAL(tmp);
+ }
+
+ /*
+ * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
+ * which is almost always the class constructor object, e.g. Array. Then
+ * call the corresponding prototype native method with our first argument
+ * passed as |this|.
+ */
+ memmove(vp + 1, vp + 2, argc * sizeof(jsval));
+
+ /*
+ * Follow Function.prototype.apply and .call by using the global object as
+ * the 'this' param if no args.
+ */
+ if (!js_ComputeThis(cx, JS_FALSE, vp + 2))
+ return JS_FALSE;
+ /*
+ * Protect against argc underflowing. By calling js_ComputeThis, we made
+ * it as if the static was called with one parameter, the explicit |this|
+ * object.
+ */
+ if (argc != 0)
+ --argc;
+
+ native =
+#ifdef JS_TRACER
+ (fs->flags & JSFUN_TRACEABLE)
+ ? ((JSTraceableNative *) fs->call)->native
+ :
+#endif
+ (JSFastNative) fs->call;
+ return native(cx, argc, vp);
+}
+
+static JSBool
+js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ jsval fsv;
+ JSFunctionSpec *fs;
+ JSObject *tmp;
+
+ if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(argv[-2]), 0, &fsv))
+ return JS_FALSE;
+ fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv);
+ JS_ASSERT((fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) ==
+ JSFUN_GENERIC_NATIVE);
+
+ /*
+ * We know that argv[0] is valid because JS_DefineFunctions, which is our
+ * only (indirect) referrer, defined us as requiring at least one argument
+ * (notice how it passes fs->nargs + 1 as the next-to-last argument to
+ * JS_DefineFunction).
+ */
+ if (JSVAL_IS_PRIMITIVE(argv[0])) {
+ /*
+ * Make sure that this is an object or null, as required by the generic
+ * functions.
+ */
+ if (!js_ValueToObject(cx, argv[0], &tmp))
+ return JS_FALSE;
+ argv[0] = OBJECT_TO_JSVAL(tmp);
+ }
+
+ /*
+ * Copy all actual (argc) arguments down over our |this| parameter,
+ * argv[-1], which is almost always the class constructor object, e.g.
+ * Array. Then call the corresponding prototype native method with our
+ * first argument passed as |this|.
+ */
+ memmove(argv - 1, argv, argc * sizeof(jsval));
+
+ /*
+ * Follow Function.prototype.apply and .call by using the global object as
+ * the 'this' param if no args.
+ */
+ JS_ASSERT(cx->fp->argv == argv);
+ if (!js_ComputeThis(cx, JS_TRUE, argv))
+ return JS_FALSE;
+ cx->fp->thisp = JSVAL_TO_OBJECT(argv[-1]);
+
+ /*
+ * Protect against argc underflowing. By calling js_ComputeThis, we made
+ * it as if the static was called with one parameter, the explicit |this|
+ * object.
+ */
+ if (argc != 0)
+ --argc;
+
+ return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc, argv, rval);
+}
+JS_END_EXTERN_C
+
+JS_PUBLIC_API(JSBool)
+JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
+{
+ uintN flags;
+ JSObject *ctor;
+ JSFunction *fun;
+
+ CHECK_REQUEST(cx);
+ ctor = NULL;
+ for (; fs->name; fs++) {
+ flags = fs->flags;
+
+ /*
+ * Define a generic arity N+1 static method for the arity N prototype
+ * method if flags contains JSFUN_GENERIC_NATIVE.
+ */
+ if (flags & JSFUN_GENERIC_NATIVE) {
+ if (!ctor) {
+ ctor = JS_GetConstructor(cx, obj);
+ if (!ctor)
+ return JS_FALSE;
+ }
+
+ flags &= ~JSFUN_GENERIC_NATIVE;
+ fun = JS_DefineFunction(cx, ctor, fs->name,
+ (flags & JSFUN_FAST_NATIVE)
+ ? (JSNative)
+ js_generic_fast_native_method_dispatcher
+ : js_generic_native_method_dispatcher,
+ fs->nargs + 1,
+ flags & ~JSFUN_TRACEABLE);
+ if (!fun)
+ return JS_FALSE;
+ fun->u.n.extra = (uint16)fs->extra;
+
+ /*
+ * As jsapi.h notes, fs must point to storage that lives as long
+ * as fun->object lives.
+ */
+ if (!JS_SetReservedSlot(cx, FUN_OBJECT(fun), 0, PRIVATE_TO_JSVAL(fs)))
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(!(flags & JSFUN_FAST_NATIVE) ||
+ (uint16)(fs->extra >> 16) <= fs->nargs);
+ fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, flags);
+ if (!fun)
+ return JS_FALSE;
+ fun->u.n.extra = (uint16)fs->extra;
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
+ uintN nargs, uintN attrs)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return NULL;
+ return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_DefineUCFunction(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, JSNative call,
+ uintN nargs, uintN attrs)
+{
+ JSAtom *atom;
+
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return NULL;
+ return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileScript(JSContext *cx, JSObject *obj,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno)
+{
+ jschar *chars;
+ JSScript *script;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+ script = JS_CompileUCScript(cx, obj, chars, length, filename, lineno);
+ JS_free(cx, chars);
+ return script;
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno)
+{
+ jschar *chars;
+ JSScript *script;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+ script = JS_CompileUCScriptForPrincipals(cx, obj, principals,
+ chars, length, filename, lineno);
+ JS_free(cx, chars);
+ return script;
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileUCScript(JSContext *cx, JSObject *obj,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno)
+{
+ CHECK_REQUEST(cx);
+ return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length,
+ filename, lineno);
+}
+
+#define LAST_FRAME_EXCEPTION_CHECK(cx,result) \
+ JS_BEGIN_MACRO \
+ if (!(result) && !((cx)->options & JSOPTION_DONT_REPORT_UNCAUGHT)) \
+ js_ReportUncaughtException(cx); \
+ JS_END_MACRO
+
+#define LAST_FRAME_CHECKS(cx,result) \
+ JS_BEGIN_MACRO \
+ if (!(cx)->fp) { \
+ (cx)->weakRoots.lastInternalResult = JSVAL_NULL; \
+ LAST_FRAME_EXCEPTION_CHECK(cx, result); \
+ } \
+ JS_END_MACRO
+
+#define JS_OPTIONS_TO_TCFLAGS(cx) \
+ ((((cx)->options & JSOPTION_COMPILE_N_GO) ? TCF_COMPILE_N_GO : 0) | \
+ (((cx)->options & JSOPTION_NO_SCRIPT_RVAL) ? TCF_NO_SCRIPT_RVAL : 0))
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno)
+{
+ uint32 tcflags;
+ JSScript *script;
+
+ CHECK_REQUEST(cx);
+ tcflags = JS_OPTIONS_TO_TCFLAGS(cx);
+ script = js_CompileScript(cx, obj, NULL, principals, tcflags,
+ chars, length, NULL, filename, lineno);
+ LAST_FRAME_CHECKS(cx, script);
+ return script;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
+ const char *bytes, size_t length)
+{
+ jschar *chars;
+ JSBool result;
+ JSExceptionState *exnState;
+ JSParseContext pc;
+ JSErrorReporter older;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return JS_TRUE;
+
+ /*
+ * Return true on any out-of-memory error, so our caller doesn't try to
+ * collect more buffered source.
+ */
+ result = JS_TRUE;
+ exnState = JS_SaveExceptionState(cx);
+ if (js_InitParseContext(cx, &pc, NULL, NULL, chars, length, NULL, NULL,
+ 1)) {
+ older = JS_SetErrorReporter(cx, NULL);
+ if (!js_ParseScript(cx, obj, &pc) &&
+ (pc.tokenStream.flags & TSF_UNEXPECTED_EOF)) {
+ /*
+ * We ran into an error. If it was because we ran out of source,
+ * we return false, so our caller will know to try to collect more
+ * buffered source.
+ */
+ result = JS_FALSE;
+ }
+ JS_SetErrorReporter(cx, older);
+ js_FinishParseContext(cx, &pc);
+ }
+ JS_free(cx, chars);
+ JS_RestoreExceptionState(cx, exnState);
+ return result;
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
+{
+ FILE *fp;
+ uint32 tcflags;
+ JSScript *script;
+
+ CHECK_REQUEST(cx);
+ if (!filename || strcmp(filename, "-") == 0) {
+ fp = stdin;
+ } else {
+ fp = fopen(filename, "r");
+ if (!fp) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN,
+ filename, "No such file or directory");
+ return NULL;
+ }
+ }
+
+ tcflags = JS_OPTIONS_TO_TCFLAGS(cx);
+ script = js_CompileScript(cx, obj, NULL, NULL, tcflags,
+ NULL, 0, fp, filename, 1);
+ if (fp != stdin)
+ fclose(fp);
+ LAST_FRAME_CHECKS(cx, script);
+ return script;
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
+ FILE *file)
+{
+ return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL);
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
+ const char *filename, FILE *file,
+ JSPrincipals *principals)
+{
+ uint32 tcflags;
+ JSScript *script;
+
+ CHECK_REQUEST(cx);
+ tcflags = JS_OPTIONS_TO_TCFLAGS(cx);
+ script = js_CompileScript(cx, obj, NULL, principals, tcflags,
+ NULL, 0, file, filename, 1);
+ LAST_FRAME_CHECKS(cx, script);
+ return script;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewScriptObject(JSContext *cx, JSScript *script)
+{
+ JSTempValueRooter tvr;
+ JSObject *obj;
+
+ CHECK_REQUEST(cx);
+ if (!script)
+ return js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
+
+ JS_ASSERT(!script->u.object);
+
+ JS_PUSH_TEMP_ROOT_SCRIPT(cx, script, &tvr);
+ obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
+ if (obj) {
+ JS_SetPrivate(cx, obj, script);
+ script->u.object = obj;
+#ifdef CHECK_SCRIPT_OWNER
+ script->owner = NULL;
+#endif
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return obj;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetScriptObject(JSScript *script)
+{
+ return script->u.object;
+}
+
+JS_PUBLIC_API(void)
+JS_DestroyScript(JSContext *cx, JSScript *script)
+{
+ CHECK_REQUEST(cx);
+ js_DestroyScript(cx, script);
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
+ uintN nargs, const char **argnames,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno)
+{
+ jschar *chars;
+ JSFunction *fun;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+ fun = JS_CompileUCFunction(cx, obj, name, nargs, argnames, chars, length,
+ filename, lineno);
+ JS_free(cx, chars);
+ return fun;
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals, const char *name,
+ uintN nargs, const char **argnames,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno)
+{
+ jschar *chars;
+ JSFunction *fun;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+ fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
+ nargs, argnames, chars, length,
+ filename, lineno);
+ JS_free(cx, chars);
+ return fun;
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
+ uintN nargs, const char **argnames,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno)
+{
+ CHECK_REQUEST(cx);
+ return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name,
+ nargs, argnames,
+ chars, length,
+ filename, lineno);
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals, const char *name,
+ uintN nargs, const char **argnames,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno)
+{
+ JSFunction *fun;
+ JSTempValueRooter tvr;
+ JSAtom *funAtom, *argAtom;
+ uintN i;
+
+ CHECK_REQUEST(cx);
+ if (!name) {
+ funAtom = NULL;
+ } else {
+ funAtom = js_Atomize(cx, name, strlen(name), 0);
+ if (!funAtom) {
+ fun = NULL;
+ goto out2;
+ }
+ }
+ fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom);
+ if (!fun)
+ goto out2;
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, FUN_OBJECT(fun), &tvr);
+ for (i = 0; i < nargs; i++) {
+ argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0);
+ if (!argAtom) {
+ fun = NULL;
+ goto out;
+ }
+ if (!js_AddLocal(cx, fun, argAtom, JSLOCAL_ARG)) {
+ fun = NULL;
+ goto out;
+ }
+ }
+
+ if (!js_CompileFunctionBody(cx, fun, principals, chars, length,
+ filename, lineno)) {
+ fun = NULL;
+ goto out;
+ }
+
+ if (obj &&
+ funAtom &&
+ !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(funAtom),
+ OBJECT_TO_JSVAL(FUN_OBJECT(fun)),
+ NULL, NULL, JSPROP_ENUMERATE, NULL)) {
+ fun = NULL;
+ }
+
+#ifdef JS_SCOPE_DEPTH_METER
+ if (fun && obj) {
+ JSObject *pobj = obj;
+ uintN depth = 1;
+
+ while ((pobj = OBJ_GET_PARENT(cx, pobj)) != NULL)
+ ++depth;
+ JS_BASIC_STATS_ACCUM(&cx->runtime->hostenvScopeDepthStats, depth);
+ }
+#endif
+
+ out:
+ cx->weakRoots.newborn[JSTRACE_OBJECT] = FUN_OBJECT(fun);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+
+ out2:
+ LAST_FRAME_CHECKS(cx, fun);
+ return fun;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
+ uintN indent)
+{
+ JSPrinter *jp;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ jp = JS_NEW_PRINTER(cx, name, NULL,
+ indent & ~JS_DONT_PRETTY_PRINT,
+ !(indent & JS_DONT_PRETTY_PRINT));
+ if (!jp)
+ return NULL;
+ if (js_DecompileScript(jp, script))
+ str = js_GetPrinterOutput(jp);
+ else
+ str = NULL;
+ js_DestroyPrinter(jp);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
+{
+ JSPrinter *jp;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ jp = JS_NEW_PRINTER(cx, "JS_DecompileFunction", fun,
+ indent & ~JS_DONT_PRETTY_PRINT,
+ !(indent & JS_DONT_PRETTY_PRINT));
+ if (!jp)
+ return NULL;
+ if (js_DecompileFunction(jp))
+ str = js_GetPrinterOutput(jp);
+ else
+ str = NULL;
+ js_DestroyPrinter(jp);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
+{
+ JSPrinter *jp;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ jp = JS_NEW_PRINTER(cx, "JS_DecompileFunctionBody", fun,
+ indent & ~JS_DONT_PRETTY_PRINT,
+ !(indent & JS_DONT_PRETTY_PRINT));
+ if (!jp)
+ return NULL;
+ if (js_DecompileFunctionBody(jp))
+ str = js_GetPrinterOutput(jp);
+ else
+ str = NULL;
+ js_DestroyPrinter(jp);
+ return str;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ ok = js_Execute(cx, obj, script, NULL, 0, rval);
+ LAST_FRAME_CHECKS(cx, ok);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script,
+ JSExecPart part, jsval *rval)
+{
+ JSScript tmp;
+ JSDebugHooks *hooks;
+ JSBool ok;
+
+ /* Make a temporary copy of the JSScript structure and farble it a bit. */
+ tmp = *script;
+ if (part == JSEXEC_PROLOG) {
+ tmp.length = PTRDIFF(tmp.main, tmp.code, jsbytecode);
+ } else {
+ tmp.length -= PTRDIFF(tmp.main, tmp.code, jsbytecode);
+ tmp.code = tmp.main;
+ }
+
+ /* Tell the debugger about our temporary copy of the script structure. */
+ hooks = cx->debugHooks;
+ if (hooks->newScriptHook) {
+ hooks->newScriptHook(cx, tmp.filename, tmp.lineno, &tmp, NULL,
+ hooks->newScriptHookData);
+ }
+
+ /* Execute the farbled struct and tell the debugger to forget about it. */
+ ok = JS_ExecuteScript(cx, obj, &tmp, rval);
+ if (hooks->destroyScriptHook)
+ hooks->destroyScriptHook(cx, &tmp, hooks->destroyScriptHookData);
+ return ok;
+}
+
+/* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
+JS_PUBLIC_API(JSBool)
+JS_EvaluateScript(JSContext *cx, JSObject *obj,
+ const char *bytes, uintN nbytes,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ size_t length = nbytes;
+ jschar *chars;
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return JS_FALSE;
+ ok = JS_EvaluateUCScript(cx, obj, chars, length, filename, lineno, rval);
+ JS_free(cx, chars);
+ return ok;
+}
+
+/* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
+JS_PUBLIC_API(JSBool)
+JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const char *bytes, uintN nbytes,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ size_t length = nbytes;
+ jschar *chars;
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return JS_FALSE;
+ ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
+ filename, lineno, rval);
+ JS_free(cx, chars);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ CHECK_REQUEST(cx);
+ return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length,
+ filename, lineno, rval);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ JSScript *script;
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ script = js_CompileScript(cx, obj, NULL, principals,
+ !rval
+ ? TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL
+ : TCF_COMPILE_N_GO,
+ chars, length, NULL, filename, lineno);
+ if (!script) {
+ LAST_FRAME_CHECKS(cx, script);
+ return JS_FALSE;
+ }
+ ok = js_Execute(cx, obj, script, NULL, 0, rval);
+ LAST_FRAME_CHECKS(cx, ok);
+ JS_DestroyScript(cx, script);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
+ jsval *argv, jsval *rval)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(FUN_OBJECT(fun)), argc, argv,
+ rval);
+ LAST_FRAME_CHECKS(cx, ok);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
+ jsval *argv, jsval *rval)
+{
+ JSBool ok;
+ jsval fval;
+
+ CHECK_REQUEST(cx);
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ JSXMLObjectOps *ops;
+ JSAtom *atom;
+
+ ops = (JSXMLObjectOps *) obj->map->ops;
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+ obj = ops->getMethod(cx, obj, ATOM_TO_JSID(atom), &fval);
+ if (!obj)
+ return JS_FALSE;
+ } else
+#endif
+ if (!JS_GetProperty(cx, obj, name, &fval))
+ return JS_FALSE;
+ ok = js_InternalCall(cx, obj, fval, argc, argv, rval);
+ LAST_FRAME_CHECKS(cx, ok);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
+ jsval *argv, jsval *rval)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ ok = js_InternalCall(cx, obj, fval, argc, argv, rval);
+ LAST_FRAME_CHECKS(cx, ok);
+ return ok;
+}
+
+JS_PUBLIC_API(void)
+JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback,
+ uint32 operationLimit)
+{
+ JS_ASSERT(callback);
+ JS_ASSERT(operationLimit <= JS_MAX_OPERATION_LIMIT);
+ JS_ASSERT(operationLimit > 0);
+
+ cx->operationCount = (int32) operationLimit;
+ cx->operationLimit = operationLimit;
+ cx->operationCallbackIsSet = 1;
+ cx->operationCallback = callback;
+}
+
+JS_PUBLIC_API(void)
+JS_ClearOperationCallback(JSContext *cx)
+{
+ cx->operationCount = (int32) JS_MAX_OPERATION_LIMIT;
+ cx->operationLimit = JS_MAX_OPERATION_LIMIT;
+ cx->operationCallbackIsSet = 0;
+ cx->operationCallback = NULL;
+}
+
+JS_PUBLIC_API(JSOperationCallback)
+JS_GetOperationCallback(JSContext *cx)
+{
+ JS_ASSERT(cx->operationCallbackIsSet || !cx->operationCallback);
+ return cx->operationCallback;
+}
+
+JS_PUBLIC_API(uint32)
+JS_GetOperationLimit(JSContext *cx)
+{
+ JS_ASSERT(cx->operationCallbackIsSet);
+ return cx->operationLimit;
+}
+
+JS_PUBLIC_API(void)
+JS_SetOperationLimit(JSContext *cx, uint32 operationLimit)
+{
+ JS_ASSERT(operationLimit <= JS_MAX_OPERATION_LIMIT);
+ JS_ASSERT(operationLimit > 0);
+ JS_ASSERT(cx->operationCallbackIsSet);
+
+ cx->operationLimit = operationLimit;
+ if (cx->operationCount > (int32) operationLimit)
+ cx->operationCount = (int32) operationLimit;
+}
+
+JS_PUBLIC_API(JSBranchCallback)
+JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb)
+{
+ JSBranchCallback oldcb;
+
+ if (cx->operationCallbackIsSet) {
+#ifdef DEBUG
+ fprintf(stderr,
+"JS API usage error: call to JS_SetOperationCallback is followed by\n"
+"invocation of deprecated JS_SetBranchCallback\n");
+ JS_ASSERT(0);
+#endif
+ cx->operationCallbackIsSet = 0;
+ oldcb = NULL;
+ } else {
+ oldcb = (JSBranchCallback) cx->operationCallback;
+ }
+ if (cb) {
+ cx->operationCount = JSOW_SCRIPT_JUMP;
+ cx->operationLimit = JSOW_SCRIPT_JUMP;
+ cx->operationCallback = (JSOperationCallback) cb;
+ } else {
+ JS_ClearOperationCallback(cx);
+ }
+ return oldcb;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsRunning(JSContext *cx)
+{
+ return cx->fp != NULL;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsConstructing(JSContext *cx)
+{
+ return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING);
+}
+
+JS_FRIEND_API(JSBool)
+JS_IsAssigning(JSContext *cx)
+{
+ JSStackFrame *fp;
+
+ for (fp = cx->fp; fp && !fp->script; fp = fp->down)
+ continue;
+ if (!fp || !fp->regs)
+ return JS_FALSE;
+ return (js_CodeSpec[*fp->regs->pc].format & JOF_ASSIGNING) != 0;
+}
+
+JS_PUBLIC_API(void)
+JS_SetCallReturnValue2(JSContext *cx, jsval v)
+{
+#if JS_HAS_LVALUE_RETURN
+ cx->rval2 = v;
+ cx->rval2set = JS_TRUE;
+#endif
+}
+
+JS_PUBLIC_API(JSStackFrame *)
+JS_SaveFrameChain(JSContext *cx)
+{
+ JSStackFrame *fp;
+
+ fp = cx->fp;
+ if (!fp)
+ return fp;
+
+ JS_ASSERT(!fp->dormantNext);
+ fp->dormantNext = cx->dormantFrameChain;
+ cx->dormantFrameChain = fp;
+ cx->fp = NULL;
+ return fp;
+}
+
+JS_PUBLIC_API(void)
+JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp)
+{
+ JS_ASSERT(!cx->fp);
+ if (!fp)
+ return;
+
+ JS_ASSERT(fp == cx->dormantFrameChain);
+ cx->fp = fp;
+ cx->dormantFrameChain = fp->dormantNext;
+ fp->dormantNext = NULL;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(JSString *)
+JS_NewString(JSContext *cx, char *bytes, size_t nbytes)
+{
+ size_t length = nbytes;
+ jschar *chars;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+
+ /* Make a UTF-16 vector from the 8-bit char codes in bytes. */
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+
+ /* Free chars (but not bytes, which caller frees on error) if we fail. */
+ str = js_NewString(cx, chars, length);
+ if (!str) {
+ JS_free(cx, chars);
+ return NULL;
+ }
+
+ /* Hand off bytes to the deflated string cache, if possible. */
+ if (!js_SetStringBytes(cx, str, bytes, nbytes))
+ JS_free(cx, bytes);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
+{
+ jschar *js;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ js = js_InflateString(cx, s, &n);
+ if (!js)
+ return NULL;
+ str = js_NewString(cx, js, n);
+ if (!str)
+ JS_free(cx, js);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewStringCopyZ(JSContext *cx, const char *s)
+{
+ size_t n;
+ jschar *js;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ if (!s)
+ return cx->runtime->emptyString;
+ n = strlen(s);
+ js = js_InflateString(cx, s, &n);
+ if (!js)
+ return NULL;
+ str = js_NewString(cx, js, n);
+ if (!str)
+ JS_free(cx, js);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_InternString(JSContext *cx, const char *s)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, s, strlen(s), ATOM_INTERNED);
+ if (!atom)
+ return NULL;
+ return ATOM_TO_STRING(atom);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
+{
+ CHECK_REQUEST(cx);
+ return js_NewString(cx, chars, length);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
+{
+ CHECK_REQUEST(cx);
+ return js_NewStringCopyN(cx, s, n);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
+{
+ CHECK_REQUEST(cx);
+ if (!s)
+ return cx->runtime->emptyString;
+ return js_NewStringCopyZ(cx, s);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_AtomizeChars(cx, s, length, ATOM_INTERNED);
+ if (!atom)
+ return NULL;
+ return ATOM_TO_STRING(atom);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_InternUCString(JSContext *cx, const jschar *s)
+{
+ return JS_InternUCStringN(cx, s, js_strlen(s));
+}
+
+JS_PUBLIC_API(char *)
+JS_GetStringBytes(JSString *str)
+{
+ const char *bytes;
+
+ bytes = js_GetStringBytes(NULL, str);
+ return (char *)(bytes ? bytes : "");
+}
+
+JS_PUBLIC_API(jschar *)
+JS_GetStringChars(JSString *str)
+{
+ size_t n, size;
+ jschar *s;
+
+ /*
+ * API botch (again, shades of JS_GetStringBytes): we have no cx to report
+ * out-of-memory when undepending strings, so we replace js_UndependString
+ * with explicit malloc call and ignore its errors.
+ *
+ * If we fail to convert a dependent string into an independent one, our
+ * caller will not be guaranteed a \u0000 terminator as a backstop. This
+ * may break some clients who already misbehave on embedded NULs.
+ *
+ * The gain of dependent strings, which cure quadratic and cubic growth
+ * rate bugs in string concatenation, is worth this slight loss in API
+ * compatibility.
+ */
+ if (JSSTRING_IS_DEPENDENT(str)) {
+ n = JSSTRDEP_LENGTH(str);
+ size = (n + 1) * sizeof(jschar);
+ s = (jschar *) malloc(size);
+ if (s) {
+ memcpy(s, JSSTRDEP_CHARS(str), n * sizeof *s);
+ s[n] = 0;
+ JSFLATSTR_INIT(str, s, n);
+ } else {
+ s = JSSTRDEP_CHARS(str);
+ }
+ } else {
+ JSFLATSTR_CLEAR_MUTABLE(str);
+ s = JSFLATSTR_CHARS(str);
+ }
+ return s;
+}
+
+JS_PUBLIC_API(size_t)
+JS_GetStringLength(JSString *str)
+{
+ return JSSTRING_LENGTH(str);
+}
+
+JS_PUBLIC_API(intN)
+JS_CompareStrings(JSString *str1, JSString *str2)
+{
+ return js_CompareStrings(str1, str2);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length)
+{
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ str = js_NewString(cx, chars, length);
+ if (!str)
+ return str;
+ JSFLATSTR_SET_MUTABLE(str);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewDependentString(JSContext *cx, JSString *str, size_t start,
+ size_t length)
+{
+ CHECK_REQUEST(cx);
+ return js_NewDependentString(cx, str, start, length);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
+{
+ CHECK_REQUEST(cx);
+ return js_ConcatStrings(cx, left, right);
+}
+
+JS_PUBLIC_API(const jschar *)
+JS_UndependString(JSContext *cx, JSString *str)
+{
+ CHECK_REQUEST(cx);
+ return js_UndependString(cx, str);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_MakeStringImmutable(JSContext *cx, JSString *str)
+{
+ CHECK_REQUEST(cx);
+ return js_MakeStringImmutable(cx, str);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst,
+ size_t *dstlenp)
+{
+ size_t n;
+
+ if (!dst) {
+ n = js_GetDeflatedStringLength(cx, src, srclen);
+ if (n == (size_t)-1) {
+ *dstlenp = 0;
+ return JS_FALSE;
+ }
+ *dstlenp = n;
+ return JS_TRUE;
+ }
+
+ return js_DeflateStringToBuffer(cx, src, srclen, dst, dstlenp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst,
+ size_t *dstlenp)
+{
+ return js_InflateStringToBuffer(cx, src, srclen, dst, dstlenp);
+}
+
+JS_PUBLIC_API(char *)
+JS_EncodeString(JSContext *cx, JSString *str)
+{
+ return js_DeflateString(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
+}
+
+JS_PUBLIC_API(JSBool)
+JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer,
+ JSONWriteCallback callback, void *data)
+{
+ CHECK_REQUEST(cx);
+ return js_Stringify(cx, vp, replacer, callback, data, 0);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_TryJSON(JSContext *cx, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ return js_TryJSON(cx, vp);
+}
+
+JS_PUBLIC_API(JSONParser *)
+JS_BeginJSONParse(JSContext *cx, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ return js_BeginJSONParse(cx, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len)
+{
+ CHECK_REQUEST(cx);
+ return js_ConsumeJSONText(cx, jp, data, len);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_FinishJSONParse(JSContext *cx, JSONParser *jp)
+{
+ CHECK_REQUEST(cx);
+ return js_FinishJSONParse(cx, jp);
+}
+
+/*
+ * The following determines whether C Strings are to be treated as UTF-8
+ * or ISO-8859-1. For correct operation, it must be set prior to the
+ * first call to JS_NewRuntime.
+ */
+#ifndef JS_C_STRINGS_ARE_UTF8
+JSBool js_CStringsAreUTF8 = JS_FALSE;
+#endif
+
+JS_PUBLIC_API(JSBool)
+JS_CStringsAreUTF8()
+{
+ return js_CStringsAreUTF8;
+}
+
+JS_PUBLIC_API(void)
+JS_SetCStringsAreUTF8()
+{
+ JS_ASSERT(!js_NewRuntimeWasCalled);
+
+#ifndef JS_C_STRINGS_ARE_UTF8
+ js_CStringsAreUTF8 = JS_TRUE;
+#endif
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(void)
+JS_ReportError(JSContext *cx, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
+ va_end(ap);
+}
+
+JS_PUBLIC_API(void)
+JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
+ void *userRef, const uintN errorNumber, ...)
+{
+ va_list ap;
+
+ va_start(ap, errorNumber);
+ js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
+ errorNumber, JS_TRUE, ap);
+ va_end(ap);
+}
+
+JS_PUBLIC_API(void)
+JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
+ void *userRef, const uintN errorNumber, ...)
+{
+ va_list ap;
+
+ va_start(ap, errorNumber);
+ js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
+ errorNumber, JS_FALSE, ap);
+ va_end(ap);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ReportWarning(JSContext *cx, const char *format, ...)
+{
+ va_list ap;
+ JSBool ok;
+
+ va_start(ap, format);
+ ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
+ va_end(ap);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
+ JSErrorCallback errorCallback, void *userRef,
+ const uintN errorNumber, ...)
+{
+ va_list ap;
+ JSBool ok;
+
+ va_start(ap, errorNumber);
+ ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
+ errorNumber, JS_TRUE, ap);
+ va_end(ap);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
+ JSErrorCallback errorCallback, void *userRef,
+ const uintN errorNumber, ...)
+{
+ va_list ap;
+ JSBool ok;
+
+ va_start(ap, errorNumber);
+ ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
+ errorNumber, JS_FALSE, ap);
+ va_end(ap);
+ return ok;
+}
+
+JS_PUBLIC_API(void)
+JS_ReportOutOfMemory(JSContext *cx)
+{
+ js_ReportOutOfMemory(cx);
+}
+
+JS_PUBLIC_API(void)
+JS_ReportAllocationOverflow(JSContext *cx)
+{
+ js_ReportAllocationOverflow(cx);
+}
+
+JS_PUBLIC_API(JSErrorReporter)
+JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
+{
+ JSErrorReporter older;
+
+ older = cx->errorReporter;
+ cx->errorReporter = er;
+ return older;
+}
+
+/************************************************************************/
+
+/*
+ * Regular Expressions.
+ */
+JS_PUBLIC_API(JSObject *)
+JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags)
+{
+ jschar *chars;
+ JSObject *obj;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+ obj = js_NewRegExpObject(cx, NULL, chars, length, flags);
+ JS_free(cx, chars);
+ return obj;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags)
+{
+ CHECK_REQUEST(cx);
+ return js_NewRegExpObject(cx, NULL, chars, length, flags);
+}
+
+JS_PUBLIC_API(void)
+JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline)
+{
+ JSRegExpStatics *res;
+
+ CHECK_REQUEST(cx);
+ /* No locking required, cx is thread-private and input must be live. */
+ res = &cx->regExpStatics;
+ res->input = input;
+ res->multiline = multiline;
+ cx->runtime->gcPoke = JS_TRUE;
+}
+
+JS_PUBLIC_API(void)
+JS_ClearRegExpStatics(JSContext *cx)
+{
+ JSRegExpStatics *res;
+
+ /* No locking required, cx is thread-private and input must be live. */
+ res = &cx->regExpStatics;
+ res->input = NULL;
+ res->multiline = JS_FALSE;
+ res->parenCount = 0;
+ res->lastMatch = res->lastParen = js_EmptySubString;
+ res->leftContext = res->rightContext = js_EmptySubString;
+ cx->runtime->gcPoke = JS_TRUE;
+}
+
+JS_PUBLIC_API(void)
+JS_ClearRegExpRoots(JSContext *cx)
+{
+ JSRegExpStatics *res;
+
+ /* No locking required, cx is thread-private and input must be live. */
+ res = &cx->regExpStatics;
+ res->input = NULL;
+ cx->runtime->gcPoke = JS_TRUE;
+}
+
+/* TODO: compile, execute, get/set other statics... */
+
+/************************************************************************/
+
+JS_PUBLIC_API(void)
+JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks)
+{
+ cx->localeCallbacks = callbacks;
+}
+
+JS_PUBLIC_API(JSLocaleCallbacks *)
+JS_GetLocaleCallbacks(JSContext *cx)
+{
+ return cx->localeCallbacks;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(JSBool)
+JS_IsExceptionPending(JSContext *cx)
+{
+ return (JSBool) cx->throwing;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPendingException(JSContext *cx, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ if (!cx->throwing)
+ return JS_FALSE;
+ *vp = cx->exception;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(void)
+JS_SetPendingException(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ cx->throwing = JS_TRUE;
+ cx->exception = v;
+}
+
+JS_PUBLIC_API(void)
+JS_ClearPendingException(JSContext *cx)
+{
+ cx->throwing = JS_FALSE;
+ cx->exception = JSVAL_VOID;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ReportPendingException(JSContext *cx)
+{
+ JSBool save, ok;
+
+ CHECK_REQUEST(cx);
+
+ /*
+ * Set cx->generatingError to suppress the standard error-to-exception
+ * conversion done by all {js,JS}_Report* functions except for OOM. The
+ * cx->generatingError flag was added to suppress recursive divergence
+ * under js_ErrorToException, but it serves for our purposes here too.
+ */
+ save = cx->generatingError;
+ cx->generatingError = JS_TRUE;
+ ok = js_ReportUncaughtException(cx);
+ cx->generatingError = save;
+ return ok;
+}
+
+struct JSExceptionState {
+ JSBool throwing;
+ jsval exception;
+};
+
+JS_PUBLIC_API(JSExceptionState *)
+JS_SaveExceptionState(JSContext *cx)
+{
+ JSExceptionState *state;
+
+ CHECK_REQUEST(cx);
+ state = (JSExceptionState *) JS_malloc(cx, sizeof(JSExceptionState));
+ if (state) {
+ state->throwing = JS_GetPendingException(cx, &state->exception);
+ if (state->throwing && JSVAL_IS_GCTHING(state->exception))
+ js_AddRoot(cx, &state->exception, "JSExceptionState.exception");
+ }
+ return state;
+}
+
+JS_PUBLIC_API(void)
+JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
+{
+ CHECK_REQUEST(cx);
+ if (state) {
+ if (state->throwing)
+ JS_SetPendingException(cx, state->exception);
+ else
+ JS_ClearPendingException(cx);
+ JS_DropExceptionState(cx, state);
+ }
+}
+
+JS_PUBLIC_API(void)
+JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
+{
+ CHECK_REQUEST(cx);
+ if (state) {
+ if (state->throwing && JSVAL_IS_GCTHING(state->exception))
+ JS_RemoveRoot(cx, &state->exception);
+ JS_free(cx, state);
+ }
+}
+
+JS_PUBLIC_API(JSErrorReport *)
+JS_ErrorFromException(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ return js_ErrorFromException(cx, v);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ThrowReportedError(JSContext *cx, const char *message,
+ JSErrorReport *reportp)
+{
+ return cx->fp && js_ErrorToException(cx, message, reportp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ThrowStopIteration(JSContext *cx)
+{
+ return js_ThrowStopIteration(cx);
+}
+
+/*
+ * Get the owning thread id of a context. Returns 0 if the context is not
+ * owned by any thread.
+ */
+JS_PUBLIC_API(jsword)
+JS_GetContextThread(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ return JS_THREAD_ID(cx);
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Set the current thread as the owning thread of a context. Returns the
+ * old owning thread id, or -1 if the operation failed.
+ */
+JS_PUBLIC_API(jsword)
+JS_SetContextThread(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ jsword old = JS_THREAD_ID(cx);
+ if (!js_SetContextThread(cx))
+ return -1;
+ return old;
+#else
+ return 0;
+#endif
+}
+
+JS_PUBLIC_API(jsword)
+JS_ClearContextThread(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ jsword old = JS_THREAD_ID(cx);
+ js_ClearContextThread(cx);
+ return old;
+#else
+ return 0;
+#endif
+}
+
+#ifdef JS_GC_ZEAL
+JS_PUBLIC_API(void)
+JS_SetGCZeal(JSContext *cx, uint8 zeal)
+{
+ cx->runtime->gcZeal = zeal;
+}
+#endif
+
+/************************************************************************/
+
+#if !defined(STATIC_JS_API) && defined(XP_WIN) && !defined (WINCE)
+
+#include <windows.h>
+
+/*
+ * Initialization routine for the JS DLL.
+ */
+BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
+{
+ return TRUE;
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsapi.h b/tools/node_modules/expresso/deps/jscoverage/js/jsapi.h
new file mode 100644
index 0000000..7842192
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsapi.h
@@ -0,0 +1,2699 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsapi_h___
+#define jsapi_h___
+/*
+ * JavaScript API.
+ */
+#include <stddef.h>
+#include <stdio.h>
+#include "js-config.h"
+#include "jspubtd.h"
+#include "jsutil.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Type tags stored in the low bits of a jsval.
+ */
+#define JSVAL_OBJECT 0x0 /* untagged reference to object */
+#define JSVAL_INT 0x1 /* tagged 31-bit integer value */
+#define JSVAL_DOUBLE 0x2 /* tagged reference to double */
+#define JSVAL_STRING 0x4 /* tagged reference to string */
+#define JSVAL_BOOLEAN 0x6 /* tagged boolean value */
+
+/* Type tag bitfield length and derived macros. */
+#define JSVAL_TAGBITS 3
+#define JSVAL_TAGMASK JS_BITMASK(JSVAL_TAGBITS)
+#define JSVAL_TAG(v) ((v) & JSVAL_TAGMASK)
+#define JSVAL_SETTAG(v,t) ((v) | (t))
+#define JSVAL_CLRTAG(v) ((v) & ~(jsval)JSVAL_TAGMASK)
+#define JSVAL_ALIGN JS_BIT(JSVAL_TAGBITS)
+
+/* Predicates for type testing. */
+#define JSVAL_IS_OBJECT(v) (JSVAL_TAG(v) == JSVAL_OBJECT)
+#define JSVAL_IS_NUMBER(v) (JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v))
+#define JSVAL_IS_INT(v) ((v) & JSVAL_INT)
+#define JSVAL_IS_DOUBLE(v) (JSVAL_TAG(v) == JSVAL_DOUBLE)
+#define JSVAL_IS_STRING(v) (JSVAL_TAG(v) == JSVAL_STRING)
+#define JSVAL_IS_BOOLEAN(v) (((v) & ~((jsval)1 << JSVAL_TAGBITS)) == \
+ JSVAL_BOOLEAN)
+#define JSVAL_IS_NULL(v) ((v) == JSVAL_NULL)
+#define JSVAL_IS_VOID(v) ((v) == JSVAL_VOID)
+#define JSVAL_IS_PRIMITIVE(v) (!JSVAL_IS_OBJECT(v) || JSVAL_IS_NULL(v))
+
+/* Objects, strings, and doubles are GC'ed. */
+#define JSVAL_IS_GCTHING(v) (!((v) & JSVAL_INT) && \
+ JSVAL_TAG(v) != JSVAL_BOOLEAN)
+#define JSVAL_TO_GCTHING(v) ((void *)JSVAL_CLRTAG(v))
+#define JSVAL_TO_OBJECT(v) ((JSObject *)JSVAL_TO_GCTHING(v))
+#define JSVAL_TO_DOUBLE(v) ((jsdouble *)JSVAL_TO_GCTHING(v))
+#define JSVAL_TO_STRING(v) ((JSString *)JSVAL_TO_GCTHING(v))
+#define OBJECT_TO_JSVAL(obj) ((jsval)(obj))
+#define DOUBLE_TO_JSVAL(dp) JSVAL_SETTAG((jsval)(dp), JSVAL_DOUBLE)
+#define STRING_TO_JSVAL(str) JSVAL_SETTAG((jsval)(str), JSVAL_STRING)
+
+/* Lock and unlock the GC thing held by a jsval. */
+#define JSVAL_LOCK(cx,v) (JSVAL_IS_GCTHING(v) \
+ ? JS_LockGCThing(cx, JSVAL_TO_GCTHING(v)) \
+ : JS_TRUE)
+#define JSVAL_UNLOCK(cx,v) (JSVAL_IS_GCTHING(v) \
+ ? JS_UnlockGCThing(cx, JSVAL_TO_GCTHING(v)) \
+ : JS_TRUE)
+
+/* Domain limits for the jsval int type. */
+#define JSVAL_INT_BITS 31
+#define JSVAL_INT_POW2(n) ((jsval)1 << (n))
+#define JSVAL_INT_MIN (-JSVAL_INT_POW2(30))
+#define JSVAL_INT_MAX (JSVAL_INT_POW2(30) - 1)
+#define INT_FITS_IN_JSVAL(i) ((jsuint)(i) - (jsuint)JSVAL_INT_MIN <= \
+ (jsuint)(JSVAL_INT_MAX - JSVAL_INT_MIN))
+#define JSVAL_TO_INT(v) ((jsint)(v) >> 1)
+#define INT_TO_JSVAL(i) (((jsval)(i) << 1) | JSVAL_INT)
+
+/* Convert between boolean and jsval. */
+#define JSVAL_TO_BOOLEAN(v) ((JSBool)((v) >> JSVAL_TAGBITS))
+#define BOOLEAN_TO_JSVAL(b) JSVAL_SETTAG((jsval)(b) << JSVAL_TAGBITS, \
+ JSVAL_BOOLEAN)
+
+/* A private data pointer (2-byte-aligned) can be stored as an int jsval. */
+#define JSVAL_TO_PRIVATE(v) ((void *)((v) & ~JSVAL_INT))
+#define PRIVATE_TO_JSVAL(p) ((jsval)(p) | JSVAL_INT)
+
+/* Property attributes, set in JSPropertySpec and passed to API functions. */
+#define JSPROP_ENUMERATE 0x01 /* property is visible to for/in loop */
+#define JSPROP_READONLY 0x02 /* not settable: assignment is no-op */
+#define JSPROP_PERMANENT 0x04 /* property cannot be deleted */
+#define JSPROP_GETTER 0x10 /* property holds getter function */
+#define JSPROP_SETTER 0x20 /* property holds setter function */
+#define JSPROP_SHARED 0x40 /* don't allocate a value slot for this
+ property; don't copy the property on
+ set of the same-named property in an
+ object that delegates to a prototype
+ containing this property */
+#define JSPROP_INDEX 0x80 /* name is actually (jsint) index */
+
+/* Function flags, set in JSFunctionSpec and passed to JS_NewFunction etc. */
+#define JSFUN_LAMBDA 0x08 /* expressed, not declared, function */
+#define JSFUN_GETTER JSPROP_GETTER
+#define JSFUN_SETTER JSPROP_SETTER
+#define JSFUN_BOUND_METHOD 0x40 /* bind this to fun->object's parent */
+#define JSFUN_HEAVYWEIGHT 0x80 /* activation requires a Call object */
+
+#define JSFUN_DISJOINT_FLAGS(f) ((f) & 0x0f)
+#define JSFUN_GSFLAGS(f) ((f) & (JSFUN_GETTER | JSFUN_SETTER))
+
+#define JSFUN_GETTER_TEST(f) ((f) & JSFUN_GETTER)
+#define JSFUN_SETTER_TEST(f) ((f) & JSFUN_SETTER)
+#define JSFUN_BOUND_METHOD_TEST(f) ((f) & JSFUN_BOUND_METHOD)
+#define JSFUN_HEAVYWEIGHT_TEST(f) ((f) & JSFUN_HEAVYWEIGHT)
+
+#define JSFUN_GSFLAG2ATTR(f) JSFUN_GSFLAGS(f)
+
+#define JSFUN_THISP_FLAGS(f) (f)
+#define JSFUN_THISP_TEST(f,t) ((f) & t)
+
+#define JSFUN_THISP_STRING 0x0100 /* |this| may be a primitive string */
+#define JSFUN_THISP_NUMBER 0x0200 /* |this| may be a primitive number */
+#define JSFUN_THISP_BOOLEAN 0x0400 /* |this| may be a primitive boolean */
+#define JSFUN_THISP_PRIMITIVE 0x0700 /* |this| may be any primitive value */
+
+#define JSFUN_FAST_NATIVE 0x0800 /* JSFastNative needs no JSStackFrame */
+
+#define JSFUN_FLAGS_MASK 0x0ff8 /* overlay JSFUN_* attributes --
+ note that bit #15 is used internally
+ to flag interpreted functions */
+
+#define JSFUN_STUB_GSOPS 0x1000 /* use JS_PropertyStub getter/setter
+ instead of defaulting to class gsops
+ for property holding function */
+
+/*
+ * Re-use JSFUN_LAMBDA, which applies only to scripted functions, for use in
+ * JSFunctionSpec arrays that specify generic native prototype methods, i.e.,
+ * methods of a class prototype that are exposed as static methods taking an
+ * extra leading argument: the generic |this| parameter.
+ *
+ * If you set this flag in a JSFunctionSpec struct's flags initializer, then
+ * that struct must live at least as long as the native static method object
+ * created due to this flag by JS_DefineFunctions or JS_InitClass. Typically
+ * JSFunctionSpec structs are allocated in static arrays.
+ */
+#define JSFUN_GENERIC_NATIVE JSFUN_LAMBDA
+
+/*
+ * Well-known JS values. The extern'd variables are initialized when the
+ * first JSContext is created by JS_NewContext (see below).
+ */
+#define JSVAL_VOID BOOLEAN_TO_JSVAL(2)
+#define JSVAL_NULL OBJECT_TO_JSVAL(0)
+#define JSVAL_ZERO INT_TO_JSVAL(0)
+#define JSVAL_ONE INT_TO_JSVAL(1)
+#define JSVAL_FALSE BOOLEAN_TO_JSVAL(JS_FALSE)
+#define JSVAL_TRUE BOOLEAN_TO_JSVAL(JS_TRUE)
+
+/*
+ * Microseconds since the epoch, midnight, January 1, 1970 UTC. See the
+ * comment in jstypes.h regarding safe int64 usage.
+ */
+extern JS_PUBLIC_API(int64)
+JS_Now(void);
+
+/* Don't want to export data, so provide accessors for non-inline jsvals. */
+extern JS_PUBLIC_API(jsval)
+JS_GetNaNValue(JSContext *cx);
+
+extern JS_PUBLIC_API(jsval)
+JS_GetNegativeInfinityValue(JSContext *cx);
+
+extern JS_PUBLIC_API(jsval)
+JS_GetPositiveInfinityValue(JSContext *cx);
+
+extern JS_PUBLIC_API(jsval)
+JS_GetEmptyStringValue(JSContext *cx);
+
+/*
+ * Format is a string of the following characters (spaces are insignificant),
+ * specifying the tabulated type conversions:
+ *
+ * b JSBool Boolean
+ * c uint16/jschar ECMA uint16, Unicode char
+ * i int32 ECMA int32
+ * u uint32 ECMA uint32
+ * j int32 Rounded int32 (coordinate)
+ * d jsdouble IEEE double
+ * I jsdouble Integral IEEE double
+ * s char * C string
+ * S JSString * Unicode string, accessed by a JSString pointer
+ * W jschar * Unicode character vector, 0-terminated (W for wide)
+ * o JSObject * Object reference
+ * f JSFunction * Function private
+ * v jsval Argument value (no conversion)
+ * * N/A Skip this argument (no vararg)
+ * / N/A End of required arguments
+ *
+ * The variable argument list after format must consist of &b, &c, &s, e.g.,
+ * where those variables have the types given above. For the pointer types
+ * char *, JSString *, and JSObject *, the pointed-at memory returned belongs
+ * to the JS runtime, not to the calling native code. The runtime promises
+ * to keep this memory valid so long as argv refers to allocated stack space
+ * (so long as the native function is active).
+ *
+ * Fewer arguments than format specifies may be passed only if there is a /
+ * in format after the last required argument specifier and argc is at least
+ * the number of required arguments. More arguments than format specifies
+ * may be passed without error; it is up to the caller to deal with trailing
+ * unconverted arguments.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
+ ...);
+
+#ifdef va_start
+extern JS_PUBLIC_API(JSBool)
+JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
+ const char *format, va_list ap);
+#endif
+
+/*
+ * Inverse of JS_ConvertArguments: scan format and convert trailing arguments
+ * into jsvals, GC-rooted if necessary by the JS stack. Return null on error,
+ * and a pointer to the new argument vector on success. Also return a stack
+ * mark on success via *markp, in which case the caller must eventually clean
+ * up by calling JS_PopArguments.
+ *
+ * Note that the number of actual arguments supplied is specified exclusively
+ * by format, so there is no argc parameter.
+ */
+extern JS_PUBLIC_API(jsval *)
+JS_PushArguments(JSContext *cx, void **markp, const char *format, ...);
+
+#ifdef va_start
+extern JS_PUBLIC_API(jsval *)
+JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap);
+#endif
+
+extern JS_PUBLIC_API(void)
+JS_PopArguments(JSContext *cx, void *mark);
+
+#ifdef JS_ARGUMENT_FORMATTER_DEFINED
+
+/*
+ * Add and remove a format string handler for JS_{Convert,Push}Arguments{,VA}.
+ * The handler function has this signature (see jspubtd.h):
+ *
+ * JSBool MyArgumentFormatter(JSContext *cx, const char *format,
+ * JSBool fromJS, jsval **vpp, va_list *app);
+ *
+ * It should return true on success, and return false after reporting an error
+ * or detecting an already-reported error.
+ *
+ * For a given format string, for example "AA", the formatter is called from
+ * JS_ConvertArgumentsVA like so:
+ *
+ * formatter(cx, "AA...", JS_TRUE, &sp, &ap);
+ *
+ * sp points into the arguments array on the JS stack, while ap points into
+ * the stdarg.h va_list on the C stack. The JS_TRUE passed for fromJS tells
+ * the formatter to convert zero or more jsvals at sp to zero or more C values
+ * accessed via pointers-to-values at ap, updating both sp (via *vpp) and ap
+ * (via *app) to point past the converted arguments and their result pointers
+ * on the C stack.
+ *
+ * When called from JS_PushArgumentsVA, the formatter is invoked thus:
+ *
+ * formatter(cx, "AA...", JS_FALSE, &sp, &ap);
+ *
+ * where JS_FALSE for fromJS means to wrap the C values at ap according to the
+ * format specifier and store them at sp, updating ap and sp appropriately.
+ *
+ * The "..." after "AA" is the rest of the format string that was passed into
+ * JS_{Convert,Push}Arguments{,VA}. The actual format trailing substring used
+ * in each Convert or PushArguments call is passed to the formatter, so that
+ * one such function may implement several formats, in order to share code.
+ *
+ * Remove just forgets about any handler associated with format. Add does not
+ * copy format, it points at the string storage allocated by the caller, which
+ * is typically a string constant. If format is in dynamic storage, it is up
+ * to the caller to keep the string alive until Remove is called.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_AddArgumentFormatter(JSContext *cx, const char *format,
+ JSArgumentFormatter formatter);
+
+extern JS_PUBLIC_API(void)
+JS_RemoveArgumentFormatter(JSContext *cx, const char *format);
+
+#endif /* JS_ARGUMENT_FORMATTER_DEFINED */
+
+extern JS_PUBLIC_API(JSBool)
+JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_ValueToFunction(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_ValueToConstructor(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(JSString *)
+JS_ValueToString(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(JSString *)
+JS_ValueToSource(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp);
+
+/*
+ * Convert a value to a number, then to an int32, according to the ECMA rules
+ * for ToInt32.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip);
+
+/*
+ * Convert a value to a number, then to a uint32, according to the ECMA rules
+ * for ToUint32.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip);
+
+/*
+ * Convert a value to a number, then to an int32 if it fits by rounding to
+ * nearest; but failing with an error report if the double is out of range
+ * or unordered.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip);
+
+/*
+ * ECMA ToUint16, for mapping a jsval to a Unicode point.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp);
+
+extern JS_PUBLIC_API(JSType)
+JS_TypeOfValue(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(const char *)
+JS_GetTypeName(JSContext *cx, JSType type);
+
+/************************************************************************/
+
+/*
+ * Initialization, locking, contexts, and memory allocation.
+ *
+ * It is important that the first runtime and first context be created in a
+ * single-threaded fashion, otherwise the behavior of the library is undefined.
+ * See: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference
+ */
+#define JS_NewRuntime JS_Init
+#define JS_DestroyRuntime JS_Finish
+#define JS_LockRuntime JS_Lock
+#define JS_UnlockRuntime JS_Unlock
+
+extern JS_PUBLIC_API(JSRuntime *)
+JS_NewRuntime(uint32 maxbytes);
+
+extern JS_PUBLIC_API(void)
+JS_DestroyRuntime(JSRuntime *rt);
+
+extern JS_PUBLIC_API(void)
+JS_ShutDown(void);
+
+JS_PUBLIC_API(void *)
+JS_GetRuntimePrivate(JSRuntime *rt);
+
+JS_PUBLIC_API(void)
+JS_SetRuntimePrivate(JSRuntime *rt, void *data);
+
+extern JS_PUBLIC_API(void)
+JS_BeginRequest(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_EndRequest(JSContext *cx);
+
+/* Yield to pending GC operations, regardless of request depth */
+extern JS_PUBLIC_API(void)
+JS_YieldRequest(JSContext *cx);
+
+extern JS_PUBLIC_API(jsrefcount)
+JS_SuspendRequest(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth);
+
+#ifdef __cplusplus
+JS_END_EXTERN_C
+
+class JSAutoRequest {
+ public:
+ JSAutoRequest(JSContext *cx) : mContext(cx), mSaveDepth(0) {
+ JS_BeginRequest(mContext);
+ }
+ ~JSAutoRequest() {
+ JS_EndRequest(mContext);
+ }
+
+ void suspend() {
+ mSaveDepth = JS_SuspendRequest(mContext);
+ }
+ void resume() {
+ JS_ResumeRequest(mContext, mSaveDepth);
+ }
+
+ protected:
+ JSContext *mContext;
+ jsrefcount mSaveDepth;
+
+#if 0
+ private:
+ static void *operator new(size_t) CPP_THROW_NEW { return 0; };
+ static void operator delete(void *, size_t) { };
+#endif
+};
+
+class JSAutoSuspendRequest {
+ public:
+ JSAutoSuspendRequest(JSContext *cx) : mContext(cx), mSaveDepth(0) {
+ if (mContext) {
+ mSaveDepth = JS_SuspendRequest(mContext);
+ }
+ }
+ ~JSAutoSuspendRequest() {
+ resume();
+ }
+
+ void resume() {
+ if (mContext) {
+ JS_ResumeRequest(mContext, mSaveDepth);
+ mContext = 0;
+ }
+ }
+
+ protected:
+ JSContext *mContext;
+ jsrefcount mSaveDepth;
+
+#if 0
+ private:
+ static void *operator new(size_t) CPP_THROW_NEW { return 0; };
+ static void operator delete(void *, size_t) { };
+#endif
+};
+
+JS_BEGIN_EXTERN_C
+#endif
+
+extern JS_PUBLIC_API(void)
+JS_Lock(JSRuntime *rt);
+
+extern JS_PUBLIC_API(void)
+JS_Unlock(JSRuntime *rt);
+
+extern JS_PUBLIC_API(JSContextCallback)
+JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback);
+
+extern JS_PUBLIC_API(JSContext *)
+JS_NewContext(JSRuntime *rt, size_t stackChunkSize);
+
+extern JS_PUBLIC_API(void)
+JS_DestroyContext(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_DestroyContextNoGC(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_DestroyContextMaybeGC(JSContext *cx);
+
+extern JS_PUBLIC_API(void *)
+JS_GetContextPrivate(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_SetContextPrivate(JSContext *cx, void *data);
+
+extern JS_PUBLIC_API(JSRuntime *)
+JS_GetRuntime(JSContext *cx);
+
+extern JS_PUBLIC_API(JSContext *)
+JS_ContextIterator(JSRuntime *rt, JSContext **iterp);
+
+extern JS_PUBLIC_API(JSVersion)
+JS_GetVersion(JSContext *cx);
+
+extern JS_PUBLIC_API(JSVersion)
+JS_SetVersion(JSContext *cx, JSVersion version);
+
+extern JS_PUBLIC_API(const char *)
+JS_VersionToString(JSVersion version);
+
+extern JS_PUBLIC_API(JSVersion)
+JS_StringToVersion(const char *string);
+
+/*
+ * JS options are orthogonal to version, and may be freely composed with one
+ * another as well as with version.
+ *
+ * JSOPTION_VAROBJFIX is recommended -- see the comments associated with the
+ * prototypes for JS_ExecuteScript, JS_EvaluateScript, etc.
+ */
+#define JSOPTION_STRICT JS_BIT(0) /* warn on dubious practice */
+#define JSOPTION_WERROR JS_BIT(1) /* convert warning to error */
+#define JSOPTION_VAROBJFIX JS_BIT(2) /* make JS_EvaluateScript use
+ the last object on its 'obj'
+ param's scope chain as the
+ ECMA 'variables object' */
+#define JSOPTION_PRIVATE_IS_NSISUPPORTS \
+ JS_BIT(3) /* context private data points
+ to an nsISupports subclass */
+#define JSOPTION_COMPILE_N_GO JS_BIT(4) /* caller of JS_Compile*Script
+ promises to execute compiled
+ script once only; enables
+ compile-time scope chain
+ resolution of consts. */
+#define JSOPTION_ATLINE JS_BIT(5) /* //@line number ["filename"]
+ option supported for the
+ XUL preprocessor and kindred
+ beasts. */
+#define JSOPTION_XML JS_BIT(6) /* EMCAScript for XML support:
+ parse <!-- --> as a token,
+ not backward compatible with
+ the comment-hiding hack used
+ in HTML script tags. */
+#define JSOPTION_NATIVE_BRANCH_CALLBACK \
+ JS_BIT(7) /* the branch callback set by
+ JS_SetBranchCallback may be
+ called with a null script
+ parameter, by native code
+ that loops intensively.
+ Deprecated, use
+ JS_SetOperationCallback
+ instead */
+#define JSOPTION_DONT_REPORT_UNCAUGHT \
+ JS_BIT(8) /* When returning from the
+ outermost API call, prevent
+ uncaught exceptions from
+ being converted to error
+ reports */
+
+#define JSOPTION_RELIMIT JS_BIT(9) /* Throw exception on any
+ regular expression which
+ backtracks more than n^3
+ times, where n is length
+ of the input string */
+#define JSOPTION_ANONFUNFIX JS_BIT(10) /* Disallow function () {} in
+ statement context per
+ ECMA-262 Edition 3. */
+
+#define JSOPTION_JIT JS_BIT(11) /* Enable JIT compilation. */
+
+#define JSOPTION_NO_SCRIPT_RVAL JS_BIT(12) /* A promise to the compiler
+ that a null rval out-param
+ will be passed to each call
+ to JS_ExecuteScript. */
+
+extern JS_PUBLIC_API(uint32)
+JS_GetOptions(JSContext *cx);
+
+extern JS_PUBLIC_API(uint32)
+JS_SetOptions(JSContext *cx, uint32 options);
+
+extern JS_PUBLIC_API(uint32)
+JS_ToggleOptions(JSContext *cx, uint32 options);
+
+extern JS_PUBLIC_API(const char *)
+JS_GetImplementationVersion(void);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetGlobalObject(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_SetGlobalObject(JSContext *cx, JSObject *obj);
+
+/*
+ * Initialize standard JS class constructors, prototypes, and any top-level
+ * functions and constants associated with the standard classes (e.g. isNaN
+ * for Number).
+ *
+ * NB: This sets cx's global object to obj if it was null.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_InitStandardClasses(JSContext *cx, JSObject *obj);
+
+/*
+ * Resolve id, which must contain either a string or an int, to a standard
+ * class name in obj if possible, defining the class's constructor and/or
+ * prototype and storing true in *resolved. If id does not name a standard
+ * class or a top-level property induced by initializing a standard class,
+ * store false in *resolved and just return true. Return false on error,
+ * as usual for JSBool result-typed API entry points.
+ *
+ * This API can be called directly from a global object class's resolve op,
+ * to define standard classes lazily. The class's enumerate op should call
+ * JS_EnumerateStandardClasses(cx, obj), to define eagerly during for..in
+ * loops any classes not yet resolved lazily.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
+ JSBool *resolved);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj);
+
+/*
+ * Enumerate any already-resolved standard class ids into ida, or into a new
+ * JSIdArray if ida is null. Return the augmented array on success, null on
+ * failure with ida (if it was non-null on entry) destroyed.
+ */
+extern JS_PUBLIC_API(JSIdArray *)
+JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
+ JSIdArray *ida);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
+ JSObject **objp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetScopeChain(JSContext *cx);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetGlobalForObject(JSContext *cx, JSObject *obj);
+
+/*
+ * Macros to hide interpreter stack layout details from a JSFastNative using
+ * its jsval *vp parameter. The stack layout underlying invocation can't change
+ * without breaking source and binary compatibility (argv[-2] is well-known to
+ * be the callee jsval, and argv[-1] is as well known to be |this|).
+ *
+ * Note well: However, argv[-1] may be JSVAL_NULL where with slow natives it
+ * is the global object, so embeddings implementing fast natives *must* call
+ * JS_THIS or JS_THIS_OBJECT and test for failure indicated by a null return,
+ * which should propagate as a false return from native functions and hooks.
+ *
+ * To reduce boilerplace checks, JS_InstanceOf and JS_GetInstancePrivate now
+ * handle a null obj parameter by returning false (throwing a TypeError if
+ * given non-null argv), so most native functions that type-check their |this|
+ * parameter need not add null checking.
+ *
+ * NB: there is an anti-dependency between JS_CALLEE and JS_SET_RVAL: native
+ * methods that may inspect their callee must defer setting their return value
+ * until after any such possible inspection. Otherwise the return value will be
+ * inspected instead of the callee function object.
+ *
+ * WARNING: These are not (yet) mandatory macros, but new code outside of the
+ * engine should use them. In the Mozilla 2.0 milestone their definitions may
+ * change incompatibly.
+ */
+#define JS_CALLEE(cx,vp) ((vp)[0])
+#define JS_ARGV_CALLEE(argv) ((argv)[-2])
+#define JS_THIS(cx,vp) JS_ComputeThis(cx, vp)
+#define JS_THIS_OBJECT(cx,vp) ((JSObject *) JS_THIS(cx,vp))
+#define JS_ARGV(cx,vp) ((vp) + 2)
+#define JS_RVAL(cx,vp) (*(vp))
+#define JS_SET_RVAL(cx,vp,v) (*(vp) = (v))
+
+extern JS_PUBLIC_API(jsval)
+JS_ComputeThis(JSContext *cx, jsval *vp);
+
+extern JS_PUBLIC_API(void *)
+JS_malloc(JSContext *cx, size_t nbytes);
+
+extern JS_PUBLIC_API(void *)
+JS_realloc(JSContext *cx, void *p, size_t nbytes);
+
+extern JS_PUBLIC_API(void)
+JS_free(JSContext *cx, void *p);
+
+extern JS_PUBLIC_API(char *)
+JS_strdup(JSContext *cx, const char *s);
+
+extern JS_PUBLIC_API(jsdouble *)
+JS_NewDouble(JSContext *cx, jsdouble d);
+
+extern JS_PUBLIC_API(JSBool)
+JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval);
+
+/*
+ * A JS GC root is a pointer to a JSObject *, JSString *, or jsdouble * that
+ * itself points into the GC heap (more recently, we support this extension:
+ * a root may be a pointer to a jsval v for which JSVAL_IS_GCTHING(v) is true).
+ *
+ * Therefore, you never pass JSObject *obj to JS_AddRoot(cx, obj). You always
+ * call JS_AddRoot(cx, &obj), passing obj by reference. And later, before obj
+ * or the structure it is embedded within goes out of scope or is freed, you
+ * must call JS_RemoveRoot(cx, &obj).
+ *
+ * Also, use JS_AddNamedRoot(cx, &structPtr->memberObj, "structPtr->memberObj")
+ * in preference to JS_AddRoot(cx, &structPtr->memberObj), in order to identify
+ * roots by their source callsites. This way, you can find the callsite while
+ * debugging if you should fail to do JS_RemoveRoot(cx, &structPtr->memberObj)
+ * before freeing structPtr's memory.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_AddRoot(JSContext *cx, void *rp);
+
+#ifdef NAME_ALL_GC_ROOTS
+#define JS_DEFINE_TO_TOKEN(def) #def
+#define JS_DEFINE_TO_STRING(def) JS_DEFINE_TO_TOKEN(def)
+#define JS_AddRoot(cx,rp) JS_AddNamedRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__))
+#endif
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddNamedRoot(JSContext *cx, void *rp, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
+JS_RemoveRoot(JSContext *cx, void *rp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_RemoveRootRT(JSRuntime *rt, void *rp);
+
+/*
+ * The last GC thing of each type (object, string, double, external string
+ * types) created on a given context is kept alive until another thing of the
+ * same type is created, using a newborn root in the context. These newborn
+ * roots help native code protect newly-created GC-things from GC invocations
+ * activated before those things can be rooted using local or global roots.
+ *
+ * However, the newborn roots can also entrain great gobs of garbage, so the
+ * JS_GC entry point clears them for the context on which GC is being forced.
+ * Embeddings may need to do likewise for all contexts.
+ *
+ * See the scoped local root API immediately below for a better way to manage
+ * newborns in cases where native hooks (functions, getters, setters, etc.)
+ * create many GC-things, potentially without connecting them to predefined
+ * local roots such as *rval or argv[i] in an active native function. Using
+ * JS_EnterLocalRootScope disables updating of the context's per-gc-thing-type
+ * newborn roots, until control flow unwinds and leaves the outermost nesting
+ * local root scope.
+ */
+extern JS_PUBLIC_API(void)
+JS_ClearNewbornRoots(JSContext *cx);
+
+/*
+ * Scoped local root management allows native functions, getter/setters, etc.
+ * to avoid worrying about the newborn root pigeon-holes, overloading local
+ * roots allocated in argv and *rval, or ending up having to call JS_Add*Root
+ * and JS_RemoveRoot to manage global roots temporarily.
+ *
+ * Instead, calling JS_EnterLocalRootScope and JS_LeaveLocalRootScope around
+ * the body of the native hook causes the engine to allocate a local root for
+ * each newborn created in between the two API calls, using a local root stack
+ * associated with cx. For example:
+ *
+ * JSBool
+ * my_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+ * {
+ * JSBool ok;
+ *
+ * if (!JS_EnterLocalRootScope(cx))
+ * return JS_FALSE;
+ * ok = my_GetPropertyBody(cx, obj, id, vp);
+ * JS_LeaveLocalRootScope(cx);
+ * return ok;
+ * }
+ *
+ * NB: JS_LeaveLocalRootScope must be called once for every prior successful
+ * call to JS_EnterLocalRootScope. If JS_EnterLocalRootScope fails, you must
+ * not make the matching JS_LeaveLocalRootScope call.
+ *
+ * JS_LeaveLocalRootScopeWithResult(cx, rval) is an alternative way to leave
+ * a local root scope that protects a result or return value, by effectively
+ * pushing it in the caller's local root scope.
+ *
+ * In case a native hook allocates many objects or other GC-things, but the
+ * native protects some of those GC-things by storing them as property values
+ * in an object that is itself protected, the hook can call JS_ForgetLocalRoot
+ * to free the local root automatically pushed for the now-protected GC-thing.
+ *
+ * JS_ForgetLocalRoot works on any GC-thing allocated in the current local
+ * root scope, but it's more time-efficient when called on references to more
+ * recently created GC-things. Calling it successively on other than the most
+ * recently allocated GC-thing will tend to average the time inefficiency, and
+ * may risk O(n^2) growth rate, but in any event, you shouldn't allocate too
+ * many local roots if you can root as you go (build a tree of objects from
+ * the top down, forgetting each latest-allocated GC-thing immediately upon
+ * linking it to its parent).
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_EnterLocalRootScope(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_LeaveLocalRootScope(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval);
+
+extern JS_PUBLIC_API(void)
+JS_ForgetLocalRoot(JSContext *cx, void *thing);
+
+#ifdef __cplusplus
+JS_END_EXTERN_C
+
+class JSAutoLocalRootScope {
+ public:
+ JSAutoLocalRootScope(JSContext *cx) : mContext(cx) {
+ JS_EnterLocalRootScope(mContext);
+ }
+ ~JSAutoLocalRootScope() {
+ JS_LeaveLocalRootScope(mContext);
+ }
+
+ void forget(void *thing) {
+ JS_ForgetLocalRoot(mContext, thing);
+ }
+
+ protected:
+ JSContext *mContext;
+
+#if 0
+ private:
+ static void *operator new(size_t) CPP_THROW_NEW { return 0; };
+ static void operator delete(void *, size_t) { };
+#endif
+};
+
+JS_BEGIN_EXTERN_C
+#endif
+
+#ifdef DEBUG
+extern JS_PUBLIC_API(void)
+JS_DumpNamedRoots(JSRuntime *rt,
+ void (*dump)(const char *name, void *rp, void *data),
+ void *data);
+#endif
+
+/*
+ * Call JS_MapGCRoots to map the GC's roots table using map(rp, name, data).
+ * The root is pointed at by rp; if the root is unnamed, name is null; data is
+ * supplied from the third parameter to JS_MapGCRoots.
+ *
+ * The map function should return JS_MAP_GCROOT_REMOVE to cause the currently
+ * enumerated root to be removed. To stop enumeration, set JS_MAP_GCROOT_STOP
+ * in the return value. To keep on mapping, return JS_MAP_GCROOT_NEXT. These
+ * constants are flags; you can OR them together.
+ *
+ * This function acquires and releases rt's GC lock around the mapping of the
+ * roots table, so the map function should run to completion in as few cycles
+ * as possible. Of course, map cannot call JS_GC, JS_MaybeGC, JS_BeginRequest,
+ * or any JS API entry point that acquires locks, without double-tripping or
+ * deadlocking on the GC lock.
+ *
+ * JS_MapGCRoots returns the count of roots that were successfully mapped.
+ */
+#define JS_MAP_GCROOT_NEXT 0 /* continue mapping entries */
+#define JS_MAP_GCROOT_STOP 1 /* stop mapping entries */
+#define JS_MAP_GCROOT_REMOVE 2 /* remove and free the current entry */
+
+typedef intN
+(* JSGCRootMapFun)(void *rp, const char *name, void *data);
+
+extern JS_PUBLIC_API(uint32)
+JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LockGCThing(JSContext *cx, void *thing);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LockGCThingRT(JSRuntime *rt, void *thing);
+
+extern JS_PUBLIC_API(JSBool)
+JS_UnlockGCThing(JSContext *cx, void *thing);
+
+extern JS_PUBLIC_API(JSBool)
+JS_UnlockGCThingRT(JSRuntime *rt, void *thing);
+
+/*
+ * Register externally maintained GC roots.
+ *
+ * traceOp: the trace operation. For each root the implementation should call
+ * JS_CallTracer whenever the root contains a traceable thing.
+ * data: the data argument to pass to each invocation of traceOp.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetExtraGCRoots(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
+
+/*
+ * For implementors of JSMarkOp. All new code should implement JSTraceOp
+ * instead.
+ */
+extern JS_PUBLIC_API(void)
+JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg);
+
+/*
+ * JS_CallTracer API and related macros for implementors of JSTraceOp, to
+ * enumerate all references to traceable things reachable via a property or
+ * other strong ref identified for debugging purposes by name or index or
+ * a naming callback.
+ *
+ * By definition references to traceable things include non-null pointers
+ * to JSObject, JSString and jsdouble and corresponding jsvals.
+ *
+ * See the JSTraceOp typedef in jspubtd.h.
+ */
+
+/* Trace kinds to pass to JS_Tracing. */
+#define JSTRACE_OBJECT 0
+#define JSTRACE_DOUBLE 1
+#define JSTRACE_STRING 2
+
+/*
+ * Use the following macros to check if a particular jsval is a traceable
+ * thing and to extract the thing and its kind to pass to JS_CallTracer.
+ */
+#define JSVAL_IS_TRACEABLE(v) (JSVAL_IS_GCTHING(v) && !JSVAL_IS_NULL(v))
+#define JSVAL_TO_TRACEABLE(v) (JSVAL_TO_GCTHING(v))
+#define JSVAL_TRACE_KIND(v) (JSVAL_TAG(v) >> 1)
+
+JS_STATIC_ASSERT(JSVAL_TRACE_KIND(JSVAL_OBJECT) == JSTRACE_OBJECT);
+JS_STATIC_ASSERT(JSVAL_TRACE_KIND(JSVAL_DOUBLE) == JSTRACE_DOUBLE);
+JS_STATIC_ASSERT(JSVAL_TRACE_KIND(JSVAL_STRING) == JSTRACE_STRING);
+
+struct JSTracer {
+ JSContext *context;
+ JSTraceCallback callback;
+#ifdef DEBUG
+ JSTraceNamePrinter debugPrinter;
+ const void *debugPrintArg;
+ size_t debugPrintIndex;
+#endif
+};
+
+/*
+ * The method to call on each reference to a traceable thing stored in a
+ * particular JSObject or other runtime structure. With DEBUG defined the
+ * caller before calling JS_CallTracer must initialize JSTracer fields
+ * describing the reference using the macros below.
+ */
+extern JS_PUBLIC_API(void)
+JS_CallTracer(JSTracer *trc, void *thing, uint32 kind);
+
+/*
+ * Set debugging information about a reference to a traceable thing to prepare
+ * for the following call to JS_CallTracer.
+ *
+ * When printer is null, arg must be const char * or char * C string naming
+ * the reference and index must be either (size_t)-1 indicating that the name
+ * alone describes the reference or it must be an index into some array vector
+ * that stores the reference.
+ *
+ * When printer callback is not null, the arg and index arguments are
+ * available to the callback as debugPrinterArg and debugPrintIndex fields
+ * of JSTracer.
+ *
+ * The storage for name or callback's arguments needs to live only until
+ * the following call to JS_CallTracer returns.
+ */
+#ifdef DEBUG
+# define JS_SET_TRACING_DETAILS(trc, printer, arg, index) \
+ JS_BEGIN_MACRO \
+ (trc)->debugPrinter = (printer); \
+ (trc)->debugPrintArg = (arg); \
+ (trc)->debugPrintIndex = (index); \
+ JS_END_MACRO
+#else
+# define JS_SET_TRACING_DETAILS(trc, printer, arg, index) \
+ JS_BEGIN_MACRO \
+ JS_END_MACRO
+#endif
+
+/*
+ * Convenience macro to describe the argument of JS_CallTracer using C string
+ * and index.
+ */
+# define JS_SET_TRACING_INDEX(trc, name, index) \
+ JS_SET_TRACING_DETAILS(trc, NULL, name, index)
+
+/*
+ * Convenience macro to describe the argument of JS_CallTracer using C string.
+ */
+# define JS_SET_TRACING_NAME(trc, name) \
+ JS_SET_TRACING_DETAILS(trc, NULL, name, (size_t)-1)
+
+/*
+ * Convenience macro to invoke JS_CallTracer using C string as the name for
+ * the reference to a traceable thing.
+ */
+# define JS_CALL_TRACER(trc, thing, kind, name) \
+ JS_BEGIN_MACRO \
+ JS_SET_TRACING_NAME(trc, name); \
+ JS_CallTracer((trc), (thing), (kind)); \
+ JS_END_MACRO
+
+/*
+ * Convenience macros to invoke JS_CallTracer when jsval represents a
+ * reference to a traceable thing.
+ */
+#define JS_CALL_VALUE_TRACER(trc, val, name) \
+ JS_BEGIN_MACRO \
+ if (JSVAL_IS_TRACEABLE(val)) { \
+ JS_CALL_TRACER((trc), JSVAL_TO_GCTHING(val), \
+ JSVAL_TRACE_KIND(val), name); \
+ } \
+ JS_END_MACRO
+
+#define JS_CALL_OBJECT_TRACER(trc, object, name) \
+ JS_BEGIN_MACRO \
+ JSObject *obj_ = (object); \
+ JS_ASSERT(obj_); \
+ JS_CALL_TRACER((trc), obj_, JSTRACE_OBJECT, name); \
+ JS_END_MACRO
+
+#define JS_CALL_STRING_TRACER(trc, string, name) \
+ JS_BEGIN_MACRO \
+ JSString *str_ = (string); \
+ JS_ASSERT(str_); \
+ JS_CALL_TRACER((trc), str_, JSTRACE_STRING, name); \
+ JS_END_MACRO
+
+#define JS_CALL_DOUBLE_TRACER(trc, number, name) \
+ JS_BEGIN_MACRO \
+ jsdouble *num_ = (number); \
+ JS_ASSERT(num_); \
+ JS_CALL_TRACER((trc), num_, JSTRACE_DOUBLE, name); \
+ JS_END_MACRO
+
+/*
+ * API for JSTraceCallback implementations.
+ */
+# define JS_TRACER_INIT(trc, cx_, callback_) \
+ JS_BEGIN_MACRO \
+ (trc)->context = (cx_); \
+ (trc)->callback = (callback_); \
+ JS_SET_TRACING_DETAILS(trc, NULL, NULL, (size_t)-1); \
+ JS_END_MACRO
+
+extern JS_PUBLIC_API(void)
+JS_TraceChildren(JSTracer *trc, void *thing, uint32 kind);
+
+extern JS_PUBLIC_API(void)
+JS_TraceRuntime(JSTracer *trc);
+
+#ifdef DEBUG
+
+extern JS_PUBLIC_API(void)
+JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
+ void *thing, uint32 kind, JSBool includeDetails);
+
+/*
+ * DEBUG-only method to dump the object graph of heap-allocated things.
+ *
+ * fp: file for the dump output.
+ * start: when non-null, dump only things reachable from start
+ * thing. Otherwise dump all things reachable from the
+ * runtime roots.
+ * startKind: trace kind of start if start is not null. Must be 0 when
+ * start is null.
+ * thingToFind: dump only paths in the object graph leading to thingToFind
+ * when non-null.
+ * maxDepth: the upper bound on the number of edges to descend from the
+ * graph roots.
+ * thingToIgnore: thing to ignore during the graph traversal when non-null.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, uint32 startKind,
+ void *thingToFind, size_t maxDepth, void *thingToIgnore);
+
+#endif
+
+/*
+ * Garbage collector API.
+ */
+extern JS_PUBLIC_API(void)
+JS_GC(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_MaybeGC(JSContext *cx);
+
+extern JS_PUBLIC_API(JSGCCallback)
+JS_SetGCCallback(JSContext *cx, JSGCCallback cb);
+
+extern JS_PUBLIC_API(JSGCCallback)
+JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsGCMarkingTracer(JSTracer *trc);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsAboutToBeFinalized(JSContext *cx, void *thing);
+
+typedef enum JSGCParamKey {
+ /* Maximum nominal heap before last ditch GC. */
+ JSGC_MAX_BYTES = 0,
+
+ /* Number of JS_malloc bytes before last ditch GC. */
+ JSGC_MAX_MALLOC_BYTES = 1,
+
+ /* Hoard stackPools for this long, in ms, default is 30 seconds. */
+ JSGC_STACKPOOL_LIFESPAN = 2
+} JSGCParamKey;
+
+extern JS_PUBLIC_API(void)
+JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value);
+
+/*
+ * Add a finalizer for external strings created by JS_NewExternalString (see
+ * below) using a type-code returned from this function, and that understands
+ * how to free or release the memory pointed at by JS_GetStringChars(str).
+ *
+ * Return a nonnegative type index if there is room for finalizer in the
+ * global GC finalizers table, else return -1. If the engine is compiled
+ * JS_THREADSAFE and used in a multi-threaded environment, this function must
+ * be invoked on the primordial thread only, at startup -- or else the entire
+ * program must single-thread itself while loading a module that calls this
+ * function.
+ */
+extern JS_PUBLIC_API(intN)
+JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer);
+
+/*
+ * Remove finalizer from the global GC finalizers table, returning its type
+ * code if found, -1 if not found.
+ *
+ * As with JS_AddExternalStringFinalizer, there is a threading restriction
+ * if you compile the engine JS_THREADSAFE: this function may be called for a
+ * given finalizer pointer on only one thread; different threads may call to
+ * remove distinct finalizers safely.
+ *
+ * You must ensure that all strings with finalizer's type have been collected
+ * before calling this function. Otherwise, string data will be leaked by the
+ * GC, for want of a finalizer to call.
+ */
+extern JS_PUBLIC_API(intN)
+JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer);
+
+/*
+ * Create a new JSString whose chars member refers to external memory, i.e.,
+ * memory requiring special, type-specific finalization. The type code must
+ * be a nonnegative return value from JS_AddExternalStringFinalizer.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type);
+
+/*
+ * Returns the external-string finalizer index for this string, or -1 if it is
+ * an "internal" (native to JS engine) string.
+ */
+extern JS_PUBLIC_API(intN)
+JS_GetExternalStringGCType(JSRuntime *rt, JSString *str);
+
+/*
+ * Sets maximum (if stack grows upward) or minimum (downward) legal stack byte
+ * address in limitAddr for the thread or process stack used by cx. To disable
+ * stack size checking, pass 0 for limitAddr.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr);
+
+/*
+ * Set the quota on the number of bytes that stack-like data structures can
+ * use when the runtime compiles and executes scripts. These structures
+ * consume heap space, so JS_SetThreadStackLimit does not bound their size.
+ * The default quota is 32MB which is quite generous.
+ *
+ * The function must be called before any script compilation or execution API
+ * calls, i.e. either immediately after JS_NewContext or from JSCONTEXT_NEW
+ * context callback.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetScriptStackQuota(JSContext *cx, size_t quota);
+
+#define JS_DEFAULT_SCRIPT_STACK_QUOTA ((size_t) 0x2000000)
+
+/************************************************************************/
+
+/*
+ * Classes, objects, and properties.
+ */
+
+/* For detailed comments on the function pointer types, see jspubtd.h. */
+struct JSClass {
+ const char *name;
+ uint32 flags;
+
+ /* Mandatory non-null function pointer members. */
+ JSPropertyOp addProperty;
+ JSPropertyOp delProperty;
+ JSPropertyOp getProperty;
+ JSPropertyOp setProperty;
+ JSEnumerateOp enumerate;
+ JSResolveOp resolve;
+ JSConvertOp convert;
+ JSFinalizeOp finalize;
+
+ /* Optionally non-null members start here. */
+ JSGetObjectOps getObjectOps;
+ JSCheckAccessOp checkAccess;
+ JSNative call;
+ JSNative construct;
+ JSXDRObjectOp xdrObject;
+ JSHasInstanceOp hasInstance;
+ JSMarkOp mark;
+ JSReserveSlotsOp reserveSlots;
+};
+
+struct JSExtendedClass {
+ JSClass base;
+ JSEqualityOp equality;
+ JSObjectOp outerObject;
+ JSObjectOp innerObject;
+ JSIteratorOp iteratorObject;
+ JSObjectOp wrappedObject; /* NB: infallible, null
+ returns are treated as
+ the original object */
+ void (*reserved0)(void);
+ void (*reserved1)(void);
+ void (*reserved2)(void);
+};
+
+#define JSCLASS_HAS_PRIVATE (1<<0) /* objects have private slot */
+#define JSCLASS_NEW_ENUMERATE (1<<1) /* has JSNewEnumerateOp hook */
+#define JSCLASS_NEW_RESOLVE (1<<2) /* has JSNewResolveOp hook */
+#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) /* private is (nsISupports *) */
+#define JSCLASS_SHARE_ALL_PROPERTIES (1<<4) /* all properties are SHARED */
+#define JSCLASS_NEW_RESOLVE_GETS_START (1<<5) /* JSNewResolveOp gets starting
+ object in prototype chain
+ passed in via *objp in/out
+ parameter */
+#define JSCLASS_CONSTRUCT_PROTOTYPE (1<<6) /* call constructor on class
+ prototype */
+#define JSCLASS_DOCUMENT_OBSERVER (1<<7) /* DOM document observer */
+
+/*
+ * To reserve slots fetched and stored via JS_Get/SetReservedSlot, bitwise-or
+ * JSCLASS_HAS_RESERVED_SLOTS(n) into the initializer for JSClass.flags, where
+ * n is a constant in [1, 255]. Reserved slots are indexed from 0 to n-1.
+ */
+#define JSCLASS_RESERVED_SLOTS_SHIFT 8 /* room for 8 flags below */
+#define JSCLASS_RESERVED_SLOTS_WIDTH 8 /* and 16 above this field */
+#define JSCLASS_RESERVED_SLOTS_MASK JS_BITMASK(JSCLASS_RESERVED_SLOTS_WIDTH)
+#define JSCLASS_HAS_RESERVED_SLOTS(n) (((n) & JSCLASS_RESERVED_SLOTS_MASK) \
+ << JSCLASS_RESERVED_SLOTS_SHIFT)
+#define JSCLASS_RESERVED_SLOTS(clasp) (((clasp)->flags \
+ >> JSCLASS_RESERVED_SLOTS_SHIFT) \
+ & JSCLASS_RESERVED_SLOTS_MASK)
+
+#define JSCLASS_HIGH_FLAGS_SHIFT (JSCLASS_RESERVED_SLOTS_SHIFT + \
+ JSCLASS_RESERVED_SLOTS_WIDTH)
+
+/* True if JSClass is really a JSExtendedClass. */
+#define JSCLASS_IS_EXTENDED (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0))
+#define JSCLASS_IS_ANONYMOUS (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1))
+#define JSCLASS_IS_GLOBAL (1<<(JSCLASS_HIGH_FLAGS_SHIFT+2))
+
+/* Indicates that JSClass.mark is a tracer with JSTraceOp type. */
+#define JSCLASS_MARK_IS_TRACE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3))
+
+/*
+ * ECMA-262 requires that most constructors used internally create objects
+ * with "the original Foo.prototype value" as their [[Prototype]] (__proto__)
+ * member initial value. The "original ... value" verbiage is there because
+ * in ECMA-262, global properties naming class objects are read/write and
+ * deleteable, for the most part.
+ *
+ * Implementing this efficiently requires that global objects have classes
+ * with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS won't break
+ * anything except the ECMA-262 "original prototype value" behavior, which was
+ * broken for years in SpiderMonkey. In other words, without these flags you
+ * get backward compatibility.
+ */
+#define JSCLASS_GLOBAL_FLAGS \
+ (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSProto_LIMIT))
+
+/* Fast access to the original value of each standard class's prototype. */
+#define JSCLASS_CACHED_PROTO_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT + 8)
+#define JSCLASS_CACHED_PROTO_WIDTH 8
+#define JSCLASS_CACHED_PROTO_MASK JS_BITMASK(JSCLASS_CACHED_PROTO_WIDTH)
+#define JSCLASS_HAS_CACHED_PROTO(key) ((key) << JSCLASS_CACHED_PROTO_SHIFT)
+#define JSCLASS_CACHED_PROTO_KEY(clasp) ((JSProtoKey) \
+ (((clasp)->flags \
+ >> JSCLASS_CACHED_PROTO_SHIFT) \
+ & JSCLASS_CACHED_PROTO_MASK))
+
+/* Initializer for unused members of statically initialized JSClass structs. */
+#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,0
+#define JSCLASS_NO_RESERVED_MEMBERS 0,0,0
+
+/* For detailed comments on these function pointer types, see jspubtd.h. */
+struct JSObjectOps {
+ /* Mandatory non-null function pointer members. */
+ JSNewObjectMapOp newObjectMap;
+ JSObjectMapOp destroyObjectMap;
+ JSLookupPropOp lookupProperty;
+ JSDefinePropOp defineProperty;
+ JSPropertyIdOp getProperty;
+ JSPropertyIdOp setProperty;
+ JSAttributesOp getAttributes;
+ JSAttributesOp setAttributes;
+ JSPropertyIdOp deleteProperty;
+ JSConvertOp defaultValue;
+ JSNewEnumerateOp enumerate;
+ JSCheckAccessIdOp checkAccess;
+
+ /* Optionally non-null members start here. */
+ JSObjectOp thisObject;
+ JSPropertyRefOp dropProperty;
+ JSNative call;
+ JSNative construct;
+ JSXDRObjectOp xdrObject;
+ JSHasInstanceOp hasInstance;
+ JSSetObjectSlotOp setProto;
+ JSSetObjectSlotOp setParent;
+ JSTraceOp trace;
+ JSFinalizeOp clear;
+ JSGetRequiredSlotOp getRequiredSlot;
+ JSSetRequiredSlotOp setRequiredSlot;
+};
+
+struct JSXMLObjectOps {
+ JSObjectOps base;
+ JSGetMethodOp getMethod;
+ JSSetMethodOp setMethod;
+ JSEnumerateValuesOp enumerateValues;
+ JSEqualityOp equality;
+ JSConcatenateOp concatenate;
+};
+
+/*
+ * Classes that expose JSObjectOps via a non-null getObjectOps class hook may
+ * derive a property structure from this struct, return a pointer to it from
+ * lookupProperty and defineProperty, and use the pointer to avoid rehashing
+ * in getAttributes and setAttributes.
+ *
+ * The jsid type contains either an int jsval (see JSVAL_IS_INT above), or an
+ * internal pointer that is opaque to users of this API, but which users may
+ * convert from and to a jsval using JS_ValueToId and JS_IdToValue.
+ */
+struct JSProperty {
+ jsid id;
+};
+
+struct JSIdArray {
+ jsint length;
+ jsid vector[1]; /* actually, length jsid words */
+};
+
+extern JS_PUBLIC_API(void)
+JS_DestroyIdArray(JSContext *cx, JSIdArray *ida);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToId(JSContext *cx, jsval v, jsid *idp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IdToValue(JSContext *cx, jsid id, jsval *vp);
+
+/*
+ * The magic XML namespace id is int-tagged, but not a valid integer jsval.
+ * Global object classes in embeddings that enable JS_HAS_XML_SUPPORT (E4X)
+ * should handle this id specially before converting id via JSVAL_TO_INT.
+ */
+#define JS_DEFAULT_XML_NAMESPACE_ID ((jsid) JSVAL_VOID)
+
+/*
+ * JSNewResolveOp flag bits.
+ */
+#define JSRESOLVE_QUALIFIED 0x01 /* resolve a qualified property id */
+#define JSRESOLVE_ASSIGNING 0x02 /* resolve on the left of assignment */
+#define JSRESOLVE_DETECTING 0x04 /* 'if (o.p)...' or '(o.p) ?...:...' */
+#define JSRESOLVE_DECLARING 0x08 /* var, const, or function prolog op */
+#define JSRESOLVE_CLASSNAME 0x10 /* class name used when constructing */
+
+extern JS_PUBLIC_API(JSBool)
+JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EnumerateStub(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+
+extern JS_PUBLIC_API(void)
+JS_FinalizeStub(JSContext *cx, JSObject *obj);
+
+struct JSConstDoubleSpec {
+ jsdouble dval;
+ const char *name;
+ uint8 flags;
+ uint8 spare[3];
+};
+
+/*
+ * To define an array element rather than a named property member, cast the
+ * element's index to (const char *) and initialize name with it, and set the
+ * JSPROP_INDEX bit in flags.
+ */
+struct JSPropertySpec {
+ const char *name;
+ int8 tinyid;
+ uint8 flags;
+ JSPropertyOp getter;
+ JSPropertyOp setter;
+};
+
+struct JSFunctionSpec {
+ const char *name;
+ JSNative call;
+ uint16 nargs;
+ uint16 flags;
+
+ /*
+ * extra & 0xFFFF: Number of extra argument slots for local GC roots.
+ * If fast native, must be zero.
+ * extra >> 16: Reserved for future use (must be 0).
+ */
+ uint32 extra;
+};
+
+/*
+ * Terminating sentinel initializer to put at the end of a JSFunctionSpec array
+ * that's passed to JS_DefineFunctions or JS_InitClass.
+ */
+#define JS_FS_END JS_FS(NULL,NULL,0,0,0)
+
+/*
+ * Initializer macro for a JSFunctionSpec array element. This is the original
+ * kind of native function specifier initializer. Use JS_FN ("fast native", see
+ * JSFastNative in jspubtd.h) for all functions that do not need a stack frame
+ * when activated.
+ */
+#define JS_FS(name,call,nargs,flags,extra) \
+ {name, call, nargs, flags, extra}
+
+/*
+ * "Fast native" initializer macro for a JSFunctionSpec array element. Use this
+ * in preference to JS_FS if the native in question does not need its own stack
+ * frame when activated.
+ */
+#define JS_FN(name,fastcall,nargs,flags) \
+ {name, (JSNative)(fastcall), nargs, \
+ (flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS, 0}
+
+extern JS_PUBLIC_API(JSObject *)
+JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
+ JSClass *clasp, JSNative constructor, uintN nargs,
+ JSPropertySpec *ps, JSFunctionSpec *fs,
+ JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
+
+#ifdef JS_THREADSAFE
+extern JS_PUBLIC_API(JSClass *)
+JS_GetClass(JSContext *cx, JSObject *obj);
+
+#define JS_GET_CLASS(cx,obj) JS_GetClass(cx, obj)
+#else
+extern JS_PUBLIC_API(JSClass *)
+JS_GetClass(JSObject *obj);
+
+#define JS_GET_CLASS(cx,obj) JS_GetClass(obj)
+#endif
+
+extern JS_PUBLIC_API(JSBool)
+JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+extern JS_PUBLIC_API(void *)
+JS_GetPrivate(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetPrivate(JSContext *cx, JSObject *obj, void *data);
+
+extern JS_PUBLIC_API(void *)
+JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
+ jsval *argv);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetPrototype(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetParent(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetConstructor(JSContext *cx, JSObject *proto);
+
+/*
+ * Get a unique identifier for obj, good for the lifetime of obj (even if it
+ * is moved by a copying GC). Return false on failure (likely out of memory),
+ * and true with *idp containing the unique id on success.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
+
+/*
+ * Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default
+ * proto if proto's actual parameter value is null.
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN argc, jsval *argv);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
+ JSObject *proto, uintN attrs);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
+
+/*
+ * Determine the attributes (JSPROP_* flags) of a property on a given object.
+ *
+ * If the object does not have a property by that name, *foundp will be
+ * JS_FALSE and the value of *attrsp is undefined.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+ uintN *attrsp, JSBool *foundp);
+
+/*
+ * The same, but if the property is native, return its getter and setter via
+ * *getterp and *setterp, respectively (and only if the out parameter pointer
+ * is not null).
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+ const char *name,
+ uintN *attrsp, JSBool *foundp,
+ JSPropertyOp *getterp,
+ JSPropertyOp *setterp);
+
+/*
+ * Set the attributes of a property on a given object.
+ *
+ * If the object does not have a property by that name, *foundp will be
+ * JS_FALSE and nothing will be altered.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+ uintN attrs, JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
+ int8 tinyid, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
+ const char *alias);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, const char *name,
+ JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj, jsid id,
+ JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
+ uintN flags, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj, jsid id,
+ uintN flags, JSObject **objp, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
+ jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeletePropertyById(JSContext *cx, JSObject *obj, jsid id);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs);
+
+/*
+ * Determine the attributes (JSPROP_* flags) of a property on a given object.
+ *
+ * If the object does not have a property by that name, *foundp will be
+ * JS_FALSE and the value of *attrsp is undefined.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN *attrsp, JSBool *foundp);
+
+/*
+ * The same, but if the property is native, return its getter and setter via
+ * *getterp and *setterp, respectively (and only if the out parameter pointer
+ * is not null).
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN *attrsp, JSBool *foundp,
+ JSPropertyOp *getterp,
+ JSPropertyOp *setterp);
+
+/*
+ * Set the attributes of a property on a given object.
+ *
+ * If the object does not have a property by that name, *foundp will be
+ * JS_FALSE and nothing will be altered.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN attrs, JSBool *foundp);
+
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ int8 tinyid, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *obj, const jschar *name,
+ size_t namelen, JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ JSBool *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeleteUCProperty2(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsArrayObject(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, jsint index,
+ JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval);
+
+extern JS_PUBLIC_API(void)
+JS_ClearScope(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSIdArray *)
+JS_Enumerate(JSContext *cx, JSObject *obj);
+
+/*
+ * Create an object to iterate over enumerable properties of obj, in arbitrary
+ * property definition order. NB: This differs from longstanding for..in loop
+ * order, which uses order of property definition in obj.
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_NewPropertyIterator(JSContext *cx, JSObject *obj);
+
+/*
+ * Return true on success with *idp containing the id of the next enumerable
+ * property to visit using iterobj, or JSVAL_VOID if there is no such property
+ * left to visit. Return false on error.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v);
+
+/************************************************************************/
+
+/*
+ * Security protocol.
+ */
+struct JSPrincipals {
+ char *codebase;
+
+ /* XXX unspecified and unused by Mozilla code -- can we remove these? */
+ void * (* getPrincipalArray)(JSContext *cx, JSPrincipals *);
+ JSBool (* globalPrivilegesEnabled)(JSContext *cx, JSPrincipals *);
+
+ /* Don't call "destroy"; use reference counting macros below. */
+ jsrefcount refcount;
+
+ void (* destroy)(JSContext *cx, JSPrincipals *);
+ JSBool (* subsume)(JSPrincipals *, JSPrincipals *);
+};
+
+#ifdef JS_THREADSAFE
+#define JSPRINCIPALS_HOLD(cx, principals) JS_HoldPrincipals(cx,principals)
+#define JSPRINCIPALS_DROP(cx, principals) JS_DropPrincipals(cx,principals)
+
+extern JS_PUBLIC_API(jsrefcount)
+JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals);
+
+extern JS_PUBLIC_API(jsrefcount)
+JS_DropPrincipals(JSContext *cx, JSPrincipals *principals);
+
+#else
+#define JSPRINCIPALS_HOLD(cx, principals) (++(principals)->refcount)
+#define JSPRINCIPALS_DROP(cx, principals) \
+ ((--(principals)->refcount == 0) \
+ ? ((*(principals)->destroy)((cx), (principals)), 0) \
+ : (principals)->refcount)
+#endif
+
+
+struct JSSecurityCallbacks {
+ JSCheckAccessOp checkObjectAccess;
+ JSPrincipalsTranscoder principalsTranscoder;
+ JSObjectPrincipalsFinder findObjectPrincipals;
+};
+
+extern JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_SetRuntimeSecurityCallbacks(JSRuntime *rt, JSSecurityCallbacks *callbacks);
+
+extern JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_GetRuntimeSecurityCallbacks(JSRuntime *rt);
+
+extern JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks);
+
+extern JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_GetSecurityCallbacks(JSContext *cx);
+
+/************************************************************************/
+
+/*
+ * Functions and scripts.
+ */
+extern JS_PUBLIC_API(JSFunction *)
+JS_NewFunction(JSContext *cx, JSNative call, uintN nargs, uintN flags,
+ JSObject *parent, const char *name);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFunctionObject(JSFunction *fun);
+
+/*
+ * Deprecated, useful only for diagnostics. Use JS_GetFunctionId instead for
+ * anonymous vs. "anonymous" disambiguation and Unicode fidelity.
+ */
+extern JS_PUBLIC_API(const char *)
+JS_GetFunctionName(JSFunction *fun);
+
+/*
+ * Return the function's identifier as a JSString, or null if fun is unnamed.
+ * The returned string lives as long as fun, so you don't need to root a saved
+ * reference to it if fun is well-connected or rooted, and provided you bound
+ * the use of the saved reference by fun's lifetime.
+ *
+ * Prefer JS_GetFunctionId over JS_GetFunctionName because it returns null for
+ * truly anonymous functions, and because it doesn't chop to ISO-Latin-1 chars
+ * from UTF-16-ish jschars.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_GetFunctionId(JSFunction *fun);
+
+/*
+ * Return JSFUN_* flags for fun.
+ */
+extern JS_PUBLIC_API(uintN)
+JS_GetFunctionFlags(JSFunction *fun);
+
+/*
+ * Return the arity (length) of fun.
+ */
+extern JS_PUBLIC_API(uint16)
+JS_GetFunctionArity(JSFunction *fun);
+
+/*
+ * Infallible predicate to test whether obj is a function object (faster than
+ * comparing obj's class name to "Function", but equivalent unless someone has
+ * overwritten the "Function" identifier with a different constructor and then
+ * created instances using that constructor that might be passed in as obj).
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ObjectIsFunction(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
+ uintN nargs, uintN attrs);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_DefineUCFunction(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, JSNative call,
+ uintN nargs, uintN attrs);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
+
+/*
+ * Given a buffer, return JS_FALSE if the buffer might become a valid
+ * javascript statement with the addition of more lines. Otherwise return
+ * JS_TRUE. The intent is to support interactive compilation - accumulate
+ * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
+ * the compiler.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
+ const char *bytes, size_t length);
+
+/*
+ * The JSScript objects returned by the following functions refer to string and
+ * other kinds of literals, including doubles and RegExp objects. These
+ * literals are vulnerable to garbage collection; to root script objects and
+ * prevent literals from being collected, create a rootable object using
+ * JS_NewScriptObject, and root the resulting object using JS_Add[Named]Root.
+ */
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileScript(JSContext *cx, JSObject *obj,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileUCScript(JSContext *cx, JSObject *obj,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
+ FILE *fh);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
+ const char *filename, FILE *fh,
+ JSPrincipals *principals);
+
+/*
+ * NB: you must use JS_NewScriptObject and root a pointer to its return value
+ * in order to keep a JSScript and its atoms safe from garbage collection after
+ * creating the script via JS_Compile* and before a JS_ExecuteScript* call.
+ * E.g., and without error checks:
+ *
+ * JSScript *script = JS_CompileFile(cx, global, filename);
+ * JSObject *scrobj = JS_NewScriptObject(cx, script);
+ * JS_AddNamedRoot(cx, &scrobj, "scrobj");
+ * do {
+ * jsval result;
+ * JS_ExecuteScript(cx, global, script, &result);
+ * JS_GC();
+ * } while (!JSVAL_IS_BOOLEAN(result) || JSVAL_TO_BOOLEAN(result));
+ * JS_RemoveRoot(cx, &scrobj);
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_NewScriptObject(JSContext *cx, JSScript *script);
+
+/*
+ * Infallible getter for a script's object. If JS_NewScriptObject has not been
+ * called on script yet, the return value will be null.
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_GetScriptObject(JSScript *script);
+
+extern JS_PUBLIC_API(void)
+JS_DestroyScript(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
+ uintN nargs, const char **argnames,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals, const char *name,
+ uintN nargs, const char **argnames,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
+ uintN nargs, const char **argnames,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals, const char *name,
+ uintN nargs, const char **argnames,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSString *)
+JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
+ uintN indent);
+
+/*
+ * API extension: OR this into indent to avoid pretty-printing the decompiled
+ * source resulting from JS_DecompileFunction{,Body}.
+ */
+#define JS_DONT_PRETTY_PRINT ((uintN)0x8000)
+
+extern JS_PUBLIC_API(JSString *)
+JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent);
+
+extern JS_PUBLIC_API(JSString *)
+JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent);
+
+/*
+ * NB: JS_ExecuteScript, JS_ExecuteScriptPart, and the JS_Evaluate*Script*
+ * quadruplets all use the obj parameter as the initial scope chain header,
+ * the 'this' keyword value, and the variables object (ECMA parlance for where
+ * 'var' and 'function' bind names) of the execution context for script.
+ *
+ * Using obj as the variables object is problematic if obj's parent (which is
+ * the scope chain link; see JS_SetParent and JS_NewObject) is not null: in
+ * this case, variables created by 'var x = 0', e.g., go in obj, but variables
+ * created by assignment to an unbound id, 'x = 0', go in the last object on
+ * the scope chain linked by parent.
+ *
+ * ECMA calls that last scoping object the "global object", but note that many
+ * embeddings have several such objects. ECMA requires that "global code" be
+ * executed with the variables object equal to this global object. But these
+ * JS API entry points provide freedom to execute code against a "sub-global",
+ * i.e., a parented or scoped object, in which case the variables object will
+ * differ from the last object on the scope chain, resulting in confusing and
+ * non-ECMA explicit vs. implicit variable creation.
+ *
+ * Caveat embedders: unless you already depend on this buggy variables object
+ * binding behavior, you should call JS_SetOptions(cx, JSOPTION_VAROBJFIX) or
+ * JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_VAROBJFIX) -- the latter if
+ * someone may have set other options on cx already -- for each context in the
+ * application, if you pass parented objects as the obj parameter, or may ever
+ * pass such objects in the future.
+ *
+ * Why a runtime option? The alternative is to add six or so new API entry
+ * points with signatures matching the following six, and that doesn't seem
+ * worth the code bloat cost. Such new entry points would probably have less
+ * obvious names, too, so would not tend to be used. The JS_SetOption call,
+ * OTOH, can be more easily hacked into existing code that does not depend on
+ * the bug; such code can continue to use the familiar JS_EvaluateScript,
+ * etc., entry points.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval);
+
+/*
+ * Execute either the function-defining prolog of a script, or the script's
+ * main body, but not both.
+ */
+typedef enum JSExecPart { JSEXEC_PROLOG, JSEXEC_MAIN } JSExecPart;
+
+extern JS_PUBLIC_API(JSBool)
+JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script,
+ JSExecPart part, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateScript(JSContext *cx, JSObject *obj,
+ const char *bytes, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const char *bytes, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
+ jsval *argv, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
+ jsval *argv, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
+ jsval *argv, jsval *rval);
+
+/*
+ * The maximum value of the operation limit to pass to JS_SetOperationCallback
+ * and JS_SetOperationLimit.
+ */
+#define JS_MAX_OPERATION_LIMIT ((uint32) 0x7FFFFFFF)
+
+#define JS_OPERATION_WEIGHT_BASE 4096
+
+/*
+ * Set the operation callback that the engine calls periodically after
+ * the internal operation count reaches the specified limit.
+ *
+ * When operationLimit is JS_OPERATION_WEIGHT_BASE, the callback will be
+ * called at least after each backward jump in the interpreter. To minimize
+ * the overhead of the callback invocation we suggest at least
+ *
+ * 100 * JS_OPERATION_WEIGHT_BASE
+ *
+ * as a value for operationLimit.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback,
+ uint32 operationLimit);
+
+extern JS_PUBLIC_API(void)
+JS_ClearOperationCallback(JSContext *cx);
+
+extern JS_PUBLIC_API(JSOperationCallback)
+JS_GetOperationCallback(JSContext *cx);
+
+/*
+ * Get the operation limit associated with the operation callback. This API
+ * function may be called only when the result of JS_GetOperationCallback(cx)
+ * is not null.
+ */
+extern JS_PUBLIC_API(uint32)
+JS_GetOperationLimit(JSContext *cx);
+
+/*
+ * Change the operation limit associated with the operation callback. This API
+ * function may be called only when the result of JS_GetOperationCallback(cx)
+ * is not null.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetOperationLimit(JSContext *cx, uint32 operationLimit);
+
+/*
+ * Note well: JS_SetBranchCallback is deprecated. It is similar to
+ *
+ * JS_SetOperationCallback(cx, callback, 4096, NULL);
+ *
+ * except that the callback will not be called from a long-running native
+ * function when JSOPTION_NATIVE_BRANCH_CALLBACK is not set and the top-most
+ * frame is native.
+ */
+extern JS_PUBLIC_API(JSBranchCallback)
+JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsRunning(JSContext *cx);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsConstructing(JSContext *cx);
+
+/*
+ * Returns true if a script is executing and its current bytecode is a set
+ * (assignment) operation, even if there are native (no script) stack frames
+ * between the script and the caller to JS_IsAssigning.
+ */
+extern JS_FRIEND_API(JSBool)
+JS_IsAssigning(JSContext *cx);
+
+/*
+ * Set the second return value, which should be a string or int jsval that
+ * identifies a property in the returned object, to form an ECMA reference
+ * type value (obj, id). Only native methods can return reference types,
+ * and if the returned value is used on the left-hand side of an assignment
+ * op, the identified property will be set. If the return value is in an
+ * r-value, the interpreter just gets obj[id]'s value.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetCallReturnValue2(JSContext *cx, jsval v);
+
+/*
+ * Saving and restoring frame chains.
+ *
+ * These two functions are used to set aside cx's call stack while that stack
+ * is inactive. After a call to JS_SaveFrameChain, it looks as if there is no
+ * code running on cx. Before calling JS_RestoreFrameChain, cx's call stack
+ * must be balanced and all nested calls to JS_SaveFrameChain must have had
+ * matching JS_RestoreFrameChain calls.
+ *
+ * JS_SaveFrameChain deals with cx not having any code running on it. A null
+ * return does not signify an error, and JS_RestoreFrameChain handles a null
+ * frame pointer argument safely.
+ */
+extern JS_PUBLIC_API(JSStackFrame *)
+JS_SaveFrameChain(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp);
+
+/************************************************************************/
+
+/*
+ * Strings.
+ *
+ * NB: JS_NewString takes ownership of bytes on success, avoiding a copy; but
+ * on error (signified by null return), it leaves bytes owned by the caller.
+ * So the caller must free bytes in the error case, if it has no use for them.
+ * In contrast, all the JS_New*StringCopy* functions do not take ownership of
+ * the character memory passed to them -- they copy it.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_NewString(JSContext *cx, char *bytes, size_t length);
+
+extern JS_PUBLIC_API(JSString *)
+JS_NewStringCopyN(JSContext *cx, const char *s, size_t n);
+
+extern JS_PUBLIC_API(JSString *)
+JS_NewStringCopyZ(JSContext *cx, const char *s);
+
+extern JS_PUBLIC_API(JSString *)
+JS_InternString(JSContext *cx, const char *s);
+
+extern JS_PUBLIC_API(JSString *)
+JS_NewUCString(JSContext *cx, jschar *chars, size_t length);
+
+extern JS_PUBLIC_API(JSString *)
+JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n);
+
+extern JS_PUBLIC_API(JSString *)
+JS_NewUCStringCopyZ(JSContext *cx, const jschar *s);
+
+extern JS_PUBLIC_API(JSString *)
+JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length);
+
+extern JS_PUBLIC_API(JSString *)
+JS_InternUCString(JSContext *cx, const jschar *s);
+
+extern JS_PUBLIC_API(char *)
+JS_GetStringBytes(JSString *str);
+
+extern JS_PUBLIC_API(jschar *)
+JS_GetStringChars(JSString *str);
+
+extern JS_PUBLIC_API(size_t)
+JS_GetStringLength(JSString *str);
+
+extern JS_PUBLIC_API(intN)
+JS_CompareStrings(JSString *str1, JSString *str2);
+
+/*
+ * Mutable string support. A string's characters are never mutable in this JS
+ * implementation, but a growable string has a buffer that can be reallocated,
+ * and a dependent string is a substring of another (growable, dependent, or
+ * immutable) string. The direct data members of the (opaque to API clients)
+ * JSString struct may be changed in a single-threaded way for growable and
+ * dependent strings.
+ *
+ * Therefore mutable strings cannot be used by more than one thread at a time.
+ * You may call JS_MakeStringImmutable to convert the string from a mutable
+ * (growable or dependent) string to an immutable (and therefore thread-safe)
+ * string. The engine takes care of converting growable and dependent strings
+ * to immutable for you if you store strings in multi-threaded objects using
+ * JS_SetProperty or kindred API entry points.
+ *
+ * If you store a JSString pointer in a native data structure that is (safely)
+ * accessible to multiple threads, you must call JS_MakeStringImmutable before
+ * retiring the store.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length);
+
+/*
+ * Create a dependent string, i.e., a string that owns no character storage,
+ * but that refers to a slice of another string's chars. Dependent strings
+ * are mutable by definition, so the thread safety comments above apply.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_NewDependentString(JSContext *cx, JSString *str, size_t start,
+ size_t length);
+
+/*
+ * Concatenate two strings, resulting in a new growable string. If you create
+ * the left string and pass it to JS_ConcatStrings on a single thread, try to
+ * use JS_NewGrowableString to create the left string -- doing so helps Concat
+ * avoid allocating a new buffer for the result and copying left's chars into
+ * the new buffer. See above for thread safety comments.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right);
+
+/*
+ * Convert a dependent string into an independent one. This function does not
+ * change the string's mutability, so the thread safety comments above apply.
+ */
+extern JS_PUBLIC_API(const jschar *)
+JS_UndependString(JSContext *cx, JSString *str);
+
+/*
+ * Convert a mutable string (either growable or dependent) into an immutable,
+ * thread-safe one.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_MakeStringImmutable(JSContext *cx, JSString *str);
+
+/*
+ * Return JS_TRUE if C (char []) strings passed via the API and internally
+ * are UTF-8.
+ */
+JS_PUBLIC_API(JSBool)
+JS_CStringsAreUTF8(void);
+
+/*
+ * Update the value to be returned by JS_CStringsAreUTF8(). Once set, it
+ * can never be changed. This API must be called before the first call to
+ * JS_NewRuntime.
+ */
+JS_PUBLIC_API(void)
+JS_SetCStringsAreUTF8(void);
+
+/*
+ * Character encoding support.
+ *
+ * For both JS_EncodeCharacters and JS_DecodeBytes, set *dstlenp to the size
+ * of the destination buffer before the call; on return, *dstlenp contains the
+ * number of bytes (JS_EncodeCharacters) or jschars (JS_DecodeBytes) actually
+ * stored. To determine the necessary destination buffer size, make a sizing
+ * call that passes NULL for dst.
+ *
+ * On errors, the functions report the error. In that case, *dstlenp contains
+ * the number of characters or bytes transferred so far. If cx is NULL, no
+ * error is reported on failure, and the functions simply return JS_FALSE.
+ *
+ * NB: Neither function stores an additional zero byte or jschar after the
+ * transcoded string.
+ *
+ * If JS_CStringsAreUTF8() is true then JS_EncodeCharacters encodes to
+ * UTF-8, and JS_DecodeBytes decodes from UTF-8, which may create additional
+ * errors if the character sequence is malformed. If UTF-8 support is
+ * disabled, the functions deflate and inflate, respectively.
+ */
+JS_PUBLIC_API(JSBool)
+JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst,
+ size_t *dstlenp);
+
+JS_PUBLIC_API(JSBool)
+JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst,
+ size_t *dstlenp);
+
+/*
+ * A variation on JS_EncodeCharacters where a null terminated string is
+ * returned that you are expected to call JS_free on when done.
+ */
+JS_PUBLIC_API(char *)
+JS_EncodeString(JSContext *cx, JSString *str);
+
+/************************************************************************/
+/*
+ * JSON functions
+ */
+typedef JSBool (* JSONWriteCallback)(const jschar *buf, uint32 len, void *data);
+
+/*
+ * JSON.stringify as specificed by ES3.1 (draft)
+ */
+JS_PUBLIC_API(JSBool)
+JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer,
+ JSONWriteCallback callback, void *data);
+
+/*
+ * Retrieve a toJSON function. If found, set vp to its result.
+ */
+JS_PUBLIC_API(JSBool)
+JS_TryJSON(JSContext *cx, jsval *vp);
+
+/*
+ * JSON.parse as specificed by ES3.1 (draft)
+ */
+JS_PUBLIC_API(JSONParser *)
+JS_BeginJSONParse(JSContext *cx, jsval *vp);
+
+JS_PUBLIC_API(JSBool)
+JS_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len);
+
+JS_PUBLIC_API(JSBool)
+JS_FinishJSONParse(JSContext *cx, JSONParser *jp);
+
+/************************************************************************/
+
+/*
+ * Locale specific string conversion and error message callbacks.
+ */
+struct JSLocaleCallbacks {
+ JSLocaleToUpperCase localeToUpperCase;
+ JSLocaleToLowerCase localeToLowerCase;
+ JSLocaleCompare localeCompare;
+ JSLocaleToUnicode localeToUnicode;
+ JSErrorCallback localeGetErrorMessage;
+};
+
+/*
+ * Establish locale callbacks. The pointer must persist as long as the
+ * JSContext. Passing NULL restores the default behaviour.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks);
+
+/*
+ * Return the address of the current locale callbacks struct, which may
+ * be NULL.
+ */
+extern JS_PUBLIC_API(JSLocaleCallbacks *)
+JS_GetLocaleCallbacks(JSContext *cx);
+
+/************************************************************************/
+
+/*
+ * Error reporting.
+ */
+
+/*
+ * Report an exception represented by the sprintf-like conversion of format
+ * and its arguments. This exception message string is passed to a pre-set
+ * JSErrorReporter function (set by JS_SetErrorReporter; see jspubtd.h for
+ * the JSErrorReporter typedef).
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportError(JSContext *cx, const char *format, ...);
+
+/*
+ * Use an errorNumber to retrieve the format string, args are char *
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
+ void *userRef, const uintN errorNumber, ...);
+
+/*
+ * Use an errorNumber to retrieve the format string, args are jschar *
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
+ void *userRef, const uintN errorNumber, ...);
+
+/*
+ * As above, but report a warning instead (JSREPORT_IS_WARNING(report.flags)).
+ * Return true if there was no error trying to issue the warning, and if the
+ * warning was not converted into an error due to the JSOPTION_WERROR option
+ * being set, false otherwise.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ReportWarning(JSContext *cx, const char *format, ...);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
+ JSErrorCallback errorCallback, void *userRef,
+ const uintN errorNumber, ...);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
+ JSErrorCallback errorCallback, void *userRef,
+ const uintN errorNumber, ...);
+
+/*
+ * Complain when out of memory.
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportOutOfMemory(JSContext *cx);
+
+/*
+ * Complain when an allocation size overflows the maximum supported limit.
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportAllocationOverflow(JSContext *cx);
+
+struct JSErrorReport {
+ const char *filename; /* source file name, URL, etc., or null */
+ uintN lineno; /* source line number */
+ const char *linebuf; /* offending source line without final \n */
+ const char *tokenptr; /* pointer to error token in linebuf */
+ const jschar *uclinebuf; /* unicode (original) line buffer */
+ const jschar *uctokenptr; /* unicode (original) token pointer */
+ uintN flags; /* error/warning, etc. */
+ uintN errorNumber; /* the error number, e.g. see js.msg */
+ const jschar *ucmessage; /* the (default) error message */
+ const jschar **messageArgs; /* arguments for the error message */
+};
+
+/*
+ * JSErrorReport flag values. These may be freely composed.
+ */
+#define JSREPORT_ERROR 0x0 /* pseudo-flag for default case */
+#define JSREPORT_WARNING 0x1 /* reported via JS_ReportWarning */
+#define JSREPORT_EXCEPTION 0x2 /* exception was thrown */
+#define JSREPORT_STRICT 0x4 /* error or warning due to strict option */
+
+/*
+ * If JSREPORT_EXCEPTION is set, then a JavaScript-catchable exception
+ * has been thrown for this runtime error, and the host should ignore it.
+ * Exception-aware hosts should also check for JS_IsExceptionPending if
+ * JS_ExecuteScript returns failure, and signal or propagate the exception, as
+ * appropriate.
+ */
+#define JSREPORT_IS_WARNING(flags) (((flags) & JSREPORT_WARNING) != 0)
+#define JSREPORT_IS_EXCEPTION(flags) (((flags) & JSREPORT_EXCEPTION) != 0)
+#define JSREPORT_IS_STRICT(flags) (((flags) & JSREPORT_STRICT) != 0)
+
+extern JS_PUBLIC_API(JSErrorReporter)
+JS_SetErrorReporter(JSContext *cx, JSErrorReporter er);
+
+/************************************************************************/
+
+/*
+ * Regular Expressions.
+ */
+#define JSREG_FOLD 0x01 /* fold uppercase to lowercase */
+#define JSREG_GLOB 0x02 /* global exec, creates array of matches */
+#define JSREG_MULTILINE 0x04 /* treat ^ and $ as begin and end of line */
+#define JSREG_STICKY 0x08 /* only match starting at lastIndex */
+
+extern JS_PUBLIC_API(JSObject *)
+JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags);
+
+extern JS_PUBLIC_API(void)
+JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline);
+
+extern JS_PUBLIC_API(void)
+JS_ClearRegExpStatics(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_ClearRegExpRoots(JSContext *cx);
+
+/* TODO: compile, exec, get/set other statics... */
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsExceptionPending(JSContext *cx);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetPendingException(JSContext *cx, jsval *vp);
+
+extern JS_PUBLIC_API(void)
+JS_SetPendingException(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(void)
+JS_ClearPendingException(JSContext *cx);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ReportPendingException(JSContext *cx);
+
+/*
+ * Save the current exception state. This takes a snapshot of cx's current
+ * exception state without making any change to that state.
+ *
+ * The returned state pointer MUST be passed later to JS_RestoreExceptionState
+ * (to restore that saved state, overriding any more recent state) or else to
+ * JS_DropExceptionState (to free the state struct in case it is not correct
+ * or desirable to restore it). Both Restore and Drop free the state struct,
+ * so callers must stop using the pointer returned from Save after calling the
+ * Release or Drop API.
+ */
+extern JS_PUBLIC_API(JSExceptionState *)
+JS_SaveExceptionState(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state);
+
+extern JS_PUBLIC_API(void)
+JS_DropExceptionState(JSContext *cx, JSExceptionState *state);
+
+/*
+ * If the given value is an exception object that originated from an error,
+ * the exception will contain an error report struct, and this API will return
+ * the address of that struct. Otherwise, it returns NULL. The lifetime of
+ * the error report struct that might be returned is the same as the lifetime
+ * of the exception object.
+ */
+extern JS_PUBLIC_API(JSErrorReport *)
+JS_ErrorFromException(JSContext *cx, jsval v);
+
+/*
+ * Given a reported error's message and JSErrorReport struct pointer, throw
+ * the corresponding exception on cx.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ThrowReportedError(JSContext *cx, const char *message,
+ JSErrorReport *reportp);
+
+/*
+ * Throws a StopIteration exception on cx.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ThrowStopIteration(JSContext *cx);
+
+/*
+ * Associate the current thread with the given context. This is done
+ * implicitly by JS_NewContext.
+ *
+ * Returns the old thread id for this context, which should be treated as
+ * an opaque value. This value is provided for comparison to 0, which
+ * indicates that ClearContextThread has been called on this context
+ * since the last SetContextThread, or non-0, which indicates the opposite.
+ */
+extern JS_PUBLIC_API(jsword)
+JS_GetContextThread(JSContext *cx);
+
+extern JS_PUBLIC_API(jsword)
+JS_SetContextThread(JSContext *cx);
+
+extern JS_PUBLIC_API(jsword)
+JS_ClearContextThread(JSContext *cx);
+
+/************************************************************************/
+
+#ifdef DEBUG
+#define JS_GC_ZEAL 1
+#endif
+
+#ifdef JS_GC_ZEAL
+extern JS_PUBLIC_API(void)
+JS_SetGCZeal(JSContext *cx, uint8 zeal);
+#endif
+
+JS_END_EXTERN_C
+
+#endif /* jsapi_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsarena.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsarena.cpp
new file mode 100644
index 0000000..f632552
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsarena.cpp
@@ -0,0 +1,450 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Lifetime-based fast allocation, inspired by much prior art, including
+ * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+ * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+
+#ifdef JS_ARENAMETER
+static JSArenaStats *arena_stats_list;
+
+#define COUNT(pool,what) (pool)->stats.what++
+#else
+#define COUNT(pool,what) /* nothing */
+#endif
+
+#define JS_ARENA_DEFAULT_ALIGN sizeof(double)
+
+JS_PUBLIC_API(void)
+JS_INIT_NAMED_ARENA_POOL(JSArenaPool *pool, const char *name, size_t size,
+ size_t align, size_t *quotap)
+{
+ if (align == 0)
+ align = JS_ARENA_DEFAULT_ALIGN;
+ pool->mask = JS_BITMASK(JS_CeilingLog2(align));
+ pool->first.next = NULL;
+ pool->first.base = pool->first.avail = pool->first.limit =
+ JS_ARENA_ALIGN(pool, &pool->first + 1);
+ pool->current = &pool->first;
+ pool->arenasize = size;
+ pool->quotap = quotap;
+#ifdef JS_ARENAMETER
+ memset(&pool->stats, 0, sizeof pool->stats);
+ pool->stats.name = strdup(name);
+ pool->stats.next = arena_stats_list;
+ arena_stats_list = &pool->stats;
+#endif
+}
+
+/*
+ * An allocation that consumes more than pool->arenasize also has a header
+ * pointing back to its previous arena's next member. This header is not
+ * included in [a->base, a->limit), so its space can't be wrongly claimed.
+ *
+ * As the header is a pointer, it must be well-aligned. If pool->mask is
+ * greater than or equal to POINTER_MASK, the header just preceding a->base
+ * for an oversized arena a is well-aligned, because a->base is well-aligned.
+ * However, we may need to add more space to pad the JSArena ** back-pointer
+ * so that it lies just behind a->base, because a might not be aligned such
+ * that (jsuword)(a + 1) is on a pointer boundary.
+ *
+ * By how much must we pad? Let M be the alignment modulus for pool and P
+ * the modulus for a pointer. Given M >= P, the base of an oversized arena
+ * that satisfies M is well-aligned for P.
+ *
+ * On the other hand, if M < P, we must include enough space in the header
+ * size to align the back-pointer on a P boundary so that it can be found by
+ * subtracting P from a->base. This means a->base must be on a P boundary,
+ * even though subsequent allocations from a may be aligned on a lesser (M)
+ * boundary. Given powers of two M and P as above, the extra space needed
+ * when M < P is P-M or POINTER_MASK - pool->mask.
+ *
+ * The size of a header including padding is given by the HEADER_SIZE macro,
+ * below, for any pool (for any value of M).
+ *
+ * The mask to align a->base for any pool is (pool->mask | POINTER_MASK), or
+ * HEADER_BASE_MASK(pool).
+ *
+ * PTR_TO_HEADER computes the address of the back-pointer, given an oversized
+ * allocation at p. By definition, p must be a->base for the arena a that
+ * contains p. GET_HEADER and SET_HEADER operate on an oversized arena a, in
+ * the case of SET_HEADER with back-pointer ap.
+ */
+#define POINTER_MASK ((jsuword)(JS_ALIGN_OF_POINTER - 1))
+#define HEADER_SIZE(pool) (sizeof(JSArena **) \
+ + (((pool)->mask < POINTER_MASK) \
+ ? POINTER_MASK - (pool)->mask \
+ : 0))
+#define HEADER_BASE_MASK(pool) ((pool)->mask | POINTER_MASK)
+#define PTR_TO_HEADER(pool,p) (JS_ASSERT(((jsuword)(p) \
+ & HEADER_BASE_MASK(pool)) \
+ == 0), \
+ (JSArena ***)(p) - 1)
+#define GET_HEADER(pool,a) (*PTR_TO_HEADER(pool, (a)->base))
+#define SET_HEADER(pool,a,ap) (*PTR_TO_HEADER(pool, (a)->base) = (ap))
+
+JS_PUBLIC_API(void *)
+JS_ArenaAllocate(JSArenaPool *pool, size_t nb)
+{
+ JSArena **ap, *a, *b;
+ jsuword extra, hdrsz, gross;
+ void *p;
+
+ /*
+ * Search pool from current forward till we find or make enough space.
+ *
+ * NB: subtract nb from a->limit in the loop condition, instead of adding
+ * nb to a->avail, to avoid overflowing a 32-bit address space (possible
+ * when running a 32-bit program on a 64-bit system where the kernel maps
+ * the heap up against the top of the 32-bit address space).
+ *
+ * Thanks to Juergen Kreileder <jk@blackdown.de>, who brought this up in
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=279273.
+ */
+ JS_ASSERT((nb & pool->mask) == 0);
+ for (a = pool->current; nb > a->limit || a->avail > a->limit - nb;
+ pool->current = a) {
+ ap = &a->next;
+ if (!*ap) {
+ /* Not enough space in pool, so we must malloc. */
+ extra = (nb > pool->arenasize) ? HEADER_SIZE(pool) : 0;
+ hdrsz = sizeof *a + extra + pool->mask;
+ gross = hdrsz + JS_MAX(nb, pool->arenasize);
+ if (gross < nb)
+ return NULL;
+ if (pool->quotap) {
+ if (gross > *pool->quotap)
+ return NULL;
+ b = (JSArena *) malloc(gross);
+ if (!b)
+ return NULL;
+ *pool->quotap -= gross;
+ } else {
+ b = (JSArena *) malloc(gross);
+ if (!b)
+ return NULL;
+ }
+
+ b->next = NULL;
+ b->limit = (jsuword)b + gross;
+ JS_COUNT_ARENA(pool,++);
+ COUNT(pool, nmallocs);
+
+ /* If oversized, store ap in the header, just before a->base. */
+ *ap = a = b;
+ JS_ASSERT(gross <= JS_UPTRDIFF(a->limit, a));
+ if (extra) {
+ a->base = a->avail =
+ ((jsuword)a + hdrsz) & ~HEADER_BASE_MASK(pool);
+ SET_HEADER(pool, a, ap);
+ } else {
+ a->base = a->avail = JS_ARENA_ALIGN(pool, a + 1);
+ }
+ continue;
+ }
+ a = *ap; /* move to next arena */
+ }
+
+ p = (void *)a->avail;
+ a->avail += nb;
+ JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+ return p;
+}
+
+JS_PUBLIC_API(void *)
+JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr)
+{
+ JSArena **ap, *a, *b;
+ jsuword boff, aoff, extra, hdrsz, gross, growth;
+
+ /*
+ * Use the oversized-single-allocation header to avoid searching for ap.
+ * See JS_ArenaAllocate, the SET_HEADER call.
+ */
+ if (size > pool->arenasize) {
+ ap = *PTR_TO_HEADER(pool, p);
+ a = *ap;
+ } else {
+ ap = &pool->first.next;
+ while ((a = *ap) != pool->current)
+ ap = &a->next;
+ }
+
+ JS_ASSERT(a->base == (jsuword)p);
+ boff = JS_UPTRDIFF(a->base, a);
+ aoff = JS_ARENA_ALIGN(pool, size + incr);
+ JS_ASSERT(aoff > pool->arenasize);
+ extra = HEADER_SIZE(pool); /* oversized header holds ap */
+ hdrsz = sizeof *a + extra + pool->mask; /* header and alignment slop */
+ gross = hdrsz + aoff;
+ JS_ASSERT(gross > aoff);
+ if (pool->quotap) {
+ growth = gross - (a->limit - (jsuword) a);
+ if (growth > *pool->quotap)
+ return NULL;
+ a = (JSArena *) realloc(a, gross);
+ if (!a)
+ return NULL;
+ *pool->quotap -= growth;
+ } else {
+ a = (JSArena *) realloc(a, gross);
+ if (!a)
+ return NULL;
+ }
+#ifdef JS_ARENAMETER
+ pool->stats.nreallocs++;
+#endif
+
+ if (a != *ap) {
+ /* Oops, realloc moved the allocation: update other pointers to a. */
+ if (pool->current == *ap)
+ pool->current = a;
+ b = a->next;
+ if (b && b->avail - b->base > pool->arenasize) {
+ JS_ASSERT(GET_HEADER(pool, b) == &(*ap)->next);
+ SET_HEADER(pool, b, &a->next);
+ }
+
+ /* Now update *ap, the next link of the arena before a. */
+ *ap = a;
+ }
+
+ a->base = ((jsuword)a + hdrsz) & ~HEADER_BASE_MASK(pool);
+ a->limit = (jsuword)a + gross;
+ a->avail = a->base + aoff;
+ JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+
+ /* Check whether realloc aligned differently, and copy if necessary. */
+ if (boff != JS_UPTRDIFF(a->base, a))
+ memmove((void *)a->base, (char *)a + boff, size);
+
+ /* Store ap in the oversized-load arena header. */
+ SET_HEADER(pool, a, ap);
+ return (void *)a->base;
+}
+
+JS_PUBLIC_API(void *)
+JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr)
+{
+ void *newp;
+
+ /*
+ * If p points to an oversized allocation, it owns an entire arena, so we
+ * can simply realloc the arena.
+ */
+ if (size > pool->arenasize)
+ return JS_ArenaRealloc(pool, p, size, incr);
+
+ JS_ARENA_ALLOCATE(newp, pool, size + incr);
+ if (newp)
+ memcpy(newp, p, size);
+ return newp;
+}
+
+/*
+ * Free tail arenas linked after head, which may not be the true list head.
+ * Reset pool->current to point to head in case it pointed at a tail arena.
+ */
+static void
+FreeArenaList(JSArenaPool *pool, JSArena *head)
+{
+ JSArena **ap, *a;
+
+ ap = &head->next;
+ a = *ap;
+ if (!a)
+ return;
+
+#ifdef DEBUG
+ do {
+ JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+ a->avail = a->base;
+ JS_CLEAR_UNUSED(a);
+ } while ((a = a->next) != NULL);
+ a = *ap;
+#endif
+
+ do {
+ *ap = a->next;
+ if (pool->quotap)
+ *pool->quotap += a->limit - (jsuword) a;
+ JS_CLEAR_ARENA(a);
+ JS_COUNT_ARENA(pool,--);
+ free(a);
+ } while ((a = *ap) != NULL);
+
+ pool->current = head;
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaRelease(JSArenaPool *pool, char *mark)
+{
+ JSArena *a;
+
+ for (a = &pool->first; a; a = a->next) {
+ JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+
+ if (JS_ARENA_MARK_MATCH(a, mark)) {
+ a->avail = JS_ARENA_ALIGN(pool, mark);
+ JS_ASSERT(a->avail <= a->limit);
+ FreeArenaList(pool, a);
+ return;
+ }
+ }
+}
+
+JS_PUBLIC_API(void)
+JS_FreeArenaPool(JSArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first);
+ COUNT(pool, ndeallocs);
+}
+
+JS_PUBLIC_API(void)
+JS_FinishArenaPool(JSArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first);
+#ifdef JS_ARENAMETER
+ {
+ JSArenaStats *stats, **statsp;
+
+ if (pool->stats.name) {
+ free(pool->stats.name);
+ pool->stats.name = NULL;
+ }
+ for (statsp = &arena_stats_list; (stats = *statsp) != 0;
+ statsp = &stats->next) {
+ if (stats == &pool->stats) {
+ *statsp = stats->next;
+ return;
+ }
+ }
+ }
+#endif
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaFinish()
+{
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaShutDown(void)
+{
+}
+
+#ifdef JS_ARENAMETER
+JS_PUBLIC_API(void)
+JS_ArenaCountAllocation(JSArenaPool *pool, size_t nb)
+{
+ pool->stats.nallocs++;
+ pool->stats.nbytes += nb;
+ if (nb > pool->stats.maxalloc)
+ pool->stats.maxalloc = nb;
+ pool->stats.variance += nb * nb;
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaCountInplaceGrowth(JSArenaPool *pool, size_t size, size_t incr)
+{
+ pool->stats.ninplace++;
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaCountGrowth(JSArenaPool *pool, size_t size, size_t incr)
+{
+ pool->stats.ngrows++;
+ pool->stats.nbytes += incr;
+ pool->stats.variance -= size * size;
+ size += incr;
+ if (size > pool->stats.maxalloc)
+ pool->stats.maxalloc = size;
+ pool->stats.variance += size * size;
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaCountRelease(JSArenaPool *pool, char *mark)
+{
+ pool->stats.nreleases++;
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaCountRetract(JSArenaPool *pool, char *mark)
+{
+ pool->stats.nfastrels++;
+}
+
+#include <stdio.h>
+
+JS_PUBLIC_API(void)
+JS_DumpArenaStats(FILE *fp)
+{
+ JSArenaStats *stats;
+ double mean, sigma;
+
+ for (stats = arena_stats_list; stats; stats = stats->next) {
+ mean = JS_MeanAndStdDev(stats->nallocs, stats->nbytes, stats->variance,
+ &sigma);
+
+ fprintf(fp, "\n%s allocation statistics:\n", stats->name);
+ fprintf(fp, " number of arenas: %u\n", stats->narenas);
+ fprintf(fp, " number of allocations: %u\n", stats->nallocs);
+ fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs);
+ fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs);
+ fprintf(fp, " number of allocation growths: %u\n", stats->ngrows);
+ fprintf(fp, " number of in-place growths: %u\n", stats->ninplace);
+ fprintf(fp, " number of realloc'ing growths: %u\n", stats->nreallocs);
+ fprintf(fp, "number of released allocations: %u\n", stats->nreleases);
+ fprintf(fp, " number of fast releases: %u\n", stats->nfastrels);
+ fprintf(fp, " total bytes allocated: %u\n", stats->nbytes);
+ fprintf(fp, " mean allocation size: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sigma);
+ fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc);
+ }
+}
+#endif /* JS_ARENAMETER */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsarena.h b/tools/node_modules/expresso/deps/jscoverage/js/jsarena.h
new file mode 100644
index 0000000..8e99a74
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsarena.h
@@ -0,0 +1,318 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsarena_h___
+#define jsarena_h___
+/*
+ * Lifetime-based fast allocation, inspired by much prior art, including
+ * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+ * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+ *
+ * Also supports LIFO allocation (JS_ARENA_MARK/JS_ARENA_RELEASE).
+ */
+#include <stdlib.h>
+#include "jstypes.h"
+#include "jscompat.h"
+
+JS_BEGIN_EXTERN_C
+
+typedef struct JSArena JSArena;
+typedef struct JSArenaPool JSArenaPool;
+
+struct JSArena {
+ JSArena *next; /* next arena for this lifetime */
+ jsuword base; /* aligned base address, follows this header */
+ jsuword limit; /* one beyond last byte in arena */
+ jsuword avail; /* points to next available byte */
+};
+
+#ifdef JS_ARENAMETER
+typedef struct JSArenaStats JSArenaStats;
+
+struct JSArenaStats {
+ JSArenaStats *next; /* next in arenaStats list */
+ char *name; /* name for debugging */
+ uint32 narenas; /* number of arenas in pool */
+ uint32 nallocs; /* number of JS_ARENA_ALLOCATE() calls */
+ uint32 nmallocs; /* number of malloc() calls */
+ uint32 ndeallocs; /* number of lifetime deallocations */
+ uint32 ngrows; /* number of JS_ARENA_GROW() calls */
+ uint32 ninplace; /* number of in-place growths */
+ uint32 nreallocs; /* number of arena grow extending reallocs */
+ uint32 nreleases; /* number of JS_ARENA_RELEASE() calls */
+ uint32 nfastrels; /* number of "fast path" releases */
+ size_t nbytes; /* total bytes allocated */
+ size_t maxalloc; /* maximum allocation size in bytes */
+ double variance; /* size variance accumulator */
+};
+#endif
+
+struct JSArenaPool {
+ JSArena first; /* first arena in pool list */
+ JSArena *current; /* arena from which to allocate space */
+ size_t arenasize; /* net exact size of a new arena */
+ jsuword mask; /* alignment mask (power-of-2 - 1) */
+ size_t *quotap; /* pointer to the quota on pool allocation
+ size or null if pool is unlimited */
+#ifdef JS_ARENAMETER
+ JSArenaStats stats;
+#endif
+};
+
+#ifdef JS_ARENAMETER
+#define JS_INIT_NAMED_ARENA_POOL(pool, name, size, align, quotap) \
+ JS_InitArenaPool(pool, name, size, align, quotap)
+#else
+#define JS_INIT_NAMED_ARENA_POOL(pool, name, size, align, quotap) \
+ JS_InitArenaPool(pool, size, align, quotap)
+#endif
+
+/*
+ * If the including .c file uses only one power-of-2 alignment, it may define
+ * JS_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions
+ * per ALLOCATE and GROW.
+ */
+#ifdef JS_ARENA_CONST_ALIGN_MASK
+#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + JS_ARENA_CONST_ALIGN_MASK) \
+ & ~(jsuword)JS_ARENA_CONST_ALIGN_MASK)
+
+#define JS_INIT_ARENA_POOL(pool, name, size, quotap) \
+ JS_INIT_NAMED_ARENA_POOL(pool, name, size, JS_ARENA_CONST_ALIGN_MASK + 1, \
+ quotap)
+
+#else
+#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + (pool)->mask) & ~(pool)->mask)
+
+#define JS_INIT_ARENA_POOL(pool, name, size, align, quotap) \
+ JS_INIT_NAMED_ARENA_POOL(pool, name, size, align, quotap)
+
+#endif
+
+#define JS_ARENA_ALLOCATE(p, pool, nb) \
+ JS_ARENA_ALLOCATE_CAST(p, void *, pool, nb)
+
+#define JS_ARENA_ALLOCATE_TYPE(p, type, pool) \
+ JS_ARENA_ALLOCATE_COMMON(p, type *, pool, sizeof(type), 0)
+
+#define JS_ARENA_ALLOCATE_CAST(p, type, pool, nb) \
+ JS_ARENA_ALLOCATE_COMMON(p, type, pool, nb, _nb > _a->limit)
+
+/*
+ * NB: In JS_ARENA_ALLOCATE_CAST and JS_ARENA_GROW_CAST, always subtract _nb
+ * from a->limit rather than adding _nb to _p, to avoid overflowing a 32-bit
+ * address space (possible when running a 32-bit program on a 64-bit system
+ * where the kernel maps the heap up against the top of the 32-bit address
+ * space).
+ *
+ * Thanks to Juergen Kreileder <jk@blackdown.de>, who brought this up in
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=279273.
+ */
+#define JS_ARENA_ALLOCATE_COMMON(p, type, pool, nb, guard) \
+ JS_BEGIN_MACRO \
+ JSArena *_a = (pool)->current; \
+ size_t _nb = JS_ARENA_ALIGN(pool, nb); \
+ jsuword _p = _a->avail; \
+ if ((guard) || _p > _a->limit - _nb) \
+ _p = (jsuword)JS_ArenaAllocate(pool, _nb); \
+ else \
+ _a->avail = _p + _nb; \
+ p = (type) _p; \
+ JS_ArenaCountAllocation(pool, nb); \
+ JS_END_MACRO
+
+#define JS_ARENA_GROW(p, pool, size, incr) \
+ JS_ARENA_GROW_CAST(p, void *, pool, size, incr)
+
+#define JS_ARENA_GROW_CAST(p, type, pool, size, incr) \
+ JS_BEGIN_MACRO \
+ JSArena *_a = (pool)->current; \
+ if (_a->avail == (jsuword)(p) + JS_ARENA_ALIGN(pool, size)) { \
+ size_t _nb = (size) + (incr); \
+ _nb = JS_ARENA_ALIGN(pool, _nb); \
+ if (_a->limit >= _nb && (jsuword)(p) <= _a->limit - _nb) { \
+ _a->avail = (jsuword)(p) + _nb; \
+ JS_ArenaCountInplaceGrowth(pool, size, incr); \
+ } else if ((jsuword)(p) == _a->base) { \
+ p = (type) JS_ArenaRealloc(pool, p, size, incr); \
+ } else { \
+ p = (type) JS_ArenaGrow(pool, p, size, incr); \
+ } \
+ } else { \
+ p = (type) JS_ArenaGrow(pool, p, size, incr); \
+ } \
+ JS_ArenaCountGrowth(pool, size, incr); \
+ JS_END_MACRO
+
+#define JS_ARENA_MARK(pool) ((void *) (pool)->current->avail)
+#define JS_UPTRDIFF(p,q) ((jsuword)(p) - (jsuword)(q))
+
+/*
+ * Check if the mark is inside arena's allocated area.
+ */
+#define JS_ARENA_MARK_MATCH(a, mark) \
+ (JS_UPTRDIFF(mark, (a)->base) <= JS_UPTRDIFF((a)->avail, (a)->base))
+
+#ifdef DEBUG
+#define JS_FREE_PATTERN 0xDA
+#define JS_CLEAR_UNUSED(a) (JS_ASSERT((a)->avail <= (a)->limit), \
+ memset((void*)(a)->avail, JS_FREE_PATTERN, \
+ (a)->limit - (a)->avail))
+#define JS_CLEAR_ARENA(a) memset((void*)(a), JS_FREE_PATTERN, \
+ (a)->limit - (jsuword)(a))
+#else
+#define JS_CLEAR_UNUSED(a) /* nothing */
+#define JS_CLEAR_ARENA(a) /* nothing */
+#endif
+
+#define JS_ARENA_RELEASE(pool, mark) \
+ JS_BEGIN_MACRO \
+ char *_m = (char *)(mark); \
+ JSArena *_a = (pool)->current; \
+ if (_a != &(pool)->first && JS_ARENA_MARK_MATCH(_a, _m)) { \
+ _a->avail = (jsuword)JS_ARENA_ALIGN(pool, _m); \
+ JS_ASSERT(_a->avail <= _a->limit); \
+ JS_CLEAR_UNUSED(_a); \
+ JS_ArenaCountRetract(pool, _m); \
+ } else { \
+ JS_ArenaRelease(pool, _m); \
+ } \
+ JS_ArenaCountRelease(pool, _m); \
+ JS_END_MACRO
+
+#ifdef JS_ARENAMETER
+#define JS_COUNT_ARENA(pool,op) ((pool)->stats.narenas op)
+#else
+#define JS_COUNT_ARENA(pool,op)
+#endif
+
+#define JS_ARENA_DESTROY(pool, a, pnext) \
+ JS_BEGIN_MACRO \
+ JS_COUNT_ARENA(pool,--); \
+ if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
+ *(pnext) = (a)->next; \
+ JS_CLEAR_ARENA(a); \
+ free(a); \
+ (a) = NULL; \
+ JS_END_MACRO
+
+/*
+ * Initialize an arena pool with a minimum size per arena of size bytes.
+ * Always call JS_SET_ARENA_METER_NAME before calling this or use
+ * JS_INIT_ARENA_POOL macro to provide a name for for debugging and metering.
+ */
+extern JS_PUBLIC_API(void)
+JS_INIT_NAMED_ARENA_POOL(JSArenaPool *pool, const char *name, size_t size,
+ size_t align, size_t *quotap);
+
+/*
+ * Free the arenas in pool. The user may continue to allocate from pool
+ * after calling this function. There is no need to call JS_InitArenaPool()
+ * again unless JS_FinishArenaPool(pool) has been called.
+ */
+extern JS_PUBLIC_API(void)
+JS_FreeArenaPool(JSArenaPool *pool);
+
+/*
+ * Free the arenas in pool and finish using it altogether.
+ */
+extern JS_PUBLIC_API(void)
+JS_FinishArenaPool(JSArenaPool *pool);
+
+/*
+ * Deprecated do-nothing function.
+ */
+extern JS_PUBLIC_API(void)
+JS_ArenaFinish(void);
+
+/*
+ * Deprecated do-nothing function.
+ */
+extern JS_PUBLIC_API(void)
+JS_ArenaShutDown(void);
+
+/*
+ * Friend functions used by the JS_ARENA_*() macros.
+ */
+extern JS_PUBLIC_API(void *)
+JS_ArenaAllocate(JSArenaPool *pool, size_t nb);
+
+extern JS_PUBLIC_API(void *)
+JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr);
+
+extern JS_PUBLIC_API(void *)
+JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr);
+
+extern JS_PUBLIC_API(void)
+JS_ArenaRelease(JSArenaPool *pool, char *mark);
+
+#ifdef JS_ARENAMETER
+
+#include <stdio.h>
+
+extern JS_PUBLIC_API(void)
+JS_ArenaCountAllocation(JSArenaPool *pool, size_t nb);
+
+extern JS_PUBLIC_API(void)
+JS_ArenaCountInplaceGrowth(JSArenaPool *pool, size_t size, size_t incr);
+
+extern JS_PUBLIC_API(void)
+JS_ArenaCountGrowth(JSArenaPool *pool, size_t size, size_t incr);
+
+extern JS_PUBLIC_API(void)
+JS_ArenaCountRelease(JSArenaPool *pool, char *mark);
+
+extern JS_PUBLIC_API(void)
+JS_ArenaCountRetract(JSArenaPool *pool, char *mark);
+
+extern JS_PUBLIC_API(void)
+JS_DumpArenaStats(FILE *fp);
+
+#else /* !JS_ARENAMETER */
+
+#define JS_ArenaCountAllocation(ap, nb) /* nothing */
+#define JS_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */
+#define JS_ArenaCountGrowth(ap, size, incr) /* nothing */
+#define JS_ArenaCountRelease(ap, mark) /* nothing */
+#define JS_ArenaCountRetract(ap, mark) /* nothing */
+
+#endif /* !JS_ARENAMETER */
+
+JS_END_EXTERN_C
+
+#endif /* jsarena_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsarray.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsarray.cpp
new file mode 100644
index 0000000..d6a2d83
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsarray.cpp
@@ -0,0 +1,3426 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS array class.
+ *
+ * Array objects begin as "dense" arrays, optimized for numeric-only property
+ * access over a vector of slots (obj->dslots) with high load factor. Array
+ * methods optimize for denseness by testing that the object's class is
+ * &js_ArrayClass, and can then directly manipulate the slots for efficiency.
+ *
+ * We track these pieces of metadata for arrays in dense mode:
+ * - the array's length property as a uint32, in JSSLOT_ARRAY_LENGTH,
+ * - the number of indices that are filled (non-holes), in JSSLOT_ARRAY_COUNT,
+ * - the net number of slots starting at dslots (DENSELEN), in dslots[-1] if
+ * dslots is non-NULL.
+ *
+ * In dense mode, holes in the array are represented by JSVAL_HOLE. The final
+ * slot in fslots (JSSLOT_ARRAY_LOOKUP_HOLDER) is used to store the single jsid
+ * "in use" by a lookupProperty caller.
+ *
+ * Arrays are converted to use js_SlowArrayClass when any of these conditions
+ * are met:
+ * - the load factor (COUNT / DENSELEN) is less than 0.25, and there are
+ * more than MIN_SPARSE_INDEX slots total
+ * - a property is set that is non-numeric (and not "length"); or
+ * - a hole is filled below DENSELEN (possibly implicitly through methods like
+ * |reverse| or |splice|).
+ *
+ * In the latter two cases, property creation order is no longer index order,
+ * which necessitates use of a structure that keeps track of property creation
+ * order. (ES4, due to expectations baked into web script, requires that
+ * enumeration order be the order in which properties were created.)
+ *
+ * An alternative in the latter case (out-of-order index set) would be to
+ * maintain the scope to track property enumeration order, but still use
+ * the fast slot access. That would have the same memory cost as just using
+ * a js_SlowArrayClass, but have the same performance characteristics as
+ * a dense array for slot accesses, at some cost in code complexity.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbit.h"
+#include "jsbool.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h" /* for js_TraceWatchPoints */
+#include "jsdtoa.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsscope.h"
+#include "jsstr.h"
+#include "jsstaticcheck.h"
+
+/* 2^32 - 1 as a number and a string */
+#define MAXINDEX 4294967295u
+#define MAXSTR "4294967295"
+
+/* Small arrays are dense, no matter what. */
+#define MIN_SPARSE_INDEX 32
+
+#define INDEX_TOO_BIG(index) ((index) > JS_BIT(29) - 1)
+#define INDEX_TOO_SPARSE(array, index) \
+ (INDEX_TOO_BIG(index) || \
+ ((index) > ARRAY_DENSE_LENGTH(array) && (index) >= MIN_SPARSE_INDEX && \
+ (index) > (uint32)((array)->fslots[JSSLOT_ARRAY_COUNT] + 1) * 4))
+
+JS_STATIC_ASSERT(sizeof(JSScopeProperty) > 4 * sizeof(jsval));
+
+#define ENSURE_SLOW_ARRAY(cx, obj) \
+ (OBJ_GET_CLASS(cx, obj) == &js_SlowArrayClass || js_MakeArraySlow(cx, obj))
+
+/*
+ * Determine if the id represents an array index or an XML property index.
+ *
+ * An id is an array index according to ECMA by (15.4):
+ *
+ * "Array objects give special treatment to a certain class of property names.
+ * A property name P (in the form of a string value) is an array index if and
+ * only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal
+ * to 2^32-1."
+ *
+ * In our implementation, it would be sufficient to check for JSVAL_IS_INT(id)
+ * except that by using signed 32-bit integers we miss the top half of the
+ * valid range. This function checks the string representation itself; note
+ * that calling a standard conversion routine might allow strings such as
+ * "08" or "4.0" as array indices, which they are not.
+ */
+JSBool
+js_IdIsIndex(jsval id, jsuint *indexp)
+{
+ JSString *str;
+ jschar *cp;
+
+ if (JSVAL_IS_INT(id)) {
+ jsint i;
+ i = JSVAL_TO_INT(id);
+ if (i < 0)
+ return JS_FALSE;
+ *indexp = (jsuint)i;
+ return JS_TRUE;
+ }
+
+ /* NB: id should be a string, but jsxml.c may call us with an object id. */
+ if (!JSVAL_IS_STRING(id))
+ return JS_FALSE;
+
+ str = JSVAL_TO_STRING(id);
+ cp = JSSTRING_CHARS(str);
+ if (JS7_ISDEC(*cp) && JSSTRING_LENGTH(str) < sizeof(MAXSTR)) {
+ jsuint index = JS7_UNDEC(*cp++);
+ jsuint oldIndex = 0;
+ jsuint c = 0;
+ if (index != 0) {
+ while (JS7_ISDEC(*cp)) {
+ oldIndex = index;
+ c = JS7_UNDEC(*cp);
+ index = 10*index + c;
+ cp++;
+ }
+ }
+
+ /* Ensure that all characters were consumed and we didn't overflow. */
+ if (*cp == 0 &&
+ (oldIndex < (MAXINDEX / 10) ||
+ (oldIndex == (MAXINDEX / 10) && c < (MAXINDEX % 10))))
+ {
+ *indexp = index;
+ return JS_TRUE;
+ }
+ }
+ return JS_FALSE;
+}
+
+static jsuint
+ValueIsLength(JSContext *cx, jsval* vp)
+{
+ jsint i;
+ jsdouble d;
+ jsuint length;
+
+ if (JSVAL_IS_INT(*vp)) {
+ i = JSVAL_TO_INT(*vp);
+ if (i < 0)
+ goto error;
+ return (jsuint) i;
+ }
+
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ goto error;
+
+ if (JSDOUBLE_IS_NaN(d))
+ goto error;
+ length = (jsuint) d;
+ if (d != (jsdouble) length)
+ goto error;
+ return length;
+
+ error:
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_ARRAY_LENGTH);
+ *vp = JSVAL_NULL;
+ return 0;
+}
+
+JSBool
+js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
+{
+ JSTempValueRooter tvr;
+ jsid id;
+ JSBool ok;
+ jsint i;
+
+ if (OBJ_IS_ARRAY(cx, obj)) {
+ *lengthp = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ return JS_TRUE;
+ }
+
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value);
+ if (ok) {
+ if (JSVAL_IS_INT(tvr.u.value)) {
+ i = JSVAL_TO_INT(tvr.u.value);
+ *lengthp = (jsuint)i; /* jsuint cast does ToUint32 */
+ } else {
+ *lengthp = js_ValueToECMAUint32(cx, &tvr.u.value);
+ ok = !JSVAL_IS_NULL(tvr.u.value);
+ }
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSBool
+IndexToValue(JSContext *cx, jsuint index, jsval *vp)
+{
+ if (index <= JSVAL_INT_MAX) {
+ *vp = INT_TO_JSVAL(index);
+ return JS_TRUE;
+ }
+ return JS_NewDoubleValue(cx, (jsdouble)index, vp);
+}
+
+JSBool JS_FASTCALL
+js_IndexToId(JSContext *cx, jsuint index, jsid *idp)
+{
+ JSString *str;
+
+ if (index <= JSVAL_INT_MAX) {
+ *idp = INT_TO_JSID(index);
+ return JS_TRUE;
+ }
+ str = js_NumberToString(cx, index);
+ if (!str)
+ return JS_FALSE;
+ return js_ValueToStringId(cx, STRING_TO_JSVAL(str), idp);
+}
+
+static JSBool
+BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom,
+ jsid *idp)
+{
+ jschar buf[10], *start;
+ JSClass *clasp;
+ JSAtom *atom;
+ JS_STATIC_ASSERT((jsuint)-1 == 4294967295U);
+
+ JS_ASSERT(index > JSVAL_INT_MAX);
+
+ start = JS_ARRAY_END(buf);
+ do {
+ --start;
+ *start = (jschar)('0' + index % 10);
+ index /= 10;
+ } while (index != 0);
+
+ /*
+ * Skip the atomization if the class is known to store atoms corresponding
+ * to big indexes together with elements. In such case we know that the
+ * array does not have an element at the given index if its atom does not
+ * exist. Fast arrays (clasp == &js_ArrayClass) don't use atoms for
+ * any indexes, though it would be rare to see them have a big index
+ * in any case.
+ */
+ if (!createAtom &&
+ ((clasp = OBJ_GET_CLASS(cx, obj)) == &js_SlowArrayClass ||
+ clasp == &js_ArgumentsClass ||
+ clasp == &js_ObjectClass)) {
+ atom = js_GetExistingStringAtom(cx, start, JS_ARRAY_END(buf) - start);
+ if (!atom) {
+ *idp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ } else {
+ atom = js_AtomizeChars(cx, start, JS_ARRAY_END(buf) - start, 0);
+ if (!atom)
+ return JS_FALSE;
+ }
+
+ *idp = ATOM_TO_JSID(atom);
+ return JS_TRUE;
+}
+
+static JSBool
+ResizeSlots(JSContext *cx, JSObject *obj, uint32 oldlen, uint32 len)
+{
+ jsval *slots, *newslots;
+
+ if (len == 0) {
+ if (obj->dslots) {
+ JS_free(cx, obj->dslots - 1);
+ obj->dslots = NULL;
+ }
+ return JS_TRUE;
+ }
+
+ if (len > ~(uint32)0 / sizeof(jsval)) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+
+ slots = obj->dslots ? obj->dslots - 1 : NULL;
+ newslots = (jsval *) JS_realloc(cx, slots, sizeof (jsval) * (len + 1));
+ if (!newslots)
+ return JS_FALSE;
+
+ obj->dslots = newslots + 1;
+ ARRAY_SET_DENSE_LENGTH(obj, len);
+
+ for (slots = obj->dslots + oldlen; slots < obj->dslots + len; slots++)
+ *slots = JSVAL_HOLE;
+
+ return JS_TRUE;
+}
+
+static JSBool
+EnsureLength(JSContext *cx, JSObject *obj, uint32 len)
+{
+ uint32 oldlen = ARRAY_DENSE_LENGTH(obj);
+
+ if (len > oldlen) {
+ return ResizeSlots(cx, obj, oldlen,
+ len + ARRAY_GROWBY - (len % ARRAY_GROWBY));
+ }
+ return JS_TRUE;
+}
+
+/*
+ * If the property at the given index exists, get its value into location
+ * pointed by vp and set *hole to false. Otherwise set *hole to true and *vp
+ * to JSVAL_VOID. This function assumes that the location pointed by vp is
+ * properly rooted and can be used as GC-protected storage for temporaries.
+ */
+static JSBool
+GetArrayElement(JSContext *cx, JSObject *obj, jsuint index, JSBool *hole,
+ jsval *vp)
+{
+ jsid id;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj) && index < ARRAY_DENSE_LENGTH(obj) &&
+ (*vp = obj->dslots[index]) != JSVAL_HOLE) {
+ *hole = JS_FALSE;
+ return JS_TRUE;
+ }
+
+ if (index <= JSVAL_INT_MAX) {
+ id = INT_TO_JSID(index);
+ } else {
+ if (!BigIndexToId(cx, obj, index, JS_FALSE, &id))
+ return JS_FALSE;
+ if (JSVAL_IS_VOID(id)) {
+ *hole = JS_TRUE;
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ }
+
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ *hole = JS_TRUE;
+ *vp = JSVAL_VOID;
+ } else {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!OBJ_GET_PROPERTY(cx, obj, id, vp))
+ return JS_FALSE;
+ *hole = JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+/*
+ * Set the value of the property at the given index to v assuming v is rooted.
+ */
+static JSBool
+SetArrayElement(JSContext *cx, JSObject *obj, jsuint index, jsval v)
+{
+ jsid id;
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ /* Predicted/prefeched code should favor the remains-dense case. */
+ if (!INDEX_TOO_SPARSE(obj, index)) {
+ if (!EnsureLength(cx, obj, index + 1))
+ return JS_FALSE;
+ if (index >= (uint32)obj->fslots[JSSLOT_ARRAY_LENGTH])
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = index + 1;
+ if (obj->dslots[index] == JSVAL_HOLE)
+ obj->fslots[JSSLOT_ARRAY_COUNT]++;
+ obj->dslots[index] = v;
+ return JS_TRUE;
+ }
+
+ if (!js_MakeArraySlow(cx, obj))
+ return JS_FALSE;
+ }
+
+ if (index <= JSVAL_INT_MAX) {
+ id = INT_TO_JSID(index);
+ } else {
+ if (!BigIndexToId(cx, obj, index, JS_TRUE, &id))
+ return JS_FALSE;
+ JS_ASSERT(!JSVAL_IS_VOID(id));
+ }
+ return OBJ_SET_PROPERTY(cx, obj, id, &v);
+}
+
+static JSBool
+DeleteArrayElement(JSContext *cx, JSObject *obj, jsuint index)
+{
+ jsid id;
+ jsval junk;
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ if (index < ARRAY_DENSE_LENGTH(obj)) {
+ if (obj->dslots[index] != JSVAL_HOLE)
+ obj->fslots[JSSLOT_ARRAY_COUNT]--;
+ obj->dslots[index] = JSVAL_HOLE;
+ }
+ return JS_TRUE;
+ }
+
+ if (index <= JSVAL_INT_MAX) {
+ id = INT_TO_JSID(index);
+ } else {
+ if (!BigIndexToId(cx, obj, index, JS_FALSE, &id))
+ return JS_FALSE;
+ if (JSVAL_IS_VOID(id))
+ return JS_TRUE;
+ }
+ return OBJ_DELETE_PROPERTY(cx, obj, id, &junk);
+}
+
+/*
+ * When hole is true, delete the property at the given index. Otherwise set
+ * its value to v assuming v is rooted.
+ */
+static JSBool
+SetOrDeleteArrayElement(JSContext *cx, JSObject *obj, jsuint index,
+ JSBool hole, jsval v)
+{
+ if (hole) {
+ JS_ASSERT(JSVAL_IS_VOID(v));
+ return DeleteArrayElement(cx, obj, index);
+ }
+ return SetArrayElement(cx, obj, index, v);
+}
+
+JSBool
+js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length)
+{
+ jsval v;
+ jsid id;
+
+ if (!IndexToValue(cx, length, &v))
+ return JS_FALSE;
+ id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
+ return OBJ_SET_PROPERTY(cx, obj, id, &v);
+}
+
+JSBool
+js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
+{
+ JSErrorReporter older;
+ JSTempValueRooter tvr;
+ jsid id;
+ JSBool ok;
+
+ older = JS_SetErrorReporter(cx, NULL);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value);
+ JS_SetErrorReporter(cx, older);
+ if (ok) {
+ *lengthp = ValueIsLength(cx, &tvr.u.value);
+ ok = !JSVAL_IS_NULL(tvr.u.value);
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+JSBool
+js_IsArrayLike(JSContext *cx, JSObject *obj, JSBool *answerp, jsuint *lengthp)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ *answerp = (clasp == &js_ArgumentsClass || clasp == &js_ArrayClass ||
+ clasp == &js_SlowArrayClass);
+ if (!*answerp) {
+ *lengthp = 0;
+ return JS_TRUE;
+ }
+ return js_GetLengthProperty(cx, obj, lengthp);
+}
+
+/*
+ * The 'length' property of all native Array instances is a shared permanent
+ * property of Array.prototype, so it appears to be a direct property of each
+ * array instance delegating to that Array.prototype. It accesses the private
+ * slot reserved by js_ArrayClass.
+ *
+ * Since SpiderMonkey supports cross-class prototype-based delegation, we have
+ * to be careful about the length getter and setter being called on an object
+ * not of Array class. For the getter, we search obj's prototype chain for the
+ * array that caused this getter to be invoked. In the setter case to overcome
+ * the JSPROP_SHARED attribute, we must define a shadowing length property.
+ */
+static JSBool
+array_length_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ do {
+ if (OBJ_IS_ARRAY(cx, obj))
+ return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
+ } while ((obj = OBJ_GET_PROTO(cx, obj)) != NULL);
+ return JS_TRUE;
+}
+
+static JSBool
+array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsuint newlen, oldlen, gap, index;
+ jsval junk;
+ JSObject *iter;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ if (!OBJ_IS_ARRAY(cx, obj)) {
+ jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
+
+ return OBJ_DEFINE_PROPERTY(cx, obj, lengthId, *vp, NULL, NULL,
+ JSPROP_ENUMERATE, NULL);
+ }
+
+ newlen = ValueIsLength(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return JS_FALSE;
+ oldlen = obj->fslots[JSSLOT_ARRAY_LENGTH];
+
+ if (oldlen == newlen)
+ return JS_TRUE;
+
+ if (!IndexToValue(cx, newlen, vp))
+ return JS_FALSE;
+
+ if (oldlen < newlen) {
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = newlen;
+ return JS_TRUE;
+ }
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ if (ARRAY_DENSE_LENGTH(obj) && !ResizeSlots(cx, obj, oldlen, newlen))
+ return JS_FALSE;
+ } else if (oldlen - newlen < (1 << 24)) {
+ do {
+ --oldlen;
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) ||
+ !DeleteArrayElement(cx, obj, oldlen)) {
+ return JS_FALSE;
+ }
+ } while (oldlen != newlen);
+ } else {
+ /*
+ * We are going to remove a lot of indexes in a presumably sparse
+ * array. So instead of looping through indexes between newlen and
+ * oldlen, we iterate through all properties and remove those that
+ * correspond to indexes in the half-open range [newlen, oldlen). See
+ * bug 322135.
+ */
+ iter = JS_NewPropertyIterator(cx, obj);
+ if (!iter)
+ return JS_FALSE;
+
+ /* Protect iter against GC in OBJ_DELETE_PROPERTY. */
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, iter, &tvr);
+ gap = oldlen - newlen;
+ for (;;) {
+ ok = (JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ JS_NextProperty(cx, iter, &id));
+ if (!ok)
+ break;
+ if (JSVAL_IS_VOID(id))
+ break;
+ if (js_IdIsIndex(id, &index) && index - newlen < gap) {
+ ok = OBJ_DELETE_PROPERTY(cx, obj, id, &junk);
+ if (!ok)
+ break;
+ }
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+ }
+
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = newlen;
+ return JS_TRUE;
+}
+
+static JSBool
+array_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp)
+{
+ uint32 i;
+ union { JSProperty *p; jsval *v; } u;
+
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj))
+ return js_LookupProperty(cx, obj, id, objp, propp);
+
+ /*
+ * We have only indexed properties up to DENSELEN (excepting holes), plus
+ * the length property. For all else, we delegate to the prototype.
+ */
+ if (id != ATOM_TO_JSID(cx->runtime->atomState.lengthAtom) &&
+ (!js_IdIsIndex(id, &i) ||
+ obj->fslots[JSSLOT_ARRAY_LENGTH] == 0 ||
+ i >= ARRAY_DENSE_LENGTH(obj) ||
+ obj->dslots[i] == JSVAL_HOLE))
+ {
+ JSObject *proto = STOBJ_GET_PROTO(obj);
+
+ if (!proto) {
+ *objp = NULL;
+ *propp = NULL;
+ return JS_TRUE;
+ }
+
+ return OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp);
+ }
+
+ /* FIXME 417501: threadsafety: could race with a lookup on another thread.
+ * If we can only have a single lookup active per context, we could
+ * pigeonhole this on the context instead. */
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_ARRAY_LOOKUP_HOLDER]));
+ obj->fslots[JSSLOT_ARRAY_LOOKUP_HOLDER] = (jsval) id;
+ u.v = &(obj->fslots[JSSLOT_ARRAY_LOOKUP_HOLDER]);
+ *propp = u.p;
+ *objp = obj;
+ return JS_TRUE;
+}
+
+static void
+array_dropProperty(JSContext *cx, JSObject *obj, JSProperty *prop)
+{
+ JS_ASSERT_IF(OBJ_IS_DENSE_ARRAY(cx, obj),
+ !JSVAL_IS_VOID(obj->fslots[JSSLOT_ARRAY_LOOKUP_HOLDER]));
+#ifdef DEBUG
+ obj->fslots[JSSLOT_ARRAY_LOOKUP_HOLDER] = JSVAL_VOID;
+#endif
+}
+
+static JSBool
+array_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ uint32 i;
+
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))
+ return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
+
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.protoAtom)) {
+ *vp = STOBJ_GET_SLOT(obj, JSSLOT_PROTO);
+ return JS_TRUE;
+ }
+
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj))
+ return js_GetProperty(cx, obj, id, vp);
+
+ if (!js_IdIsIndex(ID_TO_VALUE(id), &i) || i >= ARRAY_DENSE_LENGTH(obj) ||
+ obj->dslots[i] == JSVAL_HOLE) {
+ JSObject *obj2;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ JSObject *proto = STOBJ_GET_PROTO(obj);
+ if (!proto) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ *vp = JSVAL_VOID;
+ if (js_LookupPropertyWithFlags(cx, proto, id, cx->resolveFlags,
+ &obj2, &prop) < 0)
+ return JS_FALSE;
+
+ if (prop) {
+ if (OBJ_IS_NATIVE(obj2)) {
+ sprop = (JSScopeProperty *) prop;
+ if (!js_NativeGet(cx, obj, obj2, sprop, vp))
+ return JS_FALSE;
+ }
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+ return JS_TRUE;
+ }
+
+ *vp = obj->dslots[i];
+ return JS_TRUE;
+}
+
+static JSBool
+slowarray_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsuint index, length;
+
+ if (!js_IdIsIndex(id, &index))
+ return JS_TRUE;
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (index >= length)
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = index + 1;
+ return JS_TRUE;
+}
+
+static void
+slowarray_trace(JSTracer *trc, JSObject *obj)
+{
+ uint32 length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_SlowArrayClass);
+
+ /*
+ * Move JSSLOT_ARRAY_LENGTH aside to prevent the GC from treating
+ * untagged integer values as objects or strings.
+ */
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = JSVAL_VOID;
+ js_TraceObject(trc, obj);
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = length;
+}
+
+static JSObjectOps js_SlowArrayObjectOps;
+
+static JSObjectOps *
+slowarray_getObjectOps(JSContext *cx, JSClass *clasp)
+{
+ return &js_SlowArrayObjectOps;
+}
+
+static JSBool
+array_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ uint32 i;
+
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))
+ return array_length_setter(cx, obj, id, vp);
+
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj))
+ return js_SetProperty(cx, obj, id, vp);
+
+ if (!js_IdIsIndex(id, &i) || INDEX_TOO_SPARSE(obj, i)) {
+ if (!js_MakeArraySlow(cx, obj))
+ return JS_FALSE;
+ return js_SetProperty(cx, obj, id, vp);
+ }
+
+ if (!EnsureLength(cx, obj, i + 1))
+ return JS_FALSE;
+
+ if (i >= (uint32)obj->fslots[JSSLOT_ARRAY_LENGTH])
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
+ if (obj->dslots[i] == JSVAL_HOLE)
+ obj->fslots[JSSLOT_ARRAY_COUNT]++;
+ obj->dslots[i] = *vp;
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+JSBool FASTCALL
+js_Array_dense_setelem(JSContext* cx, JSObject* obj, jsint i, jsval v)
+{
+ JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj));
+
+ do {
+ jsuint length = ARRAY_DENSE_LENGTH(obj);
+ if ((jsuint)i < length) {
+ if (obj->dslots[i] == JSVAL_HOLE) {
+ if (cx->runtime->anyArrayProtoHasElement)
+ break;
+ if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH])
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
+ obj->fslots[JSSLOT_ARRAY_COUNT]++;
+ }
+ obj->dslots[i] = v;
+ return JS_TRUE;
+ }
+ } while (0);
+ return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(i), &v);
+}
+#endif
+
+static JSBool
+array_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ JSProperty **propp)
+{
+ uint32 i;
+ JSBool isIndex;
+
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))
+ return JS_TRUE;
+
+ isIndex = js_IdIsIndex(ID_TO_VALUE(id), &i);
+ if (!isIndex || attrs != JSPROP_ENUMERATE) {
+ if (!ENSURE_SLOW_ARRAY(cx, obj))
+ return JS_FALSE;
+ if (isIndex && STOBJ_IS_DELEGATE(obj))
+ cx->runtime->anyArrayProtoHasElement = JS_TRUE;
+ return js_DefineProperty(cx, obj, id, value, getter, setter, attrs, propp);
+ }
+
+ return array_setProperty(cx, obj, id, &value);
+}
+
+static JSBool
+array_getAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ *attrsp = id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)
+ ? JSPROP_PERMANENT : JSPROP_ENUMERATE;
+ return JS_TRUE;
+}
+
+static JSBool
+array_setAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_SET_ARRAY_ATTRS);
+ return JS_FALSE;
+}
+
+static JSBool
+array_deleteProperty(JSContext *cx, JSObject *obj, jsval id, jsval *rval)
+{
+ uint32 i;
+
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj))
+ return js_DeleteProperty(cx, obj, id, rval);
+
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) {
+ *rval = JSVAL_FALSE;
+ return JS_TRUE;
+ }
+
+ if (js_IdIsIndex(id, &i) && i < ARRAY_DENSE_LENGTH(obj) &&
+ obj->dslots[i] != JSVAL_HOLE) {
+ obj->fslots[JSSLOT_ARRAY_COUNT]--;
+ obj->dslots[i] = JSVAL_HOLE;
+ }
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+}
+
+/*
+ * JSObjectOps.enumerate implementation.
+ *
+ * For a fast array, JSENUMERATE_INIT captures in the enumeration state both
+ * the length of the array and the bitmap indicating the positions of holes in
+ * the array. This ensures that adding or deleting array elements does not
+ * affect the sequence of indexes JSENUMERATE_NEXT returns.
+ *
+ * For a common case of an array without holes, to represent the state we pack
+ * the (nextEnumerationIndex, arrayLength) pair as a pseudo-boolean jsval.
+ * This is possible when length <= PACKED_UINT_PAIR_BITS. For arrays with
+ * greater length or holes we allocate the JSIndexIterState structure and
+ * store it as an int-tagged private pointer jsval. For a slow array we
+ * delegate the enumeration implementation to js_Enumerate in
+ * slowarray_enumerate.
+ *
+ * Array mutations can turn a fast array into a slow one after the enumeration
+ * starts. When this happens, slowarray_enumerate receives a state created
+ * when the array was fast. To distinguish such fast state from a slow state,
+ * which is an int-tagged pointer that js_Enumerate creates, we set not one
+ * but two lowest bits when tagging a JSIndexIterState pointer -- see
+ * INDEX_ITER_TAG usage below. Thus, when slowarray_enumerate receives a state
+ * tagged with JSVAL_BOOLEAN or with two lowest bits set, it knows that this
+ * is a fast state so it calls array_enumerate to continue enumerating the
+ * indexes present in the original fast array.
+ */
+
+#define PACKED_UINT_PAIR_BITS 14
+#define PACKED_UINT_PAIR_MASK JS_BITMASK(PACKED_UINT_PAIR_BITS)
+
+#define UINT_PAIR_TO_BOOLEAN_JSVAL(i,j) \
+ (JS_ASSERT((uint32) (i) <= PACKED_UINT_PAIR_MASK), \
+ JS_ASSERT((uint32) (j) <= PACKED_UINT_PAIR_MASK), \
+ ((jsval) (i) << (PACKED_UINT_PAIR_BITS + JSVAL_TAGBITS)) | \
+ ((jsval) (j) << (JSVAL_TAGBITS)) | \
+ (jsval) JSVAL_BOOLEAN)
+
+#define BOOLEAN_JSVAL_TO_UINT_PAIR(v,i,j) \
+ (JS_ASSERT(JSVAL_TAG(v) == JSVAL_BOOLEAN), \
+ (i) = (uint32) ((v) >> (PACKED_UINT_PAIR_BITS + JSVAL_TAGBITS)), \
+ (j) = (uint32) ((v) >> JSVAL_TAGBITS) & PACKED_UINT_PAIR_MASK, \
+ JS_ASSERT((i) <= PACKED_UINT_PAIR_MASK))
+
+JS_STATIC_ASSERT(PACKED_UINT_PAIR_BITS * 2 + JSVAL_TAGBITS <= JS_BITS_PER_WORD);
+
+typedef struct JSIndexIterState {
+ uint32 index;
+ uint32 length;
+ JSBool hasHoles;
+
+ /*
+ * Variable-length bitmap representing array's holes. It must not be
+ * accessed when hasHoles is false.
+ */
+ jsbitmap holes[1];
+} JSIndexIterState;
+
+#define INDEX_ITER_TAG 3
+
+JS_STATIC_ASSERT(JSVAL_INT == 1);
+
+static JSBool
+array_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ uint32 length, i;
+ JSIndexIterState *ii;
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj));
+ length = ARRAY_DENSE_LENGTH(obj);
+ if (idp)
+ *idp = INT_TO_JSVAL(obj->fslots[JSSLOT_ARRAY_COUNT]);
+ ii = NULL;
+ for (i = 0; i != length; ++i) {
+ if (obj->dslots[i] == JSVAL_HOLE) {
+ if (!ii) {
+ ii = (JSIndexIterState *)
+ JS_malloc(cx, offsetof(JSIndexIterState, holes) +
+ JS_BITMAP_SIZE(length));
+ if (!ii)
+ return JS_FALSE;
+ ii->hasHoles = JS_TRUE;
+ memset(ii->holes, 0, JS_BITMAP_SIZE(length));
+ }
+ JS_SET_BIT(ii->holes, i);
+ }
+ }
+ if (!ii) {
+ /* Array has no holes. */
+ if (length <= PACKED_UINT_PAIR_MASK) {
+ *statep = UINT_PAIR_TO_BOOLEAN_JSVAL(0, length);
+ break;
+ }
+ ii = (JSIndexIterState *)
+ JS_malloc(cx, offsetof(JSIndexIterState, holes));
+ if (!ii)
+ return JS_FALSE;
+ ii->hasHoles = JS_FALSE;
+ }
+ ii->index = 0;
+ ii->length = length;
+ *statep = (jsval) ii | INDEX_ITER_TAG;
+ JS_ASSERT(*statep & JSVAL_INT);
+ break;
+
+ case JSENUMERATE_NEXT:
+ if (JSVAL_TAG(*statep) == JSVAL_BOOLEAN) {
+ BOOLEAN_JSVAL_TO_UINT_PAIR(*statep, i, length);
+ if (i != length) {
+ *idp = INT_TO_JSID(i);
+ *statep = UINT_PAIR_TO_BOOLEAN_JSVAL(i + 1, length);
+ break;
+ }
+ } else {
+ JS_ASSERT((*statep & INDEX_ITER_TAG) == INDEX_ITER_TAG);
+ ii = (JSIndexIterState *) (*statep & ~INDEX_ITER_TAG);
+ i = ii->index;
+ if (i != ii->length) {
+ /* Skip holes if any. */
+ if (ii->hasHoles) {
+ while (JS_TEST_BIT(ii->holes, i) && ++i != ii->length)
+ continue;
+ }
+ if (i != ii->length) {
+ ii->index = i + 1;
+ return js_IndexToId(cx, i, idp);
+ }
+ }
+ }
+ /* FALL THROUGH */
+
+ case JSENUMERATE_DESTROY:
+ if (JSVAL_TAG(*statep) != JSVAL_BOOLEAN) {
+ JS_ASSERT((*statep & INDEX_ITER_TAG) == INDEX_ITER_TAG);
+ ii = (JSIndexIterState *) (*statep & ~INDEX_ITER_TAG);
+ JS_free(cx, ii);
+ }
+ *statep = JSVAL_NULL;
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+slowarray_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ JSBool ok;
+
+ /* Are we continuing an enumeration that started when we were dense? */
+ if (enum_op != JSENUMERATE_INIT) {
+ if (JSVAL_TAG(*statep) == JSVAL_BOOLEAN ||
+ (*statep & INDEX_ITER_TAG) == INDEX_ITER_TAG) {
+ return array_enumerate(cx, obj, enum_op, statep, idp);
+ }
+ JS_ASSERT((*statep & INDEX_ITER_TAG) == JSVAL_INT);
+ }
+ ok = js_Enumerate(cx, obj, enum_op, statep, idp);
+ JS_ASSERT(*statep == JSVAL_NULL || (*statep & INDEX_ITER_TAG) == JSVAL_INT);
+ return ok;
+}
+
+static void
+array_finalize(JSContext *cx, JSObject *obj)
+{
+ if (obj->dslots)
+ JS_free(cx, obj->dslots - 1);
+ obj->dslots = NULL;
+}
+
+static void
+array_trace(JSTracer *trc, JSObject *obj)
+{
+ uint32 length;
+ size_t i;
+ jsval v;
+
+ JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj));
+
+ length = ARRAY_DENSE_LENGTH(obj);
+ for (i = 0; i < length; i++) {
+ v = obj->dslots[i];
+ if (JSVAL_IS_TRACEABLE(v)) {
+ JS_SET_TRACING_INDEX(trc, "array_dslots", i);
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
+ }
+ }
+
+ for (i = JSSLOT_PROTO; i <= JSSLOT_PARENT; ++i) {
+ v = STOBJ_GET_SLOT(obj, i);
+ if (JSVAL_IS_TRACEABLE(v)) {
+ JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
+ }
+ }
+}
+
+static JSObjectMap *
+array_newObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp, JSObject *obj)
+{
+#ifdef DEBUG
+ extern JSClass js_ArrayClass;
+ extern JSObjectOps js_ArrayObjectOps;
+#endif
+ JSObjectMap *map = (JSObjectMap *) JS_malloc(cx, sizeof(*map));
+ if (!map)
+ return NULL;
+
+ map->nrefs = nrefs;
+ JS_ASSERT(ops == &js_ArrayObjectOps);
+ map->ops = ops;
+ JS_ASSERT(clasp == &js_ArrayClass);
+ map->freeslot = JSSLOT_FREE(clasp);
+
+ return map;
+}
+
+void
+array_destroyObjectMap(JSContext *cx, JSObjectMap *map)
+{
+ JS_free(cx, map);
+}
+
+JSObjectOps js_ArrayObjectOps = {
+ array_newObjectMap, array_destroyObjectMap,
+ array_lookupProperty, array_defineProperty,
+ array_getProperty, array_setProperty,
+ array_getAttributes, array_setAttributes,
+ array_deleteProperty, js_DefaultValue,
+ array_enumerate, js_CheckAccess,
+ NULL, array_dropProperty,
+ NULL, NULL,
+ NULL, js_HasInstance,
+ js_SetProtoOrParent, js_SetProtoOrParent,
+ array_trace, NULL,
+ NULL, NULL
+};
+
+static JSObjectOps *
+array_getObjectOps(JSContext *cx, JSClass *clasp)
+{
+ return &js_ArrayObjectOps;
+}
+
+JSClass js_ArrayClass = {
+ "Array",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
+ JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_NEW_ENUMERATE,
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, js_TryValueOf, array_finalize,
+ array_getObjectOps, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+JSClass js_SlowArrayClass = {
+ "Array",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
+ slowarray_addProperty, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, js_TryValueOf, JS_FinalizeStub,
+ slowarray_getObjectOps, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+/*
+ * Convert an array object from fast-and-dense to slow-and-flexible.
+ */
+JSBool
+js_MakeArraySlow(JSContext *cx, JSObject *obj)
+{
+ JSObjectMap *map, *oldmap;
+ uint32 i, length;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ArrayClass);
+
+ /* Create a native scope. */
+ map = js_NewObjectMap(cx, obj->map->nrefs, &js_SlowArrayObjectOps,
+ &js_SlowArrayClass, obj);
+ if (!map)
+ return JS_FALSE;
+
+ length = ARRAY_DENSE_LENGTH(obj);
+ if (length) {
+ map->freeslot = STOBJ_NSLOTS(obj) + JS_INITIAL_NSLOTS;
+ obj->dslots[-1] = JS_INITIAL_NSLOTS + length;
+ } else {
+ map->freeslot = STOBJ_NSLOTS(obj);
+ }
+
+ /* Create new properties pointing to existing values in dslots */
+ for (i = 0; i < length; i++) {
+ jsid id;
+ JSScopeProperty *sprop;
+
+ if (!JS_ValueToId(cx, INT_TO_JSVAL(i), &id))
+ goto out_bad;
+
+ if (obj->dslots[i] == JSVAL_HOLE) {
+ obj->dslots[i] = JSVAL_VOID;
+ continue;
+ }
+
+ sprop = js_AddScopeProperty(cx, (JSScope *)map, id, NULL, NULL,
+ i + JS_INITIAL_NSLOTS, JSPROP_ENUMERATE,
+ 0, 0);
+ if (!sprop)
+ goto out_bad;
+ }
+
+ /*
+ * Render our formerly-reserved count property GC-safe. If length fits in
+ * a jsval, set our slow/sparse COUNT to the current length as a jsval, so
+ * we can tell when only named properties have been added to a dense array
+ * to make it slow-but-not-sparse.
+ */
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ obj->fslots[JSSLOT_ARRAY_COUNT] = INT_FITS_IN_JSVAL(length)
+ ? INT_TO_JSVAL(length)
+ : JSVAL_VOID;
+
+ /* Make sure we preserve any flags borrowing bits in classword. */
+ obj->classword ^= (jsuword) &js_ArrayClass;
+ obj->classword |= (jsuword) &js_SlowArrayClass;
+
+ /* Swap in our new map. */
+ oldmap = obj->map;
+ obj->map = map;
+ array_destroyObjectMap(cx, oldmap);
+
+ return JS_TRUE;
+
+out_bad:
+ js_DestroyObjectMap(cx, map);
+ return JS_FALSE;
+}
+
+enum ArrayToStringOp {
+ TO_STRING,
+ TO_LOCALE_STRING,
+ TO_SOURCE
+};
+
+/*
+ * When op is TO_STRING or TO_LOCALE_STRING sep indicates a separator to use
+ * or "," when sep is NULL.
+ * When op is TO_SOURCE sep must be NULL.
+ */
+static JSBool
+array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op,
+ JSString *sep, jsval *rval)
+{
+ JSBool ok, hole;
+ jsuint length, index;
+ jschar *chars, *ochars;
+ size_t nchars, growth, seplen, tmplen, extratail;
+ const jschar *sepstr;
+ JSString *str;
+ JSHashEntry *he;
+ JSAtom *atom;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ ok = js_GetLengthProperty(cx, obj, &length);
+ if (!ok)
+ return JS_FALSE;
+
+ he = js_EnterSharpObject(cx, obj, NULL, &chars);
+ if (!he)
+ return JS_FALSE;
+#ifdef DEBUG
+ growth = (size_t) -1;
+#endif
+
+ if (op == TO_SOURCE) {
+ if (IS_SHARP(he)) {
+#if JS_HAS_SHARP_VARS
+ nchars = js_strlen(chars);
+#else
+ chars[0] = '[';
+ chars[1] = ']';
+ chars[2] = 0;
+ nchars = 2;
+#endif
+ goto make_string;
+ }
+
+ /*
+ * Always allocate 2 extra chars for closing ']' and terminating 0
+ * and then preallocate 1 + extratail to include starting '['.
+ */
+ extratail = 2;
+ growth = (1 + extratail) * sizeof(jschar);
+ if (!chars) {
+ nchars = 0;
+ chars = (jschar *) malloc(growth);
+ if (!chars)
+ goto done;
+ } else {
+ MAKE_SHARP(he);
+ nchars = js_strlen(chars);
+ growth += nchars * sizeof(jschar);
+ chars = (jschar *)realloc((ochars = chars), growth);
+ if (!chars) {
+ free(ochars);
+ goto done;
+ }
+ }
+ chars[nchars++] = '[';
+ JS_ASSERT(sep == NULL);
+ sepstr = NULL; /* indicates to use ", " as separator */
+ seplen = 2;
+ } else {
+ /*
+ * Free any sharp variable definition in chars. Normally, we would
+ * MAKE_SHARP(he) so that only the first sharp variable annotation is
+ * a definition, and all the rest are references, but in the current
+ * case of (op != TO_SOURCE), we don't need chars at all.
+ */
+ if (chars)
+ JS_free(cx, chars);
+ chars = NULL;
+ nchars = 0;
+ extratail = 1; /* allocate extra char for terminating 0 */
+
+ /* Return the empty string on a cycle as well as on empty join. */
+ if (IS_BUSY(he) || length == 0) {
+ js_LeaveSharpObject(cx, NULL);
+ *rval = JS_GetEmptyStringValue(cx);
+ return ok;
+ }
+
+ /* Flag he as BUSY so we can distinguish a cycle from a join-point. */
+ MAKE_BUSY(he);
+
+ if (sep) {
+ JSSTRING_CHARS_AND_LENGTH(sep, sepstr, seplen);
+ } else {
+ sepstr = NULL; /* indicates to use "," as separator */
+ seplen = 1;
+ }
+ }
+
+ /* Use rval to locally root each element value as we loop and convert. */
+ for (index = 0; index < length; index++) {
+ ok = (JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, index, &hole, rval));
+ if (!ok)
+ goto done;
+ if (hole ||
+ (op != TO_SOURCE &&
+ (JSVAL_IS_VOID(*rval) || JSVAL_IS_NULL(*rval)))) {
+ str = cx->runtime->emptyString;
+ } else {
+ if (op == TO_LOCALE_STRING) {
+ JSObject *robj;
+
+ atom = cx->runtime->atomState.toLocaleStringAtom;
+ ok = js_ValueToObject(cx, *rval, &robj);
+ if (ok) {
+ /* Re-use *rval to protect robj temporarily. */
+ *rval = OBJECT_TO_JSVAL(robj);
+ ok = js_TryMethod(cx, robj, atom, 0, NULL, rval);
+ }
+ if (!ok)
+ goto done;
+ str = js_ValueToString(cx, *rval);
+ } else if (op == TO_STRING) {
+ str = js_ValueToString(cx, *rval);
+ } else {
+ JS_ASSERT(op == TO_SOURCE);
+ str = js_ValueToSource(cx, *rval);
+ }
+ if (!str) {
+ ok = JS_FALSE;
+ goto done;
+ }
+ }
+
+ /*
+ * Do not append separator after the last element unless it is a hole
+ * and we are in toSource. In that case we append single ",".
+ */
+ if (index + 1 == length)
+ seplen = (hole && op == TO_SOURCE) ? 1 : 0;
+
+ /* Allocate 1 at end for closing bracket and zero. */
+ tmplen = JSSTRING_LENGTH(str);
+ growth = nchars + tmplen + seplen + extratail;
+ if (nchars > growth || tmplen > growth ||
+ growth > (size_t)-1 / sizeof(jschar)) {
+ if (chars) {
+ free(chars);
+ chars = NULL;
+ }
+ goto done;
+ }
+ growth *= sizeof(jschar);
+ JS_COUNT_OPERATION(cx, JSOW_ALLOCATION);
+ if (!chars) {
+ chars = (jschar *) malloc(growth);
+ if (!chars)
+ goto done;
+ } else {
+ chars = (jschar *) realloc((ochars = chars), growth);
+ if (!chars) {
+ free(ochars);
+ goto done;
+ }
+ }
+
+ js_strncpy(&chars[nchars], JSSTRING_CHARS(str), tmplen);
+ nchars += tmplen;
+
+ if (seplen) {
+ if (sepstr) {
+ js_strncpy(&chars[nchars], sepstr, seplen);
+ } else {
+ JS_ASSERT(seplen == 1 || seplen == 2);
+ chars[nchars] = ',';
+ if (seplen == 2)
+ chars[nchars + 1] = ' ';
+ }
+ nchars += seplen;
+ }
+ }
+
+ done:
+ if (op == TO_SOURCE) {
+ if (chars)
+ chars[nchars++] = ']';
+ } else {
+ CLEAR_BUSY(he);
+ }
+ js_LeaveSharpObject(cx, NULL);
+ if (!ok) {
+ if (chars)
+ free(chars);
+ return ok;
+ }
+
+ make_string:
+ if (!chars) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ chars[nchars] = 0;
+ JS_ASSERT(growth == (size_t)-1 || (nchars + 1) * sizeof(jschar) == growth);
+ str = js_NewString(cx, chars, nchars);
+ if (!str) {
+ free(chars);
+ return JS_FALSE;
+ }
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+array_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (OBJ_GET_CLASS(cx, obj) != &js_SlowArrayClass &&
+ !JS_InstanceOf(cx, obj, &js_ArrayClass, vp + 2)) {
+ return JS_FALSE;
+ }
+ return array_join_sub(cx, obj, TO_SOURCE, NULL, vp);
+}
+#endif
+
+static JSBool
+array_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (OBJ_GET_CLASS(cx, obj) != &js_SlowArrayClass &&
+ !JS_InstanceOf(cx, obj, &js_ArrayClass, vp + 2)) {
+ return JS_FALSE;
+ }
+ return array_join_sub(cx, obj, TO_STRING, NULL, vp);
+}
+
+static JSBool
+array_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (OBJ_GET_CLASS(cx, obj) != &js_SlowArrayClass &&
+ !JS_InstanceOf(cx, obj, &js_ArrayClass, vp + 2)) {
+ return JS_FALSE;
+ }
+
+ /*
+ * Passing comma here as the separator. Need a way to get a
+ * locale-specific version.
+ */
+ return array_join_sub(cx, obj, TO_LOCALE_STRING, NULL, vp);
+}
+
+static JSBool
+InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint end,
+ jsval *vector)
+{
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ if (!EnsureLength(cx, obj, end))
+ return JS_FALSE;
+
+ if (end > (uint32)obj->fslots[JSSLOT_ARRAY_LENGTH])
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = end;
+
+ memcpy(obj->dslots + start, vector, sizeof(jsval) * (end - start));
+ return JS_TRUE;
+ }
+
+ while (start != end) {
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) ||
+ !SetArrayElement(cx, obj, start++, *vector++)) {
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, jsval *vector,
+ JSBool holey = JS_FALSE)
+{
+ JS_ASSERT(OBJ_IS_ARRAY(cx, obj));
+
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = length;
+
+ if (vector) {
+ if (!EnsureLength(cx, obj, length))
+ return JS_FALSE;
+
+ jsuint count = length;
+ if (!holey) {
+ memcpy(obj->dslots, vector, length * sizeof (jsval));
+ } else {
+ for (jsuint i = 0; i < length; i++) {
+ if (vector[i] == JSVAL_HOLE)
+ --count;
+ obj->dslots[i] = vector[i];
+ }
+ }
+ obj->fslots[JSSLOT_ARRAY_COUNT] = count;
+ } else {
+ obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
+ }
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static JSString* FASTCALL
+Array_p_join(JSContext* cx, JSObject* obj, JSString *str)
+{
+ jsval v;
+ if (!array_join_sub(cx, obj, TO_STRING, str, &v))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ return JSVAL_TO_STRING(v);
+}
+
+static JSString* FASTCALL
+Array_p_toString(JSContext* cx, JSObject* obj)
+{
+ jsval v;
+ if (!array_join_sub(cx, obj, TO_STRING, NULL, &v))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ return JSVAL_TO_STRING(v);
+}
+#endif
+
+/*
+ * Perl-inspired join, reverse, and sort.
+ */
+static JSBool
+array_join(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ JSObject *obj;
+
+ if (argc == 0 || JSVAL_IS_VOID(vp[2])) {
+ str = NULL;
+ } else {
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(str);
+ }
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && array_join_sub(cx, obj, TO_STRING, str, vp);
+}
+
+static JSBool
+array_reverse(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ JSTempValueRooter tvr;
+ jsuint len, half, i;
+ JSBool ok, hole, hole2;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &len))
+ return JS_FALSE;
+
+ ok = JS_TRUE;
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ half = len / 2;
+ for (i = 0; i < half; i++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, i, &hole, &tvr.u.value) &&
+ GetArrayElement(cx, obj, len - i - 1, &hole2, vp) &&
+ SetOrDeleteArrayElement(cx, obj, len - i - 1, hole, tvr.u.value) &&
+ SetOrDeleteArrayElement(cx, obj, i, hole2, *vp);
+ if (!ok)
+ break;
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+
+ *vp = OBJECT_TO_JSVAL(obj);
+ return ok;
+}
+
+typedef struct MSortArgs {
+ size_t elsize;
+ JSComparator cmp;
+ void *arg;
+ JSBool fastcopy;
+} MSortArgs;
+
+/* Helper function for js_MergeSort. */
+static JSBool
+MergeArrays(MSortArgs *msa, void *src, void *dest, size_t run1, size_t run2)
+{
+ void *arg, *a, *b, *c;
+ size_t elsize, runtotal;
+ int cmp_result;
+ JSComparator cmp;
+ JSBool fastcopy;
+
+ runtotal = run1 + run2;
+
+ elsize = msa->elsize;
+ cmp = msa->cmp;
+ arg = msa->arg;
+ fastcopy = msa->fastcopy;
+
+#define CALL_CMP(a, b) \
+ if (!cmp(arg, (a), (b), &cmp_result)) return JS_FALSE;
+
+ /* Copy runs already in sorted order. */
+ b = (char *)src + run1 * elsize;
+ a = (char *)b - elsize;
+ CALL_CMP(a, b);
+ if (cmp_result <= 0) {
+ memcpy(dest, src, runtotal * elsize);
+ return JS_TRUE;
+ }
+
+#define COPY_ONE(p,q,n) \
+ (fastcopy ? (void)(*(jsval*)(p) = *(jsval*)(q)) : (void)memcpy(p, q, n))
+
+ a = src;
+ c = dest;
+ for (; runtotal != 0; runtotal--) {
+ JSBool from_a = run2 == 0;
+ if (!from_a && run1 != 0) {
+ CALL_CMP(a,b);
+ from_a = cmp_result <= 0;
+ }
+
+ if (from_a) {
+ COPY_ONE(c, a, elsize);
+ run1--;
+ a = (char *)a + elsize;
+ } else {
+ COPY_ONE(c, b, elsize);
+ run2--;
+ b = (char *)b + elsize;
+ }
+ c = (char *)c + elsize;
+ }
+#undef COPY_ONE
+#undef CALL_CMP
+
+ return JS_TRUE;
+}
+
+/*
+ * This sort is stable, i.e. sequence of equal elements is preserved.
+ * See also bug #224128.
+ */
+JSBool
+js_MergeSort(void *src, size_t nel, size_t elsize,
+ JSComparator cmp, void *arg, void *tmp)
+{
+ void *swap, *vec1, *vec2;
+ MSortArgs msa;
+ size_t i, j, lo, hi, run;
+ JSBool fastcopy;
+ int cmp_result;
+
+ /* Avoid memcpy overhead for word-sized and word-aligned elements. */
+ fastcopy = (elsize == sizeof(jsval) &&
+ (((jsuword) src | (jsuword) tmp) & JSVAL_ALIGN) == 0);
+#define COPY_ONE(p,q,n) \
+ (fastcopy ? (void)(*(jsval*)(p) = *(jsval*)(q)) : (void)memcpy(p, q, n))
+#define CALL_CMP(a, b) \
+ if (!cmp(arg, (a), (b), &cmp_result)) return JS_FALSE;
+#define INS_SORT_INT 4
+
+ /*
+ * Apply insertion sort to small chunks to reduce the number of merge
+ * passes needed.
+ */
+ for (lo = 0; lo < nel; lo += INS_SORT_INT) {
+ hi = lo + INS_SORT_INT;
+ if (hi >= nel)
+ hi = nel;
+ for (i = lo + 1; i < hi; i++) {
+ vec1 = (char *)src + i * elsize;
+ vec2 = (char *)vec1 - elsize;
+ for (j = i; j > lo; j--) {
+ CALL_CMP(vec2, vec1);
+ /* "<=" instead of "<" insures the sort is stable */
+ if (cmp_result <= 0) {
+ break;
+ }
+
+ /* Swap elements, using "tmp" as tmp storage */
+ COPY_ONE(tmp, vec2, elsize);
+ COPY_ONE(vec2, vec1, elsize);
+ COPY_ONE(vec1, tmp, elsize);
+ vec1 = vec2;
+ vec2 = (char *)vec1 - elsize;
+ }
+ }
+ }
+#undef CALL_CMP
+#undef COPY_ONE
+
+ msa.elsize = elsize;
+ msa.cmp = cmp;
+ msa.arg = arg;
+ msa.fastcopy = fastcopy;
+
+ vec1 = src;
+ vec2 = tmp;
+ for (run = INS_SORT_INT; run < nel; run *= 2) {
+ for (lo = 0; lo < nel; lo += 2 * run) {
+ hi = lo + run;
+ if (hi >= nel) {
+ memcpy((char *)vec2 + lo * elsize, (char *)vec1 + lo * elsize,
+ (nel - lo) * elsize);
+ break;
+ }
+ if (!MergeArrays(&msa, (char *)vec1 + lo * elsize,
+ (char *)vec2 + lo * elsize, run,
+ hi + run > nel ? nel - hi : run)) {
+ return JS_FALSE;
+ }
+ }
+ swap = vec1;
+ vec1 = vec2;
+ vec2 = swap;
+ }
+ if (src != vec1)
+ memcpy(src, tmp, nel * elsize);
+
+ return JS_TRUE;
+}
+
+typedef struct CompareArgs {
+ JSContext *context;
+ jsval fval;
+ jsval *elemroot; /* stack needed for js_Invoke */
+} CompareArgs;
+
+static JSBool
+sort_compare(void *arg, const void *a, const void *b, int *result)
+{
+ jsval av = *(const jsval *)a, bv = *(const jsval *)b;
+ CompareArgs *ca = (CompareArgs *) arg;
+ JSContext *cx = ca->context;
+ jsval *invokevp, *sp;
+ jsdouble cmp;
+
+ /**
+ * array_sort deals with holes and undefs on its own and they should not
+ * come here.
+ */
+ JS_ASSERT(!JSVAL_IS_VOID(av));
+ JS_ASSERT(!JSVAL_IS_VOID(bv));
+
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP))
+ return JS_FALSE;
+
+ invokevp = ca->elemroot;
+ sp = invokevp;
+ *sp++ = ca->fval;
+ *sp++ = JSVAL_NULL;
+ *sp++ = av;
+ *sp++ = bv;
+
+ if (!js_Invoke(cx, 2, invokevp, 0))
+ return JS_FALSE;
+
+ cmp = js_ValueToNumber(cx, invokevp);
+ if (JSVAL_IS_NULL(*invokevp))
+ return JS_FALSE;
+
+ /* Clamp cmp to -1, 0, 1. */
+ *result = 0;
+ if (!JSDOUBLE_IS_NaN(cmp) && cmp != 0)
+ *result = cmp > 0 ? 1 : -1;
+
+ /*
+ * XXX else report some kind of error here? ECMA talks about 'consistent
+ * compare functions' that don't return NaN, but is silent about what the
+ * result should be. So we currently ignore it.
+ */
+
+ return JS_TRUE;
+}
+
+static int
+sort_compare_strings(void *arg, const void *a, const void *b, int *result)
+{
+ jsval av = *(const jsval *)a, bv = *(const jsval *)b;
+
+ JS_ASSERT(JSVAL_IS_STRING(av));
+ JS_ASSERT(JSVAL_IS_STRING(bv));
+ if (!JS_CHECK_OPERATION_LIMIT((JSContext *)arg, JSOW_JUMP))
+ return JS_FALSE;
+
+ *result = (int) js_CompareStrings(JSVAL_TO_STRING(av), JSVAL_TO_STRING(bv));
+ return JS_TRUE;
+}
+
+/*
+ * The array_sort function below assumes JSVAL_NULL is zero in order to
+ * perform initialization using memset. Other parts of SpiderMonkey likewise
+ * "know" that JSVAL_NULL is zero; this static assertion covers all cases.
+ */
+JS_STATIC_ASSERT(JSVAL_NULL == 0);
+
+static JSBool
+array_sort(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv, fval, *vec, *mergesort_tmp, v;
+ JSObject *obj;
+ CompareArgs ca;
+ jsuint len, newlen, i, undefs;
+ JSTempValueRooter tvr;
+ JSBool hole;
+ bool ok;
+ size_t elemsize;
+ JSString *str;
+
+ /*
+ * Optimize the default compare function case if all of obj's elements
+ * have values of type string.
+ */
+ JSBool all_strings;
+
+ argv = JS_ARGV(cx, vp);
+ if (argc > 0) {
+ if (JSVAL_IS_PRIMITIVE(argv[0])) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_SORT_ARG);
+ return JS_FALSE;
+ }
+ fval = argv[0]; /* non-default compare function */
+ } else {
+ fval = JSVAL_NULL;
+ }
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &len))
+ return JS_FALSE;
+ if (len == 0) {
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+ }
+
+ /*
+ * We need a temporary array of 2 * len jsvals to hold the array elements
+ * and the scratch space for merge sort. Check that its size does not
+ * overflow size_t, which would allow for indexing beyond the end of the
+ * malloc'd vector.
+ */
+#if JS_BITS_PER_WORD == 32
+ if ((size_t)len > ~(size_t)0 / (2 * sizeof(jsval))) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+#endif
+ vec = (jsval *) JS_malloc(cx, 2 * (size_t) len * sizeof(jsval));
+ if (!vec)
+ return JS_FALSE;
+
+ /*
+ * Initialize vec as a root. We will clear elements of vec one by
+ * one while increasing tvr.count when we know that the property at
+ * the corresponding index exists and its value must be rooted.
+ *
+ * In this way when sorting a huge mostly sparse array we will not
+ * access the tail of vec corresponding to properties that do not
+ * exist, allowing OS to avoiding committing RAM. See bug 330812.
+ *
+ * After this point control must flow through label out: to exit.
+ */
+ JS_PUSH_TEMP_ROOT(cx, 0, vec, &tvr);
+
+ /*
+ * By ECMA 262, 15.4.4.11, a property that does not exist (which we
+ * call a "hole") is always greater than an existing property with
+ * value undefined and that is always greater than any other property.
+ * Thus to sort holes and undefs we simply count them, sort the rest
+ * of elements, append undefs after them and then make holes after
+ * undefs.
+ */
+ undefs = 0;
+ newlen = 0;
+ all_strings = JS_TRUE;
+ for (i = 0; i < len; i++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP);
+ if (!ok)
+ goto out;
+
+ /* Clear vec[newlen] before including it in the rooted set. */
+ vec[newlen] = JSVAL_NULL;
+ tvr.count = newlen + 1;
+ ok = GetArrayElement(cx, obj, i, &hole, &vec[newlen]);
+ if (!ok)
+ goto out;
+
+ if (hole)
+ continue;
+
+ if (JSVAL_IS_VOID(vec[newlen])) {
+ ++undefs;
+ continue;
+ }
+
+ /* We know JSVAL_IS_STRING yields 0 or 1, so avoid a branch via &=. */
+ all_strings &= JSVAL_IS_STRING(vec[newlen]);
+
+ ++newlen;
+ }
+
+ if (newlen == 0) {
+ /* The array has only holes and undefs. */
+ ok = JS_TRUE;
+ goto out;
+ }
+
+ /*
+ * The first newlen elements of vec are copied from the array object
+ * (above). The remaining newlen positions are used as GC-rooted scratch
+ * space for mergesort. We must clear the space before including it to
+ * the root set covered by tvr.count. We assume JSVAL_NULL==0 to optimize
+ * initialization using memset.
+ */
+ mergesort_tmp = vec + newlen;
+ memset(mergesort_tmp, 0, newlen * sizeof(jsval));
+ tvr.count = newlen * 2;
+
+ /* Here len == 2 * (newlen + undefs + number_of_holes). */
+ if (fval == JSVAL_NULL) {
+ /*
+ * Sort using the default comparator converting all elements to
+ * strings.
+ */
+ if (all_strings) {
+ elemsize = sizeof(jsval);
+ } else {
+ /*
+ * To avoid string conversion on each compare we do it only once
+ * prior to sorting. But we also need the space for the original
+ * values to recover the sorting result. To reuse
+ * sort_compare_strings we move the original values to the odd
+ * indexes in vec, put the string conversion results in the even
+ * indexes and pass 2 * sizeof(jsval) as an element size to the
+ * sorting function. In this way sort_compare_strings will only
+ * see the string values when it casts the compare arguments as
+ * pointers to jsval.
+ *
+ * This requires doubling the temporary storage including the
+ * scratch space for the merge sort. Since vec already contains
+ * the rooted scratch space for newlen elements at the tail, we
+ * can use it to rearrange and convert to strings first and try
+ * realloc only when we know that we successfully converted all
+ * the elements.
+ */
+#if JS_BITS_PER_WORD == 32
+ if ((size_t)newlen > ~(size_t)0 / (4 * sizeof(jsval))) {
+ js_ReportAllocationOverflow(cx);
+ ok = JS_FALSE;
+ goto out;
+ }
+#endif
+
+ /*
+ * Rearrange and string-convert the elements of the vector from
+ * the tail here and, after sorting, move the results back
+ * starting from the start to prevent overwrite the existing
+ * elements.
+ */
+ i = newlen;
+ do {
+ --i;
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP);
+ if (!ok)
+ goto out;
+ v = vec[i];
+ str = js_ValueToString(cx, v);
+ if (!str) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ vec[2 * i] = STRING_TO_JSVAL(str);
+ vec[2 * i + 1] = v;
+ } while (i != 0);
+
+ JS_ASSERT(tvr.u.array == vec);
+ vec = (jsval *) JS_realloc(cx, vec,
+ 4 * (size_t) newlen * sizeof(jsval));
+ if (!vec) {
+ vec = tvr.u.array;
+ ok = JS_FALSE;
+ goto out;
+ }
+ tvr.u.array = vec;
+ mergesort_tmp = vec + 2 * newlen;
+ memset(mergesort_tmp, 0, newlen * 2 * sizeof(jsval));
+ tvr.count = newlen * 4;
+ elemsize = 2 * sizeof(jsval);
+ }
+ ok = js_MergeSort(vec, (size_t) newlen, elemsize,
+ sort_compare_strings, cx, mergesort_tmp);
+ if (!ok)
+ goto out;
+ if (!all_strings) {
+ /*
+ * We want to make the following loop fast and to unroot the
+ * cached results of toString invocations before the operation
+ * callback has a chance to run the GC. For this reason we do
+ * not call JS_CHECK_OPERATION_LIMIT in the loop.
+ */
+ i = 0;
+ do {
+ vec[i] = vec[2 * i + 1];
+ } while (++i != newlen);
+ }
+ } else {
+ void *mark;
+
+ ca.context = cx;
+ ca.fval = fval;
+ ca.elemroot = js_AllocStack(cx, 2 + 2, &mark);
+ if (!ca.elemroot) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ ok = js_MergeSort(vec, (size_t) newlen, sizeof(jsval),
+ sort_compare, &ca, mergesort_tmp);
+ js_FreeStack(cx, mark);
+ if (!ok)
+ goto out;
+ }
+
+ /*
+ * We no longer need to root the scratch space for the merge sort, so
+ * unroot it now to make the job of a potential GC under InitArrayElements
+ * easier.
+ */
+ tvr.count = newlen;
+ ok = InitArrayElements(cx, obj, 0, newlen, vec);
+ if (!ok)
+ goto out;
+
+ out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ JS_free(cx, vec);
+ if (!ok)
+ return JS_FALSE;
+
+ /* Set undefs that sorted after the rest of elements. */
+ while (undefs != 0) {
+ --undefs;
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) ||
+ !SetArrayElement(cx, obj, newlen++, JSVAL_VOID)) {
+ return JS_FALSE;
+ }
+ }
+
+ /* Re-create any holes that sorted to the end of the array. */
+ while (len > newlen) {
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) ||
+ !DeleteArrayElement(cx, obj, --len)) {
+ return JS_FALSE;
+ }
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+/*
+ * Perl-inspired push, pop, shift, unshift, and splice methods.
+ */
+static JSBool
+array_push_slowly(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsuint length, newlength;
+
+ if (!js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ newlength = length + argc;
+ if (!InitArrayElements(cx, obj, length, newlength, argv))
+ return JS_FALSE;
+
+ /* Per ECMA-262, return the new array length. */
+ if (!IndexToValue(cx, newlength, rval))
+ return JS_FALSE;
+ return js_SetLengthProperty(cx, obj, newlength);
+}
+
+static JSBool
+array_push1_dense(JSContext* cx, JSObject* obj, jsval v, jsval *rval)
+{
+ uint32 length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (INDEX_TOO_SPARSE(obj, length)) {
+ if (!js_MakeArraySlow(cx, obj))
+ return JS_FALSE;
+ return array_push_slowly(cx, obj, 1, &v, rval);
+ }
+
+ if (!EnsureLength(cx, obj, length + 1))
+ return JS_FALSE;
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = length + 1;
+
+ JS_ASSERT(obj->dslots[length] == JSVAL_HOLE);
+ obj->fslots[JSSLOT_ARRAY_COUNT]++;
+ obj->dslots[length] = v;
+ return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], rval);
+}
+
+#ifdef JS_TRACER
+static jsval FASTCALL
+Array_p_push1(JSContext* cx, JSObject* obj, jsval v)
+{
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)
+ ? array_push1_dense(cx, obj, v, &v)
+ : array_push_slowly(cx, obj, 1, &v, &v)) {
+ return v;
+ }
+ return JSVAL_ERROR_COOKIE;
+}
+#endif
+
+static JSBool
+array_push(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ /* Insist on one argument and obj of the expected class. */
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ if (argc != 1 || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return array_push_slowly(cx, obj, argc, vp + 2, vp);
+
+ return array_push1_dense(cx, obj, vp[2], vp);
+}
+
+static JSBool
+array_pop_slowly(JSContext *cx, JSObject* obj, jsval *vp)
+{
+ jsuint index;
+ JSBool hole;
+
+ if (!js_GetLengthProperty(cx, obj, &index))
+ return JS_FALSE;
+ if (index == 0) {
+ *vp = JSVAL_VOID;
+ } else {
+ index--;
+
+ /* Get the to-be-deleted property's value into vp. */
+ if (!GetArrayElement(cx, obj, index, &hole, vp))
+ return JS_FALSE;
+ if (!hole && !DeleteArrayElement(cx, obj, index))
+ return JS_FALSE;
+ }
+ return js_SetLengthProperty(cx, obj, index);
+}
+
+static JSBool
+array_pop_dense(JSContext *cx, JSObject* obj, jsval *vp)
+{
+ jsuint index;
+ JSBool hole;
+
+ index = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (index == 0) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ index--;
+ if (!GetArrayElement(cx, obj, index, &hole, vp))
+ return JS_FALSE;
+ if (!hole && !DeleteArrayElement(cx, obj, index))
+ return JS_FALSE;
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = index;
+ return JS_TRUE;
+
+}
+
+#ifdef JS_TRACER
+static jsval FASTCALL
+Array_p_pop(JSContext* cx, JSObject* obj)
+{
+ jsval v;
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)
+ ? array_pop_dense(cx, obj, &v)
+ : array_pop_slowly(cx, obj, &v)) {
+ return v;
+ }
+ return JSVAL_ERROR_COOKIE;
+}
+#endif
+
+static JSBool
+array_pop(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ if (OBJ_IS_DENSE_ARRAY(cx, obj))
+ return array_pop_dense(cx, obj, vp);
+ return array_pop_slowly(cx, obj, vp);
+}
+
+static JSBool
+array_shift(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsuint length, i;
+ JSBool hole, ok;
+ JSTempValueRooter tvr;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ if (length == 0) {
+ *vp = JSVAL_VOID;
+ } else {
+ length--;
+
+ /* Get the to-be-deleted property's value into vp ASAP. */
+ if (!GetArrayElement(cx, obj, 0, &hole, vp))
+ return JS_FALSE;
+
+ /* Slide down the array above the first element. */
+ ok = JS_TRUE;
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ for (i = 0; i != length; i++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, i + 1, &hole, &tvr.u.value) &&
+ SetOrDeleteArrayElement(cx, obj, i, hole, tvr.u.value);
+ if (!ok)
+ break;
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+
+ /* Delete the only or last element when it exist. */
+ if (!hole && !DeleteArrayElement(cx, obj, length))
+ return JS_FALSE;
+ }
+ return js_SetLengthProperty(cx, obj, length);
+}
+
+static JSBool
+array_unshift(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval *argv;
+ jsuint length, last;
+ JSBool hole, ok;
+ JSTempValueRooter tvr;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ if (argc > 0) {
+ /* Slide up the array to make room for argc at the bottom. */
+ argv = JS_ARGV(cx, vp);
+ if (length > 0) {
+ last = length;
+ ok = JS_TRUE;
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ do {
+ --last;
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, last, &hole, &tvr.u.value) &&
+ SetOrDeleteArrayElement(cx, obj, last + argc, hole,
+ tvr.u.value);
+ if (!ok)
+ break;
+ } while (last != 0);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+ }
+
+ /* Copy from argv to the bottom of the array. */
+ if (!InitArrayElements(cx, obj, 0, argc, argv))
+ return JS_FALSE;
+
+ length += argc;
+ if (!js_SetLengthProperty(cx, obj, length))
+ return JS_FALSE;
+ }
+
+ /* Follow Perl by returning the new array length. */
+ return IndexToValue(cx, length, vp);
+}
+
+static JSBool
+array_splice(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv;
+ JSObject *obj;
+ jsuint length, begin, end, count, delta, last;
+ jsdouble d;
+ JSBool hole, ok;
+ JSObject *obj2;
+ JSTempValueRooter tvr;
+
+ /*
+ * Create a new array value to return. Our ECMA v2 proposal specs
+ * that splice always returns an array value, even when given no
+ * arguments. We think this is best because it eliminates the need
+ * for callers to do an extra test to handle the empty splice case.
+ */
+ obj2 = js_NewArrayObject(cx, 0, NULL);
+ if (!obj2)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(obj2);
+
+ /* Nothing to do if no args. Otherwise get length. */
+ if (argc == 0)
+ return JS_TRUE;
+ argv = JS_ARGV(cx, vp);
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+
+ /* Convert the first argument into a starting index. */
+ d = js_ValueToNumber(cx, argv);
+ if (JSVAL_IS_NULL(*argv))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ if (d < 0) {
+ d += length;
+ if (d < 0)
+ d = 0;
+ } else if (d > length) {
+ d = length;
+ }
+ begin = (jsuint)d; /* d has been clamped to uint32 */
+ argc--;
+ argv++;
+
+ /* Convert the second argument from a count into a fencepost index. */
+ delta = length - begin;
+ if (argc == 0) {
+ count = delta;
+ end = length;
+ } else {
+ d = js_ValueToNumber(cx, argv);
+ if (JSVAL_IS_NULL(*argv))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ if (d < 0)
+ d = 0;
+ else if (d > delta)
+ d = delta;
+ count = (jsuint)d;
+ end = begin + count;
+ argc--;
+ argv++;
+ }
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+
+ /* If there are elements to remove, put them into the return value. */
+ if (count > 0) {
+ for (last = begin; last < end; last++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, last, &hole, &tvr.u.value);
+ if (!ok)
+ goto out;
+
+ /* Copy tvr.u.value to new array unless it's a hole. */
+ if (!hole) {
+ ok = SetArrayElement(cx, obj2, last - begin, tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ }
+
+ ok = js_SetLengthProperty(cx, obj2, end - begin);
+ if (!ok)
+ goto out;
+ }
+
+ /* Find the direction (up or down) to copy and make way for argv. */
+ if (argc > count) {
+ delta = (jsuint)argc - count;
+ last = length;
+ /* (uint) end could be 0, so can't use vanilla >= test */
+ while (last-- > end) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, last, &hole, &tvr.u.value) &&
+ SetOrDeleteArrayElement(cx, obj, last + delta, hole,
+ tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ length += delta;
+ } else if (argc < count) {
+ delta = count - (jsuint)argc;
+ for (last = end; last < length; last++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, last, &hole, &tvr.u.value) &&
+ SetOrDeleteArrayElement(cx, obj, last - delta, hole,
+ tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ length -= delta;
+ }
+
+ /* Copy from argv into the hole to complete the splice. */
+ ok = InitArrayElements(cx, obj, begin, begin + argc, argv);
+ if (!ok)
+ goto out;
+
+ /* Update length in case we deleted elements from the end. */
+ ok = js_SetLengthProperty(cx, obj, length);
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+/*
+ * Python-esque sequence operations.
+ */
+static JSBool
+array_concat(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv, v;
+ JSObject *aobj, *nobj;
+ jsuint length, alength, slot;
+ uintN i;
+ JSBool hole, ok;
+ JSTempValueRooter tvr;
+
+ /* Treat our |this| object as the first argument; see ECMA 15.4.4.4. */
+ argv = JS_ARGV(cx, vp) - 1;
+ JS_ASSERT(JS_THIS_OBJECT(cx, vp) == JSVAL_TO_OBJECT(argv[0]));
+
+ /* Create a new Array object and root it using *vp. */
+ aobj = JS_THIS_OBJECT(cx, vp);
+ if (OBJ_IS_DENSE_ARRAY(cx, aobj)) {
+ /*
+ * Clone aobj but pass the minimum of its length and capacity (aka
+ * "dense length"), to handle a = [1,2,3]; a.length = 10000 "dense"
+ * cases efficiently. In such a case we'll pass 8 (not 3) due to the
+ * ARRAY_GROWBY over-allocation policy, which will cause nobj to be
+ * over-allocated to 16. But in the normal case where length is <=
+ * capacity, nobj and aobj will have the same dense length.
+ */
+ length = aobj->fslots[JSSLOT_ARRAY_LENGTH];
+ jsuint capacity = ARRAY_DENSE_LENGTH(aobj);
+ nobj = js_NewArrayObject(cx, JS_MIN(length, capacity), aobj->dslots,
+ aobj->fslots[JSSLOT_ARRAY_COUNT] !=
+ (jsval) length);
+ if (!nobj)
+ return JS_FALSE;
+ nobj->fslots[JSSLOT_ARRAY_LENGTH] = length;
+ *vp = OBJECT_TO_JSVAL(nobj);
+ if (argc == 0)
+ return JS_TRUE;
+ argc--;
+ argv++;
+ } else {
+ nobj = js_NewArrayObject(cx, 0, NULL);
+ if (!nobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(nobj);
+ length = 0;
+ }
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+
+ /* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */
+ for (i = 0; i <= argc; i++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP);
+ if (!ok)
+ goto out;
+ v = argv[i];
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ JSObject *wobj;
+
+ aobj = JSVAL_TO_OBJECT(v);
+ wobj = js_GetWrappedObject(cx, aobj);
+ if (OBJ_IS_ARRAY(cx, wobj)) {
+ ok = OBJ_GET_PROPERTY(cx, aobj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .lengthAtom),
+ &tvr.u.value);
+ if (!ok)
+ goto out;
+ alength = ValueIsLength(cx, &tvr.u.value);
+ ok = !JSVAL_IS_NULL(tvr.u.value);
+ if (!ok)
+ goto out;
+ for (slot = 0; slot < alength; slot++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, aobj, slot, &hole,
+ &tvr.u.value);
+ if (!ok)
+ goto out;
+
+ /*
+ * Per ECMA 262, 15.4.4.4, step 9, ignore non-existent
+ * properties.
+ */
+ if (!hole) {
+ ok = SetArrayElement(cx, nobj, length + slot,
+ tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ }
+ length += alength;
+ continue;
+ }
+ }
+
+ ok = SetArrayElement(cx, nobj, length, v);
+ if (!ok)
+ goto out;
+ length++;
+ }
+
+ ok = js_SetLengthProperty(cx, nobj, length);
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSBool
+array_slice(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv;
+ JSObject *nobj, *obj;
+ jsuint length, begin, end, slot;
+ jsdouble d;
+ JSBool hole, ok;
+ JSTempValueRooter tvr;
+
+ argv = JS_ARGV(cx, vp);
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ begin = 0;
+ end = length;
+
+ if (argc > 0) {
+ d = js_ValueToNumber(cx, &argv[0]);
+ if (JSVAL_IS_NULL(argv[0]))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ if (d < 0) {
+ d += length;
+ if (d < 0)
+ d = 0;
+ } else if (d > length) {
+ d = length;
+ }
+ begin = (jsuint)d;
+
+ if (argc > 1) {
+ d = js_ValueToNumber(cx, &argv[1]);
+ if (JSVAL_IS_NULL(argv[1]))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ if (d < 0) {
+ d += length;
+ if (d < 0)
+ d = 0;
+ } else if (d > length) {
+ d = length;
+ }
+ end = (jsuint)d;
+ }
+ }
+
+ if (begin > end)
+ begin = end;
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj) && end <= ARRAY_DENSE_LENGTH(obj)) {
+ nobj = js_NewArrayObject(cx, end - begin, obj->dslots + begin,
+ obj->fslots[JSSLOT_ARRAY_COUNT] !=
+ obj->fslots[JSSLOT_ARRAY_LENGTH]);
+ if (!nobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(nobj);
+ return JS_TRUE;
+ }
+
+ /* Create a new Array object and root it using *vp. */
+ nobj = js_NewArrayObject(cx, 0, NULL);
+ if (!nobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(nobj);
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+
+ for (slot = begin; slot < end; slot++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, slot, &hole, &tvr.u.value);
+ if (!ok)
+ goto out;
+ if (!hole) {
+ ok = SetArrayElement(cx, nobj, slot - begin, tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ }
+ ok = js_SetLengthProperty(cx, nobj, end - begin);
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+#if JS_HAS_ARRAY_EXTRAS
+
+static JSBool
+array_indexOfHelper(JSContext *cx, JSBool isLast, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsuint length, i, stop;
+ jsval tosearch;
+ jsint direction;
+ JSBool hole;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ if (length == 0)
+ goto not_found;
+
+ if (argc <= 1) {
+ i = isLast ? length - 1 : 0;
+ tosearch = (argc != 0) ? vp[2] : JSVAL_VOID;
+ } else {
+ jsdouble start;
+
+ tosearch = vp[2];
+ start = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ start = js_DoubleToInteger(start);
+ if (start < 0) {
+ start += length;
+ if (start < 0) {
+ if (isLast)
+ goto not_found;
+ i = 0;
+ } else {
+ i = (jsuint)start;
+ }
+ } else if (start >= length) {
+ if (!isLast)
+ goto not_found;
+ i = length - 1;
+ } else {
+ i = (jsuint)start;
+ }
+ }
+
+ if (isLast) {
+ stop = 0;
+ direction = -1;
+ } else {
+ stop = length - 1;
+ direction = 1;
+ }
+
+ for (;;) {
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) ||
+ !GetArrayElement(cx, obj, (jsuint)i, &hole, vp)) {
+ return JS_FALSE;
+ }
+ if (!hole && js_StrictlyEqual(cx, *vp, tosearch))
+ return js_NewNumberInRootedValue(cx, i, vp);
+ if (i == stop)
+ goto not_found;
+ i += direction;
+ }
+
+ not_found:
+ *vp = INT_TO_JSVAL(-1);
+ return JS_TRUE;
+}
+
+static JSBool
+array_indexOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_indexOfHelper(cx, JS_FALSE, argc, vp);
+}
+
+static JSBool
+array_lastIndexOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_indexOfHelper(cx, JS_TRUE, argc, vp);
+}
+
+/* Order is important; extras that take a predicate funarg must follow MAP. */
+typedef enum ArrayExtraMode {
+ FOREACH,
+ REDUCE,
+ REDUCE_RIGHT,
+ MAP,
+ FILTER,
+ SOME,
+ EVERY
+} ArrayExtraMode;
+
+#define REDUCE_MODE(mode) ((mode) == REDUCE || (mode) == REDUCE_RIGHT)
+
+static JSBool
+array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsuint length, newlen;
+ jsval *argv, *elemroot, *invokevp, *sp;
+ JSBool ok, cond, hole;
+ JSObject *callable, *thisp, *newarr;
+ jsint start, end, step, i;
+ void *mark;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+
+ /*
+ * First, get or compute our callee, so that we error out consistently
+ * when passed a non-callable object.
+ */
+ if (argc == 0) {
+ js_ReportMissingArg(cx, vp, 0);
+ return JS_FALSE;
+ }
+ argv = vp + 2;
+ callable = js_ValueToCallableObject(cx, &argv[0], JSV2F_SEARCH_STACK);
+ if (!callable)
+ return JS_FALSE;
+
+ /*
+ * Set our initial return condition, used for zero-length array cases
+ * (and pre-size our map return to match our known length, for all cases).
+ */
+#ifdef __GNUC__ /* quell GCC overwarning */
+ newlen = 0;
+ newarr = NULL;
+#endif
+ start = 0, end = length, step = 1;
+
+ switch (mode) {
+ case REDUCE_RIGHT:
+ start = length - 1, end = -1, step = -1;
+ /* FALL THROUGH */
+ case REDUCE:
+ if (length == 0 && argc == 1) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_EMPTY_ARRAY_REDUCE);
+ return JS_FALSE;
+ }
+ if (argc >= 2) {
+ *vp = argv[1];
+ } else {
+ do {
+ if (!GetArrayElement(cx, obj, start, &hole, vp))
+ return JS_FALSE;
+ start += step;
+ } while (hole && start != end);
+
+ if (hole && start == end) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_EMPTY_ARRAY_REDUCE);
+ return JS_FALSE;
+ }
+ }
+ break;
+ case MAP:
+ case FILTER:
+ newlen = (mode == MAP) ? length : 0;
+ newarr = js_NewArrayObject(cx, newlen, NULL);
+ if (!newarr)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(newarr);
+ break;
+ case SOME:
+ *vp = JSVAL_FALSE;
+ break;
+ case EVERY:
+ *vp = JSVAL_TRUE;
+ break;
+ case FOREACH:
+ *vp = JSVAL_VOID;
+ break;
+ }
+
+ if (length == 0)
+ return JS_TRUE;
+
+ if (argc > 1 && !REDUCE_MODE(mode)) {
+ if (!js_ValueToObject(cx, argv[1], &thisp))
+ return JS_FALSE;
+ argv[1] = OBJECT_TO_JSVAL(thisp);
+ } else {
+ thisp = NULL;
+ }
+
+ /*
+ * For all but REDUCE, we call with 3 args (value, index, array). REDUCE
+ * requires 4 args (accum, value, index, array).
+ */
+ argc = 3 + REDUCE_MODE(mode);
+ elemroot = js_AllocStack(cx, 1 + 2 + argc, &mark);
+ if (!elemroot)
+ return JS_FALSE;
+
+ MUST_FLOW_THROUGH("out");
+ ok = JS_TRUE;
+ invokevp = elemroot + 1;
+
+ for (i = start; i != end; i += step) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, i, &hole, elemroot);
+ if (!ok)
+ goto out;
+ if (hole)
+ continue;
+
+ /*
+ * Push callable and 'this', then args. We must do this for every
+ * iteration around the loop since js_Invoke uses spbase[0] for return
+ * value storage, while some native functions use spbase[1] for local
+ * rooting.
+ */
+ sp = invokevp;
+ *sp++ = OBJECT_TO_JSVAL(callable);
+ *sp++ = OBJECT_TO_JSVAL(thisp);
+ if (REDUCE_MODE(mode))
+ *sp++ = *vp;
+ *sp++ = *elemroot;
+ *sp++ = INT_TO_JSVAL(i);
+ *sp++ = OBJECT_TO_JSVAL(obj);
+
+ /* Do the call. */
+ ok = js_Invoke(cx, argc, invokevp, 0);
+ if (!ok)
+ break;
+
+ if (mode > MAP)
+ cond = js_ValueToBoolean(*invokevp);
+#ifdef __GNUC__ /* quell GCC overwarning */
+ else
+ cond = JS_FALSE;
+#endif
+
+ switch (mode) {
+ case FOREACH:
+ break;
+ case REDUCE:
+ case REDUCE_RIGHT:
+ *vp = *invokevp;
+ break;
+ case MAP:
+ ok = SetArrayElement(cx, newarr, i, *invokevp);
+ if (!ok)
+ goto out;
+ break;
+ case FILTER:
+ if (!cond)
+ break;
+ /* The filter passed *elemroot, so push it onto our result. */
+ ok = SetArrayElement(cx, newarr, newlen++, *elemroot);
+ if (!ok)
+ goto out;
+ break;
+ case SOME:
+ if (cond) {
+ *vp = JSVAL_TRUE;
+ goto out;
+ }
+ break;
+ case EVERY:
+ if (!cond) {
+ *vp = JSVAL_FALSE;
+ goto out;
+ }
+ break;
+ }
+ }
+
+ out:
+ js_FreeStack(cx, mark);
+ if (ok && mode == FILTER)
+ ok = js_SetLengthProperty(cx, newarr, newlen);
+ return ok;
+}
+
+static JSBool
+array_forEach(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, FOREACH, argc, vp);
+}
+
+static JSBool
+array_map(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, MAP, argc, vp);
+}
+
+static JSBool
+array_reduce(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, REDUCE, argc, vp);
+}
+
+static JSBool
+array_reduceRight(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, REDUCE_RIGHT, argc, vp);
+}
+
+static JSBool
+array_filter(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, FILTER, argc, vp);
+}
+
+static JSBool
+array_some(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, SOME, argc, vp);
+}
+
+static JSBool
+array_every(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, EVERY, argc, vp);
+}
+#endif
+
+static JSPropertySpec array_props[] = {
+ {js_length_str, -1, JSPROP_SHARED | JSPROP_PERMANENT,
+ array_length_getter, array_length_setter},
+ {0,0,0,0,0}
+};
+
+JS_DEFINE_TRCINFO_1(array_toString,
+ (2, (static, STRING_FAIL, Array_p_toString, CONTEXT, THIS, 0, 0)))
+JS_DEFINE_TRCINFO_1(array_join,
+ (3, (static, STRING_FAIL, Array_p_join, CONTEXT, THIS, STRING, 0, 0)))
+JS_DEFINE_TRCINFO_1(array_push,
+ (3, (static, JSVAL_FAIL, Array_p_push1, CONTEXT, THIS, JSVAL, 0, 0)))
+JS_DEFINE_TRCINFO_1(array_pop,
+ (2, (static, JSVAL_FAIL, Array_p_pop, CONTEXT, THIS, 0, 0)))
+
+static JSFunctionSpec array_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, array_toSource, 0,0),
+#endif
+ JS_TN(js_toString_str, array_toString, 0,0, array_toString_trcinfo),
+ JS_FN(js_toLocaleString_str,array_toLocaleString,0,0),
+
+ /* Perl-ish methods. */
+ JS_TN("join", array_join, 1,JSFUN_GENERIC_NATIVE, array_join_trcinfo),
+ JS_FN("reverse", array_reverse, 0,JSFUN_GENERIC_NATIVE),
+ JS_FN("sort", array_sort, 1,JSFUN_GENERIC_NATIVE),
+ JS_TN("push", array_push, 1,JSFUN_GENERIC_NATIVE, array_push_trcinfo),
+ JS_TN("pop", array_pop, 0,JSFUN_GENERIC_NATIVE, array_pop_trcinfo),
+ JS_FN("shift", array_shift, 0,JSFUN_GENERIC_NATIVE),
+ JS_FN("unshift", array_unshift, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("splice", array_splice, 2,JSFUN_GENERIC_NATIVE),
+
+ /* Pythonic sequence methods. */
+ JS_FN("concat", array_concat, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("slice", array_slice, 2,JSFUN_GENERIC_NATIVE),
+
+#if JS_HAS_ARRAY_EXTRAS
+ JS_FN("indexOf", array_indexOf, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("lastIndexOf", array_lastIndexOf, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("forEach", array_forEach, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("map", array_map, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("reduce", array_reduce, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("reduceRight", array_reduceRight, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("filter", array_filter, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("some", array_some, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("every", array_every, 1,JSFUN_GENERIC_NATIVE),
+#endif
+
+ JS_FS_END
+};
+
+JSBool
+js_Array(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsuint length;
+ jsval *vector;
+
+ /* If called without new, replace obj with a new Array object. */
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+
+ if (argc == 0) {
+ length = 0;
+ vector = NULL;
+ } else if (argc > 1) {
+ length = (jsuint) argc;
+ vector = argv;
+ } else if (!JSVAL_IS_NUMBER(argv[0])) {
+ length = 1;
+ vector = argv;
+ } else {
+ length = ValueIsLength(cx, &argv[0]);
+ if (JSVAL_IS_NULL(argv[0]))
+ return JS_FALSE;
+ vector = NULL;
+ }
+ return InitArrayObject(cx, obj, length, vector);
+}
+
+JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_ARRAY_LENGTH);
+JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH + 1 == JSSLOT_ARRAY_COUNT);
+
+#ifdef JS_TRACER
+
+JSObject* FASTCALL
+js_FastNewArray(JSContext* cx, JSObject* proto)
+{
+ JS_ASSERT(OBJ_IS_ARRAY(cx, proto));
+
+ JS_ASSERT(JS_ON_TRACE(cx));
+ JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
+ if (!obj)
+ return NULL;
+
+ JSClass* clasp = &js_ArrayClass;
+ obj->classword = jsuword(clasp);
+
+ obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
+ obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
+
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
+ obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
+ for (unsigned i = JSSLOT_ARRAY_COUNT + 1; i != JS_INITIAL_NSLOTS; ++i)
+ obj->fslots[i] = JSVAL_VOID;
+
+ JSObjectOps* ops = clasp->getObjectOps(cx, clasp);
+ obj->map = ops->newObjectMap(cx, 1, ops, clasp, obj);
+ if (!obj->map)
+ return NULL;
+ obj->dslots = NULL;
+ return obj;
+}
+
+JSObject* FASTCALL
+js_Array_1int(JSContext* cx, JSObject* proto, int32 i)
+{
+ JS_ASSERT(JS_ON_TRACE(cx));
+ JSObject* obj = js_FastNewArray(cx, proto);
+ if (obj)
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = i;
+ return obj;
+}
+
+#define ARRAY_CTOR_GUTS(exact_len, newslots_code) \
+ JS_ASSERT(JS_ON_TRACE(cx)); \
+ JSObject* obj = js_FastNewArray(cx, proto); \
+ if (obj) { \
+ const uint32 len = ARRAY_GROWBY; \
+ jsval* newslots = (jsval*) JS_malloc(cx, sizeof (jsval) * (len + 1)); \
+ if (newslots) { \
+ obj->dslots = newslots + 1; \
+ ARRAY_SET_DENSE_LENGTH(obj, len); \
+ {newslots_code} \
+ while (++newslots < obj->dslots + len) \
+ *newslots = JSVAL_HOLE; \
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = (exact_len); \
+ return obj; \
+ } \
+ } \
+ return NULL;
+
+JSObject* FASTCALL
+js_Array_1str(JSContext* cx, JSObject* proto, JSString *str)
+{
+ ARRAY_CTOR_GUTS(1, *++newslots = STRING_TO_JSVAL(str);)
+}
+
+JSObject* FASTCALL
+js_Array_2obj(JSContext* cx, JSObject* proto, JSObject *obj1, JSObject* obj2)
+{
+ ARRAY_CTOR_GUTS(2,
+ *++newslots = OBJECT_TO_JSVAL(obj1);
+ *++newslots = OBJECT_TO_JSVAL(obj2);)
+}
+
+JSObject* FASTCALL
+js_Array_3num(JSContext* cx, JSObject* proto, jsdouble n1, jsdouble n2, jsdouble n3)
+{
+ ARRAY_CTOR_GUTS(3,
+ if (!js_NewDoubleInRootedValue(cx, n1, ++newslots))
+ return NULL;
+ if (!js_NewDoubleInRootedValue(cx, n2, ++newslots))
+ return NULL;
+ if (!js_NewDoubleInRootedValue(cx, n3, ++newslots))
+ return NULL;)
+}
+
+#endif /* JS_TRACER */
+
+JSObject *
+js_InitArrayClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ /* Initialize the ops structure used by slow arrays */
+ memcpy(&js_SlowArrayObjectOps, &js_ObjectOps, sizeof(JSObjectOps));
+ js_SlowArrayObjectOps.trace = slowarray_trace;
+ js_SlowArrayObjectOps.enumerate = slowarray_enumerate;
+ js_SlowArrayObjectOps.call = NULL;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_ArrayClass, js_Array, 1,
+ array_props, array_methods, NULL, NULL);
+
+ /* Initialize the Array prototype object so it gets a length property. */
+ if (!proto || !InitArrayObject(cx, proto, 0, NULL))
+ return NULL;
+ return proto;
+}
+
+JSObject *
+js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector, JSBool holey)
+{
+ JSTempValueRooter tvr;
+ JSObject *obj;
+
+ obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
+ if (!obj)
+ return NULL;
+
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);
+ if (!InitArrayObject(cx, obj, length, vector, holey))
+ obj = NULL;
+ JS_POP_TEMP_ROOT(cx, &tvr);
+
+ /* Set/clear newborn root, in case we lost it. */
+ cx->weakRoots.newborn[GCX_OBJECT] = obj;
+ return obj;
+}
+
+JSObject *
+js_NewSlowArrayObject(JSContext *cx)
+{
+ JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL, 0);
+ if (obj)
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
+ return obj;
+}
+
+#ifdef DEBUG_ARRAYS
+JSBool
+js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uintN i;
+ JSObject *array;
+
+ for (i = 0; i < argc; i++) {
+ char *bytes;
+
+ bytes = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, argv[i],
+ NULL);
+ if (!bytes)
+ return JS_FALSE;
+ if (JSVAL_IS_PRIMITIVE(argv[i]) ||
+ !OBJ_IS_ARRAY(cx, (array = JSVAL_TO_OBJECT(argv[i])))) {
+ fprintf(stderr, "%s: not array\n", bytes);
+ JS_free(cx, bytes);
+ continue;
+ }
+ fprintf(stderr, "%s: %s (len %lu", bytes,
+ OBJ_IS_DENSE_ARRAY(cx, array) ? "dense" : "sparse",
+ array->fslots[JSSLOT_ARRAY_LENGTH]);
+ if (OBJ_IS_DENSE_ARRAY(cx, array)) {
+ fprintf(stderr, ", count %lu, denselen %lu",
+ array->fslots[JSSLOT_ARRAY_COUNT],
+ ARRAY_DENSE_LENGTH(array));
+ }
+ fputs(")\n", stderr);
+ JS_free(cx, bytes);
+ }
+ return JS_TRUE;
+}
+#endif
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint8Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint8 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ jsint vi;
+
+ JSUint8 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v) || (vi = JSVAL_TO_INT(v)) < 0)
+ return JS_FALSE;
+
+ *dp++ = (JSUint8) vi;
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint16Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint16 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ jsint vi;
+
+ JSUint16 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v) || (vi = JSVAL_TO_INT(v)) < 0)
+ return JS_FALSE;
+
+ *dp++ = (JSUint16) vi;
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint32Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint32 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ jsint vi;
+
+ JSUint32 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v) || (vi = JSVAL_TO_INT(v)) < 0)
+ return JS_FALSE;
+
+ *dp++ = (JSUint32) vi;
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt8Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt8 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ JSInt8 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v))
+ return JS_FALSE;
+
+ *dp++ = (JSInt8) JSVAL_TO_INT(v);
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt16Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt16 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ JSInt16 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v))
+ return JS_FALSE;
+
+ *dp++ = (JSInt16) JSVAL_TO_INT(v);
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt32Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt32 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ JSInt32 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v))
+ return JS_FALSE;
+
+ *dp++ = (JSInt32) JSVAL_TO_INT(v);
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSDoubleBuffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ jsdouble *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ jsdouble *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (JSVAL_IS_INT(v))
+ *dp++ = (jsdouble) JSVAL_TO_INT(v);
+ else if (JSVAL_IS_DOUBLE(v))
+ *dp++ = *(JSVAL_TO_DOUBLE(v));
+ else
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem, CONTEXT, OBJECT, INT32, JSVAL, 0, 0)
+JS_DEFINE_CALLINFO_2(extern, OBJECT, js_FastNewArray, CONTEXT, OBJECT, 0, 0)
+JS_DEFINE_CALLINFO_3(extern, OBJECT, js_Array_1int, CONTEXT, OBJECT, INT32, 0, 0)
+JS_DEFINE_CALLINFO_3(extern, OBJECT, js_Array_1str, CONTEXT, OBJECT, STRING, 0, 0)
+JS_DEFINE_CALLINFO_4(extern, OBJECT, js_Array_2obj, CONTEXT, OBJECT, OBJECT, OBJECT, 0, 0)
+JS_DEFINE_CALLINFO_5(extern, OBJECT, js_Array_3num, CONTEXT, OBJECT, DOUBLE, DOUBLE, DOUBLE, 0, 0)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsarray.h b/tools/node_modules/expresso/deps/jscoverage/js/jsarray.h
new file mode 100644
index 0000000..ef10316
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsarray.h
@@ -0,0 +1,191 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsarray_h___
+#define jsarray_h___
+/*
+ * JS Array interface.
+ */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/* Generous sanity-bound on length (in elements) of array initialiser. */
+#define ARRAY_INIT_LIMIT JS_BIT(24)
+
+extern JSBool
+js_IdIsIndex(jsval id, jsuint *indexp);
+
+extern JSClass js_ArrayClass, js_SlowArrayClass;
+
+#define OBJ_IS_DENSE_ARRAY(cx,obj) (OBJ_GET_CLASS(cx, obj) == &js_ArrayClass)
+
+#define OBJ_IS_ARRAY(cx,obj) (OBJ_IS_DENSE_ARRAY(cx, obj) || \
+ OBJ_GET_CLASS(cx, obj) == &js_SlowArrayClass)
+
+extern JSObject *
+js_InitArrayClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector,
+ JSBool holey = JS_FALSE);
+
+/* Create an array object that starts out already made slow/sparse. */
+extern JSObject *
+js_NewSlowArrayObject(JSContext *cx);
+
+extern JSBool
+js_MakeArraySlow(JSContext *cx, JSObject *obj);
+
+#define JSSLOT_ARRAY_LENGTH JSSLOT_PRIVATE
+#define JSSLOT_ARRAY_COUNT (JSSLOT_ARRAY_LENGTH + 1)
+#define JSSLOT_ARRAY_LOOKUP_HOLDER (JSSLOT_ARRAY_COUNT + 1)
+
+#define ARRAY_DENSE_LENGTH(obj) \
+ (JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj)), \
+ (obj)->dslots ? (uint32)(obj)->dslots[-1] : 0)
+
+#define ARRAY_SET_DENSE_LENGTH(obj, max) \
+ (JS_ASSERT((obj)->dslots), (obj)->dslots[-1] = (jsval)(max))
+
+#define ARRAY_GROWBY 8
+
+extern JSBool
+js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
+
+extern JSBool
+js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length);
+
+extern JSBool
+js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
+
+extern JSBool JS_FASTCALL
+js_IndexToId(JSContext *cx, jsuint index, jsid *idp);
+
+/*
+ * Test whether an object is "array-like". Currently this means whether obj
+ * is an Array or an arguments object. We would like an API, and probably a
+ * way in the language, to bless other objects as array-like: having indexed
+ * properties, and a 'length' property of uint32 value equal to one more than
+ * the greatest index.
+ */
+extern JSBool
+js_IsArrayLike(JSContext *cx, JSObject *obj, JSBool *answerp, jsuint *lengthp);
+
+/*
+ * JS-specific merge sort function.
+ */
+typedef JSBool (*JSComparator)(void *arg, const void *a, const void *b,
+ int *result);
+/*
+ * NB: vec is the array to be sorted, tmp is temporary space at least as big
+ * as vec. Both should be GC-rooted if appropriate.
+ *
+ * The sorted result is in vec. vec may be in an inconsistent state if the
+ * comparator function cmp returns an error inside a comparison, so remember
+ * to check the return value of this function.
+ */
+extern JSBool
+js_MergeSort(void *vec, size_t nel, size_t elsize, JSComparator cmp,
+ void *arg, void *tmp);
+
+#ifdef DEBUG_ARRAYS
+extern JSBool
+js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+#endif
+
+/*
+ * Fast dense-array-to-buffer conversions.
+ *
+ * If the array is a dense array, fill [offset..offset+count] values
+ * into destination, assuming that types are consistent. Return
+ * JS_TRUE if successful, otherwise JS_FALSE -- note that the
+ * destination buffer may be modified even if JS_FALSE is returned
+ * (e.g. due to finding an inappropriate type later on in the array).
+ * If JS_FALSE is returned, no error conditions or exceptions are set
+ * on the context.
+ *
+ * For ArrayToJSUint8, ArrayToJSUint16, and ArrayToJSUint32, each element
+ * in the array a) must be an integer; b) must be >= 0. Integers
+ * are clamped to fit in the destination size. Only JSVAL_IS_INT values
+ * are considered to be valid, so for JSUint32, the maximum value that
+ * can be fast-converted is less than the full unsigned 32-bit range.
+ *
+ * For ArrayToJSInt8, ArrayToJSInt16, ArrayToJSInt32, each element in
+ * the array must be an integer. Integers are clamped to fit in the
+ * destination size. Only JSVAL_IS_INT values are considered to be
+ * valid, so for JSInt32, the maximum value that can be
+ * fast-converted is less than the full signed 32-bit range.
+ *
+ * For ArrayToJSDouble, each element in the array must be an
+ * integer -or- a double (JSVAL_IS_NUMBER).
+ */
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint8Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint8 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint16Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint16 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint32Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint32 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt8Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt8 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt16Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt16 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt32Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt32 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSDoubleBuffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ jsdouble *dest);
+
+JS_END_EXTERN_C
+
+#endif /* jsarray_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsatom.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsatom.cpp
new file mode 100644
index 0000000..7bcfeca
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsatom.cpp
@@ -0,0 +1,1064 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS atom table.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jshash.h" /* Added by JSIFY */
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsgc.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsscan.h"
+#include "jsstr.h"
+
+const char *
+js_AtomToPrintableString(JSContext *cx, JSAtom *atom)
+{
+ return js_ValueToPrintableString(cx, ATOM_KEY(atom));
+}
+
+#define JS_PROTO(name,code,init) const char js_##name##_str[] = #name;
+#include "jsproto.tbl"
+#undef JS_PROTO
+
+/*
+ * String constants for common atoms defined in JSAtomState starting from
+ * JSAtomState.emptyAtom until JSAtomState.lazy.
+ *
+ * The elements of the array after the first empty string define strings
+ * corresponding to the two boolean literals, false and true, followed by the
+ * JSType enumerators from jspubtd.h starting with "undefined" for JSTYPE_VOID
+ * (which is pseudo-boolean 2) and continuing as initialized below. The static
+ * asserts check these relations.
+ */
+JS_STATIC_ASSERT(JSTYPE_LIMIT == 8);
+JS_STATIC_ASSERT(JSVAL_TO_BOOLEAN(JSVAL_VOID) == 2);
+JS_STATIC_ASSERT(JSTYPE_VOID == 0);
+
+const char *const js_common_atom_names[] = {
+ "", /* emptyAtom */
+ js_false_str, /* booleanAtoms[0] */
+ js_true_str, /* booleanAtoms[1] */
+ js_undefined_str, /* typeAtoms[JSTYPE_VOID] */
+ js_object_str, /* typeAtoms[JSTYPE_OBJECT] */
+ js_function_str, /* typeAtoms[JSTYPE_FUNCTION] */
+ "string", /* typeAtoms[JSTYPE_STRING] */
+ "number", /* typeAtoms[JSTYPE_NUMBER] */
+ "boolean", /* typeAtoms[JSTYPE_BOOLEAN] */
+ js_null_str, /* typeAtoms[JSTYPE_NULL] */
+ "xml", /* typeAtoms[JSTYPE_XML] */
+ js_null_str, /* nullAtom */
+
+#define JS_PROTO(name,code,init) js_##name##_str,
+#include "jsproto.tbl"
+#undef JS_PROTO
+
+ js_anonymous_str, /* anonymousAtom */
+ js_apply_str, /* applyAtom */
+ js_arguments_str, /* argumentsAtom */
+ js_arity_str, /* arityAtom */
+ js_call_str, /* callAtom */
+ js_callee_str, /* calleeAtom */
+ js_caller_str, /* callerAtom */
+ js_class_prototype_str, /* classPrototypeAtom */
+ js_constructor_str, /* constructorAtom */
+ js_count_str, /* countAtom */
+ js_each_str, /* eachAtom */
+ js_eval_str, /* evalAtom */
+ js_fileName_str, /* fileNameAtom */
+ js_get_str, /* getAtom */
+ js_getter_str, /* getterAtom */
+ js_index_str, /* indexAtom */
+ js_input_str, /* inputAtom */
+ js_iterator_str, /* iteratorAtom */
+ js_length_str, /* lengthAtom */
+ js_lineNumber_str, /* lineNumberAtom */
+ js_message_str, /* messageAtom */
+ js_name_str, /* nameAtom */
+ js_next_str, /* nextAtom */
+ js_noSuchMethod_str, /* noSuchMethodAtom */
+ js_parent_str, /* parentAtom */
+ js_proto_str, /* protoAtom */
+ js_set_str, /* setAtom */
+ js_setter_str, /* setterAtom */
+ js_stack_str, /* stackAtom */
+ js_toLocaleString_str, /* toLocaleStringAtom */
+ js_toSource_str, /* toSourceAtom */
+ js_toString_str, /* toStringAtom */
+ js_valueOf_str, /* valueOfAtom */
+ js_toJSON_str, /* toJSONAtom */
+ "(void 0)", /* void0Atom */
+
+#if JS_HAS_XML_SUPPORT
+ js_etago_str, /* etagoAtom */
+ js_namespace_str, /* namespaceAtom */
+ js_ptagc_str, /* ptagcAtom */
+ js_qualifier_str, /* qualifierAtom */
+ js_space_str, /* spaceAtom */
+ js_stago_str, /* stagoAtom */
+ js_star_str, /* starAtom */
+ js_starQualifier_str, /* starQualifierAtom */
+ js_tagc_str, /* tagcAtom */
+ js_xml_str, /* xmlAtom */
+#endif
+
+#ifdef NARCISSUS
+ js___call___str, /* __call__Atom */
+ js___construct___str, /* __construct__Atom */
+ js___hasInstance___str, /* __hasInstance__Atom */
+ js_ExecutionContext_str, /* ExecutionContextAtom */
+ js_current_str, /* currentAtom */
+#endif
+};
+
+JS_STATIC_ASSERT(JS_ARRAY_LENGTH(js_common_atom_names) * sizeof(JSAtom *) ==
+ LAZY_ATOM_OFFSET_START - ATOM_OFFSET_START);
+
+/*
+ * Interpreter macros called by the trace recorder assume common atom indexes
+ * fit in one byte of immediate operand.
+ */
+JS_STATIC_ASSERT(JS_ARRAY_LENGTH(js_common_atom_names) < 256);
+
+const size_t js_common_atom_count = JS_ARRAY_LENGTH(js_common_atom_names);
+
+const char js_anonymous_str[] = "anonymous";
+const char js_apply_str[] = "apply";
+const char js_arguments_str[] = "arguments";
+const char js_arity_str[] = "arity";
+const char js_call_str[] = "call";
+const char js_callee_str[] = "callee";
+const char js_caller_str[] = "caller";
+const char js_class_prototype_str[] = "prototype";
+const char js_constructor_str[] = "constructor";
+const char js_count_str[] = "__count__";
+const char js_each_str[] = "each";
+const char js_eval_str[] = "eval";
+const char js_fileName_str[] = "fileName";
+const char js_get_str[] = "get";
+const char js_getter_str[] = "getter";
+const char js_index_str[] = "index";
+const char js_input_str[] = "input";
+const char js_iterator_str[] = "__iterator__";
+const char js_length_str[] = "length";
+const char js_lineNumber_str[] = "lineNumber";
+const char js_message_str[] = "message";
+const char js_name_str[] = "name";
+const char js_next_str[] = "next";
+const char js_noSuchMethod_str[] = "__noSuchMethod__";
+const char js_object_str[] = "object";
+const char js_parent_str[] = "__parent__";
+const char js_proto_str[] = "__proto__";
+const char js_setter_str[] = "setter";
+const char js_set_str[] = "set";
+const char js_stack_str[] = "stack";
+const char js_toSource_str[] = "toSource";
+const char js_toString_str[] = "toString";
+const char js_toLocaleString_str[] = "toLocaleString";
+const char js_undefined_str[] = "undefined";
+const char js_valueOf_str[] = "valueOf";
+const char js_toJSON_str[] = "toJSON";
+
+#if JS_HAS_XML_SUPPORT
+const char js_etago_str[] = "</";
+const char js_namespace_str[] = "namespace";
+const char js_ptagc_str[] = "/>";
+const char js_qualifier_str[] = "::";
+const char js_space_str[] = " ";
+const char js_stago_str[] = "<";
+const char js_star_str[] = "*";
+const char js_starQualifier_str[] = "*::";
+const char js_tagc_str[] = ">";
+const char js_xml_str[] = "xml";
+#endif
+
+#if JS_HAS_GENERATORS
+const char js_close_str[] = "close";
+const char js_send_str[] = "send";
+#endif
+
+#ifdef NARCISSUS
+const char js___call___str[] = "__call__";
+const char js___construct___str[] = "__construct__";
+const char js___hasInstance___str[] = "__hasInstance__";
+const char js_ExecutionContext_str[] = "ExecutionContext";
+const char js_current_str[] = "current";
+#endif
+
+/*
+ * JSAtomState.doubleAtoms and JSAtomState.stringAtoms hashtable entry. To
+ * support pinned and interned string atoms, we use the lowest bits of the
+ * keyAndFlags field to store ATOM_PINNED and ATOM_INTERNED flags.
+ */
+typedef struct JSAtomHashEntry {
+ JSDHashEntryHdr hdr;
+ jsuword keyAndFlags;
+} JSAtomHashEntry;
+
+#define ATOM_ENTRY_FLAG_MASK (ATOM_PINNED | ATOM_INTERNED)
+
+JS_STATIC_ASSERT(ATOM_ENTRY_FLAG_MASK < JSVAL_ALIGN);
+
+/*
+ * Helper macros to access and modify JSAtomHashEntry.
+ */
+#define TO_ATOM_ENTRY(hdr) ((JSAtomHashEntry *) hdr)
+#define ATOM_ENTRY_KEY(entry) \
+ ((void *)((entry)->keyAndFlags & ~ATOM_ENTRY_FLAG_MASK))
+#define ATOM_ENTRY_FLAGS(entry) \
+ ((uintN)((entry)->keyAndFlags & ATOM_ENTRY_FLAG_MASK))
+#define INIT_ATOM_ENTRY(entry, key) \
+ ((void)((entry)->keyAndFlags = (jsuword)(key)))
+#define ADD_ATOM_ENTRY_FLAGS(entry, flags) \
+ ((void)((entry)->keyAndFlags |= (jsuword)(flags)))
+#define CLEAR_ATOM_ENTRY_FLAGS(entry, flags) \
+ ((void)((entry)->keyAndFlags &= ~(jsuword)(flags)))
+
+static JSDHashNumber
+HashDouble(JSDHashTable *table, const void *key);
+
+static JSBool
+MatchDouble(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key);
+
+static JSDHashNumber
+HashString(JSDHashTable *table, const void *key);
+
+static JSBool
+MatchString(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key);
+
+static const JSDHashTableOps DoubleHashOps = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ HashDouble,
+ MatchDouble,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+static const JSDHashTableOps StringHashOps = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ HashString,
+ MatchString,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+#define IS_DOUBLE_TABLE(table) ((table)->ops == &DoubleHashOps)
+#define IS_STRING_TABLE(table) ((table)->ops == &StringHashOps)
+
+#define IS_INITIALIZED_STATE(state) IS_DOUBLE_TABLE(&(state)->doubleAtoms)
+
+static JSDHashNumber
+HashDouble(JSDHashTable *table, const void *key)
+{
+ jsdouble d;
+
+ JS_ASSERT(IS_DOUBLE_TABLE(table));
+ d = *(jsdouble *)key;
+ return JSDOUBLE_HI32(d) ^ JSDOUBLE_LO32(d);
+}
+
+static JSDHashNumber
+HashString(JSDHashTable *table, const void *key)
+{
+ JS_ASSERT(IS_STRING_TABLE(table));
+ return js_HashString((JSString *)key);
+}
+
+static JSBool
+MatchDouble(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ jsdouble d1, d2;
+
+ JS_ASSERT(IS_DOUBLE_TABLE(table));
+ if (entry->keyAndFlags == 0) {
+ /* See comments in MatchString. */
+ return JS_FALSE;
+ }
+
+ d1 = *(jsdouble *)ATOM_ENTRY_KEY(entry);
+ d2 = *(jsdouble *)key;
+ if (JSDOUBLE_IS_NaN(d1))
+ return JSDOUBLE_IS_NaN(d2);
+#if defined(XP_WIN)
+ /* XXX MSVC miscompiles such that (NaN == 0) */
+ if (JSDOUBLE_IS_NaN(d2))
+ return JS_FALSE;
+#endif
+ return d1 == d2;
+}
+
+static JSBool
+MatchString(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+
+ JS_ASSERT(IS_STRING_TABLE(table));
+ if (entry->keyAndFlags == 0) {
+ /*
+ * This happens when js_AtomizeString adds a new hash entry and
+ * releases the lock but before it takes the lock the second time to
+ * initialize keyAndFlags for the entry.
+ *
+ * We always return false for such entries so JS_DHashTableOperate
+ * never finds them. We clean them during GC's sweep phase.
+ *
+ * It means that with a contested lock or when GC is triggered outside
+ * the lock we may end up adding two entries, but this is a price for
+ * simpler code.
+ */
+ return JS_FALSE;
+ }
+ return js_EqualStrings((JSString *)ATOM_ENTRY_KEY(entry), (JSString *)key);
+}
+
+/*
+ * For a browser build from 2007-08-09 after the browser starts up there are
+ * just 55 double atoms, but over 15000 string atoms. Not to penalize more
+ * economical embeddings allocating too much memory initially we initialize
+ * atomized strings with just 1K entries.
+ */
+#define JS_STRING_HASH_COUNT 1024
+#define JS_DOUBLE_HASH_COUNT 64
+
+JSBool
+js_InitAtomState(JSRuntime *rt)
+{
+ JSAtomState *state = &rt->atomState;
+
+ /*
+ * The caller must zero the state before calling this function.
+ */
+ JS_ASSERT(!state->stringAtoms.ops);
+ JS_ASSERT(!state->doubleAtoms.ops);
+
+ if (!JS_DHashTableInit(&state->stringAtoms, &StringHashOps,
+ NULL, sizeof(JSAtomHashEntry),
+ JS_DHASH_DEFAULT_CAPACITY(JS_STRING_HASH_COUNT))) {
+ state->stringAtoms.ops = NULL;
+ return JS_FALSE;
+ }
+ JS_ASSERT(IS_STRING_TABLE(&state->stringAtoms));
+
+ if (!JS_DHashTableInit(&state->doubleAtoms, &DoubleHashOps,
+ NULL, sizeof(JSAtomHashEntry),
+ JS_DHASH_DEFAULT_CAPACITY(JS_DOUBLE_HASH_COUNT))) {
+ state->doubleAtoms.ops = NULL;
+ JS_DHashTableFinish(&state->stringAtoms);
+ state->stringAtoms.ops = NULL;
+ return JS_FALSE;
+ }
+ JS_ASSERT(IS_DOUBLE_TABLE(&state->doubleAtoms));
+
+#ifdef JS_THREADSAFE
+ js_InitLock(&state->lock);
+#endif
+ JS_ASSERT(IS_INITIALIZED_STATE(state));
+ return JS_TRUE;
+}
+
+static JSDHashOperator
+js_string_uninterner(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ JSRuntime *rt = (JSRuntime *)arg;
+ JSString *str;
+
+ /*
+ * Any string entry that remains at this point must be initialized, as the
+ * last GC should clean any uninitialized ones.
+ */
+ JS_ASSERT(IS_STRING_TABLE(table));
+ JS_ASSERT(entry->keyAndFlags != 0);
+ str = (JSString *)ATOM_ENTRY_KEY(entry);
+
+ /* Pass null as context. */
+ js_FinalizeStringRT(rt, str, js_GetExternalStringGCType(str), NULL);
+ return JS_DHASH_NEXT;
+}
+
+void
+js_FinishAtomState(JSRuntime *rt)
+{
+ JSAtomState *state = &rt->atomState;
+
+ if (!IS_INITIALIZED_STATE(state)) {
+ /*
+ * We are called with uninitialized state when JS_NewRuntime fails and
+ * calls JS_DestroyRuntime on a partially initialized runtime.
+ */
+ return;
+ }
+
+ JS_DHashTableEnumerate(&state->stringAtoms, js_string_uninterner, rt);
+ JS_DHashTableFinish(&state->stringAtoms);
+ JS_DHashTableFinish(&state->doubleAtoms);
+
+#ifdef JS_THREADSAFE
+ js_FinishLock(&state->lock);
+#endif
+#ifdef DEBUG
+ memset(state, JS_FREE_PATTERN, sizeof *state);
+#endif
+}
+
+JSBool
+js_InitCommonAtoms(JSContext *cx)
+{
+ JSAtomState *state = &cx->runtime->atomState;
+ uintN i;
+ JSAtom **atoms;
+
+ atoms = COMMON_ATOMS_START(state);
+ for (i = 0; i < JS_ARRAY_LENGTH(js_common_atom_names); i++, atoms++) {
+ *atoms = js_Atomize(cx, js_common_atom_names[i],
+ strlen(js_common_atom_names[i]), ATOM_PINNED);
+ if (!*atoms)
+ return JS_FALSE;
+ }
+ JS_ASSERT((uint8 *)atoms - (uint8 *)state == LAZY_ATOM_OFFSET_START);
+ memset(atoms, 0, ATOM_OFFSET_LIMIT - LAZY_ATOM_OFFSET_START);
+
+ return JS_TRUE;
+}
+
+static JSDHashOperator
+js_atom_unpinner(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JS_ASSERT(IS_STRING_TABLE(table));
+ CLEAR_ATOM_ENTRY_FLAGS(TO_ATOM_ENTRY(hdr), ATOM_PINNED);
+ return JS_DHASH_NEXT;
+}
+
+void
+js_FinishCommonAtoms(JSContext *cx)
+{
+ JSAtomState *state = &cx->runtime->atomState;
+
+ JS_DHashTableEnumerate(&state->stringAtoms, js_atom_unpinner, NULL);
+#ifdef DEBUG
+ memset(COMMON_ATOMS_START(state), JS_FREE_PATTERN,
+ ATOM_OFFSET_LIMIT - ATOM_OFFSET_START);
+#endif
+}
+
+static JSDHashOperator
+js_locked_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ JSTracer *trc = (JSTracer *)arg;
+
+ if (entry->keyAndFlags == 0) {
+ /* Ignore uninitialized entries during tracing. */
+ return JS_DHASH_NEXT;
+ }
+ JS_SET_TRACING_INDEX(trc, "locked_atom", (size_t)number);
+ JS_CallTracer(trc, ATOM_ENTRY_KEY(entry),
+ IS_STRING_TABLE(table) ? JSTRACE_STRING : JSTRACE_DOUBLE);
+ return JS_DHASH_NEXT;
+}
+
+static JSDHashOperator
+js_pinned_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ JSTracer *trc = (JSTracer *)arg;
+ uintN flags = ATOM_ENTRY_FLAGS(entry);
+
+ JS_ASSERT(IS_STRING_TABLE(table));
+ if (flags & (ATOM_PINNED | ATOM_INTERNED)) {
+ JS_SET_TRACING_INDEX(trc,
+ flags & ATOM_PINNED
+ ? "pinned_atom"
+ : "interned_atom",
+ (size_t)number);
+ JS_CallTracer(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING);
+ }
+ return JS_DHASH_NEXT;
+}
+
+void
+js_TraceAtomState(JSTracer *trc, JSBool allAtoms)
+{
+ JSAtomState *state;
+
+ state = &trc->context->runtime->atomState;
+ if (allAtoms) {
+ JS_DHashTableEnumerate(&state->doubleAtoms, js_locked_atom_tracer, trc);
+ JS_DHashTableEnumerate(&state->stringAtoms, js_locked_atom_tracer, trc);
+ } else {
+ JS_DHashTableEnumerate(&state->stringAtoms, js_pinned_atom_tracer, trc);
+ }
+}
+
+static JSDHashOperator
+js_atom_sweeper(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ JSContext *cx = (JSContext *)arg;
+
+ /* Remove uninitialized entries. */
+ if (entry->keyAndFlags == 0)
+ return JS_DHASH_REMOVE;
+
+ if (ATOM_ENTRY_FLAGS(entry) & (ATOM_PINNED | ATOM_INTERNED)) {
+ /* Pinned or interned key cannot be finalized. */
+ JS_ASSERT(!js_IsAboutToBeFinalized(cx, ATOM_ENTRY_KEY(entry)));
+ } else if (js_IsAboutToBeFinalized(cx, ATOM_ENTRY_KEY(entry))) {
+ /* Remove entries with things about to be GC'ed. */
+ return JS_DHASH_REMOVE;
+ }
+ return JS_DHASH_NEXT;
+}
+
+void
+js_SweepAtomState(JSContext *cx)
+{
+ JSAtomState *state = &cx->runtime->atomState;
+
+ JS_DHashTableEnumerate(&state->doubleAtoms, js_atom_sweeper, cx);
+ JS_DHashTableEnumerate(&state->stringAtoms, js_atom_sweeper, cx);
+
+ /*
+ * Optimize for simplicity and mutate table generation numbers even if the
+ * sweeper has not removed any entries.
+ */
+ state->doubleAtoms.generation++;
+ state->stringAtoms.generation++;
+}
+
+JSAtom *
+js_AtomizeDouble(JSContext *cx, jsdouble d)
+{
+ JSAtomState *state;
+ JSDHashTable *table;
+ JSAtomHashEntry *entry;
+ uint32 gen;
+ jsdouble *key;
+ jsval v;
+
+ state = &cx->runtime->atomState;
+ table = &state->doubleAtoms;
+
+ JS_LOCK(cx, &state->lock);
+ entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, &d, JS_DHASH_ADD));
+ if (!entry)
+ goto failed_hash_add;
+ if (entry->keyAndFlags == 0) {
+ gen = ++table->generation;
+ JS_UNLOCK(cx, &state->lock);
+
+ key = js_NewWeaklyRootedDouble(cx, d);
+ if (!key)
+ return NULL;
+
+ JS_LOCK(cx, &state->lock);
+ if (table->generation == gen) {
+ JS_ASSERT(entry->keyAndFlags == 0);
+ } else {
+ entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, key,
+ JS_DHASH_ADD));
+ if (!entry)
+ goto failed_hash_add;
+ if (entry->keyAndFlags != 0)
+ goto finish;
+ ++table->generation;
+ }
+ INIT_ATOM_ENTRY(entry, key);
+ }
+
+ finish:
+ v = DOUBLE_TO_JSVAL((jsdouble *)ATOM_ENTRY_KEY(entry));
+ cx->weakRoots.lastAtom = v;
+ JS_UNLOCK(cx, &state->lock);
+
+ return (JSAtom *)v;
+
+ failed_hash_add:
+ JS_UNLOCK(cx, &state->lock);
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+}
+
+JSAtom *
+js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
+{
+ jsval v;
+ JSAtomState *state;
+ JSDHashTable *table;
+ JSAtomHashEntry *entry;
+ JSString *key;
+ uint32 gen;
+
+ JS_ASSERT(!(flags & ~(ATOM_PINNED|ATOM_INTERNED|ATOM_TMPSTR|ATOM_NOCOPY)));
+ JS_ASSERT_IF(flags & ATOM_NOCOPY, flags & ATOM_TMPSTR);
+
+ state = &cx->runtime->atomState;
+ table = &state->stringAtoms;
+
+ JS_LOCK(cx, &state->lock);
+ entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, str, JS_DHASH_ADD));
+ if (!entry)
+ goto failed_hash_add;
+ if (entry->keyAndFlags != 0) {
+ key = (JSString *)ATOM_ENTRY_KEY(entry);
+ } else {
+ /*
+ * We created a new hashtable entry. Unless str is already allocated
+ * from the GC heap and flat, we have to release state->lock as
+ * string construction is a complex operation. For example, it can
+ * trigger GC which may rehash the table and make the entry invalid.
+ */
+ ++table->generation;
+ if (!(flags & ATOM_TMPSTR) && JSSTRING_IS_FLAT(str)) {
+ JSFLATSTR_CLEAR_MUTABLE(str);
+ key = str;
+ } else {
+ gen = table->generation;
+ JS_UNLOCK(cx, &state->lock);
+
+ if (flags & ATOM_TMPSTR) {
+ if (flags & ATOM_NOCOPY) {
+ key = js_NewString(cx, JSFLATSTR_CHARS(str),
+ JSFLATSTR_LENGTH(str));
+ if (!key)
+ return NULL;
+
+ /* Finish handing off chars to the GC'ed key string. */
+ str->u.chars = NULL;
+ } else {
+ key = js_NewStringCopyN(cx, JSFLATSTR_CHARS(str),
+ JSFLATSTR_LENGTH(str));
+ if (!key)
+ return NULL;
+ }
+ } else {
+ JS_ASSERT(JSSTRING_IS_DEPENDENT(str));
+ if (!js_UndependString(cx, str))
+ return NULL;
+ key = str;
+ }
+
+ JS_LOCK(cx, &state->lock);
+ if (table->generation == gen) {
+ JS_ASSERT(entry->keyAndFlags == 0);
+ } else {
+ entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, key,
+ JS_DHASH_ADD));
+ if (!entry)
+ goto failed_hash_add;
+ if (entry->keyAndFlags != 0) {
+ key = (JSString *)ATOM_ENTRY_KEY(entry);
+ goto finish;
+ }
+ ++table->generation;
+ }
+ }
+ INIT_ATOM_ENTRY(entry, key);
+ JSFLATSTR_SET_ATOMIZED(key);
+ }
+
+ finish:
+ ADD_ATOM_ENTRY_FLAGS(entry, flags & (ATOM_PINNED | ATOM_INTERNED));
+ JS_ASSERT(JSSTRING_IS_ATOMIZED(key));
+ v = STRING_TO_JSVAL(key);
+ cx->weakRoots.lastAtom = v;
+ JS_UNLOCK(cx, &state->lock);
+ return (JSAtom *)v;
+
+ failed_hash_add:
+ JS_UNLOCK(cx, &state->lock);
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+}
+
+JSAtom *
+js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags)
+{
+ jschar *chars;
+ JSString str;
+ JSAtom *atom;
+
+ /*
+ * Avoiding the malloc in js_InflateString on shorter strings saves us
+ * over 20,000 malloc calls on mozilla browser startup. This compares to
+ * only 131 calls where the string is longer than a 31 char (net) buffer.
+ * The vast majority of atomized strings are already in the hashtable. So
+ * js_AtomizeString rarely has to copy the temp string we make.
+ */
+#define ATOMIZE_BUF_MAX 32
+ jschar inflated[ATOMIZE_BUF_MAX];
+ size_t inflatedLength = ATOMIZE_BUF_MAX - 1;
+
+ if (length < ATOMIZE_BUF_MAX) {
+ js_InflateStringToBuffer(cx, bytes, length, inflated, &inflatedLength);
+ inflated[inflatedLength] = 0;
+ chars = inflated;
+ } else {
+ inflatedLength = length;
+ chars = js_InflateString(cx, bytes, &inflatedLength);
+ if (!chars)
+ return NULL;
+ flags |= ATOM_NOCOPY;
+ }
+
+ JSFLATSTR_INIT(&str, (jschar *)chars, inflatedLength);
+ atom = js_AtomizeString(cx, &str, ATOM_TMPSTR | flags);
+ if (chars != inflated && str.u.chars)
+ JS_free(cx, chars);
+ return atom;
+}
+
+JSAtom *
+js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags)
+{
+ JSString str;
+
+ JSFLATSTR_INIT(&str, (jschar *)chars, length);
+ return js_AtomizeString(cx, &str, ATOM_TMPSTR | flags);
+}
+
+JSAtom *
+js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
+{
+ JSString str, *str2;
+ JSAtomState *state;
+ JSDHashEntryHdr *hdr;
+
+ JSFLATSTR_INIT(&str, (jschar *)chars, length);
+ state = &cx->runtime->atomState;
+
+ JS_LOCK(cx, &state->lock);
+ hdr = JS_DHashTableOperate(&state->stringAtoms, &str, JS_DHASH_LOOKUP);
+ str2 = JS_DHASH_ENTRY_IS_BUSY(hdr)
+ ? (JSString *)ATOM_ENTRY_KEY(TO_ATOM_ENTRY(hdr))
+ : NULL;
+ JS_UNLOCK(cx, &state->lock);
+
+ return str2 ? (JSAtom *)STRING_TO_JSVAL(str2) : NULL;
+}
+
+JSBool
+js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp)
+{
+ JSAtom *atom;
+
+ if (JSVAL_IS_STRING(v)) {
+ atom = js_AtomizeString(cx, JSVAL_TO_STRING(v), 0);
+ if (!atom)
+ return JS_FALSE;
+ } else if (JSVAL_IS_DOUBLE(v)) {
+ atom = js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(v));
+ if (!atom)
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_BOOLEAN(v) ||
+ JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v));
+ atom = (JSAtom *)v;
+ }
+ *atomp = atom;
+ return JS_TRUE;
+}
+
+JSBool
+js_ValueToStringId(JSContext *cx, jsval v, jsid *idp)
+{
+ JSString *str;
+ JSAtom *atom;
+
+ /*
+ * Optimize for the common case where v is an already-atomized string. The
+ * comment in jsstr.h before the JSSTRING_SET_ATOMIZED macro's definition
+ * explains why this is thread-safe. The extra rooting via lastAtom (which
+ * would otherwise be done in js_js_AtomizeString) ensures the caller that
+ * the resulting id at is least weakly rooted.
+ */
+ if (JSVAL_IS_STRING(v)) {
+ str = JSVAL_TO_STRING(v);
+ if (JSSTRING_IS_ATOMIZED(str)) {
+ cx->weakRoots.lastAtom = v;
+ *idp = ATOM_TO_JSID((JSAtom *) v);
+ return JS_TRUE;
+ }
+ } else {
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return JS_FALSE;
+ }
+ atom = js_AtomizeString(cx, str, 0);
+ if (!atom)
+ return JS_FALSE;
+ *idp = ATOM_TO_JSID(atom);
+ return JS_TRUE;
+}
+
+#ifdef DEBUG
+
+static JSDHashOperator
+atom_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ FILE *fp = (FILE *)arg;
+ void *key;
+ uintN flags;
+
+ fprintf(fp, "%3u %08x ", number, (uintN)entry->hdr.keyHash);
+ if (entry->keyAndFlags == 0) {
+ fputs("<uninitialized>", fp);
+ } else {
+ key = ATOM_ENTRY_KEY(entry);
+ if (IS_DOUBLE_TABLE(table)) {
+ fprintf(fp, "%.16g", *(jsdouble *)key);
+ } else {
+ JS_ASSERT(IS_STRING_TABLE(table));
+ js_FileEscapedString(fp, (JSString *)key, '"');
+ }
+ flags = ATOM_ENTRY_FLAGS(entry);
+ if (flags != 0) {
+ fputs((flags & (ATOM_PINNED | ATOM_INTERNED))
+ ? " pinned | interned"
+ : (flags & ATOM_PINNED) ? " pinned" : " interned",
+ fp);
+ }
+ }
+ putc('\n', fp);
+ return JS_DHASH_NEXT;
+}
+
+JS_FRIEND_API(void)
+js_DumpAtoms(JSContext *cx, FILE *fp)
+{
+ JSAtomState *state = &cx->runtime->atomState;
+
+ fprintf(fp, "stringAtoms table contents:\n");
+ JS_DHashTableEnumerate(&state->stringAtoms, atom_dumper, fp);
+#ifdef JS_DHASHMETER
+ JS_DHashTableDumpMeter(&state->stringAtoms, atom_dumper, fp);
+#endif
+ putc('\n', fp);
+
+ fprintf(fp, "doubleAtoms table contents:\n");
+ JS_DHashTableEnumerate(&state->doubleAtoms, atom_dumper, fp);
+#ifdef JS_DHASHMETER
+ JS_DHashTableDumpMeter(&state->doubleAtoms, atom_dumper, fp);
+#endif
+ putc('\n', fp);
+}
+
+#endif
+
+static JSHashNumber
+js_hash_atom_ptr(const void *key)
+{
+ const JSAtom *atom = (const JSAtom *) key;
+ return ATOM_HASH(atom);
+}
+
+static void *
+js_alloc_temp_space(void *priv, size_t size)
+{
+ JSContext *cx = (JSContext *) priv;
+ void *space;
+
+ JS_ARENA_ALLOCATE(space, &cx->tempPool, size);
+ if (!space)
+ js_ReportOutOfScriptQuota(cx);
+ return space;
+}
+
+static void
+js_free_temp_space(void *priv, void *item)
+{
+}
+
+static JSHashEntry *
+js_alloc_temp_entry(void *priv, const void *key)
+{
+ JSContext *cx = (JSContext *) priv;
+ JSAtomListElement *ale;
+
+ JS_ARENA_ALLOCATE_TYPE(ale, JSAtomListElement, &cx->tempPool);
+ if (!ale) {
+ js_ReportOutOfScriptQuota(cx);
+ return NULL;
+ }
+ return &ale->entry;
+}
+
+static void
+js_free_temp_entry(void *priv, JSHashEntry *he, uintN flag)
+{
+}
+
+static JSHashAllocOps temp_alloc_ops = {
+ js_alloc_temp_space, js_free_temp_space,
+ js_alloc_temp_entry, js_free_temp_entry
+};
+
+JSAtomListElement *
+js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al)
+{
+ JSAtomListElement *ale, *ale2, *next;
+ JSHashEntry **hep;
+
+ ATOM_LIST_LOOKUP(ale, hep, al, atom);
+ if (!ale) {
+ if (al->count < 10) {
+ /* Few enough for linear search, no hash table needed. */
+ JS_ASSERT(!al->table);
+ ale = (JSAtomListElement *)js_alloc_temp_entry(cx, atom);
+ if (!ale)
+ return NULL;
+ ALE_SET_ATOM(ale, atom);
+ ale->entry.next = al->list;
+ al->list = &ale->entry;
+ } else {
+ /* We want to hash. Have we already made a hash table? */
+ if (!al->table) {
+ /* No hash table yet, so hep had better be null! */
+ JS_ASSERT(!hep);
+ al->table = JS_NewHashTable(al->count + 1, js_hash_atom_ptr,
+ JS_CompareValues, JS_CompareValues,
+ &temp_alloc_ops, cx);
+ if (!al->table)
+ return NULL;
+
+ /*
+ * Set ht->nentries explicitly, because we are moving entries
+ * from al to ht, not calling JS_HashTable(Raw|)Add.
+ */
+ al->table->nentries = al->count;
+
+ /* Insert each ale on al->list into the new hash table. */
+ for (ale2 = (JSAtomListElement *)al->list; ale2; ale2 = next) {
+ next = ALE_NEXT(ale2);
+ ale2->entry.keyHash = ATOM_HASH(ALE_ATOM(ale2));
+ hep = JS_HashTableRawLookup(al->table, ale2->entry.keyHash,
+ ale2->entry.key);
+ ale2->entry.next = *hep;
+ *hep = &ale2->entry;
+ }
+ al->list = NULL;
+
+ /* Set hep for insertion of atom's ale, immediately below. */
+ hep = JS_HashTableRawLookup(al->table, ATOM_HASH(atom), atom);
+ }
+
+ /* Finally, add an entry for atom into the hash bucket at hep. */
+ ale = (JSAtomListElement *)
+ JS_HashTableRawAdd(al->table, hep, ATOM_HASH(atom), atom,
+ NULL);
+ if (!ale)
+ return NULL;
+ }
+
+ ALE_SET_INDEX(ale, al->count++);
+ }
+ return ale;
+}
+
+static intN
+js_map_atom(JSHashEntry *he, intN i, void *arg)
+{
+ JSAtomListElement *ale = (JSAtomListElement *)he;
+ JSAtom **vector = (JSAtom **) arg;
+
+ vector[ALE_INDEX(ale)] = ALE_ATOM(ale);
+ return HT_ENUMERATE_NEXT;
+}
+
+#ifdef DEBUG
+static jsrefcount js_atom_map_count;
+static jsrefcount js_atom_map_hash_table_count;
+#endif
+
+void
+js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al)
+{
+ JSAtom **vector;
+ JSAtomListElement *ale;
+ uint32 count;
+
+ /* Map length must already be initialized. */
+ JS_ASSERT(al->count == map->length);
+#ifdef DEBUG
+ JS_ATOMIC_INCREMENT(&js_atom_map_count);
+#endif
+ ale = (JSAtomListElement *)al->list;
+ if (!ale && !al->table) {
+ JS_ASSERT(!map->vector);
+ return;
+ }
+
+ count = al->count;
+ vector = map->vector;
+ if (al->table) {
+#ifdef DEBUG
+ JS_ATOMIC_INCREMENT(&js_atom_map_hash_table_count);
+#endif
+ JS_HashTableEnumerateEntries(al->table, js_map_atom, vector);
+ } else {
+ do {
+ vector[ALE_INDEX(ale)] = ALE_ATOM(ale);
+ } while ((ale = ALE_NEXT(ale)) != NULL);
+ }
+ ATOM_LIST_INIT(al);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsatom.h b/tools/node_modules/expresso/deps/jscoverage/js/jsatom.h
new file mode 100644
index 0000000..76dd5c4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsatom.h
@@ -0,0 +1,458 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsatom_h___
+#define jsatom_h___
+/*
+ * JS atom table.
+ */
+#include <stddef.h>
+#include "jsversion.h"
+#include "jstypes.h"
+#include "jshash.h" /* Added by JSIFY */
+#include "jsdhash.h"
+#include "jsapi.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jslock.h"
+
+JS_BEGIN_EXTERN_C
+
+#define ATOM_PINNED 0x1 /* atom is pinned against GC */
+#define ATOM_INTERNED 0x2 /* pinned variant for JS_Intern* API */
+#define ATOM_NOCOPY 0x4 /* don't copy atom string bytes */
+#define ATOM_TMPSTR 0x8 /* internal, to avoid extra string */
+
+#define ATOM_KEY(atom) ((jsval)(atom))
+#define ATOM_IS_DOUBLE(atom) JSVAL_IS_DOUBLE(ATOM_KEY(atom))
+#define ATOM_TO_DOUBLE(atom) JSVAL_TO_DOUBLE(ATOM_KEY(atom))
+#define ATOM_IS_STRING(atom) JSVAL_IS_STRING(ATOM_KEY(atom))
+#define ATOM_TO_STRING(atom) JSVAL_TO_STRING(ATOM_KEY(atom))
+
+JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
+JS_STATIC_ASSERT(sizeof(JSAtom *) == JS_BYTES_PER_WORD);
+
+#if JS_BYTES_PER_WORD == 4
+# define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2)
+#elif JS_BYTES_PER_WORD == 8
+# define ATOM_HASH(atom) (((JSHashNumber)(jsuword)(atom) >> 3) ^ \
+ (JSHashNumber)((jsuword)(atom) >> 32))
+#else
+# error "Unsupported configuration"
+#endif
+
+/*
+ * Return a printable, lossless char[] representation of a string-type atom.
+ * The lifetime of the result extends at least until the next GC activation,
+ * longer if cx's string newborn root is not overwritten.
+ */
+extern const char *
+js_AtomToPrintableString(JSContext *cx, JSAtom *atom);
+
+struct JSAtomListElement {
+ JSHashEntry entry;
+};
+
+#define ALE_ATOM(ale) ((JSAtom *) (ale)->entry.key)
+#define ALE_INDEX(ale) ((jsatomid) JS_PTR_TO_UINT32((ale)->entry.value))
+#define ALE_JSOP(ale) ((JSOp) JS_PTR_TO_UINT32((ale)->entry.value))
+#define ALE_VALUE(ale) ((jsval) (ale)->entry.value)
+#define ALE_NEXT(ale) ((JSAtomListElement *) (ale)->entry.next)
+
+#define ALE_SET_ATOM(ale,atom) ((ale)->entry.key = (const void *)(atom))
+#define ALE_SET_INDEX(ale,index)((ale)->entry.value = JS_UINT32_TO_PTR(index))
+#define ALE_SET_JSOP(ale,op) ((ale)->entry.value = JS_UINT32_TO_PTR(op))
+#define ALE_SET_VALUE(ale, v) ((ale)->entry.value = (void *)(v))
+
+struct JSAtomList {
+ JSHashEntry *list; /* literals indexed for mapping */
+ JSHashTable *table; /* hash table if list gets too long */
+ jsuint count; /* count of indexed literals */
+};
+
+#define ATOM_LIST_INIT(al) ((al)->list = NULL, (al)->table = NULL, \
+ (al)->count = 0)
+
+#define ATOM_LIST_SEARCH(_ale,_al,_atom) \
+ JS_BEGIN_MACRO \
+ JSHashEntry **_hep; \
+ ATOM_LIST_LOOKUP(_ale, _hep, _al, _atom); \
+ JS_END_MACRO
+
+#define ATOM_LIST_LOOKUP(_ale,_hep,_al,_atom) \
+ JS_BEGIN_MACRO \
+ if ((_al)->table) { \
+ _hep = JS_HashTableRawLookup((_al)->table, ATOM_HASH(_atom), \
+ _atom); \
+ _ale = *_hep ? (JSAtomListElement *) *_hep : NULL; \
+ } else { \
+ JSHashEntry **_alep = &(_al)->list; \
+ _hep = NULL; \
+ while ((_ale = (JSAtomListElement *)*_alep) != NULL) { \
+ if (ALE_ATOM(_ale) == (_atom)) { \
+ /* Hit, move atom's element to the front of the list. */ \
+ *_alep = (_ale)->entry.next; \
+ (_ale)->entry.next = (_al)->list; \
+ (_al)->list = &_ale->entry; \
+ break; \
+ } \
+ _alep = &_ale->entry.next; \
+ } \
+ } \
+ JS_END_MACRO
+
+struct JSAtomMap {
+ JSAtom **vector; /* array of ptrs to indexed atoms */
+ jsatomid length; /* count of (to-be-)indexed atoms */
+};
+
+struct JSAtomState {
+ JSDHashTable stringAtoms; /* hash table with shared strings */
+ JSDHashTable doubleAtoms; /* hash table with shared doubles */
+#ifdef JS_THREADSAFE
+ JSThinLock lock;
+#endif
+
+ /*
+ * From this point until the end of struct definition the struct must
+ * contain only JSAtom fields. We use this to access the storage occupied
+ * by the common atoms in js_FinishCommonAtoms.
+ *
+ * js_common_atom_names defined in jsatom.c contains C strings for atoms
+ * in the order of atom fields here. Therefore you must update that array
+ * if you change member order here.
+ */
+
+ /* The rt->emptyString atom, see jsstr.c's js_InitRuntimeStringState. */
+ JSAtom *emptyAtom;
+
+ /*
+ * Literal value and type names.
+ * NB: booleanAtoms must come right before typeAtoms!
+ */
+ JSAtom *booleanAtoms[2];
+ JSAtom *typeAtoms[JSTYPE_LIMIT];
+ JSAtom *nullAtom;
+
+ /* Standard class constructor or prototype names. */
+ JSAtom *classAtoms[JSProto_LIMIT];
+
+ /* Various built-in or commonly-used atoms, pinned on first context. */
+ JSAtom *anonymousAtom;
+ JSAtom *applyAtom;
+ JSAtom *argumentsAtom;
+ JSAtom *arityAtom;
+ JSAtom *callAtom;
+ JSAtom *calleeAtom;
+ JSAtom *callerAtom;
+ JSAtom *classPrototypeAtom;
+ JSAtom *constructorAtom;
+ JSAtom *countAtom;
+ JSAtom *eachAtom;
+ JSAtom *evalAtom;
+ JSAtom *fileNameAtom;
+ JSAtom *getAtom;
+ JSAtom *getterAtom;
+ JSAtom *indexAtom;
+ JSAtom *inputAtom;
+ JSAtom *iteratorAtom;
+ JSAtom *lengthAtom;
+ JSAtom *lineNumberAtom;
+ JSAtom *messageAtom;
+ JSAtom *nameAtom;
+ JSAtom *nextAtom;
+ JSAtom *noSuchMethodAtom;
+ JSAtom *parentAtom;
+ JSAtom *protoAtom;
+ JSAtom *setAtom;
+ JSAtom *setterAtom;
+ JSAtom *stackAtom;
+ JSAtom *toLocaleStringAtom;
+ JSAtom *toSourceAtom;
+ JSAtom *toStringAtom;
+ JSAtom *valueOfAtom;
+ JSAtom *toJSONAtom;
+ JSAtom *void0Atom;
+
+#if JS_HAS_XML_SUPPORT
+ JSAtom *etagoAtom;
+ JSAtom *namespaceAtom;
+ JSAtom *ptagcAtom;
+ JSAtom *qualifierAtom;
+ JSAtom *spaceAtom;
+ JSAtom *stagoAtom;
+ JSAtom *starAtom;
+ JSAtom *starQualifierAtom;
+ JSAtom *tagcAtom;
+ JSAtom *xmlAtom;
+#endif
+
+#ifdef NARCISSUS
+ JSAtom *__call__Atom;
+ JSAtom *__construct__Atom;
+ JSAtom *__hasInstance__Atom;
+ JSAtom *ExecutionContextAtom;
+ JSAtom *currentAtom;
+#endif
+
+ /* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
+ struct {
+ JSAtom *InfinityAtom;
+ JSAtom *NaNAtom;
+ JSAtom *XMLListAtom;
+ JSAtom *decodeURIAtom;
+ JSAtom *decodeURIComponentAtom;
+ JSAtom *defineGetterAtom;
+ JSAtom *defineSetterAtom;
+ JSAtom *encodeURIAtom;
+ JSAtom *encodeURIComponentAtom;
+ JSAtom *escapeAtom;
+ JSAtom *functionNamespaceURIAtom;
+ JSAtom *hasOwnPropertyAtom;
+ JSAtom *isFiniteAtom;
+ JSAtom *isNaNAtom;
+ JSAtom *isPrototypeOfAtom;
+ JSAtom *isXMLNameAtom;
+ JSAtom *lookupGetterAtom;
+ JSAtom *lookupSetterAtom;
+ JSAtom *parseFloatAtom;
+ JSAtom *parseIntAtom;
+ JSAtom *propertyIsEnumerableAtom;
+ JSAtom *unescapeAtom;
+ JSAtom *unevalAtom;
+ JSAtom *unwatchAtom;
+ JSAtom *watchAtom;
+ } lazy;
+};
+
+#define ATOM_OFFSET_START offsetof(JSAtomState, emptyAtom)
+#define LAZY_ATOM_OFFSET_START offsetof(JSAtomState, lazy)
+#define ATOM_OFFSET_LIMIT (sizeof(JSAtomState))
+
+#define COMMON_ATOMS_START(state) \
+ ((JSAtom **)((uint8 *)(state) + ATOM_OFFSET_START))
+#define COMMON_ATOM_INDEX(name) \
+ ((offsetof(JSAtomState, name##Atom) - ATOM_OFFSET_START) \
+ / sizeof(JSAtom*))
+#define COMMON_TYPE_ATOM_INDEX(type) \
+ ((offsetof(JSAtomState, typeAtoms[type]) - ATOM_OFFSET_START) \
+ / sizeof(JSAtom*))
+
+/* Start and limit offsets should correspond to atoms. */
+JS_STATIC_ASSERT(ATOM_OFFSET_START % sizeof(JSAtom *) == 0);
+JS_STATIC_ASSERT(ATOM_OFFSET_LIMIT % sizeof(JSAtom *) == 0);
+
+#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom)
+#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off)))
+#define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState,classAtoms[JSProto_##name])
+
+#define CLASS_ATOM(cx,name) \
+ ((cx)->runtime->atomState.classAtoms[JSProto_##name])
+
+extern const char *const js_common_atom_names[];
+extern const size_t js_common_atom_count;
+
+/*
+ * Macros to access C strings for JSType and boolean literals together with
+ * checks that boolean names start from index 1 and type names from 1+2.
+ */
+#define JS_BOOLEAN_STR(type) (js_common_atom_names[1 + (type)])
+#define JS_TYPE_STR(type) (js_common_atom_names[1 + 2 + (type)])
+
+JS_STATIC_ASSERT(1 * sizeof(JSAtom *) ==
+ offsetof(JSAtomState, booleanAtoms) - ATOM_OFFSET_START);
+JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) ==
+ offsetof(JSAtomState, typeAtoms) - ATOM_OFFSET_START);
+
+/* Well-known predefined C strings. */
+#define JS_PROTO(name,code,init) extern const char js_##name##_str[];
+#include "jsproto.tbl"
+#undef JS_PROTO
+
+extern const char js_anonymous_str[];
+extern const char js_apply_str[];
+extern const char js_arguments_str[];
+extern const char js_arity_str[];
+extern const char js_call_str[];
+extern const char js_callee_str[];
+extern const char js_caller_str[];
+extern const char js_class_prototype_str[];
+extern const char js_close_str[];
+extern const char js_constructor_str[];
+extern const char js_count_str[];
+extern const char js_etago_str[];
+extern const char js_each_str[];
+extern const char js_eval_str[];
+extern const char js_fileName_str[];
+extern const char js_get_str[];
+extern const char js_getter_str[];
+extern const char js_index_str[];
+extern const char js_input_str[];
+extern const char js_iterator_str[];
+extern const char js_length_str[];
+extern const char js_lineNumber_str[];
+extern const char js_message_str[];
+extern const char js_name_str[];
+extern const char js_namespace_str[];
+extern const char js_next_str[];
+extern const char js_noSuchMethod_str[];
+extern const char js_object_str[];
+extern const char js_parent_str[];
+extern const char js_proto_str[];
+extern const char js_ptagc_str[];
+extern const char js_qualifier_str[];
+extern const char js_send_str[];
+extern const char js_setter_str[];
+extern const char js_set_str[];
+extern const char js_space_str[];
+extern const char js_stack_str[];
+extern const char js_stago_str[];
+extern const char js_star_str[];
+extern const char js_starQualifier_str[];
+extern const char js_tagc_str[];
+extern const char js_toSource_str[];
+extern const char js_toString_str[];
+extern const char js_toLocaleString_str[];
+extern const char js_undefined_str[];
+extern const char js_valueOf_str[];
+extern const char js_toJSON_str[];
+extern const char js_xml_str[];
+
+#ifdef NARCISSUS
+extern const char js___call___str[];
+extern const char js___construct___str[];
+extern const char js___hasInstance___str[];
+extern const char js_ExecutionContext_str[];
+extern const char js_current_str[];
+#endif
+
+/*
+ * Initialize atom state. Return true on success, false on failure to allocate
+ * memory. The caller must zero rt->atomState before calling this function and
+ * only call it after js_InitGC successfully returns.
+ */
+extern JSBool
+js_InitAtomState(JSRuntime *rt);
+
+/*
+ * Free and clear atom state including any interned string atoms. This
+ * function must be called before js_FinishGC.
+ */
+extern void
+js_FinishAtomState(JSRuntime *rt);
+
+/*
+ * Atom tracing and garbage collection hooks.
+ */
+
+extern void
+js_TraceAtomState(JSTracer *trc, JSBool allAtoms);
+
+extern void
+js_SweepAtomState(JSContext *cx);
+
+extern JSBool
+js_InitCommonAtoms(JSContext *cx);
+
+extern void
+js_FinishCommonAtoms(JSContext *cx);
+
+/*
+ * Find or create the atom for a double value. Return null on failure to
+ * allocate memory.
+ */
+extern JSAtom *
+js_AtomizeDouble(JSContext *cx, jsdouble d);
+
+/*
+ * Find or create the atom for a string. Return null on failure to allocate
+ * memory.
+ */
+extern JSAtom *
+js_AtomizeString(JSContext *cx, JSString *str, uintN flags);
+
+extern JSAtom *
+js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags);
+
+extern JSAtom *
+js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags);
+
+/*
+ * Return an existing atom for the given char array or null if the char
+ * sequence is currently not atomized.
+ */
+extern JSAtom *
+js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length);
+
+/*
+ * This variant handles all primitive values.
+ */
+JSBool
+js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp);
+
+/*
+ * Convert v to an atomized string and wrap it as an id.
+ */
+extern JSBool
+js_ValueToStringId(JSContext *cx, jsval v, jsid *idp);
+
+#ifdef DEBUG
+
+extern JS_FRIEND_API(void)
+js_DumpAtoms(JSContext *cx, FILE *fp);
+
+#endif
+
+/*
+ * Assign atom an index and insert it on al.
+ */
+extern JSAtomListElement *
+js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al);
+
+/*
+ * For all unmapped atoms recorded in al, add a mapping from the atom's index
+ * to its address. map->length must already be set to the number of atoms in
+ * the list and map->vector must point to pre-allocated memory.
+ */
+extern void
+js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al);
+
+JS_END_EXTERN_C
+
+#endif /* jsatom_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsbit.h b/tools/node_modules/expresso/deps/jscoverage/js/jsbit.h
new file mode 100644
index 0000000..f54199b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsbit.h
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsbit_h___
+#define jsbit_h___
+
+#include "jstypes.h"
+#include "jsutil.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+** A jsbitmap_t is a long integer that can be used for bitmaps
+*/
+typedef JSUword jsbitmap_t; /* NSPR name, a la Unix system types */
+typedef jsbitmap_t jsbitmap; /* JS-style scalar typedef name */
+
+#define JS_BITMAP_SIZE(bits) (JS_HOWMANY(bits, JS_BITS_PER_WORD) * \
+ sizeof(jsbitmap))
+
+#define JS_TEST_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] & \
+ ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
+#define JS_SET_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] |= \
+ ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
+#define JS_CLEAR_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &= \
+ ~((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
+
+/*
+** Compute the log of the least power of 2 greater than or equal to n
+*/
+extern JS_PUBLIC_API(JSIntn) JS_CeilingLog2(JSUint32 i);
+
+/*
+** Compute the log of the greatest power of 2 less than or equal to n
+*/
+extern JS_PUBLIC_API(JSIntn) JS_FloorLog2(JSUint32 i);
+
+/*
+ * Replace bit-scanning code sequences with CPU-specific instructions to
+ * speedup calculations of ceiling/floor log2.
+ *
+ * With GCC 3.4 or later we can use __builtin_clz for that, see bug 327129.
+ *
+ * SWS: Added MSVC intrinsic bitscan support. See bugs 349364 and 356856.
+ */
+#if defined(_WIN32) && (_MSC_VER >= 1300) && defined(_M_IX86)
+
+unsigned char _BitScanForward(unsigned long * Index, unsigned long Mask);
+unsigned char _BitScanReverse(unsigned long * Index, unsigned long Mask);
+# pragma intrinsic(_BitScanForward,_BitScanReverse)
+
+__forceinline static int
+__BitScanForward32(unsigned int val)
+{
+ unsigned long idx;
+
+ _BitScanForward(&idx, (unsigned long)val);
+ return (int)idx;
+}
+__forceinline static int
+__BitScanReverse32(unsigned int val)
+{
+ unsigned long idx;
+
+ _BitScanReverse(&idx, (unsigned long)val);
+ return (int)(31-idx);
+}
+# define js_bitscan_ctz32(val) __BitScanForward32(val)
+# define js_bitscan_clz32(val) __BitScanReverse32(val)
+# define JS_HAS_BUILTIN_BITSCAN32
+
+#elif (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+
+# define js_bitscan_ctz32(val) __builtin_ctz(val)
+# define js_bitscan_clz32(val) __builtin_clz(val)
+# define JS_HAS_BUILTIN_BITSCAN32
+# if (JS_BYTES_PER_WORD == 8)
+# define js_bitscan_ctz64(val) __builtin_ctzll(val)
+# define js_bitscan_clz64(val) __builtin_clzll(val)
+# define JS_HAS_BUILTIN_BITSCAN64
+# endif
+
+#endif
+
+/*
+** Macro version of JS_CeilingLog2: Compute the log of the least power of
+** 2 greater than or equal to _n. The result is returned in _log2.
+*/
+#ifdef JS_HAS_BUILTIN_BITSCAN32
+/*
+ * Use intrinsic function or count-leading-zeros to calculate ceil(log2(_n)).
+ * The macro checks for "n <= 1" and not "n != 0" as js_bitscan_clz32(0) is
+ * undefined.
+ */
+# define JS_CEILING_LOG2(_log2,_n) \
+ JS_BEGIN_MACRO \
+ JS_STATIC_ASSERT(sizeof(unsigned int) == sizeof(JSUint32)); \
+ unsigned int j_ = (unsigned int)(_n); \
+ (_log2) = (j_ <= 1 ? 0 : 32 - js_bitscan_clz32(j_ - 1)); \
+ JS_END_MACRO
+#else
+# define JS_CEILING_LOG2(_log2,_n) \
+ JS_BEGIN_MACRO \
+ JSUint32 j_ = (JSUint32)(_n); \
+ (_log2) = 0; \
+ if ((j_) & ((j_)-1)) \
+ (_log2) += 1; \
+ if ((j_) >> 16) \
+ (_log2) += 16, (j_) >>= 16; \
+ if ((j_) >> 8) \
+ (_log2) += 8, (j_) >>= 8; \
+ if ((j_) >> 4) \
+ (_log2) += 4, (j_) >>= 4; \
+ if ((j_) >> 2) \
+ (_log2) += 2, (j_) >>= 2; \
+ if ((j_) >> 1) \
+ (_log2) += 1; \
+ JS_END_MACRO
+#endif
+
+/*
+** Macro version of JS_FloorLog2: Compute the log of the greatest power of
+** 2 less than or equal to _n. The result is returned in _log2.
+**
+** This is equivalent to finding the highest set bit in the word.
+*/
+#ifdef JS_HAS_BUILTIN_BITSCAN32
+/*
+ * Use js_bitscan_clz32 or count-leading-zeros to calculate floor(log2(_n)).
+ * Since js_bitscan_clz32(0) is undefined, the macro set the loweset bit to 1
+ * to ensure 0 result when _n == 0.
+ */
+# define JS_FLOOR_LOG2(_log2,_n) \
+ JS_BEGIN_MACRO \
+ JS_STATIC_ASSERT(sizeof(unsigned int) == sizeof(JSUint32)); \
+ (_log2) = 31 - js_bitscan_clz32(((unsigned int)(_n)) | 1); \
+ JS_END_MACRO
+#else
+# define JS_FLOOR_LOG2(_log2,_n) \
+ JS_BEGIN_MACRO \
+ JSUint32 j_ = (JSUint32)(_n); \
+ (_log2) = 0; \
+ if ((j_) >> 16) \
+ (_log2) += 16, (j_) >>= 16; \
+ if ((j_) >> 8) \
+ (_log2) += 8, (j_) >>= 8; \
+ if ((j_) >> 4) \
+ (_log2) += 4, (j_) >>= 4; \
+ if ((j_) >> 2) \
+ (_log2) += 2, (j_) >>= 2; \
+ if ((j_) >> 1) \
+ (_log2) += 1; \
+ JS_END_MACRO
+#endif
+
+/*
+ * Internal function.
+ * Compute the log of the least power of 2 greater than or equal to n.
+ * This is a version of JS_CeilingLog2 that operates on jsuword with
+ * CPU-dependant size.
+ */
+#define JS_CEILING_LOG2W(n) ((n) <= 1 ? 0 : 1 + JS_FLOOR_LOG2W((n) - 1))
+
+/*
+ * Internal function.
+ * Compute the log of the greatest power of 2 less than or equal to n.
+ * This is a version of JS_FloorLog2 that operates on jsuword with
+ * CPU-dependant size and requires that n != 0.
+ */
+#define JS_FLOOR_LOG2W(n) (JS_ASSERT((n) != 0), js_FloorLog2wImpl(n))
+
+#if JS_BYTES_PER_WORD == 4
+
+# ifdef JS_HAS_BUILTIN_BITSCAN32
+JS_STATIC_ASSERT(sizeof(unsigned) == sizeof(JSUword));
+# define js_FloorLog2wImpl(n) \
+ ((JSUword)(JS_BITS_PER_WORD - 1 - js_bitscan_clz32(n)))
+# else
+# define js_FloorLog2wImpl(n) ((JSUword)JS_FloorLog2(n))
+#endif
+
+#elif JS_BYTES_PER_WORD == 8
+
+# ifdef JS_HAS_BUILTIN_BITSCAN64
+JS_STATIC_ASSERT(sizeof(unsigned long long) == sizeof(JSUword));
+# define js_FloorLog2wImpl(n) \
+ ((JSUword)(JS_BITS_PER_WORD - 1 - js_bitscan_clz64(n)))
+# else
+extern JSUword js_FloorLog2wImpl(JSUword n);
+# endif
+
+#else
+
+# error "NOT SUPPORTED"
+
+#endif
+
+/*
+ * Macros for rotate left. There is no rotate operation in the C Language so
+ * the construct (a << 4) | (a >> 28) is used instead. Most compilers convert
+ * this to a rotate instruction but some versions of MSVC don't without a
+ * little help. To get MSVC to generate a rotate instruction, we have to use
+ * the _rotl intrinsic and use a pragma to make _rotl inline.
+ *
+ * MSVC in VS2005 will do an inline rotate instruction on the above construct.
+ */
+
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || \
+ defined(_M_X64))
+#include <stdlib.h>
+#pragma intrinsic(_rotl)
+#define JS_ROTATE_LEFT32(a, bits) _rotl(a, bits)
+#else
+#define JS_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits))))
+#endif
+
+JS_END_EXTERN_C
+#endif /* jsbit_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsbool.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsbool.cpp
new file mode 100644
index 0000000..9167fa1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsbool.cpp
@@ -0,0 +1,182 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS boolean implementation.
+ */
+#include "jsstddef.h"
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsstr.h"
+
+/* Check pseudo-booleans values. */
+JS_STATIC_ASSERT(JSVAL_VOID == JSVAL_TRUE + JSVAL_ALIGN);
+JS_STATIC_ASSERT(JSVAL_HOLE == JSVAL_VOID + JSVAL_ALIGN);
+JS_STATIC_ASSERT(JSVAL_ARETURN == JSVAL_HOLE + JSVAL_ALIGN);
+
+JSClass js_BooleanClass = {
+ "Boolean",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+#if JS_HAS_TOSOURCE
+#include "jsprf.h"
+
+static JSBool
+bool_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ char buf[32];
+ JSString *str;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
+ JS_snprintf(buf, sizeof buf, "(new %s(%s))",
+ js_BooleanClass.name,
+ JS_BOOLEAN_STR(JSVAL_TO_BOOLEAN(v)));
+ str = JS_NewStringCopyZ(cx, buf);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif
+
+static JSBool
+bool_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ JSAtom *atom;
+ JSString *str;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
+ atom = cx->runtime->atomState.booleanAtoms[JSVAL_TO_BOOLEAN(v) ? 1 : 0];
+ str = ATOM_TO_STRING(atom);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+bool_valueOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_GetPrimitiveThis(cx, vp, &js_BooleanClass, vp);
+}
+
+static JSFunctionSpec boolean_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, bool_toSource, 0, JSFUN_THISP_BOOLEAN),
+#endif
+ JS_FN(js_toString_str, bool_toString, 0, JSFUN_THISP_BOOLEAN),
+ JS_FN(js_valueOf_str, bool_valueOf, 0, JSFUN_THISP_BOOLEAN),
+ JS_FN(js_toJSON_str, bool_valueOf, 0, JSFUN_THISP_BOOLEAN),
+ JS_FS_END
+};
+
+static JSBool
+Boolean(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsval bval;
+
+ bval = (argc != 0)
+ ? BOOLEAN_TO_JSVAL(js_ValueToBoolean(argv[0]))
+ : JSVAL_FALSE;
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ *rval = bval;
+ return JS_TRUE;
+ }
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, bval);
+ return JS_TRUE;
+}
+
+JSObject *
+js_InitBooleanClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1,
+ NULL, boolean_methods, NULL, NULL);
+ if (!proto)
+ return NULL;
+ STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE, JSVAL_FALSE);
+ return proto;
+}
+
+JSString *
+js_BooleanToString(JSContext *cx, JSBool b)
+{
+ return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[b ? 1 : 0]);
+}
+
+JSBool
+js_ValueToBoolean(jsval v)
+{
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
+ return JS_FALSE;
+ if (JSVAL_IS_OBJECT(v))
+ return JS_TRUE;
+ if (JSVAL_IS_STRING(v))
+ return JSSTRING_LENGTH(JSVAL_TO_STRING(v)) != 0;
+ if (JSVAL_IS_INT(v))
+ return JSVAL_TO_INT(v) != 0;
+ if (JSVAL_IS_DOUBLE(v)) {
+ jsdouble d;
+
+ d = *JSVAL_TO_DOUBLE(v);
+ return !JSDOUBLE_IS_NaN(d) && d != 0;
+ }
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
+ return JSVAL_TO_BOOLEAN(v);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsbool.h b/tools/node_modules/expresso/deps/jscoverage/js/jsbool.h
new file mode 100644
index 0000000..f76de2e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsbool.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsbool_h___
+#define jsbool_h___
+/*
+ * JS boolean interface.
+ */
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Pseudo-booleans, not visible to script but used internally by the engine.
+ *
+ * JSVAL_HOLE is a useful value for identifying a hole in an array. It's also
+ * used in the interpreter to represent "no exception pending". In general it
+ * can be used to represent "no value".
+ *
+ * JSVAL_ARETURN is used to throw asynchronous return for generator.close().
+ *
+ * NB: BOOLEAN_TO_JSVAL(2) is JSVAL_VOID (see jsapi.h).
+ */
+#define JSVAL_HOLE BOOLEAN_TO_JSVAL(3)
+#define JSVAL_ARETURN BOOLEAN_TO_JSVAL(4)
+
+extern JSClass js_BooleanClass;
+
+extern JSObject *
+js_InitBooleanClass(JSContext *cx, JSObject *obj);
+
+extern JSString *
+js_BooleanToString(JSContext *cx, JSBool b);
+
+extern JSBool
+js_ValueToBoolean(jsval v);
+
+JS_END_EXTERN_C
+
+#endif /* jsbool_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.cpp
new file mode 100644
index 0000000..8a21edb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.cpp
@@ -0,0 +1,497 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * May 28, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Andreas Gal <gal@mozilla.com>
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org>
+ * Mike Shaver <shaver@mozilla.org>
+ * David Anderson <danderson@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h"
+#include <math.h>
+
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsgc.h"
+#include "jsiter.h"
+#include "jslibmath.h"
+#include "jsmath.h"
+#include "jsnum.h"
+#include "prmjtime.h"
+#include "jsdate.h"
+#include "jsscope.h"
+#include "jsstr.h"
+#include "jsbuiltins.h"
+#include "jstracer.h"
+
+using namespace avmplus;
+using namespace nanojit;
+
+extern jsdouble js_NaN;
+
+/*
+ * NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
+ * Do not use bool FASTCALL, use JSBool only!
+ */
+
+jsdouble FASTCALL
+js_dmod(jsdouble a, jsdouble b)
+{
+ if (b == 0.0) {
+ jsdpun u;
+ u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
+ u.s.lo = 0xffffffff;
+ return u.d;
+ }
+ jsdouble r;
+#ifdef XP_WIN
+ /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
+ if (JSDOUBLE_IS_FINITE(a) && JSDOUBLE_IS_INFINITE(b))
+ r = a;
+ else
+#endif
+ r = fmod(a, b);
+ return r;
+}
+
+int32 FASTCALL
+js_imod(int32 a, int32 b)
+{
+ if (a < 0 || b <= 0)
+ return -1;
+ int r = a % b;
+ return r;
+}
+
+/* The following boxing/unboxing primitives we can't emit inline because
+ they either interact with the GC and depend on Spidermonkey's 32-bit
+ integer representation. */
+
+jsval FASTCALL
+js_BoxDouble(JSContext* cx, jsdouble d)
+{
+ int32 i;
+ if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i))
+ return INT_TO_JSVAL(i);
+ JS_ASSERT(JS_ON_TRACE(cx));
+ jsval v; /* not rooted but ok here because we know GC won't run */
+ if (!js_NewDoubleInRootedValue(cx, d, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+jsval FASTCALL
+js_BoxInt32(JSContext* cx, int32 i)
+{
+ if (JS_LIKELY(INT_FITS_IN_JSVAL(i)))
+ return INT_TO_JSVAL(i);
+ JS_ASSERT(JS_ON_TRACE(cx));
+ jsval v; /* not rooted but ok here because we know GC won't run */
+ jsdouble d = (jsdouble)i;
+ if (!js_NewDoubleInRootedValue(cx, d, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+jsdouble FASTCALL
+js_UnboxDouble(jsval v)
+{
+ if (JS_LIKELY(JSVAL_IS_INT(v)))
+ return (jsdouble)JSVAL_TO_INT(v);
+ return *JSVAL_TO_DOUBLE(v);
+}
+
+int32 FASTCALL
+js_UnboxInt32(jsval v)
+{
+ if (JS_LIKELY(JSVAL_IS_INT(v)))
+ return JSVAL_TO_INT(v);
+ return js_DoubleToECMAInt32(*JSVAL_TO_DOUBLE(v));
+}
+
+int32 FASTCALL
+js_DoubleToInt32(jsdouble d)
+{
+ return js_DoubleToECMAInt32(d);
+}
+
+uint32 FASTCALL
+js_DoubleToUint32(jsdouble d)
+{
+ return js_DoubleToECMAUint32(d);
+}
+
+jsdouble FASTCALL
+js_StringToNumber(JSContext* cx, JSString* str)
+{
+ const jschar* bp;
+ const jschar* end;
+ const jschar* ep;
+ jsdouble d;
+
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if ((!js_strtod(cx, bp, end, &ep, &d) ||
+ js_SkipWhiteSpace(ep, end) != end) &&
+ (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
+ js_SkipWhiteSpace(ep, end) != end)) {
+ return js_NaN;
+ }
+ return d;
+}
+
+int32 FASTCALL
+js_StringToInt32(JSContext* cx, JSString* str)
+{
+ const jschar* bp;
+ const jschar* end;
+ const jschar* ep;
+ jsdouble d;
+
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if (!js_strtod(cx, bp, end, &ep, &d) || js_SkipWhiteSpace(ep, end) != end)
+ return 0;
+ return js_DoubleToECMAInt32(d);
+}
+
+static inline JSBool
+js_Int32ToId(JSContext* cx, int32 index, jsid* id)
+{
+ if (index <= JSVAL_INT_MAX) {
+ *id = INT_TO_JSID(index);
+ return JS_TRUE;
+ }
+ JSString* str = js_NumberToString(cx, index);
+ if (!str)
+ return JS_FALSE;
+ return js_ValueToStringId(cx, STRING_TO_JSVAL(str), id);
+}
+
+jsval FASTCALL
+js_Any_getprop(JSContext* cx, JSObject* obj, JSString* idstr)
+{
+ jsval v;
+ jsid id;
+
+ if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
+ return JSVAL_ERROR_COOKIE;
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+JSBool FASTCALL
+js_Any_setprop(JSContext* cx, JSObject* obj, JSString* idstr, jsval v)
+{
+ jsid id;
+ if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
+ return JS_FALSE;
+ return OBJ_SET_PROPERTY(cx, obj, id, &v);
+}
+
+jsval FASTCALL
+js_Any_getelem(JSContext* cx, JSObject* obj, int32 index)
+{
+ jsval v;
+ jsid id;
+ if (!js_Int32ToId(cx, index, &id))
+ return JSVAL_ERROR_COOKIE;
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+JSBool FASTCALL
+js_Any_setelem(JSContext* cx, JSObject* obj, int32 index, jsval v)
+{
+ jsid id;
+ if (!js_Int32ToId(cx, index, &id))
+ return JSVAL_ERROR_COOKIE;
+ return OBJ_SET_PROPERTY(cx, obj, id, &v);
+}
+
+JSObject* FASTCALL
+js_FastValueToIterator(JSContext* cx, jsuint flags, jsval v)
+{
+ if (!js_ValueToIterator(cx, flags, &v))
+ return NULL;
+ return JSVAL_TO_OBJECT(v);
+}
+
+jsval FASTCALL
+js_FastCallIteratorNext(JSContext* cx, JSObject* iterobj)
+{
+ jsval v;
+ if (!js_CallIteratorNext(cx, iterobj, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+SideExit* FASTCALL
+js_CallTree(InterpState* state, Fragment* f)
+{
+ union { NIns *code; GuardRecord* (FASTCALL *func)(InterpState*, Fragment*); } u;
+
+ u.code = f->code();
+ JS_ASSERT(u.code);
+
+ GuardRecord* rec;
+#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
+ SIMULATE_FASTCALL(rec, state, NULL, u.func);
+#else
+ rec = u.func(state, NULL);
+#endif
+ VMSideExit* lr = (VMSideExit*)rec->exit;
+
+ if (lr->exitType == NESTED_EXIT) {
+ /* This only occurs once a tree call guard mismatches and we unwind the tree call stack.
+ We store the first (innermost) tree call guard in state and we will try to grow
+ the outer tree the failing call was in starting at that guard. */
+ if (!state->lastTreeCallGuard) {
+ state->lastTreeCallGuard = lr;
+ FrameInfo* rp = (FrameInfo*)state->rp;
+ state->rpAtLastTreeCall = rp + lr->calldepth;
+ }
+ } else {
+ /* If the tree exits on a regular (non-nested) guard, keep updating lastTreeExitGuard
+ with that guard. If we mismatch on a tree call guard, this will contain the last
+ non-nested guard we encountered, which is the innermost loop or branch guard. */
+ state->lastTreeExitGuard = lr;
+ }
+
+ return lr;
+}
+
+JSObject* FASTCALL
+js_FastNewObject(JSContext* cx, JSObject* ctor)
+{
+ JS_ASSERT(HAS_FUNCTION_CLASS(ctor));
+ JSFunction* fun = GET_FUNCTION_PRIVATE(cx, ctor);
+ JSClass* clasp = (FUN_INTERPRETED(fun) || (fun->flags & JSFUN_TRACEABLE))
+ ? &js_ObjectClass
+ : FUN_CLASP(fun);
+ JS_ASSERT(clasp != &js_ArrayClass);
+
+ JS_LOCK_OBJ(cx, ctor);
+ JSScope *scope = OBJ_SCOPE(ctor);
+ JS_ASSERT(scope->object == ctor);
+ JSAtom* atom = cx->runtime->atomState.classPrototypeAtom;
+
+ JSScopeProperty *sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom));
+ JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, scope));
+ jsval v = LOCKED_OBJ_GET_SLOT(ctor, sprop->slot);
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ JSObject* proto;
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ if (!js_GetClassPrototype(cx, JSVAL_TO_OBJECT(ctor->fslots[JSSLOT_PARENT]),
+ INT_TO_JSID(JSProto_Object), &proto)) {
+ return NULL;
+ }
+ } else {
+ proto = JSVAL_TO_OBJECT(v);
+ }
+
+ JS_ASSERT(JS_ON_TRACE(cx));
+ JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
+ if (!obj)
+ return NULL;
+
+ obj->classword = jsuword(clasp);
+ obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
+ obj->fslots[JSSLOT_PARENT] = ctor->fslots[JSSLOT_PARENT];
+ for (unsigned i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i)
+ obj->fslots[i] = JSVAL_VOID;
+
+ obj->map = js_HoldObjectMap(cx, proto->map);
+ obj->dslots = NULL;
+ return obj;
+}
+
+JSBool FASTCALL
+js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
+{
+ JSScopeProperty* sprop2 = NULL; // initialize early to make MSVC happy
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ JS_ASSERT(SPROP_HAS_STUB_SETTER(sprop));
+
+ JS_LOCK_OBJ(cx, obj);
+ JSScope* scope = OBJ_SCOPE(obj);
+ if (scope->object == obj) {
+ JS_ASSERT(!SCOPE_HAS_PROPERTY(scope, sprop));
+ } else {
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+ }
+ }
+
+ uint32 slot = sprop->slot;
+ if (!scope->table && sprop->parent == scope->lastProp && slot == scope->map.freeslot) {
+ if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) {
+ JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->map.freeslot)));
+ ++scope->map.freeslot;
+ } else {
+ if (!js_AllocSlot(cx, obj, &slot)) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE;
+ }
+
+ if (slot != sprop->slot)
+ goto slot_changed;
+ }
+
+ SCOPE_EXTEND_SHAPE(cx, scope, sprop);
+ ++scope->entryCount;
+ scope->lastProp = sprop;
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+ }
+
+ sprop2 = js_AddScopeProperty(cx, scope, sprop->id,
+ sprop->getter, sprop->setter, SPROP_INVALID_SLOT,
+ sprop->attrs, sprop->flags, sprop->shortid);
+ if (sprop2 == sprop) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+ }
+ slot = sprop2->slot;
+
+ slot_changed:
+ js_FreeSlot(cx, obj, slot);
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE;
+}
+
+JSBool FASTCALL
+js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr)
+{
+ jsid id;
+ if (!obj || !js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+
+ JSObject* obj2;
+ JSProperty* prop;
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return prop != NULL;
+}
+
+JSBool FASTCALL
+js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index)
+{
+ jsid id;
+ if (!obj || !js_Int32ToId(cx, index, &id))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+
+ JSObject* obj2;
+ JSProperty* prop;
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return prop != NULL;
+}
+
+jsval FASTCALL
+js_CallGetter(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
+{
+ JS_ASSERT(!SPROP_HAS_STUB_GETTER(sprop));
+ jsval v;
+ if (!SPROP_GET(cx, sprop, obj, obj, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+JSString* FASTCALL
+js_TypeOfObject(JSContext* cx, JSObject* obj)
+{
+ JSType type = JS_TypeOfValue(cx, OBJECT_TO_JSVAL(obj));
+ return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
+}
+
+JSString* FASTCALL
+js_TypeOfBoolean(JSContext* cx, int32 unboxed)
+{
+ jsval boxed = BOOLEAN_TO_JSVAL(unboxed);
+ JS_ASSERT(JSVAL_IS_VOID(boxed) || JSVAL_IS_BOOLEAN(boxed));
+ JSType type = JS_TypeOfValue(cx, boxed);
+ return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
+}
+
+jsdouble FASTCALL
+js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed)
+{
+ if (unboxed == JSVAL_TO_BOOLEAN(JSVAL_VOID))
+ return js_NaN;
+ return unboxed;
+}
+
+JSString* FASTCALL
+js_BooleanOrUndefinedToString(JSContext *cx, int32 unboxed)
+{
+ JS_ASSERT(uint32(unboxed) <= 2);
+ return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[unboxed]);
+}
+
+JSString* FASTCALL
+js_ObjectToString(JSContext* cx, JSObject* obj)
+{
+ if (!obj)
+ return ATOM_TO_STRING(cx->runtime->atomState.nullAtom);
+ jsval v;
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ return JSVAL_TO_STRING(v);
+}
+
+JSObject* FASTCALL
+js_Arguments(JSContext* cx)
+{
+ return NULL;
+}
+
+#define BUILTIN1 JS_DEFINE_CALLINFO_1
+#define BUILTIN2 JS_DEFINE_CALLINFO_2
+#define BUILTIN3 JS_DEFINE_CALLINFO_3
+#define BUILTIN4 JS_DEFINE_CALLINFO_4
+#define BUILTIN5 JS_DEFINE_CALLINFO_5
+#include "builtins.tbl"
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.h b/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.h
new file mode 100644
index 0000000..366d24f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.h
@@ -0,0 +1,374 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * May 28, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ *
+ * Contributor(s):
+ * Jason Orendorff <jorendorff@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsbuiltins_h___
+#define jsbuiltins_h___
+
+#ifdef JS_TRACER
+
+#include "nanojit/nanojit.h"
+#include "jstracer.h"
+
+enum JSTNErrType { INFALLIBLE, FAIL_NULL, FAIL_NEG, FAIL_VOID, FAIL_JSVAL };
+enum { JSTN_ERRTYPE_MASK = 7, JSTN_MORE = 8 };
+
+#define JSTN_ERRTYPE(jstn) ((jstn)->flags & JSTN_ERRTYPE_MASK)
+
+/*
+ * |prefix| and |argtypes| declare what arguments should be passed to the
+ * native function. |prefix| can contain the following characters:
+ *
+ * 'C': a JSContext* argument
+ * 'T': |this| as a JSObject* argument (bails if |this| is not an object)
+ * 'S': |this| as a JSString* argument (bails if |this| is not a string)
+ * 'R': a JSRuntime* argument
+ * 'P': the pc as a jsbytecode*
+ * 'D': |this| as a number (jsdouble)
+ * 'f': the function being called, as a JSObject*
+ * 'p': the .prototype of the function, as a JSObject*
+ *
+ * The corresponding things will get passed as arguments to the builtin in
+ * reverse order (so TC means JSContext* as the first arg, and the
+ * JSObject* for |this| as the second arg).
+ *
+ * |argtypes| can contain the following characters:
+ * 'd': a number (double) argument
+ * 'i': an integer argument
+ * 's': a JSString* argument
+ * 'o': a JSObject* argument
+ * 'r': a JSObject* argument that is of class js_RegExpClass
+ * 'f': a JSObject* argument that is of class js_FunctionClass
+ * 'v': a jsval argument (boxing whatever value is actually being passed in)
+ */
+struct JSTraceableNative {
+ JSFastNative native;
+ const nanojit::CallInfo *builtin;
+ const char *prefix;
+ const char *argtypes;
+ uintN flags; /* JSTN_MORE | JSTNErrType */
+};
+
+/*
+ * We use a magic boxed pointer value to represent error conditions that
+ * trigger a side exit. The address is so low that it should never be actually
+ * in use. If it is, a performance regression occurs, not an actual runtime
+ * error.
+ */
+#define JSVAL_ERROR_COOKIE OBJECT_TO_JSVAL((void*)0x10)
+
+/* Macros used by JS_DEFINE_CALLINFOn. */
+#ifdef DEBUG
+#define _JS_CI_NAME(op) ,#op
+#else
+#define _JS_CI_NAME(op)
+#endif
+
+#define _JS_I32_ARGSIZE nanojit::ARGSIZE_LO
+#define _JS_I32_RETSIZE nanojit::ARGSIZE_LO
+#define _JS_F64_ARGSIZE nanojit::ARGSIZE_F
+#define _JS_F64_RETSIZE nanojit::ARGSIZE_F
+#define _JS_PTR_ARGSIZE nanojit::ARGSIZE_LO
+#if defined AVMPLUS_64BIT
+# define _JS_PTR_RETSIZE nanojit::ARGSIZE_Q
+#else
+# define _JS_PTR_RETSIZE nanojit::ARGSIZE_LO
+#endif
+
+/*
+ * Supported types for builtin functions.
+ *
+ * Types with -- for the two string fields are not permitted as argument types
+ * in JS_DEFINE_TRCINFO.
+ *
+ * If a traceable native can fail, the values that indicate failure are part of
+ * the return type:
+ * JSVAL_FAIL: JSVAL_ERROR_COOKIE
+ * BOOL_FAIL: JSVAL_TO_BOOLEAN(JSVAL_VOID)
+ * INT32_FAIL: any negative value
+ * STRING_FAIL: NULL
+ * OBJECT_FAIL_NULL: NULL
+ * OBJECT_FAIL_VOID: JSVAL_TO_OBJECT(JSVAL_VOID)
+ * (NULL means the function successfully returned JS null.)
+ *
+ * Special builtins known to the tracer can have their own idiosyncratic
+ * error codes.
+ *
+ * When a traceable native returns a value indicating failure, we fall off
+ * trace. If an exception is pending, it is thrown; otherwise, we assume the
+ * builtin had no side effects and retry the current bytecode in the
+ * interpreter.
+ *
+ * So a builtin must not return a value indicating failure after causing side
+ * effects (such as reporting an error), without setting an exception pending.
+ * The operation would be retried, despite the first attempt's observable
+ * effects.
+ */
+#define _JS_CTYPE(ctype, size, pch, ach, flags) (ctype, size, pch, ach, flags)
+#define _JS_CTYPE_CONTEXT _JS_CTYPE(JSContext *, _JS_PTR,"C", "", INFALLIBLE)
+#define _JS_CTYPE_RUNTIME _JS_CTYPE(JSRuntime *, _JS_PTR,"R", "", INFALLIBLE)
+#define _JS_CTYPE_THIS _JS_CTYPE(JSObject *, _JS_PTR,"T", "", INFALLIBLE)
+#define _JS_CTYPE_THIS_DOUBLE _JS_CTYPE(jsdouble, _JS_F64,"D", "", INFALLIBLE)
+#define _JS_CTYPE_THIS_STRING _JS_CTYPE(JSString *, _JS_PTR,"S", "", INFALLIBLE)
+#define _JS_CTYPE_PC _JS_CTYPE(jsbytecode *, _JS_PTR,"P", "", INFALLIBLE)
+#define _JS_CTYPE_JSVAL _JS_CTYPE(jsval, _JS_PTR, "","v", INFALLIBLE)
+#define _JS_CTYPE_JSVAL_FAIL _JS_CTYPE(jsval, _JS_PTR, --, --, FAIL_JSVAL)
+#define _JS_CTYPE_BOOL _JS_CTYPE(JSBool, _JS_I32, "","i", INFALLIBLE)
+#define _JS_CTYPE_BOOL_FAIL _JS_CTYPE(int32, _JS_I32, --, --, FAIL_VOID)
+#define _JS_CTYPE_INT32 _JS_CTYPE(int32, _JS_I32, "","i", INFALLIBLE)
+#define _JS_CTYPE_INT32_FAIL _JS_CTYPE(int32, _JS_I32, --, --, FAIL_NEG)
+#define _JS_CTYPE_UINT32 _JS_CTYPE(uint32, _JS_I32, --, --, INFALLIBLE)
+#define _JS_CTYPE_DOUBLE _JS_CTYPE(jsdouble, _JS_F64, "","d", INFALLIBLE)
+#define _JS_CTYPE_STRING _JS_CTYPE(JSString *, _JS_PTR, "","s", INFALLIBLE)
+#define _JS_CTYPE_STRING_FAIL _JS_CTYPE(JSString *, _JS_PTR, --, --, FAIL_NULL)
+#define _JS_CTYPE_OBJECT _JS_CTYPE(JSObject *, _JS_PTR, "","o", INFALLIBLE)
+#define _JS_CTYPE_OBJECT_FAIL_NULL _JS_CTYPE(JSObject *, _JS_PTR, --, --, FAIL_NULL)
+#define _JS_CTYPE_OBJECT_FAIL_VOID _JS_CTYPE(JSObject *, _JS_PTR, --, --, FAIL_VOID)
+#define _JS_CTYPE_REGEXP _JS_CTYPE(JSObject *, _JS_PTR, "","r", INFALLIBLE)
+#define _JS_CTYPE_SCOPEPROP _JS_CTYPE(JSScopeProperty *, _JS_PTR, --, --, INFALLIBLE)
+#define _JS_CTYPE_SIDEEXIT _JS_CTYPE(SideExit *, _JS_PTR, --, --, INFALLIBLE)
+#define _JS_CTYPE_INTERPSTATE _JS_CTYPE(InterpState *, _JS_PTR, --, --, INFALLIBLE)
+#define _JS_CTYPE_FRAGMENT _JS_CTYPE(nanojit::Fragment *, _JS_PTR, --, --, INFALLIBLE)
+
+#define _JS_EXPAND(tokens) tokens
+
+#define _JS_CTYPE_TYPE2(t,s,p,a,f) t
+#define _JS_CTYPE_TYPE(tyname) _JS_EXPAND(_JS_CTYPE_TYPE2 _JS_CTYPE_##tyname)
+#define _JS_CTYPE_RETSIZE2(t,s,p,a,f) s##_RETSIZE
+#define _JS_CTYPE_RETSIZE(tyname) _JS_EXPAND(_JS_CTYPE_RETSIZE2 _JS_CTYPE_##tyname)
+#define _JS_CTYPE_ARGSIZE2(t,s,p,a,f) s##_ARGSIZE
+#define _JS_CTYPE_ARGSIZE(tyname) _JS_EXPAND(_JS_CTYPE_ARGSIZE2 _JS_CTYPE_##tyname)
+#define _JS_CTYPE_PCH2(t,s,p,a,f) p
+#define _JS_CTYPE_PCH(tyname) _JS_EXPAND(_JS_CTYPE_PCH2 _JS_CTYPE_##tyname)
+#define _JS_CTYPE_ACH2(t,s,p,a,f) a
+#define _JS_CTYPE_ACH(tyname) _JS_EXPAND(_JS_CTYPE_ACH2 _JS_CTYPE_##tyname)
+#define _JS_CTYPE_FLAGS2(t,s,p,a,f) f
+#define _JS_CTYPE_FLAGS(tyname) _JS_EXPAND(_JS_CTYPE_FLAGS2 _JS_CTYPE_##tyname)
+
+#define _JS_static_TN(t) static t
+#define _JS_static_CI static
+#define _JS_extern_TN(t) extern t
+#define _JS_extern_CI
+#define _JS_FRIEND_TN(t) extern JS_FRIEND_API(t)
+#define _JS_FRIEND_CI
+#define _JS_TN_LINKAGE(linkage, t) _JS_##linkage##_TN(t)
+#define _JS_CI_LINKAGE(linkage) _JS_##linkage##_CI
+
+#define _JS_CALLINFO(name) name##_ci
+
+#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
+#define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, cse, fold) \
+ _JS_TN_LINKAGE(linkage, crtype) name cargtypes; \
+ _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \
+ { (intptr_t) &name, argtypes, cse, fold, nanojit::ABI_CDECL _JS_CI_NAME(name) };
+#else
+#define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, cse, fold) \
+ _JS_TN_LINKAGE(linkage, crtype) FASTCALL name cargtypes; \
+ _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \
+ { (intptr_t) &name, argtypes, cse, fold, nanojit::ABI_FASTCALL _JS_CI_NAME(name) };
+#endif
+
+/*
+ * Declare a C function named <op> and a CallInfo struct named <op>_callinfo so the
+ * tracer can call it. |linkage| controls the visibility of both the function
+ * and the CallInfo global. It can be extern, static, or FRIEND, which
+ * specifies JS_FRIEND_API linkage for the function.
+ */
+#define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, cse, fold) \
+ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), (_JS_CTYPE_TYPE(at0)), \
+ (_JS_CTYPE_ARGSIZE(at0) << 2) | _JS_CTYPE_RETSIZE(rt), cse, fold)
+#define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, cse, fold) \
+ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
+ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1)), \
+ (_JS_CTYPE_ARGSIZE(at0) << 4) | (_JS_CTYPE_ARGSIZE(at1) << 2) | \
+ _JS_CTYPE_RETSIZE(rt), \
+ cse, fold)
+#define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, cse, fold) \
+ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
+ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2)), \
+ (_JS_CTYPE_ARGSIZE(at0) << 6) | (_JS_CTYPE_ARGSIZE(at1) << 4) | \
+ (_JS_CTYPE_ARGSIZE(at2) << 2) | _JS_CTYPE_RETSIZE(rt), \
+ cse, fold)
+#define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, cse, fold) \
+ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
+ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2), \
+ _JS_CTYPE_TYPE(at3)), \
+ (_JS_CTYPE_ARGSIZE(at0) << 8) | (_JS_CTYPE_ARGSIZE(at1) << 6) | \
+ (_JS_CTYPE_ARGSIZE(at2) << 4) | (_JS_CTYPE_ARGSIZE(at3) << 2) | \
+ _JS_CTYPE_RETSIZE(rt), \
+ cse, fold)
+#define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) \
+ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
+ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2), \
+ _JS_CTYPE_TYPE(at3), _JS_CTYPE_TYPE(at4)), \
+ (_JS_CTYPE_ARGSIZE(at0) << 10) | (_JS_CTYPE_ARGSIZE(at1) << 8) | \
+ (_JS_CTYPE_ARGSIZE(at2) << 6) | (_JS_CTYPE_ARGSIZE(at3) << 4) | \
+ (_JS_CTYPE_ARGSIZE(at4) << 2) | _JS_CTYPE_RETSIZE(rt), \
+ cse, fold)
+
+#define JS_DECLARE_CALLINFO(name) extern const nanojit::CallInfo _JS_CALLINFO(name);
+
+#define _JS_TN_INIT_HELPER_n(n, args) _JS_TN_INIT_HELPER_##n args
+
+#define _JS_TN_INIT_HELPER_1(linkage, rt, op, at0, cse, fold) \
+ &_JS_CALLINFO(op), \
+ _JS_CTYPE_PCH(at0), \
+ _JS_CTYPE_ACH(at0), \
+ _JS_CTYPE_FLAGS(rt)
+
+#define _JS_TN_INIT_HELPER_2(linkage, rt, op, at0, at1, cse, fold) \
+ &_JS_CALLINFO(op), \
+ _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
+ _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1), \
+ _JS_CTYPE_FLAGS(rt)
+
+#define _JS_TN_INIT_HELPER_3(linkage, rt, op, at0, at1, at2, cse, fold) \
+ &_JS_CALLINFO(op), \
+ _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
+ _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at2), \
+ _JS_CTYPE_FLAGS(rt)
+
+#define _JS_TN_INIT_HELPER_4(linkage, rt, op, at0, at1, at2, at3, cse, fold) \
+ &_JS_CALLINFO(op), \
+ _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
+ _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at3), \
+ _JS_CTYPE_FLAGS(rt)
+
+#define _JS_TN_INIT_HELPER_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) \
+ &_JS_CALLINFO(op), \
+ _JS_CTYPE_PCH(at4) _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) \
+ _JS_CTYPE_PCH(at0), \
+ _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at3) \
+ _JS_CTYPE_ACH(at4), \
+ _JS_CTYPE_FLAGS(rt)
+
+#define JS_DEFINE_TRCINFO_1(name, tn0) \
+ _JS_DEFINE_CALLINFO_n tn0 \
+ JSTraceableNative name##_trcinfo[] = { \
+ { name, _JS_TN_INIT_HELPER_n tn0 } \
+ };
+
+#define JS_DEFINE_TRCINFO_2(name, tn0, tn1) \
+ _JS_DEFINE_CALLINFO_n tn0 \
+ _JS_DEFINE_CALLINFO_n tn1 \
+ JSTraceableNative name##_trcinfo[] = { \
+ { name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn1 } \
+ };
+
+#define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2) \
+ _JS_DEFINE_CALLINFO_n tn0 \
+ _JS_DEFINE_CALLINFO_n tn1 \
+ _JS_DEFINE_CALLINFO_n tn2 \
+ JSTraceableNative name##_trcinfo[] = { \
+ { name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn2 } \
+ };
+
+#define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3) \
+ _JS_DEFINE_CALLINFO_n tn0 \
+ _JS_DEFINE_CALLINFO_n tn1 \
+ _JS_DEFINE_CALLINFO_n tn2 \
+ _JS_DEFINE_CALLINFO_n tn3 \
+ JSTraceableNative name##_trcinfo[] = { \
+ { name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn2 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn3 } \
+ };
+
+#define _JS_DEFINE_CALLINFO_n(n, args) JS_DEFINE_CALLINFO_##n args
+
+jsdouble FASTCALL
+js_StringToNumber(JSContext* cx, JSString* str);
+
+jsdouble FASTCALL
+js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed);
+
+#else
+
+#define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, cse, fold)
+#define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, cse, fold)
+#define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, cse, fold)
+#define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, cse, fold)
+#define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold)
+#define JS_DECLARE_CALLINFO(name)
+#define JS_DEFINE_TRCINFO_1(name, tn0)
+#define JS_DEFINE_TRCINFO_2(name, tn0, tn1)
+#define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2)
+#define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3)
+
+#endif /* !JS_TRACER */
+
+/* Defined in jsarray.cpp */
+JS_DECLARE_CALLINFO(js_Array_dense_setelem)
+JS_DECLARE_CALLINFO(js_FastNewArray)
+JS_DECLARE_CALLINFO(js_Array_1int)
+JS_DECLARE_CALLINFO(js_Array_1str)
+JS_DECLARE_CALLINFO(js_Array_2obj)
+JS_DECLARE_CALLINFO(js_Array_3num)
+
+/* Defined in jsdate.cpp */
+JS_DECLARE_CALLINFO(js_FastNewDate)
+
+/* Defined in jsnum.cpp */
+JS_DECLARE_CALLINFO(js_NumberToString)
+
+/* Defined in jsstr.cpp */
+JS_DECLARE_CALLINFO(js_ConcatStrings)
+JS_DECLARE_CALLINFO(js_String_getelem)
+JS_DECLARE_CALLINFO(js_String_p_charCodeAt)
+JS_DECLARE_CALLINFO(js_EqualStrings)
+JS_DECLARE_CALLINFO(js_CompareStrings)
+
+/* Defined in jsbuiltins.cpp */
+#define BUILTIN1(linkage, rt, op, at0, cse, fold) JS_DECLARE_CALLINFO(op)
+#define BUILTIN2(linkage, rt, op, at0, at1, cse, fold) JS_DECLARE_CALLINFO(op)
+#define BUILTIN3(linkage, rt, op, at0, at1, at2, cse, fold) JS_DECLARE_CALLINFO(op)
+#define BUILTIN4(linkage, rt, op, at0, at1, at2, at3, cse, fold) JS_DECLARE_CALLINFO(op)
+#define BUILTIN5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) JS_DECLARE_CALLINFO(op)
+#include "builtins.tbl"
+#undef BUILTIN
+#undef BUILTIN1
+#undef BUILTIN2
+#undef BUILTIN3
+#undef BUILTIN4
+#undef BUILTIN5
+
+#endif /* jsbuiltins_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsclist.h b/tools/node_modules/expresso/deps/jscoverage/js/jsclist.h
new file mode 100644
index 0000000..604ec0e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsclist.h
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsclist_h___
+#define jsclist_h___
+
+#include "jstypes.h"
+
+/*
+** Circular linked list
+*/
+typedef struct JSCListStr {
+ struct JSCListStr *next;
+ struct JSCListStr *prev;
+} JSCList;
+
+/*
+** Insert element "_e" into the list, before "_l".
+*/
+#define JS_INSERT_BEFORE(_e,_l) \
+ JS_BEGIN_MACRO \
+ (_e)->next = (_l); \
+ (_e)->prev = (_l)->prev; \
+ (_l)->prev->next = (_e); \
+ (_l)->prev = (_e); \
+ JS_END_MACRO
+
+/*
+** Insert element "_e" into the list, after "_l".
+*/
+#define JS_INSERT_AFTER(_e,_l) \
+ JS_BEGIN_MACRO \
+ (_e)->next = (_l)->next; \
+ (_e)->prev = (_l); \
+ (_l)->next->prev = (_e); \
+ (_l)->next = (_e); \
+ JS_END_MACRO
+
+/*
+** Return the element following element "_e"
+*/
+#define JS_NEXT_LINK(_e) \
+ ((_e)->next)
+/*
+** Return the element preceding element "_e"
+*/
+#define JS_PREV_LINK(_e) \
+ ((_e)->prev)
+
+/*
+** Append an element "_e" to the end of the list "_l"
+*/
+#define JS_APPEND_LINK(_e,_l) JS_INSERT_BEFORE(_e,_l)
+
+/*
+** Insert an element "_e" at the head of the list "_l"
+*/
+#define JS_INSERT_LINK(_e,_l) JS_INSERT_AFTER(_e,_l)
+
+/* Return the head/tail of the list */
+#define JS_LIST_HEAD(_l) (_l)->next
+#define JS_LIST_TAIL(_l) (_l)->prev
+
+/*
+** Remove the element "_e" from it's circular list.
+*/
+#define JS_REMOVE_LINK(_e) \
+ JS_BEGIN_MACRO \
+ (_e)->prev->next = (_e)->next; \
+ (_e)->next->prev = (_e)->prev; \
+ JS_END_MACRO
+
+/*
+** Remove the element "_e" from it's circular list. Also initializes the
+** linkage.
+*/
+#define JS_REMOVE_AND_INIT_LINK(_e) \
+ JS_BEGIN_MACRO \
+ (_e)->prev->next = (_e)->next; \
+ (_e)->next->prev = (_e)->prev; \
+ (_e)->next = (_e); \
+ (_e)->prev = (_e); \
+ JS_END_MACRO
+
+/*
+** Return non-zero if the given circular list "_l" is empty, zero if the
+** circular list is not empty
+*/
+#define JS_CLIST_IS_EMPTY(_l) \
+ ((_l)->next == (_l))
+
+/*
+** Initialize a circular list
+*/
+#define JS_INIT_CLIST(_l) \
+ JS_BEGIN_MACRO \
+ (_l)->next = (_l); \
+ (_l)->prev = (_l); \
+ JS_END_MACRO
+
+#define JS_INIT_STATIC_CLIST(_l) \
+ {(_l), (_l)}
+
+#endif /* jsclist_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.cpp
new file mode 100644
index 0000000..c06a334
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.cpp
@@ -0,0 +1,1394 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS execution context.
+ */
+#include "jsstddef.h"
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsclist.h"
+#include "jsprf.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsexn.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jstracer.h"
+
+#ifdef JS_THREADSAFE
+#include "prtypes.h"
+
+/*
+ * The index for JSThread info, returned by PR_NewThreadPrivateIndex. The
+ * index value is visible and shared by all threads, but the data associated
+ * with it is private to each thread.
+ */
+static PRUintn threadTPIndex;
+static JSBool tpIndexInited = JS_FALSE;
+
+JS_BEGIN_EXTERN_C
+JSBool
+js_InitThreadPrivateIndex(void (*ptr)(void *))
+{
+ PRStatus status;
+
+ if (tpIndexInited)
+ return JS_TRUE;
+
+ status = PR_NewThreadPrivateIndex(&threadTPIndex, ptr);
+
+ if (status == PR_SUCCESS)
+ tpIndexInited = JS_TRUE;
+ return status == PR_SUCCESS;
+}
+JS_END_EXTERN_C
+
+/*
+ * Callback function to delete a JSThread info when the thread that owns it
+ * is destroyed.
+ */
+void
+js_ThreadDestructorCB(void *ptr)
+{
+ JSThread *thread = (JSThread *)ptr;
+
+ if (!thread)
+ return;
+
+ /*
+ * Check that this thread properly called either JS_DestroyContext or
+ * JS_ClearContextThread on each JSContext it created or used.
+ */
+ JS_ASSERT(JS_CLIST_IS_EMPTY(&thread->contextList));
+ GSN_CACHE_CLEAR(&thread->gsnCache);
+#if defined JS_TRACER
+ js_FinishJIT(&thread->traceMonitor);
+#endif
+ free(thread);
+}
+
+/*
+ * Get current thread-local JSThread info, creating one if it doesn't exist.
+ * Each thread has a unique JSThread pointer.
+ *
+ * Since we are dealing with thread-local data, no lock is needed.
+ *
+ * Return a pointer to the thread local info, NULL if the system runs out
+ * of memory, or it failed to set thread private data (neither case is very
+ * likely; both are probably due to out-of-memory). It is up to the caller
+ * to report an error, if possible.
+ */
+JSThread *
+js_GetCurrentThread(JSRuntime *rt)
+{
+ JSThread *thread;
+
+ thread = (JSThread *)PR_GetThreadPrivate(threadTPIndex);
+ if (!thread) {
+ thread = (JSThread *) malloc(sizeof(JSThread));
+ if (!thread)
+ return NULL;
+#ifdef DEBUG
+ memset(thread, JS_FREE_PATTERN, sizeof(JSThread));
+#endif
+ if (PR_FAILURE == PR_SetThreadPrivate(threadTPIndex, thread)) {
+ free(thread);
+ return NULL;
+ }
+
+ JS_INIT_CLIST(&thread->contextList);
+ thread->id = js_CurrentThreadId();
+ thread->gcMallocBytes = 0;
+#ifdef JS_TRACER
+ memset(&thread->traceMonitor, 0, sizeof(thread->traceMonitor));
+ js_InitJIT(&thread->traceMonitor);
+#endif
+ thread->scriptsToGC = NULL;
+
+ /*
+ * js_SetContextThread initializes the remaining fields as necessary.
+ */
+ }
+ return thread;
+}
+
+/*
+ * Sets current thread as owning thread of a context by assigning the
+ * thread-private info to the context. If the current thread doesn't have
+ * private JSThread info, create one.
+ */
+JSBool
+js_SetContextThread(JSContext *cx)
+{
+ JSThread *thread = js_GetCurrentThread(cx->runtime);
+
+ if (!thread) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ /*
+ * Clear caches on each transition from 0 to 1 context active on the
+ * current thread. See bug 425828.
+ */
+ if (JS_CLIST_IS_EMPTY(&thread->contextList)) {
+ memset(&thread->gsnCache, 0, sizeof(thread->gsnCache));
+ memset(&thread->propertyCache, 0, sizeof(thread->propertyCache));
+ }
+
+ /* Assert that the previous cx->thread called JS_ClearContextThread(). */
+ JS_ASSERT(!cx->thread || cx->thread == thread);
+ if (!cx->thread)
+ JS_APPEND_LINK(&cx->threadLinks, &thread->contextList);
+ cx->thread = thread;
+ return JS_TRUE;
+}
+
+/* Remove the owning thread info of a context. */
+void
+js_ClearContextThread(JSContext *cx)
+{
+ /*
+ * If cx is associated with a thread, this must be called only from that
+ * thread. If not, this is a harmless no-op.
+ */
+ JS_ASSERT(cx->thread == js_GetCurrentThread(cx->runtime) || !cx->thread);
+ JS_REMOVE_AND_INIT_LINK(&cx->threadLinks);
+ cx->thread = NULL;
+}
+
+#endif /* JS_THREADSAFE */
+
+void
+js_OnVersionChange(JSContext *cx)
+{
+#ifdef DEBUG
+ JSVersion version = JSVERSION_NUMBER(cx);
+
+ JS_ASSERT(version == JSVERSION_DEFAULT || version >= JSVERSION_ECMA_3);
+#endif
+}
+
+void
+js_SetVersion(JSContext *cx, JSVersion version)
+{
+ cx->version = version;
+ js_OnVersionChange(cx);
+}
+
+JSContext *
+js_NewContext(JSRuntime *rt, size_t stackChunkSize)
+{
+ JSContext *cx;
+ JSBool ok, first;
+ JSContextCallback cxCallback;
+
+ cx = (JSContext *) malloc(sizeof *cx);
+ if (!cx)
+ return NULL;
+ memset(cx, 0, sizeof *cx);
+
+ cx->runtime = rt;
+ JS_ClearOperationCallback(cx);
+ cx->debugHooks = &rt->globalDebugHooks;
+#if JS_STACK_GROWTH_DIRECTION > 0
+ cx->stackLimit = (jsuword)-1;
+#endif
+ cx->scriptStackQuota = JS_DEFAULT_SCRIPT_STACK_QUOTA;
+#ifdef JS_THREADSAFE
+ cx->gcLocalFreeLists = (JSGCFreeListSet *) &js_GCEmptyFreeListSet;
+ JS_INIT_CLIST(&cx->threadLinks);
+ js_SetContextThread(cx);
+#endif
+
+ JS_LOCK_GC(rt);
+ for (;;) {
+ first = (rt->contextList.next == &rt->contextList);
+ if (rt->state == JSRTS_UP) {
+ JS_ASSERT(!first);
+ break;
+ }
+ if (rt->state == JSRTS_DOWN) {
+ JS_ASSERT(first);
+ rt->state = JSRTS_LAUNCHING;
+ break;
+ }
+ JS_WAIT_CONDVAR(rt->stateChange, JS_NO_TIMEOUT);
+ }
+ JS_APPEND_LINK(&cx->links, &rt->contextList);
+ JS_UNLOCK_GC(rt);
+
+ /*
+ * First we do the infallible, every-time per-context initializations.
+ * Should a later, fallible initialization (js_InitRegExpStatics, e.g.,
+ * or the stuff under 'if (first)' below) fail, at least the version
+ * and arena-pools will be valid and safe to use (say, from the last GC
+ * done by js_DestroyContext).
+ */
+ cx->version = JSVERSION_DEFAULT;
+ JS_INIT_ARENA_POOL(&cx->stackPool, "stack", stackChunkSize, sizeof(jsval),
+ &cx->scriptStackQuota);
+
+ JS_INIT_ARENA_POOL(&cx->tempPool, "temp",
+ 1024, /* FIXME: bug 421435 */
+ sizeof(jsdouble), &cx->scriptStackQuota);
+
+ /*
+ * To avoid multiple allocations in InitMatch() (in jsregexp.c), the arena
+ * size parameter should be at least as big as:
+ * INITIAL_BACKTRACK
+ * + (sizeof(REProgState) * INITIAL_STATESTACK)
+ * + (offsetof(REMatchState, parens) + avgParanSize * sizeof(RECapture))
+ */
+ JS_INIT_ARENA_POOL(&cx->regexpPool, "regexp",
+ 12 * 1024 - 40, /* FIXME: bug 421435 */
+ sizeof(void *), &cx->scriptStackQuota);
+
+ if (!js_InitRegExpStatics(cx, &cx->regExpStatics)) {
+ js_DestroyContext(cx, JSDCM_NEW_FAILED);
+ return NULL;
+ }
+
+ cx->resolveFlags = 0;
+
+ /*
+ * If cx is the first context on this runtime, initialize well-known atoms,
+ * keywords, numbers, and strings. If one of these steps should fail, the
+ * runtime will be left in a partially initialized state, with zeroes and
+ * nulls stored in the default-initialized remainder of the struct. We'll
+ * clean the runtime up under js_DestroyContext, because cx will be "last"
+ * as well as "first".
+ */
+ if (first) {
+#ifdef JS_THREADSAFE
+ JS_BeginRequest(cx);
+#endif
+ ok = js_InitCommonAtoms(cx);
+
+ /*
+ * scriptFilenameTable may be left over from a previous episode of
+ * non-zero contexts alive in rt, so don't re-init the table if it's
+ * not necessary.
+ */
+ if (ok && !rt->scriptFilenameTable)
+ ok = js_InitRuntimeScriptState(rt);
+ if (ok)
+ ok = js_InitRuntimeNumberState(cx);
+ if (ok)
+ ok = js_InitRuntimeStringState(cx);
+#ifdef JS_THREADSAFE
+ JS_EndRequest(cx);
+#endif
+ if (!ok) {
+ js_DestroyContext(cx, JSDCM_NEW_FAILED);
+ return NULL;
+ }
+
+ JS_LOCK_GC(rt);
+ rt->state = JSRTS_UP;
+ JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
+ JS_UNLOCK_GC(rt);
+ }
+
+ cxCallback = rt->cxCallback;
+ if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) {
+ js_DestroyContext(cx, JSDCM_NEW_FAILED);
+ return NULL;
+ }
+
+ return cx;
+}
+
+void
+js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
+{
+ JSRuntime *rt;
+ JSContextCallback cxCallback;
+ JSBool last;
+ JSArgumentFormatMap *map;
+ JSLocalRootStack *lrs;
+ JSLocalRootChunk *lrc;
+
+ rt = cx->runtime;
+
+ if (mode != JSDCM_NEW_FAILED) {
+ cxCallback = rt->cxCallback;
+ if (cxCallback) {
+ /*
+ * JSCONTEXT_DESTROY callback is not allowed to fail and must
+ * return true.
+ */
+#ifdef DEBUG
+ JSBool callbackStatus =
+#endif
+ cxCallback(cx, JSCONTEXT_DESTROY);
+ JS_ASSERT(callbackStatus);
+ }
+ }
+
+ /* Remove cx from context list first. */
+ JS_LOCK_GC(rt);
+ JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING);
+ JS_REMOVE_LINK(&cx->links);
+ last = (rt->contextList.next == &rt->contextList);
+ if (last)
+ rt->state = JSRTS_LANDING;
+#ifdef JS_THREADSAFE
+ js_RevokeGCLocalFreeLists(cx);
+#endif
+ JS_UNLOCK_GC(rt);
+
+ if (last) {
+#ifdef JS_THREADSAFE
+ /*
+ * If cx is not in a request already, begin one now so that we wait
+ * for any racing GC started on a not-last context to finish, before
+ * we plow ahead and unpin atoms. Note that even though we begin a
+ * request here if necessary, we end all requests on cx below before
+ * forcing a final GC. This lets any not-last context destruction
+ * racing in another thread try to force or maybe run the GC, but by
+ * that point, rt->state will not be JSRTS_UP, and that GC attempt
+ * will return early.
+ */
+ if (cx->requestDepth == 0)
+ JS_BeginRequest(cx);
+#endif
+
+ /* Unlock and clear GC things held by runtime pointers. */
+ js_FinishRuntimeNumberState(cx);
+ js_FinishRuntimeStringState(cx);
+
+ /* Unpin all common atoms before final GC. */
+ js_FinishCommonAtoms(cx);
+
+ /* Clear debugging state to remove GC roots. */
+ JS_ClearAllTraps(cx);
+ JS_ClearAllWatchPoints(cx);
+ }
+
+ /*
+ * Remove more GC roots in regExpStatics, then collect garbage.
+ * XXX anti-modularity alert: we rely on the call to js_RemoveRoot within
+ * XXX this function call to wait for any racing GC to complete, in the
+ * XXX case where JS_DestroyContext is called outside of a request on cx
+ */
+ js_FreeRegExpStatics(cx, &cx->regExpStatics);
+
+#ifdef JS_THREADSAFE
+ /*
+ * Destroying a context implicitly calls JS_EndRequest(). Also, we must
+ * end our request here in case we are "last" -- in that event, another
+ * js_DestroyContext that was not last might be waiting in the GC for our
+ * request to end. We'll let it run below, just before we do the truly
+ * final GC and then free atom state.
+ *
+ * At this point, cx must be inaccessible to other threads. It's off the
+ * rt->contextList, and it should not be reachable via any object private
+ * data structure.
+ */
+ while (cx->requestDepth != 0)
+ JS_EndRequest(cx);
+#endif
+
+ if (last) {
+ js_GC(cx, GC_LAST_CONTEXT);
+
+ /*
+ * Free the script filename table if it exists and is empty. Do this
+ * after the last GC to avoid finalizers tripping on free memory.
+ */
+ if (rt->scriptFilenameTable && rt->scriptFilenameTable->nentries == 0)
+ js_FinishRuntimeScriptState(rt);
+
+ /* Take the runtime down, now that it has no contexts or atoms. */
+ JS_LOCK_GC(rt);
+ rt->state = JSRTS_DOWN;
+ JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
+ JS_UNLOCK_GC(rt);
+ } else {
+ if (mode == JSDCM_FORCE_GC)
+ js_GC(cx, GC_NORMAL);
+ else if (mode == JSDCM_MAYBE_GC)
+ JS_MaybeGC(cx);
+ }
+
+ /* Free the stuff hanging off of cx. */
+ JS_FinishArenaPool(&cx->stackPool);
+ JS_FinishArenaPool(&cx->tempPool);
+ JS_FinishArenaPool(&cx->regexpPool);
+
+ if (cx->lastMessage)
+ free(cx->lastMessage);
+
+ /* Remove any argument formatters. */
+ map = cx->argumentFormatMap;
+ while (map) {
+ JSArgumentFormatMap *temp = map;
+ map = map->next;
+ JS_free(cx, temp);
+ }
+
+ /* Destroy the resolve recursion damper. */
+ if (cx->resolvingTable) {
+ JS_DHashTableDestroy(cx->resolvingTable);
+ cx->resolvingTable = NULL;
+ }
+
+ lrs = cx->localRootStack;
+ if (lrs) {
+ while ((lrc = lrs->topChunk) != &lrs->firstChunk) {
+ lrs->topChunk = lrc->down;
+ JS_free(cx, lrc);
+ }
+ JS_free(cx, lrs);
+ }
+
+#ifdef JS_THREADSAFE
+ js_ClearContextThread(cx);
+#endif
+
+ /* Finally, free cx itself. */
+ free(cx);
+}
+
+JSBool
+js_ValidContextPointer(JSRuntime *rt, JSContext *cx)
+{
+ JSCList *cl;
+
+ for (cl = rt->contextList.next; cl != &rt->contextList; cl = cl->next) {
+ if (cl == &cx->links)
+ return JS_TRUE;
+ }
+ JS_RUNTIME_METER(rt, deadContexts);
+ return JS_FALSE;
+}
+
+JSContext *
+js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp)
+{
+ JSContext *cx = *iterp;
+
+ if (unlocked)
+ JS_LOCK_GC(rt);
+ cx = (JSContext *) (cx ? cx->links.next : rt->contextList.next);
+ if (&cx->links == &rt->contextList)
+ cx = NULL;
+ *iterp = cx;
+ if (unlocked)
+ JS_UNLOCK_GC(rt);
+ return cx;
+}
+
+static JSDHashNumber
+resolving_HashKey(JSDHashTable *table, const void *ptr)
+{
+ const JSResolvingKey *key = (const JSResolvingKey *)ptr;
+
+ return ((JSDHashNumber)JS_PTR_TO_UINT32(key->obj) >> JSVAL_TAGBITS) ^ key->id;
+}
+
+JS_PUBLIC_API(JSBool)
+resolving_MatchEntry(JSDHashTable *table,
+ const JSDHashEntryHdr *hdr,
+ const void *ptr)
+{
+ const JSResolvingEntry *entry = (const JSResolvingEntry *)hdr;
+ const JSResolvingKey *key = (const JSResolvingKey *)ptr;
+
+ return entry->key.obj == key->obj && entry->key.id == key->id;
+}
+
+static const JSDHashTableOps resolving_dhash_ops = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ resolving_HashKey,
+ resolving_MatchEntry,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+JSBool
+js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
+ JSResolvingEntry **entryp)
+{
+ JSDHashTable *table;
+ JSResolvingEntry *entry;
+
+ table = cx->resolvingTable;
+ if (!table) {
+ table = JS_NewDHashTable(&resolving_dhash_ops, NULL,
+ sizeof(JSResolvingEntry),
+ JS_DHASH_MIN_SIZE);
+ if (!table)
+ goto outofmem;
+ cx->resolvingTable = table;
+ }
+
+ entry = (JSResolvingEntry *)
+ JS_DHashTableOperate(table, key, JS_DHASH_ADD);
+ if (!entry)
+ goto outofmem;
+
+ if (entry->flags & flag) {
+ /* An entry for (key, flag) exists already -- dampen recursion. */
+ entry = NULL;
+ } else {
+ /* Fill in key if we were the first to add entry, then set flag. */
+ if (!entry->key.obj)
+ entry->key = *key;
+ entry->flags |= flag;
+ }
+ *entryp = entry;
+ return JS_TRUE;
+
+outofmem:
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+}
+
+void
+js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
+ JSResolvingEntry *entry, uint32 generation)
+{
+ JSDHashTable *table;
+
+ /*
+ * Clear flag from entry->flags and return early if other flags remain.
+ * We must take care to re-lookup entry if the table has changed since
+ * it was found by js_StartResolving.
+ */
+ table = cx->resolvingTable;
+ if (!entry || table->generation != generation) {
+ entry = (JSResolvingEntry *)
+ JS_DHashTableOperate(table, key, JS_DHASH_LOOKUP);
+ }
+ JS_ASSERT(JS_DHASH_ENTRY_IS_BUSY(&entry->hdr));
+ entry->flags &= ~flag;
+ if (entry->flags)
+ return;
+
+ /*
+ * Do a raw remove only if fewer entries were removed than would cause
+ * alpha to be less than .5 (alpha is at most .75). Otherwise, we just
+ * call JS_DHashTableOperate to re-lookup the key and remove its entry,
+ * compressing or shrinking the table as needed.
+ */
+ if (table->removedCount < JS_DHASH_TABLE_SIZE(table) >> 2)
+ JS_DHashTableRawRemove(table, &entry->hdr);
+ else
+ JS_DHashTableOperate(table, key, JS_DHASH_REMOVE);
+}
+
+JSBool
+js_EnterLocalRootScope(JSContext *cx)
+{
+ JSLocalRootStack *lrs;
+ int mark;
+
+ lrs = cx->localRootStack;
+ if (!lrs) {
+ lrs = (JSLocalRootStack *) JS_malloc(cx, sizeof *lrs);
+ if (!lrs)
+ return JS_FALSE;
+ lrs->scopeMark = JSLRS_NULL_MARK;
+ lrs->rootCount = 0;
+ lrs->topChunk = &lrs->firstChunk;
+ lrs->firstChunk.down = NULL;
+ cx->localRootStack = lrs;
+ }
+
+ /* Push lrs->scopeMark to save it for restore when leaving. */
+ mark = js_PushLocalRoot(cx, lrs, INT_TO_JSVAL(lrs->scopeMark));
+ if (mark < 0)
+ return JS_FALSE;
+ lrs->scopeMark = (uint32) mark;
+ return JS_TRUE;
+}
+
+void
+js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
+{
+ JSLocalRootStack *lrs;
+ uint32 mark, m, n;
+ JSLocalRootChunk *lrc;
+
+ /* Defend against buggy native callers. */
+ lrs = cx->localRootStack;
+ JS_ASSERT(lrs && lrs->rootCount != 0);
+ if (!lrs || lrs->rootCount == 0)
+ return;
+
+ mark = lrs->scopeMark;
+ JS_ASSERT(mark != JSLRS_NULL_MARK);
+ if (mark == JSLRS_NULL_MARK)
+ return;
+
+ /* Free any chunks being popped by this leave operation. */
+ m = mark >> JSLRS_CHUNK_SHIFT;
+ n = (lrs->rootCount - 1) >> JSLRS_CHUNK_SHIFT;
+ while (n > m) {
+ lrc = lrs->topChunk;
+ JS_ASSERT(lrc != &lrs->firstChunk);
+ lrs->topChunk = lrc->down;
+ JS_free(cx, lrc);
+ --n;
+ }
+
+ /*
+ * Pop the scope, restoring lrs->scopeMark. If rval is a GC-thing, push
+ * it on the caller's scope, or store it in lastInternalResult if we are
+ * leaving the outermost scope. We don't need to allocate a new lrc
+ * because we can overwrite the old mark's slot with rval.
+ */
+ lrc = lrs->topChunk;
+ m = mark & JSLRS_CHUNK_MASK;
+ lrs->scopeMark = (uint32) JSVAL_TO_INT(lrc->roots[m]);
+ if (JSVAL_IS_GCTHING(rval) && !JSVAL_IS_NULL(rval)) {
+ if (mark == 0) {
+ cx->weakRoots.lastInternalResult = rval;
+ } else {
+ /*
+ * Increment m to avoid the "else if (m == 0)" case below. If
+ * rval is not a GC-thing, that case would take care of freeing
+ * any chunk that contained only the old mark. Since rval *is*
+ * a GC-thing here, we want to reuse that old mark's slot.
+ */
+ lrc->roots[m++] = rval;
+ ++mark;
+ }
+ }
+ lrs->rootCount = (uint32) mark;
+
+ /*
+ * Free the stack eagerly, risking malloc churn. The alternative would
+ * require an lrs->entryCount member, maintained by Enter and Leave, and
+ * tested by the GC in addition to the cx->localRootStack non-null test.
+ *
+ * That approach would risk hoarding 264 bytes (net) per context. Right
+ * now it seems better to give fresh (dirty in CPU write-back cache, and
+ * the data is no longer needed) memory back to the malloc heap.
+ */
+ if (mark == 0) {
+ cx->localRootStack = NULL;
+ JS_free(cx, lrs);
+ } else if (m == 0) {
+ lrs->topChunk = lrc->down;
+ JS_free(cx, lrc);
+ }
+}
+
+void
+js_ForgetLocalRoot(JSContext *cx, jsval v)
+{
+ JSLocalRootStack *lrs;
+ uint32 i, j, m, n, mark;
+ JSLocalRootChunk *lrc, *lrc2;
+ jsval top;
+
+ lrs = cx->localRootStack;
+ JS_ASSERT(lrs && lrs->rootCount);
+ if (!lrs || lrs->rootCount == 0)
+ return;
+
+ /* Prepare to pop the top-most value from the stack. */
+ n = lrs->rootCount - 1;
+ m = n & JSLRS_CHUNK_MASK;
+ lrc = lrs->topChunk;
+ top = lrc->roots[m];
+
+ /* Be paranoid about calls on an empty scope. */
+ mark = lrs->scopeMark;
+ JS_ASSERT(mark < n);
+ if (mark >= n)
+ return;
+
+ /* If v was not the last root pushed in the top scope, find it. */
+ if (top != v) {
+ /* Search downward in case v was recently pushed. */
+ i = n;
+ j = m;
+ lrc2 = lrc;
+ while (--i > mark) {
+ if (j == 0)
+ lrc2 = lrc2->down;
+ j = i & JSLRS_CHUNK_MASK;
+ if (lrc2->roots[j] == v)
+ break;
+ }
+
+ /* If we didn't find v in this scope, assert and bail out. */
+ JS_ASSERT(i != mark);
+ if (i == mark)
+ return;
+
+ /* Swap top and v so common tail code can pop v. */
+ lrc2->roots[j] = top;
+ }
+
+ /* Pop the last value from the stack. */
+ lrc->roots[m] = JSVAL_NULL;
+ lrs->rootCount = n;
+ if (m == 0) {
+ JS_ASSERT(n != 0);
+ JS_ASSERT(lrc != &lrs->firstChunk);
+ lrs->topChunk = lrc->down;
+ JS_free(cx, lrc);
+ }
+}
+
+int
+js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v)
+{
+ uint32 n, m;
+ JSLocalRootChunk *lrc;
+
+ n = lrs->rootCount;
+ m = n & JSLRS_CHUNK_MASK;
+ if (n == 0 || m != 0) {
+ /*
+ * At start of first chunk, or not at start of a non-first top chunk.
+ * Check for lrs->rootCount overflow.
+ */
+ if ((uint32)(n + 1) == 0) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_TOO_MANY_LOCAL_ROOTS);
+ return -1;
+ }
+ lrc = lrs->topChunk;
+ JS_ASSERT(n != 0 || lrc == &lrs->firstChunk);
+ } else {
+ /*
+ * After lrs->firstChunk, trying to index at a power-of-two chunk
+ * boundary: need a new chunk.
+ */
+ lrc = (JSLocalRootChunk *) JS_malloc(cx, sizeof *lrc);
+ if (!lrc)
+ return -1;
+ lrc->down = lrs->topChunk;
+ lrs->topChunk = lrc;
+ }
+ lrs->rootCount = n + 1;
+ lrc->roots[m] = v;
+ return (int) n;
+}
+
+void
+js_TraceLocalRoots(JSTracer *trc, JSLocalRootStack *lrs)
+{
+ uint32 n, m, mark;
+ JSLocalRootChunk *lrc;
+ jsval v;
+
+ n = lrs->rootCount;
+ if (n == 0)
+ return;
+
+ mark = lrs->scopeMark;
+ lrc = lrs->topChunk;
+ do {
+ while (--n > mark) {
+ m = n & JSLRS_CHUNK_MASK;
+ v = lrc->roots[m];
+ JS_ASSERT(JSVAL_IS_GCTHING(v) && v != JSVAL_NULL);
+ JS_SET_TRACING_INDEX(trc, "local_root", n);
+ js_CallValueTracerIfGCThing(trc, v);
+ if (m == 0)
+ lrc = lrc->down;
+ }
+ m = n & JSLRS_CHUNK_MASK;
+ mark = JSVAL_TO_INT(lrc->roots[m]);
+ if (m == 0)
+ lrc = lrc->down;
+ } while (n != 0);
+ JS_ASSERT(!lrc);
+}
+
+static void
+ReportError(JSContext *cx, const char *message, JSErrorReport *reportp)
+{
+ /*
+ * Check the error report, and set a JavaScript-catchable exception
+ * if the error is defined to have an associated exception. If an
+ * exception is thrown, then the JSREPORT_EXCEPTION flag will be set
+ * on the error report, and exception-aware hosts should ignore it.
+ */
+ JS_ASSERT(reportp);
+ if (reportp->errorNumber == JSMSG_UNCAUGHT_EXCEPTION)
+ reportp->flags |= JSREPORT_EXCEPTION;
+
+ /*
+ * Call the error reporter only if an exception wasn't raised.
+ *
+ * If an exception was raised, then we call the debugErrorHook
+ * (if present) to give it a chance to see the error before it
+ * propagates out of scope. This is needed for compatability
+ * with the old scheme.
+ */
+ if (!cx->fp || !js_ErrorToException(cx, message, reportp)) {
+ js_ReportErrorAgain(cx, message, reportp);
+ } else if (cx->debugHooks->debugErrorHook && cx->errorReporter) {
+ JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
+ /* test local in case debugErrorHook changed on another thread */
+ if (hook)
+ hook(cx, message, reportp, cx->debugHooks->debugErrorHookData);
+ }
+}
+
+/*
+ * We don't post an exception in this case, since doing so runs into
+ * complications of pre-allocating an exception object which required
+ * running the Exception class initializer early etc.
+ * Instead we just invoke the errorReporter with an "Out Of Memory"
+ * type message, and then hope the process ends swiftly.
+ */
+void
+js_ReportOutOfMemory(JSContext *cx)
+{
+ JSStackFrame *fp;
+ JSErrorReport report;
+ JSErrorReporter onError = cx->errorReporter;
+
+ /* Get the message for this error, but we won't expand any arguments. */
+ const JSErrorFormatString *efs =
+ js_GetLocalizedErrorMessage(cx, NULL, NULL, JSMSG_OUT_OF_MEMORY);
+ const char *msg = efs ? efs->format : "Out of memory";
+
+ /* Fill out the report, but don't do anything that requires allocation. */
+ memset(&report, 0, sizeof (struct JSErrorReport));
+ report.flags = JSREPORT_ERROR;
+ report.errorNumber = JSMSG_OUT_OF_MEMORY;
+
+ /*
+ * Walk stack until we find a frame that is associated with some script
+ * rather than a native frame.
+ */
+ for (fp = cx->fp; fp; fp = fp->down) {
+ if (fp->regs) {
+ report.filename = fp->script->filename;
+ report.lineno = js_FramePCToLineNumber(cx, fp);
+ break;
+ }
+ }
+
+ /*
+ * If debugErrorHook is present then we give it a chance to veto sending
+ * the error on to the regular ErrorReporter. We also clear a pending
+ * exception if any now so the hooks can replace the out-of-memory error
+ * by a script-catchable exception.
+ */
+ cx->throwing = JS_FALSE;
+ if (onError) {
+ JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
+ if (hook &&
+ !hook(cx, msg, &report, cx->debugHooks->debugErrorHookData)) {
+ onError = NULL;
+ }
+ }
+
+ if (onError)
+ onError(cx, msg, &report);
+}
+
+void
+js_ReportOutOfScriptQuota(JSContext *cx)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_SCRIPT_STACK_QUOTA);
+}
+
+void
+js_ReportOverRecursed(JSContext *cx)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);
+}
+
+void
+js_ReportAllocationOverflow(JSContext *cx)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_ALLOC_OVERFLOW);
+}
+
+JSBool
+js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
+{
+ char *message;
+ jschar *ucmessage;
+ size_t messagelen;
+ JSStackFrame *fp;
+ JSErrorReport report;
+ JSBool warning;
+
+ if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
+ return JS_TRUE;
+
+ message = JS_vsmprintf(format, ap);
+ if (!message)
+ return JS_FALSE;
+ messagelen = strlen(message);
+
+ memset(&report, 0, sizeof (struct JSErrorReport));
+ report.flags = flags;
+ report.errorNumber = JSMSG_USER_DEFINED_ERROR;
+ report.ucmessage = ucmessage = js_InflateString(cx, message, &messagelen);
+
+ /* Find the top-most active script frame, for best line number blame. */
+ for (fp = cx->fp; fp; fp = fp->down) {
+ if (fp->regs) {
+ report.filename = fp->script->filename;
+ report.lineno = js_FramePCToLineNumber(cx, fp);
+ break;
+ }
+ }
+
+ warning = JSREPORT_IS_WARNING(report.flags);
+ if (warning && JS_HAS_WERROR_OPTION(cx)) {
+ report.flags &= ~JSREPORT_WARNING;
+ warning = JS_FALSE;
+ }
+
+ ReportError(cx, message, &report);
+ free(message);
+ JS_free(cx, ucmessage);
+ return warning;
+}
+
+/*
+ * The arguments from ap need to be packaged up into an array and stored
+ * into the report struct.
+ *
+ * The format string addressed by the error number may contain operands
+ * identified by the format {N}, where N is a decimal digit. Each of these
+ * is to be replaced by the Nth argument from the va_list. The complete
+ * message is placed into reportp->ucmessage converted to a JSString.
+ *
+ * Returns true if the expansion succeeds (can fail if out of memory).
+ */
+JSBool
+js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
+ void *userRef, const uintN errorNumber,
+ char **messagep, JSErrorReport *reportp,
+ JSBool *warningp, JSBool charArgs, va_list ap)
+{
+ const JSErrorFormatString *efs;
+ int i;
+ int argCount;
+
+ *warningp = JSREPORT_IS_WARNING(reportp->flags);
+ if (*warningp && JS_HAS_WERROR_OPTION(cx)) {
+ reportp->flags &= ~JSREPORT_WARNING;
+ *warningp = JS_FALSE;
+ }
+
+ *messagep = NULL;
+
+ /* Most calls supply js_GetErrorMessage; if this is so, assume NULL. */
+ if (!callback || callback == js_GetErrorMessage)
+ efs = js_GetLocalizedErrorMessage(cx, userRef, NULL, errorNumber);
+ else
+ efs = callback(userRef, NULL, errorNumber);
+ if (efs) {
+ size_t totalArgsLength = 0;
+ size_t argLengths[10]; /* only {0} thru {9} supported */
+ argCount = efs->argCount;
+ JS_ASSERT(argCount <= 10);
+ if (argCount > 0) {
+ /*
+ * Gather the arguments into an array, and accumulate
+ * their sizes. We allocate 1 more than necessary and
+ * null it out to act as the caboose when we free the
+ * pointers later.
+ */
+ reportp->messageArgs = (const jschar **)
+ JS_malloc(cx, sizeof(jschar *) * (argCount + 1));
+ if (!reportp->messageArgs)
+ return JS_FALSE;
+ reportp->messageArgs[argCount] = NULL;
+ for (i = 0; i < argCount; i++) {
+ if (charArgs) {
+ char *charArg = va_arg(ap, char *);
+ size_t charArgLength = strlen(charArg);
+ reportp->messageArgs[i]
+ = js_InflateString(cx, charArg, &charArgLength);
+ if (!reportp->messageArgs[i])
+ goto error;
+ } else {
+ reportp->messageArgs[i] = va_arg(ap, jschar *);
+ }
+ argLengths[i] = js_strlen(reportp->messageArgs[i]);
+ totalArgsLength += argLengths[i];
+ }
+ /* NULL-terminate for easy copying. */
+ reportp->messageArgs[i] = NULL;
+ }
+ /*
+ * Parse the error format, substituting the argument X
+ * for {X} in the format.
+ */
+ if (argCount > 0) {
+ if (efs->format) {
+ jschar *buffer, *fmt, *out;
+ int expandedArgs = 0;
+ size_t expandedLength;
+ size_t len = strlen(efs->format);
+
+ buffer = fmt = js_InflateString (cx, efs->format, &len);
+ if (!buffer)
+ goto error;
+ expandedLength = len
+ - (3 * argCount) /* exclude the {n} */
+ + totalArgsLength;
+
+ /*
+ * Note - the above calculation assumes that each argument
+ * is used once and only once in the expansion !!!
+ */
+ reportp->ucmessage = out = (jschar *)
+ JS_malloc(cx, (expandedLength + 1) * sizeof(jschar));
+ if (!out) {
+ JS_free (cx, buffer);
+ goto error;
+ }
+ while (*fmt) {
+ if (*fmt == '{') {
+ if (isdigit(fmt[1])) {
+ int d = JS7_UNDEC(fmt[1]);
+ JS_ASSERT(d < argCount);
+ js_strncpy(out, reportp->messageArgs[d],
+ argLengths[d]);
+ out += argLengths[d];
+ fmt += 3;
+ expandedArgs++;
+ continue;
+ }
+ }
+ *out++ = *fmt++;
+ }
+ JS_ASSERT(expandedArgs == argCount);
+ *out = 0;
+ JS_free (cx, buffer);
+ *messagep =
+ js_DeflateString(cx, reportp->ucmessage,
+ (size_t)(out - reportp->ucmessage));
+ if (!*messagep)
+ goto error;
+ }
+ } else {
+ /*
+ * Zero arguments: the format string (if it exists) is the
+ * entire message.
+ */
+ if (efs->format) {
+ size_t len;
+ *messagep = JS_strdup(cx, efs->format);
+ if (!*messagep)
+ goto error;
+ len = strlen(*messagep);
+ reportp->ucmessage = js_InflateString(cx, *messagep, &len);
+ if (!reportp->ucmessage)
+ goto error;
+ }
+ }
+ }
+ if (*messagep == NULL) {
+ /* where's the right place for this ??? */
+ const char *defaultErrorMessage
+ = "No error message available for error number %d";
+ size_t nbytes = strlen(defaultErrorMessage) + 16;
+ *messagep = (char *)JS_malloc(cx, nbytes);
+ if (!*messagep)
+ goto error;
+ JS_snprintf(*messagep, nbytes, defaultErrorMessage, errorNumber);
+ }
+ return JS_TRUE;
+
+error:
+ if (reportp->messageArgs) {
+ /* free the arguments only if we allocated them */
+ if (charArgs) {
+ i = 0;
+ while (reportp->messageArgs[i])
+ JS_free(cx, (void *)reportp->messageArgs[i++]);
+ }
+ JS_free(cx, (void *)reportp->messageArgs);
+ reportp->messageArgs = NULL;
+ }
+ if (reportp->ucmessage) {
+ JS_free(cx, (void *)reportp->ucmessage);
+ reportp->ucmessage = NULL;
+ }
+ if (*messagep) {
+ JS_free(cx, (void *)*messagep);
+ *messagep = NULL;
+ }
+ return JS_FALSE;
+}
+
+JSBool
+js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
+ void *userRef, const uintN errorNumber,
+ JSBool charArgs, va_list ap)
+{
+ JSStackFrame *fp;
+ JSErrorReport report;
+ char *message;
+ JSBool warning;
+
+ if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
+ return JS_TRUE;
+
+ memset(&report, 0, sizeof (struct JSErrorReport));
+ report.flags = flags;
+ report.errorNumber = errorNumber;
+
+ /*
+ * If we can't find out where the error was based on the current frame,
+ * see if the next frame has a script/pc combo we can use.
+ */
+ for (fp = cx->fp; fp; fp = fp->down) {
+ if (fp->regs) {
+ report.filename = fp->script->filename;
+ report.lineno = js_FramePCToLineNumber(cx, fp);
+ break;
+ }
+ }
+
+ if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
+ &message, &report, &warning, charArgs, ap)) {
+ return JS_FALSE;
+ }
+
+ ReportError(cx, message, &report);
+
+ if (message)
+ JS_free(cx, message);
+ if (report.messageArgs) {
+ /*
+ * js_ExpandErrorArguments owns its messageArgs only if it had to
+ * inflate the arguments (from regular |char *|s).
+ */
+ if (charArgs) {
+ int i = 0;
+ while (report.messageArgs[i])
+ JS_free(cx, (void *)report.messageArgs[i++]);
+ }
+ JS_free(cx, (void *)report.messageArgs);
+ }
+ if (report.ucmessage)
+ JS_free(cx, (void *)report.ucmessage);
+
+ return warning;
+}
+
+JS_FRIEND_API(void)
+js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
+{
+ JSErrorReporter onError;
+
+ if (!message)
+ return;
+
+ if (cx->lastMessage)
+ free(cx->lastMessage);
+ cx->lastMessage = JS_strdup(cx, message);
+ if (!cx->lastMessage)
+ return;
+ onError = cx->errorReporter;
+
+ /*
+ * If debugErrorHook is present then we give it a chance to veto
+ * sending the error on to the regular ErrorReporter.
+ */
+ if (onError) {
+ JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
+ if (hook &&
+ !hook(cx, cx->lastMessage, reportp,
+ cx->debugHooks->debugErrorHookData)) {
+ onError = NULL;
+ }
+ }
+ if (onError)
+ onError(cx, cx->lastMessage, reportp);
+}
+
+void
+js_ReportIsNotDefined(JSContext *cx, const char *name)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_DEFINED, name);
+}
+
+JSBool
+js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
+ JSString *fallback)
+{
+ char *bytes;
+ JSBool ok;
+
+ bytes = js_DecompileValueGenerator(cx, spindex, v, fallback);
+ if (!bytes)
+ return JS_FALSE;
+
+ if (strcmp(bytes, js_undefined_str) == 0 ||
+ strcmp(bytes, js_null_str) == 0) {
+ ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_NO_PROPERTIES, bytes,
+ NULL, NULL);
+ } else if (JSVAL_IS_VOID(v)) {
+ ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_NULL_OR_UNDEFINED, bytes,
+ js_undefined_str, NULL);
+ } else {
+ JS_ASSERT(JSVAL_IS_NULL(v));
+ ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_NULL_OR_UNDEFINED, bytes,
+ js_null_str, NULL);
+ }
+
+ JS_free(cx, bytes);
+ return ok;
+}
+
+void
+js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg)
+{
+ char argbuf[11];
+ char *bytes;
+ JSAtom *atom;
+
+ JS_snprintf(argbuf, sizeof argbuf, "%u", arg);
+ bytes = NULL;
+ if (VALUE_IS_FUNCTION(cx, *vp)) {
+ atom = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(*vp))->atom;
+ bytes = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, *vp,
+ ATOM_TO_STRING(atom));
+ if (!bytes)
+ return;
+ }
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_MISSING_FUN_ARG, argbuf,
+ bytes ? bytes : "");
+ JS_free(cx, bytes);
+}
+
+JSBool
+js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
+ intN spindex, jsval v, JSString *fallback,
+ const char *arg1, const char *arg2)
+{
+ char *bytes;
+ JSBool ok;
+
+ JS_ASSERT(js_ErrorFormatString[errorNumber].argCount >= 1);
+ JS_ASSERT(js_ErrorFormatString[errorNumber].argCount <= 3);
+ bytes = js_DecompileValueGenerator(cx, spindex, v, fallback);
+ if (!bytes)
+ return JS_FALSE;
+
+ ok = JS_ReportErrorFlagsAndNumber(cx, flags, js_GetErrorMessage,
+ NULL, errorNumber, bytes, arg1, arg2);
+ JS_free(cx, bytes);
+ return ok;
+}
+
+#if defined DEBUG && defined XP_UNIX
+/* For gdb usage. */
+void js_traceon(JSContext *cx) { cx->tracefp = stderr; }
+void js_traceoff(JSContext *cx) { cx->tracefp = NULL; }
+#endif
+
+JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = {
+#define MSG_DEF(name, number, count, exception, format) \
+ { format, count, exception } ,
+#include "js.msg"
+#undef MSG_DEF
+};
+
+JS_FRIEND_API(const JSErrorFormatString *)
+js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
+{
+ if ((errorNumber > 0) && (errorNumber < JSErr_Limit))
+ return &js_ErrorFormatString[errorNumber];
+ return NULL;
+}
+
+JSBool
+js_ResetOperationCount(JSContext *cx)
+{
+ JSScript *script;
+
+ JS_ASSERT(cx->operationCount <= 0);
+ JS_ASSERT(cx->operationLimit > 0);
+
+ cx->operationCount = (int32) cx->operationLimit;
+ if (cx->operationCallbackIsSet)
+ return cx->operationCallback(cx);
+
+ if (cx->operationCallback) {
+ /*
+ * Invoke the deprecated branch callback. It may be called only when
+ * the top-most frame is scripted or JSOPTION_NATIVE_BRANCH_CALLBACK
+ * is set.
+ */
+ script = cx->fp ? cx->fp->script : NULL;
+ if (script || JS_HAS_OPTION(cx, JSOPTION_NATIVE_BRANCH_CALLBACK))
+ return ((JSBranchCallback) cx->operationCallback)(cx, script);
+ }
+ return JS_TRUE;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.h b/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.h
new file mode 100644
index 0000000..c201f1f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.h
@@ -0,0 +1,1247 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jscntxt_h___
+#define jscntxt_h___
+/*
+ * JS execution context.
+ */
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsclist.h"
+#include "jslong.h"
+#include "jsatom.h"
+#include "jsversion.h"
+#include "jsdhash.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsobj.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsregexp.h"
+#include "jsutil.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * js_GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
+ * given pc in a script. We use the script->code pointer to tag the cache,
+ * instead of the script address itself, so that source notes are always found
+ * by offset from the bytecode with which they were generated.
+ */
+typedef struct JSGSNCache {
+ jsbytecode *code;
+ JSDHashTable table;
+#ifdef JS_GSNMETER
+ uint32 hits;
+ uint32 misses;
+ uint32 fills;
+ uint32 clears;
+# define GSN_CACHE_METER(cache,cnt) (++(cache)->cnt)
+#else
+# define GSN_CACHE_METER(cache,cnt) /* nothing */
+#endif
+} JSGSNCache;
+
+#define GSN_CACHE_CLEAR(cache) \
+ JS_BEGIN_MACRO \
+ (cache)->code = NULL; \
+ if ((cache)->table.ops) { \
+ JS_DHashTableFinish(&(cache)->table); \
+ (cache)->table.ops = NULL; \
+ } \
+ GSN_CACHE_METER(cache, clears); \
+ JS_END_MACRO
+
+/* These helper macros take a cx as parameter and operate on its GSN cache. */
+#define JS_CLEAR_GSN_CACHE(cx) GSN_CACHE_CLEAR(&JS_GSN_CACHE(cx))
+#define JS_METER_GSN_CACHE(cx,cnt) GSN_CACHE_METER(&JS_GSN_CACHE(cx), cnt)
+
+#ifdef __cplusplus
+namespace nanojit {
+ class Fragment;
+ class Fragmento;
+}
+class TraceRecorder;
+extern "C++" { template<typename T> class Queue; }
+typedef Queue<uint16> SlotList;
+class TypeMap;
+
+# define CLS(T) T*
+#else
+# define CLS(T) void*
+#endif
+
+/*
+ * Trace monitor. Every JSThread (if JS_THREADSAFE) or JSRuntime (if not
+ * JS_THREADSAFE) has an associated trace monitor that keeps track of loop
+ * frequencies for all JavaScript code loaded into that runtime.
+ */
+typedef struct JSTraceMonitor {
+ /*
+ * Flag set when running (or recording) JIT-compiled code. This prevents
+ * both interpreter activation and last-ditch garbage collection when up
+ * against our runtime's memory limits. This flag also suppresses calls to
+ * JS_ReportOutOfMemory when failing due to runtime limits.
+ */
+ JSBool onTrace;
+ CLS(nanojit::Fragmento) fragmento;
+ CLS(TraceRecorder) recorder;
+ uint32 globalShape;
+ CLS(SlotList) globalSlots;
+ CLS(TypeMap) globalTypeMap;
+ jsval *recoveryDoublePool;
+ jsval *recoveryDoublePoolPtr;
+
+ /* Fragmento for the regular expression compiler. This is logically
+ * a distinct compiler but needs to be managed in exactly the same
+ * way as the real tracing Fragmento. */
+ CLS(nanojit::Fragmento) reFragmento;
+
+ /* Keep a list of recorders we need to abort on cache flush. */
+ CLS(TraceRecorder) abortStack;
+} JSTraceMonitor;
+
+#ifdef JS_TRACER
+# define JS_ON_TRACE(cx) (JS_TRACE_MONITOR(cx).onTrace)
+#else
+# define JS_ON_TRACE(cx) JS_FALSE
+#endif
+
+#ifdef JS_THREADSAFE
+
+/*
+ * Structure uniquely representing a thread. It holds thread-private data
+ * that can be accessed without a global lock.
+ */
+struct JSThread {
+ /* Linked list of all contexts active on this thread. */
+ JSCList contextList;
+
+ /* Opaque thread-id, from NSPR's PR_GetCurrentThread(). */
+ jsword id;
+
+ /*
+ * Thread-local version of JSRuntime.gcMallocBytes to avoid taking
+ * locks on each JS_malloc.
+ */
+ uint32 gcMallocBytes;
+
+ /*
+ * Store the GSN cache in struct JSThread, not struct JSContext, both to
+ * save space and to simplify cleanup in js_GC. Any embedding (Firefox
+ * or another Gecko application) that uses many contexts per thread is
+ * unlikely to interleave js_GetSrcNote-intensive loops in the decompiler
+ * among two or more contexts running script in one thread.
+ */
+ JSGSNCache gsnCache;
+
+ /* Property cache for faster call/get/set invocation. */
+ JSPropertyCache propertyCache;
+
+ /* Trace-tree JIT recorder/interpreter state. */
+ JSTraceMonitor traceMonitor;
+
+ /* Lock-free list of scripts created by eval to garbage-collect. */
+ JSScript *scriptsToGC;
+};
+
+#define JS_GSN_CACHE(cx) ((cx)->thread->gsnCache)
+#define JS_PROPERTY_CACHE(cx) ((cx)->thread->propertyCache)
+#define JS_TRACE_MONITOR(cx) ((cx)->thread->traceMonitor)
+#define JS_SCRIPTS_TO_GC(cx) ((cx)->thread->scriptsToGC)
+
+extern void
+js_ThreadDestructorCB(void *ptr);
+
+extern JSBool
+js_SetContextThread(JSContext *cx);
+
+extern void
+js_ClearContextThread(JSContext *cx);
+
+extern JSThread *
+js_GetCurrentThread(JSRuntime *rt);
+
+#endif /* JS_THREADSAFE */
+
+typedef enum JSDestroyContextMode {
+ JSDCM_NO_GC,
+ JSDCM_MAYBE_GC,
+ JSDCM_FORCE_GC,
+ JSDCM_NEW_FAILED
+} JSDestroyContextMode;
+
+typedef enum JSRuntimeState {
+ JSRTS_DOWN,
+ JSRTS_LAUNCHING,
+ JSRTS_UP,
+ JSRTS_LANDING
+} JSRuntimeState;
+
+typedef struct JSPropertyTreeEntry {
+ JSDHashEntryHdr hdr;
+ JSScopeProperty *child;
+} JSPropertyTreeEntry;
+
+typedef struct JSSetSlotRequest JSSetSlotRequest;
+
+struct JSSetSlotRequest {
+ JSObject *obj; /* object containing slot to set */
+ JSObject *pobj; /* new proto or parent reference */
+ uint16 slot; /* which to set, proto or parent */
+ uint16 errnum; /* JSMSG_NO_ERROR or error result */
+ JSSetSlotRequest *next; /* next request in GC worklist */
+};
+
+struct JSRuntime {
+ /* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
+ JSRuntimeState state;
+
+ /* Context create/destroy callback. */
+ JSContextCallback cxCallback;
+
+ /* Garbage collector state, used by jsgc.c. */
+ JSGCChunkInfo *gcChunkList;
+ JSGCArenaList gcArenaList[GC_NUM_FREELISTS];
+ JSGCDoubleArenaList gcDoubleArenaList;
+ JSGCFreeListSet *gcFreeListsPool;
+ JSDHashTable gcRootsHash;
+ JSDHashTable *gcLocksHash;
+ jsrefcount gcKeepAtoms;
+ uint32 gcBytes;
+ uint32 gcLastBytes;
+ uint32 gcMaxBytes;
+ uint32 gcMaxMallocBytes;
+ uint32 gcEmptyArenaPoolLifespan;
+ uint32 gcLevel;
+ uint32 gcNumber;
+ JSTracer *gcMarkingTracer;
+
+ /*
+ * NB: do not pack another flag here by claiming gcPadding unless the new
+ * flag is written only by the GC thread. Atomic updates to packed bytes
+ * are not guaranteed, so stores issued by one thread may be lost due to
+ * unsynchronized read-modify-write cycles on other threads.
+ */
+ JSPackedBool gcPoke;
+ JSPackedBool gcRunning;
+ uint16 gcPadding;
+#ifdef JS_GC_ZEAL
+ jsrefcount gcZeal;
+#endif
+
+ JSGCCallback gcCallback;
+ uint32 gcMallocBytes;
+ JSGCArenaInfo *gcUntracedArenaStackTop;
+#ifdef DEBUG
+ size_t gcTraceLaterCount;
+#endif
+
+ /*
+ * Table for tracking iterators to ensure that we close iterator's state
+ * before finalizing the iterable object.
+ */
+ JSPtrTable gcIteratorTable;
+
+ /*
+ * The trace operation and its data argument to trace embedding-specific
+ * GC roots.
+ */
+ JSTraceDataOp gcExtraRootsTraceOp;
+ void *gcExtraRootsData;
+
+ /*
+ * Used to serialize cycle checks when setting __proto__ or __parent__ by
+ * requesting the GC handle the required cycle detection. If the GC hasn't
+ * been poked, it won't scan for garbage. This member is protected by
+ * rt->gcLock.
+ */
+ JSSetSlotRequest *setSlotRequests;
+
+ /* Random number generator state, used by jsmath.c. */
+ JSBool rngInitialized;
+ int64 rngMultiplier;
+ int64 rngAddend;
+ int64 rngMask;
+ int64 rngSeed;
+ jsdouble rngDscale;
+
+ /* Well-known numbers held for use by this runtime's contexts. */
+ jsdouble *jsNaN;
+ jsdouble *jsNegativeInfinity;
+ jsdouble *jsPositiveInfinity;
+
+#ifdef JS_THREADSAFE
+ JSLock *deflatedStringCacheLock;
+#endif
+ JSHashTable *deflatedStringCache;
+#ifdef DEBUG
+ uint32 deflatedStringCacheBytes;
+#endif
+
+ /*
+ * Empty and unit-length strings held for use by this runtime's contexts.
+ * The unitStrings array and its elements are created on demand.
+ */
+ JSString *emptyString;
+ JSString **unitStrings;
+
+ /* List of active contexts sharing this runtime; protected by gcLock. */
+ JSCList contextList;
+
+ /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
+ JSDebugHooks globalDebugHooks;
+
+ /* More debugging state, see jsdbgapi.c. */
+ JSCList trapList;
+ JSCList watchPointList;
+
+ /* Client opaque pointers */
+ void *data;
+
+#ifdef JS_THREADSAFE
+ /* These combine to interlock the GC and new requests. */
+ PRLock *gcLock;
+ PRCondVar *gcDone;
+ PRCondVar *requestDone;
+ uint32 requestCount;
+ JSThread *gcThread;
+
+ /* Lock and owning thread pointer for JS_LOCK_RUNTIME. */
+ PRLock *rtLock;
+#ifdef DEBUG
+ jsword rtLockOwner;
+#endif
+
+ /* Used to synchronize down/up state change; protected by gcLock. */
+ PRCondVar *stateChange;
+
+ /*
+ * State for sharing single-threaded titles, once a second thread tries to
+ * lock a title. The titleSharingDone condvar is protected by rt->gcLock
+ * to minimize number of locks taken in JS_EndRequest.
+ *
+ * The titleSharingTodo linked list is likewise "global" per runtime, not
+ * one-list-per-context, to conserve space over all contexts, optimizing
+ * for the likely case that titles become shared rarely, and among a very
+ * small set of threads (contexts).
+ */
+ PRCondVar *titleSharingDone;
+ JSTitle *titleSharingTodo;
+
+/*
+ * Magic terminator for the rt->titleSharingTodo linked list, threaded through
+ * title->u.link. This hack allows us to test whether a title is on the list
+ * by asking whether title->u.link is non-null. We use a large, likely bogus
+ * pointer here to distinguish this value from any valid u.count (small int)
+ * value.
+ */
+#define NO_TITLE_SHARING_TODO ((JSTitle *) 0xfeedbeef)
+
+ /*
+ * Lock serializing trapList and watchPointList accesses, and count of all
+ * mutations to trapList and watchPointList made by debugger threads. To
+ * keep the code simple, we define debuggerMutations for the thread-unsafe
+ * case too.
+ */
+ PRLock *debuggerLock;
+#endif /* JS_THREADSAFE */
+ uint32 debuggerMutations;
+
+ /*
+ * Security callbacks set on the runtime are used by each context unless
+ * an override is set on the context.
+ */
+ JSSecurityCallbacks *securityCallbacks;
+
+ /*
+ * Shared scope property tree, and arena-pool for allocating its nodes.
+ * The propertyRemovals counter is incremented for every js_ClearScope,
+ * and for each js_RemoveScopeProperty that frees a slot in an object.
+ * See js_NativeGet and js_NativeSet in jsobj.c.
+ */
+ JSDHashTable propertyTreeHash;
+ JSScopeProperty *propertyFreeList;
+ JSArenaPool propertyArenaPool;
+ int32 propertyRemovals;
+
+ /* Script filename table. */
+ struct JSHashTable *scriptFilenameTable;
+ JSCList scriptFilenamePrefixes;
+#ifdef JS_THREADSAFE
+ PRLock *scriptFilenameTableLock;
+#endif
+
+ /* Number localization, used by jsnum.c */
+ const char *thousandsSeparator;
+ const char *decimalSeparator;
+ const char *numGrouping;
+
+ /*
+ * Weak references to lazily-created, well-known XML singletons.
+ *
+ * NB: Singleton objects must be carefully disconnected from the rest of
+ * the object graph usually associated with a JSContext's global object,
+ * including the set of standard class objects. See jsxml.c for details.
+ */
+ JSObject *anynameObject;
+ JSObject *functionNamespaceObject;
+
+ /*
+ * A helper list for the GC, so it can mark native iterator states. See
+ * js_TraceNativeEnumerators for details.
+ */
+ JSNativeEnumerator *nativeEnumerators;
+
+#ifndef JS_THREADSAFE
+ /*
+ * For thread-unsafe embeddings, the GSN cache lives in the runtime and
+ * not each context, since we expect it to be filled once when decompiling
+ * a longer script, then hit repeatedly as js_GetSrcNote is called during
+ * the decompiler activation that filled it.
+ */
+ JSGSNCache gsnCache;
+
+ /* Property cache for faster call/get/set invocation. */
+ JSPropertyCache propertyCache;
+
+ /* Trace-tree JIT recorder/interpreter state. */
+ JSTraceMonitor traceMonitor;
+
+ /* Lock-free list of scripts created by eval to garbage-collect. */
+ JSScript *scriptsToGC;
+
+#define JS_GSN_CACHE(cx) ((cx)->runtime->gsnCache)
+#define JS_PROPERTY_CACHE(cx) ((cx)->runtime->propertyCache)
+#define JS_TRACE_MONITOR(cx) ((cx)->runtime->traceMonitor)
+#define JS_SCRIPTS_TO_GC(cx) ((cx)->runtime->scriptsToGC)
+#endif
+
+ /*
+ * Object shape (property cache structural type) identifier generator.
+ *
+ * Type 0 stands for the empty scope, and must not be regenerated due to
+ * uint32 wrap-around. Since we use atomic pre-increment, the initial
+ * value for the first typed non-empty scope will be 1.
+ *
+ * The GC compresses live types, minimizing rt->shapeGen in the process.
+ * If this counter overflows into SHAPE_OVERFLOW_BIT (in jsinterp.h), the
+ * GC will disable property caches for all threads, to avoid aliasing two
+ * different types. Updated by js_GenerateShape (in jsinterp.c).
+ */
+ uint32 shapeGen;
+
+ /* Literal table maintained by jsatom.c functions. */
+ JSAtomState atomState;
+
+ /*
+ * Cache of reusable JSNativeEnumerators mapped by shape identifiers (as
+ * stored in scope->shape). This cache is nulled by the GC and protected
+ * by gcLock.
+ */
+#define NATIVE_ENUM_CACHE_LOG2 8
+#define NATIVE_ENUM_CACHE_MASK JS_BITMASK(NATIVE_ENUM_CACHE_LOG2)
+#define NATIVE_ENUM_CACHE_SIZE JS_BIT(NATIVE_ENUM_CACHE_LOG2)
+
+#define NATIVE_ENUM_CACHE_HASH(shape) \
+ ((((shape) >> NATIVE_ENUM_CACHE_LOG2) ^ (shape)) & NATIVE_ENUM_CACHE_MASK)
+
+ jsuword nativeEnumCache[NATIVE_ENUM_CACHE_SIZE];
+
+ /*
+ * Runtime-wide flag set to true when any Array prototype has an indexed
+ * property defined on it, creating a hazard for code reading or writing
+ * over a hole from a dense Array instance that is not prepared to look up
+ * the proto chain (the writing case must involve a check for a read-only
+ * element, which cannot be shadowed).
+ */
+ JSBool anyArrayProtoHasElement;
+
+ /*
+ * Various metering fields are defined at the end of JSRuntime. In this
+ * way there is no need to recompile all the code that refers to other
+ * fields of JSRuntime after enabling the corresponding metering macro.
+ */
+#ifdef JS_DUMP_ENUM_CACHE_STATS
+ int32 nativeEnumProbes;
+ int32 nativeEnumMisses;
+# define ENUM_CACHE_METER(name) JS_ATOMIC_INCREMENT(&cx->runtime->name)
+#else
+# define ENUM_CACHE_METER(name) ((void) 0)
+#endif
+
+#ifdef JS_DUMP_LOOP_STATS
+ /* Loop statistics, to trigger trace recording and compiling. */
+ JSBasicStats loopStats;
+#endif
+
+#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS
+ /* Function invocation metering. */
+ jsrefcount inlineCalls;
+ jsrefcount nativeCalls;
+ jsrefcount nonInlineCalls;
+ jsrefcount constructs;
+
+ /* Title lock and scope property metering. */
+ jsrefcount claimAttempts;
+ jsrefcount claimedTitles;
+ jsrefcount deadContexts;
+ jsrefcount deadlocksAvoided;
+ jsrefcount liveScopes;
+ jsrefcount sharedTitles;
+ jsrefcount totalScopes;
+ jsrefcount liveScopeProps;
+ jsrefcount liveScopePropsPreSweep;
+ jsrefcount totalScopeProps;
+ jsrefcount livePropTreeNodes;
+ jsrefcount duplicatePropTreeNodes;
+ jsrefcount totalPropTreeNodes;
+ jsrefcount propTreeKidsChunks;
+ jsrefcount middleDeleteFixups;
+
+ /* String instrumentation. */
+ jsrefcount liveStrings;
+ jsrefcount totalStrings;
+ jsrefcount liveDependentStrings;
+ jsrefcount totalDependentStrings;
+ jsrefcount badUndependStrings;
+ double lengthSum;
+ double lengthSquaredSum;
+ double strdepLengthSum;
+ double strdepLengthSquaredSum;
+#endif /* DEBUG || JS_DUMP_PROPTREE_STATS */
+
+#ifdef JS_SCOPE_DEPTH_METER
+ /*
+ * Stats on runtime prototype chain lookups and scope chain depths, i.e.,
+ * counts of objects traversed on a chain until the wanted id is found.
+ */
+ JSBasicStats protoLookupDepthStats;
+ JSBasicStats scopeSearchDepthStats;
+
+ /*
+ * Stats on compile-time host environment and lexical scope chain lengths
+ * (maximum depths).
+ */
+ JSBasicStats hostenvScopeDepthStats;
+ JSBasicStats lexicalScopeDepthStats;
+#endif
+
+#ifdef JS_GCMETER
+ JSGCStats gcStats;
+#endif
+};
+
+#ifdef DEBUG
+# define JS_RUNTIME_METER(rt, which) JS_ATOMIC_INCREMENT(&(rt)->which)
+# define JS_RUNTIME_UNMETER(rt, which) JS_ATOMIC_DECREMENT(&(rt)->which)
+#else
+# define JS_RUNTIME_METER(rt, which) /* nothing */
+# define JS_RUNTIME_UNMETER(rt, which) /* nothing */
+#endif
+
+#define JS_KEEP_ATOMS(rt) JS_ATOMIC_INCREMENT(&(rt)->gcKeepAtoms);
+#define JS_UNKEEP_ATOMS(rt) JS_ATOMIC_DECREMENT(&(rt)->gcKeepAtoms);
+
+#ifdef JS_ARGUMENT_FORMATTER_DEFINED
+/*
+ * Linked list mapping format strings for JS_{Convert,Push}Arguments{,VA} to
+ * formatter functions. Elements are sorted in non-increasing format string
+ * length order.
+ */
+struct JSArgumentFormatMap {
+ const char *format;
+ size_t length;
+ JSArgumentFormatter formatter;
+ JSArgumentFormatMap *next;
+};
+#endif
+
+struct JSStackHeader {
+ uintN nslots;
+ JSStackHeader *down;
+};
+
+#define JS_STACK_SEGMENT(sh) ((jsval *)(sh) + 2)
+
+/*
+ * Key and entry types for the JSContext.resolvingTable hash table, typedef'd
+ * here because all consumers need to see these declarations (and not just the
+ * typedef names, as would be the case for an opaque pointer-to-typedef'd-type
+ * declaration), along with cx->resolvingTable.
+ */
+typedef struct JSResolvingKey {
+ JSObject *obj;
+ jsid id;
+} JSResolvingKey;
+
+typedef struct JSResolvingEntry {
+ JSDHashEntryHdr hdr;
+ JSResolvingKey key;
+ uint32 flags;
+} JSResolvingEntry;
+
+#define JSRESFLAG_LOOKUP 0x1 /* resolving id from lookup */
+#define JSRESFLAG_WATCH 0x2 /* resolving id from watch */
+
+typedef struct JSLocalRootChunk JSLocalRootChunk;
+
+#define JSLRS_CHUNK_SHIFT 8
+#define JSLRS_CHUNK_SIZE JS_BIT(JSLRS_CHUNK_SHIFT)
+#define JSLRS_CHUNK_MASK JS_BITMASK(JSLRS_CHUNK_SHIFT)
+
+struct JSLocalRootChunk {
+ jsval roots[JSLRS_CHUNK_SIZE];
+ JSLocalRootChunk *down;
+};
+
+typedef struct JSLocalRootStack {
+ uint32 scopeMark;
+ uint32 rootCount;
+ JSLocalRootChunk *topChunk;
+ JSLocalRootChunk firstChunk;
+} JSLocalRootStack;
+
+#define JSLRS_NULL_MARK ((uint32) -1)
+
+/*
+ * Macros to push/pop JSTempValueRooter instances to context-linked stack of
+ * temporary GC roots. If you need to protect a result value that flows out of
+ * a C function across several layers of other functions, use the
+ * js_LeaveLocalRootScopeWithResult internal API (see further below) instead.
+ *
+ * The macros also provide a simple way to get a single rooted pointer via
+ * JS_PUSH_TEMP_ROOT_<KIND>(cx, NULL, &tvr). Then &tvr.u.<kind> gives the
+ * necessary pointer.
+ *
+ * JSTempValueRooter.count defines the type of the rooted value referenced by
+ * JSTempValueRooter.u union of type JSTempValueUnion. When count is positive
+ * or zero, u.array points to a vector of jsvals. Otherwise it must be one of
+ * the following constants:
+ */
+#define JSTVU_SINGLE (-1) /* u.value or u.<gcthing> is single jsval
+ or GC-thing */
+#define JSTVU_TRACE (-2) /* u.trace is a hook to trace a custom
+ * structure */
+#define JSTVU_SPROP (-3) /* u.sprop roots property tree node */
+#define JSTVU_WEAK_ROOTS (-4) /* u.weakRoots points to saved weak roots */
+#define JSTVU_PARSE_CONTEXT (-5) /* u.parseContext roots JSParseContext* */
+#define JSTVU_SCRIPT (-6) /* u.script roots JSScript* */
+
+/*
+ * Here single JSTVU_SINGLE covers both jsval and pointers to any GC-thing via
+ * reinterpreting the thing as JSVAL_OBJECT. It works because the GC-thing is
+ * aligned on a 0 mod 8 boundary, and object has the 0 jsval tag. So any
+ * GC-thing may be tagged as if it were an object and untagged, if it's then
+ * used only as an opaque pointer until discriminated by other means than tag
+ * bits. This is how, for example, js_GetGCThingTraceKind uses its |thing|
+ * parameter -- it consults GC-thing flags stored separately from the thing to
+ * decide the kind of thing.
+ *
+ * The following checks that this type-punning is possible.
+ */
+JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(jsval));
+JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(void *));
+
+#define JS_PUSH_TEMP_ROOT_COMMON(cx,x,tvr,cnt,kind) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT((cx)->tempValueRooters != (tvr)); \
+ (tvr)->count = (cnt); \
+ (tvr)->u.kind = (x); \
+ (tvr)->down = (cx)->tempValueRooters; \
+ (cx)->tempValueRooters = (tvr); \
+ JS_END_MACRO
+
+#define JS_POP_TEMP_ROOT(cx,tvr) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT((cx)->tempValueRooters == (tvr)); \
+ (cx)->tempValueRooters = (tvr)->down; \
+ JS_END_MACRO
+
+#define JS_PUSH_TEMP_ROOT(cx,cnt,arr,tvr) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT((int)(cnt) >= 0); \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, arr, tvr, (ptrdiff_t) (cnt), array); \
+ JS_END_MACRO
+
+#define JS_PUSH_SINGLE_TEMP_ROOT(cx,val,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, val, tvr, JSTVU_SINGLE, value)
+
+#define JS_PUSH_TEMP_ROOT_OBJECT(cx,obj,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, obj, tvr, JSTVU_SINGLE, object)
+
+#define JS_PUSH_TEMP_ROOT_STRING(cx,str,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, str, tvr, JSTVU_SINGLE, string)
+
+#define JS_PUSH_TEMP_ROOT_XML(cx,xml_,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, xml_, tvr, JSTVU_SINGLE, xml)
+
+#define JS_PUSH_TEMP_ROOT_TRACE(cx,trace_,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, trace_, tvr, JSTVU_TRACE, trace)
+
+#define JS_PUSH_TEMP_ROOT_SPROP(cx,sprop_,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, sprop_, tvr, JSTVU_SPROP, sprop)
+
+#define JS_PUSH_TEMP_ROOT_WEAK_COPY(cx,weakRoots_,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, weakRoots_, tvr, JSTVU_WEAK_ROOTS, weakRoots)
+
+#define JS_PUSH_TEMP_ROOT_PARSE_CONTEXT(cx,pc,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, pc, tvr, JSTVU_PARSE_CONTEXT, parseContext)
+
+#define JS_PUSH_TEMP_ROOT_SCRIPT(cx,script_,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, script_, tvr, JSTVU_SCRIPT, script)
+
+
+#define JSRESOLVE_INFER 0xffff /* infer bits from current bytecode */
+
+struct JSContext {
+ /* JSRuntime contextList linkage. */
+ JSCList links;
+
+ /*
+ * Operation count. It is declared early in the structure as a frequently
+ * accessed field.
+ */
+ int32 operationCount;
+
+#if JS_HAS_XML_SUPPORT
+ /*
+ * Bit-set formed from binary exponentials of the XML_* tiny-ids defined
+ * for boolean settings in jsxml.c, plus an XSF_CACHE_VALID bit. Together
+ * these act as a cache of the boolean XML.ignore* and XML.prettyPrinting
+ * property values associated with this context's global object.
+ */
+ uint8 xmlSettingFlags;
+ uint8 padding;
+#else
+ uint16 padding;
+#endif
+
+ /*
+ * Classic Algol "display" static link optimization.
+ */
+#define JS_DISPLAY_SIZE 16
+
+ JSStackFrame *display[JS_DISPLAY_SIZE];
+
+ /* Runtime version control identifier. */
+ uint16 version;
+
+ /* Per-context options. */
+ uint32 options; /* see jsapi.h for JSOPTION_* */
+
+ /* Locale specific callbacks for string conversion. */
+ JSLocaleCallbacks *localeCallbacks;
+
+ /*
+ * cx->resolvingTable is non-null and non-empty if we are initializing
+ * standard classes lazily, or if we are otherwise recursing indirectly
+ * from js_LookupProperty through a JSClass.resolve hook. It is used to
+ * limit runaway recursion (see jsapi.c and jsobj.c).
+ */
+ JSDHashTable *resolvingTable;
+
+#if JS_HAS_LVALUE_RETURN
+ /*
+ * Secondary return value from native method called on the left-hand side
+ * of an assignment operator. The native should store the object in which
+ * to set a property in *rval, and return the property's id expressed as a
+ * jsval by calling JS_SetCallReturnValue2(cx, idval).
+ */
+ jsval rval2;
+ JSPackedBool rval2set;
+#endif
+
+ /*
+ * True if generating an error, to prevent runaway recursion.
+ * NB: generatingError packs with rval2set, #if JS_HAS_LVALUE_RETURN;
+ * with insideGCMarkCallback and with throwing below.
+ */
+ JSPackedBool generatingError;
+
+ /* Flag to indicate that we run inside gcCallback(cx, JSGC_MARK_END). */
+ JSPackedBool insideGCMarkCallback;
+
+ /* Exception state -- the exception member is a GC root by definition. */
+ JSPackedBool throwing; /* is there a pending exception? */
+ jsval exception; /* most-recently-thrown exception */
+
+ /* Limit pointer for checking native stack consumption during recursion. */
+ jsuword stackLimit;
+
+ /* Quota on the size of arenas used to compile and execute scripts. */
+ size_t scriptStackQuota;
+
+ /* Data shared by threads in an address space. */
+ JSRuntime *runtime;
+
+ /* Stack arena pool and frame pointer register. */
+ JSArenaPool stackPool;
+ JSStackFrame *fp;
+
+ /* Temporary arena pool used while compiling and decompiling. */
+ JSArenaPool tempPool;
+
+ /* Top-level object and pointer to top stack frame's scope chain. */
+ JSObject *globalObject;
+
+ /* Storage to root recently allocated GC things and script result. */
+ JSWeakRoots weakRoots;
+
+ /* Regular expression class statics (XXX not shared globally). */
+ JSRegExpStatics regExpStatics;
+
+ /* State for object and array toSource conversion. */
+ JSSharpObjectMap sharpObjectMap;
+
+ /* Argument formatter support for JS_{Convert,Push}Arguments{,VA}. */
+ JSArgumentFormatMap *argumentFormatMap;
+
+ /* Last message string and trace file for debugging. */
+ char *lastMessage;
+#ifdef DEBUG
+ void *tracefp;
+#endif
+
+ /* Per-context optional error reporter. */
+ JSErrorReporter errorReporter;
+
+ /*
+ * Flag indicating that the operation callback is set. When the flag is 0
+ * but operationCallback is not null, operationCallback stores the branch
+ * callback.
+ */
+ uint32 operationCallbackIsSet : 1;
+ uint32 operationLimit : 31;
+ JSOperationCallback operationCallback;
+
+ /* Interpreter activation count. */
+ uintN interpLevel;
+
+ /* Client opaque pointers. */
+ void *data;
+ void *data2;
+
+ /* GC and thread-safe state. */
+ JSStackFrame *dormantFrameChain; /* dormant stack frame to scan */
+#ifdef JS_THREADSAFE
+ JSThread *thread;
+ jsrefcount requestDepth;
+ /* Same as requestDepth but ignoring JS_SuspendRequest/JS_ResumeRequest */
+ jsrefcount outstandingRequests;
+ JSTitle *titleToShare; /* weak reference, see jslock.c */
+ JSTitle *lockedSealedTitle; /* weak ref, for low-cost sealed
+ title locking */
+ JSCList threadLinks; /* JSThread contextList linkage */
+
+#define CX_FROM_THREAD_LINKS(tl) \
+ ((JSContext *)((char *)(tl) - offsetof(JSContext, threadLinks)))
+#endif
+
+ /* PDL of stack headers describing stack slots not rooted by argv, etc. */
+ JSStackHeader *stackHeaders;
+
+ /* Optional stack of heap-allocated scoped local GC roots. */
+ JSLocalRootStack *localRootStack;
+
+ /* Stack of thread-stack-allocated temporary GC roots. */
+ JSTempValueRooter *tempValueRooters;
+
+#ifdef JS_THREADSAFE
+ JSGCFreeListSet *gcLocalFreeLists;
+#endif
+
+ /* List of pre-allocated doubles. */
+ JSGCDoubleCell *doubleFreeList;
+
+ /* Debug hooks associated with the current context. */
+ JSDebugHooks *debugHooks;
+
+ /* Security callbacks that override any defined on the runtime. */
+ JSSecurityCallbacks *securityCallbacks;
+
+ /* Pinned regexp pool used for regular expressions. */
+ JSArenaPool regexpPool;
+
+ /* Stored here to avoid passing it around as a parameter. */
+ uintN resolveFlags;
+};
+
+#ifdef JS_THREADSAFE
+# define JS_THREAD_ID(cx) ((cx)->thread ? (cx)->thread->id : 0)
+#endif
+
+#ifdef __cplusplus
+/* FIXME(bug 332648): Move this into a public header. */
+class JSAutoTempValueRooter
+{
+ public:
+ JSAutoTempValueRooter(JSContext *cx, size_t len, jsval *vec)
+ : mContext(cx) {
+ JS_PUSH_TEMP_ROOT(mContext, len, vec, &mTvr);
+ }
+ JSAutoTempValueRooter(JSContext *cx, jsval v)
+ : mContext(cx) {
+ JS_PUSH_SINGLE_TEMP_ROOT(mContext, v, &mTvr);
+ }
+
+ ~JSAutoTempValueRooter() {
+ JS_POP_TEMP_ROOT(mContext, &mTvr);
+ }
+
+ protected:
+ JSContext *mContext;
+
+ private:
+#ifndef AIX
+ static void *operator new(size_t);
+ static void operator delete(void *, size_t);
+#endif
+
+ JSTempValueRooter mTvr;
+};
+
+class JSAutoResolveFlags
+{
+ public:
+ JSAutoResolveFlags(JSContext *cx, uintN flags)
+ : mContext(cx), mSaved(cx->resolveFlags) {
+ cx->resolveFlags = flags;
+ }
+
+ ~JSAutoResolveFlags() { mContext->resolveFlags = mSaved; }
+
+ private:
+ JSContext *mContext;
+ uintN mSaved;
+};
+#endif
+
+/*
+ * Slightly more readable macros for testing per-context option settings (also
+ * to hide bitset implementation detail).
+ *
+ * JSOPTION_XML must be handled specially in order to propagate from compile-
+ * to run-time (from cx->options to script->version/cx->version). To do that,
+ * we copy JSOPTION_XML from cx->options into cx->version as JSVERSION_HAS_XML
+ * whenever options are set, and preserve this XML flag across version number
+ * changes done via the JS_SetVersion API.
+ *
+ * But when executing a script or scripted function, the interpreter changes
+ * cx->version, including the XML flag, to script->version. Thus JSOPTION_XML
+ * is a compile-time option that causes a run-time version change during each
+ * activation of the compiled script. That version change has the effect of
+ * changing JS_HAS_XML_OPTION, so that any compiling done via eval enables XML
+ * support. If an XML-enabled script or function calls a non-XML function,
+ * the flag bit will be cleared during the callee's activation.
+ *
+ * Note that JS_SetVersion API calls never pass JSVERSION_HAS_XML or'd into
+ * that API's version parameter.
+ *
+ * Note also that script->version must contain this XML option flag in order
+ * for XDR'ed scripts to serialize and deserialize with that option preserved
+ * for detection at run-time. We can't copy other compile-time options into
+ * script->version because that would break backward compatibility (certain
+ * other options, e.g. JSOPTION_VAROBJFIX, are analogous to JSOPTION_XML).
+ */
+#define JS_HAS_OPTION(cx,option) (((cx)->options & (option)) != 0)
+#define JS_HAS_STRICT_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_STRICT)
+#define JS_HAS_WERROR_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_WERROR)
+#define JS_HAS_COMPILE_N_GO_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_COMPILE_N_GO)
+#define JS_HAS_ATLINE_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_ATLINE)
+
+#define JSVERSION_MASK 0x0FFF /* see JSVersion in jspubtd.h */
+#define JSVERSION_HAS_XML 0x1000 /* flag induced by XML option */
+
+#define JSVERSION_NUMBER(cx) ((JSVersion)((cx)->version & \
+ JSVERSION_MASK))
+#define JS_HAS_XML_OPTION(cx) ((cx)->version & JSVERSION_HAS_XML || \
+ JSVERSION_NUMBER(cx) >= JSVERSION_1_6)
+
+/*
+ * Initialize a library-wide thread private data index, and remember that it
+ * has already been done, so that it happens only once ever. Returns true on
+ * success.
+ */
+extern JSBool
+js_InitThreadPrivateIndex(void (*ptr)(void *));
+
+/*
+ * Common subroutine of JS_SetVersion and js_SetVersion, to update per-context
+ * data that depends on version.
+ */
+extern void
+js_OnVersionChange(JSContext *cx);
+
+/*
+ * Unlike the JS_SetVersion API, this function stores JSVERSION_HAS_XML and
+ * any future non-version-number flags induced by compiler options.
+ */
+extern void
+js_SetVersion(JSContext *cx, JSVersion version);
+
+/*
+ * Create and destroy functions for JSContext, which is manually allocated
+ * and exclusively owned.
+ */
+extern JSContext *
+js_NewContext(JSRuntime *rt, size_t stackChunkSize);
+
+extern void
+js_DestroyContext(JSContext *cx, JSDestroyContextMode mode);
+
+/*
+ * Return true if cx points to a context in rt->contextList, else return false.
+ * NB: the caller (see jslock.c:ClaimTitle) must hold rt->gcLock.
+ */
+extern JSBool
+js_ValidContextPointer(JSRuntime *rt, JSContext *cx);
+
+/*
+ * If unlocked, acquire and release rt->gcLock around *iterp update; otherwise
+ * the caller must be holding rt->gcLock.
+ */
+extern JSContext *
+js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp);
+
+/*
+ * JSClass.resolve and watchpoint recursion damping machinery.
+ */
+extern JSBool
+js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
+ JSResolvingEntry **entryp);
+
+extern void
+js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
+ JSResolvingEntry *entry, uint32 generation);
+
+/*
+ * Local root set management.
+ *
+ * NB: the jsval parameters below may be properly tagged jsvals, or GC-thing
+ * pointers cast to (jsval). This relies on JSObject's tag being zero, but
+ * on the up side it lets us push int-jsval-encoded scopeMark values on the
+ * local root stack.
+ */
+extern JSBool
+js_EnterLocalRootScope(JSContext *cx);
+
+#define js_LeaveLocalRootScope(cx) \
+ js_LeaveLocalRootScopeWithResult(cx, JSVAL_NULL)
+
+extern void
+js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval);
+
+extern void
+js_ForgetLocalRoot(JSContext *cx, jsval v);
+
+extern int
+js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v);
+
+extern void
+js_TraceLocalRoots(JSTracer *trc, JSLocalRootStack *lrs);
+
+/*
+ * Report an exception, which is currently realized as a printf-style format
+ * string and its arguments.
+ */
+typedef enum JSErrNum {
+#define MSG_DEF(name, number, count, exception, format) \
+ name = number,
+#include "js.msg"
+#undef MSG_DEF
+ JSErr_Limit
+} JSErrNum;
+
+extern JS_FRIEND_API(const JSErrorFormatString *)
+js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
+
+#ifdef va_start
+extern JSBool
+js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap);
+
+extern JSBool
+js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
+ void *userRef, const uintN errorNumber,
+ JSBool charArgs, va_list ap);
+
+extern JSBool
+js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
+ void *userRef, const uintN errorNumber,
+ char **message, JSErrorReport *reportp,
+ JSBool *warningp, JSBool charArgs, va_list ap);
+#endif
+
+extern void
+js_ReportOutOfMemory(JSContext *cx);
+
+/*
+ * Report that cx->scriptStackQuota is exhausted.
+ */
+extern void
+js_ReportOutOfScriptQuota(JSContext *cx);
+
+extern void
+js_ReportOverRecursed(JSContext *cx);
+
+extern void
+js_ReportAllocationOverflow(JSContext *cx);
+
+#define JS_CHECK_RECURSION(cx, onerror) \
+ JS_BEGIN_MACRO \
+ int stackDummy_; \
+ \
+ if (!JS_CHECK_STACK_SIZE(cx, stackDummy_)) { \
+ js_ReportOverRecursed(cx); \
+ onerror; \
+ } \
+ JS_END_MACRO
+
+/*
+ * Report an exception using a previously composed JSErrorReport.
+ * XXXbe remove from "friend" API
+ */
+extern JS_FRIEND_API(void)
+js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report);
+
+extern void
+js_ReportIsNotDefined(JSContext *cx, const char *name);
+
+/*
+ * Report an attempt to access the property of a null or undefined value (v).
+ */
+extern JSBool
+js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
+ JSString *fallback);
+
+extern void
+js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg);
+
+/*
+ * Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as
+ * the first argument for the error message. If the error message has less
+ * then 3 arguments, use null for arg1 or arg2.
+ */
+extern JSBool
+js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
+ intN spindex, jsval v, JSString *fallback,
+ const char *arg1, const char *arg2);
+
+#define js_ReportValueError(cx,errorNumber,spindex,v,fallback) \
+ ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
+ spindex, v, fallback, NULL, NULL))
+
+#define js_ReportValueError2(cx,errorNumber,spindex,v,fallback,arg1) \
+ ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
+ spindex, v, fallback, arg1, NULL))
+
+#define js_ReportValueError3(cx,errorNumber,spindex,v,fallback,arg1,arg2) \
+ ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
+ spindex, v, fallback, arg1, arg2))
+
+extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
+
+/*
+ * See JS_SetThreadStackLimit in jsapi.c, where we check that the stack grows
+ * in the expected direction. On Unix-y systems, JS_STACK_GROWTH_DIRECTION is
+ * computed on the build host by jscpucfg.c and written into jsautocfg.h. The
+ * macro is hardcoded in jscpucfg.h on Windows and Mac systems (for historical
+ * reasons pre-dating autoconf usage).
+ */
+#if JS_STACK_GROWTH_DIRECTION > 0
+# define JS_CHECK_STACK_SIZE(cx, lval) ((jsuword)&(lval) < (cx)->stackLimit)
+#else
+# define JS_CHECK_STACK_SIZE(cx, lval) ((jsuword)&(lval) > (cx)->stackLimit)
+#endif
+
+/*
+ * Update the operation counter according to the given weight and call the
+ * operation callback when we reach the operation limit. To make this
+ * frequently executed macro faster we decrease the counter from
+ * JSContext.operationLimit and compare against zero to check the limit.
+ *
+ * This macro can run the full GC. Return true if it is OK to continue and
+ * false otherwise.
+ */
+#define JS_CHECK_OPERATION_LIMIT(cx, weight) \
+ (JS_CHECK_OPERATION_WEIGHT(weight), \
+ (((cx)->operationCount -= (weight)) > 0 || js_ResetOperationCount(cx)))
+
+/*
+ * A version of JS_CHECK_OPERATION_LIMIT that just updates the operation count
+ * without calling the operation callback or any other API. This macro resets
+ * the count to 0 when it becomes negative to prevent a wrap-around when the
+ * macro is called repeatably.
+ */
+#define JS_COUNT_OPERATION(cx, weight) \
+ ((void)(JS_CHECK_OPERATION_WEIGHT(weight), \
+ (cx)->operationCount = ((cx)->operationCount > 0) \
+ ? (cx)->operationCount - (weight) \
+ : 0))
+
+/*
+ * The implementation of the above macros assumes that subtracting weights
+ * twice from a positive number does not wrap-around INT32_MIN.
+ */
+#define JS_CHECK_OPERATION_WEIGHT(weight) \
+ (JS_ASSERT((uint32) (weight) > 0), \
+ JS_ASSERT((uint32) (weight) < JS_BIT(30)))
+
+/* Relative operations weights. */
+#define JSOW_JUMP 1
+#define JSOW_ALLOCATION 100
+#define JSOW_LOOKUP_PROPERTY 5
+#define JSOW_GET_PROPERTY 10
+#define JSOW_SET_PROPERTY 20
+#define JSOW_NEW_PROPERTY 200
+#define JSOW_DELETE_PROPERTY 30
+#define JSOW_ENTER_SHARP JS_OPERATION_WEIGHT_BASE
+#define JSOW_SCRIPT_JUMP JS_OPERATION_WEIGHT_BASE
+
+/*
+ * Reset the operation count and call the operation callback assuming that the
+ * operation limit is reached.
+ */
+extern JSBool
+js_ResetOperationCount(JSContext *cx);
+
+JS_END_EXTERN_C
+
+#endif /* jscntxt_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jscompat.h b/tools/node_modules/expresso/deps/jscoverage/js/jscompat.h
new file mode 100644
index 0000000..80d8605
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jscompat.h
@@ -0,0 +1,57 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* -*- Mode: C; tab-width: 8 -*-
+ * Copyright (C) 1996-1999 Netscape Communications Corporation, All Rights Reserved.
+ */
+#ifndef jscompat_h___
+#define jscompat_h___
+/*
+ * Compatibility glue for various NSPR versions. We must always define int8,
+ * int16, jsword, and so on to minimize differences with js/ref, no matter what
+ * the NSPR typedef names may be.
+ */
+#include "jstypes.h"
+#include "jslong.h"
+
+typedef JSIntn intN;
+typedef JSUintn uintN;
+typedef JSUword jsuword;
+typedef JSWord jsword;
+typedef float float32;
+#define allocPriv allocPool
+#endif /* jscompat_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsconfig.mk b/tools/node_modules/expresso/deps/jscoverage/js/jsconfig.mk
new file mode 100644
index 0000000..1aeb75f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsconfig.mk
@@ -0,0 +1,181 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998-1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+ifndef OBJDIR
+ ifdef OBJDIR_NAME
+ OBJDIR = $(OBJDIR_NAME)
+ endif
+endif
+
+NSPR_VERSION = v4.0
+NSPR_LIBSUFFIX = 4
+
+NSPR_LOCAL = $(MOZ_DEPTH)/dist/$(OBJDIR)/nspr
+NSPR_DIST = $(MOZ_DEPTH)/dist/$(OBJDIR)
+NSPR_OBJDIR = $(OBJDIR)
+ifeq ($(OS_ARCH), SunOS)
+ NSPR_OBJDIR := $(subst _sparc,,$(NSPR_OBJDIR))
+endif
+ifeq ($(OS_ARCH), Linux)
+ LINUX_REL := $(shell uname -r)
+ ifneq (,$(findstring 2.0,$(LINUX_REL)))
+ NSPR_OBJDIR := $(subst _All,2.0_x86_glibc_PTH,$(NSPR_OBJDIR))
+ else
+ NSPR_OBJDIR := $(subst _All,2.2_x86_glibc_PTH,$(NSPR_OBJDIR))
+ endif
+endif
+ifeq ($(OS_ARCH), AIX)
+ NSPR_OBJDIR := $(subst 4.1,4.2,$(NSPR_OBJDIR))
+endif
+ifeq ($(OS_CONFIG), IRIX6.2)
+ NSPR_OBJDIR := $(subst 6.2,6.2_n32_PTH,$(NSPR_OBJDIR))
+endif
+ifeq ($(OS_CONFIG), IRIX6.5)
+ NSPR_OBJDIR := $(subst 6.5,6.5_n32_PTH,$(NSPR_OBJDIR))
+endif
+ifeq ($(OS_ARCH), WINNT)
+ ifeq ($(OBJDIR), WIN32_D.OBJ)
+ NSPR_OBJDIR = WINNT4.0_DBG.OBJ
+ endif
+ ifeq ($(OBJDIR), WIN32_O.OBJ)
+ NSPR_OBJDIR = WINNT4.0_OPT.OBJ
+ endif
+endif
+NSPR_SHARED = /share/builds/components/nspr20/$(NSPR_VERSION)/$(NSPR_OBJDIR)
+ifeq ($(OS_ARCH), WINNT)
+ NSPR_SHARED = nspr20/$(NSPR_VERSION)/$(NSPR_OBJDIR)
+endif
+NSPR_VERSIONFILE = $(NSPR_LOCAL)/Version
+NSPR_CURVERSION := $(shell cat $(NSPR_VERSIONFILE) 2>/dev/null)
+
+get_nspr:
+ @echo "Grabbing NSPR component..."
+ifeq ($(NSPR_VERSION), $(NSPR_CURVERSION))
+ @echo "No need, NSPR is up to date in this tree (ver=$(NSPR_VERSION))."
+else
+ mkdir -p $(NSPR_LOCAL)
+ mkdir -p $(NSPR_DIST)
+ ifneq ($(OS_ARCH), WINNT)
+ cp $(NSPR_SHARED)/*.jar $(NSPR_LOCAL)
+ else
+ sh $(MOZ_DEPTH)/../reltools/compftp.sh $(NSPR_SHARED) $(NSPR_LOCAL) *.jar
+ endif
+ unzip -o $(NSPR_LOCAL)/mdbinary.jar -d $(NSPR_DIST)
+ mkdir -p $(NSPR_DIST)/include
+ unzip -o $(NSPR_LOCAL)/mdheader.jar -d $(NSPR_DIST)/include
+ rm -rf $(NSPR_DIST)/META-INF
+ rm -rf $(NSPR_DIST)/include/META-INF
+ echo $(NSPR_VERSION) > $(NSPR_VERSIONFILE)
+endif
+
+SHIP_DIST = $(MOZ_DEPTH)/dist/$(OBJDIR)
+SHIP_DIR = $(SHIP_DIST)/SHIP
+
+SHIP_LIBS = libjs.$(SO_SUFFIX) libjs.a
+ifdef JS_LIVECONNECT
+ SHIP_LIBS += libjsj.$(SO_SUFFIX) libjsj.a
+endif
+ifeq ($(OS_ARCH), WINNT)
+ SHIP_LIBS = js32.dll js32.lib
+ ifdef JS_LIVECONNECT
+ SHIP_LIBS += jsj.dll jsj.lib
+ endif
+endif
+SHIP_LIBS += $(LCJAR)
+SHIP_LIBS := $(addprefix $(SHIP_DIST)/lib/, $(SHIP_LIBS))
+
+SHIP_INCS = js*.h prmjtime.h resource.h *.msg *.tbl
+ifdef JS_LIVECONNECT
+ SHIP_INCS += netscape*.h nsC*.h nsI*.h
+endif
+SHIP_INCS := $(addprefix $(SHIP_DIST)/include/, $(SHIP_INCS))
+
+SHIP_BINS = js
+ifdef JS_LIVECONNECT
+ SHIP_BINS += lcshell
+endif
+ifeq ($(OS_ARCH), WINNT)
+ SHIP_BINS := $(addsuffix .exe, $(SHIP_BINS))
+endif
+SHIP_BINS := $(addprefix $(SHIP_DIST)/bin/, $(SHIP_BINS))
+
+ifdef BUILD_OPT
+ JSREFJAR = jsref_opt.jar
+else
+ifdef BUILD_IDG
+ JSREFJAR = jsref_idg.jar
+else
+ JSREFJAR = jsref_dbg.jar
+endif
+endif
+
+ship:
+ mkdir -p $(SHIP_DIR)/$(LIBDIR)
+ mkdir -p $(SHIP_DIR)/include
+ mkdir -p $(SHIP_DIR)/bin
+ cp $(SHIP_LIBS) $(SHIP_DIR)/$(LIBDIR)
+ cp $(SHIP_INCS) $(SHIP_DIR)/include
+ cp $(SHIP_BINS) $(SHIP_DIR)/bin
+ cd $(SHIP_DIR); \
+ zip -r $(JSREFJAR) bin lib include
+ifdef BUILD_SHIP
+ cp $(SHIP_DIR)/$(JSREFJAR) $(BUILD_SHIP)
+endif
+
+CWD = $(shell pwd)
+shipSource: $(SHIP_DIR)/jsref_src.lst .FORCE
+ mkdir -p $(SHIP_DIR)
+ cd $(MOZ_DEPTH)/.. ; \
+ zip $(CWD)/$(SHIP_DIR)/jsref_src.jar -@ < $(CWD)/$(SHIP_DIR)/jsref_src.lst
+ifdef BUILD_SHIP
+ cp $(SHIP_DIR)/jsref_src.jar $(BUILD_SHIP)
+endif
+
+JSREFSRCDIRS := $(shell cat $(DEPTH)/SpiderMonkey.rsp)
+$(SHIP_DIR)/jsref_src.lst: .FORCE
+ mkdir -p $(SHIP_DIR)
+ rm -f $@
+ touch $@
+ for d in $(JSREFSRCDIRS); do \
+ cd $(MOZ_DEPTH)/..; \
+ ls -1 -d $$d | grep -v CVS | grep -v \.OBJ >> $(CWD)/$@; \
+ cd $(CWD); \
+ done
+
+.FORCE:
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.cpp
new file mode 100644
index 0000000..c41a47e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.cpp
@@ -0,0 +1,388 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Generate CPU-specific bit-size and similar #defines.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef CROSS_COMPILE
+#include <prtypes.h>
+#define INT64 PRInt64
+#else
+
+/************************************************************************/
+
+/* Generate cpucfg.h */
+
+#if defined(XP_WIN) || defined(XP_OS2)
+#ifdef WIN32
+#if defined(__GNUC__)
+#define INT64 long long
+#else
+#define INT64 _int64
+#endif /* __GNUC__ */
+#else
+#define INT64 long
+#endif
+#else
+#if defined(HPUX) || defined(__QNX__)
+#define INT64 long
+#else
+#define INT64 long long
+#endif
+#endif
+
+#endif /* CROSS_COMPILE */
+
+#ifdef __GNUC__
+#define NS_NEVER_INLINE __attribute__((noinline))
+#else
+#define NS_NEVER_INLINE
+#endif
+
+#ifdef __SUNPRO_C
+static int StackGrowthDirection(int *dummy1addr);
+#pragma no_inline(StackGrowthDirection)
+#endif
+
+typedef void *prword;
+
+struct align_short {
+ char c;
+ short a;
+};
+struct align_int {
+ char c;
+ int a;
+};
+struct align_long {
+ char c;
+ long a;
+};
+struct align_int64 {
+ char c;
+ INT64 a;
+};
+struct align_fakelonglong {
+ char c;
+ struct {
+ long hi, lo;
+ } a;
+};
+struct align_float {
+ char c;
+ float a;
+};
+struct align_double {
+ char c;
+ double a;
+};
+struct align_pointer {
+ char c;
+ void *a;
+};
+struct align_prword {
+ char c;
+ prword a;
+};
+
+#define ALIGN_OF(type) \
+ (((char*)&(((struct align_##type *)0)->a)) - ((char*)0))
+
+unsigned int bpb;
+
+static int Log2(unsigned int n)
+{
+ int log2 = 0;
+
+ if (n & (n-1))
+ log2++;
+ if (n >> 16)
+ log2 += 16, n >>= 16;
+ if (n >> 8)
+ log2 += 8, n >>= 8;
+ if (n >> 4)
+ log2 += 4, n >>= 4;
+ if (n >> 2)
+ log2 += 2, n >>= 2;
+ if (n >> 1)
+ log2++;
+ return log2;
+}
+
+/*
+ * Conceivably this could actually be used, but there is lots of code out
+ * there with ands and shifts in it that assumes a byte is exactly 8 bits,
+ * so forget about porting THIS code to all those non 8 bit byte machines.
+ */
+static void BitsPerByte(void)
+{
+ bpb = 8;
+}
+
+static int NS_NEVER_INLINE StackGrowthDirection(int *dummy1addr)
+{
+ int dummy2;
+
+ return (&dummy2 < dummy1addr) ? -1 : 1;
+}
+
+int main(int argc, char **argv)
+{
+ int sizeof_char, sizeof_short, sizeof_int, sizeof_int64, sizeof_long,
+ sizeof_float, sizeof_double, sizeof_word, sizeof_dword;
+ int bits_per_int64_log2, align_of_short, align_of_int, align_of_long,
+ align_of_int64, align_of_float, align_of_double, align_of_pointer,
+ align_of_word;
+ int dummy1;
+
+ BitsPerByte();
+
+ printf("#ifndef js_cpucfg___\n");
+ printf("#define js_cpucfg___\n\n");
+
+ printf("/* AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n");
+
+#ifdef CROSS_COMPILE
+#if defined(IS_LITTLE_ENDIAN)
+ printf("#define IS_LITTLE_ENDIAN 1\n");
+ printf("#undef IS_BIG_ENDIAN\n\n");
+#elif defined(IS_BIG_ENDIAN)
+ printf("#undef IS_LITTLE_ENDIAN\n");
+ printf("#define IS_BIG_ENDIAN 1\n\n");
+#else
+#error "Endianess not defined."
+#endif
+
+ sizeof_char = PR_BYTES_PER_BYTE;
+ sizeof_short = PR_BYTES_PER_SHORT;
+ sizeof_int = PR_BYTES_PER_INT;
+ sizeof_int64 = PR_BYTES_PER_INT64;
+ sizeof_long = PR_BYTES_PER_LONG;
+ sizeof_float = PR_BYTES_PER_FLOAT;
+ sizeof_double = PR_BYTES_PER_DOUBLE;
+ sizeof_word = PR_BYTES_PER_WORD;
+ sizeof_dword = PR_BYTES_PER_DWORD;
+
+ bits_per_int64_log2 = PR_BITS_PER_INT64_LOG2;
+
+ align_of_short = PR_ALIGN_OF_SHORT;
+ align_of_int = PR_ALIGN_OF_INT;
+ align_of_long = PR_ALIGN_OF_LONG;
+ align_of_int64 = PR_ALIGN_OF_INT64;
+ align_of_float = PR_ALIGN_OF_FLOAT;
+ align_of_double = PR_ALIGN_OF_DOUBLE;
+ align_of_pointer = PR_ALIGN_OF_POINTER;
+ align_of_word = PR_ALIGN_OF_WORD;
+
+#else /* !CROSS_COMPILE */
+
+ /*
+ * We don't handle PDP-endian or similar orders: if a short is big-endian,
+ * so must int and long be big-endian for us to generate the IS_BIG_ENDIAN
+ * #define and the IS_LITTLE_ENDIAN #undef.
+ */
+ {
+ int big_endian = 0, little_endian = 0, ntests = 0;
+
+ if (sizeof(short) == 2) {
+ /* force |volatile| here to get rid of any compiler optimisations
+ * (var in register etc.) which may be appiled to |auto| vars -
+ * even those in |union|s...
+ * (|static| is used to get the same functionality for compilers
+ * which do not honor |volatile|...).
+ */
+ volatile static union {
+ short i;
+ char c[2];
+ } u;
+
+ u.i = 0x0102;
+ big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02);
+ little_endian += (u.c[0] == 0x02 && u.c[1] == 0x01);
+ ntests++;
+ }
+
+ if (sizeof(int) == 4) {
+ /* force |volatile| here ... */
+ volatile static union {
+ int i;
+ char c[4];
+ } u;
+
+ u.i = 0x01020304;
+ big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02 &&
+ u.c[2] == 0x03 && u.c[3] == 0x04);
+ little_endian += (u.c[0] == 0x04 && u.c[1] == 0x03 &&
+ u.c[2] == 0x02 && u.c[3] == 0x01);
+ ntests++;
+ }
+
+ if (sizeof(long) == 8) {
+ /* force |volatile| here ... */
+ volatile static union {
+ long i;
+ char c[8];
+ } u;
+
+ /*
+ * Write this as portably as possible: avoid 0x0102030405060708L
+ * and <<= 32.
+ */
+ u.i = 0x01020304;
+ u.i <<= 16, u.i <<= 16;
+ u.i |= 0x05060708;
+ big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02 &&
+ u.c[2] == 0x03 && u.c[3] == 0x04 &&
+ u.c[4] == 0x05 && u.c[5] == 0x06 &&
+ u.c[6] == 0x07 && u.c[7] == 0x08);
+ little_endian += (u.c[0] == 0x08 && u.c[1] == 0x07 &&
+ u.c[2] == 0x06 && u.c[3] == 0x05 &&
+ u.c[4] == 0x04 && u.c[5] == 0x03 &&
+ u.c[6] == 0x02 && u.c[7] == 0x01);
+ ntests++;
+ }
+
+ if (big_endian && big_endian == ntests) {
+ printf("#undef IS_LITTLE_ENDIAN\n");
+ printf("#define IS_BIG_ENDIAN 1\n\n");
+ } else if (little_endian && little_endian == ntests) {
+ printf("#define IS_LITTLE_ENDIAN 1\n");
+ printf("#undef IS_BIG_ENDIAN\n\n");
+ } else {
+ fprintf(stderr, "%s: unknown byte order"
+ "(big_endian=%d, little_endian=%d, ntests=%d)!\n",
+ argv[0], big_endian, little_endian, ntests);
+ return EXIT_FAILURE;
+ }
+ }
+
+ sizeof_char = sizeof(char);
+ sizeof_short = sizeof(short);
+ sizeof_int = sizeof(int);
+ sizeof_int64 = 8;
+ sizeof_long = sizeof(long);
+ sizeof_float = sizeof(float);
+ sizeof_double = sizeof(double);
+ sizeof_word = sizeof(prword);
+ sizeof_dword = 8;
+
+ bits_per_int64_log2 = 6;
+
+ align_of_short = ALIGN_OF(short);
+ align_of_int = ALIGN_OF(int);
+ align_of_long = ALIGN_OF(long);
+ if (sizeof(INT64) < 8) {
+ /* this machine doesn't actually support int64's */
+ align_of_int64 = ALIGN_OF(fakelonglong);
+ } else {
+ align_of_int64 = ALIGN_OF(int64);
+ }
+ align_of_float = ALIGN_OF(float);
+ align_of_double = ALIGN_OF(double);
+ align_of_pointer = ALIGN_OF(pointer);
+ align_of_word = ALIGN_OF(prword);
+
+#endif /* CROSS_COMPILE */
+
+ printf("#define JS_BYTES_PER_BYTE %dL\n", sizeof_char);
+ printf("#define JS_BYTES_PER_SHORT %dL\n", sizeof_short);
+ printf("#define JS_BYTES_PER_INT %dL\n", sizeof_int);
+ printf("#define JS_BYTES_PER_INT64 %dL\n", sizeof_int64);
+ printf("#define JS_BYTES_PER_LONG %dL\n", sizeof_long);
+ printf("#define JS_BYTES_PER_FLOAT %dL\n", sizeof_float);
+ printf("#define JS_BYTES_PER_DOUBLE %dL\n", sizeof_double);
+ printf("#define JS_BYTES_PER_WORD %dL\n", sizeof_word);
+ printf("#define JS_BYTES_PER_DWORD %dL\n", sizeof_dword);
+ printf("\n");
+
+ printf("#define JS_BITS_PER_BYTE %dL\n", bpb);
+ printf("#define JS_BITS_PER_SHORT %dL\n", bpb * sizeof_short);
+ printf("#define JS_BITS_PER_INT %dL\n", bpb * sizeof_int);
+ printf("#define JS_BITS_PER_INT64 %dL\n", bpb * sizeof_int64);
+ printf("#define JS_BITS_PER_LONG %dL\n", bpb * sizeof_long);
+ printf("#define JS_BITS_PER_FLOAT %dL\n", bpb * sizeof_float);
+ printf("#define JS_BITS_PER_DOUBLE %dL\n", bpb * sizeof_double);
+ printf("#define JS_BITS_PER_WORD %dL\n", bpb * sizeof_word);
+ printf("\n");
+
+ printf("#define JS_BITS_PER_BYTE_LOG2 %dL\n", Log2(bpb));
+ printf("#define JS_BITS_PER_SHORT_LOG2 %dL\n", Log2(bpb * sizeof_short));
+ printf("#define JS_BITS_PER_INT_LOG2 %dL\n", Log2(bpb * sizeof_int));
+ printf("#define JS_BITS_PER_INT64_LOG2 %dL\n", bits_per_int64_log2);
+ printf("#define JS_BITS_PER_LONG_LOG2 %dL\n", Log2(bpb * sizeof_long));
+ printf("#define JS_BITS_PER_FLOAT_LOG2 %dL\n", Log2(bpb * sizeof_float));
+ printf("#define JS_BITS_PER_DOUBLE_LOG2 %dL\n", Log2(bpb * sizeof_double));
+ printf("#define JS_BITS_PER_WORD_LOG2 %dL\n", Log2(bpb * sizeof_word));
+ printf("\n");
+
+ printf("#define JS_ALIGN_OF_SHORT %dL\n", align_of_short);
+ printf("#define JS_ALIGN_OF_INT %dL\n", align_of_int);
+ printf("#define JS_ALIGN_OF_LONG %dL\n", align_of_long);
+ printf("#define JS_ALIGN_OF_INT64 %dL\n", align_of_int64);
+ printf("#define JS_ALIGN_OF_FLOAT %dL\n", align_of_float);
+ printf("#define JS_ALIGN_OF_DOUBLE %dL\n", align_of_double);
+ printf("#define JS_ALIGN_OF_POINTER %dL\n", align_of_pointer);
+ printf("#define JS_ALIGN_OF_WORD %dL\n", align_of_word);
+ printf("\n");
+
+ printf("#define JS_BYTES_PER_WORD_LOG2 %dL\n", Log2(sizeof_word));
+ printf("#define JS_BYTES_PER_DWORD_LOG2 %dL\n", Log2(sizeof_dword));
+ printf("#define JS_WORDS_PER_DWORD_LOG2 %dL\n", Log2(sizeof_dword/sizeof_word));
+ printf("\n");
+
+ printf("#define JS_STACK_GROWTH_DIRECTION (%d)\n", StackGrowthDirection(&dummy1));
+ printf("\n");
+
+ printf("#define JS_HAVE_LONG_LONG\n");
+ printf("\n");
+
+#if defined __GNUC__ && defined __x86_64__
+ printf("#define HAVE_VA_LIST_AS_ARRAY 1\n");
+ printf("\n");
+#endif
+
+ printf("#endif /* js_cpucfg___ */\n");
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.h b/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.h
new file mode 100644
index 0000000..c745e81
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.h
@@ -0,0 +1,212 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef js_cpucfg___
+#define js_cpucfg___
+
+#define JS_HAVE_LONG_LONG
+
+#if defined(XP_WIN) || defined(XP_OS2) || defined(WINCE)
+
+#if defined(_WIN64)
+
+#if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define JS_BYTES_PER_BYTE 1L
+#define JS_BYTES_PER_SHORT 2L
+#define JS_BYTES_PER_INT 4L
+#define JS_BYTES_PER_INT64 8L
+#define JS_BYTES_PER_LONG 4L
+#define JS_BYTES_PER_FLOAT 4L
+#define JS_BYTES_PER_DOUBLE 8L
+#define JS_BYTES_PER_WORD 8L
+#define JS_BYTES_PER_DWORD 8L
+
+#define JS_BITS_PER_BYTE 8L
+#define JS_BITS_PER_SHORT 16L
+#define JS_BITS_PER_INT 32L
+#define JS_BITS_PER_INT64 64L
+#define JS_BITS_PER_LONG 32L
+#define JS_BITS_PER_FLOAT 32L
+#define JS_BITS_PER_DOUBLE 64L
+#define JS_BITS_PER_WORD 64L
+
+#define JS_BITS_PER_BYTE_LOG2 3L
+#define JS_BITS_PER_SHORT_LOG2 4L
+#define JS_BITS_PER_INT_LOG2 5L
+#define JS_BITS_PER_INT64_LOG2 6L
+#define JS_BITS_PER_LONG_LOG2 5L
+#define JS_BITS_PER_FLOAT_LOG2 5L
+#define JS_BITS_PER_DOUBLE_LOG2 6L
+#define JS_BITS_PER_WORD_LOG2 6L
+
+#define JS_ALIGN_OF_SHORT 2L
+#define JS_ALIGN_OF_INT 4L
+#define JS_ALIGN_OF_LONG 4L
+#define JS_ALIGN_OF_INT64 8L
+#define JS_ALIGN_OF_FLOAT 4L
+#define JS_ALIGN_OF_DOUBLE 8L
+#define JS_ALIGN_OF_POINTER 8L
+#define JS_ALIGN_OF_WORD 8L
+
+#define JS_BYTES_PER_WORD_LOG2 3L
+#define JS_BYTES_PER_DWORD_LOG2 3L
+#define PR_WORDS_PER_DWORD_LOG2 0L
+#else /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
+#error "CPU type is unknown"
+#endif /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
+
+#elif defined(_WIN32) || defined(XP_OS2) || defined(WINCE)
+
+#ifdef __WATCOMC__
+#define HAVE_VA_LIST_AS_ARRAY 1
+#endif
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define JS_BYTES_PER_BYTE 1L
+#define JS_BYTES_PER_SHORT 2L
+#define JS_BYTES_PER_INT 4L
+#define JS_BYTES_PER_INT64 8L
+#define JS_BYTES_PER_LONG 4L
+#define JS_BYTES_PER_FLOAT 4L
+#define JS_BYTES_PER_DOUBLE 8L
+#define JS_BYTES_PER_WORD 4L
+#define JS_BYTES_PER_DWORD 8L
+
+#define JS_BITS_PER_BYTE 8L
+#define JS_BITS_PER_SHORT 16L
+#define JS_BITS_PER_INT 32L
+#define JS_BITS_PER_INT64 64L
+#define JS_BITS_PER_LONG 32L
+#define JS_BITS_PER_FLOAT 32L
+#define JS_BITS_PER_DOUBLE 64L
+#define JS_BITS_PER_WORD 32L
+
+#define JS_BITS_PER_BYTE_LOG2 3L
+#define JS_BITS_PER_SHORT_LOG2 4L
+#define JS_BITS_PER_INT_LOG2 5L
+#define JS_BITS_PER_INT64_LOG2 6L
+#define JS_BITS_PER_LONG_LOG2 5L
+#define JS_BITS_PER_FLOAT_LOG2 5L
+#define JS_BITS_PER_DOUBLE_LOG2 6L
+#define JS_BITS_PER_WORD_LOG2 5L
+
+#define JS_ALIGN_OF_SHORT 2L
+#define JS_ALIGN_OF_INT 4L
+#define JS_ALIGN_OF_LONG 4L
+#define JS_ALIGN_OF_INT64 8L
+#define JS_ALIGN_OF_FLOAT 4L
+#define JS_ALIGN_OF_DOUBLE 4L
+#define JS_ALIGN_OF_POINTER 4L
+#define JS_ALIGN_OF_WORD 4L
+
+#define JS_BYTES_PER_WORD_LOG2 2L
+#define JS_BYTES_PER_DWORD_LOG2 3L
+#define PR_WORDS_PER_DWORD_LOG2 1L
+#endif /* _WIN32 || XP_OS2 || WINCE*/
+
+#if defined(_WINDOWS) && !defined(_WIN32) /* WIN16 */
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define JS_BYTES_PER_BYTE 1L
+#define JS_BYTES_PER_SHORT 2L
+#define JS_BYTES_PER_INT 2L
+#define JS_BYTES_PER_INT64 8L
+#define JS_BYTES_PER_LONG 4L
+#define JS_BYTES_PER_FLOAT 4L
+#define JS_BYTES_PER_DOUBLE 8L
+#define JS_BYTES_PER_WORD 4L
+#define JS_BYTES_PER_DWORD 8L
+
+#define JS_BITS_PER_BYTE 8L
+#define JS_BITS_PER_SHORT 16L
+#define JS_BITS_PER_INT 16L
+#define JS_BITS_PER_INT64 64L
+#define JS_BITS_PER_LONG 32L
+#define JS_BITS_PER_FLOAT 32L
+#define JS_BITS_PER_DOUBLE 64L
+#define JS_BITS_PER_WORD 32L
+
+#define JS_BITS_PER_BYTE_LOG2 3L
+#define JS_BITS_PER_SHORT_LOG2 4L
+#define JS_BITS_PER_INT_LOG2 4L
+#define JS_BITS_PER_INT64_LOG2 6L
+#define JS_BITS_PER_LONG_LOG2 5L
+#define JS_BITS_PER_FLOAT_LOG2 5L
+#define JS_BITS_PER_DOUBLE_LOG2 6L
+#define JS_BITS_PER_WORD_LOG2 5L
+
+#define JS_ALIGN_OF_SHORT 2L
+#define JS_ALIGN_OF_INT 2L
+#define JS_ALIGN_OF_LONG 2L
+#define JS_ALIGN_OF_INT64 2L
+#define JS_ALIGN_OF_FLOAT 2L
+#define JS_ALIGN_OF_DOUBLE 2L
+#define JS_ALIGN_OF_POINTER 2L
+#define JS_ALIGN_OF_WORD 2L
+
+#define JS_BYTES_PER_WORD_LOG2 2L
+#define JS_BYTES_PER_DWORD_LOG2 3L
+#define PR_WORDS_PER_DWORD_LOG2 1L
+
+#endif /* defined(_WINDOWS) && !defined(_WIN32) */
+
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+
+#error "This file is supposed to be auto-generated on UNIX platforms, but the"
+#error "static version for Mac and Windows platforms is being used."
+#error "Something's probably wrong with paths/headers/dependencies/Makefiles."
+
+#else
+
+#error "Must define one of XP_BEOS, XP_OS2, XP_WIN, or XP_UNIX"
+
+#endif
+
+#ifndef JS_STACK_GROWTH_DIRECTION
+#define JS_STACK_GROWTH_DIRECTION (-1)
+#endif
+
+#endif /* js_cpucfg___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdate.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsdate.cpp
new file mode 100644
index 0000000..2fe7963
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdate.cpp
@@ -0,0 +1,2475 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS date methods.
+ */
+
+/*
+ * "For example, OS/360 devotes 26 bytes of the permanently
+ * resident date-turnover routine to the proper handling of
+ * December 31 on leap years (when it is Day 366). That
+ * might have been left to the operator."
+ *
+ * Frederick Brooks, 'The Second-System Effect'.
+ */
+
+#include "jsstddef.h"
+#include <ctype.h>
+#include <locale.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsprf.h"
+#include "prmjtime.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsversion.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsdate.h"
+#include "jsinterp.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsstr.h"
+
+/*
+ * The JS 'Date' object is patterned after the Java 'Date' object.
+ * Here is an script:
+ *
+ * today = new Date();
+ *
+ * print(today.toLocaleString());
+ *
+ * weekDay = today.getDay();
+ *
+ *
+ * These Java (and ECMA-262) methods are supported:
+ *
+ * UTC
+ * getDate (getUTCDate)
+ * getDay (getUTCDay)
+ * getHours (getUTCHours)
+ * getMinutes (getUTCMinutes)
+ * getMonth (getUTCMonth)
+ * getSeconds (getUTCSeconds)
+ * getMilliseconds (getUTCMilliseconds)
+ * getTime
+ * getTimezoneOffset
+ * getYear
+ * getFullYear (getUTCFullYear)
+ * parse
+ * setDate (setUTCDate)
+ * setHours (setUTCHours)
+ * setMinutes (setUTCMinutes)
+ * setMonth (setUTCMonth)
+ * setSeconds (setUTCSeconds)
+ * setMilliseconds (setUTCMilliseconds)
+ * setTime
+ * setYear (setFullYear, setUTCFullYear)
+ * toGMTString (toUTCString)
+ * toLocaleString
+ * toString
+ *
+ *
+ * These Java methods are not supported
+ *
+ * setDay
+ * before
+ * after
+ * equals
+ * hashCode
+ */
+
+/*
+ * 11/97 - jsdate.c has been rewritten to conform to the ECMA-262 language
+ * definition and reduce dependence on NSPR. NSPR is used to get the current
+ * time in milliseconds, the time zone offset, and the daylight savings time
+ * offset for a given time. NSPR is also used for Date.toLocaleString(), for
+ * locale-specific formatting, and to get a string representing the timezone.
+ * (Which turns out to be platform-dependent.)
+ *
+ * To do:
+ * (I did some performance tests by timing how long it took to run what
+ * I had of the js ECMA conformance tests.)
+ *
+ * - look at saving results across multiple calls to supporting
+ * functions; the toString functions compute some of the same values
+ * multiple times. Although - I took a quick stab at this, and I lost
+ * rather than gained. (Fractionally.) Hard to tell what compilers/processors
+ * are doing these days.
+ *
+ * - look at tweaking function return types to return double instead
+ * of int; this seems to make things run slightly faster sometimes.
+ * (though it could be architecture-dependent.) It'd be good to see
+ * how this does on win32. (Tried it on irix.) Types could use a
+ * general going-over.
+ */
+
+/*
+ * Supporting functions - ECMA 15.9.1.*
+ */
+
+#define HalfTimeDomain 8.64e15
+#define HoursPerDay 24.0
+#define MinutesPerDay (HoursPerDay * MinutesPerHour)
+#define MinutesPerHour 60.0
+#define SecondsPerDay (MinutesPerDay * SecondsPerMinute)
+#define SecondsPerHour (MinutesPerHour * SecondsPerMinute)
+#define SecondsPerMinute 60.0
+
+#if defined(XP_WIN) || defined(XP_OS2)
+/* Work around msvc double optimization bug by making these runtime values; if
+ * they're available at compile time, msvc optimizes division by them by
+ * computing the reciprocal and multiplying instead of dividing - this loses
+ * when the reciprocal isn't representable in a double.
+ */
+static jsdouble msPerSecond = 1000.0;
+static jsdouble msPerDay = SecondsPerDay * 1000.0;
+static jsdouble msPerHour = SecondsPerHour * 1000.0;
+static jsdouble msPerMinute = SecondsPerMinute * 1000.0;
+#else
+#define msPerDay (SecondsPerDay * msPerSecond)
+#define msPerHour (SecondsPerHour * msPerSecond)
+#define msPerMinute (SecondsPerMinute * msPerSecond)
+#define msPerSecond 1000.0
+#endif
+
+#define Day(t) floor((t) / msPerDay)
+
+static jsdouble
+TimeWithinDay(jsdouble t)
+{
+ jsdouble result;
+ result = fmod(t, msPerDay);
+ if (result < 0)
+ result += msPerDay;
+ return result;
+}
+
+#define DaysInYear(y) ((y) % 4 == 0 && ((y) % 100 || ((y) % 400 == 0)) \
+ ? 366 : 365)
+
+/* math here has to be f.p, because we need
+ * floor((1968 - 1969) / 4) == -1
+ */
+#define DayFromYear(y) (365 * ((y)-1970) + floor(((y)-1969)/4.0) \
+ - floor(((y)-1901)/100.0) + floor(((y)-1601)/400.0))
+#define TimeFromYear(y) (DayFromYear(y) * msPerDay)
+
+static jsint
+YearFromTime(jsdouble t)
+{
+ jsint y = (jsint) floor(t /(msPerDay*365.2425)) + 1970;
+ jsdouble t2 = (jsdouble) TimeFromYear(y);
+
+ if (t2 > t) {
+ y--;
+ } else {
+ if (t2 + msPerDay * DaysInYear(y) <= t)
+ y++;
+ }
+ return y;
+}
+
+#define InLeapYear(t) (JSBool) (DaysInYear(YearFromTime(t)) == 366)
+
+#define DayWithinYear(t, year) ((intN) (Day(t) - DayFromYear(year)))
+
+/*
+ * The following array contains the day of year for the first day of
+ * each month, where index 0 is January, and day 0 is January 1.
+ */
+static jsdouble firstDayOfMonth[2][12] = {
+ {0.0, 31.0, 59.0, 90.0, 120.0, 151.0, 181.0, 212.0, 243.0, 273.0, 304.0, 334.0},
+ {0.0, 31.0, 60.0, 91.0, 121.0, 152.0, 182.0, 213.0, 244.0, 274.0, 305.0, 335.0}
+};
+
+#define DayFromMonth(m, leap) firstDayOfMonth[leap][(intN)m];
+
+static intN
+MonthFromTime(jsdouble t)
+{
+ intN d, step;
+ jsint year = YearFromTime(t);
+ d = DayWithinYear(t, year);
+
+ if (d < (step = 31))
+ return 0;
+ step += (InLeapYear(t) ? 29 : 28);
+ if (d < step)
+ return 1;
+ if (d < (step += 31))
+ return 2;
+ if (d < (step += 30))
+ return 3;
+ if (d < (step += 31))
+ return 4;
+ if (d < (step += 30))
+ return 5;
+ if (d < (step += 31))
+ return 6;
+ if (d < (step += 31))
+ return 7;
+ if (d < (step += 30))
+ return 8;
+ if (d < (step += 31))
+ return 9;
+ if (d < (step += 30))
+ return 10;
+ return 11;
+}
+
+static intN
+DateFromTime(jsdouble t)
+{
+ intN d, step, next;
+ jsint year = YearFromTime(t);
+ d = DayWithinYear(t, year);
+
+ if (d <= (next = 30))
+ return d + 1;
+ step = next;
+ next += (InLeapYear(t) ? 29 : 28);
+ if (d <= next)
+ return d - step;
+ step = next;
+ if (d <= (next += 31))
+ return d - step;
+ step = next;
+ if (d <= (next += 30))
+ return d - step;
+ step = next;
+ if (d <= (next += 31))
+ return d - step;
+ step = next;
+ if (d <= (next += 30))
+ return d - step;
+ step = next;
+ if (d <= (next += 31))
+ return d - step;
+ step = next;
+ if (d <= (next += 31))
+ return d - step;
+ step = next;
+ if (d <= (next += 30))
+ return d - step;
+ step = next;
+ if (d <= (next += 31))
+ return d - step;
+ step = next;
+ if (d <= (next += 30))
+ return d - step;
+ step = next;
+ return d - step;
+}
+
+static intN
+WeekDay(jsdouble t)
+{
+ jsint result;
+ result = (jsint) Day(t) + 4;
+ result = result % 7;
+ if (result < 0)
+ result += 7;
+ return (intN) result;
+}
+
+#define MakeTime(hour, min, sec, ms) \
+((((hour) * MinutesPerHour + (min)) * SecondsPerMinute + (sec)) * msPerSecond + (ms))
+
+static jsdouble
+MakeDay(jsdouble year, jsdouble month, jsdouble date)
+{
+ JSBool leap;
+ jsdouble yearday;
+ jsdouble monthday;
+
+ year += floor(month / 12);
+
+ month = fmod(month, 12.0);
+ if (month < 0)
+ month += 12;
+
+ leap = (DaysInYear((jsint) year) == 366);
+
+ yearday = floor(TimeFromYear(year) / msPerDay);
+ monthday = DayFromMonth(month, leap);
+
+ return yearday + monthday + date - 1;
+}
+
+#define MakeDate(day, time) ((day) * msPerDay + (time))
+
+/*
+ * Years and leap years on which Jan 1 is a Sunday, Monday, etc.
+ *
+ * yearStartingWith[0][i] is an example non-leap year where
+ * Jan 1 appears on Sunday (i == 0), Monday (i == 1), etc.
+ *
+ * yearStartingWith[1][i] is an example leap year where
+ * Jan 1 appears on Sunday (i == 0), Monday (i == 1), etc.
+ */
+static jsint yearStartingWith[2][7] = {
+ {1978, 1973, 1974, 1975, 1981, 1971, 1977},
+ {1984, 1996, 1980, 1992, 1976, 1988, 1972}
+};
+
+/*
+ * Find a year for which any given date will fall on the same weekday.
+ *
+ * This function should be used with caution when used other than
+ * for determining DST; it hasn't been proven not to produce an
+ * incorrect year for times near year boundaries.
+ */
+static jsint
+EquivalentYearForDST(jsint year)
+{
+ jsint day;
+ JSBool isLeapYear;
+
+ day = (jsint) DayFromYear(year) + 4;
+ day = day % 7;
+ if (day < 0)
+ day += 7;
+
+ isLeapYear = (DaysInYear(year) == 366);
+
+ return yearStartingWith[isLeapYear][day];
+}
+
+/* LocalTZA gets set by js_InitDateClass() */
+static jsdouble LocalTZA;
+
+static jsdouble
+DaylightSavingTA(jsdouble t)
+{
+ volatile int64 PR_t;
+ int64 ms2us;
+ int64 offset;
+ jsdouble result;
+
+ /* abort if NaN */
+ if (JSDOUBLE_IS_NaN(t))
+ return t;
+
+ /*
+ * If earlier than 1970 or after 2038, potentially beyond the ken of
+ * many OSes, map it to an equivalent year before asking.
+ */
+ if (t < 0.0 || t > 2145916800000.0) {
+ jsint year;
+ jsdouble day;
+
+ year = EquivalentYearForDST(YearFromTime(t));
+ day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
+ t = MakeDate(day, TimeWithinDay(t));
+ }
+
+ /* put our t in an LL, and map it to usec for prtime */
+ JSLL_D2L(PR_t, t);
+ JSLL_I2L(ms2us, PRMJ_USEC_PER_MSEC);
+ JSLL_MUL(PR_t, PR_t, ms2us);
+
+ offset = PRMJ_DSTOffset(PR_t);
+
+ JSLL_DIV(offset, offset, ms2us);
+ JSLL_L2D(result, offset);
+ return result;
+}
+
+
+#define AdjustTime(t) fmod(LocalTZA + DaylightSavingTA(t), msPerDay)
+
+#define LocalTime(t) ((t) + AdjustTime(t))
+
+static jsdouble
+UTC(jsdouble t)
+{
+ return t - AdjustTime(t - LocalTZA);
+}
+
+static intN
+HourFromTime(jsdouble t)
+{
+ intN result = (intN) fmod(floor(t/msPerHour), HoursPerDay);
+ if (result < 0)
+ result += (intN)HoursPerDay;
+ return result;
+}
+
+static intN
+MinFromTime(jsdouble t)
+{
+ intN result = (intN) fmod(floor(t / msPerMinute), MinutesPerHour);
+ if (result < 0)
+ result += (intN)MinutesPerHour;
+ return result;
+}
+
+static intN
+SecFromTime(jsdouble t)
+{
+ intN result = (intN) fmod(floor(t / msPerSecond), SecondsPerMinute);
+ if (result < 0)
+ result += (intN)SecondsPerMinute;
+ return result;
+}
+
+static intN
+msFromTime(jsdouble t)
+{
+ intN result = (intN) fmod(t, msPerSecond);
+ if (result < 0)
+ result += (intN)msPerSecond;
+ return result;
+}
+
+#define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \
+ && !((d < 0 ? -d : d) > HalfTimeDomain)) \
+ ? js_DoubleToInteger(d + (+0.)) : *cx->runtime->jsNaN)
+
+/**
+ * end of ECMA 'support' functions
+ */
+
+/*
+ * Other Support routines and definitions
+ */
+
+/*
+ * We use the first reseved slot to store UTC time, and the second for caching
+ * the local time. The initial value of the cache entry is NaN.
+ */
+const uint32 JSSLOT_UTC_TIME = JSSLOT_PRIVATE;
+const uint32 JSSLOT_LOCAL_TIME = JSSLOT_PRIVATE + 1;
+
+const uint32 DATE_RESERVED_SLOTS = 2;
+
+JSClass js_DateClass = {
+ js_Date_str,
+ JSCLASS_HAS_RESERVED_SLOTS(DATE_RESERVED_SLOTS) |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+/* for use by date_parse */
+
+static const char* wtb[] = {
+ "am", "pm",
+ "monday", "tuesday", "wednesday", "thursday", "friday",
+ "saturday", "sunday",
+ "january", "february", "march", "april", "may", "june",
+ "july", "august", "september", "october", "november", "december",
+ "gmt", "ut", "utc",
+ "est", "edt",
+ "cst", "cdt",
+ "mst", "mdt",
+ "pst", "pdt"
+ /* time zone table needs to be expanded */
+};
+
+static int ttb[] = {
+ -1, -2, 0, 0, 0, 0, 0, 0, 0, /* AM/PM */
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 10000 + 0, 10000 + 0, 10000 + 0, /* GMT/UT/UTC */
+ 10000 + 5 * 60, 10000 + 4 * 60, /* EST/EDT */
+ 10000 + 6 * 60, 10000 + 5 * 60, /* CST/CDT */
+ 10000 + 7 * 60, 10000 + 6 * 60, /* MST/MDT */
+ 10000 + 8 * 60, 10000 + 7 * 60 /* PST/PDT */
+};
+
+/* helper for date_parse */
+static JSBool
+date_regionMatches(const char* s1, int s1off, const jschar* s2, int s2off,
+ int count, int ignoreCase)
+{
+ JSBool result = JS_FALSE;
+ /* return true if matches, otherwise, false */
+
+ while (count > 0 && s1[s1off] && s2[s2off]) {
+ if (ignoreCase) {
+ if (JS_TOLOWER((jschar)s1[s1off]) != JS_TOLOWER(s2[s2off])) {
+ break;
+ }
+ } else {
+ if ((jschar)s1[s1off] != s2[s2off]) {
+ break;
+ }
+ }
+ s1off++;
+ s2off++;
+ count--;
+ }
+
+ if (count == 0) {
+ result = JS_TRUE;
+ }
+
+ return result;
+}
+
+/* find UTC time from given date... no 1900 correction! */
+static jsdouble
+date_msecFromDate(jsdouble year, jsdouble mon, jsdouble mday, jsdouble hour,
+ jsdouble min, jsdouble sec, jsdouble msec)
+{
+ jsdouble day;
+ jsdouble msec_time;
+ jsdouble result;
+
+ day = MakeDay(year, mon, mday);
+ msec_time = MakeTime(hour, min, sec, msec);
+ result = MakeDate(day, msec_time);
+ return result;
+}
+
+/* compute the time in msec (unclipped) from the given args */
+#define MAXARGS 7
+
+static JSBool
+date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval)
+{
+ uintN loop;
+ jsdouble array[MAXARGS];
+ jsdouble d;
+ jsdouble msec_time;
+
+ for (loop = 0; loop < MAXARGS; loop++) {
+ if (loop < argc) {
+ d = js_ValueToNumber(cx, &argv[loop]);
+ if (JSVAL_IS_NULL(argv[loop]))
+ return JS_FALSE;
+ /* return NaN if any arg is not finite */
+ if (!JSDOUBLE_IS_FINITE(d)) {
+ *rval = *cx->runtime->jsNaN;
+ return JS_TRUE;
+ }
+ array[loop] = js_DoubleToInteger(d);
+ } else {
+ if (loop == 2) {
+ array[loop] = 1; /* Default the date argument to 1. */
+ } else {
+ array[loop] = 0;
+ }
+ }
+ }
+
+ /* adjust 2-digit years into the 20th century */
+ if (array[0] >= 0 && array[0] <= 99)
+ array[0] += 1900;
+
+ msec_time = date_msecFromDate(array[0], array[1], array[2],
+ array[3], array[4], array[5], array[6]);
+ *rval = msec_time;
+ return JS_TRUE;
+}
+
+/*
+ * See ECMA 15.9.4.[3-10];
+ */
+static JSBool
+date_UTC(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble msec_time;
+
+ if (!date_msecFromArgs(cx, argc, vp + 2, &msec_time))
+ return JS_FALSE;
+
+ msec_time = TIMECLIP(msec_time);
+
+ return js_NewNumberInRootedValue(cx, msec_time, vp);
+}
+
+static JSBool
+date_parseString(JSString *str, jsdouble *result)
+{
+ jsdouble msec;
+
+ const jschar *s;
+ size_t limit;
+ size_t i = 0;
+ int year = -1;
+ int mon = -1;
+ int mday = -1;
+ int hour = -1;
+ int min = -1;
+ int sec = -1;
+ int c = -1;
+ int n = -1;
+ int tzoffset = -1;
+ int prevc = 0;
+ JSBool seenplusminus = JS_FALSE;
+ int temp;
+ JSBool seenmonthname = JS_FALSE;
+
+ JSSTRING_CHARS_AND_LENGTH(str, s, limit);
+ if (limit == 0)
+ goto syntax;
+ while (i < limit) {
+ c = s[i];
+ i++;
+ if (c <= ' ' || c == ',' || c == '-') {
+ if (c == '-' && '0' <= s[i] && s[i] <= '9') {
+ prevc = c;
+ }
+ continue;
+ }
+ if (c == '(') { /* comments) */
+ int depth = 1;
+ while (i < limit) {
+ c = s[i];
+ i++;
+ if (c == '(') depth++;
+ else if (c == ')')
+ if (--depth <= 0)
+ break;
+ }
+ continue;
+ }
+ if ('0' <= c && c <= '9') {
+ n = c - '0';
+ while (i < limit && '0' <= (c = s[i]) && c <= '9') {
+ n = n * 10 + c - '0';
+ i++;
+ }
+
+ /* allow TZA before the year, so
+ * 'Wed Nov 05 21:49:11 GMT-0800 1997'
+ * works */
+
+ /* uses of seenplusminus allow : in TZA, so Java
+ * no-timezone style of GMT+4:30 works
+ */
+
+ if ((prevc == '+' || prevc == '-')/* && year>=0 */) {
+ /* make ':' case below change tzoffset */
+ seenplusminus = JS_TRUE;
+
+ /* offset */
+ if (n < 24)
+ n = n * 60; /* EG. "GMT-3" */
+ else
+ n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */
+ if (prevc == '+') /* plus means east of GMT */
+ n = -n;
+ if (tzoffset != 0 && tzoffset != -1)
+ goto syntax;
+ tzoffset = n;
+ } else if (prevc == '/' && mon >= 0 && mday >= 0 && year < 0) {
+ if (c <= ' ' || c == ',' || c == '/' || i >= limit)
+ year = n;
+ else
+ goto syntax;
+ } else if (c == ':') {
+ if (hour < 0)
+ hour = /*byte*/ n;
+ else if (min < 0)
+ min = /*byte*/ n;
+ else
+ goto syntax;
+ } else if (c == '/') {
+ /* until it is determined that mon is the actual
+ month, keep it as 1-based rather than 0-based */
+ if (mon < 0)
+ mon = /*byte*/ n;
+ else if (mday < 0)
+ mday = /*byte*/ n;
+ else
+ goto syntax;
+ } else if (i < limit && c != ',' && c > ' ' && c != '-' && c != '(') {
+ goto syntax;
+ } else if (seenplusminus && n < 60) { /* handle GMT-3:30 */
+ if (tzoffset < 0)
+ tzoffset -= n;
+ else
+ tzoffset += n;
+ } else if (hour >= 0 && min < 0) {
+ min = /*byte*/ n;
+ } else if (prevc == ':' && min >= 0 && sec < 0) {
+ sec = /*byte*/ n;
+ } else if (mon < 0) {
+ mon = /*byte*/n;
+ } else if (mon >= 0 && mday < 0) {
+ mday = /*byte*/ n;
+ } else if (mon >= 0 && mday >= 0 && year < 0) {
+ year = n;
+ } else {
+ goto syntax;
+ }
+ prevc = 0;
+ } else if (c == '/' || c == ':' || c == '+' || c == '-') {
+ prevc = c;
+ } else {
+ size_t st = i - 1;
+ int k;
+ while (i < limit) {
+ c = s[i];
+ if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')))
+ break;
+ i++;
+ }
+ if (i <= st + 1)
+ goto syntax;
+ for (k = JS_ARRAY_LENGTH(wtb); --k >= 0;)
+ if (date_regionMatches(wtb[k], 0, s, st, i-st, 1)) {
+ int action = ttb[k];
+ if (action != 0) {
+ if (action < 0) {
+ /*
+ * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as
+ * 12:30, instead of blindly adding 12 if PM.
+ */
+ JS_ASSERT(action == -1 || action == -2);
+ if (hour > 12 || hour < 0) {
+ goto syntax;
+ } else {
+ if (action == -1 && hour == 12) { /* am */
+ hour = 0;
+ } else if (action == -2 && hour != 12) { /* pm */
+ hour += 12;
+ }
+ }
+ } else if (action <= 13) { /* month! */
+ /* Adjust mon to be 1-based until the final values
+ for mon, mday and year are adjusted below */
+ if (seenmonthname) {
+ goto syntax;
+ }
+ seenmonthname = JS_TRUE;
+ temp = /*byte*/ (action - 2) + 1;
+
+ if (mon < 0) {
+ mon = temp;
+ } else if (mday < 0) {
+ mday = mon;
+ mon = temp;
+ } else if (year < 0) {
+ year = mon;
+ mon = temp;
+ } else {
+ goto syntax;
+ }
+ } else {
+ tzoffset = action - 10000;
+ }
+ }
+ break;
+ }
+ if (k < 0)
+ goto syntax;
+ prevc = 0;
+ }
+ }
+ if (year < 0 || mon < 0 || mday < 0)
+ goto syntax;
+ /*
+ Case 1. The input string contains an English month name.
+ The form of the string can be month f l, or f month l, or
+ f l month which each evaluate to the same date.
+ If f and l are both greater than or equal to 70, or
+ both less than 70, the date is invalid.
+ The year is taken to be the greater of the values f, l.
+ If the year is greater than or equal to 70 and less than 100,
+ it is considered to be the number of years after 1900.
+ Case 2. The input string is of the form "f/m/l" where f, m and l are
+ integers, e.g. 7/16/45.
+ Adjust the mon, mday and year values to achieve 100% MSIE
+ compatibility.
+ a. If 0 <= f < 70, f/m/l is interpreted as month/day/year.
+ i. If year < 100, it is the number of years after 1900
+ ii. If year >= 100, it is the number of years after 0.
+ b. If 70 <= f < 100
+ i. If m < 70, f/m/l is interpreted as
+ year/month/day where year is the number of years after
+ 1900.
+ ii. If m >= 70, the date is invalid.
+ c. If f >= 100
+ i. If m < 70, f/m/l is interpreted as
+ year/month/day where year is the number of years after 0.
+ ii. If m >= 70, the date is invalid.
+ */
+ if (seenmonthname) {
+ if ((mday >= 70 && year >= 70) || (mday < 70 && year < 70)) {
+ goto syntax;
+ }
+ if (mday > year) {
+ temp = year;
+ year = mday;
+ mday = temp;
+ }
+ if (year >= 70 && year < 100) {
+ year += 1900;
+ }
+ } else if (mon < 70) { /* (a) month/day/year */
+ if (year < 100) {
+ year += 1900;
+ }
+ } else if (mon < 100) { /* (b) year/month/day */
+ if (mday < 70) {
+ temp = year;
+ year = mon + 1900;
+ mon = mday;
+ mday = temp;
+ } else {
+ goto syntax;
+ }
+ } else { /* (c) year/month/day */
+ if (mday < 70) {
+ temp = year;
+ year = mon;
+ mon = mday;
+ mday = temp;
+ } else {
+ goto syntax;
+ }
+ }
+ mon -= 1; /* convert month to 0-based */
+ if (sec < 0)
+ sec = 0;
+ if (min < 0)
+ min = 0;
+ if (hour < 0)
+ hour = 0;
+ if (tzoffset == -1) { /* no time zone specified, have to use local */
+ jsdouble msec_time;
+ msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
+
+ *result = UTC(msec_time);
+ return JS_TRUE;
+ }
+
+ msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
+ msec += tzoffset * msPerMinute;
+ *result = msec;
+ return JS_TRUE;
+
+syntax:
+ /* syntax error */
+ *result = 0;
+ return JS_FALSE;
+}
+
+static JSBool
+date_parse(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ jsdouble result;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(str);
+ if (!date_parseString(str, &result)) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+
+ result = TIMECLIP(result);
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_now(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_NewDoubleInRootedValue(cx, PRMJ_Now() / PRMJ_USEC_PER_MSEC, vp);
+}
+
+#ifdef JS_TRACER
+static jsdouble FASTCALL
+date_now_tn(JSContext*)
+{
+ return PRMJ_Now() / PRMJ_USEC_PER_MSEC;
+}
+#endif
+
+/*
+ * Get UTC time from the date object. Returns false if the object is not
+ * Date type.
+ */
+static JSBool
+GetUTCTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
+{
+ if (!JS_InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
+ return JS_FALSE;
+ *dp = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]);
+ return JS_TRUE;
+}
+
+/*
+ * Set UTC time slot with a pointer pointing to a jsdouble. This function is
+ * used only for setting UTC time to some predefined values, such as NaN.
+ *
+ * It also invalidates cached local time.
+ */
+static JSBool
+SetUTCTimePtr(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
+{
+ if (vp && !JS_InstanceOf(cx, obj, &js_DateClass, vp + 2))
+ return JS_FALSE;
+ JS_ASSERT_IF(!vp, STOBJ_GET_CLASS(obj) == &js_DateClass);
+
+ /* Invalidate local time cache. */
+ obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(dp);
+ return JS_TRUE;
+}
+
+/*
+ * Set UTC time to a given time.
+ */
+static JSBool
+SetUTCTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble t)
+{
+ jsdouble *dp = js_NewWeaklyRootedDouble(cx, t);
+ if (!dp)
+ return JS_FALSE;
+ return SetUTCTimePtr(cx, obj, vp, dp);
+}
+
+/*
+ * Get the local time, cache it if necessary. If UTC time is not finite
+ * (e.g., NaN), the local time slot is set to the UTC time without conversion.
+ */
+static JSBool
+GetAndCacheLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
+{
+ jsval v;
+ jsdouble result;
+ jsdouble *cached;
+
+ if (!obj || !JS_InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
+ return JS_FALSE;
+ v = obj->fslots[JSSLOT_LOCAL_TIME];
+
+ result = *JSVAL_TO_DOUBLE(v);
+
+ if (JSDOUBLE_IS_NaN(result)) {
+ if (!GetUTCTime(cx, obj, vp, &result))
+ return JS_FALSE;
+
+ /* if result is NaN, it couldn't be finite. */
+ if (JSDOUBLE_IS_FINITE(result))
+ result = LocalTime(result);
+
+ cached = js_NewWeaklyRootedDouble(cx, result);
+ if (!cached)
+ return JS_FALSE;
+
+ obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cached);
+ }
+
+ *dp = result;
+ return JS_TRUE;
+}
+
+/*
+ * See ECMA 15.9.5.4 thru 15.9.5.23
+ */
+static JSBool
+date_getTime(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ return GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result) &&
+ js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+GetYear(JSContext *cx, JSBool fullyear, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result)) {
+ result = YearFromTime(result);
+
+ /* Follow ECMA-262 to the letter, contrary to IE JScript. */
+ if (!fullyear)
+ result -= 1900;
+ }
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ return GetYear(cx, JS_FALSE, vp);
+}
+
+static JSBool
+date_getFullYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ return GetYear(cx, JS_TRUE, vp);
+}
+
+static JSBool
+date_getUTCFullYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = YearFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getMonth(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = MonthFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getUTCMonth(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = MonthFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getDate(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = DateFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getUTCDate(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = DateFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getDay(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = WeekDay(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getUTCDay(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = WeekDay(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getHours(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = HourFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getUTCHours(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = HourFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getMinutes(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = MinFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getUTCMinutes(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = MinFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+/* Date.getSeconds is mapped to getUTCSeconds */
+
+static JSBool
+date_getUTCSeconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = SecFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+/* Date.getMilliseconds is mapped to getUTCMilliseconds */
+
+static JSBool
+date_getUTCMilliseconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = msFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getTimezoneOffset(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsdouble utctime, localtime, result;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!GetUTCTime(cx, obj, vp, &utctime))
+ return JS_FALSE;
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime))
+ return JS_FALSE;
+
+ /*
+ * Return the time zone offset in minutes for the current locale that is
+ * appropriate for this time. This value would be a constant except for
+ * daylight savings time.
+ */
+ result = (utctime - localtime) / msPerMinute;
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+SetDateToNaN(JSContext *cx, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!SetUTCTimePtr(cx, obj, NULL, cx->runtime->jsNaN))
+ return JS_FALSE;
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+}
+
+static JSBool
+date_setTime(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (argc == 0)
+ return SetDateToNaN(cx, vp);
+ result = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+
+ result = TIMECLIP(result);
+
+ if (!SetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, result))
+ return JS_FALSE;
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval *argv;
+ uintN i;
+ jsdouble args[4], *argp, *stop;
+ jsdouble hour, min, sec, msec;
+ jsdouble lorutime; /* Local or UTC version of *date */
+
+ jsdouble msec_time;
+ jsdouble result;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!GetUTCTime(cx, obj, vp, &result))
+ return JS_FALSE;
+
+ /* just return NaN if the date is already NaN */
+ if (!JSDOUBLE_IS_FINITE(result))
+ return js_NewNumberInRootedValue(cx, result, vp);
+
+ /*
+ * Satisfy the ECMA rule that if a function is called with
+ * fewer arguments than the specified formal arguments, the
+ * remaining arguments are set to undefined. Seems like all
+ * the Date.setWhatever functions in ECMA are only varargs
+ * beyond the first argument; this should be set to undefined
+ * if it's not given. This means that "d = new Date();
+ * d.setMilliseconds()" returns NaN. Blech.
+ */
+ if (argc == 0)
+ return SetDateToNaN(cx, vp);
+ if (argc > maxargs)
+ argc = maxargs; /* clamp argc */
+ JS_ASSERT(argc <= 4);
+
+ argv = vp + 2;
+ for (i = 0; i < argc; i++) {
+ args[i] = js_ValueToNumber(cx, &argv[i]);
+ if (JSVAL_IS_NULL(argv[i]))
+ return JS_FALSE;
+ if (!JSDOUBLE_IS_FINITE(args[i]))
+ return SetDateToNaN(cx, vp);
+ args[i] = js_DoubleToInteger(args[i]);
+ }
+
+ if (local)
+ lorutime = LocalTime(result);
+ else
+ lorutime = result;
+
+ argp = args;
+ stop = argp + argc;
+ if (maxargs >= 4 && argp < stop)
+ hour = *argp++;
+ else
+ hour = HourFromTime(lorutime);
+
+ if (maxargs >= 3 && argp < stop)
+ min = *argp++;
+ else
+ min = MinFromTime(lorutime);
+
+ if (maxargs >= 2 && argp < stop)
+ sec = *argp++;
+ else
+ sec = SecFromTime(lorutime);
+
+ if (maxargs >= 1 && argp < stop)
+ msec = *argp;
+ else
+ msec = msFromTime(lorutime);
+
+ msec_time = MakeTime(hour, min, sec, msec);
+ result = MakeDate(Day(lorutime), msec_time);
+
+/* fprintf(stderr, "%f\n", result); */
+
+ if (local)
+ result = UTC(result);
+
+/* fprintf(stderr, "%f\n", result); */
+
+ result = TIMECLIP(result);
+ if (!SetUTCTime(cx, obj, NULL, result))
+ return JS_FALSE;
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_setMilliseconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 1, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCMilliseconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 1, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setSeconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 2, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCSeconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 2, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setMinutes(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 3, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCMinutes(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 3, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setHours(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 4, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCHours(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 4, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval *argv;
+ uintN i;
+ jsdouble lorutime; /* local or UTC version of *date */
+ jsdouble args[3], *argp, *stop;
+ jsdouble year, month, day;
+ jsdouble result;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!GetUTCTime(cx, obj, vp, &result))
+ return JS_FALSE;
+
+ /* see complaint about ECMA in date_MakeTime */
+ if (argc == 0)
+ return SetDateToNaN(cx, vp);
+ if (argc > maxargs)
+ argc = maxargs; /* clamp argc */
+ JS_ASSERT(1 <= argc && argc <= 3);
+
+ argv = vp + 2;
+ for (i = 0; i < argc; i++) {
+ args[i] = js_ValueToNumber(cx, &argv[i]);
+ if (JSVAL_IS_NULL(argv[i]))
+ return JS_FALSE;
+ if (!JSDOUBLE_IS_FINITE(args[i]))
+ return SetDateToNaN(cx, vp);
+ args[i] = js_DoubleToInteger(args[i]);
+ }
+
+ /* return NaN if date is NaN and we're not setting the year,
+ * If we are, use 0 as the time. */
+ if (!(JSDOUBLE_IS_FINITE(result))) {
+ if (maxargs < 3)
+ return js_NewNumberInRootedValue(cx, result, vp);
+ lorutime = +0.;
+ } else {
+ lorutime = local ? LocalTime(result) : result;
+ }
+
+ argp = args;
+ stop = argp + argc;
+ if (maxargs >= 3 && argp < stop)
+ year = *argp++;
+ else
+ year = YearFromTime(lorutime);
+
+ if (maxargs >= 2 && argp < stop)
+ month = *argp++;
+ else
+ month = MonthFromTime(lorutime);
+
+ if (maxargs >= 1 && argp < stop)
+ day = *argp++;
+ else
+ day = DateFromTime(lorutime);
+
+ day = MakeDay(year, month, day); /* day within year */
+ result = MakeDate(day, TimeWithinDay(lorutime));
+
+ if (local)
+ result = UTC(result);
+
+ result = TIMECLIP(result);
+ if (!SetUTCTime(cx, obj, NULL, result))
+ return JS_FALSE;
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_setDate(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 1, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCDate(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 1, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setMonth(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 2, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCMonth(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 2, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setFullYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 3, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCFullYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 3, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsdouble t;
+ jsdouble year;
+ jsdouble day;
+ jsdouble result;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!GetUTCTime(cx, obj, vp, &result))
+ return JS_FALSE;
+
+ if (argc == 0)
+ return SetDateToNaN(cx, vp);
+ year = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ if (!JSDOUBLE_IS_FINITE(year))
+ return SetDateToNaN(cx, vp);
+
+ year = js_DoubleToInteger(year);
+
+ if (!JSDOUBLE_IS_FINITE(result)) {
+ t = +0.0;
+ } else {
+ t = LocalTime(result);
+ }
+
+ if (year >= 0 && year <= 99)
+ year += 1900;
+
+ day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
+ result = MakeDate(day, TimeWithinDay(t));
+ result = UTC(result);
+
+ result = TIMECLIP(result);
+ if (!SetUTCTime(cx, obj, NULL, result))
+ return JS_FALSE;
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+/* constants for toString, toUTCString */
+static char js_NaN_date_str[] = "Invalid Date";
+static const char* days[] =
+{
+ "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
+};
+static const char* months[] =
+{
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+
+// Avoid dependence on PRMJ_FormatTimeUSEnglish, because it
+// requires a PRMJTime... which only has 16-bit years. Sub-ECMA.
+static void
+print_gmt_string(char* buf, size_t size, jsdouble utctime)
+{
+ JS_snprintf(buf, size, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
+ days[WeekDay(utctime)],
+ DateFromTime(utctime),
+ months[MonthFromTime(utctime)],
+ YearFromTime(utctime),
+ HourFromTime(utctime),
+ MinFromTime(utctime),
+ SecFromTime(utctime));
+}
+
+static void
+print_iso_string(char* buf, size_t size, jsdouble utctime)
+{
+ JS_snprintf(buf, size, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.3dZ",
+ YearFromTime(utctime),
+ MonthFromTime(utctime) + 1,
+ DateFromTime(utctime),
+ HourFromTime(utctime),
+ MinFromTime(utctime),
+ SecFromTime(utctime),
+ msFromTime(utctime));
+}
+
+static JSBool
+date_utc_format(JSContext *cx, jsval *vp,
+ void (*printFunc)(char*, size_t, jsdouble))
+{
+ char buf[100];
+ JSString *str;
+ jsdouble utctime;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
+ return JS_FALSE;
+
+ if (!JSDOUBLE_IS_FINITE(utctime)) {
+ JS_snprintf(buf, sizeof buf, js_NaN_date_str);
+ } else {
+ (*printFunc)(buf, sizeof buf, utctime);
+ }
+ str = JS_NewStringCopyZ(cx, buf);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+date_toGMTString(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_utc_format(cx, vp, print_gmt_string);
+}
+
+static JSBool
+date_toISOString(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_utc_format(cx, vp, print_iso_string);
+}
+
+/* for Date.toLocaleString; interface to PRMJTime date struct.
+ */
+static void
+new_explode(jsdouble timeval, PRMJTime *split)
+{
+ jsint year = YearFromTime(timeval);
+
+ split->tm_usec = (int32) msFromTime(timeval) * 1000;
+ split->tm_sec = (int8) SecFromTime(timeval);
+ split->tm_min = (int8) MinFromTime(timeval);
+ split->tm_hour = (int8) HourFromTime(timeval);
+ split->tm_mday = (int8) DateFromTime(timeval);
+ split->tm_mon = (int8) MonthFromTime(timeval);
+ split->tm_wday = (int8) WeekDay(timeval);
+ split->tm_year = year;
+ split->tm_yday = (int16) DayWithinYear(timeval, year);
+
+ /* not sure how this affects things, but it doesn't seem
+ to matter. */
+ split->tm_isdst = (DaylightSavingTA(timeval) != 0);
+}
+
+typedef enum formatspec {
+ FORMATSPEC_FULL, FORMATSPEC_DATE, FORMATSPEC_TIME
+} formatspec;
+
+/* helper function */
+static JSBool
+date_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval)
+{
+ char buf[100];
+ JSString *str;
+ char tzbuf[100];
+ JSBool usetz;
+ size_t i, tzlen;
+ PRMJTime split;
+
+ if (!JSDOUBLE_IS_FINITE(date)) {
+ JS_snprintf(buf, sizeof buf, js_NaN_date_str);
+ } else {
+ jsdouble local = LocalTime(date);
+
+ /* offset from GMT in minutes. The offset includes daylight savings,
+ if it applies. */
+ jsint minutes = (jsint) floor(AdjustTime(date) / msPerMinute);
+
+ /* map 510 minutes to 0830 hours */
+ intN offset = (minutes / 60) * 100 + minutes % 60;
+
+ /* print as "Wed Nov 05 19:38:03 GMT-0800 (PST) 1997" The TZA is
+ * printed as 'GMT-0800' rather than as 'PST' to avoid
+ * operating-system dependence on strftime (which
+ * PRMJ_FormatTimeUSEnglish calls, for %Z only.) win32 prints
+ * PST as 'Pacific Standard Time.' This way we always know
+ * what we're getting, and can parse it if we produce it.
+ * The OS TZA string is included as a comment.
+ */
+
+ /* get a timezone string from the OS to include as a
+ comment. */
+ new_explode(date, &split);
+ if (PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &split) != 0) {
+
+ /* Decide whether to use the resulting timezone string.
+ *
+ * Reject it if it contains any non-ASCII, non-alphanumeric
+ * characters. It's then likely in some other character
+ * encoding, and we probably won't display it correctly.
+ */
+ usetz = JS_TRUE;
+ tzlen = strlen(tzbuf);
+ if (tzlen > 100) {
+ usetz = JS_FALSE;
+ } else {
+ for (i = 0; i < tzlen; i++) {
+ jschar c = tzbuf[i];
+ if (c > 127 ||
+ !(isalpha(c) || isdigit(c) ||
+ c == ' ' || c == '(' || c == ')')) {
+ usetz = JS_FALSE;
+ }
+ }
+ }
+
+ /* Also reject it if it's not parenthesized or if it's '()'. */
+ if (tzbuf[0] != '(' || tzbuf[1] == ')')
+ usetz = JS_FALSE;
+ } else
+ usetz = JS_FALSE;
+
+ switch (format) {
+ case FORMATSPEC_FULL:
+ /*
+ * Avoid dependence on PRMJ_FormatTimeUSEnglish, because it
+ * requires a PRMJTime... which only has 16-bit years. Sub-ECMA.
+ */
+ /* Tue Oct 31 2000 09:41:40 GMT-0800 (PST) */
+ JS_snprintf(buf, sizeof buf,
+ "%s %s %.2d %.4d %.2d:%.2d:%.2d GMT%+.4d%s%s",
+ days[WeekDay(local)],
+ months[MonthFromTime(local)],
+ DateFromTime(local),
+ YearFromTime(local),
+ HourFromTime(local),
+ MinFromTime(local),
+ SecFromTime(local),
+ offset,
+ usetz ? " " : "",
+ usetz ? tzbuf : "");
+ break;
+ case FORMATSPEC_DATE:
+ /* Tue Oct 31 2000 */
+ JS_snprintf(buf, sizeof buf,
+ "%s %s %.2d %.4d",
+ days[WeekDay(local)],
+ months[MonthFromTime(local)],
+ DateFromTime(local),
+ YearFromTime(local));
+ break;
+ case FORMATSPEC_TIME:
+ /* 09:41:40 GMT-0800 (PST) */
+ JS_snprintf(buf, sizeof buf,
+ "%.2d:%.2d:%.2d GMT%+.4d%s%s",
+ HourFromTime(local),
+ MinFromTime(local),
+ SecFromTime(local),
+ offset,
+ usetz ? " " : "",
+ usetz ? tzbuf : "");
+ break;
+ }
+ }
+
+ str = JS_NewStringCopyZ(cx, buf);
+ if (!str)
+ return JS_FALSE;
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
+{
+ JSObject *obj;
+ char buf[100];
+ JSString *str;
+ PRMJTime split;
+ jsdouble utctime;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!GetUTCTime(cx, obj, vp, &utctime))
+ return JS_FALSE;
+
+ if (!JSDOUBLE_IS_FINITE(utctime)) {
+ JS_snprintf(buf, sizeof buf, js_NaN_date_str);
+ } else {
+ intN result_len;
+ jsdouble local = LocalTime(utctime);
+ new_explode(local, &split);
+
+ /* let PRMJTime format it. */
+ result_len = PRMJ_FormatTime(buf, sizeof buf, format, &split);
+
+ /* If it failed, default to toString. */
+ if (result_len == 0)
+ return date_format(cx, utctime, FORMATSPEC_FULL, vp);
+
+ /* Hacked check against undesired 2-digit year 00/00/00 form. */
+ if (strcmp(format, "%x") == 0 && result_len >= 6 &&
+ /* Format %x means use OS settings, which may have 2-digit yr, so
+ hack end of 3/11/22 or 11.03.22 or 11Mar22 to use 4-digit yr...*/
+ !isdigit(buf[result_len - 3]) &&
+ isdigit(buf[result_len - 2]) && isdigit(buf[result_len - 1]) &&
+ /* ...but not if starts with 4-digit year, like 2022/3/11. */
+ !(isdigit(buf[0]) && isdigit(buf[1]) &&
+ isdigit(buf[2]) && isdigit(buf[3]))) {
+ JS_snprintf(buf + (result_len - 2), (sizeof buf) - (result_len - 2),
+ "%d", js_DateGetYear(cx, obj));
+ }
+
+ }
+
+ if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
+ return cx->localeCallbacks->localeToUnicode(cx, buf, vp);
+
+ str = JS_NewStringCopyZ(cx, buf);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+date_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
+{
+ /* Use '%#c' for windows, because '%c' is
+ * backward-compatible and non-y2k with msvc; '%#c' requests that a
+ * full year be used in the result string.
+ */
+ return date_toLocaleHelper(cx,
+#if defined(_WIN32) && !defined(__MWERKS__)
+ "%#c"
+#else
+ "%c"
+#endif
+ , vp);
+}
+
+static JSBool
+date_toLocaleDateString(JSContext *cx, uintN argc, jsval *vp)
+{
+ /* Use '%#x' for windows, because '%x' is
+ * backward-compatible and non-y2k with msvc; '%#x' requests that a
+ * full year be used in the result string.
+ */
+ return date_toLocaleHelper(cx,
+#if defined(_WIN32) && !defined(__MWERKS__)
+ "%#x"
+#else
+ "%x"
+#endif
+ , vp);
+}
+
+static JSBool
+date_toLocaleTimeString(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_toLocaleHelper(cx, "%X", vp);
+}
+
+static JSBool
+date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *fmt;
+ const char *fmtbytes;
+
+ if (argc == 0)
+ return date_toLocaleString(cx, argc, vp);
+
+ fmt = js_ValueToString(cx, vp[2]);
+ if (!fmt)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(fmt);
+ fmtbytes = js_GetStringBytes(cx, fmt);
+ if (!fmtbytes)
+ return JS_FALSE;
+
+ return date_toLocaleHelper(cx, fmtbytes, vp);
+}
+
+static JSBool
+date_toTimeString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble utctime;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
+ return JS_FALSE;
+ return date_format(cx, utctime, FORMATSPEC_TIME, vp);
+}
+
+static JSBool
+date_toDateString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble utctime;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
+ return JS_FALSE;
+ return date_format(cx, utctime, FORMATSPEC_DATE, vp);
+}
+
+#if JS_HAS_TOSOURCE
+#include <string.h>
+#include "jsdtoa.h"
+
+static JSBool
+date_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble utctime;
+ char buf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr, *bytes;
+ JSString *str;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
+ return JS_FALSE;
+
+ numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, utctime);
+ if (!numStr) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ bytes = JS_smprintf("(new %s(%s))", js_Date_str, numStr);
+ if (!bytes) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ str = JS_NewString(cx, bytes, strlen(bytes));
+ if (!str) {
+ free(bytes);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif
+
+static JSBool
+date_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble utctime;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
+ return JS_FALSE;
+ return date_format(cx, utctime, FORMATSPEC_FULL, vp);
+}
+
+#ifdef JS_TRACER
+static jsval FASTCALL
+date_valueOf_tn(JSContext* cx, JSObject* obj, JSString* str)
+{
+ JS_ASSERT(JS_InstanceOf(cx, obj, &js_DateClass, NULL));
+ jsdouble t = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]);
+
+ JSString* number_str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]);
+ jsval v;
+ if (js_EqualStrings(str, number_str)) {
+ if (!js_NewNumberInRootedValue(cx, t, &v))
+ return JSVAL_ERROR_COOKIE;
+ } else {
+ if (!date_format(cx, t, FORMATSPEC_FULL, &v))
+ return JSVAL_ERROR_COOKIE;
+ }
+ return v;
+}
+#endif
+
+static JSBool
+date_valueOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str, *number_str;
+
+ /* It is an error to call date_valueOf on a non-date object, but we don't
+ * need to check for that explicitly here because every path calls
+ * GetUTCTime, which does the check.
+ */
+
+ /* If called directly with no arguments, convert to a time number. */
+ if (argc == 0)
+ return date_getTime(cx, argc, vp);
+
+ /* Convert to number only if the hint was given, otherwise favor string. */
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ number_str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]);
+ if (js_EqualStrings(str, number_str))
+ return date_getTime(cx, argc, vp);
+ return date_toString(cx, argc, vp);
+}
+
+JS_DEFINE_CALLINFO_2(extern, OBJECT, js_FastNewDate, CONTEXT, OBJECT, 0, 0)
+
+// Don't really need an argument here, but we don't support arg-less builtins
+JS_DEFINE_TRCINFO_1(date_now,
+ (1, (static, DOUBLE, date_now_tn, CONTEXT, 0, 0)))
+
+static JSFunctionSpec date_static_methods[] = {
+ JS_FN("UTC", date_UTC, MAXARGS,0),
+ JS_FN("parse", date_parse, 1,0),
+ JS_TN("now", date_now, 0,0, date_now_trcinfo),
+ JS_FS_END
+};
+
+JS_DEFINE_TRCINFO_1(date_valueOf,
+ (3, (static, JSVAL_FAIL, date_valueOf_tn, CONTEXT, THIS, STRING, 0, 0)))
+
+static JSFunctionSpec date_methods[] = {
+ JS_FN("getTime", date_getTime, 0,0),
+ JS_FN("getTimezoneOffset", date_getTimezoneOffset, 0,0),
+ JS_FN("getYear", date_getYear, 0,0),
+ JS_FN("getFullYear", date_getFullYear, 0,0),
+ JS_FN("getUTCFullYear", date_getUTCFullYear, 0,0),
+ JS_FN("getMonth", date_getMonth, 0,0),
+ JS_FN("getUTCMonth", date_getUTCMonth, 0,0),
+ JS_FN("getDate", date_getDate, 0,0),
+ JS_FN("getUTCDate", date_getUTCDate, 0,0),
+ JS_FN("getDay", date_getDay, 0,0),
+ JS_FN("getUTCDay", date_getUTCDay, 0,0),
+ JS_FN("getHours", date_getHours, 0,0),
+ JS_FN("getUTCHours", date_getUTCHours, 0,0),
+ JS_FN("getMinutes", date_getMinutes, 0,0),
+ JS_FN("getUTCMinutes", date_getUTCMinutes, 0,0),
+ JS_FN("getSeconds", date_getUTCSeconds, 0,0),
+ JS_FN("getUTCSeconds", date_getUTCSeconds, 0,0),
+ JS_FN("getMilliseconds", date_getUTCMilliseconds, 0,0),
+ JS_FN("getUTCMilliseconds", date_getUTCMilliseconds, 0,0),
+ JS_FN("setTime", date_setTime, 1,0),
+ JS_FN("setYear", date_setYear, 1,0),
+ JS_FN("setFullYear", date_setFullYear, 3,0),
+ JS_FN("setUTCFullYear", date_setUTCFullYear, 3,0),
+ JS_FN("setMonth", date_setMonth, 2,0),
+ JS_FN("setUTCMonth", date_setUTCMonth, 2,0),
+ JS_FN("setDate", date_setDate, 1,0),
+ JS_FN("setUTCDate", date_setUTCDate, 1,0),
+ JS_FN("setHours", date_setHours, 4,0),
+ JS_FN("setUTCHours", date_setUTCHours, 4,0),
+ JS_FN("setMinutes", date_setMinutes, 3,0),
+ JS_FN("setUTCMinutes", date_setUTCMinutes, 3,0),
+ JS_FN("setSeconds", date_setSeconds, 2,0),
+ JS_FN("setUTCSeconds", date_setUTCSeconds, 2,0),
+ JS_FN("setMilliseconds", date_setMilliseconds, 1,0),
+ JS_FN("setUTCMilliseconds", date_setUTCMilliseconds, 1,0),
+ JS_FN("toUTCString", date_toGMTString, 0,0),
+ JS_FN(js_toLocaleString_str, date_toLocaleString, 0,0),
+ JS_FN("toLocaleDateString", date_toLocaleDateString, 0,0),
+ JS_FN("toLocaleTimeString", date_toLocaleTimeString, 0,0),
+ JS_FN("toLocaleFormat", date_toLocaleFormat, 0,0),
+ JS_FN("toDateString", date_toDateString, 0,0),
+ JS_FN("toTimeString", date_toTimeString, 0,0),
+ JS_FN("toISOString", date_toISOString, 0,0),
+ JS_FN(js_toJSON_str, date_toISOString, 0,0),
+
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, date_toSource, 0,0),
+#endif
+ JS_FN(js_toString_str, date_toString, 0,0),
+ JS_TN(js_valueOf_str, date_valueOf, 0,0, date_valueOf_trcinfo),
+ JS_FS_END
+};
+
+static jsdouble *
+date_constructor(JSContext *cx, JSObject* obj)
+{
+ jsdouble *date;
+
+ date = js_NewWeaklyRootedDouble(cx, 0.0);
+ if (!date)
+ return NULL;
+
+ obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(date);
+ obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return date;
+}
+
+JSBool
+js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsdouble *date;
+ JSString *str;
+ jsdouble d;
+
+ /* Date called as function. */
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ return date_format(cx, PRMJ_Now() / PRMJ_USEC_PER_MSEC,
+ FORMATSPEC_FULL, rval);
+ }
+
+ /* Date called as constructor. */
+ if (argc == 0) {
+ date = date_constructor(cx, obj);
+ if (!date)
+ return JS_FALSE;
+ *date = PRMJ_Now() / PRMJ_USEC_PER_MSEC;
+ } else if (argc == 1) {
+ if (!JSVAL_IS_STRING(argv[0])) {
+ /* the argument is a millisecond number */
+ d = js_ValueToNumber(cx, &argv[0]);
+ if (JSVAL_IS_NULL(argv[0]))
+ return JS_FALSE;
+ date = date_constructor(cx, obj);
+ if (!date)
+ return JS_FALSE;
+ *date = TIMECLIP(d);
+ } else {
+ /* the argument is a string; parse it. */
+ date = date_constructor(cx, obj);
+ if (!date)
+ return JS_FALSE;
+
+ str = js_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+
+ if (!date_parseString(str, date))
+ *date = *cx->runtime->jsNaN;
+ *date = TIMECLIP(*date);
+ }
+ } else {
+ jsdouble *date;
+ jsdouble msec_time;
+
+ if (!date_msecFromArgs(cx, argc, argv, &msec_time))
+ return JS_FALSE;
+
+ date = date_constructor(cx, obj);
+ if (!date)
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(msec_time)) {
+ msec_time = UTC(msec_time);
+ msec_time = TIMECLIP(msec_time);
+ }
+
+ *date = msec_time;
+ }
+ return JS_TRUE;
+}
+
+JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_UTC_TIME);
+JS_STATIC_ASSERT(JSSLOT_UTC_TIME + 1 == JSSLOT_LOCAL_TIME);
+
+#ifdef JS_TRACER
+JSObject* FASTCALL
+js_FastNewDate(JSContext* cx, JSObject* proto)
+{
+ JS_ASSERT(JS_ON_TRACE(cx));
+ JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
+ if (!obj)
+ return NULL;
+
+ JSClass* clasp = &js_DateClass;
+ obj->classword = jsuword(clasp);
+
+ obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
+ obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
+
+ jsdouble* date = js_NewWeaklyRootedDouble(cx, 0.0);
+ if (!date)
+ return NULL;
+ *date = date_now_tn(cx);
+ obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(date);
+ obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ for (unsigned i = JSSLOT_LOCAL_TIME + 1; i != JS_INITIAL_NSLOTS; ++i)
+ obj->fslots[i] = JSVAL_VOID;
+
+ JS_ASSERT(!clasp->getObjectOps);
+ JS_ASSERT(proto->map->ops == &js_ObjectOps);
+ obj->map = js_HoldObjectMap(cx, proto->map);
+ obj->dslots = NULL;
+ return obj;
+}
+#endif
+
+JSObject *
+js_InitDateClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+ jsdouble *proto_date;
+
+ /* set static LocalTZA */
+ LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
+ proto = JS_InitClass(cx, obj, NULL, &js_DateClass, js_Date, MAXARGS,
+ NULL, date_methods, NULL, date_static_methods);
+ if (!proto)
+ return NULL;
+
+ /* Alias toUTCString with toGMTString. (ECMA B.2.6) */
+ if (!JS_AliasProperty(cx, proto, "toUTCString", "toGMTString"))
+ return NULL;
+
+ /* Set the value of the Date.prototype date to NaN */
+ proto_date = date_constructor(cx, proto);
+ if (!proto_date)
+ return NULL;
+ *proto_date = *cx->runtime->jsNaN;
+
+ return proto;
+}
+
+JS_FRIEND_API(JSObject *)
+js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)
+{
+ JSObject *obj;
+ jsdouble *date;
+
+ obj = js_NewObject(cx, &js_DateClass, NULL, NULL, 0);
+ if (!obj)
+ return NULL;
+
+ date = date_constructor(cx, obj);
+ if (!date)
+ return NULL;
+
+ *date = msec_time;
+ return obj;
+}
+
+JS_FRIEND_API(JSObject *)
+js_NewDateObject(JSContext* cx, int year, int mon, int mday,
+ int hour, int min, int sec)
+{
+ JSObject *obj;
+ jsdouble msec_time;
+
+ JS_ASSERT(mon < 12);
+ msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
+ obj = js_NewDateObjectMsec(cx, UTC(msec_time));
+ return obj;
+}
+
+JS_FRIEND_API(JSBool)
+js_DateIsValid(JSContext *cx, JSObject* obj)
+{
+ jsdouble utctime;
+ return GetUTCTime(cx, obj, NULL, &utctime) && !JSDOUBLE_IS_NaN(utctime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetYear(JSContext *cx, JSObject* obj)
+{
+ jsdouble localtime;
+
+ /* Preserve legacy API behavior of returning 0 for invalid dates. */
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
+ JSDOUBLE_IS_NaN(localtime)) {
+ return 0;
+ }
+
+ return (int) YearFromTime(localtime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetMonth(JSContext *cx, JSObject* obj)
+{
+ jsdouble localtime;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
+ JSDOUBLE_IS_NaN(localtime)) {
+ return 0;
+ }
+
+ return (int) MonthFromTime(localtime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetDate(JSContext *cx, JSObject* obj)
+{
+ jsdouble localtime;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
+ JSDOUBLE_IS_NaN(localtime)) {
+ return 0;
+ }
+
+ return (int) DateFromTime(localtime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetHours(JSContext *cx, JSObject* obj)
+{
+ jsdouble localtime;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
+ JSDOUBLE_IS_NaN(localtime)) {
+ return 0;
+ }
+
+ return (int) HourFromTime(localtime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetMinutes(JSContext *cx, JSObject* obj)
+{
+ jsdouble localtime;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
+ JSDOUBLE_IS_NaN(localtime)) {
+ return 0;
+ }
+
+ return (int) MinFromTime(localtime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetSeconds(JSContext *cx, JSObject* obj)
+{
+ jsdouble utctime;
+
+ if (!GetUTCTime(cx, obj, NULL, &utctime) || JSDOUBLE_IS_NaN(utctime))
+ return 0;
+
+ return (int) SecFromTime(utctime);
+}
+
+JS_FRIEND_API(void)
+js_DateSetYear(JSContext *cx, JSObject *obj, int year)
+{
+ jsdouble local;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ /* reset date if it was NaN */
+ if (JSDOUBLE_IS_NaN(local))
+ local = 0;
+
+ local = date_msecFromDate(year,
+ MonthFromTime(local),
+ DateFromTime(local),
+ HourFromTime(local),
+ MinFromTime(local),
+ SecFromTime(local),
+ msFromTime(local));
+
+ /* SetUTCTime also invalidates local time cache. */
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(void)
+js_DateSetMonth(JSContext *cx, JSObject *obj, int month)
+{
+ jsdouble local;
+
+ JS_ASSERT(month < 12);
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ /* bail if date was NaN */
+ if (JSDOUBLE_IS_NaN(local))
+ return;
+
+ local = date_msecFromDate(YearFromTime(local),
+ month,
+ DateFromTime(local),
+ HourFromTime(local),
+ MinFromTime(local),
+ SecFromTime(local),
+ msFromTime(local));
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(void)
+js_DateSetDate(JSContext *cx, JSObject *obj, int date)
+{
+ jsdouble local;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ if (JSDOUBLE_IS_NaN(local))
+ return;
+
+ local = date_msecFromDate(YearFromTime(local),
+ MonthFromTime(local),
+ date,
+ HourFromTime(local),
+ MinFromTime(local),
+ SecFromTime(local),
+ msFromTime(local));
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(void)
+js_DateSetHours(JSContext *cx, JSObject *obj, int hours)
+{
+ jsdouble local;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ if (JSDOUBLE_IS_NaN(local))
+ return;
+ local = date_msecFromDate(YearFromTime(local),
+ MonthFromTime(local),
+ DateFromTime(local),
+ hours,
+ MinFromTime(local),
+ SecFromTime(local),
+ msFromTime(local));
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(void)
+js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes)
+{
+ jsdouble local;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ if (JSDOUBLE_IS_NaN(local))
+ return;
+ local = date_msecFromDate(YearFromTime(local),
+ MonthFromTime(local),
+ DateFromTime(local),
+ HourFromTime(local),
+ minutes,
+ SecFromTime(local),
+ msFromTime(local));
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(void)
+js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds)
+{
+ jsdouble local;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ if (JSDOUBLE_IS_NaN(local))
+ return;
+ local = date_msecFromDate(YearFromTime(local),
+ MonthFromTime(local),
+ DateFromTime(local),
+ HourFromTime(local),
+ MinFromTime(local),
+ seconds,
+ msFromTime(local));
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(jsdouble)
+js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj)
+{
+ jsdouble utctime;
+ if (!GetUTCTime(cx, obj, NULL, &utctime))
+ return 0;
+ return utctime;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdate.h b/tools/node_modules/expresso/deps/jscoverage/js/jsdate.h
new file mode 100644
index 0000000..6c5b3aa
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdate.h
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS Date class interface.
+ */
+
+#ifndef jsdate_h___
+#define jsdate_h___
+
+JS_BEGIN_EXTERN_C
+
+extern JSClass js_DateClass;
+
+extern JSObject *
+js_InitDateClass(JSContext *cx, JSObject *obj);
+
+/*
+ * These functions provide a C interface to the date/time object
+ */
+
+/*
+ * Construct a new Date Object from a time value given in milliseconds UTC
+ * since the epoch.
+ */
+extern JS_FRIEND_API(JSObject*)
+js_NewDateObjectMsec(JSContext* cx, jsdouble msec_time);
+
+/*
+ * Construct a new Date Object from an exploded local time value.
+ *
+ * Assert that mon < 12 to help catch off-by-one user errors, which are common
+ * due to the 0-based month numbering copied into JS from Java (java.util.Date
+ * in 1995). js_DateSetMonth (below) likewise asserts month < 12.
+ */
+extern JS_FRIEND_API(JSObject*)
+js_NewDateObject(JSContext* cx, int year, int mon, int mday,
+ int hour, int min, int sec);
+
+/*
+ * Detect whether the internal date value is NaN. (Because failure is
+ * out-of-band for js_DateGet*)
+ */
+extern JS_FRIEND_API(JSBool)
+js_DateIsValid(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetYear(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetMonth(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetDate(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetHours(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetMinutes(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetSeconds(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(void)
+js_DateSetYear(JSContext *cx, JSObject *obj, int year);
+
+extern JS_FRIEND_API(void)
+js_DateSetMonth(JSContext *cx, JSObject *obj, int month);
+
+extern JS_FRIEND_API(void)
+js_DateSetDate(JSContext *cx, JSObject *obj, int date);
+
+extern JS_FRIEND_API(void)
+js_DateSetHours(JSContext *cx, JSObject *obj, int hours);
+
+extern JS_FRIEND_API(void)
+js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes);
+
+extern JS_FRIEND_API(void)
+js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds);
+
+extern JS_FRIEND_API(jsdouble)
+js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj);
+
+JS_END_EXTERN_C
+
+#endif /* jsdate_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.cpp
new file mode 100644
index 0000000..dad4590
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.cpp
@@ -0,0 +1,1954 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS debugging API.
+ */
+#include "jsstddef.h"
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsclist.h"
+#include "jsapi.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+
+#include "jsautooplen.h"
+
+typedef struct JSTrap {
+ JSCList links;
+ JSScript *script;
+ jsbytecode *pc;
+ JSOp op;
+ JSTrapHandler handler;
+ void *closure;
+} JSTrap;
+
+#define DBG_LOCK(rt) JS_ACQUIRE_LOCK((rt)->debuggerLock)
+#define DBG_UNLOCK(rt) JS_RELEASE_LOCK((rt)->debuggerLock)
+#define DBG_LOCK_EVAL(rt,expr) (DBG_LOCK(rt), (expr), DBG_UNLOCK(rt))
+
+/*
+ * NB: FindTrap must be called with rt->debuggerLock acquired.
+ */
+static JSTrap *
+FindTrap(JSRuntime *rt, JSScript *script, jsbytecode *pc)
+{
+ JSTrap *trap;
+
+ for (trap = (JSTrap *)rt->trapList.next;
+ &trap->links != &rt->trapList;
+ trap = (JSTrap *)trap->links.next) {
+ if (trap->script == script && trap->pc == pc)
+ return trap;
+ }
+ return NULL;
+}
+
+jsbytecode *
+js_UntrapScriptCode(JSContext *cx, JSScript *script)
+{
+ jsbytecode *code;
+ JSRuntime *rt;
+ JSTrap *trap;
+
+ code = script->code;
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (trap = (JSTrap *)rt->trapList.next;
+ &trap->links !=
+ &rt->trapList;
+ trap = (JSTrap *)trap->links.next) {
+ if (trap->script == script &&
+ (size_t)(trap->pc - script->code) < script->length) {
+ if (code == script->code) {
+ jssrcnote *sn, *notes;
+ size_t nbytes;
+
+ nbytes = script->length * sizeof(jsbytecode);
+ notes = SCRIPT_NOTES(script);
+ for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
+ continue;
+ nbytes += (sn - notes + 1) * sizeof *sn;
+
+ code = (jsbytecode *) JS_malloc(cx, nbytes);
+ if (!code)
+ break;
+ memcpy(code, script->code, nbytes);
+ JS_CLEAR_GSN_CACHE(cx);
+ }
+ code[trap->pc - script->code] = trap->op;
+ }
+ }
+ DBG_UNLOCK(rt);
+ return code;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
+ JSTrapHandler handler, void *closure)
+{
+ JSTrap *junk, *trap, *twin;
+ JSRuntime *rt;
+ uint32 sample;
+
+ JS_ASSERT((JSOp) *pc != JSOP_TRAP);
+ junk = NULL;
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ trap = FindTrap(rt, script, pc);
+ if (trap) {
+ JS_ASSERT(trap->script == script && trap->pc == pc);
+ JS_ASSERT(*pc == JSOP_TRAP);
+ } else {
+ sample = rt->debuggerMutations;
+ DBG_UNLOCK(rt);
+ trap = (JSTrap *) JS_malloc(cx, sizeof *trap);
+ if (!trap)
+ return JS_FALSE;
+ trap->closure = NULL;
+ if(!js_AddRoot(cx, &trap->closure, "trap->closure")) {
+ JS_free(cx, trap);
+ return JS_FALSE;
+ }
+ DBG_LOCK(rt);
+ twin = (rt->debuggerMutations != sample)
+ ? FindTrap(rt, script, pc)
+ : NULL;
+ if (twin) {
+ junk = trap;
+ trap = twin;
+ } else {
+ JS_APPEND_LINK(&trap->links, &rt->trapList);
+ ++rt->debuggerMutations;
+ trap->script = script;
+ trap->pc = pc;
+ trap->op = (JSOp)*pc;
+ *pc = JSOP_TRAP;
+ }
+ }
+ trap->handler = handler;
+ trap->closure = closure;
+ DBG_UNLOCK(rt);
+ if (junk) {
+ js_RemoveRoot(rt, &junk->closure);
+ JS_free(cx, junk);
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSOp)
+JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc)
+{
+ JSRuntime *rt;
+ JSTrap *trap;
+ JSOp op;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ trap = FindTrap(rt, script, pc);
+ op = trap ? trap->op : (JSOp) *pc;
+ DBG_UNLOCK(rt);
+ return op;
+}
+
+static void
+DestroyTrapAndUnlock(JSContext *cx, JSTrap *trap)
+{
+ ++cx->runtime->debuggerMutations;
+ JS_REMOVE_LINK(&trap->links);
+ *trap->pc = (jsbytecode)trap->op;
+ DBG_UNLOCK(cx->runtime);
+
+ js_RemoveRoot(cx->runtime, &trap->closure);
+ JS_free(cx, trap);
+}
+
+JS_PUBLIC_API(void)
+JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
+ JSTrapHandler *handlerp, void **closurep)
+{
+ JSTrap *trap;
+
+ DBG_LOCK(cx->runtime);
+ trap = FindTrap(cx->runtime, script, pc);
+ if (handlerp)
+ *handlerp = trap ? trap->handler : NULL;
+ if (closurep)
+ *closurep = trap ? trap->closure : NULL;
+ if (trap)
+ DestroyTrapAndUnlock(cx, trap);
+ else
+ DBG_UNLOCK(cx->runtime);
+}
+
+JS_PUBLIC_API(void)
+JS_ClearScriptTraps(JSContext *cx, JSScript *script)
+{
+ JSRuntime *rt;
+ JSTrap *trap, *next;
+ uint32 sample;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (trap = (JSTrap *)rt->trapList.next;
+ &trap->links != &rt->trapList;
+ trap = next) {
+ next = (JSTrap *)trap->links.next;
+ if (trap->script == script) {
+ sample = rt->debuggerMutations;
+ DestroyTrapAndUnlock(cx, trap);
+ DBG_LOCK(rt);
+ if (rt->debuggerMutations != sample + 1)
+ next = (JSTrap *)rt->trapList.next;
+ }
+ }
+ DBG_UNLOCK(rt);
+}
+
+JS_PUBLIC_API(void)
+JS_ClearAllTraps(JSContext *cx)
+{
+ JSRuntime *rt;
+ JSTrap *trap, *next;
+ uint32 sample;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (trap = (JSTrap *)rt->trapList.next;
+ &trap->links != &rt->trapList;
+ trap = next) {
+ next = (JSTrap *)trap->links.next;
+ sample = rt->debuggerMutations;
+ DestroyTrapAndUnlock(cx, trap);
+ DBG_LOCK(rt);
+ if (rt->debuggerMutations != sample + 1)
+ next = (JSTrap *)rt->trapList.next;
+ }
+ DBG_UNLOCK(rt);
+}
+
+JS_PUBLIC_API(JSTrapStatus)
+JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval)
+{
+ JSTrap *trap;
+ jsint op;
+ JSTrapStatus status;
+
+ DBG_LOCK(cx->runtime);
+ trap = FindTrap(cx->runtime, script, pc);
+ JS_ASSERT(!trap || trap->handler);
+ if (!trap) {
+ op = (JSOp) *pc;
+ DBG_UNLOCK(cx->runtime);
+
+ /* Defend against "pc for wrong script" API usage error. */
+ JS_ASSERT(op != JSOP_TRAP);
+
+#ifdef JS_THREADSAFE
+ /* If the API was abused, we must fail for want of the real op. */
+ if (op == JSOP_TRAP)
+ return JSTRAP_ERROR;
+
+ /* Assume a race with a debugger thread and try to carry on. */
+ *rval = INT_TO_JSVAL(op);
+ return JSTRAP_CONTINUE;
+#else
+ /* Always fail if single-threaded (must be an API usage error). */
+ return JSTRAP_ERROR;
+#endif
+ }
+ DBG_UNLOCK(cx->runtime);
+
+ /*
+ * It's important that we not use 'trap->' after calling the callback --
+ * the callback might remove the trap!
+ */
+ op = (jsint)trap->op;
+ status = trap->handler(cx, script, pc, rval, trap->closure);
+ if (status == JSTRAP_CONTINUE) {
+ /* By convention, return the true op to the interpreter in rval. */
+ *rval = INT_TO_JSVAL(op);
+ }
+ return status;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure)
+{
+ rt->globalDebugHooks.interruptHandler = handler;
+ rt->globalDebugHooks.interruptHandlerData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep)
+{
+ if (handlerp)
+ *handlerp = (JSTrapHandler)rt->globalDebugHooks.interruptHandler;
+ if (closurep)
+ *closurep = rt->globalDebugHooks.interruptHandlerData;
+ rt->globalDebugHooks.interruptHandler = 0;
+ rt->globalDebugHooks.interruptHandlerData = 0;
+ return JS_TRUE;
+}
+
+/************************************************************************/
+
+typedef struct JSWatchPoint {
+ JSCList links;
+ JSObject *object; /* weak link, see js_FinalizeObject */
+ JSScopeProperty *sprop;
+ JSPropertyOp setter;
+ JSWatchPointHandler handler;
+ void *closure;
+ uintN flags;
+} JSWatchPoint;
+
+#define JSWP_LIVE 0x1 /* live because set and not cleared */
+#define JSWP_HELD 0x2 /* held while running handler/setter */
+
+/*
+ * NB: DropWatchPointAndUnlock releases cx->runtime->debuggerLock in all cases.
+ */
+static JSBool
+DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag)
+{
+ JSBool ok, found;
+ JSScopeProperty *sprop;
+ JSScope *scope;
+ JSPropertyOp setter;
+
+ ok = JS_TRUE;
+ wp->flags &= ~flag;
+ if (wp->flags != 0) {
+ DBG_UNLOCK(cx->runtime);
+ return ok;
+ }
+
+ /*
+ * Remove wp from the list, then if there are no other watchpoints for
+ * wp->sprop in any scope, restore wp->sprop->setter from wp.
+ */
+ ++cx->runtime->debuggerMutations;
+ JS_REMOVE_LINK(&wp->links);
+ sprop = wp->sprop;
+
+ /*
+ * Passing null for the scope parameter tells js_GetWatchedSetter to find
+ * any watch point for sprop, and not to lock or unlock rt->debuggerLock.
+ * If js_ChangeNativePropertyAttrs fails, propagate failure after removing
+ * wp->closure's root and freeing wp.
+ */
+ setter = js_GetWatchedSetter(cx->runtime, NULL, sprop);
+ DBG_UNLOCK(cx->runtime);
+ if (!setter) {
+ JS_LOCK_OBJ(cx, wp->object);
+ scope = OBJ_SCOPE(wp->object);
+ found = (scope->object == wp->object &&
+ SCOPE_GET_PROPERTY(scope, sprop->id));
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ /*
+ * If the property wasn't found on wp->object or didn't exist, then
+ * someone else has dealt with this sprop, and we don't need to change
+ * the property attributes.
+ */
+ if (found) {
+ sprop = js_ChangeScopePropertyAttrs(cx, scope, sprop,
+ 0, sprop->attrs,
+ sprop->getter,
+ wp->setter);
+ if (!sprop)
+ ok = JS_FALSE;
+ }
+ }
+
+ JS_free(cx, wp);
+ return ok;
+}
+
+/*
+ * NB: js_TraceWatchPoints does not acquire cx->runtime->debuggerLock, since
+ * the debugger should never be racing with the GC (i.e., the debugger must
+ * respect the request model).
+ */
+void
+js_TraceWatchPoints(JSTracer *trc, JSObject *obj)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp;
+
+ rt = trc->context->runtime;
+
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = (JSWatchPoint *)wp->links.next) {
+ if (wp->object == obj) {
+ TRACE_SCOPE_PROPERTY(trc, wp->sprop);
+ if ((wp->sprop->attrs & JSPROP_SETTER) && wp->setter) {
+ JS_CALL_OBJECT_TRACER(trc, (JSObject *)wp->setter,
+ "wp->setter");
+ }
+ JS_SET_TRACING_NAME(trc, "wp->closure");
+ js_CallValueTracerIfGCThing(trc, (jsval) wp->closure);
+ }
+ }
+}
+
+void
+js_SweepWatchPoints(JSContext *cx)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp, *next;
+ uint32 sample;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = next) {
+ next = (JSWatchPoint *)wp->links.next;
+ if (js_IsAboutToBeFinalized(cx, wp->object)) {
+ sample = rt->debuggerMutations;
+
+ /* Ignore failures. */
+ DropWatchPointAndUnlock(cx, wp, JSWP_LIVE);
+ DBG_LOCK(rt);
+ if (rt->debuggerMutations != sample + 1)
+ next = (JSWatchPoint *)rt->watchPointList.next;
+ }
+ }
+ DBG_UNLOCK(rt);
+}
+
+
+
+/*
+ * NB: FindWatchPoint must be called with rt->debuggerLock acquired.
+ */
+static JSWatchPoint *
+FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id)
+{
+ JSWatchPoint *wp;
+
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = (JSWatchPoint *)wp->links.next) {
+ if (wp->object == scope->object && wp->sprop->id == id)
+ return wp;
+ }
+ return NULL;
+}
+
+JSScopeProperty *
+js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id)
+{
+ JSWatchPoint *wp;
+ JSScopeProperty *sprop;
+
+ DBG_LOCK(rt);
+ wp = FindWatchPoint(rt, scope, id);
+ sprop = wp ? wp->sprop : NULL;
+ DBG_UNLOCK(rt);
+ return sprop;
+}
+
+/*
+ * Secret handshake with DropWatchPointAndUnlock: if (!scope), we know our
+ * caller has acquired rt->debuggerLock, so we don't have to.
+ */
+JSPropertyOp
+js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
+ const JSScopeProperty *sprop)
+{
+ JSPropertyOp setter;
+ JSWatchPoint *wp;
+
+ setter = NULL;
+ if (scope)
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = (JSWatchPoint *)wp->links.next) {
+ if ((!scope || wp->object == scope->object) && wp->sprop == sprop) {
+ setter = wp->setter;
+ break;
+ }
+ }
+ if (scope)
+ DBG_UNLOCK(rt);
+ return setter;
+}
+
+JSBool
+js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp;
+ JSScopeProperty *sprop;
+ jsval propid, userid;
+ JSScope *scope;
+ JSBool ok;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = (JSWatchPoint *)wp->links.next) {
+ sprop = wp->sprop;
+ if (wp->object == obj && SPROP_USERID(sprop) == id &&
+ !(wp->flags & JSWP_HELD)) {
+ wp->flags |= JSWP_HELD;
+ DBG_UNLOCK(rt);
+
+ JS_LOCK_OBJ(cx, obj);
+ propid = ID_TO_VALUE(sprop->id);
+ userid = (sprop->flags & SPROP_HAS_SHORTID)
+ ? INT_TO_JSVAL(sprop->shortid)
+ : propid;
+ scope = OBJ_SCOPE(obj);
+ JS_UNLOCK_OBJ(cx, obj);
+
+ /* NB: wp is held, so we can safely dereference it still. */
+ ok = wp->handler(cx, obj, propid,
+ SPROP_HAS_VALID_SLOT(sprop, scope)
+ ? OBJ_GET_SLOT(cx, obj, sprop->slot)
+ : JSVAL_VOID,
+ vp, wp->closure);
+ if (ok) {
+ /*
+ * Create a pseudo-frame for the setter invocation so that any
+ * stack-walking security code under the setter will correctly
+ * identify the guilty party. So that the watcher appears to
+ * be active to obj_eval and other such code, point frame.pc
+ * at the JSOP_STOP at the end of the script.
+ *
+ * The pseudo-frame is not created for fast natives as they
+ * are treated as interpreter frame extensions and always
+ * trusted.
+ */
+ JSObject *closure;
+ JSClass *clasp;
+ JSFunction *fun;
+ JSScript *script;
+ JSBool injectFrame;
+ uintN nslots;
+ jsval smallv[5];
+ jsval *argv;
+ JSStackFrame frame;
+ JSFrameRegs regs;
+
+ closure = (JSObject *) wp->closure;
+ clasp = OBJ_GET_CLASS(cx, closure);
+ if (clasp == &js_FunctionClass) {
+ fun = GET_FUNCTION_PRIVATE(cx, closure);
+ script = FUN_SCRIPT(fun);
+ } else if (clasp == &js_ScriptClass) {
+ fun = NULL;
+ script = (JSScript *) JS_GetPrivate(cx, closure);
+ } else {
+ fun = NULL;
+ script = NULL;
+ }
+
+ nslots = 2;
+ injectFrame = JS_TRUE;
+ if (fun) {
+ nslots += FUN_MINARGS(fun);
+ if (!FUN_INTERPRETED(fun)) {
+ nslots += fun->u.n.extra;
+ injectFrame = !(fun->flags & JSFUN_FAST_NATIVE);
+ }
+ }
+
+ if (injectFrame) {
+ if (nslots <= JS_ARRAY_LENGTH(smallv)) {
+ argv = smallv;
+ } else {
+ argv = (jsval *) JS_malloc(cx, nslots * sizeof(jsval));
+ if (!argv) {
+ DBG_LOCK(rt);
+ DropWatchPointAndUnlock(cx, wp, JSWP_HELD);
+ return JS_FALSE;
+ }
+ }
+
+ argv[0] = OBJECT_TO_JSVAL(closure);
+ argv[1] = JSVAL_NULL;
+ memset(argv + 2, 0, (nslots - 2) * sizeof(jsval));
+
+ memset(&frame, 0, sizeof(frame));
+ frame.script = script;
+ frame.regs = NULL;
+ if (script) {
+ JS_ASSERT(script->length >= JSOP_STOP_LENGTH);
+ regs.pc = script->code + script->length
+ - JSOP_STOP_LENGTH;
+ regs.sp = NULL;
+ frame.regs = &regs;
+ }
+ frame.callee = closure;
+ frame.fun = fun;
+ frame.argv = argv + 2;
+ frame.down = cx->fp;
+ frame.scopeChain = OBJ_GET_PARENT(cx, closure);
+
+ cx->fp = &frame;
+ }
+#ifdef __GNUC__
+ else
+ argv = NULL; /* suppress bogus gcc warnings */
+#endif
+ ok = !wp->setter ||
+ ((sprop->attrs & JSPROP_SETTER)
+ ? js_InternalCall(cx, obj, OBJECT_TO_JSVAL(wp->setter),
+ 1, vp, vp)
+ : wp->setter(cx, OBJ_THIS_OBJECT(cx, obj), userid, vp));
+ if (injectFrame) {
+ /* Evil code can cause us to have an arguments object. */
+ if (frame.callobj)
+ ok &= js_PutCallObject(cx, &frame);
+ if (frame.argsobj)
+ ok &= js_PutArgsObject(cx, &frame);
+
+ cx->fp = frame.down;
+ if (argv != smallv)
+ JS_free(cx, argv);
+ }
+ }
+ DBG_LOCK(rt);
+ return DropWatchPointAndUnlock(cx, wp, JSWP_HELD) && ok;
+ }
+ }
+ DBG_UNLOCK(rt);
+ return JS_TRUE;
+}
+
+JSBool
+js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSObject *funobj;
+ JSFunction *wrapper;
+ jsval userid;
+
+ funobj = JSVAL_TO_OBJECT(argv[-2]);
+ JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass);
+ wrapper = GET_FUNCTION_PRIVATE(cx, funobj);
+ userid = ATOM_KEY(wrapper->atom);
+ *rval = argv[0];
+ return js_watch_set(cx, obj, userid, rval);
+}
+
+JSPropertyOp
+js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
+{
+ JSAtom *atom;
+ JSFunction *wrapper;
+
+ if (!(attrs & JSPROP_SETTER))
+ return &js_watch_set; /* & to silence schoolmarmish MSVC */
+
+ if (JSID_IS_ATOM(id)) {
+ atom = JSID_TO_ATOM(id);
+ } else if (JSID_IS_INT(id)) {
+ if (!js_ValueToStringId(cx, INT_JSID_TO_JSVAL(id), &id))
+ return NULL;
+ atom = JSID_TO_ATOM(id);
+ } else {
+ atom = NULL;
+ }
+ wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0,
+ OBJ_GET_PARENT(cx, (JSObject *)setter),
+ atom);
+ if (!wrapper)
+ return NULL;
+ return (JSPropertyOp) FUN_OBJECT(wrapper);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
+ JSWatchPointHandler handler, void *closure)
+{
+ jsid propid;
+ JSObject *pobj;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ JSRuntime *rt;
+ JSBool ok;
+ JSWatchPoint *wp;
+ JSPropertyOp watcher;
+
+ if (!OBJ_IS_NATIVE(obj)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH,
+ OBJ_GET_CLASS(cx, obj)->name);
+ return JS_FALSE;
+ }
+
+ if (JSVAL_IS_INT(idval))
+ propid = INT_JSVAL_TO_JSID(idval);
+ else if (!js_ValueToStringId(cx, idval, &propid))
+ return JS_FALSE;
+
+ if (!js_LookupProperty(cx, obj, propid, &pobj, &prop))
+ return JS_FALSE;
+ sprop = (JSScopeProperty *) prop;
+ rt = cx->runtime;
+ if (!sprop) {
+ /* Check for a deleted symbol watchpoint, which holds its property. */
+ sprop = js_FindWatchPoint(rt, OBJ_SCOPE(obj), propid);
+ if (!sprop) {
+ /* Make a new property in obj so we can watch for the first set. */
+ if (!js_DefineProperty(cx, obj, propid, JSVAL_VOID,
+ NULL, NULL, JSPROP_ENUMERATE,
+ &prop)) {
+ return JS_FALSE;
+ }
+ sprop = (JSScopeProperty *) prop;
+ }
+ } else if (pobj != obj) {
+ /* Clone the prototype property so we can watch the right object. */
+ jsval value;
+ JSPropertyOp getter, setter;
+ uintN attrs, flags;
+ intN shortid;
+
+ if (OBJ_IS_NATIVE(pobj)) {
+ value = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))
+ ? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot)
+ : JSVAL_VOID;
+ getter = sprop->getter;
+ setter = sprop->setter;
+ attrs = sprop->attrs;
+ flags = sprop->flags;
+ shortid = sprop->shortid;
+ } else {
+ if (!OBJ_GET_PROPERTY(cx, pobj, propid, &value) ||
+ !OBJ_GET_ATTRIBUTES(cx, pobj, propid, prop, &attrs)) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ return JS_FALSE;
+ }
+ getter = setter = NULL;
+ flags = 0;
+ shortid = 0;
+ }
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+
+ /* Recall that obj is native, whether or not pobj is native. */
+ if (!js_DefineNativeProperty(cx, obj, propid, value, getter, setter,
+ attrs, flags, shortid, &prop)) {
+ return JS_FALSE;
+ }
+ sprop = (JSScopeProperty *) prop;
+ }
+
+ /*
+ * At this point, prop/sprop exists in obj, obj is locked, and we must
+ * OBJ_DROP_PROPERTY(cx, obj, prop) before returning.
+ */
+ ok = JS_TRUE;
+ DBG_LOCK(rt);
+ wp = FindWatchPoint(rt, OBJ_SCOPE(obj), propid);
+ if (!wp) {
+ DBG_UNLOCK(rt);
+ watcher = js_WrapWatchedSetter(cx, propid, sprop->attrs, sprop->setter);
+ if (!watcher) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ wp = (JSWatchPoint *) JS_malloc(cx, sizeof *wp);
+ if (!wp) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ wp->handler = NULL;
+ wp->closure = NULL;
+ wp->object = obj;
+ JS_ASSERT(sprop->setter != js_watch_set || pobj != obj);
+ wp->setter = sprop->setter;
+ wp->flags = JSWP_LIVE;
+
+ /* XXXbe nest in obj lock here */
+ sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, 0, sprop->attrs,
+ sprop->getter, watcher);
+ if (!sprop) {
+ /* Self-link so DropWatchPointAndUnlock can JS_REMOVE_LINK it. */
+ JS_INIT_CLIST(&wp->links);
+ DBG_LOCK(rt);
+ DropWatchPointAndUnlock(cx, wp, JSWP_LIVE);
+ ok = JS_FALSE;
+ goto out;
+ }
+ wp->sprop = sprop;
+
+ /*
+ * Now that wp is fully initialized, append it to rt's wp list.
+ * Because obj is locked we know that no other thread could have added
+ * a watchpoint for (obj, propid).
+ */
+ DBG_LOCK(rt);
+ JS_ASSERT(!FindWatchPoint(rt, OBJ_SCOPE(obj), propid));
+ JS_APPEND_LINK(&wp->links, &rt->watchPointList);
+ ++rt->debuggerMutations;
+ }
+ wp->handler = handler;
+ wp->closure = closure;
+ DBG_UNLOCK(rt);
+
+out:
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id,
+ JSWatchPointHandler *handlerp, void **closurep)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = (JSWatchPoint *)wp->links.next) {
+ if (wp->object == obj && SPROP_USERID(wp->sprop) == id) {
+ if (handlerp)
+ *handlerp = wp->handler;
+ if (closurep)
+ *closurep = wp->closure;
+ return DropWatchPointAndUnlock(cx, wp, JSWP_LIVE);
+ }
+ }
+ DBG_UNLOCK(rt);
+ if (handlerp)
+ *handlerp = NULL;
+ if (closurep)
+ *closurep = NULL;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp, *next;
+ uint32 sample;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = next) {
+ next = (JSWatchPoint *)wp->links.next;
+ if (wp->object == obj) {
+ sample = rt->debuggerMutations;
+ if (!DropWatchPointAndUnlock(cx, wp, JSWP_LIVE))
+ return JS_FALSE;
+ DBG_LOCK(rt);
+ if (rt->debuggerMutations != sample + 1)
+ next = (JSWatchPoint *)rt->watchPointList.next;
+ }
+ }
+ DBG_UNLOCK(rt);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ClearAllWatchPoints(JSContext *cx)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp, *next;
+ uint32 sample;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = next) {
+ next = (JSWatchPoint *)wp->links.next;
+ sample = rt->debuggerMutations;
+ if (!DropWatchPointAndUnlock(cx, wp, JSWP_LIVE))
+ return JS_FALSE;
+ DBG_LOCK(rt);
+ if (rt->debuggerMutations != sample + 1)
+ next = (JSWatchPoint *)rt->watchPointList.next;
+ }
+ DBG_UNLOCK(rt);
+ return JS_TRUE;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(uintN)
+JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
+{
+ return js_PCToLineNumber(cx, script, pc);
+}
+
+JS_PUBLIC_API(jsbytecode *)
+JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
+{
+ return js_LineNumberToPC(script, lineno);
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
+{
+ return FUN_SCRIPT(fun);
+}
+
+JS_PUBLIC_API(JSNative)
+JS_GetFunctionNative(JSContext *cx, JSFunction *fun)
+{
+ return FUN_NATIVE(fun);
+}
+
+JS_PUBLIC_API(JSFastNative)
+JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun)
+{
+ return FUN_FAST_NATIVE(fun);
+}
+
+JS_PUBLIC_API(JSPrincipals *)
+JS_GetScriptPrincipals(JSContext *cx, JSScript *script)
+{
+ return script->principals;
+}
+
+/************************************************************************/
+
+/*
+ * Stack Frame Iterator
+ */
+JS_PUBLIC_API(JSStackFrame *)
+JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp)
+{
+ *iteratorp = (*iteratorp == NULL) ? cx->fp : (*iteratorp)->down;
+ return *iteratorp;
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_GetFrameScript(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->script;
+}
+
+JS_PUBLIC_API(jsbytecode *)
+JS_GetFramePC(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->regs ? fp->regs->pc : NULL;
+}
+
+JS_PUBLIC_API(JSStackFrame *)
+JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp)
+{
+ if (!fp)
+ fp = cx->fp;
+ while (fp) {
+ if (fp->script)
+ return fp;
+ fp = fp->down;
+ }
+ return NULL;
+}
+
+JS_PUBLIC_API(JSPrincipals *)
+JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
+{
+ JSSecurityCallbacks *callbacks;
+
+ if (fp->fun) {
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks && callbacks->findObjectPrincipals) {
+ if (FUN_OBJECT(fp->fun) != fp->callee)
+ return callbacks->findObjectPrincipals(cx, fp->callee);
+ /* FALL THROUGH */
+ }
+ }
+ if (fp->script)
+ return fp->script->principals;
+ return NULL;
+}
+
+JS_PUBLIC_API(JSPrincipals *)
+JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller)
+{
+ JSPrincipals *principals, *callerPrincipals;
+ JSSecurityCallbacks *callbacks;
+
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks && callbacks->findObjectPrincipals) {
+ principals = callbacks->findObjectPrincipals(cx, fp->callee);
+ } else {
+ principals = NULL;
+ }
+ if (!caller)
+ return principals;
+ callerPrincipals = JS_StackFramePrincipals(cx, caller);
+ return (callerPrincipals && principals &&
+ callerPrincipals->subsume(callerPrincipals, principals))
+ ? principals
+ : callerPrincipals;
+}
+
+JS_PUBLIC_API(void *)
+JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp)
+{
+ if (fp->annotation && fp->script) {
+ JSPrincipals *principals = JS_StackFramePrincipals(cx, fp);
+
+ if (principals && principals->globalPrivilegesEnabled(cx, principals)) {
+ /*
+ * Give out an annotation only if privileges have not been revoked
+ * or disabled globally.
+ */
+ return fp->annotation;
+ }
+ }
+
+ return NULL;
+}
+
+JS_PUBLIC_API(void)
+JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation)
+{
+ fp->annotation = annotation;
+}
+
+JS_PUBLIC_API(void *)
+JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp)
+{
+ JSPrincipals *principals;
+
+ principals = JS_StackFramePrincipals(cx, fp);
+ if (!principals)
+ return NULL;
+ return principals->getPrincipalArray(cx, principals);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp)
+{
+ return !fp->script;
+}
+
+/* this is deprecated, use JS_GetFrameScopeChain instead */
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameObject(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->scopeChain;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp)
+{
+ /* Force creation of argument and call objects if not yet created */
+ (void) JS_GetFrameCallObject(cx, fp);
+ return js_GetScopeChain(cx, fp);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp)
+{
+ if (! fp->fun)
+ return NULL;
+
+ /* Force creation of argument object if not yet created */
+ (void) js_GetArgsObject(cx, fp);
+
+ /*
+ * XXX ill-defined: null return here means error was reported, unlike a
+ * null returned above or in the #else
+ */
+ return js_GetCallObject(cx, fp, NULL);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameThis(JSContext *cx, JSStackFrame *fp)
+{
+ JSStackFrame *afp;
+
+ if (fp->flags & JSFRAME_COMPUTED_THIS)
+ return fp->thisp;
+
+ /* js_ComputeThis gets confused if fp != cx->fp, so set it aside. */
+ if (cx->fp != fp) {
+ afp = cx->fp;
+ if (afp) {
+ afp->dormantNext = cx->dormantFrameChain;
+ cx->dormantFrameChain = afp;
+ cx->fp = fp;
+ }
+ } else {
+ afp = NULL;
+ }
+
+ if (!fp->thisp && fp->argv)
+ fp->thisp = js_ComputeThis(cx, JS_TRUE, fp->argv);
+
+ if (afp) {
+ cx->fp = afp;
+ cx->dormantFrameChain = afp->dormantNext;
+ afp->dormantNext = NULL;
+ }
+
+ return fp->thisp;
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->fun;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fp)
+{
+ if (!fp->fun)
+ return NULL;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, fp->callee) == &js_FunctionClass);
+ JS_ASSERT(OBJ_GET_PRIVATE(cx, fp->callee) == fp->fun);
+ return fp->callee;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp)
+{
+ return (fp->flags & JSFRAME_CONSTRUCTING) != 0;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->callee;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
+{
+ return (fp->flags & JSFRAME_DEBUGGER) != 0;
+}
+
+JS_PUBLIC_API(jsval)
+JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->rval;
+}
+
+JS_PUBLIC_API(void)
+JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval)
+{
+ fp->rval = rval;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(const char *)
+JS_GetScriptFilename(JSContext *cx, JSScript *script)
+{
+ return script->filename;
+}
+
+JS_PUBLIC_API(uintN)
+JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script)
+{
+ return script->lineno;
+}
+
+JS_PUBLIC_API(uintN)
+JS_GetScriptLineExtent(JSContext *cx, JSScript *script)
+{
+ return js_GetScriptLineExtent(script);
+}
+
+JS_PUBLIC_API(JSVersion)
+JS_GetScriptVersion(JSContext *cx, JSScript *script)
+{
+ return (JSVersion) (script->version & JSVERSION_MASK);
+}
+
+/***************************************************************************/
+
+JS_PUBLIC_API(void)
+JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata)
+{
+ rt->globalDebugHooks.newScriptHook = hook;
+ rt->globalDebugHooks.newScriptHookData = callerdata;
+}
+
+JS_PUBLIC_API(void)
+JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
+ void *callerdata)
+{
+ rt->globalDebugHooks.destroyScriptHook = hook;
+ rt->globalDebugHooks.destroyScriptHookData = callerdata;
+}
+
+/***************************************************************************/
+
+JS_PUBLIC_API(JSBool)
+JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ JSObject *scobj;
+ JSScript *script;
+ JSBool ok;
+
+ scobj = JS_GetFrameScopeChain(cx, fp);
+ if (!scobj)
+ return JS_FALSE;
+
+ script = js_CompileScript(cx, scobj, fp, JS_StackFramePrincipals(cx, fp),
+ TCF_COMPILE_N_GO |
+ TCF_PUT_STATIC_DEPTH(fp->script->staticDepth + 1),
+ chars, length, NULL,
+ filename, lineno);
+ if (!script)
+ return JS_FALSE;
+
+ ok = js_Execute(cx, scobj, script, fp, JSFRAME_DEBUGGER | JSFRAME_EVAL,
+ rval);
+ js_DestroyScript(cx, script);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
+ const char *bytes, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ jschar *chars;
+ JSBool ok;
+ size_t len = length;
+
+ chars = js_InflateString(cx, bytes, &len);
+ if (!chars)
+ return JS_FALSE;
+ length = (uintN) len;
+ ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length, filename, lineno,
+ rval);
+ JS_free(cx, chars);
+
+ return ok;
+}
+
+/************************************************************************/
+
+/* XXXbe this all needs to be reworked to avoid requiring JSScope types. */
+
+JS_PUBLIC_API(JSScopeProperty *)
+JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp)
+{
+ JSScopeProperty *sprop;
+ JSScope *scope;
+
+ sprop = *iteratorp;
+ scope = OBJ_SCOPE(obj);
+
+ /* XXXbe minor(?) incompatibility: iterate in reverse definition order */
+ if (!sprop) {
+ sprop = SCOPE_LAST_PROP(scope);
+ } else {
+ while ((sprop = sprop->parent) != NULL) {
+ if (!SCOPE_HAD_MIDDLE_DELETE(scope))
+ break;
+ if (SCOPE_HAS_PROPERTY(scope, sprop))
+ break;
+ }
+ }
+ *iteratorp = sprop;
+ return sprop;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
+ JSPropertyDesc *pd)
+{
+ JSScope *scope;
+ JSScopeProperty *aprop;
+ jsval lastException;
+ JSBool wasThrowing;
+
+ pd->id = ID_TO_VALUE(sprop->id);
+
+ wasThrowing = cx->throwing;
+ if (wasThrowing) {
+ lastException = cx->exception;
+ if (JSVAL_IS_GCTHING(lastException) &&
+ !js_AddRoot(cx, &lastException, "lastException")) {
+ return JS_FALSE;
+ }
+ cx->throwing = JS_FALSE;
+ }
+
+ if (!js_GetProperty(cx, obj, sprop->id, &pd->value)) {
+ if (!cx->throwing) {
+ pd->flags = JSPD_ERROR;
+ pd->value = JSVAL_VOID;
+ } else {
+ pd->flags = JSPD_EXCEPTION;
+ pd->value = cx->exception;
+ }
+ } else {
+ pd->flags = 0;
+ }
+
+ cx->throwing = wasThrowing;
+ if (wasThrowing) {
+ cx->exception = lastException;
+ if (JSVAL_IS_GCTHING(lastException))
+ js_RemoveRoot(cx->runtime, &lastException);
+ }
+
+ pd->flags |= ((sprop->attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0)
+ | ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 0)
+ | ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0);
+ pd->spare = 0;
+ if (sprop->getter == js_GetCallArg) {
+ pd->slot = sprop->shortid;
+ pd->flags |= JSPD_ARGUMENT;
+ } else if (sprop->getter == js_GetCallVar) {
+ pd->slot = sprop->shortid;
+ pd->flags |= JSPD_VARIABLE;
+ } else {
+ pd->slot = 0;
+ }
+ pd->alias = JSVAL_VOID;
+ scope = OBJ_SCOPE(obj);
+ if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ for (aprop = SCOPE_LAST_PROP(scope); aprop; aprop = aprop->parent) {
+ if (aprop != sprop && aprop->slot == sprop->slot) {
+ pd->alias = ID_TO_VALUE(aprop->id);
+ break;
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
+{
+ JSClass *clasp;
+ JSScope *scope;
+ uint32 i, n;
+ JSPropertyDesc *pd;
+ JSScopeProperty *sprop;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (!OBJ_IS_NATIVE(obj) || (clasp->flags & JSCLASS_NEW_ENUMERATE)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_DESCRIBE_PROPS, clasp->name);
+ return JS_FALSE;
+ }
+ if (!clasp->enumerate(cx, obj))
+ return JS_FALSE;
+
+ /* have no props, or object's scope has not mutated from that of proto */
+ scope = OBJ_SCOPE(obj);
+ if (scope->object != obj || scope->entryCount == 0) {
+ pda->length = 0;
+ pda->array = NULL;
+ return JS_TRUE;
+ }
+
+ n = STOBJ_NSLOTS(obj);
+ if (n > scope->entryCount)
+ n = scope->entryCount;
+ pd = (JSPropertyDesc *) JS_malloc(cx, (size_t)n * sizeof(JSPropertyDesc));
+ if (!pd)
+ return JS_FALSE;
+ i = 0;
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
+ if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop))
+ continue;
+ if (!js_AddRoot(cx, &pd[i].id, NULL))
+ goto bad;
+ if (!js_AddRoot(cx, &pd[i].value, NULL))
+ goto bad;
+ if (!JS_GetPropertyDesc(cx, obj, sprop, &pd[i]))
+ goto bad;
+ if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL))
+ goto bad;
+ if (++i == n)
+ break;
+ }
+ pda->length = i;
+ pda->array = pd;
+ return JS_TRUE;
+
+bad:
+ pda->length = i + 1;
+ pda->array = pd;
+ JS_PutPropertyDescArray(cx, pda);
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(void)
+JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
+{
+ JSPropertyDesc *pd;
+ uint32 i;
+
+ pd = pda->array;
+ for (i = 0; i < pda->length; i++) {
+ js_RemoveRoot(cx->runtime, &pd[i].id);
+ js_RemoveRoot(cx->runtime, &pd[i].value);
+ if (pd[i].flags & JSPD_ALIAS)
+ js_RemoveRoot(cx->runtime, &pd[i].alias);
+ }
+ JS_free(cx, pd);
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(JSBool)
+JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure)
+{
+ rt->globalDebugHooks.debuggerHandler = handler;
+ rt->globalDebugHooks.debuggerHandlerData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure)
+{
+ rt->globalDebugHooks.sourceHandler = handler;
+ rt->globalDebugHooks.sourceHandlerData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
+{
+ rt->globalDebugHooks.executeHook = hook;
+ rt->globalDebugHooks.executeHookData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
+{
+ rt->globalDebugHooks.callHook = hook;
+ rt->globalDebugHooks.callHookData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure)
+{
+ rt->globalDebugHooks.objectHook = hook;
+ rt->globalDebugHooks.objectHookData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure)
+{
+ rt->globalDebugHooks.throwHook = hook;
+ rt->globalDebugHooks.throwHookData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure)
+{
+ rt->globalDebugHooks.debugErrorHook = hook;
+ rt->globalDebugHooks.debugErrorHookData = closure;
+ return JS_TRUE;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(size_t)
+JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
+{
+ size_t nbytes;
+ JSScope *scope;
+
+ nbytes = sizeof *obj;
+ if (obj->dslots) {
+ nbytes += ((uint32)obj->dslots[-1] - JS_INITIAL_NSLOTS + 1)
+ * sizeof obj->dslots[0];
+ }
+ if (OBJ_IS_NATIVE(obj)) {
+ scope = OBJ_SCOPE(obj);
+ if (scope->object == obj) {
+ nbytes += sizeof *scope;
+ nbytes += SCOPE_CAPACITY(scope) * sizeof(JSScopeProperty *);
+ }
+ }
+ return nbytes;
+}
+
+static size_t
+GetAtomTotalSize(JSContext *cx, JSAtom *atom)
+{
+ size_t nbytes;
+
+ nbytes = sizeof(JSAtom *) + sizeof(JSDHashEntryStub);
+ if (ATOM_IS_STRING(atom)) {
+ nbytes += sizeof(JSString);
+ nbytes += (JSFLATSTR_LENGTH(ATOM_TO_STRING(atom)) + 1) * sizeof(jschar);
+ } else if (ATOM_IS_DOUBLE(atom)) {
+ nbytes += sizeof(jsdouble);
+ }
+ return nbytes;
+}
+
+JS_PUBLIC_API(size_t)
+JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
+{
+ size_t nbytes;
+
+ nbytes = sizeof *fun;
+ nbytes += JS_GetObjectTotalSize(cx, FUN_OBJECT(fun));
+ if (FUN_INTERPRETED(fun))
+ nbytes += JS_GetScriptTotalSize(cx, fun->u.i.script);
+ if (fun->atom)
+ nbytes += GetAtomTotalSize(cx, fun->atom);
+ return nbytes;
+}
+
+#include "jsemit.h"
+
+JS_PUBLIC_API(size_t)
+JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
+{
+ size_t nbytes, pbytes;
+ jsatomid i;
+ jssrcnote *sn, *notes;
+ JSObjectArray *objarray;
+ JSPrincipals *principals;
+
+ nbytes = sizeof *script;
+ if (script->u.object)
+ nbytes += JS_GetObjectTotalSize(cx, script->u.object);
+
+ nbytes += script->length * sizeof script->code[0];
+ nbytes += script->atomMap.length * sizeof script->atomMap.vector[0];
+ for (i = 0; i < script->atomMap.length; i++)
+ nbytes += GetAtomTotalSize(cx, script->atomMap.vector[i]);
+
+ if (script->filename)
+ nbytes += strlen(script->filename) + 1;
+
+ notes = SCRIPT_NOTES(script);
+ for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
+ continue;
+ nbytes += (sn - notes + 1) * sizeof *sn;
+
+ if (script->objectsOffset != 0) {
+ objarray = JS_SCRIPT_OBJECTS(script);
+ i = objarray->length;
+ nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
+ do {
+ nbytes += JS_GetObjectTotalSize(cx, objarray->vector[--i]);
+ } while (i != 0);
+ }
+
+ if (script->regexpsOffset != 0) {
+ objarray = JS_SCRIPT_REGEXPS(script);
+ i = objarray->length;
+ nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
+ do {
+ nbytes += JS_GetObjectTotalSize(cx, objarray->vector[--i]);
+ } while (i != 0);
+ }
+
+ if (script->trynotesOffset != 0) {
+ nbytes += sizeof(JSTryNoteArray) +
+ JS_SCRIPT_TRYNOTES(script)->length * sizeof(JSTryNote);
+ }
+
+ principals = script->principals;
+ if (principals) {
+ JS_ASSERT(principals->refcount);
+ pbytes = sizeof *principals;
+ if (principals->refcount > 1)
+ pbytes = JS_HOWMANY(pbytes, principals->refcount);
+ nbytes += pbytes;
+ }
+
+ return nbytes;
+}
+
+JS_PUBLIC_API(uint32)
+JS_GetTopScriptFilenameFlags(JSContext *cx, JSStackFrame *fp)
+{
+ if (!fp)
+ fp = cx->fp;
+ while (fp) {
+ if (fp->script)
+ return JS_GetScriptFilenameFlags(fp->script);
+ fp = fp->down;
+ }
+ return 0;
+ }
+
+JS_PUBLIC_API(uint32)
+JS_GetScriptFilenameFlags(JSScript *script)
+{
+ JS_ASSERT(script);
+ if (!script->filename)
+ return JSFILENAME_NULL;
+ return js_GetScriptFilenameFlags(script->filename);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_FlagScriptFilenamePrefix(JSRuntime *rt, const char *prefix, uint32 flags)
+{
+ if (!js_SaveScriptFilenameRT(rt, prefix, flags))
+ return JS_FALSE;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsSystemObject(JSContext *cx, JSObject *obj)
+{
+ return STOBJ_IS_SYSTEM(obj);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, JSBool system)
+{
+ JSObject *obj;
+
+ obj = js_NewObject(cx, clasp, proto, parent, 0);
+ if (obj && system)
+ STOBJ_SET_SYSTEM(obj);
+ return obj;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(JSDebugHooks *)
+JS_GetGlobalDebugHooks(JSRuntime *rt)
+{
+ return &rt->globalDebugHooks;
+}
+
+JS_PUBLIC_API(JSDebugHooks *)
+JS_SetContextDebugHooks(JSContext *cx, JSDebugHooks *hooks)
+{
+ JSDebugHooks *old;
+
+ JS_ASSERT(hooks);
+ old = cx->debugHooks;
+ cx->debugHooks = hooks;
+ return old;
+}
+
+#ifdef MOZ_SHARK
+
+#include <CHUD/CHUD.h>
+
+JS_PUBLIC_API(JSBool)
+JS_StartChudRemote()
+{
+ if (chudIsRemoteAccessAcquired() &&
+ (chudStartRemotePerfMonitor("Mozilla") == chudSuccess)) {
+ return JS_TRUE;
+ }
+
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_StopChudRemote()
+{
+ if (chudIsRemoteAccessAcquired() &&
+ (chudStopRemotePerfMonitor() == chudSuccess)) {
+ return JS_TRUE;
+ }
+
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConnectShark()
+{
+ if (!chudIsInitialized() && (chudInitialize() != chudSuccess))
+ return JS_FALSE;
+
+ if (chudAcquireRemoteAccess() != chudSuccess)
+ return JS_FALSE;
+
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DisconnectShark()
+{
+ if (chudIsRemoteAccessAcquired() && (chudReleaseRemoteAccess() != chudSuccess))
+ return JS_FALSE;
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_StartShark(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ if (!JS_StartChudRemote()) {
+ JS_ReportError(cx, "Error starting CHUD.");
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_StopShark(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ if (!JS_StopChudRemote()) {
+ JS_ReportError(cx, "Error stopping CHUD.");
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ConnectShark(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ if (!JS_ConnectShark()) {
+ JS_ReportError(cx, "Error connecting to Shark.");
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_DisconnectShark(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ if (!JS_DisconnectShark()) {
+ JS_ReportError(cx, "Error disconnecting from Shark.");
+ }
+
+ return JS_TRUE;
+}
+
+#endif /* MOZ_SHARK */
+
+#ifdef MOZ_CALLGRIND
+
+#include <valgrind/callgrind.h>
+
+JS_FRIEND_API(JSBool)
+js_StartCallgrind(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ CALLGRIND_START_INSTRUMENTATION;
+ CALLGRIND_ZERO_STATS;
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_StopCallgrind(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ CALLGRIND_STOP_INSTRUMENTATION;
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_DumpCallgrind(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+ char *cstr;
+
+ if (argc > 0 && JSVAL_IS_STRING(argv[0])) {
+ str = JSVAL_TO_STRING(argv[0]);
+ cstr = js_DeflateString(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
+ if (cstr) {
+ CALLGRIND_DUMP_STATS_AT(cstr);
+ JS_free(cx, cstr);
+ return JS_TRUE;
+ }
+ }
+ CALLGRIND_DUMP_STATS;
+
+ return JS_TRUE;
+}
+
+#endif /* MOZ_CALLGRIND */
+
+#ifdef MOZ_VTUNE
+#include <VTuneApi.h>
+
+static const char *vtuneErrorMessages[] = {
+ "unknown, error #0",
+ "invalid 'max samples' field",
+ "invalid 'samples per buffer' field",
+ "invalid 'sample interval' field",
+ "invalid path",
+ "sample file in use",
+ "invalid 'number of events' field",
+ "unknown, error #7",
+ "internal error",
+ "bad event name",
+ "VTStopSampling called without calling VTStartSampling",
+ "no events selected for event-based sampling",
+ "events selected cannot be run together",
+ "no sampling parameters",
+ "sample database already exists",
+ "sampling already started",
+ "time-based sampling not supported",
+ "invalid 'sampling parameters size' field",
+ "invalid 'event size' field",
+ "sampling file already bound",
+ "invalid event path",
+ "invalid license",
+ "invalid 'global options' field",
+
+};
+
+JS_FRIEND_API(JSBool)
+js_StartVtune(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ VTUNE_EVENT events[] = {
+ { 1000000, 0, 0, 0, "CPU_CLK_UNHALTED.CORE" },
+ { 1000000, 0, 0, 0, "INST_RETIRED.ANY" },
+ };
+
+ U32 n_events = sizeof(events) / sizeof(VTUNE_EVENT);
+ char *default_filename = "mozilla-vtune.tb5";
+ JSString *str;
+ U32 status;
+
+ VTUNE_SAMPLING_PARAMS params = {
+ sizeof(VTUNE_SAMPLING_PARAMS),
+ sizeof(VTUNE_EVENT),
+ 0, 0, /* Reserved fields */
+ 1, /* Initialize in "paused" state */
+ 0, /* Max samples, or 0 for "continuous" */
+ 4096, /* Samples per buffer */
+ 0.1, /* Sampling interval in ms */
+ 1, /* 1 for event-based sampling, 0 for time-based */
+
+ n_events,
+ events,
+ default_filename,
+ };
+
+ if (argc > 0 && JSVAL_IS_STRING(argv[0])) {
+ str = JSVAL_TO_STRING(argv[0]);
+ params.tb5Filename = js_DeflateString(cx,
+ JSSTRING_CHARS(str),
+ JSSTRING_LENGTH(str));
+ }
+
+ status = VTStartSampling(&params);
+
+ if (params.tb5Filename != default_filename)
+ JS_free(cx, params.tb5Filename);
+
+ if (status != 0) {
+ if (status == VTAPI_MULTIPLE_RUNS)
+ VTStopSampling(0);
+ if (status < sizeof(vtuneErrorMessages))
+ JS_ReportError(cx, "Vtune setup error: %s",
+ vtuneErrorMessages[status]);
+ else
+ JS_ReportError(cx, "Vtune setup error: %d",
+ status);
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_StopVtune(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ U32 status = VTStopSampling(1);
+ if (status) {
+ if (status < sizeof(vtuneErrorMessages))
+ JS_ReportError(cx, "Vtune shutdown error: %s",
+ vtuneErrorMessages[status]);
+ else
+ JS_ReportError(cx, "Vtune shutdown error: %d",
+ status);
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_PauseVtune(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ VTPause();
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ResumeVtune(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ VTResume();
+ return JS_TRUE;
+}
+
+#endif /* MOZ_VTUNE */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.h b/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.h
new file mode 100644
index 0000000..b6855b2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.h
@@ -0,0 +1,500 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsdbgapi_h___
+#define jsdbgapi_h___
+/*
+ * JS debugger API.
+ */
+#include "jsapi.h"
+#include "jsopcode.h"
+#include "jsprvtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Unexported library-private helper used to unpatch all traps in a script.
+ * Returns script->code if script has no traps, else a JS_malloc'ed copy of
+ * script->code which the caller must JS_free, or null on JS_malloc OOM.
+ */
+extern jsbytecode *
+js_UntrapScriptCode(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
+ JSTrapHandler handler, void *closure);
+
+extern JS_PUBLIC_API(JSOp)
+JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc);
+
+extern JS_PUBLIC_API(void)
+JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
+ JSTrapHandler *handlerp, void **closurep);
+
+extern JS_PUBLIC_API(void)
+JS_ClearScriptTraps(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(void)
+JS_ClearAllTraps(JSContext *cx);
+
+extern JS_PUBLIC_API(JSTrapStatus)
+JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
+ JSWatchPointHandler handler, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id,
+ JSWatchPointHandler *handlerp, void **closurep);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ClearAllWatchPoints(JSContext *cx);
+
+#ifdef JS_HAS_OBJ_WATCHPOINT
+/*
+ * Hide these non-API function prototypes by testing whether the internal
+ * header file "jsversion.h" has been included.
+ */
+extern void
+js_TraceWatchPoints(JSTracer *trc, JSObject *obj);
+
+extern void
+js_SweepWatchPoints(JSContext *cx);
+
+extern JSScopeProperty *
+js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id);
+
+/*
+ * NB: callers outside of jsdbgapi.c must pass non-null scope.
+ */
+extern JSPropertyOp
+js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
+ const JSScopeProperty *sprop);
+
+extern JSBool
+js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+extern JSBool
+js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JSPropertyOp
+js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter);
+
+#endif /* JS_HAS_OBJ_WATCHPOINT */
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(uintN)
+JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
+
+extern JS_PUBLIC_API(jsbytecode *)
+JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_GetFunctionScript(JSContext *cx, JSFunction *fun);
+
+extern JS_PUBLIC_API(JSNative)
+JS_GetFunctionNative(JSContext *cx, JSFunction *fun);
+
+extern JS_PUBLIC_API(JSFastNative)
+JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun);
+
+extern JS_PUBLIC_API(JSPrincipals *)
+JS_GetScriptPrincipals(JSContext *cx, JSScript *script);
+
+/*
+ * Stack Frame Iterator
+ *
+ * Used to iterate through the JS stack frames to extract
+ * information from the frames.
+ */
+
+extern JS_PUBLIC_API(JSStackFrame *)
+JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_GetFrameScript(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(jsbytecode *)
+JS_GetFramePC(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * Get the closest scripted frame below fp. If fp is null, start from cx->fp.
+ */
+extern JS_PUBLIC_API(JSStackFrame *)
+JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * Return a weak reference to fp's principals. A null return does not denote
+ * an error, it means there are no principals.
+ */
+extern JS_PUBLIC_API(JSPrincipals *)
+JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * This API is like JS_StackFramePrincipals(cx, caller), except that if
+ * cx->runtime->findObjectPrincipals is non-null, it returns the weaker of
+ * the caller's principals and the object principals of fp's callee function
+ * object (fp->argv[-2]), which is eval, Function, or a similar eval-like
+ * method. The caller parameter should be JS_GetScriptedCaller(cx, fp).
+ *
+ * All eval-like methods must use JS_EvalFramePrincipals to acquire a weak
+ * reference to the correct principals for the eval call to be secure, given
+ * an embedding that calls JS_SetObjectPrincipalsFinder (see jsapi.h).
+ */
+extern JS_PUBLIC_API(JSPrincipals *)
+JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller);
+
+extern JS_PUBLIC_API(void *)
+JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(void)
+JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
+
+extern JS_PUBLIC_API(void *)
+JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp);
+
+/* this is deprecated, use JS_GetFrameScopeChain instead */
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameObject(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameThis(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fp);
+
+/* XXXrginda Initially published with typo */
+#define JS_IsContructorFrame JS_IsConstructorFrame
+extern JS_PUBLIC_API(JSBool)
+JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(jsval)
+JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(void)
+JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval);
+
+/**
+ * Return fp's callee function object (fp->callee) if it has one.
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(const char *)
+JS_GetScriptFilename(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(uintN)
+JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(uintN)
+JS_GetScriptLineExtent(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(JSVersion)
+JS_GetScriptVersion(JSContext *cx, JSScript *script);
+
+/************************************************************************/
+
+/*
+ * Hook setters for script creation and destruction, see jsprvtd.h for the
+ * typedefs. These macros provide binary compatibility and newer, shorter
+ * synonyms.
+ */
+#define JS_SetNewScriptHook JS_SetNewScriptHookProc
+#define JS_SetDestroyScriptHook JS_SetDestroyScriptHookProc
+
+extern JS_PUBLIC_API(void)
+JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata);
+
+extern JS_PUBLIC_API(void)
+JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
+ void *callerdata);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
+ const char *bytes, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+/************************************************************************/
+
+typedef struct JSPropertyDesc {
+ jsval id; /* primary id, a string or int */
+ jsval value; /* property value */
+ uint8 flags; /* flags, see below */
+ uint8 spare; /* unused */
+ uint16 slot; /* argument/variable slot */
+ jsval alias; /* alias id if JSPD_ALIAS flag */
+} JSPropertyDesc;
+
+#define JSPD_ENUMERATE 0x01 /* visible to for/in loop */
+#define JSPD_READONLY 0x02 /* assignment is error */
+#define JSPD_PERMANENT 0x04 /* property cannot be deleted */
+#define JSPD_ALIAS 0x08 /* property has an alias id */
+#define JSPD_ARGUMENT 0x10 /* argument to function */
+#define JSPD_VARIABLE 0x20 /* local variable in function */
+#define JSPD_EXCEPTION 0x40 /* exception occurred fetching the property, */
+ /* value is exception */
+#define JSPD_ERROR 0x80 /* native getter returned JS_FALSE without */
+ /* throwing an exception */
+
+typedef struct JSPropertyDescArray {
+ uint32 length; /* number of elements in array */
+ JSPropertyDesc *array; /* alloc'd by Get, freed by Put */
+} JSPropertyDescArray;
+
+extern JS_PUBLIC_API(JSScopeProperty *)
+JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
+ JSPropertyDesc *pd);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda);
+
+extern JS_PUBLIC_API(void)
+JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(size_t)
+JS_GetObjectTotalSize(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(size_t)
+JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun);
+
+extern JS_PUBLIC_API(size_t)
+JS_GetScriptTotalSize(JSContext *cx, JSScript *script);
+
+/*
+ * Get the top-most running script on cx starting from fp, or from the top of
+ * cx's frame stack if fp is null, and return its script filename flags. If
+ * the script has a null filename member, return JSFILENAME_NULL.
+ */
+extern JS_PUBLIC_API(uint32)
+JS_GetTopScriptFilenameFlags(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * Get the script filename flags for the script. If the script doesn't have a
+ * filename, return JSFILENAME_NULL.
+ */
+extern JS_PUBLIC_API(uint32)
+JS_GetScriptFilenameFlags(JSScript *script);
+
+/*
+ * Associate flags with a script filename prefix in rt, so that any subsequent
+ * script compilation will inherit those flags if the script's filename is the
+ * same as prefix, or if prefix is a substring of the script's filename.
+ *
+ * The API defines only one flag bit, JSFILENAME_SYSTEM, leaving the remaining
+ * 31 bits up to the API client to define. The union of all 32 bits must not
+ * be a legal combination, however, in order to preserve JSFILENAME_NULL as a
+ * unique value. API clients may depend on JSFILENAME_SYSTEM being a set bit
+ * in JSFILENAME_NULL -- a script with a null filename member is presumed to
+ * be a "system" script.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_FlagScriptFilenamePrefix(JSRuntime *rt, const char *prefix, uint32 flags);
+
+#define JSFILENAME_NULL 0xffffffff /* null script filename */
+#define JSFILENAME_SYSTEM 0x00000001 /* "system" script, see below */
+#define JSFILENAME_PROTECTED 0x00000002 /* scripts need protection */
+
+/*
+ * Return true if obj is a "system" object, that is, one created by
+ * JS_NewSystemObject with the system flag set and not JS_NewObject.
+ *
+ * What "system" means is up to the API client, but it can be used to implement
+ * access control policies based on script filenames and their prefixes, using
+ * JS_FlagScriptFilenamePrefix and JS_GetTopScriptFilenameFlags.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_IsSystemObject(JSContext *cx, JSObject *obj);
+
+/*
+ * Call JS_NewObject(cx, clasp, proto, parent) and, if system is true, mark the
+ * result as a system object, that is an object for which JS_IsSystemObject
+ * returns true.
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, JSBool system);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(JSDebugHooks *)
+JS_GetGlobalDebugHooks(JSRuntime *rt);
+
+extern JS_PUBLIC_API(JSDebugHooks *)
+JS_SetContextDebugHooks(JSContext *cx, JSDebugHooks *hooks);
+
+#ifdef MOZ_SHARK
+
+extern JS_PUBLIC_API(JSBool)
+JS_StartChudRemote();
+
+extern JS_PUBLIC_API(JSBool)
+JS_StopChudRemote();
+
+extern JS_PUBLIC_API(JSBool)
+JS_ConnectShark();
+
+extern JS_PUBLIC_API(JSBool)
+JS_DisconnectShark();
+
+extern JS_FRIEND_API(JSBool)
+js_StopShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_StartShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_ConnectShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_DisconnectShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+#endif /* MOZ_SHARK */
+
+#ifdef MOZ_CALLGRIND
+
+extern JS_FRIEND_API(JSBool)
+js_StopCallgrind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_StartCallgrind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_DumpCallgrind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+#endif /* MOZ_CALLGRIND */
+
+#ifdef MOZ_VTUNE
+
+extern JS_FRIEND_API(JSBool)
+js_StartVtune(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_StopVtune(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_PauseVtune(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_ResumeVtune(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+#endif /* MOZ_VTUNE */
+
+JS_END_EXTERN_C
+
+#endif /* jsdbgapi_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.cpp
new file mode 100644
index 0000000..58cd440
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.cpp
@@ -0,0 +1,876 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla JavaScript code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (Original Author)
+ * Chris Waterson <waterson@netscape.com>
+ * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Double hashing implementation.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jsbit.h"
+#include "jsdhash.h"
+#include "jsutil.h" /* for JS_ASSERT */
+
+#ifdef JS_DHASHMETER
+# if defined MOZILLA_CLIENT && defined DEBUG_XXXbrendan
+# include "nsTraceMalloc.h"
+# endif
+# define METER(x) x
+#else
+# define METER(x) /* nothing */
+#endif
+
+/*
+ * The following DEBUG-only code is used to assert that calls to one of
+ * table->ops or to an enumerator do not cause re-entry into a call that
+ * can mutate the table. The recursion level is stored in additional
+ * space allocated at the end of the entry store to avoid changing
+ * JSDHashTable, which could cause issues when mixing DEBUG and
+ * non-DEBUG components.
+ */
+#ifdef DEBUG
+
+#define JSDHASH_ONELINE_ASSERT JS_ASSERT
+#define RECURSION_LEVEL(table_) (*(uint32*)(table_->entryStore + \
+ JS_DHASH_TABLE_SIZE(table_) * \
+ table_->entrySize))
+
+#define ENTRY_STORE_EXTRA sizeof(uint32)
+#define INCREMENT_RECURSION_LEVEL(table_) \
+ JS_BEGIN_MACRO \
+ ++RECURSION_LEVEL(table_); \
+ JS_END_MACRO
+#define DECREMENT_RECURSION_LEVEL(table_) \
+ JS_BEGIN_MACRO \
+ JSDHASH_ONELINE_ASSERT(RECURSION_LEVEL(table_) > 0); \
+ --RECURSION_LEVEL(table_); \
+ JS_END_MACRO
+
+#else
+
+#define ENTRY_STORE_EXTRA 0
+#define INCREMENT_RECURSION_LEVEL(table_) JS_BEGIN_MACRO JS_END_MACRO
+#define DECREMENT_RECURSION_LEVEL(table_) JS_BEGIN_MACRO JS_END_MACRO
+
+#endif /* defined(DEBUG) */
+
+JS_PUBLIC_API(void *)
+JS_DHashAllocTable(JSDHashTable *table, uint32 nbytes)
+{
+ return malloc(nbytes);
+}
+
+JS_PUBLIC_API(void)
+JS_DHashFreeTable(JSDHashTable *table, void *ptr)
+{
+ free(ptr);
+}
+
+JS_PUBLIC_API(JSDHashNumber)
+JS_DHashStringKey(JSDHashTable *table, const void *key)
+{
+ JSDHashNumber h;
+ const unsigned char *s;
+
+ h = 0;
+ for (s = (const unsigned char *) key; *s != '\0'; s++)
+ h = JS_ROTATE_LEFT32(h, 4) ^ *s;
+ return h;
+}
+
+JS_PUBLIC_API(JSDHashNumber)
+JS_DHashVoidPtrKeyStub(JSDHashTable *table, const void *key)
+{
+ return (JSDHashNumber)(unsigned long)key >> 2;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DHashMatchEntryStub(JSDHashTable *table,
+ const JSDHashEntryHdr *entry,
+ const void *key)
+{
+ const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry;
+
+ return stub->key == key;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DHashMatchStringKey(JSDHashTable *table,
+ const JSDHashEntryHdr *entry,
+ const void *key)
+{
+ const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry;
+
+ /* XXX tolerate null keys on account of sloppy Mozilla callers. */
+ return stub->key == key ||
+ (stub->key && key &&
+ strcmp((const char *) stub->key, (const char *) key) == 0);
+}
+
+JS_PUBLIC_API(void)
+JS_DHashMoveEntryStub(JSDHashTable *table,
+ const JSDHashEntryHdr *from,
+ JSDHashEntryHdr *to)
+{
+ memcpy(to, from, table->entrySize);
+}
+
+JS_PUBLIC_API(void)
+JS_DHashClearEntryStub(JSDHashTable *table, JSDHashEntryHdr *entry)
+{
+ memset(entry, 0, table->entrySize);
+}
+
+JS_PUBLIC_API(void)
+JS_DHashFreeStringKey(JSDHashTable *table, JSDHashEntryHdr *entry)
+{
+ const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry;
+
+ free((void *) stub->key);
+ memset(entry, 0, table->entrySize);
+}
+
+JS_PUBLIC_API(void)
+JS_DHashFinalizeStub(JSDHashTable *table)
+{
+}
+
+static const JSDHashTableOps stub_ops = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ JS_DHashVoidPtrKeyStub,
+ JS_DHashMatchEntryStub,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+JS_PUBLIC_API(const JSDHashTableOps *)
+JS_DHashGetStubOps(void)
+{
+ return &stub_ops;
+}
+
+JS_PUBLIC_API(JSDHashTable *)
+JS_NewDHashTable(const JSDHashTableOps *ops, void *data, uint32 entrySize,
+ uint32 capacity)
+{
+ JSDHashTable *table;
+
+ table = (JSDHashTable *) malloc(sizeof *table);
+ if (!table)
+ return NULL;
+ if (!JS_DHashTableInit(table, ops, data, entrySize, capacity)) {
+ free(table);
+ return NULL;
+ }
+ return table;
+}
+
+JS_PUBLIC_API(void)
+JS_DHashTableDestroy(JSDHashTable *table)
+{
+ JS_DHashTableFinish(table);
+ free(table);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DHashTableInit(JSDHashTable *table, const JSDHashTableOps *ops, void *data,
+ uint32 entrySize, uint32 capacity)
+{
+ int log2;
+ uint32 nbytes;
+
+#ifdef DEBUG
+ if (entrySize > 10 * sizeof(void *)) {
+ fprintf(stderr,
+ "jsdhash: for the table at address %p, the given entrySize"
+ " of %lu %s favors chaining over double hashing.\n",
+ (void *) table,
+ (unsigned long) entrySize,
+ (entrySize > 16 * sizeof(void*)) ? "definitely" : "probably");
+ }
+#endif
+
+ table->ops = ops;
+ table->data = data;
+ if (capacity < JS_DHASH_MIN_SIZE)
+ capacity = JS_DHASH_MIN_SIZE;
+
+ JS_CEILING_LOG2(log2, capacity);
+
+ capacity = JS_BIT(log2);
+ if (capacity >= JS_DHASH_SIZE_LIMIT)
+ return JS_FALSE;
+ table->hashShift = JS_DHASH_BITS - log2;
+ table->maxAlphaFrac = (uint8)(0x100 * JS_DHASH_DEFAULT_MAX_ALPHA);
+ table->minAlphaFrac = (uint8)(0x100 * JS_DHASH_DEFAULT_MIN_ALPHA);
+ table->entrySize = entrySize;
+ table->entryCount = table->removedCount = 0;
+ table->generation = 0;
+ nbytes = capacity * entrySize;
+
+ table->entryStore = (char *) ops->allocTable(table,
+ nbytes + ENTRY_STORE_EXTRA);
+ if (!table->entryStore)
+ return JS_FALSE;
+ memset(table->entryStore, 0, nbytes);
+ METER(memset(&table->stats, 0, sizeof table->stats));
+
+#ifdef DEBUG
+ RECURSION_LEVEL(table) = 0;
+#endif
+
+ return JS_TRUE;
+}
+
+/*
+ * Compute max and min load numbers (entry counts) from table params.
+ */
+#define MAX_LOAD(table, size) (((table)->maxAlphaFrac * (size)) >> 8)
+#define MIN_LOAD(table, size) (((table)->minAlphaFrac * (size)) >> 8)
+
+JS_PUBLIC_API(void)
+JS_DHashTableSetAlphaBounds(JSDHashTable *table,
+ float maxAlpha,
+ float minAlpha)
+{
+ uint32 size;
+
+ /*
+ * Reject obviously insane bounds, rather than trying to guess what the
+ * buggy caller intended.
+ */
+ JS_ASSERT(0.5 <= maxAlpha && maxAlpha < 1 && 0 <= minAlpha);
+ if (maxAlpha < 0.5 || 1 <= maxAlpha || minAlpha < 0)
+ return;
+
+ /*
+ * Ensure that at least one entry will always be free. If maxAlpha at
+ * minimum size leaves no entries free, reduce maxAlpha based on minimum
+ * size and the precision limit of maxAlphaFrac's fixed point format.
+ */
+ JS_ASSERT(JS_DHASH_MIN_SIZE - (maxAlpha * JS_DHASH_MIN_SIZE) >= 1);
+ if (JS_DHASH_MIN_SIZE - (maxAlpha * JS_DHASH_MIN_SIZE) < 1) {
+ maxAlpha = (float)
+ (JS_DHASH_MIN_SIZE - JS_MAX(JS_DHASH_MIN_SIZE / 256, 1))
+ / JS_DHASH_MIN_SIZE;
+ }
+
+ /*
+ * Ensure that minAlpha is strictly less than half maxAlpha. Take care
+ * not to truncate an entry's worth of alpha when storing in minAlphaFrac
+ * (8-bit fixed point format).
+ */
+ JS_ASSERT(minAlpha < maxAlpha / 2);
+ if (minAlpha >= maxAlpha / 2) {
+ size = JS_DHASH_TABLE_SIZE(table);
+ minAlpha = (size * maxAlpha - JS_MAX(size / 256, 1)) / (2 * size);
+ }
+
+ table->maxAlphaFrac = (uint8)(maxAlpha * 256);
+ table->minAlphaFrac = (uint8)(minAlpha * 256);
+}
+
+/*
+ * Double hashing needs the second hash code to be relatively prime to table
+ * size, so we simply make hash2 odd.
+ */
+#define HASH1(hash0, shift) ((hash0) >> (shift))
+#define HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1)
+
+/*
+ * Reserve keyHash 0 for free entries and 1 for removed-entry sentinels. Note
+ * that a removed-entry sentinel need be stored only if the removed entry had
+ * a colliding entry added after it. Therefore we can use 1 as the collision
+ * flag in addition to the removed-entry sentinel value. Multiplicative hash
+ * uses the high order bits of keyHash, so this least-significant reservation
+ * should not hurt the hash function's effectiveness much.
+ *
+ * If you change any of these magic numbers, also update JS_DHASH_ENTRY_IS_LIVE
+ * in jsdhash.h. It used to be private to jsdhash.c, but then became public to
+ * assist iterator writers who inspect table->entryStore directly.
+ */
+#define COLLISION_FLAG ((JSDHashNumber) 1)
+#define MARK_ENTRY_FREE(entry) ((entry)->keyHash = 0)
+#define MARK_ENTRY_REMOVED(entry) ((entry)->keyHash = 1)
+#define ENTRY_IS_REMOVED(entry) ((entry)->keyHash == 1)
+#define ENTRY_IS_LIVE(entry) JS_DHASH_ENTRY_IS_LIVE(entry)
+#define ENSURE_LIVE_KEYHASH(hash0) if (hash0 < 2) hash0 -= 2; else (void)0
+
+/* Match an entry's keyHash against an unstored one computed from a key. */
+#define MATCH_ENTRY_KEYHASH(entry,hash0) \
+ (((entry)->keyHash & ~COLLISION_FLAG) == (hash0))
+
+/* Compute the address of the indexed entry in table. */
+#define ADDRESS_ENTRY(table, index) \
+ ((JSDHashEntryHdr *)((table)->entryStore + (index) * (table)->entrySize))
+
+JS_PUBLIC_API(void)
+JS_DHashTableFinish(JSDHashTable *table)
+{
+ char *entryAddr, *entryLimit;
+ uint32 entrySize;
+ JSDHashEntryHdr *entry;
+
+#ifdef DEBUG_XXXbrendan
+ static FILE *dumpfp = NULL;
+ if (!dumpfp) dumpfp = fopen("/tmp/jsdhash.bigdump", "w");
+ if (dumpfp) {
+#ifdef MOZILLA_CLIENT
+ NS_TraceStack(1, dumpfp);
+#endif
+ JS_DHashTableDumpMeter(table, NULL, dumpfp);
+ fputc('\n', dumpfp);
+ }
+#endif
+
+ INCREMENT_RECURSION_LEVEL(table);
+
+ /* Call finalize before clearing entries, so it can enumerate them. */
+ table->ops->finalize(table);
+
+ /* Clear any remaining live entries. */
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ entryLimit = entryAddr + JS_DHASH_TABLE_SIZE(table) * entrySize;
+ while (entryAddr < entryLimit) {
+ entry = (JSDHashEntryHdr *)entryAddr;
+ if (ENTRY_IS_LIVE(entry)) {
+ METER(table->stats.removeEnums++);
+ table->ops->clearEntry(table, entry);
+ }
+ entryAddr += entrySize;
+ }
+
+ DECREMENT_RECURSION_LEVEL(table);
+ JS_ASSERT(RECURSION_LEVEL(table) == 0);
+
+ /* Free entry storage last. */
+ table->ops->freeTable(table, table->entryStore);
+}
+
+static JSDHashEntryHdr * JS_DHASH_FASTCALL
+SearchTable(JSDHashTable *table, const void *key, JSDHashNumber keyHash,
+ JSDHashOperator op)
+{
+ JSDHashNumber hash1, hash2;
+ int hashShift, sizeLog2;
+ JSDHashEntryHdr *entry, *firstRemoved;
+ JSDHashMatchEntry matchEntry;
+ uint32 sizeMask;
+
+ METER(table->stats.searches++);
+ JS_ASSERT(!(keyHash & COLLISION_FLAG));
+
+ /* Compute the primary hash address. */
+ hashShift = table->hashShift;
+ hash1 = HASH1(keyHash, hashShift);
+ entry = ADDRESS_ENTRY(table, hash1);
+
+ /* Miss: return space for a new entry. */
+ if (JS_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return entry;
+ }
+
+ /* Hit: return entry. */
+ matchEntry = table->ops->matchEntry;
+ if (MATCH_ENTRY_KEYHASH(entry, keyHash) && matchEntry(table, entry, key)) {
+ METER(table->stats.hits++);
+ return entry;
+ }
+
+ /* Collision: double hash. */
+ sizeLog2 = JS_DHASH_BITS - table->hashShift;
+ hash2 = HASH2(keyHash, sizeLog2, hashShift);
+ sizeMask = JS_BITMASK(sizeLog2);
+
+ /* Save the first removed entry pointer so JS_DHASH_ADD can recycle it. */
+ firstRemoved = NULL;
+
+ for (;;) {
+ if (JS_UNLIKELY(ENTRY_IS_REMOVED(entry))) {
+ if (!firstRemoved)
+ firstRemoved = entry;
+ } else {
+ if (op == JS_DHASH_ADD)
+ entry->keyHash |= COLLISION_FLAG;
+ }
+
+ METER(table->stats.steps++);
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+
+ entry = ADDRESS_ENTRY(table, hash1);
+ if (JS_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return (firstRemoved && op == JS_DHASH_ADD) ? firstRemoved : entry;
+ }
+
+ if (MATCH_ENTRY_KEYHASH(entry, keyHash) &&
+ matchEntry(table, entry, key)) {
+ METER(table->stats.hits++);
+ return entry;
+ }
+ }
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+/*
+ * This is a copy of SearchTable, used by ChangeTable, hardcoded to
+ * 1. assume |op == PL_DHASH_ADD|,
+ * 2. assume that |key| will never match an existing entry, and
+ * 3. assume that no entries have been removed from the current table
+ * structure.
+ * Avoiding the need for |key| means we can avoid needing a way to map
+ * entries to keys, which means callers can use complex key types more
+ * easily.
+ */
+static JSDHashEntryHdr * JS_DHASH_FASTCALL
+FindFreeEntry(JSDHashTable *table, JSDHashNumber keyHash)
+{
+ JSDHashNumber hash1, hash2;
+ int hashShift, sizeLog2;
+ JSDHashEntryHdr *entry;
+ uint32 sizeMask;
+
+ METER(table->stats.searches++);
+ JS_ASSERT(!(keyHash & COLLISION_FLAG));
+
+ /* Compute the primary hash address. */
+ hashShift = table->hashShift;
+ hash1 = HASH1(keyHash, hashShift);
+ entry = ADDRESS_ENTRY(table, hash1);
+
+ /* Miss: return space for a new entry. */
+ if (JS_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return entry;
+ }
+
+ /* Collision: double hash. */
+ sizeLog2 = JS_DHASH_BITS - table->hashShift;
+ hash2 = HASH2(keyHash, sizeLog2, hashShift);
+ sizeMask = JS_BITMASK(sizeLog2);
+
+ for (;;) {
+ JS_ASSERT(!ENTRY_IS_REMOVED(entry));
+ entry->keyHash |= COLLISION_FLAG;
+
+ METER(table->stats.steps++);
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+
+ entry = ADDRESS_ENTRY(table, hash1);
+ if (JS_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return entry;
+ }
+ }
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+static JSBool
+ChangeTable(JSDHashTable *table, int deltaLog2)
+{
+ int oldLog2, newLog2;
+ uint32 oldCapacity, newCapacity;
+ char *newEntryStore, *oldEntryStore, *oldEntryAddr;
+ uint32 entrySize, i, nbytes;
+ JSDHashEntryHdr *oldEntry, *newEntry;
+ JSDHashMoveEntry moveEntry;
+#ifdef DEBUG
+ uint32 recursionLevel;
+#endif
+
+ /* Look, but don't touch, until we succeed in getting new entry store. */
+ oldLog2 = JS_DHASH_BITS - table->hashShift;
+ newLog2 = oldLog2 + deltaLog2;
+ oldCapacity = JS_BIT(oldLog2);
+ newCapacity = JS_BIT(newLog2);
+ if (newCapacity >= JS_DHASH_SIZE_LIMIT)
+ return JS_FALSE;
+ entrySize = table->entrySize;
+ nbytes = newCapacity * entrySize;
+
+ newEntryStore = (char *) table->ops->allocTable(table,
+ nbytes + ENTRY_STORE_EXTRA);
+ if (!newEntryStore)
+ return JS_FALSE;
+
+ /* We can't fail from here on, so update table parameters. */
+#ifdef DEBUG
+ recursionLevel = RECURSION_LEVEL(table);
+#endif
+ table->hashShift = JS_DHASH_BITS - newLog2;
+ table->removedCount = 0;
+ table->generation++;
+
+ /* Assign the new entry store to table. */
+ memset(newEntryStore, 0, nbytes);
+ oldEntryAddr = oldEntryStore = table->entryStore;
+ table->entryStore = newEntryStore;
+ moveEntry = table->ops->moveEntry;
+#ifdef DEBUG
+ RECURSION_LEVEL(table) = recursionLevel;
+#endif
+
+ /* Copy only live entries, leaving removed ones behind. */
+ for (i = 0; i < oldCapacity; i++) {
+ oldEntry = (JSDHashEntryHdr *)oldEntryAddr;
+ if (ENTRY_IS_LIVE(oldEntry)) {
+ oldEntry->keyHash &= ~COLLISION_FLAG;
+ newEntry = FindFreeEntry(table, oldEntry->keyHash);
+ JS_ASSERT(JS_DHASH_ENTRY_IS_FREE(newEntry));
+ moveEntry(table, oldEntry, newEntry);
+ newEntry->keyHash = oldEntry->keyHash;
+ }
+ oldEntryAddr += entrySize;
+ }
+
+ table->ops->freeTable(table, oldEntryStore);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSDHashEntryHdr *) JS_DHASH_FASTCALL
+JS_DHashTableOperate(JSDHashTable *table, const void *key, JSDHashOperator op)
+{
+ JSDHashNumber keyHash;
+ JSDHashEntryHdr *entry;
+ uint32 size;
+ int deltaLog2;
+
+ JS_ASSERT(op == JS_DHASH_LOOKUP || RECURSION_LEVEL(table) == 0);
+ INCREMENT_RECURSION_LEVEL(table);
+
+ keyHash = table->ops->hashKey(table, key);
+ keyHash *= JS_DHASH_GOLDEN_RATIO;
+
+ /* Avoid 0 and 1 hash codes, they indicate free and removed entries. */
+ ENSURE_LIVE_KEYHASH(keyHash);
+ keyHash &= ~COLLISION_FLAG;
+
+ switch (op) {
+ case JS_DHASH_LOOKUP:
+ METER(table->stats.lookups++);
+ entry = SearchTable(table, key, keyHash, op);
+ break;
+
+ case JS_DHASH_ADD:
+ /*
+ * If alpha is >= .75, grow or compress the table. If key is already
+ * in the table, we may grow once more than necessary, but only if we
+ * are on the edge of being overloaded.
+ */
+ size = JS_DHASH_TABLE_SIZE(table);
+ if (table->entryCount + table->removedCount >= MAX_LOAD(table, size)) {
+ /* Compress if a quarter or more of all entries are removed. */
+ if (table->removedCount >= size >> 2) {
+ METER(table->stats.compresses++);
+ deltaLog2 = 0;
+ } else {
+ METER(table->stats.grows++);
+ deltaLog2 = 1;
+ }
+
+ /*
+ * Grow or compress table, returning null if ChangeTable fails and
+ * falling through might claim the last free entry.
+ */
+ if (!ChangeTable(table, deltaLog2) &&
+ table->entryCount + table->removedCount == size - 1) {
+ METER(table->stats.addFailures++);
+ entry = NULL;
+ break;
+ }
+ }
+
+ /*
+ * Look for entry after possibly growing, so we don't have to add it,
+ * then skip it while growing the table and re-add it after.
+ */
+ entry = SearchTable(table, key, keyHash, op);
+ if (!ENTRY_IS_LIVE(entry)) {
+ /* Initialize the entry, indicating that it's no longer free. */
+ METER(table->stats.addMisses++);
+ if (ENTRY_IS_REMOVED(entry)) {
+ METER(table->stats.addOverRemoved++);
+ table->removedCount--;
+ keyHash |= COLLISION_FLAG;
+ }
+ if (table->ops->initEntry &&
+ !table->ops->initEntry(table, entry, key)) {
+ /* We haven't claimed entry yet; fail with null return. */
+ memset(entry + 1, 0, table->entrySize - sizeof *entry);
+ entry = NULL;
+ break;
+ }
+ entry->keyHash = keyHash;
+ table->entryCount++;
+ }
+ METER(else table->stats.addHits++);
+ break;
+
+ case JS_DHASH_REMOVE:
+ entry = SearchTable(table, key, keyHash, op);
+ if (ENTRY_IS_LIVE(entry)) {
+ /* Clear this entry and mark it as "removed". */
+ METER(table->stats.removeHits++);
+ JS_DHashTableRawRemove(table, entry);
+
+ /* Shrink if alpha is <= .25 and table isn't too small already. */
+ size = JS_DHASH_TABLE_SIZE(table);
+ if (size > JS_DHASH_MIN_SIZE &&
+ table->entryCount <= MIN_LOAD(table, size)) {
+ METER(table->stats.shrinks++);
+ (void) ChangeTable(table, -1);
+ }
+ }
+ METER(else table->stats.removeMisses++);
+ entry = NULL;
+ break;
+
+ default:
+ JS_ASSERT(0);
+ entry = NULL;
+ }
+
+ DECREMENT_RECURSION_LEVEL(table);
+
+ return entry;
+}
+
+JS_PUBLIC_API(void)
+JS_DHashTableRawRemove(JSDHashTable *table, JSDHashEntryHdr *entry)
+{
+ JSDHashNumber keyHash; /* load first in case clearEntry goofs it */
+
+ JS_ASSERT(JS_DHASH_ENTRY_IS_LIVE(entry));
+ keyHash = entry->keyHash;
+ table->ops->clearEntry(table, entry);
+ if (keyHash & COLLISION_FLAG) {
+ MARK_ENTRY_REMOVED(entry);
+ table->removedCount++;
+ } else {
+ METER(table->stats.removeFrees++);
+ MARK_ENTRY_FREE(entry);
+ }
+ table->entryCount--;
+}
+
+JS_PUBLIC_API(uint32)
+JS_DHashTableEnumerate(JSDHashTable *table, JSDHashEnumerator etor, void *arg)
+{
+ char *entryAddr, *entryLimit;
+ uint32 i, capacity, entrySize, ceiling;
+ JSBool didRemove;
+ JSDHashEntryHdr *entry;
+ JSDHashOperator op;
+
+ INCREMENT_RECURSION_LEVEL(table);
+
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ capacity = JS_DHASH_TABLE_SIZE(table);
+ entryLimit = entryAddr + capacity * entrySize;
+ i = 0;
+ didRemove = JS_FALSE;
+ while (entryAddr < entryLimit) {
+ entry = (JSDHashEntryHdr *)entryAddr;
+ if (ENTRY_IS_LIVE(entry)) {
+ op = etor(table, entry, i++, arg);
+ if (op & JS_DHASH_REMOVE) {
+ METER(table->stats.removeEnums++);
+ JS_DHashTableRawRemove(table, entry);
+ didRemove = JS_TRUE;
+ }
+ if (op & JS_DHASH_STOP)
+ break;
+ }
+ entryAddr += entrySize;
+ }
+
+ JS_ASSERT(!didRemove || RECURSION_LEVEL(table) == 1);
+
+ /*
+ * Shrink or compress if a quarter or more of all entries are removed, or
+ * if the table is underloaded according to the configured minimum alpha,
+ * and is not minimal-size already. Do this only if we removed above, so
+ * non-removing enumerations can count on stable table->entryStore until
+ * the next non-lookup-Operate or removing-Enumerate.
+ */
+ if (didRemove &&
+ (table->removedCount >= capacity >> 2 ||
+ (capacity > JS_DHASH_MIN_SIZE &&
+ table->entryCount <= MIN_LOAD(table, capacity)))) {
+ METER(table->stats.enumShrinks++);
+ capacity = table->entryCount;
+ capacity += capacity >> 1;
+ if (capacity < JS_DHASH_MIN_SIZE)
+ capacity = JS_DHASH_MIN_SIZE;
+
+ JS_CEILING_LOG2(ceiling, capacity);
+ ceiling -= JS_DHASH_BITS - table->hashShift;
+
+ (void) ChangeTable(table, ceiling);
+ }
+
+ DECREMENT_RECURSION_LEVEL(table);
+
+ return i;
+}
+
+#ifdef JS_DHASHMETER
+#include <math.h>
+
+JS_PUBLIC_API(void)
+JS_DHashTableDumpMeter(JSDHashTable *table, JSDHashEnumerator dump, FILE *fp)
+{
+ char *entryAddr;
+ uint32 entrySize, entryCount;
+ int hashShift, sizeLog2;
+ uint32 i, tableSize, sizeMask, chainLen, maxChainLen, chainCount;
+ JSDHashNumber hash1, hash2, saveHash1, maxChainHash1, maxChainHash2;
+ double sqsum, mean, variance, sigma;
+ JSDHashEntryHdr *entry, *probe;
+
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ hashShift = table->hashShift;
+ sizeLog2 = JS_DHASH_BITS - hashShift;
+ tableSize = JS_DHASH_TABLE_SIZE(table);
+ sizeMask = JS_BITMASK(sizeLog2);
+ chainCount = maxChainLen = 0;
+ hash2 = 0;
+ sqsum = 0;
+
+ for (i = 0; i < tableSize; i++) {
+ entry = (JSDHashEntryHdr *)entryAddr;
+ entryAddr += entrySize;
+ if (!ENTRY_IS_LIVE(entry))
+ continue;
+ hash1 = HASH1(entry->keyHash & ~COLLISION_FLAG, hashShift);
+ saveHash1 = hash1;
+ probe = ADDRESS_ENTRY(table, hash1);
+ chainLen = 1;
+ if (probe == entry) {
+ /* Start of a (possibly unit-length) chain. */
+ chainCount++;
+ } else {
+ hash2 = HASH2(entry->keyHash & ~COLLISION_FLAG, sizeLog2,
+ hashShift);
+ do {
+ chainLen++;
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+ probe = ADDRESS_ENTRY(table, hash1);
+ } while (probe != entry);
+ }
+ sqsum += chainLen * chainLen;
+ if (chainLen > maxChainLen) {
+ maxChainLen = chainLen;
+ maxChainHash1 = saveHash1;
+ maxChainHash2 = hash2;
+ }
+ }
+
+ entryCount = table->entryCount;
+ if (entryCount && chainCount) {
+ mean = (double)entryCount / chainCount;
+ variance = chainCount * sqsum - entryCount * entryCount;
+ if (variance < 0 || chainCount == 1)
+ variance = 0;
+ else
+ variance /= chainCount * (chainCount - 1);
+ sigma = sqrt(variance);
+ } else {
+ mean = sigma = 0;
+ }
+
+ fprintf(fp, "Double hashing statistics:\n");
+ fprintf(fp, " table size (in entries): %u\n", tableSize);
+ fprintf(fp, " number of entries: %u\n", table->entryCount);
+ fprintf(fp, " number of removed entries: %u\n", table->removedCount);
+ fprintf(fp, " number of searches: %u\n", table->stats.searches);
+ fprintf(fp, " number of hits: %u\n", table->stats.hits);
+ fprintf(fp, " number of misses: %u\n", table->stats.misses);
+ fprintf(fp, " mean steps per search: %g\n", table->stats.searches ?
+ (double)table->stats.steps
+ / table->stats.searches :
+ 0.);
+ fprintf(fp, " mean hash chain length: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sigma);
+ fprintf(fp, " maximum hash chain length: %u\n", maxChainLen);
+ fprintf(fp, " number of lookups: %u\n", table->stats.lookups);
+ fprintf(fp, " adds that made a new entry: %u\n", table->stats.addMisses);
+ fprintf(fp, "adds that recycled removeds: %u\n", table->stats.addOverRemoved);
+ fprintf(fp, " adds that found an entry: %u\n", table->stats.addHits);
+ fprintf(fp, " add failures: %u\n", table->stats.addFailures);
+ fprintf(fp, " useful removes: %u\n", table->stats.removeHits);
+ fprintf(fp, " useless removes: %u\n", table->stats.removeMisses);
+ fprintf(fp, "removes that freed an entry: %u\n", table->stats.removeFrees);
+ fprintf(fp, " removes while enumerating: %u\n", table->stats.removeEnums);
+ fprintf(fp, " number of grows: %u\n", table->stats.grows);
+ fprintf(fp, " number of shrinks: %u\n", table->stats.shrinks);
+ fprintf(fp, " number of compresses: %u\n", table->stats.compresses);
+ fprintf(fp, "number of enumerate shrinks: %u\n", table->stats.enumShrinks);
+
+ if (dump && maxChainLen && hash2) {
+ fputs("Maximum hash chain:\n", fp);
+ hash1 = maxChainHash1;
+ hash2 = maxChainHash2;
+ entry = ADDRESS_ENTRY(table, hash1);
+ i = 0;
+ do {
+ if (dump(table, entry, i++, fp) != JS_DHASH_NEXT)
+ break;
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+ entry = ADDRESS_ENTRY(table, hash1);
+ } while (JS_DHASH_ENTRY_IS_BUSY(entry));
+ }
+}
+#endif /* JS_DHASHMETER */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.h b/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.h
new file mode 100644
index 0000000..5e17b26
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.h
@@ -0,0 +1,588 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla JavaScript code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsdhash_h___
+#define jsdhash_h___
+/*
+ * Double hashing, a la Knuth 6.
+ */
+#include "jstypes.h"
+
+JS_BEGIN_EXTERN_C
+
+#if defined(__GNUC__) && defined(__i386__) && (__GNUC__ >= 3) && !defined(XP_OS2)
+#define JS_DHASH_FASTCALL __attribute__ ((regparm (3),stdcall))
+#elif defined(XP_WIN)
+#define JS_DHASH_FASTCALL __fastcall
+#else
+#define JS_DHASH_FASTCALL
+#endif
+
+#ifdef DEBUG_XXXbrendan
+#define JS_DHASHMETER 1
+#endif
+
+/* Table size limit, do not equal or exceed (see min&maxAlphaFrac, below). */
+#undef JS_DHASH_SIZE_LIMIT
+#define JS_DHASH_SIZE_LIMIT JS_BIT(24)
+
+/* Minimum table size, or gross entry count (net is at most .75 loaded). */
+#ifndef JS_DHASH_MIN_SIZE
+#define JS_DHASH_MIN_SIZE 16
+#elif (JS_DHASH_MIN_SIZE & (JS_DHASH_MIN_SIZE - 1)) != 0
+#error "JS_DHASH_MIN_SIZE must be a power of two!"
+#endif
+
+/*
+ * Multiplicative hash uses an unsigned 32 bit integer and the golden ratio,
+ * expressed as a fixed-point 32-bit fraction.
+ */
+#define JS_DHASH_BITS 32
+#define JS_DHASH_GOLDEN_RATIO 0x9E3779B9U
+
+/* Primitive and forward-struct typedefs. */
+typedef uint32 JSDHashNumber;
+typedef struct JSDHashEntryHdr JSDHashEntryHdr;
+typedef struct JSDHashEntryStub JSDHashEntryStub;
+typedef struct JSDHashTable JSDHashTable;
+typedef struct JSDHashTableOps JSDHashTableOps;
+
+/*
+ * Table entry header structure.
+ *
+ * In order to allow in-line allocation of key and value, we do not declare
+ * either here. Instead, the API uses const void *key as a formal parameter.
+ * The key need not be stored in the entry; it may be part of the value, but
+ * need not be stored at all.
+ *
+ * Callback types are defined below and grouped into the JSDHashTableOps
+ * structure, for single static initialization per hash table sub-type.
+ *
+ * Each hash table sub-type should nest the JSDHashEntryHdr structure at the
+ * front of its particular entry type. The keyHash member contains the result
+ * of multiplying the hash code returned from the hashKey callback (see below)
+ * by JS_DHASH_GOLDEN_RATIO, then constraining the result to avoid the magic 0
+ * and 1 values. The stored keyHash value is table size invariant, and it is
+ * maintained automatically by JS_DHashTableOperate -- users should never set
+ * it, and its only uses should be via the entry macros below.
+ *
+ * The JS_DHASH_ENTRY_IS_LIVE macro tests whether entry is neither free nor
+ * removed. An entry may be either busy or free; if busy, it may be live or
+ * removed. Consumers of this API should not access members of entries that
+ * are not live.
+ *
+ * However, use JS_DHASH_ENTRY_IS_BUSY for faster liveness testing of entries
+ * returned by JS_DHashTableOperate, as JS_DHashTableOperate never returns a
+ * non-live, busy (i.e., removed) entry pointer to its caller. See below for
+ * more details on JS_DHashTableOperate's calling rules.
+ */
+struct JSDHashEntryHdr {
+ JSDHashNumber keyHash; /* every entry must begin like this */
+};
+
+#define JS_DHASH_ENTRY_IS_FREE(entry) ((entry)->keyHash == 0)
+#define JS_DHASH_ENTRY_IS_BUSY(entry) (!JS_DHASH_ENTRY_IS_FREE(entry))
+#define JS_DHASH_ENTRY_IS_LIVE(entry) ((entry)->keyHash >= 2)
+
+/*
+ * A JSDHashTable is currently 8 words (without the JS_DHASHMETER overhead)
+ * on most architectures, and may be allocated on the stack or within another
+ * structure or class (see below for the Init and Finish functions to use).
+ *
+ * To decide whether to use double hashing vs. chaining, we need to develop a
+ * trade-off relation, as follows:
+ *
+ * Let alpha be the load factor, esize the entry size in words, count the
+ * entry count, and pow2 the power-of-two table size in entries.
+ *
+ * (JSDHashTable overhead) > (JSHashTable overhead)
+ * (unused table entry space) > (malloc and .next overhead per entry) +
+ * (buckets overhead)
+ * (1 - alpha) * esize * pow2 > 2 * count + pow2
+ *
+ * Notice that alpha is by definition (count / pow2):
+ *
+ * (1 - alpha) * esize * pow2 > 2 * alpha * pow2 + pow2
+ * (1 - alpha) * esize > 2 * alpha + 1
+ *
+ * esize > (1 + 2 * alpha) / (1 - alpha)
+ *
+ * This assumes both tables must keep keyHash, key, and value for each entry,
+ * where key and value point to separately allocated strings or structures.
+ * If key and value can be combined into one pointer, then the trade-off is:
+ *
+ * esize > (1 + 3 * alpha) / (1 - alpha)
+ *
+ * If the entry value can be a subtype of JSDHashEntryHdr, rather than a type
+ * that must be allocated separately and referenced by an entry.value pointer
+ * member, and provided key's allocation can be fused with its entry's, then
+ * k (the words wasted per entry with chaining) is 4.
+ *
+ * To see these curves, feed gnuplot input like so:
+ *
+ * gnuplot> f(x,k) = (1 + k * x) / (1 - x)
+ * gnuplot> plot [0:.75] f(x,2), f(x,3), f(x,4)
+ *
+ * For k of 2 and a well-loaded table (alpha > .5), esize must be more than 4
+ * words for chaining to be more space-efficient than double hashing.
+ *
+ * Solving for alpha helps us decide when to shrink an underloaded table:
+ *
+ * esize > (1 + k * alpha) / (1 - alpha)
+ * esize - alpha * esize > 1 + k * alpha
+ * esize - 1 > (k + esize) * alpha
+ * (esize - 1) / (k + esize) > alpha
+ *
+ * alpha < (esize - 1) / (esize + k)
+ *
+ * Therefore double hashing should keep alpha >= (esize - 1) / (esize + k),
+ * assuming esize is not too large (in which case, chaining should probably be
+ * used for any alpha). For esize=2 and k=3, we want alpha >= .2; for esize=3
+ * and k=2, we want alpha >= .4. For k=4, esize could be 6, and alpha >= .5
+ * would still obtain. See the JS_DHASH_MIN_ALPHA macro further below.
+ *
+ * The current implementation uses a configurable lower bound on alpha, which
+ * defaults to .25, when deciding to shrink the table (while still respecting
+ * JS_DHASH_MIN_SIZE).
+ *
+ * Note a qualitative difference between chaining and double hashing: under
+ * chaining, entry addresses are stable across table shrinks and grows. With
+ * double hashing, you can't safely hold an entry pointer and use it after an
+ * ADD or REMOVE operation, unless you sample table->generation before adding
+ * or removing, and compare the sample after, dereferencing the entry pointer
+ * only if table->generation has not changed.
+ *
+ * The moral of this story: there is no one-size-fits-all hash table scheme,
+ * but for small table entry size, and assuming entry address stability is not
+ * required, double hashing wins.
+ */
+struct JSDHashTable {
+ const JSDHashTableOps *ops; /* virtual operations, see below */
+ void *data; /* ops- and instance-specific data */
+ int16 hashShift; /* multiplicative hash shift */
+ uint8 maxAlphaFrac; /* 8-bit fixed point max alpha */
+ uint8 minAlphaFrac; /* 8-bit fixed point min alpha */
+ uint32 entrySize; /* number of bytes in an entry */
+ uint32 entryCount; /* number of entries in table */
+ uint32 removedCount; /* removed entry sentinels in table */
+ uint32 generation; /* entry storage generation number */
+ char *entryStore; /* entry storage */
+#ifdef JS_DHASHMETER
+ struct JSDHashStats {
+ uint32 searches; /* total number of table searches */
+ uint32 steps; /* hash chain links traversed */
+ uint32 hits; /* searches that found key */
+ uint32 misses; /* searches that didn't find key */
+ uint32 lookups; /* number of JS_DHASH_LOOKUPs */
+ uint32 addMisses; /* adds that miss, and do work */
+ uint32 addOverRemoved; /* adds that recycled a removed entry */
+ uint32 addHits; /* adds that hit an existing entry */
+ uint32 addFailures; /* out-of-memory during add growth */
+ uint32 removeHits; /* removes that hit, and do work */
+ uint32 removeMisses; /* useless removes that miss */
+ uint32 removeFrees; /* removes that freed entry directly */
+ uint32 removeEnums; /* removes done by Enumerate */
+ uint32 grows; /* table expansions */
+ uint32 shrinks; /* table contractions */
+ uint32 compresses; /* table compressions */
+ uint32 enumShrinks; /* contractions after Enumerate */
+ } stats;
+#endif
+};
+
+/*
+ * Size in entries (gross, not net of free and removed sentinels) for table.
+ * We store hashShift rather than sizeLog2 to optimize the collision-free case
+ * in SearchTable.
+ */
+#define JS_DHASH_TABLE_SIZE(table) JS_BIT(JS_DHASH_BITS - (table)->hashShift)
+
+/*
+ * Table space at entryStore is allocated and freed using these callbacks.
+ * The allocator should return null on error only (not if called with nbytes
+ * equal to 0; but note that jsdhash.c code will never call with 0 nbytes).
+ */
+typedef void *
+(* JSDHashAllocTable)(JSDHashTable *table, uint32 nbytes);
+
+typedef void
+(* JSDHashFreeTable) (JSDHashTable *table, void *ptr);
+
+/*
+ * Compute the hash code for a given key to be looked up, added, or removed
+ * from table. A hash code may have any JSDHashNumber value.
+ */
+typedef JSDHashNumber
+(* JSDHashHashKey) (JSDHashTable *table, const void *key);
+
+/*
+ * Compare the key identifying entry in table with the provided key parameter.
+ * Return JS_TRUE if keys match, JS_FALSE otherwise.
+ */
+typedef JSBool
+(* JSDHashMatchEntry)(JSDHashTable *table, const JSDHashEntryHdr *entry,
+ const void *key);
+
+/*
+ * Copy the data starting at from to the new entry storage at to. Do not add
+ * reference counts for any strong references in the entry, however, as this
+ * is a "move" operation: the old entry storage at from will be freed without
+ * any reference-decrementing callback shortly.
+ */
+typedef void
+(* JSDHashMoveEntry)(JSDHashTable *table, const JSDHashEntryHdr *from,
+ JSDHashEntryHdr *to);
+
+/*
+ * Clear the entry and drop any strong references it holds. This callback is
+ * invoked during a JS_DHASH_REMOVE operation (see below for operation codes),
+ * but only if the given key is found in the table.
+ */
+typedef void
+(* JSDHashClearEntry)(JSDHashTable *table, JSDHashEntryHdr *entry);
+
+/*
+ * Called when a table (whether allocated dynamically by itself, or nested in
+ * a larger structure, or allocated on the stack) is finished. This callback
+ * allows table->ops-specific code to finalize table->data.
+ */
+typedef void
+(* JSDHashFinalize) (JSDHashTable *table);
+
+/*
+ * Initialize a new entry, apart from keyHash. This function is called when
+ * JS_DHashTableOperate's JS_DHASH_ADD case finds no existing entry for the
+ * given key, and must add a new one. At that point, entry->keyHash is not
+ * set yet, to avoid claiming the last free entry in a severely overloaded
+ * table.
+ */
+typedef JSBool
+(* JSDHashInitEntry)(JSDHashTable *table, JSDHashEntryHdr *entry,
+ const void *key);
+
+/*
+ * Finally, the "vtable" structure for JSDHashTable. The first eight hooks
+ * must be provided by implementations; they're called unconditionally by the
+ * generic jsdhash.c code. Hooks after these may be null.
+ *
+ * Summary of allocation-related hook usage with C++ placement new emphasis:
+ * allocTable Allocate raw bytes with malloc, no ctors run.
+ * freeTable Free raw bytes with free, no dtors run.
+ * initEntry Call placement new using default key-based ctor.
+ * Return JS_TRUE on success, JS_FALSE on error.
+ * moveEntry Call placement new using copy ctor, run dtor on old
+ * entry storage.
+ * clearEntry Run dtor on entry.
+ * finalize Stub unless table->data was initialized and needs to
+ * be finalized.
+ *
+ * Note the reason why initEntry is optional: the default hooks (stubs) clear
+ * entry storage: On successful JS_DHashTableOperate(tbl, key, JS_DHASH_ADD),
+ * the returned entry pointer addresses an entry struct whose keyHash member
+ * has been set non-zero, but all other entry members are still clear (null).
+ * JS_DHASH_ADD callers can test such members to see whether the entry was
+ * newly created by the JS_DHASH_ADD call that just succeeded. If placement
+ * new or similar initialization is required, define an initEntry hook. Of
+ * course, the clearEntry hook must zero or null appropriately.
+ *
+ * XXX assumes 0 is null for pointer types.
+ */
+struct JSDHashTableOps {
+ /* Mandatory hooks. All implementations must provide these. */
+ JSDHashAllocTable allocTable;
+ JSDHashFreeTable freeTable;
+ JSDHashHashKey hashKey;
+ JSDHashMatchEntry matchEntry;
+ JSDHashMoveEntry moveEntry;
+ JSDHashClearEntry clearEntry;
+ JSDHashFinalize finalize;
+
+ /* Optional hooks start here. If null, these are not called. */
+ JSDHashInitEntry initEntry;
+};
+
+/*
+ * Default implementations for the above ops.
+ */
+extern JS_PUBLIC_API(void *)
+JS_DHashAllocTable(JSDHashTable *table, uint32 nbytes);
+
+extern JS_PUBLIC_API(void)
+JS_DHashFreeTable(JSDHashTable *table, void *ptr);
+
+extern JS_PUBLIC_API(JSDHashNumber)
+JS_DHashStringKey(JSDHashTable *table, const void *key);
+
+/* A minimal entry contains a keyHash header and a void key pointer. */
+struct JSDHashEntryStub {
+ JSDHashEntryHdr hdr;
+ const void *key;
+};
+
+extern JS_PUBLIC_API(JSDHashNumber)
+JS_DHashVoidPtrKeyStub(JSDHashTable *table, const void *key);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DHashMatchEntryStub(JSDHashTable *table,
+ const JSDHashEntryHdr *entry,
+ const void *key);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DHashMatchStringKey(JSDHashTable *table,
+ const JSDHashEntryHdr *entry,
+ const void *key);
+
+extern JS_PUBLIC_API(void)
+JS_DHashMoveEntryStub(JSDHashTable *table,
+ const JSDHashEntryHdr *from,
+ JSDHashEntryHdr *to);
+
+extern JS_PUBLIC_API(void)
+JS_DHashClearEntryStub(JSDHashTable *table, JSDHashEntryHdr *entry);
+
+extern JS_PUBLIC_API(void)
+JS_DHashFreeStringKey(JSDHashTable *table, JSDHashEntryHdr *entry);
+
+extern JS_PUBLIC_API(void)
+JS_DHashFinalizeStub(JSDHashTable *table);
+
+/*
+ * If you use JSDHashEntryStub or a subclass of it as your entry struct, and
+ * if your entries move via memcpy and clear via memset(0), you can use these
+ * stub operations.
+ */
+extern JS_PUBLIC_API(const JSDHashTableOps *)
+JS_DHashGetStubOps(void);
+
+/*
+ * Dynamically allocate a new JSDHashTable using malloc, initialize it using
+ * JS_DHashTableInit, and return its address. Return null on malloc failure.
+ * Note that the entry storage at table->entryStore will be allocated using
+ * the ops->allocTable callback.
+ */
+extern JS_PUBLIC_API(JSDHashTable *)
+JS_NewDHashTable(const JSDHashTableOps *ops, void *data, uint32 entrySize,
+ uint32 capacity);
+
+/*
+ * Finalize table's data, free its entry storage (via table->ops->freeTable),
+ * and return the memory starting at table to the malloc heap.
+ */
+extern JS_PUBLIC_API(void)
+JS_DHashTableDestroy(JSDHashTable *table);
+
+/*
+ * Initialize table with ops, data, entrySize, and capacity. Capacity is a
+ * guess for the smallest table size at which the table will usually be less
+ * than 75% loaded (the table will grow or shrink as needed; capacity serves
+ * only to avoid inevitable early growth from JS_DHASH_MIN_SIZE).
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_DHashTableInit(JSDHashTable *table, const JSDHashTableOps *ops, void *data,
+ uint32 entrySize, uint32 capacity);
+
+/*
+ * Set maximum and minimum alpha for table. The defaults are 0.75 and .25.
+ * maxAlpha must be in [0.5, 0.9375] for the default JS_DHASH_MIN_SIZE; or if
+ * MinSize=JS_DHASH_MIN_SIZE <= 256, in [0.5, (float)(MinSize-1)/MinSize]; or
+ * else in [0.5, 255.0/256]. minAlpha must be in [0, maxAlpha / 2), so that
+ * we don't shrink on the very next remove after growing a table upon adding
+ * an entry that brings entryCount past maxAlpha * tableSize.
+ */
+extern JS_PUBLIC_API(void)
+JS_DHashTableSetAlphaBounds(JSDHashTable *table,
+ float maxAlpha,
+ float minAlpha);
+
+/*
+ * Call this macro with k, the number of pointer-sized words wasted per entry
+ * under chaining, to compute the minimum alpha at which double hashing still
+ * beats chaining.
+ */
+#define JS_DHASH_MIN_ALPHA(table, k) \
+ ((float)((table)->entrySize / sizeof(void *) - 1) \
+ / ((table)->entrySize / sizeof(void *) + (k)))
+
+/*
+ * Default max/min alpha, and macros to compute the value for the |capacity|
+ * parameter to JS_NewDHashTable and JS_DHashTableInit, given default or any
+ * max alpha, such that adding entryCount entries right after initializing the
+ * table will not require a reallocation (so JS_DHASH_ADD can't fail for those
+ * JS_DHashTableOperate calls).
+ *
+ * NB: JS_DHASH_CAP is a helper macro meant for use only in JS_DHASH_CAPACITY.
+ * Don't use it directly!
+ */
+#define JS_DHASH_DEFAULT_MAX_ALPHA 0.75
+#define JS_DHASH_DEFAULT_MIN_ALPHA 0.25
+
+#define JS_DHASH_CAP(entryCount, maxAlpha) \
+ ((uint32)((double)(entryCount) / (maxAlpha)))
+
+#define JS_DHASH_CAPACITY(entryCount, maxAlpha) \
+ (JS_DHASH_CAP(entryCount, maxAlpha) + \
+ (((JS_DHASH_CAP(entryCount, maxAlpha) * (uint8)(0x100 * (maxAlpha))) \
+ >> 8) < (entryCount)))
+
+#define JS_DHASH_DEFAULT_CAPACITY(entryCount) \
+ JS_DHASH_CAPACITY(entryCount, JS_DHASH_DEFAULT_MAX_ALPHA)
+
+/*
+ * Finalize table's data, free its entry storage using table->ops->freeTable,
+ * and leave its members unchanged from their last live values (which leaves
+ * pointers dangling). If you want to burn cycles clearing table, it's up to
+ * your code to call memset.
+ */
+extern JS_PUBLIC_API(void)
+JS_DHashTableFinish(JSDHashTable *table);
+
+/*
+ * To consolidate keyHash computation and table grow/shrink code, we use a
+ * single entry point for lookup, add, and remove operations. The operation
+ * codes are declared here, along with codes returned by JSDHashEnumerator
+ * functions, which control JS_DHashTableEnumerate's behavior.
+ */
+typedef enum JSDHashOperator {
+ JS_DHASH_LOOKUP = 0, /* lookup entry */
+ JS_DHASH_ADD = 1, /* add entry */
+ JS_DHASH_REMOVE = 2, /* remove entry, or enumerator says remove */
+ JS_DHASH_NEXT = 0, /* enumerator says continue */
+ JS_DHASH_STOP = 1 /* enumerator says stop */
+} JSDHashOperator;
+
+/*
+ * To lookup a key in table, call:
+ *
+ * entry = JS_DHashTableOperate(table, key, JS_DHASH_LOOKUP);
+ *
+ * If JS_DHASH_ENTRY_IS_BUSY(entry) is true, key was found and it identifies
+ * entry. If JS_DHASH_ENTRY_IS_FREE(entry) is true, key was not found.
+ *
+ * To add an entry identified by key to table, call:
+ *
+ * entry = JS_DHashTableOperate(table, key, JS_DHASH_ADD);
+ *
+ * If entry is null upon return, then either the table is severely overloaded,
+ * and memory can't be allocated for entry storage via table->ops->allocTable;
+ * Or if table->ops->initEntry is non-null, the table->ops->initEntry op may
+ * have returned false.
+ *
+ * Otherwise, entry->keyHash has been set so that JS_DHASH_ENTRY_IS_BUSY(entry)
+ * is true, and it is up to the caller to initialize the key and value parts
+ * of the entry sub-type, if they have not been set already (i.e. if entry was
+ * not already in the table, and if the optional initEntry hook was not used).
+ *
+ * To remove an entry identified by key from table, call:
+ *
+ * (void) JS_DHashTableOperate(table, key, JS_DHASH_REMOVE);
+ *
+ * If key's entry is found, it is cleared (via table->ops->clearEntry) and
+ * the entry is marked so that JS_DHASH_ENTRY_IS_FREE(entry). This operation
+ * returns null unconditionally; you should ignore its return value.
+ */
+extern JS_PUBLIC_API(JSDHashEntryHdr *) JS_DHASH_FASTCALL
+JS_DHashTableOperate(JSDHashTable *table, const void *key, JSDHashOperator op);
+
+/*
+ * Remove an entry already accessed via LOOKUP or ADD.
+ *
+ * NB: this is a "raw" or low-level routine, intended to be used only where
+ * the inefficiency of a full JS_DHashTableOperate (which rehashes in order
+ * to find the entry given its key) is not tolerable. This function does not
+ * shrink the table if it is underloaded. It does not update stats #ifdef
+ * JS_DHASHMETER, either.
+ */
+extern JS_PUBLIC_API(void)
+JS_DHashTableRawRemove(JSDHashTable *table, JSDHashEntryHdr *entry);
+
+/*
+ * Enumerate entries in table using etor:
+ *
+ * count = JS_DHashTableEnumerate(table, etor, arg);
+ *
+ * JS_DHashTableEnumerate calls etor like so:
+ *
+ * op = etor(table, entry, number, arg);
+ *
+ * where number is a zero-based ordinal assigned to live entries according to
+ * their order in table->entryStore.
+ *
+ * The return value, op, is treated as a set of flags. If op is JS_DHASH_NEXT,
+ * then continue enumerating. If op contains JS_DHASH_REMOVE, then clear (via
+ * table->ops->clearEntry) and free entry. Then we check whether op contains
+ * JS_DHASH_STOP; if so, stop enumerating and return the number of live entries
+ * that were enumerated so far. Return the total number of live entries when
+ * enumeration completes normally.
+ *
+ * If etor calls JS_DHashTableOperate on table with op != JS_DHASH_LOOKUP, it
+ * must return JS_DHASH_STOP; otherwise undefined behavior results.
+ *
+ * If any enumerator returns JS_DHASH_REMOVE, table->entryStore may be shrunk
+ * or compressed after enumeration, but before JS_DHashTableEnumerate returns.
+ * Such an enumerator therefore can't safely set aside entry pointers, but an
+ * enumerator that never returns JS_DHASH_REMOVE can set pointers to entries
+ * aside, e.g., to avoid copying live entries into an array of the entry type.
+ * Copying entry pointers is cheaper, and safe so long as the caller of such a
+ * "stable" Enumerate doesn't use the set-aside pointers after any call either
+ * to PL_DHashTableOperate, or to an "unstable" form of Enumerate, which might
+ * grow or shrink entryStore.
+ *
+ * If your enumerator wants to remove certain entries, but set aside pointers
+ * to other entries that it retains, it can use JS_DHashTableRawRemove on the
+ * entries to be removed, returning JS_DHASH_NEXT to skip them. Likewise, if
+ * you want to remove entries, but for some reason you do not want entryStore
+ * to be shrunk or compressed, you can call JS_DHashTableRawRemove safely on
+ * the entry being enumerated, rather than returning JS_DHASH_REMOVE.
+ */
+typedef JSDHashOperator
+(* JSDHashEnumerator)(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
+ void *arg);
+
+extern JS_PUBLIC_API(uint32)
+JS_DHashTableEnumerate(JSDHashTable *table, JSDHashEnumerator etor, void *arg);
+
+#ifdef JS_DHASHMETER
+#include <stdio.h>
+
+extern JS_PUBLIC_API(void)
+JS_DHashTableDumpMeter(JSDHashTable *table, JSDHashEnumerator dump, FILE *fp);
+#endif
+
+JS_END_EXTERN_C
+
+#endif /* jsdhash_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.cpp
new file mode 100644
index 0000000..ca9176d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.cpp
@@ -0,0 +1,572 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Portable double to alphanumeric string and back converters.
+ */
+#include "jsstddef.h"
+#include "jslibmath.h"
+#include "jstypes.h"
+#include "jsdtoa.h"
+#include "jsprf.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jspubtd.h"
+#include "jsnum.h"
+#include "jsbit.h"
+
+#ifdef JS_THREADSAFE
+#include "jslock.h"
+#endif
+
+#ifdef IS_LITTLE_ENDIAN
+#define IEEE_8087
+#else
+#define IEEE_MC68k
+#endif
+
+#ifndef Long
+#define Long int32
+#endif
+
+#ifndef ULong
+#define ULong uint32
+#endif
+
+/*
+#ifndef Llong
+#define Llong JSInt64
+#endif
+
+#ifndef ULlong
+#define ULlong JSUint64
+#endif
+*/
+
+#ifdef JS_THREADSAFE
+static PRLock *dtoalock;
+static JSBool _dtoainited = JS_FALSE;
+
+#define LOCK_DTOA() PR_Lock(dtoalock);
+#define UNLOCK_DTOA() PR_Unlock(dtoalock)
+#else
+#define LOCK_DTOA()
+#define UNLOCK_DTOA()
+#endif
+#include "dtoa.c"
+
+JS_FRIEND_API(JSBool)
+js_InitDtoa()
+{
+#ifdef JS_THREADSAFE
+ if (!_dtoainited) {
+ dtoalock = PR_NewLock();
+ JS_ASSERT(dtoalock);
+ _dtoainited = JS_TRUE;
+ }
+
+ return (dtoalock != 0);
+#else
+ return JS_TRUE;
+#endif
+}
+
+JS_FRIEND_API(void)
+js_FinishDtoa()
+{
+#ifdef JS_THREADSAFE
+ if (_dtoainited) {
+ PR_DestroyLock(dtoalock);
+ dtoalock = NULL;
+ _dtoainited = JS_FALSE;
+ }
+#endif
+}
+
+/* Mapping of JSDToStrMode -> js_dtoa mode */
+static const uint8 dtoaModes[] = {
+ 0, /* DTOSTR_STANDARD */
+ 0, /* DTOSTR_STANDARD_EXPONENTIAL, */
+ 3, /* DTOSTR_FIXED, */
+ 2, /* DTOSTR_EXPONENTIAL, */
+ 2}; /* DTOSTR_PRECISION */
+
+JS_FRIEND_API(double)
+JS_strtod(const char *s00, char **se, int *err)
+{
+ double retval;
+ if (err)
+ *err = 0;
+ LOCK_DTOA();
+ retval = _strtod(s00, se);
+ UNLOCK_DTOA();
+ return retval;
+}
+
+JS_FRIEND_API(char *)
+JS_dtostr(char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, double dinput)
+{
+ U d;
+ int decPt; /* Offset of decimal point from first digit */
+ int sign; /* Nonzero if the sign bit was set in d */
+ int nDigits; /* Number of significand digits returned by js_dtoa */
+ char *numBegin; /* Pointer to the digits returned by js_dtoa */
+ char *numEnd = 0; /* Pointer past the digits returned by js_dtoa */
+
+ JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL
+ ? DTOSTR_STANDARD_BUFFER_SIZE
+ : DTOSTR_VARIABLE_BUFFER_SIZE(precision)));
+
+ /*
+ * Change mode here rather than below because the buffer may not be large
+ * enough to hold a large integer.
+ */
+ if (mode == DTOSTR_FIXED && (dinput >= 1e21 || dinput <= -1e21))
+ mode = DTOSTR_STANDARD;
+
+ LOCK_DTOA();
+ dval(d) = dinput;
+ numBegin = dtoa(d, dtoaModes[mode], precision, &decPt, &sign, &numEnd);
+ if (!numBegin) {
+ UNLOCK_DTOA();
+ return NULL;
+ }
+
+ nDigits = numEnd - numBegin;
+ JS_ASSERT((size_t) nDigits <= bufferSize - 2);
+ if ((size_t) nDigits > bufferSize - 2) {
+ UNLOCK_DTOA();
+ return NULL;
+ }
+
+ memcpy(buffer + 2, numBegin, nDigits);
+ freedtoa(numBegin);
+ UNLOCK_DTOA();
+ numBegin = buffer + 2; /* +2 leaves space for sign and/or decimal point */
+ numEnd = numBegin + nDigits;
+ *numEnd = '\0';
+
+ /* If Infinity, -Infinity, or NaN, return the string regardless of mode. */
+ if (decPt != 9999) {
+ JSBool exponentialNotation = JS_FALSE;
+ int minNDigits = 0; /* Min number of significant digits required */
+ char *p;
+ char *q;
+
+ switch (mode) {
+ case DTOSTR_STANDARD:
+ if (decPt < -5 || decPt > 21)
+ exponentialNotation = JS_TRUE;
+ else
+ minNDigits = decPt;
+ break;
+
+ case DTOSTR_FIXED:
+ if (precision >= 0)
+ minNDigits = decPt + precision;
+ else
+ minNDigits = decPt;
+ break;
+
+ case DTOSTR_EXPONENTIAL:
+ JS_ASSERT(precision > 0);
+ minNDigits = precision;
+ /* Fall through */
+ case DTOSTR_STANDARD_EXPONENTIAL:
+ exponentialNotation = JS_TRUE;
+ break;
+
+ case DTOSTR_PRECISION:
+ JS_ASSERT(precision > 0);
+ minNDigits = precision;
+ if (decPt < -5 || decPt > precision)
+ exponentialNotation = JS_TRUE;
+ break;
+ }
+
+ /* If the number has fewer than minNDigits, end-pad it with zeros. */
+ if (nDigits < minNDigits) {
+ p = numBegin + minNDigits;
+ nDigits = minNDigits;
+ do {
+ *numEnd++ = '0';
+ } while (numEnd != p);
+ *numEnd = '\0';
+ }
+
+ if (exponentialNotation) {
+ /* Insert a decimal point if more than one significand digit */
+ if (nDigits != 1) {
+ numBegin--;
+ numBegin[0] = numBegin[1];
+ numBegin[1] = '.';
+ }
+ JS_snprintf(numEnd, bufferSize - (numEnd - buffer), "e%+d", decPt-1);
+ } else if (decPt != nDigits) {
+ /* Some kind of a fraction in fixed notation */
+ JS_ASSERT(decPt <= nDigits);
+ if (decPt > 0) {
+ /* dd...dd . dd...dd */
+ p = --numBegin;
+ do {
+ *p = p[1];
+ p++;
+ } while (--decPt);
+ *p = '.';
+ } else {
+ /* 0 . 00...00dd...dd */
+ p = numEnd;
+ numEnd += 1 - decPt;
+ q = numEnd;
+ JS_ASSERT(numEnd < buffer + bufferSize);
+ *numEnd = '\0';
+ while (p != numBegin)
+ *--q = *--p;
+ for (p = numBegin + 1; p != q; p++)
+ *p = '0';
+ *numBegin = '.';
+ *--numBegin = '0';
+ }
+ }
+ }
+
+ /* If negative and neither -0.0 nor NaN, output a leading '-'. */
+ if (sign &&
+ !(word0(d) == Sign_bit && word1(d) == 0) &&
+ !((word0(d) & Exp_mask) == Exp_mask &&
+ (word1(d) || (word0(d) & Frac_mask)))) {
+ *--numBegin = '-';
+ }
+ return numBegin;
+}
+
+
+/* Let b = floor(b / divisor), and return the remainder. b must be nonnegative.
+ * divisor must be between 1 and 65536.
+ * This function cannot run out of memory. */
+static uint32
+divrem(Bigint *b, uint32 divisor)
+{
+ int32 n = b->wds;
+ uint32 remainder = 0;
+ ULong *bx;
+ ULong *bp;
+
+ JS_ASSERT(divisor > 0 && divisor <= 65536);
+
+ if (!n)
+ return 0; /* b is zero */
+ bx = b->x;
+ bp = bx + n;
+ do {
+ ULong a = *--bp;
+ ULong dividend = remainder << 16 | a >> 16;
+ ULong quotientHi = dividend / divisor;
+ ULong quotientLo;
+
+ remainder = dividend - quotientHi*divisor;
+ JS_ASSERT(quotientHi <= 0xFFFF && remainder < divisor);
+ dividend = remainder << 16 | (a & 0xFFFF);
+ quotientLo = dividend / divisor;
+ remainder = dividend - quotientLo*divisor;
+ JS_ASSERT(quotientLo <= 0xFFFF && remainder < divisor);
+ *bp = quotientHi << 16 | quotientLo;
+ } while (bp != bx);
+ /* Decrease the size of the number if its most significant word is now zero. */
+ if (bx[n-1] == 0)
+ b->wds--;
+ return remainder;
+}
+
+/* Return floor(b/2^k) and set b to be the remainder. The returned quotient must be less than 2^32. */
+static uint32 quorem2(Bigint *b, int32 k)
+{
+ ULong mask;
+ ULong result;
+ ULong *bx, *bxe;
+ int32 w;
+ int32 n = k >> 5;
+ k &= 0x1F;
+ mask = (1<<k) - 1;
+
+ w = b->wds - n;
+ if (w <= 0)
+ return 0;
+ JS_ASSERT(w <= 2);
+ bx = b->x;
+ bxe = bx + n;
+ result = *bxe >> k;
+ *bxe &= mask;
+ if (w == 2) {
+ JS_ASSERT(!(bxe[1] & ~mask));
+ if (k)
+ result |= bxe[1] << (32 - k);
+ }
+ n++;
+ while (!*bxe && bxe != bx) {
+ n--;
+ bxe--;
+ }
+ b->wds = n;
+ return result;
+}
+
+
+/* "-0.0000...(1073 zeros after decimal point)...0001\0" is the longest string that we could produce,
+ * which occurs when printing -5e-324 in binary. We could compute a better estimate of the size of
+ * the output string and malloc fewer bytes depending on d and base, but why bother? */
+#define DTOBASESTR_BUFFER_SIZE 1078
+#define BASEDIGIT(digit) ((char)(((digit) >= 10) ? 'a' - 10 + (digit) : '0' + (digit)))
+
+JS_FRIEND_API(char *)
+JS_dtobasestr(int base, double dinput)
+{
+ U d;
+ char *buffer; /* The output string */
+ char *p; /* Pointer to current position in the buffer */
+ char *pInt; /* Pointer to the beginning of the integer part of the string */
+ char *q;
+ uint32 digit;
+ U di; /* d truncated to an integer */
+ U df; /* The fractional part of d */
+
+ JS_ASSERT(base >= 2 && base <= 36);
+
+ dval(d) = dinput;
+ buffer = (char*) malloc(DTOBASESTR_BUFFER_SIZE);
+ if (buffer) {
+ p = buffer;
+ if (dval(d) < 0.0
+#if defined(XP_WIN) || defined(XP_OS2)
+ && !((word0(d) & Exp_mask) == Exp_mask && ((word0(d) & Frac_mask) || word1(d))) /* Visual C++ doesn't know how to compare against NaN */
+#endif
+ ) {
+ *p++ = '-';
+ dval(d) = -dval(d);
+ }
+
+ /* Check for Infinity and NaN */
+ if ((word0(d) & Exp_mask) == Exp_mask) {
+ strcpy(p, !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN");
+ return buffer;
+ }
+
+ LOCK_DTOA();
+ /* Output the integer part of d with the digits in reverse order. */
+ pInt = p;
+ dval(di) = floor(dval(d));
+ if (dval(di) <= 4294967295.0) {
+ uint32 n = (uint32)dval(di);
+ if (n)
+ do {
+ uint32 m = n / base;
+ digit = n - m*base;
+ n = m;
+ JS_ASSERT(digit < (uint32)base);
+ *p++ = BASEDIGIT(digit);
+ } while (n);
+ else *p++ = '0';
+ } else {
+ int e;
+ int bits; /* Number of significant bits in di; not used. */
+ Bigint *b = d2b(di, &e, &bits);
+ if (!b)
+ goto nomem1;
+ b = lshift(b, e);
+ if (!b) {
+ nomem1:
+ Bfree(b);
+ UNLOCK_DTOA();
+ free(buffer);
+ return NULL;
+ }
+ do {
+ digit = divrem(b, base);
+ JS_ASSERT(digit < (uint32)base);
+ *p++ = BASEDIGIT(digit);
+ } while (b->wds);
+ Bfree(b);
+ }
+ /* Reverse the digits of the integer part of d. */
+ q = p-1;
+ while (q > pInt) {
+ char ch = *pInt;
+ *pInt++ = *q;
+ *q-- = ch;
+ }
+
+ dval(df) = dval(d) - dval(di);
+ if (dval(df) != 0.0) {
+ /* We have a fraction. */
+ int e, bbits;
+ int32 s2, done;
+ Bigint *b, *s, *mlo, *mhi;
+
+ b = s = mlo = mhi = NULL;
+
+ *p++ = '.';
+ b = d2b(df, &e, &bbits);
+ if (!b) {
+ nomem2:
+ Bfree(b);
+ Bfree(s);
+ if (mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ UNLOCK_DTOA();
+ free(buffer);
+ return NULL;
+ }
+ JS_ASSERT(e < 0);
+ /* At this point df = b * 2^e. e must be less than zero because 0 < df < 1. */
+
+ s2 = -(int32)(word0(d) >> Exp_shift1 & Exp_mask>>Exp_shift1);
+#ifndef Sudden_Underflow
+ if (!s2)
+ s2 = -1;
+#endif
+ s2 += Bias + P;
+ /* 1/2^s2 = (nextDouble(d) - d)/2 */
+ JS_ASSERT(-s2 < e);
+ mlo = i2b(1);
+ if (!mlo)
+ goto nomem2;
+ mhi = mlo;
+ if (!word1(d) && !(word0(d) & Bndry_mask)
+#ifndef Sudden_Underflow
+ && word0(d) & (Exp_mask & Exp_mask << 1)
+#endif
+ ) {
+ /* The special case. Here we want to be within a quarter of the last input
+ significant digit instead of one half of it when the output string's value is less than d. */
+ s2 += Log2P;
+ mhi = i2b(1<<Log2P);
+ if (!mhi)
+ goto nomem2;
+ }
+ b = lshift(b, e + s2);
+ if (!b)
+ goto nomem2;
+ s = i2b(1);
+ if (!s)
+ goto nomem2;
+ s = lshift(s, s2);
+ if (!s)
+ goto nomem2;
+ /* At this point we have the following:
+ * s = 2^s2;
+ * 1 > df = b/2^s2 > 0;
+ * (d - prevDouble(d))/2 = mlo/2^s2;
+ * (nextDouble(d) - d)/2 = mhi/2^s2. */
+
+ done = JS_FALSE;
+ do {
+ int32 j, j1;
+ Bigint *delta;
+
+ b = multadd(b, base, 0);
+ if (!b)
+ goto nomem2;
+ digit = quorem2(b, s2);
+ if (mlo == mhi) {
+ mlo = mhi = multadd(mlo, base, 0);
+ if (!mhi)
+ goto nomem2;
+ }
+ else {
+ mlo = multadd(mlo, base, 0);
+ if (!mlo)
+ goto nomem2;
+ mhi = multadd(mhi, base, 0);
+ if (!mhi)
+ goto nomem2;
+ }
+
+ /* Do we yet have the shortest string that will round to d? */
+ j = cmp(b, mlo);
+ /* j is b/2^s2 compared with mlo/2^s2. */
+ delta = diff(s, mhi);
+ if (!delta)
+ goto nomem2;
+ j1 = delta->sign ? 1 : cmp(b, delta);
+ Bfree(delta);
+ /* j1 is b/2^s2 compared with 1 - mhi/2^s2. */
+
+#ifndef ROUND_BIASED
+ if (j1 == 0 && !(word1(d) & 1)) {
+ if (j > 0)
+ digit++;
+ done = JS_TRUE;
+ } else
+#endif
+ if (j < 0 || (j == 0
+#ifndef ROUND_BIASED
+ && !(word1(d) & 1)
+#endif
+ )) {
+ if (j1 > 0) {
+ /* Either dig or dig+1 would work here as the least significant digit.
+ Use whichever would produce an output value closer to d. */
+ b = lshift(b, 1);
+ if (!b)
+ goto nomem2;
+ j1 = cmp(b, s);
+ if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output
+ * such as 3.5 in base 3. */
+ digit++;
+ }
+ done = JS_TRUE;
+ } else if (j1 > 0) {
+ digit++;
+ done = JS_TRUE;
+ }
+ JS_ASSERT(digit < (uint32)base);
+ *p++ = BASEDIGIT(digit);
+ } while (!done);
+ Bfree(b);
+ Bfree(s);
+ if (mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ }
+ JS_ASSERT(p < buffer + DTOBASESTR_BUFFER_SIZE);
+ *p = '\0';
+ UNLOCK_DTOA();
+ }
+ return buffer;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.h b/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.h
new file mode 100644
index 0000000..b074c9a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.h
@@ -0,0 +1,131 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsdtoa_h___
+#define jsdtoa_h___
+/*
+ * Public interface to portable double-precision floating point to string
+ * and back conversion package.
+ */
+
+#include "jscompat.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * JS_strtod() returns as a double-precision floating-point number
+ * the value represented by the character string pointed to by
+ * s00. The string is scanned up to the first unrecognized
+ * character.
+ * If the value of se is not (char **)NULL, a pointer to
+ * the character terminating the scan is returned in the location pointed
+ * to by se. If no number can be formed, se is set to s00r, and
+ * zero is returned.
+ *
+ * *err is set to zero on success; it's set to JS_DTOA_ERANGE on range
+ * errors and JS_DTOA_ENOMEM on memory failure.
+ */
+#define JS_DTOA_ERANGE 1
+#define JS_DTOA_ENOMEM 2
+JS_FRIEND_API(double)
+JS_strtod(const char *s00, char **se, int *err);
+
+/*
+ * Modes for converting floating-point numbers to strings.
+ *
+ * Some of the modes can round-trip; this means that if the number is converted to
+ * a string using one of these mode and then converted back to a number, the result
+ * will be identical to the original number (except that, due to ECMA, -0 will get converted
+ * to +0). These round-trip modes return the minimum number of significand digits that
+ * permit the round trip.
+ *
+ * Some of the modes take an integer parameter <precision>.
+ */
+/* NB: Keep this in sync with number_constants[]. */
+typedef enum JSDToStrMode {
+ DTOSTR_STANDARD, /* Either fixed or exponential format; round-trip */
+ DTOSTR_STANDARD_EXPONENTIAL, /* Always exponential format; round-trip */
+ DTOSTR_FIXED, /* Round to <precision> digits after the decimal point; exponential if number is large */
+ DTOSTR_EXPONENTIAL, /* Always exponential format; <precision> significant digits */
+ DTOSTR_PRECISION /* Either fixed or exponential format; <precision> significant digits */
+} JSDToStrMode;
+
+
+/* Maximum number of characters (including trailing null) that a DTOSTR_STANDARD or DTOSTR_STANDARD_EXPONENTIAL
+ * conversion can produce. This maximum is reached for a number like -0.0000012345678901234567. */
+#define DTOSTR_STANDARD_BUFFER_SIZE 26
+
+/* Maximum number of characters (including trailing null) that one of the other conversions
+ * can produce. This maximum is reached for TO_FIXED, which can generate up to 21 digits before the decimal point. */
+#define DTOSTR_VARIABLE_BUFFER_SIZE(precision) ((precision)+24 > DTOSTR_STANDARD_BUFFER_SIZE ? (precision)+24 : DTOSTR_STANDARD_BUFFER_SIZE)
+
+/*
+ * Convert dval according to the given mode and return a pointer to the resulting ASCII string.
+ * The result is held somewhere in buffer, but not necessarily at the beginning. The size of
+ * buffer is given in bufferSize, and must be at least as large as given by the above macros.
+ *
+ * Return NULL if out of memory.
+ */
+JS_FRIEND_API(char *)
+JS_dtostr(char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, double dval);
+
+/*
+ * Convert d to a string in the given base. The integral part of d will be printed exactly
+ * in that base, regardless of how large it is, because there is no exponential notation for non-base-ten
+ * numbers. The fractional part will be rounded to as few digits as possible while still preserving
+ * the round-trip property (analogous to that of printing decimal numbers). In other words, if one were
+ * to read the resulting string in via a hypothetical base-number-reading routine that rounds to the nearest
+ * IEEE double (and to an even significand if there are two equally near doubles), then the result would
+ * equal d (except for -0.0, which converts to "0", and NaN, which is not equal to itself).
+ *
+ * Return NULL if out of memory. If the result is not NULL, it must be released via free().
+ */
+JS_FRIEND_API(char *)
+JS_dtobasestr(int base, double d);
+
+/*
+ * Clean up any persistent RAM allocated during the execution of DtoA
+ * routines, and remove any locks that might have been created.
+ */
+JS_FRIEND_API(JSBool) js_InitDtoa(void);
+JS_FRIEND_API(void) js_FinishDtoa(void);
+
+JS_END_EXTERN_C
+
+#endif /* jsdtoa_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.c b/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.c
new file mode 100644
index 0000000..8d95b39
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.c
@@ -0,0 +1,318 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Copyright (C) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsapi.h"
+#include "jsutil.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsdbgapi.h"
+#include "jsfun.h"
+#include "jsinterp.h"
+#include "jsobj.h"
+#include "jsscript.h"
+#include "jsstr.h"
+
+#include "jsdtracef.h"
+#include <sys/types.h>
+
+#define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v))
+
+static char dempty[] = "<null>";
+
+char *
+jsdtrace_funcclass_name(JSFunction *fun)
+{
+ return (!FUN_INTERPRETED(fun) &&
+ !(fun->flags & JSFUN_TRACEABLE) &&
+ FUN_CLASP(fun))
+ ? (char *)FUN_CLASP(fun)->name
+ : dempty;
+}
+
+char *
+jsdtrace_filename(JSStackFrame *fp)
+{
+ while (fp && fp->script == NULL)
+ fp = fp->down;
+ return (fp && fp->script && fp->script->filename)
+ ? (char *)fp->script->filename
+ : dempty;
+}
+
+int
+jsdtrace_linenumber(JSContext *cx, JSStackFrame *fp)
+{
+ while (fp && fp->script == NULL)
+ fp = fp->down;
+ return (fp && fp->regs)
+ ? (int) js_PCToLineNumber(cx, fp->script, fp->regs->pc)
+ : -1;
+}
+
+/*
+ * This function is used to convert function arguments and return value (jsval)
+ * into the following based on each value's type tag:
+ *
+ * jsval returned
+ * -------------------
+ * STRING -> char *
+ * INT -> int
+ * DOUBLE -> double *
+ * BOOLEAN -> int
+ * OBJECT -> void *
+ *
+ * All are presented as void * for DTrace consumers to use, after shifting or
+ * masking out the JavaScript type bits. This allows D scripts to use ints and
+ * booleans directly and copyinstr() for string arguments, when types are known
+ * beforehand.
+ *
+ * This is used by the function-args and function-rval probes, which also
+ * provide raw (unmasked) jsvals should type info be useful from D scripts.
+ */
+void *
+jsdtrace_jsvaltovoid(JSContext *cx, jsval argval)
+{
+ JSType type = TYPEOF(cx, argval);
+
+ switch (type) {
+ case JSTYPE_NULL:
+ case JSTYPE_VOID:
+ return (void *)JS_TYPE_STR(type);
+
+ case JSTYPE_BOOLEAN:
+ return (void *)JSVAL_TO_BOOLEAN(argval);
+
+ case JSTYPE_STRING:
+ return (void *)js_GetStringBytes(cx, JSVAL_TO_STRING(argval));
+
+ case JSTYPE_NUMBER:
+ if (JSVAL_IS_INT(argval))
+ return (void *)JSVAL_TO_INT(argval);
+ return JSVAL_TO_DOUBLE(argval);
+
+ default:
+ return JSVAL_TO_GCTHING(argval);
+ }
+ /* NOTREACHED */
+}
+
+char *
+jsdtrace_function_name(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
+{
+ JSAtom *atom;
+ JSFrameRegs *regs;
+ JSScript *script;
+ jsbytecode *pc;
+ char *name;
+
+ atom = fun->atom;
+ if (!atom) {
+ if (fp->fun != fun || !fp->down)
+ return dempty;
+
+ regs = fp->down->regs;
+ if (!regs)
+ return dempty;
+
+ /*
+ * An anonymous function called from an active script or interpreted
+ * function: try to fetch the variable or property name by which the
+ * anonymous function was invoked.
+ */
+ pc = regs->pc;
+ script = fp->down->script;
+ switch ((JSOp) *pc) {
+ case JSOP_CALL:
+ case JSOP_EVAL:
+ JS_ASSERT(fp->argv == regs->sp - (int)GET_ARGC(pc));
+
+ /*
+ * FIXME bug 422864: update this code to use the pc stack from the
+ * decompiler.
+ */
+ break;
+ default: ;
+ }
+
+ switch ((JSOp) *pc) {
+ case JSOP_CALLNAME:
+ case JSOP_CALLPROP:
+ case JSOP_NAME:
+ case JSOP_SETNAME:
+ case JSOP_GETPROP:
+ case JSOP_SETPROP:
+ GET_ATOM_FROM_BYTECODE(script, pc, 0, atom);
+ break;
+
+ case JSOP_CALLELEM:
+ case JSOP_GETELEM:
+ case JSOP_SETELEM:
+ case JSOP_CALLGVAR:
+ case JSOP_GETGVAR:
+ case JSOP_SETGVAR:
+ case JSOP_CALLARG:
+ case JSOP_CALLLOCAL:
+ /* FIXME: try to recover a name from these ops. */
+ /* FALL THROUGH */
+
+ default:
+ return dempty;
+ }
+ }
+
+ name = (char *)js_GetStringBytes(cx, ATOM_TO_STRING(atom));
+ return name ? name : dempty;
+}
+
+/*
+ * These functions call the DTrace macros for the JavaScript USDT probes.
+ * Originally this code was inlined in the JavaScript code; however since
+ * a number of operations are called, these have been placed into functions
+ * to reduce any negative compiler optimization effect that the addition of
+ * a number of usually unused lines of code would cause.
+ */
+void
+jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
+{
+ JAVASCRIPT_FUNCTION_ENTRY(
+ jsdtrace_filename(fp),
+ jsdtrace_funcclass_name(fun),
+ jsdtrace_function_name(cx, fp, fun)
+ );
+}
+
+void
+jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp,
+ JSFunction *fun)
+{
+ JAVASCRIPT_FUNCTION_INFO(
+ jsdtrace_filename(fp),
+ jsdtrace_funcclass_name(fun),
+ jsdtrace_function_name(cx, fp, fun),
+ fp->script->lineno,
+ jsdtrace_filename(dfp),
+ jsdtrace_linenumber(cx, dfp)
+ );
+}
+
+void
+jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
+{
+ JAVASCRIPT_FUNCTION_ARGS(
+ jsdtrace_filename(fp),
+ jsdtrace_funcclass_name(fun),
+ jsdtrace_function_name(cx, fp, fun),
+ fp->argc, (void *)fp->argv,
+ (fp->argc > 0) ? jsdtrace_jsvaltovoid(cx, fp->argv[0]) : 0,
+ (fp->argc > 1) ? jsdtrace_jsvaltovoid(cx, fp->argv[1]) : 0,
+ (fp->argc > 2) ? jsdtrace_jsvaltovoid(cx, fp->argv[2]) : 0,
+ (fp->argc > 3) ? jsdtrace_jsvaltovoid(cx, fp->argv[3]) : 0,
+ (fp->argc > 4) ? jsdtrace_jsvaltovoid(cx, fp->argv[4]) : 0
+ );
+}
+
+void
+jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
+{
+ JAVASCRIPT_FUNCTION_RVAL(
+ jsdtrace_filename(fp),
+ jsdtrace_funcclass_name(fun),
+ jsdtrace_function_name(cx, fp, fun),
+ jsdtrace_linenumber(cx, fp), (void *)fp->rval,
+ jsdtrace_jsvaltovoid(cx, fp->rval)
+ );
+}
+
+void
+jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
+{
+ JAVASCRIPT_FUNCTION_RETURN(
+ jsdtrace_filename(fp),
+ jsdtrace_funcclass_name(fun),
+ jsdtrace_function_name(cx, fp, fun)
+ );
+}
+
+void
+jsdtrace_object_create_start(JSStackFrame *fp, JSClass *clasp)
+{
+ JAVASCRIPT_OBJECT_CREATE_START(jsdtrace_filename(fp), (char *)clasp->name);
+}
+
+void
+jsdtrace_object_create_done(JSStackFrame *fp, JSClass *clasp)
+{
+ JAVASCRIPT_OBJECT_CREATE_DONE(jsdtrace_filename(fp), (char *)clasp->name);
+}
+
+void
+jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj)
+{
+ JAVASCRIPT_OBJECT_CREATE(
+ jsdtrace_filename(cx->fp),
+ (char *)clasp->name,
+ (uintptr_t)obj,
+ jsdtrace_linenumber(cx, cx->fp)
+ );
+}
+
+void
+jsdtrace_object_finalize(JSObject *obj)
+{
+ JSClass *clasp;
+
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+
+ /* the first arg is NULL - reserved for future use (filename?) */
+ JAVASCRIPT_OBJECT_FINALIZE(NULL, (char *)clasp->name, (uintptr_t)obj);
+}
+
+void
+jsdtrace_execute_start(JSScript *script)
+{
+ JAVASCRIPT_EXECUTE_START(
+ script->filename ? (char *)script->filename : dempty,
+ script->lineno
+ );
+}
+
+void
+jsdtrace_execute_done(JSScript *script)
+{
+ JAVASCRIPT_EXECUTE_DONE(
+ script->filename ? (char *)script->filename : dempty,
+ script->lineno
+ );
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.h b/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.h
new file mode 100644
index 0000000..08f3098
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Copyright (C) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "javascript-trace.h"
+#include "jspubtd.h"
+#include "jsprvtd.h"
+
+#ifndef _JSDTRACEF_H
+#define _JSDTRACEF_H
+
+JS_BEGIN_EXTERN_C
+
+extern void
+jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
+
+extern void
+jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp,
+ JSFunction *fun);
+
+extern void
+jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
+
+extern void
+jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
+
+extern void
+jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
+
+extern void
+jsdtrace_object_create_start(JSStackFrame *fp, JSClass *clasp);
+
+extern void
+jsdtrace_object_create_done(JSStackFrame *fp, JSClass *clasp);
+
+extern void
+jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj);
+
+extern void
+jsdtrace_object_finalize(JSObject *obj);
+
+extern void
+jsdtrace_execute_start(JSScript *script);
+
+extern void
+jsdtrace_execute_done(JSScript *script);
+
+JS_END_EXTERN_C
+
+#endif /* _JSDTRACE_H */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsemit.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsemit.cpp
new file mode 100644
index 0000000..3d2269b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsemit.cpp
@@ -0,0 +1,6857 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS bytecode generation.
+ */
+#include "jsstddef.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsbit.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsnum.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsregexp.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsautooplen.h"
+#include "jsstaticcheck.h"
+
+/* Allocation chunk counts, must be powers of two in general. */
+#define BYTECODE_CHUNK 256 /* code allocation increment */
+#define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */
+#define TRYNOTE_CHUNK 64 /* trynote allocation increment */
+
+/* Macros to compute byte sizes from typed element counts. */
+#define BYTECODE_SIZE(n) ((n) * sizeof(jsbytecode))
+#define SRCNOTE_SIZE(n) ((n) * sizeof(jssrcnote))
+#define TRYNOTE_SIZE(n) ((n) * sizeof(JSTryNote))
+
+static JSBool
+NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind,
+ uintN stackDepth, size_t start, size_t end);
+
+JS_FRIEND_API(void)
+js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, JSParseContext *pc,
+ JSArenaPool *codePool, JSArenaPool *notePool,
+ uintN lineno)
+{
+ memset(cg, 0, sizeof *cg);
+ TREE_CONTEXT_INIT(&cg->treeContext, pc);
+ cg->codePool = codePool;
+ cg->notePool = notePool;
+ cg->codeMark = JS_ARENA_MARK(codePool);
+ cg->noteMark = JS_ARENA_MARK(notePool);
+ cg->current = &cg->main;
+ cg->firstLine = cg->prolog.currentLine = cg->main.currentLine = lineno;
+ ATOM_LIST_INIT(&cg->atomList);
+ cg->prolog.noteMask = cg->main.noteMask = SRCNOTE_CHUNK - 1;
+ ATOM_LIST_INIT(&cg->constList);
+ ATOM_LIST_INIT(&cg->upvarList);
+}
+
+JS_FRIEND_API(void)
+js_FinishCodeGenerator(JSContext *cx, JSCodeGenerator *cg)
+{
+ TREE_CONTEXT_FINISH(cx, &cg->treeContext);
+ JS_ARENA_RELEASE(cg->codePool, cg->codeMark);
+ JS_ARENA_RELEASE(cg->notePool, cg->noteMark);
+
+ /* NB: non-null only after OOM. */
+ if (cg->spanDeps)
+ JS_free(cx, cg->spanDeps);
+
+ if (cg->upvarMap.vector)
+ JS_free(cx, cg->upvarMap.vector);
+}
+
+static ptrdiff_t
+EmitCheck(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t delta)
+{
+ jsbytecode *base, *limit, *next;
+ ptrdiff_t offset, length;
+ size_t incr, size;
+
+ base = CG_BASE(cg);
+ next = CG_NEXT(cg);
+ limit = CG_LIMIT(cg);
+ offset = PTRDIFF(next, base, jsbytecode);
+ if (next + delta > limit) {
+ length = offset + delta;
+ length = (length <= BYTECODE_CHUNK)
+ ? BYTECODE_CHUNK
+ : JS_BIT(JS_CeilingLog2(length));
+ incr = BYTECODE_SIZE(length);
+ if (!base) {
+ JS_ARENA_ALLOCATE_CAST(base, jsbytecode *, cg->codePool, incr);
+ } else {
+ size = BYTECODE_SIZE(PTRDIFF(limit, base, jsbytecode));
+ incr -= size;
+ JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr);
+ }
+ if (!base) {
+ js_ReportOutOfScriptQuota(cx);
+ return -1;
+ }
+ CG_BASE(cg) = base;
+ CG_LIMIT(cg) = base + length;
+ CG_NEXT(cg) = base + offset;
+ }
+ return offset;
+}
+
+static void
+UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target)
+{
+ jsbytecode *pc;
+ JSOp op;
+ const JSCodeSpec *cs;
+ uintN depth;
+ intN nuses, ndefs;
+
+ pc = CG_CODE(cg, target);
+ op = (JSOp) *pc;
+ cs = &js_CodeSpec[op];
+ if (cs->format & JOF_TMPSLOT_MASK) {
+ depth = (uintN) cg->stackDepth +
+ ((cs->format & JOF_TMPSLOT_MASK) >> JOF_TMPSLOT_SHIFT);
+ if (depth > cg->maxStackDepth)
+ cg->maxStackDepth = depth;
+ }
+ nuses = cs->nuses;
+ if (nuses < 0)
+ nuses = js_GetVariableStackUseLength(op, pc);
+ cg->stackDepth -= nuses;
+ JS_ASSERT(cg->stackDepth >= 0);
+ if (cg->stackDepth < 0) {
+ char numBuf[12];
+ JSTokenStream *ts;
+
+ JS_snprintf(numBuf, sizeof numBuf, "%d", target);
+ ts = &cg->treeContext.parseContext->tokenStream;
+ JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING,
+ js_GetErrorMessage, NULL,
+ JSMSG_STACK_UNDERFLOW,
+ ts->filename ? ts->filename : "stdin",
+ numBuf);
+ }
+ ndefs = cs->ndefs;
+ if (ndefs < 0) {
+ JSObject *blockObj;
+
+ /* We just executed IndexParsedObject */
+ JS_ASSERT(op == JSOP_ENTERBLOCK);
+ JS_ASSERT(nuses == 0);
+ blockObj = cg->objectList.lastPob->object;
+ JS_ASSERT(STOBJ_GET_CLASS(blockObj) == &js_BlockClass);
+ JS_ASSERT(JSVAL_IS_VOID(blockObj->fslots[JSSLOT_BLOCK_DEPTH]));
+
+ OBJ_SET_BLOCK_DEPTH(cx, blockObj, cg->stackDepth);
+ ndefs = OBJ_BLOCK_COUNT(cx, blockObj);
+ }
+ cg->stackDepth += ndefs;
+ if ((uintN)cg->stackDepth > cg->maxStackDepth)
+ cg->maxStackDepth = cg->stackDepth;
+}
+
+ptrdiff_t
+js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op)
+{
+ ptrdiff_t offset = EmitCheck(cx, cg, op, 1);
+
+ if (offset >= 0) {
+ *CG_NEXT(cg)++ = (jsbytecode)op;
+ UpdateDepth(cx, cg, offset);
+ }
+ return offset;
+}
+
+ptrdiff_t
+js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1)
+{
+ ptrdiff_t offset = EmitCheck(cx, cg, op, 2);
+
+ if (offset >= 0) {
+ jsbytecode *next = CG_NEXT(cg);
+ next[0] = (jsbytecode)op;
+ next[1] = op1;
+ CG_NEXT(cg) = next + 2;
+ UpdateDepth(cx, cg, offset);
+ }
+ return offset;
+}
+
+ptrdiff_t
+js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1,
+ jsbytecode op2)
+{
+ ptrdiff_t offset = EmitCheck(cx, cg, op, 3);
+
+ if (offset >= 0) {
+ jsbytecode *next = CG_NEXT(cg);
+ next[0] = (jsbytecode)op;
+ next[1] = op1;
+ next[2] = op2;
+ CG_NEXT(cg) = next + 3;
+ UpdateDepth(cx, cg, offset);
+ }
+ return offset;
+}
+
+ptrdiff_t
+js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra)
+{
+ ptrdiff_t length = 1 + (ptrdiff_t)extra;
+ ptrdiff_t offset = EmitCheck(cx, cg, op, length);
+
+ if (offset >= 0) {
+ jsbytecode *next = CG_NEXT(cg);
+ *next = (jsbytecode)op;
+ memset(next + 1, 0, BYTECODE_SIZE(extra));
+ CG_NEXT(cg) = next + length;
+
+ /*
+ * Don't UpdateDepth if op's use-count comes from the immediate
+ * operand yet to be stored in the extra bytes after op.
+ */
+ if (js_CodeSpec[op].nuses >= 0)
+ UpdateDepth(cx, cg, offset);
+ }
+ return offset;
+}
+
+/* XXX too many "... statement" L10N gaffes below -- fix via js.msg! */
+const char js_with_statement_str[] = "with statement";
+const char js_finally_block_str[] = "finally block";
+const char js_script_str[] = "script";
+
+static const char *statementName[] = {
+ "label statement", /* LABEL */
+ "if statement", /* IF */
+ "else statement", /* ELSE */
+ "destructuring body", /* BODY */
+ "switch statement", /* SWITCH */
+ "block", /* BLOCK */
+ js_with_statement_str, /* WITH */
+ "catch block", /* CATCH */
+ "try block", /* TRY */
+ js_finally_block_str, /* FINALLY */
+ js_finally_block_str, /* SUBROUTINE */
+ "do loop", /* DO_LOOP */
+ "for loop", /* FOR_LOOP */
+ "for/in loop", /* FOR_IN_LOOP */
+ "while loop", /* WHILE_LOOP */
+};
+
+JS_STATIC_ASSERT(JS_ARRAY_LENGTH(statementName) == STMT_LIMIT);
+
+static const char *
+StatementName(JSCodeGenerator *cg)
+{
+ if (!cg->treeContext.topStmt)
+ return js_script_str;
+ return statementName[cg->treeContext.topStmt->type];
+}
+
+static void
+ReportStatementTooLarge(JSContext *cx, JSCodeGenerator *cg)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEED_DIET,
+ StatementName(cg));
+}
+
+/**
+ Span-dependent instructions in JS bytecode consist of the jump (JOF_JUMP)
+ and switch (JOF_LOOKUPSWITCH, JOF_TABLESWITCH) format opcodes, subdivided
+ into unconditional (gotos and gosubs), and conditional jumps or branches
+ (which pop a value, test it, and jump depending on its value). Most jumps
+ have just one immediate operand, a signed offset from the jump opcode's pc
+ to the target bytecode. The lookup and table switch opcodes may contain
+ many jump offsets.
+
+ Mozilla bug #80981 (http://bugzilla.mozilla.org/show_bug.cgi?id=80981) was
+ fixed by adding extended "X" counterparts to the opcodes/formats (NB: X is
+ suffixed to prefer JSOP_ORX thereby avoiding a JSOP_XOR name collision for
+ the extended form of the JSOP_OR branch opcode). The unextended or short
+ formats have 16-bit signed immediate offset operands, the extended or long
+ formats have 32-bit signed immediates. The span-dependency problem consists
+ of selecting as few long instructions as possible, or about as few -- since
+ jumps can span other jumps, extending one jump may cause another to need to
+ be extended.
+
+ Most JS scripts are short, so need no extended jumps. We optimize for this
+ case by generating short jumps until we know a long jump is needed. After
+ that point, we keep generating short jumps, but each jump's 16-bit immediate
+ offset operand is actually an unsigned index into cg->spanDeps, an array of
+ JSSpanDep structs. Each struct tells the top offset in the script of the
+ opcode, the "before" offset of the jump (which will be the same as top for
+ simplex jumps, but which will index further into the bytecode array for a
+ non-initial jump offset in a lookup or table switch), the after "offset"
+ adjusted during span-dependent instruction selection (initially the same
+ value as the "before" offset), and the jump target (more below).
+
+ Since we generate cg->spanDeps lazily, from within js_SetJumpOffset, we must
+ ensure that all bytecode generated so far can be inspected to discover where
+ the jump offset immediate operands lie within CG_CODE(cg). But the bonus is
+ that we generate span-dependency records sorted by their offsets, so we can
+ binary-search when trying to find a JSSpanDep for a given bytecode offset,
+ or the nearest JSSpanDep at or above a given pc.
+
+ To avoid limiting scripts to 64K jumps, if the cg->spanDeps index overflows
+ 65534, we store SPANDEP_INDEX_HUGE in the jump's immediate operand. This
+ tells us that we need to binary-search for the cg->spanDeps entry by the
+ jump opcode's bytecode offset (sd->before).
+
+ Jump targets need to be maintained in a data structure that lets us look
+ up an already-known target by its address (jumps may have a common target),
+ and that also lets us update the addresses (script-relative, a.k.a. absolute
+ offsets) of targets that come after a jump target (for when a jump below
+ that target needs to be extended). We use an AVL tree, implemented using
+ recursion, but with some tricky optimizations to its height-balancing code
+ (see http://www.cmcrossroads.com/bradapp/ftp/src/libs/C++/AvlTrees.html).
+
+ A final wrinkle: backpatch chains are linked by jump-to-jump offsets with
+ positive sign, even though they link "backward" (i.e., toward lower bytecode
+ address). We don't want to waste space and search time in the AVL tree for
+ such temporary backpatch deltas, so we use a single-bit wildcard scheme to
+ tag true JSJumpTarget pointers and encode untagged, signed (positive) deltas
+ in JSSpanDep.target pointers, depending on whether the JSSpanDep has a known
+ target, or is still awaiting backpatching.
+
+ Note that backpatch chains would present a problem for BuildSpanDepTable,
+ which inspects bytecode to build cg->spanDeps on demand, when the first
+ short jump offset overflows. To solve this temporary problem, we emit a
+ proxy bytecode (JSOP_BACKPATCH; JSOP_BACKPATCH_POP for branch ops) whose
+ nuses/ndefs counts help keep the stack balanced, but whose opcode format
+ distinguishes its backpatch delta immediate operand from a normal jump
+ offset.
+ */
+static int
+BalanceJumpTargets(JSJumpTarget **jtp)
+{
+ JSJumpTarget *jt, *jt2, *root;
+ int dir, otherDir, heightChanged;
+ JSBool doubleRotate;
+
+ jt = *jtp;
+ JS_ASSERT(jt->balance != 0);
+
+ if (jt->balance < -1) {
+ dir = JT_RIGHT;
+ doubleRotate = (jt->kids[JT_LEFT]->balance > 0);
+ } else if (jt->balance > 1) {
+ dir = JT_LEFT;
+ doubleRotate = (jt->kids[JT_RIGHT]->balance < 0);
+ } else {
+ return 0;
+ }
+
+ otherDir = JT_OTHER_DIR(dir);
+ if (doubleRotate) {
+ jt2 = jt->kids[otherDir];
+ *jtp = root = jt2->kids[dir];
+
+ jt->kids[otherDir] = root->kids[dir];
+ root->kids[dir] = jt;
+
+ jt2->kids[dir] = root->kids[otherDir];
+ root->kids[otherDir] = jt2;
+
+ heightChanged = 1;
+ root->kids[JT_LEFT]->balance = -JS_MAX(root->balance, 0);
+ root->kids[JT_RIGHT]->balance = -JS_MIN(root->balance, 0);
+ root->balance = 0;
+ } else {
+ *jtp = root = jt->kids[otherDir];
+ jt->kids[otherDir] = root->kids[dir];
+ root->kids[dir] = jt;
+
+ heightChanged = (root->balance != 0);
+ jt->balance = -((dir == JT_LEFT) ? --root->balance : ++root->balance);
+ }
+
+ return heightChanged;
+}
+
+typedef struct AddJumpTargetArgs {
+ JSContext *cx;
+ JSCodeGenerator *cg;
+ ptrdiff_t offset;
+ JSJumpTarget *node;
+} AddJumpTargetArgs;
+
+static int
+AddJumpTarget(AddJumpTargetArgs *args, JSJumpTarget **jtp)
+{
+ JSJumpTarget *jt;
+ int balanceDelta;
+
+ jt = *jtp;
+ if (!jt) {
+ JSCodeGenerator *cg = args->cg;
+
+ jt = cg->jtFreeList;
+ if (jt) {
+ cg->jtFreeList = jt->kids[JT_LEFT];
+ } else {
+ JS_ARENA_ALLOCATE_CAST(jt, JSJumpTarget *, &args->cx->tempPool,
+ sizeof *jt);
+ if (!jt) {
+ js_ReportOutOfScriptQuota(args->cx);
+ return 0;
+ }
+ }
+ jt->offset = args->offset;
+ jt->balance = 0;
+ jt->kids[JT_LEFT] = jt->kids[JT_RIGHT] = NULL;
+ cg->numJumpTargets++;
+ args->node = jt;
+ *jtp = jt;
+ return 1;
+ }
+
+ if (jt->offset == args->offset) {
+ args->node = jt;
+ return 0;
+ }
+
+ if (args->offset < jt->offset)
+ balanceDelta = -AddJumpTarget(args, &jt->kids[JT_LEFT]);
+ else
+ balanceDelta = AddJumpTarget(args, &jt->kids[JT_RIGHT]);
+ if (!args->node)
+ return 0;
+
+ jt->balance += balanceDelta;
+ return (balanceDelta && jt->balance)
+ ? 1 - BalanceJumpTargets(jtp)
+ : 0;
+}
+
+#ifdef DEBUG_brendan
+static int AVLCheck(JSJumpTarget *jt)
+{
+ int lh, rh;
+
+ if (!jt) return 0;
+ JS_ASSERT(-1 <= jt->balance && jt->balance <= 1);
+ lh = AVLCheck(jt->kids[JT_LEFT]);
+ rh = AVLCheck(jt->kids[JT_RIGHT]);
+ JS_ASSERT(jt->balance == rh - lh);
+ return 1 + JS_MAX(lh, rh);
+}
+#endif
+
+static JSBool
+SetSpanDepTarget(JSContext *cx, JSCodeGenerator *cg, JSSpanDep *sd,
+ ptrdiff_t off)
+{
+ AddJumpTargetArgs args;
+
+ if (off < JUMPX_OFFSET_MIN || JUMPX_OFFSET_MAX < off) {
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+
+ args.cx = cx;
+ args.cg = cg;
+ args.offset = sd->top + off;
+ args.node = NULL;
+ AddJumpTarget(&args, &cg->jumpTargets);
+ if (!args.node)
+ return JS_FALSE;
+
+#ifdef DEBUG_brendan
+ AVLCheck(cg->jumpTargets);
+#endif
+
+ SD_SET_TARGET(sd, args.node);
+ return JS_TRUE;
+}
+
+#define SPANDEPS_MIN 256
+#define SPANDEPS_SIZE(n) ((n) * sizeof(JSSpanDep))
+#define SPANDEPS_SIZE_MIN SPANDEPS_SIZE(SPANDEPS_MIN)
+
+static JSBool
+AddSpanDep(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, jsbytecode *pc2,
+ ptrdiff_t off)
+{
+ uintN index;
+ JSSpanDep *sdbase, *sd;
+ size_t size;
+
+ index = cg->numSpanDeps;
+ if (index + 1 == 0) {
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+
+ if ((index & (index - 1)) == 0 &&
+ (!(sdbase = cg->spanDeps) || index >= SPANDEPS_MIN)) {
+ size = sdbase ? SPANDEPS_SIZE(index) : SPANDEPS_SIZE_MIN / 2;
+ sdbase = (JSSpanDep *) JS_realloc(cx, sdbase, size + size);
+ if (!sdbase)
+ return JS_FALSE;
+ cg->spanDeps = sdbase;
+ }
+
+ cg->numSpanDeps = index + 1;
+ sd = cg->spanDeps + index;
+ sd->top = PTRDIFF(pc, CG_BASE(cg), jsbytecode);
+ sd->offset = sd->before = PTRDIFF(pc2, CG_BASE(cg), jsbytecode);
+
+ if (js_CodeSpec[*pc].format & JOF_BACKPATCH) {
+ /* Jump offset will be backpatched if off is a non-zero "bpdelta". */
+ if (off != 0) {
+ JS_ASSERT(off >= 1 + JUMP_OFFSET_LEN);
+ if (off > BPDELTA_MAX) {
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+ }
+ SD_SET_BPDELTA(sd, off);
+ } else if (off == 0) {
+ /* Jump offset will be patched directly, without backpatch chaining. */
+ SD_SET_TARGET(sd, 0);
+ } else {
+ /* The jump offset in off is non-zero, therefore it's already known. */
+ if (!SetSpanDepTarget(cx, cg, sd, off))
+ return JS_FALSE;
+ }
+
+ if (index > SPANDEP_INDEX_MAX)
+ index = SPANDEP_INDEX_HUGE;
+ SET_SPANDEP_INDEX(pc2, index);
+ return JS_TRUE;
+}
+
+static jsbytecode *
+AddSwitchSpanDeps(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc)
+{
+ JSOp op;
+ jsbytecode *pc2;
+ ptrdiff_t off;
+ jsint low, high;
+ uintN njumps, indexlen;
+
+ op = (JSOp) *pc;
+ JS_ASSERT(op == JSOP_TABLESWITCH || op == JSOP_LOOKUPSWITCH);
+ pc2 = pc;
+ off = GET_JUMP_OFFSET(pc2);
+ if (!AddSpanDep(cx, cg, pc, pc2, off))
+ return NULL;
+ pc2 += JUMP_OFFSET_LEN;
+ if (op == JSOP_TABLESWITCH) {
+ low = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ njumps = (uintN) (high - low + 1);
+ indexlen = 0;
+ } else {
+ njumps = GET_UINT16(pc2);
+ pc2 += UINT16_LEN;
+ indexlen = INDEX_LEN;
+ }
+ while (njumps) {
+ --njumps;
+ pc2 += indexlen;
+ off = GET_JUMP_OFFSET(pc2);
+ if (!AddSpanDep(cx, cg, pc, pc2, off))
+ return NULL;
+ pc2 += JUMP_OFFSET_LEN;
+ }
+ return 1 + pc2;
+}
+
+static JSBool
+BuildSpanDepTable(JSContext *cx, JSCodeGenerator *cg)
+{
+ jsbytecode *pc, *end;
+ JSOp op;
+ const JSCodeSpec *cs;
+ ptrdiff_t off;
+
+ pc = CG_BASE(cg) + cg->spanDepTodo;
+ end = CG_NEXT(cg);
+ while (pc != end) {
+ JS_ASSERT(pc < end);
+ op = (JSOp)*pc;
+ cs = &js_CodeSpec[op];
+
+ switch (JOF_TYPE(cs->format)) {
+ case JOF_TABLESWITCH:
+ case JOF_LOOKUPSWITCH:
+ pc = AddSwitchSpanDeps(cx, cg, pc);
+ if (!pc)
+ return JS_FALSE;
+ break;
+
+ case JOF_JUMP:
+ off = GET_JUMP_OFFSET(pc);
+ if (!AddSpanDep(cx, cg, pc, pc, off))
+ return JS_FALSE;
+ /* FALL THROUGH */
+ default:
+ pc += cs->length;
+ break;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSSpanDep *
+GetSpanDep(JSCodeGenerator *cg, jsbytecode *pc)
+{
+ uintN index;
+ ptrdiff_t offset;
+ int lo, hi, mid;
+ JSSpanDep *sd;
+
+ index = GET_SPANDEP_INDEX(pc);
+ if (index != SPANDEP_INDEX_HUGE)
+ return cg->spanDeps + index;
+
+ offset = PTRDIFF(pc, CG_BASE(cg), jsbytecode);
+ lo = 0;
+ hi = cg->numSpanDeps - 1;
+ while (lo <= hi) {
+ mid = (lo + hi) / 2;
+ sd = cg->spanDeps + mid;
+ if (sd->before == offset)
+ return sd;
+ if (sd->before < offset)
+ lo = mid + 1;
+ else
+ hi = mid - 1;
+ }
+
+ JS_ASSERT(0);
+ return NULL;
+}
+
+static JSBool
+SetBackPatchDelta(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
+ ptrdiff_t delta)
+{
+ JSSpanDep *sd;
+
+ JS_ASSERT(delta >= 1 + JUMP_OFFSET_LEN);
+ if (!cg->spanDeps && delta < JUMP_OFFSET_MAX) {
+ SET_JUMP_OFFSET(pc, delta);
+ return JS_TRUE;
+ }
+
+ if (delta > BPDELTA_MAX) {
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+
+ if (!cg->spanDeps && !BuildSpanDepTable(cx, cg))
+ return JS_FALSE;
+
+ sd = GetSpanDep(cg, pc);
+ JS_ASSERT(SD_GET_BPDELTA(sd) == 0);
+ SD_SET_BPDELTA(sd, delta);
+ return JS_TRUE;
+}
+
+static void
+UpdateJumpTargets(JSJumpTarget *jt, ptrdiff_t pivot, ptrdiff_t delta)
+{
+ if (jt->offset > pivot) {
+ jt->offset += delta;
+ if (jt->kids[JT_LEFT])
+ UpdateJumpTargets(jt->kids[JT_LEFT], pivot, delta);
+ }
+ if (jt->kids[JT_RIGHT])
+ UpdateJumpTargets(jt->kids[JT_RIGHT], pivot, delta);
+}
+
+static JSSpanDep *
+FindNearestSpanDep(JSCodeGenerator *cg, ptrdiff_t offset, int lo,
+ JSSpanDep *guard)
+{
+ int num, hi, mid;
+ JSSpanDep *sdbase, *sd;
+
+ num = cg->numSpanDeps;
+ JS_ASSERT(num > 0);
+ hi = num - 1;
+ sdbase = cg->spanDeps;
+ while (lo <= hi) {
+ mid = (lo + hi) / 2;
+ sd = sdbase + mid;
+ if (sd->before == offset)
+ return sd;
+ if (sd->before < offset)
+ lo = mid + 1;
+ else
+ hi = mid - 1;
+ }
+ if (lo == num)
+ return guard;
+ sd = sdbase + lo;
+ JS_ASSERT(sd->before >= offset && (lo == 0 || sd[-1].before < offset));
+ return sd;
+}
+
+static void
+FreeJumpTargets(JSCodeGenerator *cg, JSJumpTarget *jt)
+{
+ if (jt->kids[JT_LEFT])
+ FreeJumpTargets(cg, jt->kids[JT_LEFT]);
+ if (jt->kids[JT_RIGHT])
+ FreeJumpTargets(cg, jt->kids[JT_RIGHT]);
+ jt->kids[JT_LEFT] = cg->jtFreeList;
+ cg->jtFreeList = jt;
+}
+
+static JSBool
+OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg)
+{
+ jsbytecode *pc, *oldpc, *base, *limit, *next;
+ JSSpanDep *sd, *sd2, *sdbase, *sdlimit, *sdtop, guard;
+ ptrdiff_t offset, growth, delta, top, pivot, span, length, target;
+ JSBool done;
+ JSOp op;
+ uint32 type;
+ size_t size, incr;
+ jssrcnote *sn, *snlimit;
+ JSSrcNoteSpec *spec;
+ uintN i, n, noteIndex;
+ JSTryNode *tryNode;
+#ifdef DEBUG_brendan
+ int passes = 0;
+#endif
+
+ base = CG_BASE(cg);
+ sdbase = cg->spanDeps;
+ sdlimit = sdbase + cg->numSpanDeps;
+ offset = CG_OFFSET(cg);
+ growth = 0;
+
+ do {
+ done = JS_TRUE;
+ delta = 0;
+ top = pivot = -1;
+ sdtop = NULL;
+ pc = NULL;
+ op = JSOP_NOP;
+ type = 0;
+#ifdef DEBUG_brendan
+ passes++;
+#endif
+
+ for (sd = sdbase; sd < sdlimit; sd++) {
+ JS_ASSERT(JT_HAS_TAG(sd->target));
+ sd->offset += delta;
+
+ if (sd->top != top) {
+ sdtop = sd;
+ top = sd->top;
+ JS_ASSERT(top == sd->before);
+ pivot = sd->offset;
+ pc = base + top;
+ op = (JSOp) *pc;
+ type = JOF_OPTYPE(op);
+ if (JOF_TYPE_IS_EXTENDED_JUMP(type)) {
+ /*
+ * We already extended all the jump offset operands for
+ * the opcode at sd->top. Jumps and branches have only
+ * one jump offset operand, but switches have many, all
+ * of which are adjacent in cg->spanDeps.
+ */
+ continue;
+ }
+
+ JS_ASSERT(type == JOF_JUMP ||
+ type == JOF_TABLESWITCH ||
+ type == JOF_LOOKUPSWITCH);
+ }
+
+ if (!JOF_TYPE_IS_EXTENDED_JUMP(type)) {
+ span = SD_SPAN(sd, pivot);
+ if (span < JUMP_OFFSET_MIN || JUMP_OFFSET_MAX < span) {
+ ptrdiff_t deltaFromTop = 0;
+
+ done = JS_FALSE;
+
+ switch (op) {
+ case JSOP_GOTO: op = JSOP_GOTOX; break;
+ case JSOP_IFEQ: op = JSOP_IFEQX; break;
+ case JSOP_IFNE: op = JSOP_IFNEX; break;
+ case JSOP_OR: op = JSOP_ORX; break;
+ case JSOP_AND: op = JSOP_ANDX; break;
+ case JSOP_GOSUB: op = JSOP_GOSUBX; break;
+ case JSOP_CASE: op = JSOP_CASEX; break;
+ case JSOP_DEFAULT: op = JSOP_DEFAULTX; break;
+ case JSOP_TABLESWITCH: op = JSOP_TABLESWITCHX; break;
+ case JSOP_LOOKUPSWITCH: op = JSOP_LOOKUPSWITCHX; break;
+ default:
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+ *pc = (jsbytecode) op;
+
+ for (sd2 = sdtop; sd2 < sdlimit && sd2->top == top; sd2++) {
+ if (sd2 <= sd) {
+ /*
+ * sd2->offset already includes delta as it stood
+ * before we entered this loop, but it must also
+ * include the delta relative to top due to all the
+ * extended jump offset immediates for the opcode
+ * starting at top, which we extend in this loop.
+ *
+ * If there is only one extended jump offset, then
+ * sd2->offset won't change and this for loop will
+ * iterate once only.
+ */
+ sd2->offset += deltaFromTop;
+ deltaFromTop += JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN;
+ } else {
+ /*
+ * sd2 comes after sd, and won't be revisited by
+ * the outer for loop, so we have to increase its
+ * offset by delta, not merely by deltaFromTop.
+ */
+ sd2->offset += delta;
+ }
+
+ delta += JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN;
+ UpdateJumpTargets(cg->jumpTargets, sd2->offset,
+ JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN);
+ }
+ sd = sd2 - 1;
+ }
+ }
+ }
+
+ growth += delta;
+ } while (!done);
+
+ if (growth) {
+#ifdef DEBUG_brendan
+ JSTokenStream *ts = &cg->treeContext.parseContext->tokenStream;
+
+ printf("%s:%u: %u/%u jumps extended in %d passes (%d=%d+%d)\n",
+ ts->filename ? ts->filename : "stdin", cg->firstLine,
+ growth / (JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN), cg->numSpanDeps,
+ passes, offset + growth, offset, growth);
+#endif
+
+ /*
+ * Ensure that we have room for the extended jumps, but don't round up
+ * to a power of two -- we're done generating code, so we cut to fit.
+ */
+ limit = CG_LIMIT(cg);
+ length = offset + growth;
+ next = base + length;
+ if (next > limit) {
+ JS_ASSERT(length > BYTECODE_CHUNK);
+ size = BYTECODE_SIZE(PTRDIFF(limit, base, jsbytecode));
+ incr = BYTECODE_SIZE(length) - size;
+ JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr);
+ if (!base) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ CG_BASE(cg) = base;
+ CG_LIMIT(cg) = next = base + length;
+ }
+ CG_NEXT(cg) = next;
+
+ /*
+ * Set up a fake span dependency record to guard the end of the code
+ * being generated. This guard record is returned as a fencepost by
+ * FindNearestSpanDep if there is no real spandep at or above a given
+ * unextended code offset.
+ */
+ guard.top = -1;
+ guard.offset = offset + growth;
+ guard.before = offset;
+ guard.target = NULL;
+ }
+
+ /*
+ * Now work backwards through the span dependencies, copying chunks of
+ * bytecode between each extended jump toward the end of the grown code
+ * space, and restoring immediate offset operands for all jump bytecodes.
+ * The first chunk of bytecodes, starting at base and ending at the first
+ * extended jump offset (NB: this chunk includes the operation bytecode
+ * just before that immediate jump offset), doesn't need to be copied.
+ */
+ JS_ASSERT(sd == sdlimit);
+ top = -1;
+ while (--sd >= sdbase) {
+ if (sd->top != top) {
+ top = sd->top;
+ op = (JSOp) base[top];
+ type = JOF_OPTYPE(op);
+
+ for (sd2 = sd - 1; sd2 >= sdbase && sd2->top == top; sd2--)
+ continue;
+ sd2++;
+ pivot = sd2->offset;
+ JS_ASSERT(top == sd2->before);
+ }
+
+ oldpc = base + sd->before;
+ span = SD_SPAN(sd, pivot);
+
+ /*
+ * If this jump didn't need to be extended, restore its span immediate
+ * offset operand now, overwriting the index of sd within cg->spanDeps
+ * that was stored temporarily after *pc when BuildSpanDepTable ran.
+ *
+ * Note that span might fit in 16 bits even for an extended jump op,
+ * if the op has multiple span operands, not all of which overflowed
+ * (e.g. JSOP_LOOKUPSWITCH or JSOP_TABLESWITCH where some cases are in
+ * range for a short jump, but others are not).
+ */
+ if (!JOF_TYPE_IS_EXTENDED_JUMP(type)) {
+ JS_ASSERT(JUMP_OFFSET_MIN <= span && span <= JUMP_OFFSET_MAX);
+ SET_JUMP_OFFSET(oldpc, span);
+ continue;
+ }
+
+ /*
+ * Set up parameters needed to copy the next run of bytecode starting
+ * at offset (which is a cursor into the unextended, original bytecode
+ * vector), down to sd->before (a cursor of the same scale as offset,
+ * it's the index of the original jump pc). Reuse delta to count the
+ * nominal number of bytes to copy.
+ */
+ pc = base + sd->offset;
+ delta = offset - sd->before;
+ JS_ASSERT(delta >= 1 + JUMP_OFFSET_LEN);
+
+ /*
+ * Don't bother copying the jump offset we're about to reset, but do
+ * copy the bytecode at oldpc (which comes just before its immediate
+ * jump offset operand), on the next iteration through the loop, by
+ * including it in offset's new value.
+ */
+ offset = sd->before + 1;
+ size = BYTECODE_SIZE(delta - (1 + JUMP_OFFSET_LEN));
+ if (size) {
+ memmove(pc + 1 + JUMPX_OFFSET_LEN,
+ oldpc + 1 + JUMP_OFFSET_LEN,
+ size);
+ }
+
+ SET_JUMPX_OFFSET(pc, span);
+ }
+
+ if (growth) {
+ /*
+ * Fix source note deltas. Don't hardwire the delta fixup adjustment,
+ * even though currently it must be JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN
+ * at each sd that moved. The future may bring different offset sizes
+ * for span-dependent instruction operands. However, we fix only main
+ * notes here, not prolog notes -- we know that prolog opcodes are not
+ * span-dependent, and aren't likely ever to be.
+ */
+ offset = growth = 0;
+ sd = sdbase;
+ for (sn = cg->main.notes, snlimit = sn + cg->main.noteCount;
+ sn < snlimit;
+ sn = SN_NEXT(sn)) {
+ /*
+ * Recall that the offset of a given note includes its delta, and
+ * tells the offset of the annotated bytecode from the main entry
+ * point of the script.
+ */
+ offset += SN_DELTA(sn);
+ while (sd < sdlimit && sd->before < offset) {
+ /*
+ * To compute the delta to add to sn, we need to look at the
+ * spandep after sd, whose offset - (before + growth) tells by
+ * how many bytes sd's instruction grew.
+ */
+ sd2 = sd + 1;
+ if (sd2 == sdlimit)
+ sd2 = &guard;
+ delta = sd2->offset - (sd2->before + growth);
+ if (delta > 0) {
+ JS_ASSERT(delta == JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN);
+ sn = js_AddToSrcNoteDelta(cx, cg, sn, delta);
+ if (!sn)
+ return JS_FALSE;
+ snlimit = cg->main.notes + cg->main.noteCount;
+ growth += delta;
+ }
+ sd++;
+ }
+
+ /*
+ * If sn has span-dependent offset operands, check whether each
+ * covers further span-dependencies, and increase those operands
+ * accordingly. Some source notes measure offset not from the
+ * annotated pc, but from that pc plus some small bias. NB: we
+ * assume that spec->offsetBias can't itself span span-dependent
+ * instructions!
+ */
+ spec = &js_SrcNoteSpec[SN_TYPE(sn)];
+ if (spec->isSpanDep) {
+ pivot = offset + spec->offsetBias;
+ n = spec->arity;
+ for (i = 0; i < n; i++) {
+ span = js_GetSrcNoteOffset(sn, i);
+ if (span == 0)
+ continue;
+ target = pivot + span * spec->isSpanDep;
+ sd2 = FindNearestSpanDep(cg, target,
+ (target >= pivot)
+ ? sd - sdbase
+ : 0,
+ &guard);
+
+ /*
+ * Increase target by sd2's before-vs-after offset delta,
+ * which is absolute (i.e., relative to start of script,
+ * as is target). Recompute the span by subtracting its
+ * adjusted pivot from target.
+ */
+ target += sd2->offset - sd2->before;
+ span = target - (pivot + growth);
+ span *= spec->isSpanDep;
+ noteIndex = sn - cg->main.notes;
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, i, span))
+ return JS_FALSE;
+ sn = cg->main.notes + noteIndex;
+ snlimit = cg->main.notes + cg->main.noteCount;
+ }
+ }
+ }
+ cg->main.lastNoteOffset += growth;
+
+ /*
+ * Fix try/catch notes (O(numTryNotes * log2(numSpanDeps)), but it's
+ * not clear how we can beat that).
+ */
+ for (tryNode = cg->lastTryNode; tryNode; tryNode = tryNode->prev) {
+ /*
+ * First, look for the nearest span dependency at/above tn->start.
+ * There may not be any such spandep, in which case the guard will
+ * be returned.
+ */
+ offset = tryNode->note.start;
+ sd = FindNearestSpanDep(cg, offset, 0, &guard);
+ delta = sd->offset - sd->before;
+ tryNode->note.start = offset + delta;
+
+ /*
+ * Next, find the nearest spandep at/above tn->start + tn->length.
+ * Use its delta minus tn->start's delta to increase tn->length.
+ */
+ length = tryNode->note.length;
+ sd2 = FindNearestSpanDep(cg, offset + length, sd - sdbase, &guard);
+ if (sd2 != sd) {
+ tryNode->note.length =
+ length + sd2->offset - sd2->before - delta;
+ }
+ }
+ }
+
+#ifdef DEBUG_brendan
+ {
+ uintN bigspans = 0;
+ top = -1;
+ for (sd = sdbase; sd < sdlimit; sd++) {
+ offset = sd->offset;
+
+ /* NB: sd->top cursors into the original, unextended bytecode vector. */
+ if (sd->top != top) {
+ JS_ASSERT(top == -1 ||
+ !JOF_TYPE_IS_EXTENDED_JUMP(type) ||
+ bigspans != 0);
+ bigspans = 0;
+ top = sd->top;
+ JS_ASSERT(top == sd->before);
+ op = (JSOp) base[offset];
+ type = JOF_OPTYPE(op);
+ JS_ASSERT(type == JOF_JUMP ||
+ type == JOF_JUMPX ||
+ type == JOF_TABLESWITCH ||
+ type == JOF_TABLESWITCHX ||
+ type == JOF_LOOKUPSWITCH ||
+ type == JOF_LOOKUPSWITCHX);
+ pivot = offset;
+ }
+
+ pc = base + offset;
+ if (JOF_TYPE_IS_EXTENDED_JUMP(type)) {
+ span = GET_JUMPX_OFFSET(pc);
+ if (span < JUMP_OFFSET_MIN || JUMP_OFFSET_MAX < span) {
+ bigspans++;
+ } else {
+ JS_ASSERT(type == JOF_TABLESWITCHX ||
+ type == JOF_LOOKUPSWITCHX);
+ }
+ } else {
+ span = GET_JUMP_OFFSET(pc);
+ }
+ JS_ASSERT(SD_SPAN(sd, pivot) == span);
+ }
+ JS_ASSERT(!JOF_TYPE_IS_EXTENDED_JUMP(type) || bigspans != 0);
+ }
+#endif
+
+ /*
+ * Reset so we optimize at most once -- cg may be used for further code
+ * generation of successive, independent, top-level statements. No jump
+ * can span top-level statements, because JS lacks goto.
+ */
+ size = SPANDEPS_SIZE(JS_BIT(JS_CeilingLog2(cg->numSpanDeps)));
+ JS_free(cx, cg->spanDeps);
+ cg->spanDeps = NULL;
+ FreeJumpTargets(cg, cg->jumpTargets);
+ cg->jumpTargets = NULL;
+ cg->numSpanDeps = cg->numJumpTargets = 0;
+ cg->spanDepTodo = CG_OFFSET(cg);
+ return JS_TRUE;
+}
+
+static ptrdiff_t
+EmitJump(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t off)
+{
+ JSBool extend;
+ ptrdiff_t jmp;
+ jsbytecode *pc;
+
+ extend = off < JUMP_OFFSET_MIN || JUMP_OFFSET_MAX < off;
+ if (extend && !cg->spanDeps && !BuildSpanDepTable(cx, cg))
+ return -1;
+
+ jmp = js_Emit3(cx, cg, op, JUMP_OFFSET_HI(off), JUMP_OFFSET_LO(off));
+ if (jmp >= 0 && (extend || cg->spanDeps)) {
+ pc = CG_CODE(cg, jmp);
+ if (!AddSpanDep(cx, cg, pc, pc, off))
+ return -1;
+ }
+ return jmp;
+}
+
+static ptrdiff_t
+GetJumpOffset(JSCodeGenerator *cg, jsbytecode *pc)
+{
+ JSSpanDep *sd;
+ JSJumpTarget *jt;
+ ptrdiff_t top;
+
+ if (!cg->spanDeps)
+ return GET_JUMP_OFFSET(pc);
+
+ sd = GetSpanDep(cg, pc);
+ jt = sd->target;
+ if (!JT_HAS_TAG(jt))
+ return JT_TO_BPDELTA(jt);
+
+ top = sd->top;
+ while (--sd >= cg->spanDeps && sd->top == top)
+ continue;
+ sd++;
+ return JT_CLR_TAG(jt)->offset - sd->offset;
+}
+
+JSBool
+js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
+ ptrdiff_t off)
+{
+ if (!cg->spanDeps) {
+ if (JUMP_OFFSET_MIN <= off && off <= JUMP_OFFSET_MAX) {
+ SET_JUMP_OFFSET(pc, off);
+ return JS_TRUE;
+ }
+
+ if (!BuildSpanDepTable(cx, cg))
+ return JS_FALSE;
+ }
+
+ return SetSpanDepTarget(cx, cg, GetSpanDep(cg, pc), off);
+}
+
+JSBool
+js_InStatement(JSTreeContext *tc, JSStmtType type)
+{
+ JSStmtInfo *stmt;
+
+ for (stmt = tc->topStmt; stmt; stmt = stmt->down) {
+ if (stmt->type == type)
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+void
+js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,
+ ptrdiff_t top)
+{
+ stmt->type = type;
+ stmt->flags = 0;
+ SET_STATEMENT_TOP(stmt, top);
+ stmt->u.label = NULL;
+ JS_ASSERT(!stmt->u.blockObj);
+ stmt->down = tc->topStmt;
+ tc->topStmt = stmt;
+ if (STMT_LINKS_SCOPE(stmt)) {
+ stmt->downScope = tc->topScopeStmt;
+ tc->topScopeStmt = stmt;
+ } else {
+ stmt->downScope = NULL;
+ }
+}
+
+void
+js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObject *blockObj,
+ ptrdiff_t top)
+{
+
+ js_PushStatement(tc, stmt, STMT_BLOCK, top);
+ stmt->flags |= SIF_SCOPE;
+ STOBJ_SET_PARENT(blockObj, tc->blockChain);
+ stmt->downScope = tc->topScopeStmt;
+ tc->topScopeStmt = stmt;
+ tc->blockChain = blockObj;
+ stmt->u.blockObj = blockObj;
+}
+
+/*
+ * Emit a backpatch op with offset pointing to the previous jump of this type,
+ * so that we can walk back up the chain fixing up the op and jump offset.
+ */
+static ptrdiff_t
+EmitBackPatchOp(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t *lastp)
+{
+ ptrdiff_t offset, delta;
+
+ offset = CG_OFFSET(cg);
+ delta = offset - *lastp;
+ *lastp = offset;
+ JS_ASSERT(delta > 0);
+ return EmitJump(cx, cg, op, delta);
+}
+
+/*
+ * Macro to emit a bytecode followed by a uint16 immediate operand stored in
+ * big-endian order, used for arg and var numbers as well as for atomIndexes.
+ * NB: We use cx and cg from our caller's lexical environment, and return
+ * false on error.
+ */
+#define EMIT_UINT16_IMM_OP(op, i) \
+ JS_BEGIN_MACRO \
+ if (js_Emit3(cx, cg, op, UINT16_HI(i), UINT16_LO(i)) < 0) \
+ return JS_FALSE; \
+ JS_END_MACRO
+
+static JSBool
+FlushPops(JSContext *cx, JSCodeGenerator *cg, intN *npops)
+{
+ JS_ASSERT(*npops != 0);
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(JSOP_POPN, *npops);
+ *npops = 0;
+ return JS_TRUE;
+}
+
+/*
+ * Emit additional bytecode(s) for non-local jumps.
+ */
+static JSBool
+EmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt)
+{
+ intN depth, npops;
+ JSStmtInfo *stmt;
+
+ /*
+ * The non-local jump fixup we emit will unbalance cg->stackDepth, because
+ * the fixup replicates balanced code such as JSOP_LEAVEWITH emitted at the
+ * end of a with statement, so we save cg->stackDepth here and restore it
+ * just before a successful return.
+ */
+ depth = cg->stackDepth;
+ npops = 0;
+
+#define FLUSH_POPS() if (npops && !FlushPops(cx, cg, &npops)) return JS_FALSE
+
+ for (stmt = cg->treeContext.topStmt; stmt != toStmt; stmt = stmt->down) {
+ switch (stmt->type) {
+ case STMT_FINALLY:
+ FLUSH_POPS();
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ if (EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &GOSUBS(*stmt)) < 0)
+ return JS_FALSE;
+ break;
+
+ case STMT_WITH:
+ /* There's a With object on the stack that we need to pop. */
+ FLUSH_POPS();
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0)
+ return JS_FALSE;
+ break;
+
+ case STMT_FOR_IN_LOOP:
+ /*
+ * The iterator and the object being iterated need to be popped.
+ */
+ FLUSH_POPS();
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_ENDITER) < 0)
+ return JS_FALSE;
+ break;
+
+ case STMT_SUBROUTINE:
+ /*
+ * There's a [exception or hole, retsub pc-index] pair on the
+ * stack that we need to pop.
+ */
+ npops += 2;
+ break;
+
+ default:;
+ }
+
+ if (stmt->flags & SIF_SCOPE) {
+ uintN i;
+
+ /* There is a Block object with locals on the stack to pop. */
+ FLUSH_POPS();
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ i = OBJ_BLOCK_COUNT(cx, stmt->u.blockObj);
+ EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, i);
+ }
+ }
+
+ FLUSH_POPS();
+ cg->stackDepth = depth;
+ return JS_TRUE;
+
+#undef FLUSH_POPS
+}
+
+static ptrdiff_t
+EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,
+ ptrdiff_t *lastp, JSAtomListElement *label, JSSrcNoteType noteType)
+{
+ intN index;
+
+ if (!EmitNonLocalJumpFixup(cx, cg, toStmt))
+ return -1;
+
+ if (label)
+ index = js_NewSrcNote2(cx, cg, noteType, (ptrdiff_t) ALE_INDEX(label));
+ else if (noteType != SRC_NULL)
+ index = js_NewSrcNote(cx, cg, noteType);
+ else
+ index = 0;
+ if (index < 0)
+ return -1;
+
+ return EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, lastp);
+}
+
+static JSBool
+BackPatch(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t last,
+ jsbytecode *target, jsbytecode op)
+{
+ jsbytecode *pc, *stop;
+ ptrdiff_t delta, span;
+
+ pc = CG_CODE(cg, last);
+ stop = CG_CODE(cg, -1);
+ while (pc != stop) {
+ delta = GetJumpOffset(cg, pc);
+ span = PTRDIFF(target, pc, jsbytecode);
+ CHECK_AND_SET_JUMP_OFFSET(cx, cg, pc, span);
+
+ /*
+ * Set *pc after jump offset in case bpdelta didn't overflow, but span
+ * does (if so, CHECK_AND_SET_JUMP_OFFSET might call BuildSpanDepTable
+ * and need to see the JSOP_BACKPATCH* op at *pc).
+ */
+ *pc = op;
+ pc -= delta;
+ }
+ return JS_TRUE;
+}
+
+void
+js_PopStatement(JSTreeContext *tc)
+{
+ JSStmtInfo *stmt;
+
+ stmt = tc->topStmt;
+ tc->topStmt = stmt->down;
+ if (STMT_LINKS_SCOPE(stmt)) {
+ tc->topScopeStmt = stmt->downScope;
+ if (stmt->flags & SIF_SCOPE) {
+ tc->blockChain = STOBJ_GET_PARENT(stmt->u.blockObj);
+ JS_SCOPE_DEPTH_METERING(--tc->scopeDepth);
+ }
+ }
+}
+
+JSBool
+js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg)
+{
+ JSStmtInfo *stmt;
+
+ stmt = cg->treeContext.topStmt;
+ if (!STMT_IS_TRYING(stmt) &&
+ (!BackPatch(cx, cg, stmt->breaks, CG_NEXT(cg), JSOP_GOTO) ||
+ !BackPatch(cx, cg, stmt->continues, CG_CODE(cg, stmt->update),
+ JSOP_GOTO))) {
+ return JS_FALSE;
+ }
+ js_PopStatement(&cg->treeContext);
+ return JS_TRUE;
+}
+
+JSBool
+js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
+ JSParseNode *pn)
+{
+ jsdouble dval;
+ jsint ival;
+ JSAtom *valueAtom;
+ jsval v;
+ JSAtomListElement *ale;
+
+ /* XXX just do numbers for now */
+ if (pn->pn_type == TOK_NUMBER) {
+ dval = pn->pn_dval;
+ if (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) {
+ v = INT_TO_JSVAL(ival);
+ } else {
+ /*
+ * We atomize double to root a jsdouble instance that we wrap as
+ * jsval and store in cg->constList. This works because atoms are
+ * protected from GC during compilation.
+ */
+ valueAtom = js_AtomizeDouble(cx, dval);
+ if (!valueAtom)
+ return JS_FALSE;
+ v = ATOM_KEY(valueAtom);
+ }
+ ale = js_IndexAtom(cx, atom, &cg->constList);
+ if (!ale)
+ return JS_FALSE;
+ ALE_SET_VALUE(ale, v);
+ }
+ return JS_TRUE;
+}
+
+JSStmtInfo *
+js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp)
+{
+ JSStmtInfo *stmt;
+ JSObject *obj;
+ JSScope *scope;
+ JSScopeProperty *sprop;
+
+ for (stmt = tc->topScopeStmt; stmt; stmt = stmt->downScope) {
+ if (stmt->type == STMT_WITH)
+ break;
+
+ /* Skip "maybe scope" statements that don't contain let bindings. */
+ if (!(stmt->flags & SIF_SCOPE))
+ continue;
+
+ obj = stmt->u.blockObj;
+ JS_ASSERT(LOCKED_OBJ_GET_CLASS(obj) == &js_BlockClass);
+ scope = OBJ_SCOPE(obj);
+ sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom));
+ if (sprop) {
+ JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
+
+ if (slotp) {
+ JS_ASSERT(JSVAL_IS_INT(obj->fslots[JSSLOT_BLOCK_DEPTH]));
+ *slotp = JSVAL_TO_INT(obj->fslots[JSSLOT_BLOCK_DEPTH]) +
+ sprop->shortid;
+ }
+ return stmt;
+ }
+ }
+
+ if (slotp)
+ *slotp = -1;
+ return stmt;
+}
+
+/*
+ * Check if the attributes describe a property holding a compile-time constant
+ * or a permanent, read-only property without a getter.
+ */
+#define IS_CONSTANT_PROPERTY(attrs) \
+ (((attrs) & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_GETTER)) == \
+ (JSPROP_READONLY | JSPROP_PERMANENT))
+
+/*
+ * The function sets vp to JSVAL_HOLE when the atom does not corresponds to a
+ * name defining a constant.
+ */
+static JSBool
+LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
+ jsval *vp)
+{
+ JSBool ok;
+ JSStmtInfo *stmt;
+ JSAtomListElement *ale;
+ JSObject *obj, *pobj;
+ JSProperty *prop;
+ uintN attrs;
+
+ /*
+ * Chase down the cg stack, but only until we reach the outermost cg.
+ * This enables propagating consts from top-level into switch cases in a
+ * function compiled along with the top-level script.
+ */
+ *vp = JSVAL_HOLE;
+ do {
+ if (cg->treeContext.flags & (TCF_IN_FUNCTION | TCF_COMPILE_N_GO)) {
+ /* XXX this will need revising when 'let const' is added. */
+ stmt = js_LexicalLookup(&cg->treeContext, atom, NULL);
+ if (stmt)
+ return JS_TRUE;
+
+ ATOM_LIST_SEARCH(ale, &cg->constList, atom);
+ if (ale) {
+ JS_ASSERT(ALE_VALUE(ale) != JSVAL_HOLE);
+ *vp = ALE_VALUE(ale);
+ return JS_TRUE;
+ }
+
+ /*
+ * Try looking in the variable object for a direct property that
+ * is readonly and permanent. We know such a property can't be
+ * shadowed by another property on obj's prototype chain, or a
+ * with object or catch variable; nor can prop's value be changed,
+ * nor can prop be deleted.
+ */
+ if (cg->treeContext.flags & TCF_IN_FUNCTION) {
+ if (js_LookupLocal(cx, cg->treeContext.u.fun, atom, NULL) !=
+ JSLOCAL_NONE) {
+ break;
+ }
+ } else {
+ JS_ASSERT(cg->treeContext.flags & TCF_COMPILE_N_GO);
+ obj = cg->treeContext.u.scopeChain;
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &pobj,
+ &prop);
+ if (!ok)
+ return JS_FALSE;
+ if (pobj == obj) {
+ /*
+ * We're compiling code that will be executed immediately,
+ * not re-executed against a different scope chain and/or
+ * variable object. Therefore we can get constant values
+ * from our variable object here.
+ */
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop,
+ &attrs);
+ if (ok && IS_CONSTANT_PROPERTY(attrs)) {
+ ok = OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+ JS_ASSERT_IF(ok, *vp != JSVAL_HOLE);
+ }
+ }
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ if (!ok)
+ return JS_FALSE;
+ if (prop)
+ break;
+ }
+ }
+ } while ((cg = cg->parent) != NULL);
+ return JS_TRUE;
+}
+
+/*
+ * Return JSOP_NOP to indicate that index fits 2 bytes and no index segment
+ * reset instruction is necessary, JSOP_FALSE to indicate an error or either
+ * JSOP_RESETBASE0 or JSOP_RESETBASE1 to indicate the reset bytecode to issue
+ * after the main bytecode sequence.
+ */
+static JSOp
+EmitBigIndexPrefix(JSContext *cx, JSCodeGenerator *cg, uintN index)
+{
+ uintN indexBase;
+
+ /*
+ * We have max 3 bytes for indexes and check for INDEX_LIMIT overflow only
+ * for big indexes.
+ */
+ JS_STATIC_ASSERT(INDEX_LIMIT <= JS_BIT(24));
+ JS_STATIC_ASSERT(INDEX_LIMIT >=
+ (JSOP_INDEXBASE3 - JSOP_INDEXBASE1 + 2) << 16);
+
+ if (index < JS_BIT(16))
+ return JSOP_NOP;
+ indexBase = index >> 16;
+ if (indexBase <= JSOP_INDEXBASE3 - JSOP_INDEXBASE1 + 1) {
+ if (js_Emit1(cx, cg, (JSOp)(JSOP_INDEXBASE1 + indexBase - 1)) < 0)
+ return JSOP_FALSE;
+ return JSOP_RESETBASE0;
+ }
+
+ if (index >= INDEX_LIMIT) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_TOO_MANY_LITERALS);
+ return JSOP_FALSE;
+ }
+
+ if (js_Emit2(cx, cg, JSOP_INDEXBASE, (JSOp)indexBase) < 0)
+ return JSOP_FALSE;
+ return JSOP_RESETBASE;
+}
+
+/*
+ * Emit a bytecode and its 2-byte constant index immediate operand. If the
+ * index requires more than 2 bytes, emit a prefix op whose 8-bit immediate
+ * operand effectively extends the 16-bit immediate of the prefixed opcode,
+ * by changing index "segment" (see jsinterp.c). We optimize segments 1-3
+ * with single-byte JSOP_INDEXBASE[123] codes.
+ *
+ * Such prefixing currently requires a suffix to restore the "zero segment"
+ * register setting, but this could be optimized further.
+ */
+static JSBool
+EmitIndexOp(JSContext *cx, JSOp op, uintN index, JSCodeGenerator *cg)
+{
+ JSOp bigSuffix;
+
+ bigSuffix = EmitBigIndexPrefix(cx, cg, index);
+ if (bigSuffix == JSOP_FALSE)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(op, index);
+ return bigSuffix == JSOP_NOP || js_Emit1(cx, cg, bigSuffix) >= 0;
+}
+
+/*
+ * Slight sugar for EmitIndexOp, again accessing cx and cg from the macro
+ * caller's lexical environment, and embedding a false return on error.
+ */
+#define EMIT_INDEX_OP(op, index) \
+ JS_BEGIN_MACRO \
+ if (!EmitIndexOp(cx, op, index, cg)) \
+ return JS_FALSE; \
+ JS_END_MACRO
+
+
+static JSBool
+EmitAtomOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
+{
+ JSAtomListElement *ale;
+
+ JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
+ if (op == JSOP_GETPROP &&
+ pn->pn_atom == cx->runtime->atomState.lengthAtom) {
+ return js_Emit1(cx, cg, JSOP_LENGTH) >= 0;
+ }
+ ale = js_IndexAtom(cx, pn->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ return EmitIndexOp(cx, op, ALE_INDEX(ale), cg);
+}
+
+static uintN
+IndexParsedObject(JSParsedObjectBox *pob, JSEmittedObjectList *list);
+
+static JSBool
+EmitObjectOp(JSContext *cx, JSParsedObjectBox *pob, JSOp op,
+ JSCodeGenerator *cg)
+{
+ JS_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT);
+ return EmitIndexOp(cx, op, IndexParsedObject(pob, &cg->objectList), cg);
+}
+
+/*
+ * What good are ARGNO_LEN and SLOTNO_LEN, you ask? The answer is that, apart
+ * from EmitSlotIndexOp, they abstract out the detail that both are 2, and in
+ * other parts of the code there's no necessary relationship between the two.
+ * The abstraction cracks here in order to share EmitSlotIndexOp code among
+ * the JSOP_DEFLOCALFUN and JSOP_GET{ARG,VAR,LOCAL}PROP cases.
+ */
+JS_STATIC_ASSERT(ARGNO_LEN == 2);
+JS_STATIC_ASSERT(SLOTNO_LEN == 2);
+
+static JSBool
+EmitSlotIndexOp(JSContext *cx, JSOp op, uintN slot, uintN index,
+ JSCodeGenerator *cg)
+{
+ JSOp bigSuffix;
+ ptrdiff_t off;
+ jsbytecode *pc;
+
+ JS_ASSERT(JOF_OPTYPE(op) == JOF_SLOTATOM ||
+ JOF_OPTYPE(op) == JOF_SLOTOBJECT);
+ bigSuffix = EmitBigIndexPrefix(cx, cg, index);
+ if (bigSuffix == JSOP_FALSE)
+ return JS_FALSE;
+
+ /* Emit [op, slot, index]. */
+ off = js_EmitN(cx, cg, op, 2 + INDEX_LEN);
+ if (off < 0)
+ return JS_FALSE;
+ pc = CG_CODE(cg, off);
+ SET_UINT16(pc, slot);
+ pc += 2;
+ SET_INDEX(pc, index);
+ return bigSuffix == JSOP_NOP || js_Emit1(cx, cg, bigSuffix) >= 0;
+}
+
+/*
+ * Adjust the slot for a block local to account for the number of variables
+ * that share the same index space with locals. Due to the incremental code
+ * generation for top-level script, we do the adjustment via code patching in
+ * js_CompileScript; see comments there.
+ *
+ * The function returns -1 on failures.
+ */
+static jsint
+AdjustBlockSlot(JSContext *cx, JSCodeGenerator *cg, jsint slot)
+{
+ JS_ASSERT((jsuint) slot < cg->maxStackDepth);
+ if (cg->treeContext.flags & TCF_IN_FUNCTION) {
+ slot += cg->treeContext.u.fun->u.i.nvars;
+ if ((uintN) slot >= SLOTNO_LIMIT) {
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), NULL,
+ JSREPORT_ERROR,
+ JSMSG_TOO_MANY_LOCALS);
+ slot = -1;
+ }
+ }
+ return slot;
+}
+
+/*
+ * This routine tries to optimize name gets and sets to stack slot loads and
+ * stores, given the variables object and scope chain in cx's top frame, the
+ * compile-time context in tc, and a TOK_NAME node pn. It returns false on
+ * error, true on success.
+ *
+ * The caller can inspect pn->pn_slot for a non-negative slot number to tell
+ * whether optimization occurred, in which case BindNameToSlot also updated
+ * pn->pn_op. If pn->pn_slot is still -1 on return, pn->pn_op nevertheless
+ * may have been optimized, e.g., from JSOP_NAME to JSOP_ARGUMENTS. Whether
+ * or not pn->pn_op was modified, if this function finds an argument or local
+ * variable name, pn->pn_const will be true for const properties after a
+ * successful return.
+ *
+ * NB: if you add more opcodes specialized from JSOP_NAME, etc., don't forget
+ * to update the TOK_FOR (for-in) and TOK_ASSIGN (op=, e.g. +=) special cases
+ * in js_EmitTree.
+ */
+static JSBool
+BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
+{
+ JSTreeContext *tc;
+ JSAtom *atom;
+ JSStmtInfo *stmt;
+ jsint slot;
+ JSOp op;
+ JSLocalKind localKind;
+ uintN index;
+ JSAtomListElement *ale;
+ JSBool constOp;
+
+ JS_ASSERT(pn->pn_type == TOK_NAME);
+ if (pn->pn_slot >= 0 || pn->pn_op == JSOP_ARGUMENTS)
+ return JS_TRUE;
+
+ /* QNAME references can never be optimized to use arg/var storage. */
+ if (pn->pn_op == JSOP_QNAMEPART)
+ return JS_TRUE;
+
+ /*
+ * We can't optimize if we are compiling a with statement and its body,
+ * or we're in a catch block whose exception variable has the same name
+ * as this node. FIXME: we should be able to optimize catch vars to be
+ * block-locals.
+ */
+ tc = &cg->treeContext;
+ atom = pn->pn_atom;
+ stmt = js_LexicalLookup(tc, atom, &slot);
+ if (stmt) {
+ if (stmt->type == STMT_WITH)
+ return JS_TRUE;
+
+ JS_ASSERT(stmt->flags & SIF_SCOPE);
+ JS_ASSERT(slot >= 0);
+ op = PN_OP(pn);
+ switch (op) {
+ case JSOP_NAME: op = JSOP_GETLOCAL; break;
+ case JSOP_SETNAME: op = JSOP_SETLOCAL; break;
+ case JSOP_INCNAME: op = JSOP_INCLOCAL; break;
+ case JSOP_NAMEINC: op = JSOP_LOCALINC; break;
+ case JSOP_DECNAME: op = JSOP_DECLOCAL; break;
+ case JSOP_NAMEDEC: op = JSOP_LOCALDEC; break;
+ case JSOP_FORNAME: op = JSOP_FORLOCAL; break;
+ case JSOP_DELNAME: op = JSOP_FALSE; break;
+ default: JS_ASSERT(0);
+ }
+ if (op != pn->pn_op) {
+ slot = AdjustBlockSlot(cx, cg, slot);
+ if (slot < 0)
+ return JS_FALSE;
+ pn->pn_op = op;
+ pn->pn_slot = slot;
+ }
+ return JS_TRUE;
+ }
+
+ /*
+ * We can't optimize if var and closure (a local function not in a larger
+ * expression and not at top-level within another's body) collide.
+ * XXX suboptimal: keep track of colliding names and deoptimize only those
+ */
+ if (tc->flags & TCF_FUN_CLOSURE_VS_VAR)
+ return JS_TRUE;
+
+ if (!(tc->flags & TCF_IN_FUNCTION)) {
+ JSStackFrame *caller;
+
+ caller = tc->parseContext->callerFrame;
+ if (caller) {
+ JS_ASSERT(tc->flags & TCF_COMPILE_N_GO);
+ JS_ASSERT(caller->script);
+ if (!caller->fun || caller->varobj != tc->u.scopeChain)
+ return JS_TRUE;
+
+ /*
+ * We are compiling eval or debug script inside a function frame
+ * and the scope chain matches function's variable object.
+ * Optimize access to function's arguments and variable and the
+ * arguments object.
+ */
+ if (PN_OP(pn) != JSOP_NAME || cg->staticDepth > JS_DISPLAY_SIZE)
+ goto arguments_check;
+ localKind = js_LookupLocal(cx, caller->fun, atom, &index);
+ if (localKind == JSLOCAL_NONE)
+ goto arguments_check;
+
+ ATOM_LIST_SEARCH(ale, &cg->upvarList, atom);
+ if (!ale) {
+ uint32 length, *vector;
+
+ ale = js_IndexAtom(cx, atom, &cg->upvarList);
+ if (!ale)
+ return JS_FALSE;
+ JS_ASSERT(ALE_INDEX(ale) == cg->upvarList.count - 1);
+
+ length = cg->upvarMap.length;
+ JS_ASSERT(ALE_INDEX(ale) <= length);
+ if (ALE_INDEX(ale) == length) {
+ length = 2 * JS_MAX(2, length);
+ vector = (uint32 *)
+ JS_realloc(cx, cg->upvarMap.vector,
+ length * sizeof *vector);
+ if (!vector)
+ return JS_FALSE;
+ cg->upvarMap.vector = vector;
+ cg->upvarMap.length = length;
+ }
+
+ if (localKind != JSLOCAL_ARG)
+ index += caller->fun->nargs;
+ if (index >= JS_BIT(16)) {
+ cg->treeContext.flags |= TCF_FUN_USES_NONLOCALS;
+ return JS_TRUE;
+ }
+
+ JS_ASSERT(cg->staticDepth > caller->fun->u.i.script->staticDepth);
+ uintN skip = cg->staticDepth - caller->fun->u.i.script->staticDepth;
+ cg->upvarMap.vector[ALE_INDEX(ale)] = MAKE_UPVAR_COOKIE(skip, index);
+ }
+
+ pn->pn_op = JSOP_GETUPVAR;
+ pn->pn_slot = ALE_INDEX(ale);
+ return JS_TRUE;
+ }
+
+ /*
+ * We are optimizing global variables and there may be no pre-existing
+ * global property named atom. If atom was declared via const or var,
+ * optimize pn to access fp->vars using the appropriate JSOP_*GVAR op.
+ */
+ ATOM_LIST_SEARCH(ale, &tc->decls, atom);
+ if (!ale) {
+ /* Use precedes declaration, or name is never declared. */
+ return JS_TRUE;
+ }
+ constOp = (ALE_JSOP(ale) == JSOP_DEFCONST);
+
+ /* Index atom so we can map fast global number to name. */
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+
+ /* Defend against tc->ngvars 16-bit overflow. */
+ slot = ALE_INDEX(ale);
+ if ((slot + 1) >> 16)
+ return JS_TRUE;
+
+ if ((uint16)(slot + 1) > tc->ngvars)
+ tc->ngvars = (uint16)(slot + 1);
+
+ op = PN_OP(pn);
+ switch (op) {
+ case JSOP_NAME: op = JSOP_GETGVAR; break;
+ case JSOP_SETNAME: op = JSOP_SETGVAR; break;
+ case JSOP_SETCONST: /* NB: no change */ break;
+ case JSOP_INCNAME: op = JSOP_INCGVAR; break;
+ case JSOP_NAMEINC: op = JSOP_GVARINC; break;
+ case JSOP_DECNAME: op = JSOP_DECGVAR; break;
+ case JSOP_NAMEDEC: op = JSOP_GVARDEC; break;
+ case JSOP_FORNAME: /* NB: no change */ break;
+ case JSOP_DELNAME: /* NB: no change */ break;
+ default: JS_NOT_REACHED("gvar");
+ }
+ pn->pn_const = constOp;
+ if (op != pn->pn_op) {
+ pn->pn_op = op;
+ pn->pn_slot = slot;
+ }
+ return JS_TRUE;
+ }
+
+ if (tc->flags & TCF_IN_FUNCTION) {
+ /*
+ * We are compiling a function body and may be able to optimize name
+ * to stack slot. Look for an argument or variable in the function and
+ * rewrite pn_op and update pn accordingly.
+ */
+ localKind = js_LookupLocal(cx, tc->u.fun, atom, &index);
+ if (localKind != JSLOCAL_NONE) {
+ op = PN_OP(pn);
+ if (localKind == JSLOCAL_ARG) {
+ switch (op) {
+ case JSOP_NAME: op = JSOP_GETARG; break;
+ case JSOP_SETNAME: op = JSOP_SETARG; break;
+ case JSOP_INCNAME: op = JSOP_INCARG; break;
+ case JSOP_NAMEINC: op = JSOP_ARGINC; break;
+ case JSOP_DECNAME: op = JSOP_DECARG; break;
+ case JSOP_NAMEDEC: op = JSOP_ARGDEC; break;
+ case JSOP_FORNAME: op = JSOP_FORARG; break;
+ case JSOP_DELNAME: op = JSOP_FALSE; break;
+ default: JS_NOT_REACHED("arg");
+ }
+ pn->pn_const = JS_FALSE;
+ } else {
+ JS_ASSERT(localKind == JSLOCAL_VAR ||
+ localKind == JSLOCAL_CONST);
+ switch (op) {
+ case JSOP_NAME: op = JSOP_GETLOCAL; break;
+ case JSOP_SETNAME: op = JSOP_SETLOCAL; break;
+ case JSOP_SETCONST: op = JSOP_SETLOCAL; break;
+ case JSOP_INCNAME: op = JSOP_INCLOCAL; break;
+ case JSOP_NAMEINC: op = JSOP_LOCALINC; break;
+ case JSOP_DECNAME: op = JSOP_DECLOCAL; break;
+ case JSOP_NAMEDEC: op = JSOP_LOCALDEC; break;
+ case JSOP_FORNAME: op = JSOP_FORLOCAL; break;
+ case JSOP_DELNAME: op = JSOP_FALSE; break;
+ default: JS_NOT_REACHED("local");
+ }
+ pn->pn_const = (localKind == JSLOCAL_CONST);
+ }
+ pn->pn_op = op;
+ pn->pn_slot = index;
+ return JS_TRUE;
+ }
+ tc->flags |= TCF_FUN_USES_NONLOCALS;
+ }
+
+ arguments_check:
+ /*
+ * Here we either compiling a function body or an eval or debug script
+ * inside a function and couldn't optimize pn, so it's not a global or
+ * local slot name. We are also outside of any with blocks. Check if we
+ * can optimize the predefined arguments variable.
+ */
+ JS_ASSERT((tc->flags & TCF_IN_FUNCTION) ||
+ (tc->parseContext->callerFrame &&
+ tc->parseContext->callerFrame->fun &&
+ tc->parseContext->callerFrame->varobj == tc->u.scopeChain));
+ if (pn->pn_op == JSOP_NAME &&
+ atom == cx->runtime->atomState.argumentsAtom) {
+ pn->pn_op = JSOP_ARGUMENTS;
+ return JS_TRUE;
+ }
+ return JS_TRUE;
+}
+
+/*
+ * If pn contains a useful expression, return true with *answer set to true.
+ * If pn contains a useless expression, return true with *answer set to false.
+ * Return false on error.
+ *
+ * The caller should initialize *answer to false and invoke this function on
+ * an expression statement or similar subtree to decide whether the tree could
+ * produce code that has any side effects. For an expression statement, we
+ * define useless code as code with no side effects, because the main effect,
+ * the value left on the stack after the code executes, will be discarded by a
+ * pop bytecode.
+ */
+static JSBool
+CheckSideEffects(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
+ JSBool *answer)
+{
+ JSBool ok;
+ JSFunction *fun;
+ JSParseNode *pn2;
+
+ ok = JS_TRUE;
+ if (!pn || *answer)
+ return ok;
+
+ switch (pn->pn_arity) {
+ case PN_FUNC:
+ /*
+ * A named function is presumed useful: we can't yet know that it is
+ * not called. The side effects are the creation of a scope object
+ * to parent this function object, and the binding of the function's
+ * name in that scope object. See comments at case JSOP_NAMEDFUNOBJ:
+ * in jsinterp.c.
+ */
+ fun = (JSFunction *) pn->pn_funpob->object;
+ if (fun->atom)
+ *answer = JS_TRUE;
+ break;
+
+ case PN_LIST:
+ if (pn->pn_op == JSOP_NOP ||
+ pn->pn_op == JSOP_OR || pn->pn_op == JSOP_AND ||
+ pn->pn_op == JSOP_STRICTEQ || pn->pn_op == JSOP_STRICTNE) {
+ /*
+ * Non-operators along with ||, &&, ===, and !== never invoke
+ * toString or valueOf.
+ */
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next)
+ ok &= CheckSideEffects(cx, cg, pn2, answer);
+ } else {
+ /*
+ * All invocation operations (construct: TOK_NEW, call: TOK_LP)
+ * are presumed to be useful, because they may have side effects
+ * even if their main effect (their return value) is discarded.
+ *
+ * TOK_LB binary trees of 3 or more nodes are flattened into lists
+ * to avoid too much recursion. All such lists must be presumed
+ * to be useful because each index operation could invoke a getter
+ * (the JSOP_ARGUMENTS special case below, in the PN_BINARY case,
+ * does not apply here: arguments[i][j] might invoke a getter).
+ *
+ * Likewise, array and object initialisers may call prototype
+ * setters (the __defineSetter__ built-in, and writable __proto__
+ * on Array.prototype create this hazard). Initialiser list nodes
+ * have JSOP_NEWINIT in their pn_op.
+ */
+ *answer = JS_TRUE;
+ }
+ break;
+
+ case PN_TERNARY:
+ ok = CheckSideEffects(cx, cg, pn->pn_kid1, answer) &&
+ CheckSideEffects(cx, cg, pn->pn_kid2, answer) &&
+ CheckSideEffects(cx, cg, pn->pn_kid3, answer);
+ break;
+
+ case PN_BINARY:
+ if (pn->pn_type == TOK_ASSIGN) {
+ /*
+ * Assignment is presumed to be useful, even if the next operation
+ * is another assignment overwriting this one's ostensible effect,
+ * because the left operand may be a property with a setter that
+ * has side effects.
+ *
+ * The only exception is assignment of a useless value to a const
+ * declared in the function currently being compiled.
+ */
+ pn2 = pn->pn_left;
+ if (pn2->pn_type != TOK_NAME) {
+ *answer = JS_TRUE;
+ } else {
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ if (!CheckSideEffects(cx, cg, pn->pn_right, answer))
+ return JS_FALSE;
+ if (!*answer &&
+ (pn->pn_op != JSOP_NOP ||
+ pn2->pn_slot < 0 ||
+ !pn2->pn_const)) {
+ *answer = JS_TRUE;
+ }
+ }
+ } else {
+ if (pn->pn_op == JSOP_OR || pn->pn_op == JSOP_AND ||
+ pn->pn_op == JSOP_STRICTEQ || pn->pn_op == JSOP_STRICTNE) {
+ /*
+ * ||, &&, ===, and !== do not convert their operands via
+ * toString or valueOf method calls.
+ */
+ ok = CheckSideEffects(cx, cg, pn->pn_left, answer) &&
+ CheckSideEffects(cx, cg, pn->pn_right, answer);
+ } else {
+ /*
+ * We can't easily prove that neither operand ever denotes an
+ * object with a toString or valueOf method.
+ */
+ *answer = JS_TRUE;
+ }
+ }
+ break;
+
+ case PN_UNARY:
+ switch (pn->pn_type) {
+ case TOK_RP:
+ ok = CheckSideEffects(cx, cg, pn->pn_kid, answer);
+ break;
+
+ case TOK_DELETE:
+ pn2 = pn->pn_kid;
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ case TOK_DOT:
+#if JS_HAS_XML_SUPPORT
+ case TOK_DBLDOT:
+#endif
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+#endif
+ case TOK_LB:
+ /* All these delete addressing modes have effects too. */
+ *answer = JS_TRUE;
+ break;
+ default:
+ ok = CheckSideEffects(cx, cg, pn2, answer);
+ break;
+ }
+ break;
+
+ case TOK_UNARYOP:
+ if (pn->pn_op == JSOP_NOT) {
+ /* ! does not convert its operand via toString or valueOf. */
+ ok = CheckSideEffects(cx, cg, pn->pn_kid, answer);
+ break;
+ }
+ /* FALL THROUGH */
+
+ default:
+ /*
+ * All of TOK_INC, TOK_DEC, TOK_THROW, TOK_YIELD, and TOK_DEFSHARP
+ * have direct effects. Of the remaining unary-arity node types,
+ * we can't easily prove that the operand never denotes an object
+ * with a toString or valueOf method.
+ */
+ *answer = JS_TRUE;
+ break;
+ }
+ break;
+
+ case PN_NAME:
+ /*
+ * Take care to avoid trying to bind a label name (labels, both for
+ * statements and property values in object initialisers, have pn_op
+ * defaulted to JSOP_NOP).
+ */
+ if (pn->pn_type == TOK_NAME && pn->pn_op != JSOP_NOP) {
+ if (!BindNameToSlot(cx, cg, pn))
+ return JS_FALSE;
+ if (pn->pn_slot < 0 && pn->pn_op != JSOP_ARGUMENTS) {
+ /*
+ * Not an argument or local variable use, so this expression
+ * could invoke a getter that has side effects.
+ */
+ *answer = JS_TRUE;
+ }
+ }
+ pn2 = pn->pn_expr;
+ if (pn->pn_type == TOK_DOT) {
+ if (pn2->pn_type == TOK_NAME && !BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ if (!(pn2->pn_op == JSOP_ARGUMENTS &&
+ pn->pn_atom == cx->runtime->atomState.lengthAtom)) {
+ /*
+ * Any dotted property reference could call a getter, except
+ * for arguments.length where arguments is unambiguous.
+ */
+ *answer = JS_TRUE;
+ }
+ }
+ ok = CheckSideEffects(cx, cg, pn2, answer);
+ break;
+
+ case PN_NULLARY:
+ if (pn->pn_type == TOK_DEBUGGER)
+ *answer = JS_TRUE;
+ break;
+ }
+ return ok;
+}
+
+static JSBool
+EmitNameOp(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
+ JSBool callContext)
+{
+ JSOp op;
+
+ if (!BindNameToSlot(cx, cg, pn))
+ return JS_FALSE;
+ op = PN_OP(pn);
+
+ if (callContext) {
+ switch (op) {
+ case JSOP_NAME:
+ op = JSOP_CALLNAME;
+ break;
+ case JSOP_GETGVAR:
+ op = JSOP_CALLGVAR;
+ break;
+ case JSOP_GETARG:
+ op = JSOP_CALLARG;
+ break;
+ case JSOP_GETLOCAL:
+ op = JSOP_CALLLOCAL;
+ break;
+ case JSOP_GETUPVAR:
+ op = JSOP_CALLUPVAR;
+ break;
+ default:
+ JS_ASSERT(op == JSOP_ARGUMENTS);
+ break;
+ }
+ }
+
+ if (op == JSOP_ARGUMENTS) {
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ if (callContext && js_Emit1(cx, cg, JSOP_NULL) < 0)
+ return JS_FALSE;
+ } else {
+ if (pn->pn_slot >= 0) {
+ EMIT_UINT16_IMM_OP(op, pn->pn_slot);
+ } else {
+ if (!EmitAtomOp(cx, pn, op, cg))
+ return JS_FALSE;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+#if JS_HAS_XML_SUPPORT
+static JSBool
+EmitXMLName(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
+{
+ JSParseNode *pn2;
+ uintN oldflags;
+
+ JS_ASSERT(pn->pn_type == TOK_UNARYOP);
+ JS_ASSERT(pn->pn_op == JSOP_XMLNAME);
+ JS_ASSERT(op == JSOP_XMLNAME || op == JSOP_CALLXMLNAME);
+
+ pn2 = pn->pn_kid;
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE,
+ CG_OFFSET(cg) - pn2->pn_offset) < 0) {
+ return JS_FALSE;
+ }
+
+ return js_Emit1(cx, cg, op) >= 0;
+}
+#endif
+
+static JSBool
+EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg,
+ JSBool callContext)
+{
+ JSParseNode *pn2, *pndot, *pnup, *pndown;
+ ptrdiff_t top;
+
+ pn2 = pn->pn_expr;
+ if (callContext) {
+ JS_ASSERT(pn->pn_type == TOK_DOT);
+ JS_ASSERT(op == JSOP_GETPROP);
+ op = JSOP_CALLPROP;
+ } else if (op == JSOP_GETPROP && pn->pn_type == TOK_DOT) {
+ if (pn2->pn_op == JSOP_THIS) {
+ if (pn->pn_atom != cx->runtime->atomState.lengthAtom) {
+ /* Fast path for gets of |this.foo|. */
+ return EmitAtomOp(cx, pn, JSOP_GETTHISPROP, cg);
+ }
+ } else if (pn2->pn_type == TOK_NAME) {
+ /*
+ * Try to optimize:
+ * - arguments.length into JSOP_ARGCNT
+ * - argname.prop into JSOP_GETARGPROP
+ * - localname.prop into JSOP_GETLOCALPROP
+ * but don't do this if the property is 'length' -- prefer to emit
+ * JSOP_GETARG, etc., and then JSOP_LENGTH.
+ */
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ if (pn->pn_atom == cx->runtime->atomState.lengthAtom) {
+ if (pn2->pn_op == JSOP_ARGUMENTS)
+ return js_Emit1(cx, cg, JSOP_ARGCNT) >= 0;
+ } else {
+ switch (pn2->pn_op) {
+ case JSOP_GETARG:
+ op = JSOP_GETARGPROP;
+ goto do_indexconst;
+ case JSOP_GETLOCAL:
+ op = JSOP_GETLOCALPROP;
+ do_indexconst: {
+ JSAtomListElement *ale;
+ jsatomid atomIndex;
+
+ ale = js_IndexAtom(cx, pn->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ atomIndex = ALE_INDEX(ale);
+ return EmitSlotIndexOp(cx, op, pn2->pn_slot, atomIndex, cg);
+ }
+
+ default:;
+ }
+ }
+ }
+ }
+
+ /*
+ * If the object operand is also a dotted property reference, reverse the
+ * list linked via pn_expr temporarily so we can iterate over it from the
+ * bottom up (reversing again as we go), to avoid excessive recursion.
+ */
+ if (pn2->pn_type == TOK_DOT) {
+ pndot = pn2;
+ pnup = NULL;
+ top = CG_OFFSET(cg);
+ for (;;) {
+ /* Reverse pndot->pn_expr to point up, not down. */
+ pndot->pn_offset = top;
+ pndown = pndot->pn_expr;
+ pndot->pn_expr = pnup;
+ if (pndown->pn_type != TOK_DOT)
+ break;
+ pnup = pndot;
+ pndot = pndown;
+ }
+
+ /* pndown is a primary expression, not a dotted property reference. */
+ if (!js_EmitTree(cx, cg, pndown))
+ return JS_FALSE;
+
+ do {
+ /* Walk back up the list, emitting annotated name ops. */
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE,
+ CG_OFFSET(cg) - pndown->pn_offset) < 0) {
+ return JS_FALSE;
+ }
+ if (!EmitAtomOp(cx, pndot, PN_OP(pndot), cg))
+ return JS_FALSE;
+
+ /* Reverse the pn_expr link again. */
+ pnup = pndot->pn_expr;
+ pndot->pn_expr = pndown;
+ pndown = pndot;
+ } while ((pndot = pnup) != NULL);
+ } else {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ }
+
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE,
+ CG_OFFSET(cg) - pn2->pn_offset) < 0) {
+ return JS_FALSE;
+ }
+
+ return EmitAtomOp(cx, pn, op, cg);
+}
+
+static JSBool
+EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
+{
+ ptrdiff_t top;
+ JSParseNode *left, *right, *next, ltmp, rtmp;
+ jsint slot;
+
+ top = CG_OFFSET(cg);
+ if (pn->pn_arity == PN_LIST) {
+ /* Left-associative operator chain to avoid too much recursion. */
+ JS_ASSERT(pn->pn_op == JSOP_GETELEM);
+ JS_ASSERT(pn->pn_count >= 3);
+ left = pn->pn_head;
+ right = PN_LAST(pn);
+ next = left->pn_next;
+ JS_ASSERT(next != right);
+
+ /*
+ * Try to optimize arguments[0][j]... into JSOP_ARGSUB<0> followed by
+ * one or more index expression and JSOP_GETELEM op pairs.
+ */
+ if (left->pn_type == TOK_NAME && next->pn_type == TOK_NUMBER) {
+ if (!BindNameToSlot(cx, cg, left))
+ return JS_FALSE;
+ if (left->pn_op == JSOP_ARGUMENTS &&
+ JSDOUBLE_IS_INT(next->pn_dval, slot) &&
+ (jsuint)slot < JS_BIT(16)) {
+ /*
+ * arguments[i]() requires arguments object as "this".
+ * Check that we never generates list for that usage.
+ */
+ JS_ASSERT(op != JSOP_CALLELEM || next->pn_next);
+ left->pn_offset = next->pn_offset = top;
+ EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot);
+ left = next;
+ next = left->pn_next;
+ }
+ }
+
+ /*
+ * Check whether we generated JSOP_ARGSUB, just above, and have only
+ * one more index expression to emit. Given arguments[0][j], we must
+ * skip the while loop altogether, falling through to emit code for j
+ * (in the subtree referenced by right), followed by the annotated op,
+ * at the bottom of this function.
+ */
+ JS_ASSERT(next != right || pn->pn_count == 3);
+ if (left == pn->pn_head) {
+ if (!js_EmitTree(cx, cg, left))
+ return JS_FALSE;
+ }
+ while (next != right) {
+ if (!js_EmitTree(cx, cg, next))
+ return JS_FALSE;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_GETELEM) < 0)
+ return JS_FALSE;
+ next = next->pn_next;
+ }
+ } else {
+ if (pn->pn_arity == PN_NAME) {
+ /*
+ * Set left and right so pn appears to be a TOK_LB node, instead
+ * of a TOK_DOT node. See the TOK_FOR/IN case in js_EmitTree, and
+ * EmitDestructuringOps nearer below. In the destructuring case,
+ * the base expression (pn_expr) of the name may be null, which
+ * means we have to emit a JSOP_BINDNAME.
+ */
+ left = pn->pn_expr;
+ if (!left) {
+ left = &ltmp;
+ left->pn_type = TOK_STRING;
+ left->pn_op = JSOP_BINDNAME;
+ left->pn_arity = PN_NULLARY;
+ left->pn_pos = pn->pn_pos;
+ left->pn_atom = pn->pn_atom;
+ }
+ right = &rtmp;
+ right->pn_type = TOK_STRING;
+ JS_ASSERT(ATOM_IS_STRING(pn->pn_atom));
+ right->pn_op = js_IsIdentifier(ATOM_TO_STRING(pn->pn_atom))
+ ? JSOP_QNAMEPART
+ : JSOP_STRING;
+ right->pn_arity = PN_NULLARY;
+ right->pn_pos = pn->pn_pos;
+ right->pn_atom = pn->pn_atom;
+ } else {
+ JS_ASSERT(pn->pn_arity == PN_BINARY);
+ left = pn->pn_left;
+ right = pn->pn_right;
+ }
+
+ /* Try to optimize arguments[0] (e.g.) into JSOP_ARGSUB<0>. */
+ if (op == JSOP_GETELEM &&
+ left->pn_type == TOK_NAME &&
+ right->pn_type == TOK_NUMBER) {
+ if (!BindNameToSlot(cx, cg, left))
+ return JS_FALSE;
+ if (left->pn_op == JSOP_ARGUMENTS &&
+ JSDOUBLE_IS_INT(right->pn_dval, slot) &&
+ (jsuint)slot < JS_BIT(16)) {
+ left->pn_offset = right->pn_offset = top;
+ EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot);
+ return JS_TRUE;
+ }
+ }
+
+ if (!js_EmitTree(cx, cg, left))
+ return JS_FALSE;
+ }
+
+ /* The right side of the descendant operator is implicitly quoted. */
+ JS_ASSERT(op != JSOP_DESCENDANTS || right->pn_type != TOK_STRING ||
+ right->pn_op == JSOP_QNAMEPART);
+ if (!js_EmitTree(cx, cg, right))
+ return JS_FALSE;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0)
+ return JS_FALSE;
+ return js_Emit1(cx, cg, op) >= 0;
+}
+
+static JSBool
+EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg)
+{
+ jsint ival;
+ uint32 u;
+ ptrdiff_t off;
+ jsbytecode *pc;
+ JSAtom *atom;
+ JSAtomListElement *ale;
+
+ if (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) {
+ if (ival == 0)
+ return js_Emit1(cx, cg, JSOP_ZERO) >= 0;
+ if (ival == 1)
+ return js_Emit1(cx, cg, JSOP_ONE) >= 0;
+ if ((jsint)(int8)ival == ival)
+ return js_Emit2(cx, cg, JSOP_INT8, (jsbytecode)(int8)ival) >= 0;
+
+ u = (uint32)ival;
+ if (u < JS_BIT(16)) {
+ EMIT_UINT16_IMM_OP(JSOP_UINT16, u);
+ } else if (u < JS_BIT(24)) {
+ off = js_EmitN(cx, cg, JSOP_UINT24, 3);
+ if (off < 0)
+ return JS_FALSE;
+ pc = CG_CODE(cg, off);
+ SET_UINT24(pc, u);
+ } else {
+ off = js_EmitN(cx, cg, JSOP_INT32, 4);
+ if (off < 0)
+ return JS_FALSE;
+ pc = CG_CODE(cg, off);
+ SET_INT32(pc, ival);
+ }
+ return JS_TRUE;
+ }
+
+ atom = js_AtomizeDouble(cx, dval);
+ if (!atom)
+ return JS_FALSE;
+
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ return EmitIndexOp(cx, JSOP_DOUBLE, ALE_INDEX(ale), cg);
+}
+
+static JSBool
+EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
+ JSStmtInfo *stmtInfo)
+{
+ JSOp switchOp;
+ JSBool ok, hasDefault, constPropagated;
+ ptrdiff_t top, off, defaultOffset;
+ JSParseNode *pn2, *pn3, *pn4;
+ uint32 caseCount, tableLength;
+ JSParseNode **table;
+ jsdouble d;
+ jsint i, low, high;
+ jsval v;
+ JSAtom *atom;
+ JSAtomListElement *ale;
+ intN noteIndex;
+ size_t switchSize, tableSize;
+ jsbytecode *pc, *savepc;
+#if JS_HAS_BLOCK_SCOPE
+ jsint count;
+#endif
+
+ /* Try for most optimal, fall back if not dense ints, and per ECMAv2. */
+ switchOp = JSOP_TABLESWITCH;
+ ok = JS_TRUE;
+ hasDefault = constPropagated = JS_FALSE;
+ defaultOffset = -1;
+
+ /*
+ * If the switch contains let variables scoped by its body, model the
+ * resulting block on the stack first, before emitting the discriminant's
+ * bytecode (in case the discriminant contains a stack-model dependency
+ * such as a let expression).
+ */
+ pn2 = pn->pn_right;
+#if JS_HAS_BLOCK_SCOPE
+ if (pn2->pn_type == TOK_LEXICALSCOPE) {
+ /*
+ * Push the body's block scope before discriminant code-gen for proper
+ * static block scope linkage in case the discriminant contains a let
+ * expression. The block's locals must lie under the discriminant on
+ * the stack so that case-dispatch bytecodes can find the discriminant
+ * on top of stack.
+ */
+ count = OBJ_BLOCK_COUNT(cx, pn2->pn_pob->object);
+ js_PushBlockScope(&cg->treeContext, stmtInfo, pn2->pn_pob->object, -1);
+ stmtInfo->type = STMT_SWITCH;
+
+ /* Emit JSOP_ENTERBLOCK before code to evaluate the discriminant. */
+ if (!EmitObjectOp(cx, pn2->pn_pob, JSOP_ENTERBLOCK, cg))
+ return JS_FALSE;
+
+ /*
+ * Pop the switch's statement info around discriminant code-gen. Note
+ * how this leaves cg->treeContext.blockChain referencing the switch's
+ * block scope object, which is necessary for correct block parenting
+ * in the case where the discriminant contains a let expression.
+ */
+ cg->treeContext.topStmt = stmtInfo->down;
+ cg->treeContext.topScopeStmt = stmtInfo->downScope;
+ }
+#ifdef __GNUC__
+ else {
+ count = 0;
+ }
+#endif
+#endif
+
+ /*
+ * Emit code for the discriminant first (or nearly first, in the case of a
+ * switch whose body is a block scope).
+ */
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+
+ /* Switch bytecodes run from here till end of final case. */
+ top = CG_OFFSET(cg);
+#if !JS_HAS_BLOCK_SCOPE
+ js_PushStatement(&cg->treeContext, stmtInfo, STMT_SWITCH, top);
+#else
+ if (pn2->pn_type == TOK_LC) {
+ js_PushStatement(&cg->treeContext, stmtInfo, STMT_SWITCH, top);
+ } else {
+ /* Re-push the switch's statement info record. */
+ cg->treeContext.topStmt = cg->treeContext.topScopeStmt = stmtInfo;
+
+ /* Set the statement info record's idea of top. */
+ stmtInfo->update = top;
+
+ /* Advance pn2 to refer to the switch case list. */
+ pn2 = pn2->pn_expr;
+ }
+#endif
+
+ caseCount = pn2->pn_count;
+ tableLength = 0;
+ table = NULL;
+
+ if (caseCount == 0 ||
+ (caseCount == 1 &&
+ (hasDefault = (pn2->pn_head->pn_type == TOK_DEFAULT)))) {
+ caseCount = 0;
+ low = 0;
+ high = -1;
+ } else {
+#define INTMAP_LENGTH 256
+ jsbitmap intmap_space[INTMAP_LENGTH];
+ jsbitmap *intmap = NULL;
+ int32 intmap_bitlen = 0;
+
+ low = JSVAL_INT_MAX;
+ high = JSVAL_INT_MIN;
+
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ if (pn3->pn_type == TOK_DEFAULT) {
+ hasDefault = JS_TRUE;
+ caseCount--; /* one of the "cases" was the default */
+ continue;
+ }
+
+ JS_ASSERT(pn3->pn_type == TOK_CASE);
+ if (switchOp == JSOP_CONDSWITCH)
+ continue;
+
+ pn4 = pn3->pn_left;
+ switch (pn4->pn_type) {
+ case TOK_NUMBER:
+ d = pn4->pn_dval;
+ if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
+ pn3->pn_val = INT_TO_JSVAL(i);
+ } else {
+ atom = js_AtomizeDouble(cx, d);
+ if (!atom) {
+ ok = JS_FALSE;
+ goto release;
+ }
+ pn3->pn_val = ATOM_KEY(atom);
+ }
+ break;
+ case TOK_STRING:
+ pn3->pn_val = ATOM_KEY(pn4->pn_atom);
+ break;
+ case TOK_NAME:
+ if (!pn4->pn_expr) {
+ ok = LookupCompileTimeConstant(cx, cg, pn4->pn_atom, &v);
+ if (!ok)
+ goto release;
+ if (v != JSVAL_HOLE) {
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ /*
+ * XXX JSOP_LOOKUPSWITCH does not support const-
+ * propagated object values, see bug 407186.
+ */
+ switchOp = JSOP_CONDSWITCH;
+ continue;
+ }
+ pn3->pn_val = v;
+ constPropagated = JS_TRUE;
+ break;
+ }
+ }
+ /* FALL THROUGH */
+ case TOK_PRIMARY:
+ if (pn4->pn_op == JSOP_TRUE) {
+ pn3->pn_val = JSVAL_TRUE;
+ break;
+ }
+ if (pn4->pn_op == JSOP_FALSE) {
+ pn3->pn_val = JSVAL_FALSE;
+ break;
+ }
+ /* FALL THROUGH */
+ default:
+ switchOp = JSOP_CONDSWITCH;
+ continue;
+ }
+
+ JS_ASSERT(JSVAL_IS_PRIMITIVE(pn3->pn_val));
+
+ if (switchOp != JSOP_TABLESWITCH)
+ continue;
+ if (!JSVAL_IS_INT(pn3->pn_val)) {
+ switchOp = JSOP_LOOKUPSWITCH;
+ continue;
+ }
+ i = JSVAL_TO_INT(pn3->pn_val);
+ if ((jsuint)(i + (jsint)JS_BIT(15)) >= (jsuint)JS_BIT(16)) {
+ switchOp = JSOP_LOOKUPSWITCH;
+ continue;
+ }
+ if (i < low)
+ low = i;
+ if (high < i)
+ high = i;
+
+ /*
+ * Check for duplicates, which require a JSOP_LOOKUPSWITCH.
+ * We bias i by 65536 if it's negative, and hope that's a rare
+ * case (because it requires a malloc'd bitmap).
+ */
+ if (i < 0)
+ i += JS_BIT(16);
+ if (i >= intmap_bitlen) {
+ if (!intmap &&
+ i < (INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2)) {
+ intmap = intmap_space;
+ intmap_bitlen = INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2;
+ } else {
+ /* Just grab 8K for the worst-case bitmap. */
+ intmap_bitlen = JS_BIT(16);
+ intmap = (jsbitmap *)
+ JS_malloc(cx,
+ (JS_BIT(16) >> JS_BITS_PER_WORD_LOG2)
+ * sizeof(jsbitmap));
+ if (!intmap) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ }
+ memset(intmap, 0, intmap_bitlen >> JS_BITS_PER_BYTE_LOG2);
+ }
+ if (JS_TEST_BIT(intmap, i)) {
+ switchOp = JSOP_LOOKUPSWITCH;
+ continue;
+ }
+ JS_SET_BIT(intmap, i);
+ }
+
+ release:
+ if (intmap && intmap != intmap_space)
+ JS_free(cx, intmap);
+ if (!ok)
+ return JS_FALSE;
+
+ /*
+ * Compute table length and select lookup instead if overlarge or
+ * more than half-sparse.
+ */
+ if (switchOp == JSOP_TABLESWITCH) {
+ tableLength = (uint32)(high - low + 1);
+ if (tableLength >= JS_BIT(16) || tableLength > 2 * caseCount)
+ switchOp = JSOP_LOOKUPSWITCH;
+ } else if (switchOp == JSOP_LOOKUPSWITCH) {
+ /*
+ * Lookup switch supports only atom indexes below 64K limit.
+ * Conservatively estimate the maximum possible index during
+ * switch generation and use conditional switch if it exceeds
+ * the limit.
+ */
+ if (caseCount + cg->atomList.count > JS_BIT(16))
+ switchOp = JSOP_CONDSWITCH;
+ }
+ }
+
+ /*
+ * Emit a note with two offsets: first tells total switch code length,
+ * second tells offset to first JSOP_CASE if condswitch.
+ */
+ noteIndex = js_NewSrcNote3(cx, cg, SRC_SWITCH, 0, 0);
+ if (noteIndex < 0)
+ return JS_FALSE;
+
+ if (switchOp == JSOP_CONDSWITCH) {
+ /*
+ * 0 bytes of immediate for unoptimized ECMAv2 switch.
+ */
+ switchSize = 0;
+ } else if (switchOp == JSOP_TABLESWITCH) {
+ /*
+ * 3 offsets (len, low, high) before the table, 1 per entry.
+ */
+ switchSize = (size_t)(JUMP_OFFSET_LEN * (3 + tableLength));
+ } else {
+ /*
+ * JSOP_LOOKUPSWITCH:
+ * 1 offset (len) and 1 atom index (npairs) before the table,
+ * 1 atom index and 1 jump offset per entry.
+ */
+ switchSize = (size_t)(JUMP_OFFSET_LEN + INDEX_LEN +
+ (INDEX_LEN + JUMP_OFFSET_LEN) * caseCount);
+ }
+
+ /*
+ * Emit switchOp followed by switchSize bytes of jump or lookup table.
+ *
+ * If switchOp is JSOP_LOOKUPSWITCH or JSOP_TABLESWITCH, it is crucial
+ * to emit the immediate operand(s) by which bytecode readers such as
+ * BuildSpanDepTable discover the length of the switch opcode *before*
+ * calling js_SetJumpOffset (which may call BuildSpanDepTable). It's
+ * also important to zero all unknown jump offset immediate operands,
+ * so they can be converted to span dependencies with null targets to
+ * be computed later (js_EmitN zeros switchSize bytes after switchOp).
+ */
+ if (js_EmitN(cx, cg, switchOp, switchSize) < 0)
+ return JS_FALSE;
+
+ off = -1;
+ if (switchOp == JSOP_CONDSWITCH) {
+ intN caseNoteIndex = -1;
+ JSBool beforeCases = JS_TRUE;
+
+ /* Emit code for evaluating cases and jumping to case statements. */
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ pn4 = pn3->pn_left;
+ if (pn4 && !js_EmitTree(cx, cg, pn4))
+ return JS_FALSE;
+ if (caseNoteIndex >= 0) {
+ /* off is the previous JSOP_CASE's bytecode offset. */
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)caseNoteIndex, 0,
+ CG_OFFSET(cg) - off)) {
+ return JS_FALSE;
+ }
+ }
+ if (!pn4) {
+ JS_ASSERT(pn3->pn_type == TOK_DEFAULT);
+ continue;
+ }
+ caseNoteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0);
+ if (caseNoteIndex < 0)
+ return JS_FALSE;
+ off = EmitJump(cx, cg, JSOP_CASE, 0);
+ if (off < 0)
+ return JS_FALSE;
+ pn3->pn_offset = off;
+ if (beforeCases) {
+ uintN noteCount, noteCountDelta;
+
+ /* Switch note's second offset is to first JSOP_CASE. */
+ noteCount = CG_NOTE_COUNT(cg);
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1,
+ off - top)) {
+ return JS_FALSE;
+ }
+ noteCountDelta = CG_NOTE_COUNT(cg) - noteCount;
+ if (noteCountDelta != 0)
+ caseNoteIndex += noteCountDelta;
+ beforeCases = JS_FALSE;
+ }
+ }
+
+ /*
+ * If we didn't have an explicit default (which could fall in between
+ * cases, preventing us from fusing this js_SetSrcNoteOffset with the
+ * call in the loop above), link the last case to the implicit default
+ * for the decompiler.
+ */
+ if (!hasDefault &&
+ caseNoteIndex >= 0 &&
+ !js_SetSrcNoteOffset(cx, cg, (uintN)caseNoteIndex, 0,
+ CG_OFFSET(cg) - off)) {
+ return JS_FALSE;
+ }
+
+ /* Emit default even if no explicit default statement. */
+ defaultOffset = EmitJump(cx, cg, JSOP_DEFAULT, 0);
+ if (defaultOffset < 0)
+ return JS_FALSE;
+ } else {
+ pc = CG_CODE(cg, top + JUMP_OFFSET_LEN);
+
+ if (switchOp == JSOP_TABLESWITCH) {
+ /* Fill in switch bounds, which we know fit in 16-bit offsets. */
+ SET_JUMP_OFFSET(pc, low);
+ pc += JUMP_OFFSET_LEN;
+ SET_JUMP_OFFSET(pc, high);
+ pc += JUMP_OFFSET_LEN;
+
+ /*
+ * Use malloc to avoid arena bloat for programs with many switches.
+ * We free table if non-null at label out, so all control flow must
+ * exit this function through goto out or goto bad.
+ */
+ if (tableLength != 0) {
+ tableSize = (size_t)tableLength * sizeof *table;
+ table = (JSParseNode **) JS_malloc(cx, tableSize);
+ if (!table)
+ return JS_FALSE;
+ memset(table, 0, tableSize);
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ if (pn3->pn_type == TOK_DEFAULT)
+ continue;
+ i = JSVAL_TO_INT(pn3->pn_val);
+ i -= low;
+ JS_ASSERT((uint32)i < tableLength);
+ table[i] = pn3;
+ }
+ }
+ } else {
+ JS_ASSERT(switchOp == JSOP_LOOKUPSWITCH);
+
+ /* Fill in the number of cases. */
+ SET_INDEX(pc, caseCount);
+ pc += INDEX_LEN;
+ }
+
+ /*
+ * After this point, all control flow involving JSOP_TABLESWITCH
+ * must set ok and goto out to exit this function. To keep things
+ * simple, all switchOp cases exit that way.
+ */
+ MUST_FLOW_THROUGH("out");
+ if (cg->spanDeps) {
+ /*
+ * We have already generated at least one big jump so we must
+ * explicitly add span dependencies for the switch jumps. When
+ * called below, js_SetJumpOffset can only do it when patching
+ * the first big jump or when cg->spanDeps is null.
+ */
+ if (!AddSwitchSpanDeps(cx, cg, CG_CODE(cg, top)))
+ goto bad;
+ }
+
+ if (constPropagated) {
+ /*
+ * Skip switchOp, as we are not setting jump offsets in the two
+ * for loops below. We'll restore CG_NEXT(cg) from savepc after,
+ * unless there was an error.
+ */
+ savepc = CG_NEXT(cg);
+ CG_NEXT(cg) = pc + 1;
+ if (switchOp == JSOP_TABLESWITCH) {
+ for (i = 0; i < (jsint)tableLength; i++) {
+ pn3 = table[i];
+ if (pn3 &&
+ (pn4 = pn3->pn_left) != NULL &&
+ pn4->pn_type == TOK_NAME) {
+ /* Note a propagated constant with the const's name. */
+ JS_ASSERT(!pn4->pn_expr);
+ ale = js_IndexAtom(cx, pn4->pn_atom, &cg->atomList);
+ if (!ale)
+ goto bad;
+ CG_NEXT(cg) = pc;
+ if (js_NewSrcNote2(cx, cg, SRC_LABEL, (ptrdiff_t)
+ ALE_INDEX(ale)) < 0) {
+ goto bad;
+ }
+ }
+ pc += JUMP_OFFSET_LEN;
+ }
+ } else {
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ pn4 = pn3->pn_left;
+ if (pn4 && pn4->pn_type == TOK_NAME) {
+ /* Note a propagated constant with the const's name. */
+ JS_ASSERT(!pn4->pn_expr);
+ ale = js_IndexAtom(cx, pn4->pn_atom, &cg->atomList);
+ if (!ale)
+ goto bad;
+ CG_NEXT(cg) = pc;
+ if (js_NewSrcNote2(cx, cg, SRC_LABEL, (ptrdiff_t)
+ ALE_INDEX(ale)) < 0) {
+ goto bad;
+ }
+ }
+ pc += INDEX_LEN + JUMP_OFFSET_LEN;
+ }
+ }
+ CG_NEXT(cg) = savepc;
+ }
+ }
+
+ /* Emit code for each case's statements, copying pn_offset up to pn3. */
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ if (switchOp == JSOP_CONDSWITCH && pn3->pn_type != TOK_DEFAULT)
+ CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx, cg, pn3->pn_offset, goto bad);
+ pn4 = pn3->pn_right;
+ ok = js_EmitTree(cx, cg, pn4);
+ if (!ok)
+ goto out;
+ pn3->pn_offset = pn4->pn_offset;
+ if (pn3->pn_type == TOK_DEFAULT)
+ off = pn3->pn_offset - top;
+ }
+
+ if (!hasDefault) {
+ /* If no default case, offset for default is to end of switch. */
+ off = CG_OFFSET(cg) - top;
+ }
+
+ /* We better have set "off" by now. */
+ JS_ASSERT(off != -1);
+
+ /* Set the default offset (to end of switch if no default). */
+ if (switchOp == JSOP_CONDSWITCH) {
+ pc = NULL;
+ JS_ASSERT(defaultOffset != -1);
+ ok = js_SetJumpOffset(cx, cg, CG_CODE(cg, defaultOffset),
+ off - (defaultOffset - top));
+ if (!ok)
+ goto out;
+ } else {
+ pc = CG_CODE(cg, top);
+ ok = js_SetJumpOffset(cx, cg, pc, off);
+ if (!ok)
+ goto out;
+ pc += JUMP_OFFSET_LEN;
+ }
+
+ /* Set the SRC_SWITCH note's offset operand to tell end of switch. */
+ off = CG_OFFSET(cg) - top;
+ ok = js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, off);
+ if (!ok)
+ goto out;
+
+ if (switchOp == JSOP_TABLESWITCH) {
+ /* Skip over the already-initialized switch bounds. */
+ pc += 2 * JUMP_OFFSET_LEN;
+
+ /* Fill in the jump table, if there is one. */
+ for (i = 0; i < (jsint)tableLength; i++) {
+ pn3 = table[i];
+ off = pn3 ? pn3->pn_offset - top : 0;
+ ok = js_SetJumpOffset(cx, cg, pc, off);
+ if (!ok)
+ goto out;
+ pc += JUMP_OFFSET_LEN;
+ }
+ } else if (switchOp == JSOP_LOOKUPSWITCH) {
+ /* Skip over the already-initialized number of cases. */
+ pc += INDEX_LEN;
+
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ if (pn3->pn_type == TOK_DEFAULT)
+ continue;
+ if (!js_AtomizePrimitiveValue(cx, pn3->pn_val, &atom))
+ goto bad;
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ goto bad;
+ SET_INDEX(pc, ALE_INDEX(ale));
+ pc += INDEX_LEN;
+
+ off = pn3->pn_offset - top;
+ ok = js_SetJumpOffset(cx, cg, pc, off);
+ if (!ok)
+ goto out;
+ pc += JUMP_OFFSET_LEN;
+ }
+ }
+
+out:
+ if (table)
+ JS_free(cx, table);
+ if (ok) {
+ ok = js_PopStatementCG(cx, cg);
+
+#if JS_HAS_BLOCK_SCOPE
+ if (ok && pn->pn_right->pn_type == TOK_LEXICALSCOPE)
+ EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, count);
+#endif
+ }
+ return ok;
+
+bad:
+ ok = JS_FALSE;
+ goto out;
+}
+
+JSBool
+js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body)
+{
+ if (cg->treeContext.flags & TCF_FUN_IS_GENERATOR) {
+ /* JSOP_GENERATOR must be the first instruction. */
+ CG_SWITCH_TO_PROLOG(cg);
+ JS_ASSERT(CG_NEXT(cg) == CG_BASE(cg));
+ if (js_Emit1(cx, cg, JSOP_GENERATOR) < 0)
+ return JS_FALSE;
+ CG_SWITCH_TO_MAIN(cg);
+ }
+
+ return js_EmitTree(cx, cg, body) &&
+ js_Emit1(cx, cg, JSOP_STOP) >= 0 &&
+ js_NewScriptFromCG(cx, cg);
+}
+
+/* A macro for inlining at the top of js_EmitTree (whence it came). */
+#define UPDATE_LINE_NUMBER_NOTES(cx, cg, pn) \
+ JS_BEGIN_MACRO \
+ uintN line_ = (pn)->pn_pos.begin.lineno; \
+ uintN delta_ = line_ - CG_CURRENT_LINE(cg); \
+ if (delta_ != 0) { \
+ /* \
+ * Encode any change in the current source line number by using \
+ * either several SRC_NEWLINE notes or just one SRC_SETLINE note, \
+ * whichever consumes less space. \
+ * \
+ * NB: We handle backward line number deltas (possible with for \
+ * loops where the update part is emitted after the body, but its \
+ * line number is <= any line number in the body) here by letting \
+ * unsigned delta_ wrap to a very large number, which triggers a \
+ * SRC_SETLINE. \
+ */ \
+ CG_CURRENT_LINE(cg) = line_; \
+ if (delta_ >= (uintN)(2 + ((line_ > SN_3BYTE_OFFSET_MASK)<<1))) { \
+ if (js_NewSrcNote2(cx, cg, SRC_SETLINE, (ptrdiff_t)line_) < 0)\
+ return JS_FALSE; \
+ } else { \
+ do { \
+ if (js_NewSrcNote(cx, cg, SRC_NEWLINE) < 0) \
+ return JS_FALSE; \
+ } while (--delta_ != 0); \
+ } \
+ } \
+ JS_END_MACRO
+
+/* A function, so that we avoid macro-bloating all the other callsites. */
+static JSBool
+UpdateLineNumberNotes(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
+{
+ UPDATE_LINE_NUMBER_NOTES(cx, cg, pn);
+ return JS_TRUE;
+}
+
+static JSBool
+MaybeEmitVarDecl(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp,
+ JSParseNode *pn, jsatomid *result)
+{
+ jsatomid atomIndex;
+ JSAtomListElement *ale;
+
+ if (pn->pn_slot >= 0) {
+ atomIndex = (jsatomid) pn->pn_slot;
+ } else {
+ ale = js_IndexAtom(cx, pn->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ atomIndex = ALE_INDEX(ale);
+ }
+
+ if (JOF_OPTYPE(pn->pn_op) == JOF_ATOM &&
+ (!(cg->treeContext.flags & TCF_IN_FUNCTION) ||
+ (cg->treeContext.flags & TCF_FUN_HEAVYWEIGHT))) {
+ /* Emit a prolog bytecode to predefine the variable. */
+ CG_SWITCH_TO_PROLOG(cg);
+ if (!UpdateLineNumberNotes(cx, cg, pn))
+ return JS_FALSE;
+ EMIT_INDEX_OP(prologOp, atomIndex);
+ CG_SWITCH_TO_MAIN(cg);
+ }
+
+ if (result)
+ *result = atomIndex;
+ return JS_TRUE;
+}
+
+#if JS_HAS_DESTRUCTURING
+
+typedef JSBool
+(*DestructuringDeclEmitter)(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp,
+ JSParseNode *pn);
+
+static JSBool
+EmitDestructuringDecl(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp,
+ JSParseNode *pn)
+{
+ JS_ASSERT(pn->pn_type == TOK_NAME);
+ if (!BindNameToSlot(cx, cg, pn))
+ return JS_FALSE;
+
+ JS_ASSERT(pn->pn_op != JSOP_ARGUMENTS);
+ return MaybeEmitVarDecl(cx, cg, prologOp, pn, NULL);
+}
+
+static JSBool
+EmitDestructuringDecls(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp,
+ JSParseNode *pn)
+{
+ JSParseNode *pn2, *pn3;
+ DestructuringDeclEmitter emitter;
+
+ if (pn->pn_type == TOK_RB) {
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (pn2->pn_type == TOK_COMMA)
+ continue;
+ emitter = (pn2->pn_type == TOK_NAME)
+ ? EmitDestructuringDecl
+ : EmitDestructuringDecls;
+ if (!emitter(cx, cg, prologOp, pn2))
+ return JS_FALSE;
+ }
+ } else {
+ JS_ASSERT(pn->pn_type == TOK_RC);
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ pn3 = pn2->pn_right;
+ emitter = (pn3->pn_type == TOK_NAME)
+ ? EmitDestructuringDecl
+ : EmitDestructuringDecls;
+ if (!emitter(cx, cg, prologOp, pn3))
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn);
+
+static JSBool
+EmitDestructuringLHS(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
+{
+ jsuint slot;
+
+ /* Skip any parenthesization. */
+ while (pn->pn_type == TOK_RP)
+ pn = pn->pn_kid;
+
+ /*
+ * Now emit the lvalue opcode sequence. If the lvalue is a nested
+ * destructuring initialiser-form, call ourselves to handle it, then
+ * pop the matched value. Otherwise emit an lvalue bytecode sequence
+ * ending with a JSOP_ENUMELEM or equivalent op.
+ */
+ if (pn->pn_type == TOK_RB || pn->pn_type == TOK_RC) {
+ if (!EmitDestructuringOpsHelper(cx, cg, pn))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ } else {
+ if (pn->pn_type == TOK_NAME && !BindNameToSlot(cx, cg, pn))
+ return JS_FALSE;
+
+ switch (pn->pn_op) {
+ case JSOP_SETNAME:
+ /*
+ * NB: pn is a PN_NAME node, not a PN_BINARY. Nevertheless,
+ * we want to emit JSOP_ENUMELEM, which has format JOF_ELEM.
+ * So here and for JSOP_ENUMCONSTELEM, we use EmitElemOp.
+ */
+ if (!EmitElemOp(cx, pn, JSOP_ENUMELEM, cg))
+ return JS_FALSE;
+ break;
+
+ case JSOP_SETCONST:
+ if (!EmitElemOp(cx, pn, JSOP_ENUMCONSTELEM, cg))
+ return JS_FALSE;
+ break;
+
+ case JSOP_SETLOCAL:
+ slot = (jsuint) pn->pn_slot;
+ EMIT_UINT16_IMM_OP(JSOP_SETLOCALPOP, slot);
+ break;
+
+ case JSOP_SETARG:
+ case JSOP_SETGVAR:
+ slot = (jsuint) pn->pn_slot;
+ EMIT_UINT16_IMM_OP(PN_OP(pn), slot);
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ break;
+
+ default:
+#if JS_HAS_LVALUE_RETURN || JS_HAS_XML_SUPPORT
+ {
+ ptrdiff_t top;
+
+ top = CG_OFFSET(cg);
+ if (!js_EmitTree(cx, cg, pn))
+ return JS_FALSE;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_ENUMELEM) < 0)
+ return JS_FALSE;
+ break;
+ }
+#endif
+ case JSOP_ENUMELEM:
+ JS_ASSERT(0);
+ }
+ }
+
+ return JS_TRUE;
+}
+
+/*
+ * Recursive helper for EmitDestructuringOps.
+ *
+ * Given a value to destructure on the stack, walk over an object or array
+ * initialiser at pn, emitting bytecodes to match property values and store
+ * them in the lvalues identified by the matched property names.
+ */
+static JSBool
+EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
+{
+ jsuint index;
+ JSParseNode *pn2, *pn3;
+ JSBool doElemOp;
+
+#ifdef DEBUG
+ intN stackDepth = cg->stackDepth;
+ JS_ASSERT(stackDepth != 0);
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ JS_ASSERT(pn->pn_type == TOK_RB || pn->pn_type == TOK_RC);
+#endif
+
+ if (pn->pn_count == 0) {
+ /* Emit a DUP;POP sequence for the decompiler. */
+ return js_Emit1(cx, cg, JSOP_DUP) >= 0 &&
+ js_Emit1(cx, cg, JSOP_POP) >= 0;
+ }
+
+ index = 0;
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ /*
+ * Duplicate the value being destructured to use as a reference base.
+ */
+ if (js_Emit1(cx, cg, JSOP_DUP) < 0)
+ return JS_FALSE;
+
+ /*
+ * Now push the property name currently being matched, which is either
+ * the array initialiser's current index, or the current property name
+ * "label" on the left of a colon in the object initialiser. Set pn3
+ * to the lvalue node, which is in the value-initializing position.
+ */
+ doElemOp = JS_TRUE;
+ if (pn->pn_type == TOK_RB) {
+ if (!EmitNumberOp(cx, index, cg))
+ return JS_FALSE;
+ pn3 = pn2;
+ } else {
+ JS_ASSERT(pn->pn_type == TOK_RC);
+ JS_ASSERT(pn2->pn_type == TOK_COLON);
+ pn3 = pn2->pn_left;
+ if (pn3->pn_type == TOK_NUMBER) {
+ /*
+ * If we are emitting an object destructuring initialiser,
+ * annotate the index op with SRC_INITPROP so we know we are
+ * not decompiling an array initialiser.
+ */
+ if (js_NewSrcNote(cx, cg, SRC_INITPROP) < 0)
+ return JS_FALSE;
+ if (!EmitNumberOp(cx, pn3->pn_dval, cg))
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(pn3->pn_type == TOK_STRING ||
+ pn3->pn_type == TOK_NAME);
+ if (!EmitAtomOp(cx, pn3, JSOP_GETPROP, cg))
+ return JS_FALSE;
+ doElemOp = JS_FALSE;
+ }
+ pn3 = pn2->pn_right;
+ }
+
+ if (doElemOp) {
+ /*
+ * Ok, get the value of the matching property name. This leaves
+ * that value on top of the value being destructured, so the stack
+ * is one deeper than when we started.
+ */
+ if (js_Emit1(cx, cg, JSOP_GETELEM) < 0)
+ return JS_FALSE;
+ JS_ASSERT(cg->stackDepth == stackDepth + 1);
+ }
+
+ /* Nullary comma node makes a hole in the array destructurer. */
+ if (pn3->pn_type == TOK_COMMA && pn3->pn_arity == PN_NULLARY) {
+ JS_ASSERT(pn->pn_type == TOK_RB);
+ JS_ASSERT(pn2 == pn3);
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ } else {
+ if (!EmitDestructuringLHS(cx, cg, pn3))
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(cg->stackDepth == stackDepth);
+ ++index;
+ }
+
+ return JS_TRUE;
+}
+
+static ptrdiff_t
+OpToDeclType(JSOp op)
+{
+ switch (op) {
+ case JSOP_NOP:
+ return SRC_DECL_LET;
+ case JSOP_DEFCONST:
+ return SRC_DECL_CONST;
+ case JSOP_DEFVAR:
+ return SRC_DECL_VAR;
+ default:
+ return SRC_DECL_NONE;
+ }
+}
+
+static JSBool
+EmitDestructuringOps(JSContext *cx, JSCodeGenerator *cg, JSOp declOp,
+ JSParseNode *pn)
+{
+ /*
+ * If we're called from a variable declaration, help the decompiler by
+ * annotating the first JSOP_DUP that EmitDestructuringOpsHelper emits.
+ * If the destructuring initialiser is empty, our helper will emit a
+ * JSOP_DUP followed by a JSOP_POP for the decompiler.
+ */
+ if (js_NewSrcNote2(cx, cg, SRC_DESTRUCT, OpToDeclType(declOp)) < 0)
+ return JS_FALSE;
+
+ /*
+ * Call our recursive helper to emit the destructuring assignments and
+ * related stack manipulations.
+ */
+ return EmitDestructuringOpsHelper(cx, cg, pn);
+}
+
+static JSBool
+EmitGroupAssignment(JSContext *cx, JSCodeGenerator *cg, JSOp declOp,
+ JSParseNode *lhs, JSParseNode *rhs)
+{
+ jsuint depth, limit, i, nslots;
+ JSParseNode *pn;
+
+ depth = limit = (uintN) cg->stackDepth;
+ for (pn = rhs->pn_head; pn; pn = pn->pn_next) {
+ if (limit == JS_BIT(16)) {
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), rhs, JSREPORT_ERROR,
+ JSMSG_ARRAY_INIT_TOO_BIG);
+ return JS_FALSE;
+ }
+
+ if (pn->pn_type == TOK_COMMA) {
+ if (js_Emit1(cx, cg, JSOP_PUSH) < 0)
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(pn->pn_type != TOK_DEFSHARP);
+ if (!js_EmitTree(cx, cg, pn))
+ return JS_FALSE;
+ }
+ ++limit;
+ }
+
+ if (js_NewSrcNote2(cx, cg, SRC_GROUPASSIGN, OpToDeclType(declOp)) < 0)
+ return JS_FALSE;
+
+ i = depth;
+ for (pn = lhs->pn_head; pn; pn = pn->pn_next, ++i) {
+ if (i < limit) {
+ jsint slot;
+
+ slot = AdjustBlockSlot(cx, cg, i);
+ if (slot < 0)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(JSOP_GETLOCAL, slot);
+ } else {
+ if (js_Emit1(cx, cg, JSOP_PUSH) < 0)
+ return JS_FALSE;
+ }
+ if (pn->pn_type == TOK_COMMA && pn->pn_arity == PN_NULLARY) {
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ } else {
+ if (!EmitDestructuringLHS(cx, cg, pn))
+ return JS_FALSE;
+ }
+ }
+
+ nslots = limit - depth;
+ EMIT_UINT16_IMM_OP(JSOP_POPN, nslots);
+ cg->stackDepth = (uintN) depth;
+ return JS_TRUE;
+}
+
+/*
+ * Helper called with pop out param initialized to a JSOP_POP* opcode. If we
+ * can emit a group assignment sequence, which results in 0 stack depth delta,
+ * we set *pop to JSOP_NOP so callers can veto emitting pn followed by a pop.
+ */
+static JSBool
+MaybeEmitGroupAssignment(JSContext *cx, JSCodeGenerator *cg, JSOp declOp,
+ JSParseNode *pn, JSOp *pop)
+{
+ JSParseNode *lhs, *rhs;
+
+ JS_ASSERT(pn->pn_type == TOK_ASSIGN);
+ JS_ASSERT(*pop == JSOP_POP || *pop == JSOP_POPV);
+ lhs = pn->pn_left;
+ rhs = pn->pn_right;
+ if (lhs->pn_type == TOK_RB && rhs->pn_type == TOK_RB &&
+ lhs->pn_count <= rhs->pn_count &&
+ (rhs->pn_count == 0 ||
+ rhs->pn_head->pn_type != TOK_DEFSHARP)) {
+ if (!EmitGroupAssignment(cx, cg, declOp, lhs, rhs))
+ return JS_FALSE;
+ *pop = JSOP_NOP;
+ }
+ return JS_TRUE;
+}
+
+#endif /* JS_HAS_DESTRUCTURING */
+
+static JSBool
+EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
+ JSBool inLetHead, ptrdiff_t *headNoteIndex)
+{
+ JSTreeContext *tc;
+ JSBool let, forInVar;
+#if JS_HAS_BLOCK_SCOPE
+ JSBool forInLet, popScope;
+ JSStmtInfo *stmt, *scopeStmt;
+#endif
+ ptrdiff_t off, noteIndex, tmp;
+ JSParseNode *pn2, *pn3;
+ JSOp op;
+ jsatomid atomIndex;
+ uintN oldflags;
+
+ /* Default in case of JS_HAS_BLOCK_SCOPE early return, below. */
+ *headNoteIndex = -1;
+
+ /*
+ * Let blocks and expressions have a parenthesized head in which the new
+ * scope is not yet open. Initializer evaluation uses the parent node's
+ * lexical scope. If popScope is true below, then we hide the top lexical
+ * block from any calls to BindNameToSlot hiding in pn2->pn_expr so that
+ * it won't find any names in the new let block.
+ *
+ * The same goes for let declarations in the head of any kind of for loop.
+ * Unlike a let declaration 'let x = i' within a block, where x is hoisted
+ * to the start of the block, a 'for (let x = i...) ...' loop evaluates i
+ * in the containing scope, and puts x in the loop body's scope.
+ */
+ tc = &cg->treeContext;
+ let = (pn->pn_op == JSOP_NOP);
+ forInVar = (pn->pn_extra & PNX_FORINVAR) != 0;
+#if JS_HAS_BLOCK_SCOPE
+ forInLet = let && forInVar;
+ popScope = (inLetHead || (let && (tc->flags & TCF_IN_FOR_INIT)));
+ JS_ASSERT(!popScope || let);
+#endif
+
+ off = noteIndex = -1;
+ for (pn2 = pn->pn_head; ; pn2 = pn2->pn_next) {
+#if JS_HAS_DESTRUCTURING
+ if (pn2->pn_type != TOK_NAME) {
+ if (pn2->pn_type == TOK_RB || pn2->pn_type == TOK_RC) {
+ /*
+ * Emit variable binding ops, but not destructuring ops.
+ * The parser (see Variables, jsparse.c) has ensured that
+ * our caller will be the TOK_FOR/TOK_IN case in js_EmitTree,
+ * and that case will emit the destructuring code only after
+ * emitting an enumerating opcode and a branch that tests
+ * whether the enumeration ended.
+ */
+ JS_ASSERT(forInVar);
+ JS_ASSERT(pn->pn_count == 1);
+ if (!EmitDestructuringDecls(cx, cg, PN_OP(pn), pn2))
+ return JS_FALSE;
+ break;
+ }
+
+ /*
+ * A destructuring initialiser assignment preceded by var will
+ * never occur to the left of 'in' in a for-in loop. As with 'for
+ * (var x = i in o)...', this will cause the entire 'var [a, b] =
+ * i' to be hoisted out of the loop.
+ */
+ JS_ASSERT(pn2->pn_type == TOK_ASSIGN);
+ JS_ASSERT(!forInVar);
+ if (pn->pn_count == 1) {
+ /*
+ * If this is the only destructuring assignment in the list,
+ * try to optimize to a group assignment. If we're in a let
+ * head, pass JSOP_POP rather than the pseudo-prolog JSOP_NOP
+ * in pn->pn_op, to suppress a second (and misplaced) 'let'.
+ */
+ JS_ASSERT(noteIndex < 0 && !pn2->pn_next);
+ op = JSOP_POP;
+ if (!MaybeEmitGroupAssignment(cx, cg,
+ inLetHead ? JSOP_POP : PN_OP(pn),
+ pn2, &op)) {
+ return JS_FALSE;
+ }
+ if (op == JSOP_NOP) {
+ pn->pn_extra = (pn->pn_extra & ~PNX_POPVAR) | PNX_GROUPINIT;
+ break;
+ }
+ }
+
+ pn3 = pn2->pn_left;
+ if (!EmitDestructuringDecls(cx, cg, PN_OP(pn), pn3))
+ return JS_FALSE;
+
+ if (!js_EmitTree(cx, cg, pn2->pn_right))
+ return JS_FALSE;
+
+ /*
+ * Veto pn->pn_op if inLetHead to avoid emitting a SRC_DESTRUCT
+ * that's redundant with respect to the SRC_DECL/SRC_DECL_LET that
+ * we will emit at the bottom of this function.
+ */
+ if (!EmitDestructuringOps(cx, cg,
+ inLetHead ? JSOP_POP : PN_OP(pn),
+ pn3)) {
+ return JS_FALSE;
+ }
+ goto emit_note_pop;
+ }
+#else
+ JS_ASSERT(pn2->pn_type == TOK_NAME);
+#endif
+
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ JS_ASSERT(pn2->pn_slot >= 0 || !let);
+
+ op = PN_OP(pn2);
+ if (op == JSOP_ARGUMENTS) {
+ /* JSOP_ARGUMENTS => no initializer */
+ JS_ASSERT(!pn2->pn_expr && !let);
+ pn3 = NULL;
+#ifdef __GNUC__
+ atomIndex = 0; /* quell GCC overwarning */
+#endif
+ } else {
+ if (!MaybeEmitVarDecl(cx, cg, PN_OP(pn), pn2, &atomIndex))
+ return JS_FALSE;
+
+ pn3 = pn2->pn_expr;
+ if (pn3) {
+ JS_ASSERT(!forInVar);
+ if (op == JSOP_SETNAME) {
+ JS_ASSERT(!let);
+ EMIT_INDEX_OP(JSOP_BINDNAME, atomIndex);
+ }
+ if (pn->pn_op == JSOP_DEFCONST &&
+ !js_DefineCompileTimeConstant(cx, cg, pn2->pn_atom,
+ pn3)) {
+ return JS_FALSE;
+ }
+
+#if JS_HAS_BLOCK_SCOPE
+ /* Evaluate expr in the outer lexical scope if requested. */
+ if (popScope) {
+ stmt = tc->topStmt;
+ scopeStmt = tc->topScopeStmt;
+
+ tc->topStmt = stmt->down;
+ tc->topScopeStmt = scopeStmt->downScope;
+ }
+# ifdef __GNUC__
+ else stmt = scopeStmt = NULL; /* quell GCC overwarning */
+# endif
+#endif
+
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+
+#if JS_HAS_BLOCK_SCOPE
+ if (popScope) {
+ tc->topStmt = stmt;
+ tc->topScopeStmt = scopeStmt;
+ }
+#endif
+ }
+ }
+
+ /*
+ * The parser rewrites 'for (var x = i in o)' to hoist 'var x = i' --
+ * likewise 'for (let x = i in o)' becomes 'i; for (let x in o)' using
+ * a TOK_SEQ node to make the two statements appear as one. Therefore
+ * if this declaration is part of a for-in loop head, we do not need to
+ * emit op or any source note. Our caller, the TOK_FOR/TOK_IN case in
+ * js_EmitTree, will annotate appropriately.
+ */
+ JS_ASSERT(pn3 == pn2->pn_expr);
+ if (forInVar) {
+ JS_ASSERT(pn->pn_count == 1);
+ JS_ASSERT(!pn3);
+ break;
+ }
+
+ if (pn2 == pn->pn_head &&
+ !inLetHead &&
+ js_NewSrcNote2(cx, cg, SRC_DECL,
+ (pn->pn_op == JSOP_DEFCONST)
+ ? SRC_DECL_CONST
+ : (pn->pn_op == JSOP_DEFVAR)
+ ? SRC_DECL_VAR
+ : SRC_DECL_LET) < 0) {
+ return JS_FALSE;
+ }
+ if (op == JSOP_ARGUMENTS) {
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ } else if (pn2->pn_slot >= 0) {
+ EMIT_UINT16_IMM_OP(op, atomIndex);
+ } else {
+ EMIT_INDEX_OP(op, atomIndex);
+ }
+
+#if JS_HAS_DESTRUCTURING
+ emit_note_pop:
+#endif
+ tmp = CG_OFFSET(cg);
+ if (noteIndex >= 0) {
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off))
+ return JS_FALSE;
+ }
+ if (!pn2->pn_next)
+ break;
+ off = tmp;
+ noteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0);
+ if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ }
+
+ /* If this is a let head, emit and return a srcnote on the pop. */
+ if (inLetHead) {
+ *headNoteIndex = js_NewSrcNote(cx, cg, SRC_DECL);
+ if (*headNoteIndex < 0)
+ return JS_FALSE;
+ if (!(pn->pn_extra & PNX_POPVAR))
+ return js_Emit1(cx, cg, JSOP_NOP) >= 0;
+ }
+
+ return !(pn->pn_extra & PNX_POPVAR) || js_Emit1(cx, cg, JSOP_POP) >= 0;
+}
+
+#if defined DEBUG_brendanXXX || defined DEBUG_mrbkap
+static JSBool
+GettableNoteForNextOp(JSCodeGenerator *cg)
+{
+ ptrdiff_t offset, target;
+ jssrcnote *sn, *end;
+
+ offset = 0;
+ target = CG_OFFSET(cg);
+ for (sn = CG_NOTES(cg), end = sn + CG_NOTE_COUNT(cg); sn < end;
+ sn = SN_NEXT(sn)) {
+ if (offset == target && SN_IS_GETTABLE(sn))
+ return JS_TRUE;
+ offset += SN_DELTA(sn);
+ }
+ return JS_FALSE;
+}
+#endif
+
+/* Top-level named functions need a nop for decompilation. */
+static JSBool
+EmitFunctionDefNop(JSContext *cx, JSCodeGenerator *cg, uintN index)
+{
+ return js_NewSrcNote2(cx, cg, SRC_FUNCDEF, (ptrdiff_t)index) >= 0 &&
+ js_Emit1(cx, cg, JSOP_NOP) >= 0;
+}
+
+/* See the SRC_FOR source note offsetBias comments later in this file. */
+JS_STATIC_ASSERT(JSOP_NOP_LENGTH == 1);
+JS_STATIC_ASSERT(JSOP_POP_LENGTH == 1);
+
+JSBool
+js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
+{
+ JSBool ok, useful, wantval;
+ JSStmtInfo *stmt, stmtInfo;
+ ptrdiff_t top, off, tmp, beq, jmp;
+ JSParseNode *pn2, *pn3;
+ JSAtom *atom;
+ JSAtomListElement *ale;
+ jsatomid atomIndex;
+ uintN index;
+ ptrdiff_t noteIndex;
+ JSSrcNoteType noteType;
+ jsbytecode *pc;
+ JSOp op;
+ JSTokenType type;
+ uint32 argc;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ ok = JS_TRUE;
+ cg->emitLevel++;
+ pn->pn_offset = top = CG_OFFSET(cg);
+
+ /* Emit notes to tell the current bytecode's source line number. */
+ UPDATE_LINE_NUMBER_NOTES(cx, cg, pn);
+
+ switch (pn->pn_type) {
+ case TOK_FUNCTION:
+ {
+ JSFunction *fun;
+ void *cg2mark;
+ JSCodeGenerator *cg2;
+ uintN slot;
+
+#if JS_HAS_XML_SUPPORT
+ if (pn->pn_arity == PN_NULLARY) {
+ if (js_Emit1(cx, cg, JSOP_GETFUNNS) < 0)
+ return JS_FALSE;
+ break;
+ }
+#endif
+
+ fun = (JSFunction *) pn->pn_funpob->object;
+ if (fun->u.i.script) {
+ /*
+ * This second pass is needed to emit JSOP_NOP with a source note
+ * for the already-emitted function definition prolog opcode. See
+ * comments in the TOK_LC case.
+ */
+ JS_ASSERT(pn->pn_op == JSOP_NOP);
+ JS_ASSERT(cg->treeContext.flags & TCF_IN_FUNCTION);
+ JS_ASSERT(pn->pn_index != (uint32) -1);
+ if (!EmitFunctionDefNop(cx, cg, pn->pn_index))
+ return JS_FALSE;
+ break;
+ }
+
+ /*
+ * Limit static nesting depth to fit in 16 bits. See cg2->staticDepth
+ * assignment below.
+ */
+ if (cg->staticDepth == JS_BITMASK(16)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TOO_DEEP,
+ js_function_str);
+ return JS_FALSE;
+ }
+
+ /* Generate code for the function's body. */
+ cg2mark = JS_ARENA_MARK(cg->codePool);
+ JS_ARENA_ALLOCATE_TYPE(cg2, JSCodeGenerator, cg->codePool);
+ if (!cg2) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ js_InitCodeGenerator(cx, cg2, cg->treeContext.parseContext,
+ cg->codePool, cg->notePool,
+ pn->pn_pos.begin.lineno);
+ cg2->treeContext.flags = (uint16) (pn->pn_flags | TCF_IN_FUNCTION);
+ cg2->treeContext.u.fun = fun;
+ cg2->staticDepth = cg->staticDepth + 1;
+ cg2->parent = cg;
+
+ /* We metered the max scope depth when parsed the function. */
+ JS_SCOPE_DEPTH_METERING(cg2->treeContext.maxScopeDepth = (uintN) -1);
+ if (!js_EmitFunctionScript(cx, cg2, pn->pn_body)) {
+ pn = NULL;
+ } else {
+ /*
+ * We need an activation object if an inner peeks out, or if such
+ * inner-peeking caused one of our inners to become heavyweight.
+ */
+ if (cg2->treeContext.flags &
+ (TCF_FUN_USES_NONLOCALS | TCF_FUN_HEAVYWEIGHT)) {
+ cg->treeContext.flags |= TCF_FUN_HEAVYWEIGHT;
+ }
+ }
+
+ js_FinishCodeGenerator(cx, cg2);
+ JS_ARENA_RELEASE(cg->codePool, cg2mark);
+ cg2 = NULL;
+ if (!pn)
+ return JS_FALSE;
+
+ /* Make the function object a literal in the outer script's pool. */
+ index = IndexParsedObject(pn->pn_funpob, &cg->objectList);
+
+ /* Emit a bytecode pointing to the closure object in its immediate. */
+ if (pn->pn_op != JSOP_NOP) {
+ if ((pn->pn_flags & TCF_GENEXP_LAMBDA) &&
+ js_NewSrcNote(cx, cg, SRC_GENEXP) < 0) {
+ return JS_FALSE;
+ }
+ EMIT_INDEX_OP(PN_OP(pn), index);
+ break;
+ }
+
+ /*
+ * For a script we emit the code as we parse. Thus the bytecode for
+ * top-level functions should go in the prolog to predefine their
+ * names in the variable object before the already-generated main code
+ * is executed. This extra work for top-level scripts is not necessary
+ * when we emit the code for a function. It is fully parsed prior to
+ * invocation of the emitter and calls to js_EmitTree for function
+ * definitions can be scheduled before generating the rest of code.
+ */
+ if (!(cg->treeContext.flags & TCF_IN_FUNCTION)) {
+ JS_ASSERT(!cg->treeContext.topStmt);
+ CG_SWITCH_TO_PROLOG(cg);
+ EMIT_INDEX_OP(JSOP_DEFFUN, index);
+ CG_SWITCH_TO_MAIN(cg);
+
+ /* Emit NOP for the decompiler. */
+ if (!EmitFunctionDefNop(cx, cg, index))
+ return JS_FALSE;
+ } else {
+#ifdef DEBUG
+ JSLocalKind localKind =
+#endif
+ js_LookupLocal(cx, cg->treeContext.u.fun, fun->atom, &slot);
+ JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
+ JS_ASSERT(pn->pn_index == (uint32) -1);
+ pn->pn_index = index;
+ if (!EmitSlotIndexOp(cx, JSOP_DEFLOCALFUN, slot, index, cg))
+ return JS_FALSE;
+ }
+ break;
+ }
+
+
+ case TOK_IF:
+ /* Initialize so we can detect else-if chains and avoid recursion. */
+ stmtInfo.type = STMT_IF;
+ beq = jmp = -1;
+ noteIndex = -1;
+
+ if_again:
+ /* Emit code for the condition before pushing stmtInfo. */
+ if (!js_EmitTree(cx, cg, pn->pn_kid1))
+ return JS_FALSE;
+ top = CG_OFFSET(cg);
+ if (stmtInfo.type == STMT_IF) {
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_IF, top);
+ } else {
+ /*
+ * We came here from the goto further below that detects else-if
+ * chains, so we must mutate stmtInfo back into a STMT_IF record.
+ * Also (see below for why) we need a note offset for SRC_IF_ELSE
+ * to help the decompiler. Actually, we need two offsets, one for
+ * decompiling any else clause and the second for decompiling an
+ * else-if chain without bracing, overindenting, or incorrectly
+ * scoping let declarations.
+ */
+ JS_ASSERT(stmtInfo.type == STMT_ELSE);
+ stmtInfo.type = STMT_IF;
+ stmtInfo.update = top;
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq))
+ return JS_FALSE;
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 1, top - jmp))
+ return JS_FALSE;
+ }
+
+ /* Emit an annotated branch-if-false around the then part. */
+ pn3 = pn->pn_kid3;
+ noteIndex = js_NewSrcNote(cx, cg, pn3 ? SRC_IF_ELSE : SRC_IF);
+ if (noteIndex < 0)
+ return JS_FALSE;
+ beq = EmitJump(cx, cg, JSOP_IFEQ, 0);
+ if (beq < 0)
+ return JS_FALSE;
+
+ /* Emit code for the then and optional else parts. */
+ if (!js_EmitTree(cx, cg, pn->pn_kid2))
+ return JS_FALSE;
+ if (pn3) {
+ /* Modify stmtInfo so we know we're in the else part. */
+ stmtInfo.type = STMT_ELSE;
+
+ /*
+ * Emit a JSOP_BACKPATCH op to jump from the end of our then part
+ * around the else part. The js_PopStatementCG call at the bottom
+ * of this switch case will fix up the backpatch chain linked from
+ * stmtInfo.breaks.
+ */
+ jmp = EmitGoto(cx, cg, &stmtInfo, &stmtInfo.breaks, NULL, SRC_NULL);
+ if (jmp < 0)
+ return JS_FALSE;
+
+ /* Ensure the branch-if-false comes here, then emit the else. */
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);
+ if (pn3->pn_type == TOK_IF) {
+ pn = pn3;
+ goto if_again;
+ }
+
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+
+ /*
+ * Annotate SRC_IF_ELSE with the offset from branch to jump, for
+ * the decompiler's benefit. We can't just "back up" from the pc
+ * of the else clause, because we don't know whether an extended
+ * jump was required to leap from the end of the then clause over
+ * the else clause.
+ */
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq))
+ return JS_FALSE;
+ } else {
+ /* No else part, fixup the branch-if-false to come here. */
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);
+ }
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_SWITCH:
+ /* Out of line to avoid bloating js_EmitTree's stack frame size. */
+ ok = EmitSwitch(cx, cg, pn, &stmtInfo);
+ break;
+
+ case TOK_WHILE:
+ /*
+ * Minimize bytecodes issued for one or more iterations by jumping to
+ * the condition below the body and closing the loop if the condition
+ * is true with a backward branch. For iteration count i:
+ *
+ * i test at the top test at the bottom
+ * = =============== ==================
+ * 0 ifeq-pass goto; ifne-fail
+ * 1 ifeq-fail; goto; ifne-pass goto; ifne-pass; ifne-fail
+ * 2 2*(ifeq-fail; goto); ifeq-pass goto; 2*ifne-pass; ifne-fail
+ * . . .
+ * N N*(ifeq-fail; goto); ifeq-pass goto; N*ifne-pass; ifne-fail
+ *
+ * SpiderMonkey, pre-mozilla.org, emitted while parsing and so used
+ * test at the top. When JSParseNode trees were added during the ES3
+ * work (1998-9), the code generation scheme was not optimized, and
+ * the decompiler continued to take advantage of the branch and jump
+ * that bracketed the body. But given the SRC_WHILE note, it is easy
+ * to support the more efficient scheme.
+ */
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_WHILE_LOOP, top);
+ noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE);
+ if (noteIndex < 0)
+ return JS_FALSE;
+ jmp = EmitJump(cx, cg, JSOP_GOTO, 0);
+ if (jmp < 0)
+ return JS_FALSE;
+ top = CG_OFFSET(cg);
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+ beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg));
+ if (beq < 0)
+ return JS_FALSE;
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, beq - jmp))
+ return JS_FALSE;
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_DO:
+ /* Emit an annotated nop so we know to decompile a 'do' keyword. */
+ noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE);
+ if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_NOP) < 0)
+ return JS_FALSE;
+
+ /* Compile the loop body. */
+ top = CG_OFFSET(cg);
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_DO_LOOP, top);
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+
+ /* Set loop and enclosing label update offsets, for continue. */
+ stmt = &stmtInfo;
+ do {
+ stmt->update = CG_OFFSET(cg);
+ } while ((stmt = stmt->down) != NULL && stmt->type == STMT_LABEL);
+
+ /* Compile the loop condition, now that continues know where to go. */
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+
+ /*
+ * Since we use JSOP_IFNE for other purposes as well as for do-while
+ * loops, we must store 1 + (beq - top) in the SRC_WHILE note offset,
+ * and the decompiler must get that delta and decompile recursively.
+ */
+ beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg));
+ if (beq < 0)
+ return JS_FALSE;
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, 1 + (beq - top)))
+ return JS_FALSE;
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_FOR:
+ beq = 0; /* suppress gcc warnings */
+ jmp = -1;
+ pn2 = pn->pn_left;
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_FOR_LOOP, top);
+
+ if (pn2->pn_type == TOK_IN) {
+ /* Set stmtInfo type for later testing. */
+ stmtInfo.type = STMT_FOR_IN_LOOP;
+
+ /*
+ * If the left part is 'var x', emit code to define x if necessary
+ * using a prolog opcode, but do not emit a pop. If the left part
+ * is 'var x = i', emit prolog code to define x if necessary; then
+ * emit code to evaluate i, assign the result to x, and pop the
+ * result off the stack.
+ *
+ * All the logic to do this is implemented in the outer switch's
+ * TOK_VAR case, conditioned on pn_extra flags set by the parser.
+ *
+ * In the 'for (var x = i in o) ...' case, the js_EmitTree(...pn3)
+ * called here will generate the proper note for the assignment
+ * op that sets x = i, hoisting the initialized var declaration
+ * out of the loop: 'var x = i; for (x in o) ...'.
+ *
+ * In the 'for (var x in o) ...' case, nothing but the prolog op
+ * (if needed) should be generated here, we must emit the note
+ * just before the JSOP_FOR* opcode in the switch on pn3->pn_type
+ * a bit below, so nothing is hoisted: 'for (var x in o) ...'.
+ *
+ * A 'for (let x = i in o)' loop must not be hoisted, since in
+ * this form the let variable is scoped by the loop body (but not
+ * the head). The initializer expression i must be evaluated for
+ * any side effects. So we hoist only i in the let case.
+ */
+ pn3 = pn2->pn_left;
+ type = PN_TYPE(pn3);
+ cg->treeContext.flags |= TCF_IN_FOR_INIT;
+ if (TOKEN_TYPE_IS_DECL(type) && !js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+
+ /* Compile the object expression to the right of 'in'. */
+ if (!js_EmitTree(cx, cg, pn2->pn_right))
+ return JS_FALSE;
+
+ /*
+ * Emit a bytecode to convert top of stack value to the iterator
+ * object depending on the loop variant (for-in, for-each-in, or
+ * destructuring for-in).
+ */
+ JS_ASSERT(pn->pn_op == JSOP_ITER);
+ if (js_Emit2(cx, cg, JSOP_ITER, (uint8) pn->pn_iflags) < 0)
+ return JS_FALSE;
+
+ /* Annotate so the decompiler can find the loop-closing jump. */
+ noteIndex = js_NewSrcNote(cx, cg, SRC_FOR_IN);
+ if (noteIndex < 0)
+ return JS_FALSE;
+
+ /*
+ * Jump down to the loop condition to minimize overhead assuming at
+ * least one iteration, as the other loop forms do.
+ */
+ jmp = EmitJump(cx, cg, JSOP_GOTO, 0);
+ if (jmp < 0)
+ return JS_FALSE;
+
+ top = CG_OFFSET(cg);
+ SET_STATEMENT_TOP(&stmtInfo, top);
+
+#ifdef DEBUG
+ intN loopDepth = cg->stackDepth;
+#endif
+
+ /*
+ * Compile a JSOP_FOR* bytecode based on the left hand side.
+ *
+ * Initialize op to JSOP_SETNAME in case of |for ([a, b] in o)...|
+ * or similar, to signify assignment, rather than declaration, to
+ * the decompiler. EmitDestructuringOps takes a prolog bytecode
+ * parameter and emits the appropriate source note, defaulting to
+ * assignment, so JSOP_SETNAME is not critical here; many similar
+ * ops could be used -- just not JSOP_NOP (which means 'let').
+ */
+ op = JSOP_SETNAME;
+ switch (type) {
+#if JS_HAS_BLOCK_SCOPE
+ case TOK_LET:
+#endif
+ case TOK_VAR:
+ JS_ASSERT(pn3->pn_arity == PN_LIST && pn3->pn_count == 1);
+ pn3 = pn3->pn_head;
+#if JS_HAS_DESTRUCTURING
+ if (pn3->pn_type == TOK_ASSIGN) {
+ pn3 = pn3->pn_left;
+ JS_ASSERT(pn3->pn_type == TOK_RB || pn3->pn_type == TOK_RC);
+ }
+ if (pn3->pn_type == TOK_RB || pn3->pn_type == TOK_RC) {
+ op = PN_OP(pn2->pn_left);
+ goto destructuring_for;
+ }
+#else
+ JS_ASSERT(pn3->pn_type == TOK_NAME);
+#endif
+ /* FALL THROUGH */
+
+ case TOK_NAME:
+ /*
+ * Always annotate JSOP_FORLOCAL if given input of the form
+ * 'for (let x in * o)' -- the decompiler must not hoist the
+ * 'let x' out of the loop head, or x will be bound in the
+ * wrong scope. Likewise, but in this case only for the sake
+ * of higher decompilation fidelity only, do not hoist 'var x'
+ * when given 'for (var x in o)'.
+ */
+ if ((
+#if JS_HAS_BLOCK_SCOPE
+ type == TOK_LET ||
+#endif
+ (type == TOK_VAR && !pn3->pn_expr)) &&
+ js_NewSrcNote2(cx, cg, SRC_DECL,
+ (type == TOK_VAR)
+ ? SRC_DECL_VAR
+ : SRC_DECL_LET) < 0) {
+ return JS_FALSE;
+ }
+ if (pn3->pn_slot >= 0) {
+ op = PN_OP(pn3);
+ switch (op) {
+ case JSOP_GETARG: /* FALL THROUGH */
+ case JSOP_SETARG: op = JSOP_FORARG; break;
+ case JSOP_GETGVAR: /* FALL THROUGH */
+ case JSOP_SETGVAR: op = JSOP_FORNAME; break;
+ case JSOP_GETLOCAL: /* FALL THROUGH */
+ case JSOP_SETLOCAL: op = JSOP_FORLOCAL; break;
+ default: JS_ASSERT(0);
+ }
+ } else {
+ pn3->pn_op = JSOP_FORNAME;
+ if (!BindNameToSlot(cx, cg, pn3))
+ return JS_FALSE;
+ op = PN_OP(pn3);
+ }
+ if (pn3->pn_slot >= 0) {
+ if (pn3->pn_const) {
+ JS_ASSERT(op == JSOP_FORLOCAL);
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), pn3, JSREPORT_ERROR,
+ JSMSG_BAD_FOR_LEFTSIDE);
+ return JS_FALSE;
+ }
+ atomIndex = (jsatomid) pn3->pn_slot;
+ EMIT_UINT16_IMM_OP(op, atomIndex);
+ } else {
+ if (!EmitAtomOp(cx, pn3, op, cg))
+ return JS_FALSE;
+ }
+ break;
+
+ case TOK_DOT:
+ /*
+ * 'for (o.p in q)' can use JSOP_FORPROP only if evaluating 'o'
+ * has no side effects.
+ */
+ useful = JS_FALSE;
+ if (!CheckSideEffects(cx, cg, pn3->pn_expr, &useful))
+ return JS_FALSE;
+ if (!useful) {
+ if (!EmitPropOp(cx, pn3, JSOP_FORPROP, cg, JS_FALSE))
+ return JS_FALSE;
+ break;
+ }
+ /* FALL THROUGH */
+
+#if JS_HAS_DESTRUCTURING
+ destructuring_for:
+#endif
+ default:
+ if (js_Emit1(cx, cg, JSOP_FORELEM) < 0)
+ return JS_FALSE;
+ JS_ASSERT(cg->stackDepth >= 3);
+
+#if JS_HAS_DESTRUCTURING
+ if (pn3->pn_type == TOK_RB || pn3->pn_type == TOK_RC) {
+ if (!EmitDestructuringOps(cx, cg, op, pn3))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ } else
+#endif
+#if JS_HAS_LVALUE_RETURN
+ if (pn3->pn_type == TOK_LP) {
+ JS_ASSERT(pn3->pn_op == JSOP_SETCALL);
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_ENUMELEM) < 0)
+ return JS_FALSE;
+ } else
+#endif
+#if JS_HAS_XML_SUPPORT
+ if (pn3->pn_type == TOK_UNARYOP) {
+ JS_ASSERT(pn3->pn_op == JSOP_BINDXMLNAME);
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_ENUMELEM) < 0)
+ return JS_FALSE;
+ } else
+#endif
+ if (!EmitElemOp(cx, pn3, JSOP_ENUMELEM, cg))
+ return JS_FALSE;
+ break;
+ }
+
+ /* The stack should be balanced around the JSOP_FOR* opcode sequence. */
+ JS_ASSERT(cg->stackDepth == loopDepth);
+
+ /* Set the first srcnote offset so we can find the start of the loop body. */
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, CG_OFFSET(cg) - jmp))
+ return JS_FALSE;
+
+ /* Emit code for the loop body. */
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+
+ /* Set loop and enclosing "update" offsets, for continue. */
+ stmt = &stmtInfo;
+ do {
+ stmt->update = CG_OFFSET(cg);
+ } while ((stmt = stmt->down) != NULL && stmt->type == STMT_LABEL);
+
+ /*
+ * Fixup the goto that starts the loop to jump down to JSOP_NEXTITER.
+ */
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
+ if (js_Emit1(cx, cg, JSOP_NEXTITER) < 0)
+ return JS_FALSE;
+ beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg));
+ if (beq < 0)
+ return JS_FALSE;
+
+ /* Set the second srcnote offset so we can find the closing jump. */
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, beq - jmp))
+ return JS_FALSE;
+ } else {
+ /* C-style for (init; cond; update) ... loop. */
+ op = JSOP_POP;
+ pn3 = pn2->pn_kid1;
+ if (!pn3) {
+ /* No initializer: emit an annotated nop for the decompiler. */
+ op = JSOP_NOP;
+ } else {
+ cg->treeContext.flags |= TCF_IN_FOR_INIT;
+#if JS_HAS_DESTRUCTURING
+ if (pn3->pn_type == TOK_ASSIGN &&
+ !MaybeEmitGroupAssignment(cx, cg, op, pn3, &op)) {
+ return JS_FALSE;
+ }
+#endif
+ if (op == JSOP_POP) {
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ if (TOKEN_TYPE_IS_DECL(pn3->pn_type)) {
+ /*
+ * Check whether a destructuring-initialized var decl
+ * was optimized to a group assignment. If so, we do
+ * not need to emit a pop below, so switch to a nop,
+ * just for the decompiler.
+ */
+ JS_ASSERT(pn3->pn_arity == PN_LIST);
+ if (pn3->pn_extra & PNX_GROUPINIT)
+ op = JSOP_NOP;
+ }
+ }
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ }
+
+ /*
+ * NB: the SRC_FOR note has offsetBias 1 (JSOP_{NOP,POP}_LENGTH).
+ * Use tmp to hold the biased srcnote "top" offset, which differs
+ * from the top local variable by the length of the JSOP_GOTO{,X}
+ * emitted in between tmp and top if this loop has a condition.
+ */
+ noteIndex = js_NewSrcNote(cx, cg, SRC_FOR);
+ if (noteIndex < 0 || js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ tmp = CG_OFFSET(cg);
+
+ if (pn2->pn_kid2) {
+ /* Goto the loop condition, which branches back to iterate. */
+ jmp = EmitJump(cx, cg, JSOP_GOTO, 0);
+ if (jmp < 0)
+ return JS_FALSE;
+ }
+
+ top = CG_OFFSET(cg);
+ SET_STATEMENT_TOP(&stmtInfo, top);
+
+ /* Emit code for the loop body. */
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+
+ /* Set the second note offset so we can find the update part. */
+ JS_ASSERT(noteIndex != -1);
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1,
+ CG_OFFSET(cg) - tmp)) {
+ return JS_FALSE;
+ }
+
+ /* Set loop and enclosing "update" offsets, for continue. */
+ stmt = &stmtInfo;
+ do {
+ stmt->update = CG_OFFSET(cg);
+ } while ((stmt = stmt->down) != NULL && stmt->type == STMT_LABEL);
+
+ /* Check for update code to do before the condition (if any). */
+ pn3 = pn2->pn_kid3;
+ if (pn3) {
+ op = JSOP_POP;
+#if JS_HAS_DESTRUCTURING
+ if (pn3->pn_type == TOK_ASSIGN &&
+ !MaybeEmitGroupAssignment(cx, cg, op, pn3, &op)) {
+ return JS_FALSE;
+ }
+#endif
+ if (op == JSOP_POP && !js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+
+ /* Always emit the POP or NOP, to help the decompiler. */
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+
+ /* Restore the absolute line number for source note readers. */
+ off = (ptrdiff_t) pn->pn_pos.end.lineno;
+ if (CG_CURRENT_LINE(cg) != (uintN) off) {
+ if (js_NewSrcNote2(cx, cg, SRC_SETLINE, off) < 0)
+ return JS_FALSE;
+ CG_CURRENT_LINE(cg) = (uintN) off;
+ }
+ }
+
+ /* Set the first note offset so we can find the loop condition. */
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0,
+ CG_OFFSET(cg) - tmp)) {
+ return JS_FALSE;
+ }
+
+ if (pn2->pn_kid2) {
+ /* Fix up the goto from top to target the loop condition. */
+ JS_ASSERT(jmp >= 0);
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
+
+ if (!js_EmitTree(cx, cg, pn2->pn_kid2))
+ return JS_FALSE;
+ }
+
+ /* The third note offset helps us find the loop-closing jump. */
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 2,
+ CG_OFFSET(cg) - tmp)) {
+ return JS_FALSE;
+ }
+
+ if (pn2->pn_kid2) {
+ beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg));
+ if (beq < 0)
+ return JS_FALSE;
+ } else {
+ /* No loop condition -- emit the loop-closing jump. */
+ jmp = EmitJump(cx, cg, JSOP_GOTO, top - CG_OFFSET(cg));
+ if (jmp < 0)
+ return JS_FALSE;
+ }
+ }
+
+ /* Now fixup all breaks and continues (before for/in's JSOP_ENDITER). */
+ if (!js_PopStatementCG(cx, cg))
+ return JS_FALSE;
+
+ if (pn2->pn_type == TOK_IN) {
+ /*
+ * JSOP_ENDITER must have a slot to save an exception thrown from
+ * the body of for-in loop when closing the iterator object, and
+ * fortunately it does: the slot that was set by JSOP_NEXTITER to
+ * the return value of iterator.next().
+ */
+ JS_ASSERT(js_CodeSpec[JSOP_ENDITER].nuses == 2);
+ if (!NewTryNote(cx, cg, JSTRY_ITER, cg->stackDepth, top, CG_OFFSET(cg)) ||
+ js_Emit1(cx, cg, JSOP_ENDITER) < 0) {
+ return JS_FALSE;
+ }
+ }
+ break;
+
+ case TOK_BREAK:
+ stmt = cg->treeContext.topStmt;
+ atom = pn->pn_atom;
+ if (atom) {
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ while (stmt->type != STMT_LABEL || stmt->u.label != atom)
+ stmt = stmt->down;
+ noteType = SRC_BREAK2LABEL;
+ } else {
+ ale = NULL;
+ while (!STMT_IS_LOOP(stmt) && stmt->type != STMT_SWITCH)
+ stmt = stmt->down;
+ noteType = (stmt->type == STMT_SWITCH) ? SRC_NULL : SRC_BREAK;
+ }
+
+ if (EmitGoto(cx, cg, stmt, &stmt->breaks, ale, noteType) < 0)
+ return JS_FALSE;
+ break;
+
+ case TOK_CONTINUE:
+ stmt = cg->treeContext.topStmt;
+ atom = pn->pn_atom;
+ if (atom) {
+ /* Find the loop statement enclosed by the matching label. */
+ JSStmtInfo *loop = NULL;
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ while (stmt->type != STMT_LABEL || stmt->u.label != atom) {
+ if (STMT_IS_LOOP(stmt))
+ loop = stmt;
+ stmt = stmt->down;
+ }
+ stmt = loop;
+ noteType = SRC_CONT2LABEL;
+ } else {
+ ale = NULL;
+ while (!STMT_IS_LOOP(stmt))
+ stmt = stmt->down;
+ noteType = SRC_CONTINUE;
+ }
+
+ if (EmitGoto(cx, cg, stmt, &stmt->continues, ale, noteType) < 0)
+ return JS_FALSE;
+ break;
+
+ case TOK_WITH:
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_WITH, CG_OFFSET(cg));
+ if (js_Emit1(cx, cg, JSOP_ENTERWITH) < 0)
+ return JS_FALSE;
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0)
+ return JS_FALSE;
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_TRY:
+ {
+ ptrdiff_t tryStart, tryEnd, catchJump, finallyStart;
+ intN depth;
+ JSParseNode *lastCatch;
+
+ catchJump = -1;
+
+ /*
+ * Push stmtInfo to track jumps-over-catches and gosubs-to-finally
+ * for later fixup.
+ *
+ * When a finally block is 'active' (STMT_FINALLY on the treeContext),
+ * non-local jumps (including jumps-over-catches) result in a GOSUB
+ * being written into the bytecode stream and fixed-up later (c.f.
+ * EmitBackPatchOp and BackPatch).
+ */
+ js_PushStatement(&cg->treeContext, &stmtInfo,
+ pn->pn_kid3 ? STMT_FINALLY : STMT_TRY,
+ CG_OFFSET(cg));
+
+ /*
+ * Since an exception can be thrown at any place inside the try block,
+ * we need to restore the stack and the scope chain before we transfer
+ * the control to the exception handler.
+ *
+ * For that we store in a try note associated with the catch or
+ * finally block the stack depth upon the try entry. The interpreter
+ * uses this depth to properly unwind the stack and the scope chain.
+ */
+ depth = cg->stackDepth;
+
+ /* Mark try location for decompilation, then emit try block. */
+ if (js_Emit1(cx, cg, JSOP_TRY) < 0)
+ return JS_FALSE;
+ tryStart = CG_OFFSET(cg);
+ if (!js_EmitTree(cx, cg, pn->pn_kid1))
+ return JS_FALSE;
+ JS_ASSERT(depth == cg->stackDepth);
+
+ /* GOSUB to finally, if present. */
+ if (pn->pn_kid3) {
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &GOSUBS(stmtInfo));
+ if (jmp < 0)
+ return JS_FALSE;
+ }
+
+ /* Emit (hidden) jump over catch and/or finally. */
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &catchJump);
+ if (jmp < 0)
+ return JS_FALSE;
+
+ tryEnd = CG_OFFSET(cg);
+
+ /* If this try has a catch block, emit it. */
+ pn2 = pn->pn_kid2;
+ lastCatch = NULL;
+ if (pn2) {
+ jsint count = 0; /* previous catch block's population */
+
+ /*
+ * The emitted code for a catch block looks like:
+ *
+ * [throwing] only if 2nd+ catch block
+ * [leaveblock] only if 2nd+ catch block
+ * enterblock with SRC_CATCH
+ * exception
+ * [dup] only if catchguard
+ * setlocalpop <slot> or destructuring code
+ * [< catchguard code >] if there's a catchguard
+ * [ifeq <offset to next catch block>] " "
+ * [pop] only if catchguard
+ * < catch block contents >
+ * leaveblock
+ * goto <end of catch blocks> non-local; finally applies
+ *
+ * If there's no catch block without a catchguard, the last
+ * <offset to next catch block> points to rethrow code. This
+ * code will [gosub] to the finally code if appropriate, and is
+ * also used for the catch-all trynote for capturing exceptions
+ * thrown from catch{} blocks.
+ */
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ ptrdiff_t guardJump, catchNote;
+
+ JS_ASSERT(cg->stackDepth == depth);
+ guardJump = GUARDJUMP(stmtInfo);
+ if (guardJump != -1) {
+ /* Fix up and clean up previous catch block. */
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, guardJump);
+
+ /*
+ * Account for JSOP_ENTERBLOCK (whose block object count
+ * is saved below) and pushed exception object that we
+ * still have after the jumping from the previous guard.
+ */
+ cg->stackDepth = depth + count + 1;
+
+ /*
+ * Move exception back to cx->exception to prepare for
+ * the next catch. We hide [throwing] from the decompiler
+ * since it compensates for the hidden JSOP_DUP at the
+ * start of the previous guarded catch.
+ */
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||
+ js_Emit1(cx, cg, JSOP_THROWING) < 0) {
+ return JS_FALSE;
+ }
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, count);
+ JS_ASSERT(cg->stackDepth == depth);
+ }
+
+ /*
+ * Annotate the JSOP_ENTERBLOCK that's about to be generated
+ * by the call to js_EmitTree immediately below. Save this
+ * source note's index in stmtInfo for use by the TOK_CATCH:
+ * case, where the length of the catch guard is set as the
+ * note's offset.
+ */
+ catchNote = js_NewSrcNote2(cx, cg, SRC_CATCH, 0);
+ if (catchNote < 0)
+ return JS_FALSE;
+ CATCHNOTE(stmtInfo) = catchNote;
+
+ /*
+ * Emit the lexical scope and catch body. Save the catch's
+ * block object population via count, for use when targeting
+ * guardJump at the next catch (the guard mismatch case).
+ */
+ JS_ASSERT(pn3->pn_type == TOK_LEXICALSCOPE);
+ count = OBJ_BLOCK_COUNT(cx, pn3->pn_pob->object);
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+
+ /* gosub <finally>, if required */
+ if (pn->pn_kid3) {
+ jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH,
+ &GOSUBS(stmtInfo));
+ if (jmp < 0)
+ return JS_FALSE;
+ JS_ASSERT(cg->stackDepth == depth);
+ }
+
+ /*
+ * Jump over the remaining catch blocks. This will get fixed
+ * up to jump to after catch/finally.
+ */
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &catchJump);
+ if (jmp < 0)
+ return JS_FALSE;
+
+ /*
+ * Save a pointer to the last catch node to handle try-finally
+ * and try-catch(guard)-finally special cases.
+ */
+ lastCatch = pn3->pn_expr;
+ }
+ }
+
+ /*
+ * Last catch guard jumps to the rethrow code sequence if none of the
+ * guards match. Target guardJump at the beginning of the rethrow
+ * sequence, just in case a guard expression throws and leaves the
+ * stack unbalanced.
+ */
+ if (lastCatch && lastCatch->pn_kid2) {
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, GUARDJUMP(stmtInfo));
+
+ /* Sync the stack to take into account pushed exception. */
+ JS_ASSERT(cg->stackDepth == depth);
+ cg->stackDepth = depth + 1;
+
+ /*
+ * Rethrow the exception, delegating executing of finally if any
+ * to the exception handler.
+ */
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||
+ js_Emit1(cx, cg, JSOP_THROW) < 0) {
+ return JS_FALSE;
+ }
+ }
+
+ JS_ASSERT(cg->stackDepth == depth);
+
+ /* Emit finally handler if any. */
+ finallyStart = 0; /* to quell GCC uninitialized warnings */
+ if (pn->pn_kid3) {
+ /*
+ * Fix up the gosubs that might have been emitted before non-local
+ * jumps to the finally code.
+ */
+ if (!BackPatch(cx, cg, GOSUBS(stmtInfo), CG_NEXT(cg), JSOP_GOSUB))
+ return JS_FALSE;
+
+ finallyStart = CG_OFFSET(cg);
+
+ /* Indicate that we're emitting a subroutine body. */
+ stmtInfo.type = STMT_SUBROUTINE;
+ if (!UpdateLineNumberNotes(cx, cg, pn->pn_kid3))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_FINALLY) < 0 ||
+ !js_EmitTree(cx, cg, pn->pn_kid3) ||
+ js_Emit1(cx, cg, JSOP_RETSUB) < 0) {
+ return JS_FALSE;
+ }
+ JS_ASSERT(cg->stackDepth == depth);
+ }
+ if (!js_PopStatementCG(cx, cg))
+ return JS_FALSE;
+
+ if (js_NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 ||
+ js_Emit1(cx, cg, JSOP_NOP) < 0) {
+ return JS_FALSE;
+ }
+
+ /* Fix up the end-of-try/catch jumps to come here. */
+ if (!BackPatch(cx, cg, catchJump, CG_NEXT(cg), JSOP_GOTO))
+ return JS_FALSE;
+
+ /*
+ * Add the try note last, to let post-order give us the right ordering
+ * (first to last for a given nesting level, inner to outer by level).
+ */
+ if (pn->pn_kid2 &&
+ !NewTryNote(cx, cg, JSTRY_CATCH, depth, tryStart, tryEnd)) {
+ return JS_FALSE;
+ }
+
+ /*
+ * If we've got a finally, mark try+catch region with additional
+ * trynote to catch exceptions (re)thrown from a catch block or
+ * for the try{}finally{} case.
+ */
+ if (pn->pn_kid3 &&
+ !NewTryNote(cx, cg, JSTRY_FINALLY, depth, tryStart, finallyStart)) {
+ return JS_FALSE;
+ }
+ break;
+ }
+
+ case TOK_CATCH:
+ {
+ ptrdiff_t catchStart, guardJump;
+ JSObject *blockObj;
+
+ /*
+ * Morph STMT_BLOCK to STMT_CATCH, note the block entry code offset,
+ * and save the block object atom.
+ */
+ stmt = cg->treeContext.topStmt;
+ JS_ASSERT(stmt->type == STMT_BLOCK && (stmt->flags & SIF_SCOPE));
+ stmt->type = STMT_CATCH;
+ catchStart = stmt->update;
+ blockObj = stmt->u.blockObj;
+
+ /* Go up one statement info record to the TRY or FINALLY record. */
+ stmt = stmt->down;
+ JS_ASSERT(stmt->type == STMT_TRY || stmt->type == STMT_FINALLY);
+
+ /* Pick up the pending exception and bind it to the catch variable. */
+ if (js_Emit1(cx, cg, JSOP_EXCEPTION) < 0)
+ return JS_FALSE;
+
+ /*
+ * Dup the exception object if there is a guard for rethrowing to use
+ * it later when rethrowing or in other catches.
+ */
+ if (pn->pn_kid2 && js_Emit1(cx, cg, JSOP_DUP) < 0)
+ return JS_FALSE;
+
+ pn2 = pn->pn_kid1;
+ switch (pn2->pn_type) {
+#if JS_HAS_DESTRUCTURING
+ case TOK_RB:
+ case TOK_RC:
+ if (!EmitDestructuringOps(cx, cg, JSOP_NOP, pn2))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ break;
+#endif
+
+ case TOK_NAME:
+ /* Inline BindNameToSlot for pn2. */
+ JS_ASSERT(pn2->pn_slot == -1);
+ pn2->pn_slot = AdjustBlockSlot(cx, cg,
+ OBJ_BLOCK_DEPTH(cx, blockObj));
+ if (pn2->pn_slot < 0)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(JSOP_SETLOCALPOP, pn2->pn_slot);
+ break;
+
+ default:
+ JS_ASSERT(0);
+ }
+
+ /* Emit the guard expression, if there is one. */
+ if (pn->pn_kid2) {
+ if (!js_EmitTree(cx, cg, pn->pn_kid2))
+ return JS_FALSE;
+ if (!js_SetSrcNoteOffset(cx, cg, CATCHNOTE(*stmt), 0,
+ CG_OFFSET(cg) - catchStart)) {
+ return JS_FALSE;
+ }
+ /* ifeq <next block> */
+ guardJump = EmitJump(cx, cg, JSOP_IFEQ, 0);
+ if (guardJump < 0)
+ return JS_FALSE;
+ GUARDJUMP(*stmt) = guardJump;
+
+ /* Pop duplicated exception object as we no longer need it. */
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ }
+
+ /* Emit the catch body. */
+ if (!js_EmitTree(cx, cg, pn->pn_kid3))
+ return JS_FALSE;
+
+ /*
+ * Annotate the JSOP_LEAVEBLOCK that will be emitted as we unwind via
+ * our TOK_LEXICALSCOPE parent, so the decompiler knows to pop.
+ */
+ off = cg->stackDepth;
+ if (js_NewSrcNote2(cx, cg, SRC_CATCH, off) < 0)
+ return JS_FALSE;
+ break;
+ }
+
+ case TOK_VAR:
+ if (!EmitVariables(cx, cg, pn, JS_FALSE, &noteIndex))
+ return JS_FALSE;
+ break;
+
+ case TOK_RETURN:
+ /* Push a return value */
+ pn2 = pn->pn_kid;
+ if (pn2) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ } else {
+ if (js_Emit1(cx, cg, JSOP_PUSH) < 0)
+ return JS_FALSE;
+ }
+
+ /*
+ * EmitNonLocalJumpFixup may add fixup bytecode to close open try
+ * blocks having finally clauses and to exit intermingled let blocks.
+ * We can't simply transfer control flow to our caller in that case,
+ * because we must gosub to those finally clauses from inner to outer,
+ * with the correct stack pointer (i.e., after popping any with,
+ * for/in, etc., slots nested inside the finally's try).
+ *
+ * In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
+ * extra JSOP_RETRVAL after the fixups.
+ */
+ top = CG_OFFSET(cg);
+ if (js_Emit1(cx, cg, JSOP_RETURN) < 0)
+ return JS_FALSE;
+ if (!EmitNonLocalJumpFixup(cx, cg, NULL))
+ return JS_FALSE;
+ if (top + JSOP_RETURN_LENGTH != CG_OFFSET(cg)) {
+ CG_BASE(cg)[top] = JSOP_SETRVAL;
+ if (js_Emit1(cx, cg, JSOP_RETRVAL) < 0)
+ return JS_FALSE;
+ }
+ break;
+
+#if JS_HAS_GENERATORS
+ case TOK_YIELD:
+ if (!(cg->treeContext.flags & TCF_IN_FUNCTION)) {
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), pn, JSREPORT_ERROR,
+ JSMSG_BAD_RETURN_OR_YIELD,
+ js_yield_str);
+ return JS_FALSE;
+ }
+ if (pn->pn_kid) {
+ if (!js_EmitTree(cx, cg, pn->pn_kid))
+ return JS_FALSE;
+ } else {
+ if (js_Emit1(cx, cg, JSOP_PUSH) < 0)
+ return JS_FALSE;
+ }
+ if (pn->pn_hidden && js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_YIELD) < 0)
+ return JS_FALSE;
+ break;
+#endif
+
+ case TOK_LC:
+#if JS_HAS_XML_SUPPORT
+ if (pn->pn_arity == PN_UNARY) {
+ if (!js_EmitTree(cx, cg, pn->pn_kid))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, PN_OP(pn)) < 0)
+ return JS_FALSE;
+ break;
+ }
+#endif
+
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+
+ noteIndex = -1;
+ tmp = CG_OFFSET(cg);
+ if (pn->pn_extra & PNX_NEEDBRACES) {
+ noteIndex = js_NewSrcNote2(cx, cg, SRC_BRACE, 0);
+ if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_NOP) < 0)
+ return JS_FALSE;
+ }
+
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_BLOCK, top);
+ if (pn->pn_extra & PNX_FUNCDEFS) {
+ /*
+ * This block contains top-level function definitions. To ensure
+ * that we emit the bytecode defining them prior the rest of code
+ * in the block we use a separate pass over functions. During the
+ * main pass later the emitter will add JSOP_NOP with source notes
+ * for the function to preserve the original functions position
+ * when decompiling.
+ *
+ * Currently this is used only for functions, as compile-as-we go
+ * mode for scripts does not allow separate emitter passes.
+ */
+ JS_ASSERT(cg->treeContext.flags & TCF_IN_FUNCTION);
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (pn2->pn_type == TOK_FUNCTION) {
+ if (pn2->pn_op == JSOP_NOP) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ } else {
+ /*
+ * JSOP_DEFFUN in a top-level block with function
+ * definitions appears, for example, when "if (true)"
+ * is optimized away from "if (true) function x() {}".
+ * See bug 428424.
+ */
+ JS_ASSERT(pn2->pn_op == JSOP_DEFFUN);
+ }
+ }
+ }
+ }
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ }
+
+ if (noteIndex >= 0 &&
+ !js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0,
+ CG_OFFSET(cg) - tmp)) {
+ return JS_FALSE;
+ }
+
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_SEQ:
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_SEQ, top);
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ }
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_SEMI:
+ pn2 = pn->pn_kid;
+ if (pn2) {
+ /*
+ * Top-level or called-from-a-native JS_Execute/EvaluateScript,
+ * debugger, and eval frames may need the value of the ultimate
+ * expression statement as the script's result, despite the fact
+ * that it appears useless to the compiler.
+ *
+ * API users may also set the JSOPTION_NO_SCRIPT_RVAL option when
+ * calling JS_Compile* to suppress JSOP_POPV.
+ */
+ useful = wantval =
+ !(cg->treeContext.flags & (TCF_IN_FUNCTION | TCF_NO_SCRIPT_RVAL));
+ if (!useful) {
+ if (!CheckSideEffects(cx, cg, pn2, &useful))
+ return JS_FALSE;
+ }
+
+ /*
+ * Don't eliminate apparently useless expressions if they are
+ * labeled expression statements. The tc->topStmt->update test
+ * catches the case where we are nesting in js_EmitTree for a
+ * labeled compound statement.
+ */
+ if (!useful &&
+ (!cg->treeContext.topStmt ||
+ cg->treeContext.topStmt->type != STMT_LABEL ||
+ cg->treeContext.topStmt->update < CG_OFFSET(cg))) {
+ CG_CURRENT_LINE(cg) = pn2->pn_pos.begin.lineno;
+ if (!js_ReportCompileErrorNumber(cx, CG_TS(cg), pn2,
+ JSREPORT_WARNING |
+ JSREPORT_STRICT,
+ JSMSG_USELESS_EXPR)) {
+ return JS_FALSE;
+ }
+ } else {
+ op = wantval ? JSOP_POPV : JSOP_POP;
+#if JS_HAS_DESTRUCTURING
+ if (!wantval &&
+ pn2->pn_type == TOK_ASSIGN &&
+ !MaybeEmitGroupAssignment(cx, cg, op, pn2, &op)) {
+ return JS_FALSE;
+ }
+#endif
+ if (op != JSOP_NOP) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ }
+ }
+ }
+ break;
+
+ case TOK_COLON:
+ /* Emit an annotated nop so we know to decompile a label. */
+ atom = pn->pn_atom;
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ pn2 = pn->pn_expr;
+ noteType = (pn2->pn_type == TOK_LC ||
+ (pn2->pn_type == TOK_LEXICALSCOPE &&
+ pn2->pn_expr->pn_type == TOK_LC))
+ ? SRC_LABELBRACE
+ : SRC_LABEL;
+ noteIndex = js_NewSrcNote2(cx, cg, noteType,
+ (ptrdiff_t) ALE_INDEX(ale));
+ if (noteIndex < 0 ||
+ js_Emit1(cx, cg, JSOP_NOP) < 0) {
+ return JS_FALSE;
+ }
+
+ /* Emit code for the labeled statement. */
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_LABEL,
+ CG_OFFSET(cg));
+ stmtInfo.u.label = atom;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (!js_PopStatementCG(cx, cg))
+ return JS_FALSE;
+
+ /* If the statement was compound, emit a note for the end brace. */
+ if (noteType == SRC_LABELBRACE) {
+ if (js_NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 ||
+ js_Emit1(cx, cg, JSOP_NOP) < 0) {
+ return JS_FALSE;
+ }
+ }
+ break;
+
+ case TOK_COMMA:
+ /*
+ * Emit SRC_PCDELTA notes on each JSOP_POP between comma operands.
+ * These notes help the decompiler bracket the bytecodes generated
+ * from each sub-expression that follows a comma.
+ */
+ off = noteIndex = -1;
+ for (pn2 = pn->pn_head; ; pn2 = pn2->pn_next) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ tmp = CG_OFFSET(cg);
+ if (noteIndex >= 0) {
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off))
+ return JS_FALSE;
+ }
+ if (!pn2->pn_next)
+ break;
+ off = tmp;
+ noteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0);
+ if (noteIndex < 0 ||
+ js_Emit1(cx, cg, JSOP_POP) < 0) {
+ return JS_FALSE;
+ }
+ }
+ break;
+
+ case TOK_ASSIGN:
+ /*
+ * Check left operand type and generate specialized code for it.
+ * Specialize to avoid ECMA "reference type" values on the operand
+ * stack, which impose pervasive runtime "GetValue" costs.
+ */
+ pn2 = pn->pn_left;
+ JS_ASSERT(pn2->pn_type != TOK_RP);
+ atomIndex = (jsatomid) -1; /* quell GCC overwarning */
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ if (pn2->pn_slot >= 0) {
+ atomIndex = (jsatomid) pn2->pn_slot;
+ } else {
+ ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ atomIndex = ALE_INDEX(ale);
+ EMIT_INDEX_OP(JSOP_BINDNAME, atomIndex);
+ }
+ break;
+ case TOK_DOT:
+ if (!js_EmitTree(cx, cg, pn2->pn_expr))
+ return JS_FALSE;
+ ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ atomIndex = ALE_INDEX(ale);
+ break;
+ case TOK_LB:
+ JS_ASSERT(pn2->pn_arity == PN_BINARY);
+ if (!js_EmitTree(cx, cg, pn2->pn_left))
+ return JS_FALSE;
+ if (!js_EmitTree(cx, cg, pn2->pn_right))
+ return JS_FALSE;
+ break;
+#if JS_HAS_DESTRUCTURING
+ case TOK_RB:
+ case TOK_RC:
+ break;
+#endif
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ break;
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ JS_ASSERT(pn2->pn_op == JSOP_SETXMLNAME);
+ if (!js_EmitTree(cx, cg, pn2->pn_kid))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_BINDXMLNAME) < 0)
+ return JS_FALSE;
+ break;
+#endif
+ default:
+ JS_ASSERT(0);
+ }
+
+ op = PN_OP(pn);
+#if JS_HAS_GETTER_SETTER
+ if (op == JSOP_GETTER || op == JSOP_SETTER) {
+ if (pn2->pn_type == TOK_NAME && PN_OP(pn2) != JSOP_SETNAME) {
+ /*
+ * x getter = y where x is a local or let variable is not
+ * supported.
+ */
+ js_ReportCompileErrorNumber(cx,
+ TS(cg->treeContext.parseContext),
+ pn2, JSREPORT_ERROR,
+ JSMSG_BAD_GETTER_OR_SETTER,
+ (op == JSOP_GETTER)
+ ? js_getter_str
+ : js_setter_str);
+ return JS_FALSE;
+ }
+
+ /* We'll emit these prefix bytecodes after emitting the r.h.s. */
+ } else
+#endif
+ /* If += or similar, dup the left operand and get its value. */
+ if (op != JSOP_NOP) {
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ if (pn2->pn_op != JSOP_SETNAME) {
+ EMIT_UINT16_IMM_OP((pn2->pn_op == JSOP_SETGVAR)
+ ? JSOP_GETGVAR
+ : (pn2->pn_op == JSOP_SETARG)
+ ? JSOP_GETARG
+ : JSOP_GETLOCAL,
+ atomIndex);
+ break;
+ }
+ if (js_Emit1(cx, cg, JSOP_DUP) < 0)
+ return JS_FALSE;
+ EMIT_INDEX_OP(JSOP_GETXPROP, atomIndex);
+ break;
+ case TOK_DOT:
+ if (js_Emit1(cx, cg, JSOP_DUP) < 0)
+ return JS_FALSE;
+ if (pn2->pn_atom == cx->runtime->atomState.lengthAtom) {
+ if (js_Emit1(cx, cg, JSOP_LENGTH) < 0)
+ return JS_FALSE;
+ } else {
+ EMIT_INDEX_OP(JSOP_GETPROP, atomIndex);
+ }
+ break;
+ case TOK_LB:
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+#endif
+ if (js_Emit1(cx, cg, JSOP_DUP2) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_GETELEM) < 0)
+ return JS_FALSE;
+ break;
+ default:;
+ }
+ }
+
+ /* Now emit the right operand (it may affect the namespace). */
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+
+ /* If += etc., emit the binary operator with a decompiler note. */
+ if (op != JSOP_NOP) {
+ /*
+ * Take care to avoid SRC_ASSIGNOP if the left-hand side is a
+ * const declared in a function (i.e., with non-negative pn_slot
+ * and when pn_const is true), as in this case (just a bit further
+ * below) we will avoid emitting the assignment op.
+ */
+ if (pn2->pn_type != TOK_NAME ||
+ pn2->pn_slot < 0 ||
+ !pn2->pn_const) {
+ if (js_NewSrcNote(cx, cg, SRC_ASSIGNOP) < 0)
+ return JS_FALSE;
+ }
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ }
+
+ /* Left parts such as a.b.c and a[b].c need a decompiler note. */
+ if (pn2->pn_type != TOK_NAME &&
+#if JS_HAS_DESTRUCTURING
+ pn2->pn_type != TOK_RB &&
+ pn2->pn_type != TOK_RC &&
+#endif
+ js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) {
+ return JS_FALSE;
+ }
+
+ /* Finally, emit the specialized assignment bytecode. */
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ if (pn2->pn_slot >= 0) {
+ if (!pn2->pn_const)
+ EMIT_UINT16_IMM_OP(PN_OP(pn2), atomIndex);
+ break;
+ }
+ /* FALL THROUGH */
+ case TOK_DOT:
+ EMIT_INDEX_OP(PN_OP(pn2), atomIndex);
+ break;
+ case TOK_LB:
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+#endif
+ if (js_Emit1(cx, cg, JSOP_SETELEM) < 0)
+ return JS_FALSE;
+ break;
+#if JS_HAS_DESTRUCTURING
+ case TOK_RB:
+ case TOK_RC:
+ if (!EmitDestructuringOps(cx, cg, JSOP_SETNAME, pn2))
+ return JS_FALSE;
+ break;
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ if (js_Emit1(cx, cg, JSOP_SETXMLNAME) < 0)
+ return JS_FALSE;
+ break;
+#endif
+ default:
+ JS_ASSERT(0);
+ }
+ break;
+
+ case TOK_HOOK:
+ /* Emit the condition, then branch if false to the else part. */
+ if (!js_EmitTree(cx, cg, pn->pn_kid1))
+ return JS_FALSE;
+ noteIndex = js_NewSrcNote(cx, cg, SRC_COND);
+ if (noteIndex < 0)
+ return JS_FALSE;
+ beq = EmitJump(cx, cg, JSOP_IFEQ, 0);
+ if (beq < 0 || !js_EmitTree(cx, cg, pn->pn_kid2))
+ return JS_FALSE;
+
+ /* Jump around else, fixup the branch, emit else, fixup jump. */
+ jmp = EmitJump(cx, cg, JSOP_GOTO, 0);
+ if (jmp < 0)
+ return JS_FALSE;
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);
+
+ /*
+ * Because each branch pushes a single value, but our stack budgeting
+ * analysis ignores branches, we now have to adjust cg->stackDepth to
+ * ignore the value pushed by the first branch. Execution will follow
+ * only one path, so we must decrement cg->stackDepth.
+ *
+ * Failing to do this will foil code, such as the try/catch/finally
+ * exception handling code generator, that samples cg->stackDepth for
+ * use at runtime (JSOP_SETSP), or in let expression and block code
+ * generation, which must use the stack depth to compute local stack
+ * indexes correctly.
+ */
+ JS_ASSERT(cg->stackDepth > 0);
+ cg->stackDepth--;
+ if (!js_EmitTree(cx, cg, pn->pn_kid3))
+ return JS_FALSE;
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq))
+ return JS_FALSE;
+ break;
+
+ case TOK_OR:
+ case TOK_AND:
+ /*
+ * JSOP_OR converts the operand on the stack to boolean, and if true,
+ * leaves the original operand value on the stack and jumps; otherwise
+ * it pops and falls into the next bytecode, which evaluates the right
+ * operand. The jump goes around the right operand evaluation.
+ *
+ * JSOP_AND converts the operand on the stack to boolean, and if false,
+ * leaves the original operand value on the stack and jumps; otherwise
+ * it pops and falls into the right operand's bytecode.
+ */
+ if (pn->pn_arity == PN_BINARY) {
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+ top = EmitJump(cx, cg, JSOP_BACKPATCH_POP, 0);
+ if (top < 0)
+ return JS_FALSE;
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+ off = CG_OFFSET(cg);
+ pc = CG_CODE(cg, top);
+ CHECK_AND_SET_JUMP_OFFSET(cx, cg, pc, off - top);
+ *pc = pn->pn_op;
+ } else {
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ JS_ASSERT(pn->pn_head->pn_next->pn_next);
+
+ /* Left-associative operator chain: avoid too much recursion. */
+ pn2 = pn->pn_head;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ top = EmitJump(cx, cg, JSOP_BACKPATCH_POP, 0);
+ if (top < 0)
+ return JS_FALSE;
+
+ /* Emit nodes between the head and the tail. */
+ jmp = top;
+ while ((pn2 = pn2->pn_next)->pn_next) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ off = EmitJump(cx, cg, JSOP_BACKPATCH_POP, 0);
+ if (off < 0)
+ return JS_FALSE;
+ if (!SetBackPatchDelta(cx, cg, CG_CODE(cg, jmp), off - jmp))
+ return JS_FALSE;
+ jmp = off;
+
+ }
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+
+ pn2 = pn->pn_head;
+ off = CG_OFFSET(cg);
+ do {
+ pc = CG_CODE(cg, top);
+ tmp = GetJumpOffset(cg, pc);
+ CHECK_AND_SET_JUMP_OFFSET(cx, cg, pc, off - top);
+ *pc = pn->pn_op;
+ top += tmp;
+ } while ((pn2 = pn2->pn_next)->pn_next);
+ }
+ break;
+
+ case TOK_BITOR:
+ case TOK_BITXOR:
+ case TOK_BITAND:
+ case TOK_EQOP:
+ case TOK_RELOP:
+ case TOK_IN:
+ case TOK_INSTANCEOF:
+ case TOK_SHOP:
+ case TOK_PLUS:
+ case TOK_MINUS:
+ case TOK_STAR:
+ case TOK_DIVOP:
+ if (pn->pn_arity == PN_LIST) {
+ /* Left-associative operator chain: avoid too much recursion. */
+ pn2 = pn->pn_head;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ op = PN_OP(pn);
+ while ((pn2 = pn2->pn_next) != NULL) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ }
+ } else {
+#if JS_HAS_XML_SUPPORT
+ uintN oldflags;
+
+ case TOK_DBLCOLON:
+ if (pn->pn_arity == PN_NAME) {
+ if (!js_EmitTree(cx, cg, pn->pn_expr))
+ return JS_FALSE;
+ if (!EmitAtomOp(cx, pn, PN_OP(pn), cg))
+ return JS_FALSE;
+ break;
+ }
+
+ /*
+ * Binary :: has a right operand that brackets arbitrary code,
+ * possibly including a let (a = b) ... expression. We must clear
+ * TCF_IN_FOR_INIT to avoid mis-compiling such beasts.
+ */
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+#endif
+
+ /* Binary operators that evaluate both operands unconditionally. */
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+#if JS_HAS_XML_SUPPORT
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+#endif
+ if (js_Emit1(cx, cg, PN_OP(pn)) < 0)
+ return JS_FALSE;
+ }
+ break;
+
+ case TOK_THROW:
+#if JS_HAS_XML_SUPPORT
+ case TOK_AT:
+ case TOK_DEFAULT:
+ JS_ASSERT(pn->pn_arity == PN_UNARY);
+ /* FALL THROUGH */
+#endif
+ case TOK_UNARYOP:
+ {
+ uintN oldflags;
+
+ /* Unary op, including unary +/-. */
+ op = PN_OP(pn);
+#if JS_HAS_XML_SUPPORT
+ if (op == JSOP_XMLNAME) {
+ if (!EmitXMLName(cx, pn, op, cg))
+ return JS_FALSE;
+ break;
+ }
+#endif
+ pn2 = pn->pn_kid;
+ if (op == JSOP_TYPEOF) {
+ for (pn3 = pn2; pn3->pn_type == TOK_RP; pn3 = pn3->pn_kid)
+ continue;
+ if (pn3->pn_type != TOK_NAME)
+ op = JSOP_TYPEOFEXPR;
+ }
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ break;
+ }
+
+ case TOK_INC:
+ case TOK_DEC:
+ /* Emit lvalue-specialized code for ++/-- operators. */
+ pn2 = pn->pn_kid;
+ JS_ASSERT(pn2->pn_type != TOK_RP);
+ op = PN_OP(pn);
+ switch (pn2->pn_type) {
+ default:
+ JS_ASSERT(pn2->pn_type == TOK_NAME);
+ pn2->pn_op = op;
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ op = PN_OP(pn2);
+ if (pn2->pn_slot >= 0) {
+ if (pn2->pn_const) {
+ /* Incrementing a declared const: just get its value. */
+ op = (JOF_OPTYPE(op) == JOF_ATOM)
+ ? JSOP_GETGVAR
+ : JSOP_GETLOCAL;
+ }
+ atomIndex = (jsatomid) pn2->pn_slot;
+ EMIT_UINT16_IMM_OP(op, atomIndex);
+ } else {
+ if (!EmitAtomOp(cx, pn2, op, cg))
+ return JS_FALSE;
+ }
+ break;
+ case TOK_DOT:
+ if (!EmitPropOp(cx, pn2, op, cg, JS_FALSE))
+ return JS_FALSE;
+ break;
+ case TOK_LB:
+ if (!EmitElemOp(cx, pn2, op, cg))
+ return JS_FALSE;
+ break;
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE,
+ CG_OFFSET(cg) - pn2->pn_offset) < 0) {
+ return JS_FALSE;
+ }
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ break;
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ JS_ASSERT(pn2->pn_op == JSOP_SETXMLNAME);
+ if (!js_EmitTree(cx, cg, pn2->pn_kid))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_BINDXMLNAME) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ break;
+#endif
+ }
+ break;
+
+ case TOK_DELETE:
+ /*
+ * Under ECMA 3, deleting a non-reference returns true -- but alas we
+ * must evaluate the operand if it appears it might have side effects.
+ */
+ pn2 = pn->pn_kid;
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ pn2->pn_op = JSOP_DELNAME;
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ op = PN_OP(pn2);
+ if (op == JSOP_FALSE) {
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ } else {
+ if (!EmitAtomOp(cx, pn2, op, cg))
+ return JS_FALSE;
+ }
+ break;
+ case TOK_DOT:
+ if (!EmitPropOp(cx, pn2, JSOP_DELPROP, cg, JS_FALSE))
+ return JS_FALSE;
+ break;
+#if JS_HAS_XML_SUPPORT
+ case TOK_DBLDOT:
+ if (!EmitElemOp(cx, pn2, JSOP_DELDESC, cg))
+ return JS_FALSE;
+ break;
+#endif
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ top = CG_OFFSET(cg);
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_DELELEM) < 0)
+ return JS_FALSE;
+ break;
+#endif
+ case TOK_LB:
+ if (!EmitElemOp(cx, pn2, JSOP_DELELEM, cg))
+ return JS_FALSE;
+ break;
+ default:
+ /*
+ * If useless, just emit JSOP_TRUE; otherwise convert delete foo()
+ * to foo(), true (a comma expression, requiring SRC_PCDELTA).
+ */
+ useful = JS_FALSE;
+ if (!CheckSideEffects(cx, cg, pn2, &useful))
+ return JS_FALSE;
+ if (!useful) {
+ off = noteIndex = -1;
+ } else {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ off = CG_OFFSET(cg);
+ noteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0);
+ if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ }
+ if (js_Emit1(cx, cg, JSOP_TRUE) < 0)
+ return JS_FALSE;
+ if (noteIndex >= 0) {
+ tmp = CG_OFFSET(cg);
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off))
+ return JS_FALSE;
+ }
+ }
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_FILTER:
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+ jmp = js_Emit3(cx, cg, JSOP_FILTER, 0, 0);
+ if (jmp < 0)
+ return JS_FALSE;
+ top = CG_OFFSET(cg);
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
+ if (EmitJump(cx, cg, JSOP_ENDFILTER, top - CG_OFFSET(cg)) < 0)
+ return JS_FALSE;
+ break;
+#endif
+
+ case TOK_DOT:
+ /*
+ * Pop a stack operand, convert it to object, get a property named by
+ * this bytecode's immediate-indexed atom operand, and push its value
+ * (not a reference to it).
+ */
+ ok = EmitPropOp(cx, pn, PN_OP(pn), cg, JS_FALSE);
+ break;
+
+ case TOK_LB:
+#if JS_HAS_XML_SUPPORT
+ case TOK_DBLDOT:
+#endif
+ /*
+ * Pop two operands, convert the left one to object and the right one
+ * to property name (atom or tagged int), get the named property, and
+ * push its value. Set the "obj" register to the result of ToObject
+ * on the left operand.
+ */
+ ok = EmitElemOp(cx, pn, PN_OP(pn), cg);
+ break;
+
+ case TOK_NEW:
+ case TOK_LP:
+ {
+ uintN oldflags;
+
+ /*
+ * Emit function call or operator new (constructor call) code.
+ * First, emit code for the left operand to evaluate the callable or
+ * constructable object expression.
+ */
+ pn2 = pn->pn_head;
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ if (!EmitNameOp(cx, cg, pn2, JS_TRUE))
+ return JS_FALSE;
+ break;
+ case TOK_DOT:
+ if (!EmitPropOp(cx, pn2, PN_OP(pn2), cg, JS_TRUE))
+ return JS_FALSE;
+ break;
+ case TOK_LB:
+ JS_ASSERT(pn2->pn_op == JSOP_GETELEM);
+ if (!EmitElemOp(cx, pn2, JSOP_CALLELEM, cg))
+ return JS_FALSE;
+ break;
+ case TOK_UNARYOP:
+#if JS_HAS_XML_SUPPORT
+ if (pn2->pn_op == JSOP_XMLNAME) {
+ if (!EmitXMLName(cx, pn2, JSOP_CALLXMLNAME, cg))
+ return JS_FALSE;
+ break;
+ }
+#endif
+ /* FALL THROUGH */
+ default:
+ /*
+ * Push null as a placeholder for the global object, per ECMA-262
+ * 11.2.3 step 6. We use JSOP_NULLTHIS to distinguish this opcode
+ * from JSOP_NULL (see jstracer.cpp for one use-case).
+ */
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_NULLTHIS) < 0)
+ return JS_FALSE;
+ }
+
+ /* Remember start of callable-object bytecode for decompilation hint. */
+ off = top;
+
+ /*
+ * Emit code for each argument in order, then emit the JSOP_*CALL or
+ * JSOP_NEW bytecode with a two-byte immediate telling how many args
+ * were pushed on the operand stack.
+ */
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ for (pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ }
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - off) < 0)
+ return JS_FALSE;
+
+ argc = pn->pn_count - 1;
+ if (js_Emit3(cx, cg, PN_OP(pn), ARGC_HI(argc), ARGC_LO(argc)) < 0)
+ return JS_FALSE;
+ if (PN_OP(pn) == JSOP_EVAL)
+ EMIT_UINT16_IMM_OP(JSOP_LINENO, pn->pn_pos.begin.lineno);
+ break;
+ }
+
+ case TOK_LEXICALSCOPE:
+ {
+ JSParsedObjectBox *pob;
+ uintN count;
+
+ pob = pn->pn_pob;
+ js_PushBlockScope(&cg->treeContext, &stmtInfo, pob->object,
+ CG_OFFSET(cg));
+
+ /*
+ * If this lexical scope is not for a catch block, let block or let
+ * expression, or any kind of for loop (where the scope starts in the
+ * head after the first part if for (;;), else in the body if for-in);
+ * and if our container is top-level but not a function body, or else
+ * a block statement; then emit a SRC_BRACE note. All other container
+ * statements get braces by default from the decompiler.
+ */
+ noteIndex = -1;
+ type = PN_TYPE(pn->pn_expr);
+ if (type != TOK_CATCH && type != TOK_LET && type != TOK_FOR &&
+ (!(stmt = stmtInfo.down)
+ ? !(cg->treeContext.flags & TCF_IN_FUNCTION)
+ : stmt->type == STMT_BLOCK)) {
+#if defined DEBUG_brendanXXX || defined DEBUG_mrbkap
+ /* There must be no source note already output for the next op. */
+ JS_ASSERT(CG_NOTE_COUNT(cg) == 0 ||
+ CG_LAST_NOTE_OFFSET(cg) != CG_OFFSET(cg) ||
+ !GettableNoteForNextOp(cg));
+#endif
+ noteIndex = js_NewSrcNote2(cx, cg, SRC_BRACE, 0);
+ if (noteIndex < 0)
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(CG_OFFSET(cg) == top);
+ if (!EmitObjectOp(cx, pob, JSOP_ENTERBLOCK, cg))
+ return JS_FALSE;
+
+ if (!js_EmitTree(cx, cg, pn->pn_expr))
+ return JS_FALSE;
+
+ op = PN_OP(pn);
+ if (op == JSOP_LEAVEBLOCKEXPR) {
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0)
+ return JS_FALSE;
+ } else {
+ if (noteIndex >= 0 &&
+ !js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0,
+ CG_OFFSET(cg) - top)) {
+ return JS_FALSE;
+ }
+ }
+
+ /* Emit the JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR opcode. */
+ count = OBJ_BLOCK_COUNT(cx, pob->object);
+ EMIT_UINT16_IMM_OP(op, count);
+
+ ok = js_PopStatementCG(cx, cg);
+ break;
+ }
+
+#if JS_HAS_BLOCK_SCOPE
+ case TOK_LET:
+ /* Let statements have their variable declarations on the left. */
+ if (pn->pn_arity == PN_BINARY) {
+ pn2 = pn->pn_right;
+ pn = pn->pn_left;
+ } else {
+ pn2 = NULL;
+ }
+
+ /* Non-null pn2 means that pn is the variable list from a let head. */
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ if (!EmitVariables(cx, cg, pn, pn2 != NULL, &noteIndex))
+ return JS_FALSE;
+
+ /* Thus non-null pn2 is the body of the let block or expression. */
+ tmp = CG_OFFSET(cg);
+ if (pn2 && !js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+
+ if (noteIndex >= 0 &&
+ !js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0,
+ CG_OFFSET(cg) - tmp)) {
+ return JS_FALSE;
+ }
+ break;
+#endif /* JS_HAS_BLOCK_SCOPE */
+
+#if JS_HAS_GENERATORS
+ case TOK_ARRAYPUSH: {
+ jsint slot;
+
+ /*
+ * The array object's stack index is in cg->arrayCompDepth. See below
+ * under the array initialiser code generator for array comprehension
+ * special casing.
+ */
+ if (!js_EmitTree(cx, cg, pn->pn_kid))
+ return JS_FALSE;
+ slot = cg->arrayCompDepth;
+ slot = AdjustBlockSlot(cx, cg, slot);
+ if (slot < 0)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(PN_OP(pn), slot);
+ break;
+ }
+#endif
+
+ case TOK_RB:
+#if JS_HAS_GENERATORS
+ case TOK_ARRAYCOMP:
+#endif
+ /*
+ * Emit code for [a, b, c] of the form:
+ *
+ * t = new Array; t[0] = a; t[1] = b; t[2] = c; t;
+ *
+ * but use a stack slot for t and avoid dup'ing and popping it using
+ * the JSOP_NEWINIT and JSOP_INITELEM bytecodes.
+ *
+ * If no sharp variable is defined and the initialiser is not for an
+ * array comprehension, use JSOP_NEWARRAY.
+ */
+ pn2 = pn->pn_head;
+ op = JSOP_NEWINIT; // FIXME: 260106 patch disabled for now
+
+#if JS_HAS_SHARP_VARS
+ if (pn2 && pn2->pn_type == TOK_DEFSHARP)
+ op = JSOP_NEWINIT;
+#endif
+#if JS_HAS_GENERATORS
+ if (pn->pn_type == TOK_ARRAYCOMP)
+ op = JSOP_NEWINIT;
+#endif
+
+ if (op == JSOP_NEWINIT &&
+ js_Emit2(cx, cg, op, (jsbytecode) JSProto_Array) < 0) {
+ return JS_FALSE;
+ }
+
+#if JS_HAS_SHARP_VARS
+ if (pn2 && pn2->pn_type == TOK_DEFSHARP) {
+ EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num);
+ pn2 = pn2->pn_next;
+ }
+#endif
+
+#if JS_HAS_GENERATORS
+ if (pn->pn_type == TOK_ARRAYCOMP) {
+ uintN saveDepth;
+
+ /*
+ * Pass the new array's stack index to the TOK_ARRAYPUSH case by
+ * storing it in pn->pn_extra, then simply traverse the TOK_FOR
+ * node and its kids under pn2 to generate this comprehension.
+ */
+ JS_ASSERT(cg->stackDepth > 0);
+ saveDepth = cg->arrayCompDepth;
+ cg->arrayCompDepth = (uint32) (cg->stackDepth - 1);
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ cg->arrayCompDepth = saveDepth;
+
+ /* Emit the usual op needed for decompilation. */
+ if (js_Emit1(cx, cg, JSOP_ENDINIT) < 0)
+ return JS_FALSE;
+ break;
+ }
+#endif /* JS_HAS_GENERATORS */
+
+ for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) {
+ if (op == JSOP_NEWINIT && !EmitNumberOp(cx, atomIndex, cg))
+ return JS_FALSE;
+
+ if (pn2->pn_type == TOK_COMMA) {
+ if (js_Emit1(cx, cg, JSOP_HOLE) < 0)
+ return JS_FALSE;
+ } else {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ }
+
+ if (op == JSOP_NEWINIT && js_Emit1(cx, cg, JSOP_INITELEM) < 0)
+ return JS_FALSE;
+ }
+
+ if (pn->pn_extra & PNX_ENDCOMMA) {
+ /* Emit a source note so we know to decompile an extra comma. */
+ if (js_NewSrcNote(cx, cg, SRC_CONTINUE) < 0)
+ return JS_FALSE;
+ }
+
+ if (op == JSOP_NEWARRAY) {
+ JS_ASSERT(atomIndex == pn->pn_count);
+ off = js_EmitN(cx, cg, op, 3);
+ if (off < 0)
+ return JS_FALSE;
+ pc = CG_CODE(cg, off);
+ SET_UINT24(pc, atomIndex);
+ UpdateDepth(cx, cg, off);
+ } else {
+ /* Emit an op for sharp array cleanup and decompilation. */
+ if (js_Emit1(cx, cg, JSOP_ENDINIT) < 0)
+ return JS_FALSE;
+ }
+ break;
+
+ case TOK_RC:
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ if (pn->pn_extra & PNX_SHORTHAND) {
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), pn, JSREPORT_ERROR,
+ JSMSG_BAD_OBJECT_INIT);
+ return JS_FALSE;
+ }
+#endif
+ /*
+ * Emit code for {p:a, '%q':b, 2:c} of the form:
+ *
+ * t = new Object; t.p = a; t['%q'] = b; t[2] = c; t;
+ *
+ * but use a stack slot for t and avoid dup'ing and popping it via
+ * the JSOP_NEWINIT and JSOP_INITELEM/JSOP_INITPROP bytecodes.
+ */
+ if (js_Emit2(cx, cg, JSOP_NEWINIT, (jsbytecode) JSProto_Object) < 0)
+ return JS_FALSE;
+
+ pn2 = pn->pn_head;
+#if JS_HAS_SHARP_VARS
+ if (pn2 && pn2->pn_type == TOK_DEFSHARP) {
+ EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num);
+ pn2 = pn2->pn_next;
+ }
+#endif
+
+ for (; pn2; pn2 = pn2->pn_next) {
+ /* Emit an index for t[2], else map an atom for t.p or t['%q']. */
+ pn3 = pn2->pn_left;
+ if (pn3->pn_type == TOK_NUMBER) {
+#ifdef __GNUC__
+ ale = NULL; /* quell GCC overwarning */
+#endif
+ if (!EmitNumberOp(cx, pn3->pn_dval, cg))
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(pn3->pn_type == TOK_NAME ||
+ pn3->pn_type == TOK_STRING);
+ ale = js_IndexAtom(cx, pn3->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ }
+
+ /* Emit code for the property initializer. */
+ if (!js_EmitTree(cx, cg, pn2->pn_right))
+ return JS_FALSE;
+
+#if JS_HAS_GETTER_SETTER
+ op = PN_OP(pn2);
+ if (op == JSOP_GETTER || op == JSOP_SETTER) {
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ }
+#endif
+ /* Annotate JSOP_INITELEM so we decompile 2:c and not just c. */
+ if (pn3->pn_type == TOK_NUMBER) {
+ if (js_NewSrcNote(cx, cg, SRC_INITPROP) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_INITELEM) < 0)
+ return JS_FALSE;
+ } else {
+ EMIT_INDEX_OP(JSOP_INITPROP, ALE_INDEX(ale));
+ }
+ }
+
+ /* Emit an op for sharpArray cleanup and decompilation. */
+ if (js_Emit1(cx, cg, JSOP_ENDINIT) < 0)
+ return JS_FALSE;
+ break;
+
+#if JS_HAS_SHARP_VARS
+ case TOK_DEFSHARP:
+ if (!js_EmitTree(cx, cg, pn->pn_kid))
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid) pn->pn_num);
+ break;
+
+ case TOK_USESHARP:
+ EMIT_UINT16_IMM_OP(JSOP_USESHARP, (jsatomid) pn->pn_num);
+ break;
+#endif /* JS_HAS_SHARP_VARS */
+
+ case TOK_RP:
+ {
+ uintN oldflags;
+
+ /*
+ * The node for (e) has e as its kid, enabling users who want to nest
+ * assignment expressions in conditions to avoid the error correction
+ * done by Condition (from x = y to x == y) by double-parenthesizing.
+ */
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ if (!js_EmitTree(cx, cg, pn->pn_kid))
+ return JS_FALSE;
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+ break;
+ }
+
+ case TOK_NAME:
+ if (!EmitNameOp(cx, cg, pn, JS_FALSE))
+ return JS_FALSE;
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_XMLATTR:
+ case TOK_XMLSPACE:
+ case TOK_XMLTEXT:
+ case TOK_XMLCDATA:
+ case TOK_XMLCOMMENT:
+#endif
+ case TOK_STRING:
+ ok = EmitAtomOp(cx, pn, PN_OP(pn), cg);
+ break;
+
+ case TOK_NUMBER:
+ ok = EmitNumberOp(cx, pn->pn_dval, cg);
+ break;
+
+ case TOK_REGEXP:
+ /*
+ * If the regexp's script is one-shot, we can avoid the extra
+ * fork-on-exec costs of JSOP_REGEXP by selecting JSOP_OBJECT.
+ * Otherwise, to avoid incorrect proto, parent, and lastIndex
+ * sharing among threads and sequentially across re-execution,
+ * select JSOP_REGEXP.
+ */
+ JS_ASSERT(pn->pn_op == JSOP_REGEXP);
+ if (cg->treeContext.flags & TCF_COMPILE_N_GO) {
+ ok = EmitObjectOp(cx, pn->pn_pob, JSOP_OBJECT, cg);
+ } else {
+ ok = EmitIndexOp(cx, JSOP_REGEXP,
+ IndexParsedObject(pn->pn_pob, &cg->regexpList),
+ cg);
+ }
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_ANYNAME:
+#endif
+ case TOK_PRIMARY:
+ if (js_Emit1(cx, cg, PN_OP(pn)) < 0)
+ return JS_FALSE;
+ break;
+
+#if JS_HAS_DEBUGGER_KEYWORD
+ case TOK_DEBUGGER:
+ if (js_Emit1(cx, cg, JSOP_DEBUGGER) < 0)
+ return JS_FALSE;
+ break;
+#endif /* JS_HAS_DEBUGGER_KEYWORD */
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_XMLELEM:
+ case TOK_XMLLIST:
+ if (pn->pn_op == JSOP_XMLOBJECT) {
+ ok = EmitObjectOp(cx, pn->pn_pob, PN_OP(pn), cg);
+ break;
+ }
+
+ JS_ASSERT(pn->pn_type == TOK_XMLLIST || pn->pn_count != 0);
+ switch (pn->pn_head ? pn->pn_head->pn_type : TOK_XMLLIST) {
+ case TOK_XMLETAGO:
+ JS_ASSERT(0);
+ /* FALL THROUGH */
+ case TOK_XMLPTAGC:
+ case TOK_XMLSTAGO:
+ break;
+ default:
+ if (js_Emit1(cx, cg, JSOP_STARTXML) < 0)
+ return JS_FALSE;
+ }
+
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (pn2->pn_type == TOK_LC &&
+ js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) {
+ return JS_FALSE;
+ }
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (pn2 != pn->pn_head && js_Emit1(cx, cg, JSOP_ADD) < 0)
+ return JS_FALSE;
+ }
+
+ if (pn->pn_extra & PNX_XMLROOT) {
+ if (pn->pn_count == 0) {
+ JS_ASSERT(pn->pn_type == TOK_XMLLIST);
+ atom = cx->runtime->atomState.emptyAtom;
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ EMIT_INDEX_OP(JSOP_STRING, ALE_INDEX(ale));
+ }
+ if (js_Emit1(cx, cg, PN_OP(pn)) < 0)
+ return JS_FALSE;
+ }
+#ifdef DEBUG
+ else
+ JS_ASSERT(pn->pn_count != 0);
+#endif
+ break;
+
+ case TOK_XMLPTAGC:
+ if (pn->pn_op == JSOP_XMLOBJECT) {
+ ok = EmitObjectOp(cx, pn->pn_pob, PN_OP(pn), cg);
+ break;
+ }
+ /* FALL THROUGH */
+
+ case TOK_XMLSTAGO:
+ case TOK_XMLETAGO:
+ {
+ uint32 i;
+
+ if (js_Emit1(cx, cg, JSOP_STARTXML) < 0)
+ return JS_FALSE;
+
+ ale = js_IndexAtom(cx,
+ (pn->pn_type == TOK_XMLETAGO)
+ ? cx->runtime->atomState.etagoAtom
+ : cx->runtime->atomState.stagoAtom,
+ &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ EMIT_INDEX_OP(JSOP_STRING, ALE_INDEX(ale));
+
+ JS_ASSERT(pn->pn_count != 0);
+ pn2 = pn->pn_head;
+ if (pn2->pn_type == TOK_LC && js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0)
+ return JS_FALSE;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_ADD) < 0)
+ return JS_FALSE;
+
+ for (pn2 = pn2->pn_next, i = 0; pn2; pn2 = pn2->pn_next, i++) {
+ if (pn2->pn_type == TOK_LC &&
+ js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) {
+ return JS_FALSE;
+ }
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if ((i & 1) && pn2->pn_type == TOK_LC) {
+ if (js_Emit1(cx, cg, JSOP_TOATTRVAL) < 0)
+ return JS_FALSE;
+ }
+ if (js_Emit1(cx, cg,
+ (i & 1) ? JSOP_ADDATTRVAL : JSOP_ADDATTRNAME) < 0) {
+ return JS_FALSE;
+ }
+ }
+
+ ale = js_IndexAtom(cx,
+ (pn->pn_type == TOK_XMLPTAGC)
+ ? cx->runtime->atomState.ptagcAtom
+ : cx->runtime->atomState.tagcAtom,
+ &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ EMIT_INDEX_OP(JSOP_STRING, ALE_INDEX(ale));
+ if (js_Emit1(cx, cg, JSOP_ADD) < 0)
+ return JS_FALSE;
+
+ if ((pn->pn_extra & PNX_XMLROOT) && js_Emit1(cx, cg, PN_OP(pn)) < 0)
+ return JS_FALSE;
+ break;
+ }
+
+ case TOK_XMLNAME:
+ if (pn->pn_arity == PN_LIST) {
+ JS_ASSERT(pn->pn_count != 0);
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (pn2 != pn->pn_head && js_Emit1(cx, cg, JSOP_ADD) < 0)
+ return JS_FALSE;
+ }
+ } else {
+ JS_ASSERT(pn->pn_arity == PN_NULLARY);
+ ok = (pn->pn_op == JSOP_OBJECT)
+ ? EmitObjectOp(cx, pn->pn_pob, PN_OP(pn), cg)
+ : EmitAtomOp(cx, pn, PN_OP(pn), cg);
+ }
+ break;
+
+ case TOK_XMLPI:
+ ale = js_IndexAtom(cx, pn->pn_atom2, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ if (!EmitIndexOp(cx, JSOP_QNAMEPART, ALE_INDEX(ale), cg))
+ return JS_FALSE;
+ if (!EmitAtomOp(cx, pn, JSOP_XMLPI, cg))
+ return JS_FALSE;
+ break;
+#endif /* JS_HAS_XML_SUPPORT */
+
+ default:
+ JS_ASSERT(0);
+ }
+
+ if (ok && --cg->emitLevel == 0 && cg->spanDeps)
+ ok = OptimizeSpanDeps(cx, cg);
+
+ return ok;
+}
+
+/*
+ * We should try to get rid of offsetBias (always 0 or 1, where 1 is
+ * JSOP_{NOP,POP}_LENGTH), which is used only by SRC_FOR and SRC_DECL.
+ */
+JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[] = {
+ {"null", 0, 0, 0},
+ {"if", 0, 0, 0},
+ {"if-else", 2, 0, 1},
+ {"for", 3, 1, 1},
+ {"while", 1, 0, 1},
+ {"continue", 0, 0, 0},
+ {"decl", 1, 1, 1},
+ {"pcdelta", 1, 0, 1},
+ {"assignop", 0, 0, 0},
+ {"cond", 1, 0, 1},
+ {"brace", 1, 0, 1},
+ {"hidden", 0, 0, 0},
+ {"pcbase", 1, 0, -1},
+ {"label", 1, 0, 0},
+ {"labelbrace", 1, 0, 0},
+ {"endbrace", 0, 0, 0},
+ {"break2label", 1, 0, 0},
+ {"cont2label", 1, 0, 0},
+ {"switch", 2, 0, 1},
+ {"funcdef", 1, 0, 0},
+ {"catch", 1, 0, 1},
+ {"extended", -1, 0, 0},
+ {"newline", 0, 0, 0},
+ {"setline", 1, 0, 0},
+ {"xdelta", 0, 0, 0},
+};
+
+static intN
+AllocSrcNote(JSContext *cx, JSCodeGenerator *cg)
+{
+ intN index;
+ JSArenaPool *pool;
+ size_t size;
+
+ index = CG_NOTE_COUNT(cg);
+ if (((uintN)index & CG_NOTE_MASK(cg)) == 0) {
+ pool = cg->notePool;
+ size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1);
+ if (!CG_NOTES(cg)) {
+ /* Allocate the first note array lazily; leave noteMask alone. */
+ JS_ARENA_ALLOCATE_CAST(CG_NOTES(cg), jssrcnote *, pool, size);
+ } else {
+ /* Grow by doubling note array size; update noteMask on success. */
+ JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size);
+ if (CG_NOTES(cg))
+ CG_NOTE_MASK(cg) = (CG_NOTE_MASK(cg) << 1) | 1;
+ }
+ if (!CG_NOTES(cg)) {
+ js_ReportOutOfScriptQuota(cx);
+ return -1;
+ }
+ }
+
+ CG_NOTE_COUNT(cg) = index + 1;
+ return index;
+}
+
+intN
+js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type)
+{
+ intN index, n;
+ jssrcnote *sn;
+ ptrdiff_t offset, delta, xdelta;
+
+ /*
+ * Claim a note slot in CG_NOTES(cg) by growing it if necessary and then
+ * incrementing CG_NOTE_COUNT(cg).
+ */
+ index = AllocSrcNote(cx, cg);
+ if (index < 0)
+ return -1;
+ sn = &CG_NOTES(cg)[index];
+
+ /*
+ * Compute delta from the last annotated bytecode's offset. If it's too
+ * big to fit in sn, allocate one or more xdelta notes and reset sn.
+ */
+ offset = CG_OFFSET(cg);
+ delta = offset - CG_LAST_NOTE_OFFSET(cg);
+ CG_LAST_NOTE_OFFSET(cg) = offset;
+ if (delta >= SN_DELTA_LIMIT) {
+ do {
+ xdelta = JS_MIN(delta, SN_XDELTA_MASK);
+ SN_MAKE_XDELTA(sn, xdelta);
+ delta -= xdelta;
+ index = AllocSrcNote(cx, cg);
+ if (index < 0)
+ return -1;
+ sn = &CG_NOTES(cg)[index];
+ } while (delta >= SN_DELTA_LIMIT);
+ }
+
+ /*
+ * Initialize type and delta, then allocate the minimum number of notes
+ * needed for type's arity. Usually, we won't need more, but if an offset
+ * does take two bytes, js_SetSrcNoteOffset will grow CG_NOTES(cg).
+ */
+ SN_MAKE_NOTE(sn, type, delta);
+ for (n = (intN)js_SrcNoteSpec[type].arity; n > 0; n--) {
+ if (js_NewSrcNote(cx, cg, SRC_NULL) < 0)
+ return -1;
+ }
+ return index;
+}
+
+intN
+js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
+ ptrdiff_t offset)
+{
+ intN index;
+
+ index = js_NewSrcNote(cx, cg, type);
+ if (index >= 0) {
+ if (!js_SetSrcNoteOffset(cx, cg, index, 0, offset))
+ return -1;
+ }
+ return index;
+}
+
+intN
+js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
+ ptrdiff_t offset1, ptrdiff_t offset2)
+{
+ intN index;
+
+ index = js_NewSrcNote(cx, cg, type);
+ if (index >= 0) {
+ if (!js_SetSrcNoteOffset(cx, cg, index, 0, offset1))
+ return -1;
+ if (!js_SetSrcNoteOffset(cx, cg, index, 1, offset2))
+ return -1;
+ }
+ return index;
+}
+
+static JSBool
+GrowSrcNotes(JSContext *cx, JSCodeGenerator *cg)
+{
+ JSArenaPool *pool;
+ size_t size;
+
+ /* Grow by doubling note array size; update noteMask on success. */
+ pool = cg->notePool;
+ size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1);
+ JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size);
+ if (!CG_NOTES(cg)) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ CG_NOTE_MASK(cg) = (CG_NOTE_MASK(cg) << 1) | 1;
+ return JS_TRUE;
+}
+
+jssrcnote *
+js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn,
+ ptrdiff_t delta)
+{
+ ptrdiff_t base, limit, newdelta, diff;
+ intN index;
+
+ /*
+ * Called only from OptimizeSpanDeps and js_FinishTakingSrcNotes to add to
+ * main script note deltas, and only by a small positive amount.
+ */
+ JS_ASSERT(cg->current == &cg->main);
+ JS_ASSERT((unsigned) delta < (unsigned) SN_XDELTA_LIMIT);
+
+ base = SN_DELTA(sn);
+ limit = SN_IS_XDELTA(sn) ? SN_XDELTA_LIMIT : SN_DELTA_LIMIT;
+ newdelta = base + delta;
+ if (newdelta < limit) {
+ SN_SET_DELTA(sn, newdelta);
+ } else {
+ index = sn - cg->main.notes;
+ if ((cg->main.noteCount & cg->main.noteMask) == 0) {
+ if (!GrowSrcNotes(cx, cg))
+ return NULL;
+ sn = cg->main.notes + index;
+ }
+ diff = cg->main.noteCount - index;
+ cg->main.noteCount++;
+ memmove(sn + 1, sn, SRCNOTE_SIZE(diff));
+ SN_MAKE_XDELTA(sn, delta);
+ sn++;
+ }
+ return sn;
+}
+
+JS_FRIEND_API(uintN)
+js_SrcNoteLength(jssrcnote *sn)
+{
+ uintN arity;
+ jssrcnote *base;
+
+ arity = (intN)js_SrcNoteSpec[SN_TYPE(sn)].arity;
+ for (base = sn++; arity; sn++, arity--) {
+ if (*sn & SN_3BYTE_OFFSET_FLAG)
+ sn += 2;
+ }
+ return sn - base;
+}
+
+JS_FRIEND_API(ptrdiff_t)
+js_GetSrcNoteOffset(jssrcnote *sn, uintN which)
+{
+ /* Find the offset numbered which (i.e., skip exactly which offsets). */
+ JS_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
+ JS_ASSERT((intN) which < js_SrcNoteSpec[SN_TYPE(sn)].arity);
+ for (sn++; which; sn++, which--) {
+ if (*sn & SN_3BYTE_OFFSET_FLAG)
+ sn += 2;
+ }
+ if (*sn & SN_3BYTE_OFFSET_FLAG) {
+ return (ptrdiff_t)(((uint32)(sn[0] & SN_3BYTE_OFFSET_MASK) << 16)
+ | (sn[1] << 8)
+ | sn[2]);
+ }
+ return (ptrdiff_t)*sn;
+}
+
+JSBool
+js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index,
+ uintN which, ptrdiff_t offset)
+{
+ jssrcnote *sn;
+ ptrdiff_t diff;
+
+ if ((jsuword)offset >= (jsuword)((ptrdiff_t)SN_3BYTE_OFFSET_FLAG << 16)) {
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+
+ /* Find the offset numbered which (i.e., skip exactly which offsets). */
+ sn = &CG_NOTES(cg)[index];
+ JS_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
+ JS_ASSERT((intN) which < js_SrcNoteSpec[SN_TYPE(sn)].arity);
+ for (sn++; which; sn++, which--) {
+ if (*sn & SN_3BYTE_OFFSET_FLAG)
+ sn += 2;
+ }
+
+ /* See if the new offset requires three bytes. */
+ if (offset > (ptrdiff_t)SN_3BYTE_OFFSET_MASK) {
+ /* Maybe this offset was already set to a three-byte value. */
+ if (!(*sn & SN_3BYTE_OFFSET_FLAG)) {
+ /* Losing, need to insert another two bytes for this offset. */
+ index = PTRDIFF(sn, CG_NOTES(cg), jssrcnote);
+
+ /*
+ * Simultaneously test to see if the source note array must grow to
+ * accomodate either the first or second byte of additional storage
+ * required by this 3-byte offset.
+ */
+ if (((CG_NOTE_COUNT(cg) + 1) & CG_NOTE_MASK(cg)) <= 1) {
+ if (!GrowSrcNotes(cx, cg))
+ return JS_FALSE;
+ sn = CG_NOTES(cg) + index;
+ }
+ CG_NOTE_COUNT(cg) += 2;
+
+ diff = CG_NOTE_COUNT(cg) - (index + 3);
+ JS_ASSERT(diff >= 0);
+ if (diff > 0)
+ memmove(sn + 3, sn + 1, SRCNOTE_SIZE(diff));
+ }
+ *sn++ = (jssrcnote)(SN_3BYTE_OFFSET_FLAG | (offset >> 16));
+ *sn++ = (jssrcnote)(offset >> 8);
+ }
+ *sn = (jssrcnote)offset;
+ return JS_TRUE;
+}
+
+#ifdef DEBUG_notme
+#define DEBUG_srcnotesize
+#endif
+
+#ifdef DEBUG_srcnotesize
+#define NBINS 10
+static uint32 hist[NBINS];
+
+void DumpSrcNoteSizeHist()
+{
+ static FILE *fp;
+ int i, n;
+
+ if (!fp) {
+ fp = fopen("/tmp/srcnotes.hist", "w");
+ if (!fp)
+ return;
+ setvbuf(fp, NULL, _IONBF, 0);
+ }
+ fprintf(fp, "SrcNote size histogram:\n");
+ for (i = 0; i < NBINS; i++) {
+ fprintf(fp, "%4u %4u ", JS_BIT(i), hist[i]);
+ for (n = (int) JS_HOWMANY(hist[i], 10); n > 0; --n)
+ fputc('*', fp);
+ fputc('\n', fp);
+ }
+ fputc('\n', fp);
+}
+#endif
+
+/*
+ * Fill in the storage at notes with prolog and main srcnotes; the space at
+ * notes was allocated using the CG_COUNT_FINAL_SRCNOTES macro from jsemit.h.
+ * SO DON'T CHANGE THIS FUNCTION WITHOUT AT LEAST CHECKING WHETHER jsemit.h's
+ * CG_COUNT_FINAL_SRCNOTES MACRO NEEDS CORRESPONDING CHANGES!
+ */
+JSBool
+js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes)
+{
+ uintN prologCount, mainCount, totalCount;
+ ptrdiff_t offset, delta;
+ jssrcnote *sn;
+
+ JS_ASSERT(cg->current == &cg->main);
+
+ prologCount = cg->prolog.noteCount;
+ if (prologCount && cg->prolog.currentLine != cg->firstLine) {
+ CG_SWITCH_TO_PROLOG(cg);
+ if (js_NewSrcNote2(cx, cg, SRC_SETLINE, (ptrdiff_t)cg->firstLine) < 0)
+ return JS_FALSE;
+ prologCount = cg->prolog.noteCount;
+ CG_SWITCH_TO_MAIN(cg);
+ } else {
+ /*
+ * Either no prolog srcnotes, or no line number change over prolog.
+ * We don't need a SRC_SETLINE, but we may need to adjust the offset
+ * of the first main note, by adding to its delta and possibly even
+ * prepending SRC_XDELTA notes to it to account for prolog bytecodes
+ * that came at and after the last annotated bytecode.
+ */
+ offset = CG_PROLOG_OFFSET(cg) - cg->prolog.lastNoteOffset;
+ JS_ASSERT(offset >= 0);
+ if (offset > 0 && cg->main.noteCount != 0) {
+ /* NB: Use as much of the first main note's delta as we can. */
+ sn = cg->main.notes;
+ delta = SN_IS_XDELTA(sn)
+ ? SN_XDELTA_MASK - (*sn & SN_XDELTA_MASK)
+ : SN_DELTA_MASK - (*sn & SN_DELTA_MASK);
+ if (offset < delta)
+ delta = offset;
+ for (;;) {
+ if (!js_AddToSrcNoteDelta(cx, cg, sn, delta))
+ return JS_FALSE;
+ offset -= delta;
+ if (offset == 0)
+ break;
+ delta = JS_MIN(offset, SN_XDELTA_MASK);
+ sn = cg->main.notes;
+ }
+ }
+ }
+
+ mainCount = cg->main.noteCount;
+ totalCount = prologCount + mainCount;
+ if (prologCount)
+ memcpy(notes, cg->prolog.notes, SRCNOTE_SIZE(prologCount));
+ memcpy(notes + prologCount, cg->main.notes, SRCNOTE_SIZE(mainCount));
+ SN_MAKE_TERMINATOR(&notes[totalCount]);
+
+#ifdef DEBUG_notme
+ { int bin = JS_CeilingLog2(totalCount);
+ if (bin >= NBINS)
+ bin = NBINS - 1;
+ ++hist[bin];
+ }
+#endif
+ return JS_TRUE;
+}
+
+static JSBool
+NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind,
+ uintN stackDepth, size_t start, size_t end)
+{
+ JSTryNode *tryNode;
+
+ JS_ASSERT((uintN)(uint16)stackDepth == stackDepth);
+ JS_ASSERT(start <= end);
+ JS_ASSERT((size_t)(uint32)start == start);
+ JS_ASSERT((size_t)(uint32)end == end);
+
+ JS_ARENA_ALLOCATE_TYPE(tryNode, JSTryNode, &cx->tempPool);
+ if (!tryNode) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+
+ tryNode->note.kind = kind;
+ tryNode->note.stackDepth = (uint16)stackDepth;
+ tryNode->note.start = (uint32)start;
+ tryNode->note.length = (uint32)(end - start);
+ tryNode->prev = cg->lastTryNode;
+ cg->lastTryNode = tryNode;
+ cg->ntrynotes++;
+ return JS_TRUE;
+}
+
+void
+js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array)
+{
+ JSTryNode *tryNode;
+ JSTryNote *tn;
+
+ JS_ASSERT(array->length > 0 && array->length == cg->ntrynotes);
+ tn = array->vector + array->length;
+ tryNode = cg->lastTryNode;
+ do {
+ *--tn = tryNode->note;
+ } while ((tryNode = tryNode->prev) != NULL);
+ JS_ASSERT(tn == array->vector);
+}
+
+/*
+ * Find the index of the given object for code generator.
+ *
+ * Since the emitter refers to each parsed object only once, for the index we
+ * use the number of already indexes objects. We also add the object to a list
+ * to convert the list to a fixed-size array when we complete code generation,
+ * see FinishParsedObjects bellow.
+ *
+ * Most of the objects go to JSCodeGenerator.objectList but for regexp we use
+ * a separated JSCodeGenerator.regexpList. In this way the emitted index can
+ * be directly used to store and fetch a reference to a cloned RegExp object
+ * that shares the same JSRegExp private data created for the object literal
+ * in pob. We need clones to hold lastIndex and other direct properties that
+ * should not be shared among threads sharing a precompiled function or
+ * script.
+ *
+ * If the code being compiled is function code, allocate a reserved slot in
+ * the cloned function object that shares its precompiled script with other
+ * cloned function objects and with the compiler-created clone-parent. There
+ * are nregexps = JS_SCRIPT_REGEXPS(script)->length such reserved slots in each
+ * function object cloned from fun->object. NB: during compilation, a funobj
+ * slots element must never be allocated, because js_AllocSlot could hand out
+ * one of the slots that should be given to a regexp clone.
+ *
+ * If the code being compiled is global code, the cloned regexp are stored in
+ * fp->vars slot after cg->treeContext.ngvars and to protect regexp slots from
+ * GC we set fp->nvars to ngvars + nregexps.
+ *
+ * The slots initially contain undefined or null. We populate them lazily when
+ * JSOP_REGEXP is executed for the first time.
+ *
+ * Why clone regexp objects? ECMA specifies that when a regular expression
+ * literal is scanned, a RegExp object is created. In the spec, compilation
+ * and execution happen indivisibly, but in this implementation and many of
+ * its embeddings, code is precompiled early and re-executed in multiple
+ * threads, or using multiple global objects, or both, for efficiency.
+ *
+ * In such cases, naively following ECMA leads to wrongful sharing of RegExp
+ * objects, which makes for collisions on the lastIndex property (especially
+ * for global regexps) and on any ad-hoc properties. Also, __proto__ and
+ * __parent__ refer to the pre-compilation prototype and global objects, a
+ * pigeon-hole problem for instanceof tests.
+ */
+static uintN
+IndexParsedObject(JSParsedObjectBox *pob, JSEmittedObjectList *list)
+{
+ JS_ASSERT(!pob->emitLink);
+ pob->emitLink = list->lastPob;
+ list->lastPob = pob;
+ return list->length++;
+}
+
+void
+FinishParsedObjects(JSEmittedObjectList *emittedList, JSObjectArray *array)
+{
+ JSObject **cursor;
+ JSParsedObjectBox *pob;
+
+ JS_ASSERT(emittedList->length <= INDEX_LIMIT);
+ JS_ASSERT(emittedList->length == array->length);
+
+ cursor = array->vector + array->length;
+ pob = emittedList->lastPob;
+ do {
+ --cursor;
+ JS_ASSERT(!*cursor);
+ *cursor = pob->object;
+ } while ((pob = pob->emitLink) != NULL);
+ JS_ASSERT(cursor == array->vector);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsemit.h b/tools/node_modules/expresso/deps/jscoverage/js/jsemit.h
new file mode 100644
index 0000000..4e39f6c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsemit.h
@@ -0,0 +1,777 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsemit_h___
+#define jsemit_h___
+/*
+ * JS bytecode generation.
+ */
+
+#include "jsstddef.h"
+#include "jstypes.h"
+#include "jsatom.h"
+#include "jsopcode.h"
+#include "jsscript.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * NB: If you add enumerators for scope statements, add them between STMT_WITH
+ * and STMT_CATCH, or you will break the STMT_TYPE_IS_SCOPE macro. If you add
+ * non-looping statement enumerators, add them before STMT_DO_LOOP or you will
+ * break the STMT_TYPE_IS_LOOP macro.
+ *
+ * Also remember to keep the statementName array in jsemit.c in sync.
+ */
+typedef enum JSStmtType {
+ STMT_LABEL, /* labeled statement: L: s */
+ STMT_IF, /* if (then) statement */
+ STMT_ELSE, /* else clause of if statement */
+ STMT_SEQ, /* synthetic sequence of statements */
+ STMT_BLOCK, /* compound statement: { s1[;... sN] } */
+ STMT_SWITCH, /* switch statement */
+ STMT_WITH, /* with statement */
+ STMT_CATCH, /* catch block */
+ STMT_TRY, /* try block */
+ STMT_FINALLY, /* finally block */
+ STMT_SUBROUTINE, /* gosub-target subroutine body */
+ STMT_DO_LOOP, /* do/while loop statement */
+ STMT_FOR_LOOP, /* for loop statement */
+ STMT_FOR_IN_LOOP, /* for/in loop statement */
+ STMT_WHILE_LOOP, /* while loop statement */
+ STMT_LIMIT
+} JSStmtType;
+
+#define STMT_TYPE_IN_RANGE(t,b,e) ((uint)((t) - (b)) <= (uintN)((e) - (b)))
+
+/*
+ * A comment on the encoding of the JSStmtType enum and type-testing macros:
+ *
+ * STMT_TYPE_MAYBE_SCOPE tells whether a statement type is always, or may
+ * become, a lexical scope. It therefore includes block and switch (the two
+ * low-numbered "maybe" scope types) and excludes with (with has dynamic scope
+ * pending the "reformed with" in ES4/JS2). It includes all try-catch-finally
+ * types, which are high-numbered maybe-scope types.
+ *
+ * STMT_TYPE_LINKS_SCOPE tells whether a JSStmtInfo of the given type eagerly
+ * links to other scoping statement info records. It excludes the two early
+ * "maybe" types, block and switch, as well as the try and both finally types,
+ * since try and the other trailing maybe-scope types don't need block scope
+ * unless they contain let declarations.
+ *
+ * We treat WITH as a static scope because it prevents lexical binding from
+ * continuing further up the static scope chain. With the lost "reformed with"
+ * proposal for ES4, we would be able to model it statically, too.
+ */
+#define STMT_TYPE_MAYBE_SCOPE(type) \
+ (type != STMT_WITH && \
+ STMT_TYPE_IN_RANGE(type, STMT_BLOCK, STMT_SUBROUTINE))
+
+#define STMT_TYPE_LINKS_SCOPE(type) \
+ STMT_TYPE_IN_RANGE(type, STMT_WITH, STMT_CATCH)
+
+#define STMT_TYPE_IS_TRYING(type) \
+ STMT_TYPE_IN_RANGE(type, STMT_TRY, STMT_SUBROUTINE)
+
+#define STMT_TYPE_IS_LOOP(type) ((type) >= STMT_DO_LOOP)
+
+#define STMT_MAYBE_SCOPE(stmt) STMT_TYPE_MAYBE_SCOPE((stmt)->type)
+#define STMT_LINKS_SCOPE(stmt) (STMT_TYPE_LINKS_SCOPE((stmt)->type) || \
+ ((stmt)->flags & SIF_SCOPE))
+#define STMT_IS_TRYING(stmt) STMT_TYPE_IS_TRYING((stmt)->type)
+#define STMT_IS_LOOP(stmt) STMT_TYPE_IS_LOOP((stmt)->type)
+
+typedef struct JSStmtInfo JSStmtInfo;
+
+struct JSStmtInfo {
+ uint16 type; /* statement type */
+ uint16 flags; /* flags, see below */
+ ptrdiff_t update; /* loop update offset (top if none) */
+ ptrdiff_t breaks; /* offset of last break in loop */
+ ptrdiff_t continues; /* offset of last continue in loop */
+ union {
+ JSAtom *label; /* name of LABEL */
+ JSObject *blockObj; /* block scope object */
+ } u;
+ JSStmtInfo *down; /* info for enclosing statement */
+ JSStmtInfo *downScope; /* next enclosing lexical scope */
+};
+
+#define SIF_SCOPE 0x0001 /* statement has its own lexical scope */
+#define SIF_BODY_BLOCK 0x0002 /* STMT_BLOCK type is a function body */
+#define SIF_FOR_BLOCK 0x0004 /* for (let ...) induced block scope */
+
+/*
+ * To reuse space in JSStmtInfo, rename breaks and continues for use during
+ * try/catch/finally code generation and backpatching. To match most common
+ * use cases, the macro argument is a struct, not a struct pointer. Only a
+ * loop, switch, or label statement info record can have breaks and continues,
+ * and only a for loop has an update backpatch chain, so it's safe to overlay
+ * these for the "trying" JSStmtTypes.
+ */
+#define CATCHNOTE(stmt) ((stmt).update)
+#define GOSUBS(stmt) ((stmt).breaks)
+#define GUARDJUMP(stmt) ((stmt).continues)
+
+#define AT_TOP_LEVEL(tc) \
+ (!(tc)->topStmt || ((tc)->topStmt->flags & SIF_BODY_BLOCK))
+
+#define SET_STATEMENT_TOP(stmt, top) \
+ ((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))
+
+struct JSTreeContext { /* tree context for semantic checks */
+ uint16 flags; /* statement state flags, see below */
+ uint16 ngvars; /* max. no. of global variables/regexps */
+ JSStmtInfo *topStmt; /* top of statement info stack */
+ JSStmtInfo *topScopeStmt; /* top lexical scope statement */
+ JSObject *blockChain; /* compile time block scope chain (NB: one
+ deeper than the topScopeStmt/downScope
+ chain when in head of let block/expr) */
+ JSParseNode *blockNode; /* parse node for a lexical scope.
+ XXX combine with blockChain? */
+ JSAtomList decls; /* function, const, and var declarations */
+ JSParseContext *parseContext;
+
+ union {
+
+ JSFunction *fun; /* function to store argument and variable
+ names when flags & TCF_IN_FUNCTION */
+ JSObject *scopeChain; /* scope chain object for the script */
+ } u;
+
+#ifdef JS_SCOPE_DEPTH_METER
+ uint16 scopeDepth; /* current lexical scope chain depth */
+ uint16 maxScopeDepth; /* maximum lexical scope chain depth */
+#endif
+};
+
+#define TCF_IN_FUNCTION 0x01 /* parsing inside function body */
+#define TCF_RETURN_EXPR 0x02 /* function has 'return expr;' */
+#define TCF_RETURN_VOID 0x04 /* function has 'return;' */
+#define TCF_IN_FOR_INIT 0x08 /* parsing init expr of for; exclude 'in' */
+#define TCF_FUN_CLOSURE_VS_VAR 0x10 /* function and var with same name */
+#define TCF_FUN_USES_NONLOCALS 0x20 /* function refers to non-local names */
+#define TCF_FUN_HEAVYWEIGHT 0x40 /* function needs Call object per call */
+#define TCF_FUN_IS_GENERATOR 0x80 /* parsed yield statement in function */
+#define TCF_HAS_DEFXMLNS 0x100 /* default xml namespace = ...; parsed */
+#define TCF_HAS_FUNCTION_STMT 0x200 /* block contains a function statement */
+#define TCF_GENEXP_LAMBDA 0x400 /* flag lambda from generator expression */
+#define TCF_COMPILE_N_GO 0x800 /* compiler-and-go mode of script, can
+ optimize name references based on scope
+ chain */
+#define TCF_NO_SCRIPT_RVAL 0x1000 /* API caller does not want result value
+ from global script */
+/*
+ * Flags to propagate out of the blocks.
+ */
+#define TCF_RETURN_FLAGS (TCF_RETURN_EXPR | TCF_RETURN_VOID)
+
+/*
+ * Flags to propagate from FunctionBody.
+ */
+#define TCF_FUN_FLAGS (TCF_FUN_IS_GENERATOR | \
+ TCF_FUN_HEAVYWEIGHT | \
+ TCF_FUN_USES_NONLOCALS | \
+ TCF_FUN_CLOSURE_VS_VAR)
+
+/*
+ * Flags field, not stored in JSTreeContext.flags, for passing staticDepth
+ * into js_CompileScript.
+ */
+#define TCF_STATIC_DEPTH_MASK 0xffff0000
+#define TCF_GET_STATIC_DEPTH(f) ((uint32)(f) >> 16)
+#define TCF_PUT_STATIC_DEPTH(d) ((uint16)(d) << 16)
+
+#ifdef JS_SCOPE_DEPTH_METER
+# define JS_SCOPE_DEPTH_METERING(code) ((void) (code))
+#else
+# define JS_SCOPE_DEPTH_METERING(code) ((void) 0)
+#endif
+
+#define TREE_CONTEXT_INIT(tc, pc) \
+ ((tc)->flags = (tc)->ngvars = 0, \
+ (tc)->topStmt = (tc)->topScopeStmt = NULL, \
+ (tc)->blockChain = NULL, \
+ ATOM_LIST_INIT(&(tc)->decls), \
+ (tc)->blockNode = NULL, \
+ (tc)->parseContext = (pc), \
+ (tc)->u.scopeChain = NULL, \
+ JS_SCOPE_DEPTH_METERING((tc)->scopeDepth = (tc)->maxScopeDepth = 0))
+
+/*
+ * For functions TREE_CONTEXT_FINISH is called the second time to finish the
+ * extra tc created during code generation. We skip stats update in such
+ * cases.
+ */
+#define TREE_CONTEXT_FINISH(cx, tc) \
+ JS_SCOPE_DEPTH_METERING( \
+ (tc)->maxScopeDepth == (uintN) -1 || \
+ JS_BASIC_STATS_ACCUM(&(cx)->runtime->lexicalScopeDepthStats, \
+ (tc)->maxScopeDepth))
+
+/*
+ * Span-dependent instructions are jumps whose span (from the jump bytecode to
+ * the jump target) may require 2 or 4 bytes of immediate operand.
+ */
+typedef struct JSSpanDep JSSpanDep;
+typedef struct JSJumpTarget JSJumpTarget;
+
+struct JSSpanDep {
+ ptrdiff_t top; /* offset of first bytecode in an opcode */
+ ptrdiff_t offset; /* offset - 1 within opcode of jump operand */
+ ptrdiff_t before; /* original offset - 1 of jump operand */
+ JSJumpTarget *target; /* tagged target pointer or backpatch delta */
+};
+
+/*
+ * Jump targets are stored in an AVL tree, for O(log(n)) lookup with targets
+ * sorted by offset from left to right, so that targets after a span-dependent
+ * instruction whose jump offset operand must be extended can be found quickly
+ * and adjusted upward (toward higher offsets).
+ */
+struct JSJumpTarget {
+ ptrdiff_t offset; /* offset of span-dependent jump target */
+ int balance; /* AVL tree balance number */
+ JSJumpTarget *kids[2]; /* left and right AVL tree child pointers */
+};
+
+#define JT_LEFT 0
+#define JT_RIGHT 1
+#define JT_OTHER_DIR(dir) (1 - (dir))
+#define JT_IMBALANCE(dir) (((dir) << 1) - 1)
+#define JT_DIR(imbalance) (((imbalance) + 1) >> 1)
+
+/*
+ * Backpatch deltas are encoded in JSSpanDep.target if JT_TAG_BIT is clear,
+ * so we can maintain backpatch chains when using span dependency records to
+ * hold jump offsets that overflow 16 bits.
+ */
+#define JT_TAG_BIT ((jsword) 1)
+#define JT_UNTAG_SHIFT 1
+#define JT_SET_TAG(jt) ((JSJumpTarget *)((jsword)(jt) | JT_TAG_BIT))
+#define JT_CLR_TAG(jt) ((JSJumpTarget *)((jsword)(jt) & ~JT_TAG_BIT))
+#define JT_HAS_TAG(jt) ((jsword)(jt) & JT_TAG_BIT)
+
+#define BITS_PER_PTRDIFF (sizeof(ptrdiff_t) * JS_BITS_PER_BYTE)
+#define BITS_PER_BPDELTA (BITS_PER_PTRDIFF - 1 - JT_UNTAG_SHIFT)
+#define BPDELTA_MAX (((ptrdiff_t)1 << BITS_PER_BPDELTA) - 1)
+#define BPDELTA_TO_JT(bp) ((JSJumpTarget *)((bp) << JT_UNTAG_SHIFT))
+#define JT_TO_BPDELTA(jt) ((ptrdiff_t)((jsword)(jt) >> JT_UNTAG_SHIFT))
+
+#define SD_SET_TARGET(sd,jt) ((sd)->target = JT_SET_TAG(jt))
+#define SD_GET_TARGET(sd) (JS_ASSERT(JT_HAS_TAG((sd)->target)), \
+ JT_CLR_TAG((sd)->target))
+#define SD_SET_BPDELTA(sd,bp) ((sd)->target = BPDELTA_TO_JT(bp))
+#define SD_GET_BPDELTA(sd) (JS_ASSERT(!JT_HAS_TAG((sd)->target)), \
+ JT_TO_BPDELTA((sd)->target))
+
+/* Avoid asserting twice by expanding SD_GET_TARGET in the "then" clause. */
+#define SD_SPAN(sd,pivot) (SD_GET_TARGET(sd) \
+ ? JT_CLR_TAG((sd)->target)->offset - (pivot) \
+ : 0)
+
+typedef struct JSTryNode JSTryNode;
+
+struct JSTryNode {
+ JSTryNote note;
+ JSTryNode *prev;
+};
+
+typedef struct JSEmittedObjectList {
+ uint32 length; /* number of emitted so far objects */
+ JSParsedObjectBox *lastPob; /* last emitted object */
+} JSEmittedObjectList;
+
+extern void
+FinishParsedObjects(JSEmittedObjectList *emittedList, JSObjectArray *objectMap);
+
+struct JSCodeGenerator {
+ JSTreeContext treeContext; /* base state: statement info stack, etc. */
+
+ JSArenaPool *codePool; /* pointer to thread code arena pool */
+ JSArenaPool *notePool; /* pointer to thread srcnote arena pool */
+ void *codeMark; /* low watermark in cg->codePool */
+ void *noteMark; /* low watermark in cg->notePool */
+
+ struct {
+ jsbytecode *base; /* base of JS bytecode vector */
+ jsbytecode *limit; /* one byte beyond end of bytecode */
+ jsbytecode *next; /* pointer to next free bytecode */
+ jssrcnote *notes; /* source notes, see below */
+ uintN noteCount; /* number of source notes so far */
+ uintN noteMask; /* growth increment for notes */
+ ptrdiff_t lastNoteOffset; /* code offset for last source note */
+ uintN currentLine; /* line number for tree-based srcnote gen */
+ } prolog, main, *current;
+
+ JSAtomList atomList; /* literals indexed for mapping */
+ uintN firstLine; /* first line, for js_NewScriptFromCG */
+
+ intN stackDepth; /* current stack depth in script frame */
+ uintN maxStackDepth; /* maximum stack depth so far */
+
+ uintN ntrynotes; /* number of allocated so far try notes */
+ JSTryNode *lastTryNode; /* the last allocated try node */
+
+ JSSpanDep *spanDeps; /* span dependent instruction records */
+ JSJumpTarget *jumpTargets; /* AVL tree of jump target offsets */
+ JSJumpTarget *jtFreeList; /* JT_LEFT-linked list of free structs */
+ uintN numSpanDeps; /* number of span dependencies */
+ uintN numJumpTargets; /* number of jump targets */
+ ptrdiff_t spanDepTodo; /* offset from main.base of potentially
+ unoptimized spandeps */
+
+ uintN arrayCompDepth; /* stack depth of array in comprehension */
+
+ uintN emitLevel; /* js_EmitTree recursion level */
+ JSAtomList constList; /* compile time constants */
+
+ JSEmittedObjectList objectList; /* list of emitted so far objects */
+ JSEmittedObjectList regexpList; /* list of emitted so far regexp
+ that will be cloned during execution */
+
+ uintN staticDepth; /* static frame chain depth */
+ JSAtomList upvarList; /* map of atoms to upvar indexes */
+ JSUpvarArray upvarMap; /* indexed upvar pairs (JS_realloc'ed) */
+ JSCodeGenerator *parent; /* enclosing function or global context */
+};
+
+#define CG_TS(cg) TS((cg)->treeContext.parseContext)
+
+#define CG_BASE(cg) ((cg)->current->base)
+#define CG_LIMIT(cg) ((cg)->current->limit)
+#define CG_NEXT(cg) ((cg)->current->next)
+#define CG_CODE(cg,offset) (CG_BASE(cg) + (offset))
+#define CG_OFFSET(cg) PTRDIFF(CG_NEXT(cg), CG_BASE(cg), jsbytecode)
+
+#define CG_NOTES(cg) ((cg)->current->notes)
+#define CG_NOTE_COUNT(cg) ((cg)->current->noteCount)
+#define CG_NOTE_MASK(cg) ((cg)->current->noteMask)
+#define CG_LAST_NOTE_OFFSET(cg) ((cg)->current->lastNoteOffset)
+#define CG_CURRENT_LINE(cg) ((cg)->current->currentLine)
+
+#define CG_PROLOG_BASE(cg) ((cg)->prolog.base)
+#define CG_PROLOG_LIMIT(cg) ((cg)->prolog.limit)
+#define CG_PROLOG_NEXT(cg) ((cg)->prolog.next)
+#define CG_PROLOG_CODE(cg,poff) (CG_PROLOG_BASE(cg) + (poff))
+#define CG_PROLOG_OFFSET(cg) PTRDIFF(CG_PROLOG_NEXT(cg), CG_PROLOG_BASE(cg),\
+ jsbytecode)
+
+#define CG_SWITCH_TO_MAIN(cg) ((cg)->current = &(cg)->main)
+#define CG_SWITCH_TO_PROLOG(cg) ((cg)->current = &(cg)->prolog)
+
+/*
+ * Initialize cg to allocate bytecode space from codePool, source note space
+ * from notePool, and all other arena-allocated temporaries from cx->tempPool.
+ */
+extern JS_FRIEND_API(void)
+js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, JSParseContext *pc,
+ JSArenaPool *codePool, JSArenaPool *notePool,
+ uintN lineno);
+
+/*
+ * Release cg->codePool, cg->notePool, and cx->tempPool to marks set by
+ * js_InitCodeGenerator. Note that cgs are magic: they own the arena pool
+ * "tops-of-stack" space above their codeMark, noteMark, and tempMark points.
+ * This means you cannot alloc from tempPool and save the pointer beyond the
+ * next JS_FinishCodeGenerator.
+ */
+extern JS_FRIEND_API(void)
+js_FinishCodeGenerator(JSContext *cx, JSCodeGenerator *cg);
+
+/*
+ * Emit one bytecode.
+ */
+extern ptrdiff_t
+js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op);
+
+/*
+ * Emit two bytecodes, an opcode (op) with a byte of immediate operand (op1).
+ */
+extern ptrdiff_t
+js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1);
+
+/*
+ * Emit three bytecodes, an opcode with two bytes of immediate operands.
+ */
+extern ptrdiff_t
+js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1,
+ jsbytecode op2);
+
+/*
+ * Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
+ */
+extern ptrdiff_t
+js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra);
+
+/*
+ * Unsafe macro to call js_SetJumpOffset and return false if it does.
+ */
+#define CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx,cg,pc,off,BAD_EXIT) \
+ JS_BEGIN_MACRO \
+ if (!js_SetJumpOffset(cx, cg, pc, off)) { \
+ BAD_EXIT; \
+ } \
+ JS_END_MACRO
+
+#define CHECK_AND_SET_JUMP_OFFSET(cx,cg,pc,off) \
+ CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx,cg,pc,off,return JS_FALSE)
+
+#define CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx,cg,off,BAD_EXIT) \
+ CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx, cg, CG_CODE(cg,off), \
+ CG_OFFSET(cg) - (off), BAD_EXIT)
+
+#define CHECK_AND_SET_JUMP_OFFSET_AT(cx,cg,off) \
+ CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx, cg, off, return JS_FALSE)
+
+extern JSBool
+js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
+ ptrdiff_t off);
+
+/* Test whether we're in a statement of given type. */
+extern JSBool
+js_InStatement(JSTreeContext *tc, JSStmtType type);
+
+/* Test whether we're in a with statement. */
+#define js_InWithStatement(tc) js_InStatement(tc, STMT_WITH)
+
+/*
+ * Push the C-stack-allocated struct at stmt onto the stmtInfo stack.
+ */
+extern void
+js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,
+ ptrdiff_t top);
+
+/*
+ * Push a block scope statement and link blockObj into tc->blockChain. To pop
+ * this statement info record, use js_PopStatement as usual, or if appropriate
+ * (if generating code), js_PopStatementCG.
+ */
+extern void
+js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObject *blockObj,
+ ptrdiff_t top);
+
+/*
+ * Pop tc->topStmt. If the top JSStmtInfo struct is not stack-allocated, it
+ * is up to the caller to free it.
+ */
+extern void
+js_PopStatement(JSTreeContext *tc);
+
+/*
+ * Like js_PopStatement(&cg->treeContext), also patch breaks and continues
+ * unless the top statement info record represents a try-catch-finally suite.
+ * May fail if a jump offset overflows.
+ */
+extern JSBool
+js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg);
+
+/*
+ * Define and lookup a primitive jsval associated with the const named by atom.
+ * js_DefineCompileTimeConstant analyzes the constant-folded initializer at pn
+ * and saves the const's value in cg->constList, if it can be used at compile
+ * time. It returns true unless an error occurred.
+ *
+ * If the initializer's value could not be saved, js_DefineCompileTimeConstant
+ * calls will return the undefined value. js_DefineCompileTimeConstant tries
+ * to find a const value memorized for atom, returning true with *vp set to a
+ * value other than undefined if the constant was found, true with *vp set to
+ * JSVAL_VOID if not found, and false on error.
+ */
+extern JSBool
+js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
+ JSParseNode *pn);
+
+/*
+ * Find a lexically scoped variable (one declared by let, catch, or an array
+ * comprehension) named by atom, looking in tc's compile-time scopes.
+ *
+ * If a WITH statement is reached along the scope stack, return its statement
+ * info record, so callers can tell that atom is ambiguous. If slotp is not
+ * null, then if atom is found, set *slotp to its stack slot, otherwise to -1.
+ * This means that if slotp is not null, all the block objects on the lexical
+ * scope chain must have had their depth slots computed by the code generator,
+ * so the caller must be under js_EmitTree.
+ *
+ * In any event, directly return the statement info record in which atom was
+ * found. Otherwise return null.
+ */
+extern JSStmtInfo *
+js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp);
+
+/*
+ * Emit code into cg for the tree rooted at pn.
+ */
+extern JSBool
+js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn);
+
+/*
+ * Emit function code using cg for the tree rooted at body.
+ */
+extern JSBool
+js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body);
+
+/*
+ * Source notes generated along with bytecode for decompiling and debugging.
+ * A source note is a uint8 with 5 bits of type and 3 of offset from the pc of
+ * the previous note. If 3 bits of offset aren't enough, extended delta notes
+ * (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset bits
+ * are emitted before the next note. Some notes have operand offsets encoded
+ * immediately after them, in note bytes or byte-triples.
+ *
+ * Source Note Extended Delta
+ * +7-6-5-4-3+2-1-0+ +7-6-5+4-3-2-1-0+
+ * |note-type|delta| |1 1| ext-delta |
+ * +---------+-----+ +---+-----------+
+ *
+ * At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE,
+ * SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode.
+ *
+ * NB: the js_SrcNoteSpec array in jsemit.c is indexed by this enum, so its
+ * initializers need to match the order here.
+ *
+ * Note on adding new source notes: every pair of bytecodes (A, B) where A and
+ * B have disjoint sets of source notes that could apply to each bytecode may
+ * reuse the same note type value for two notes (snA, snB) that have the same
+ * arity, offsetBias, and isSpanDep initializers in js_SrcNoteSpec. This is
+ * why SRC_IF and SRC_INITPROP have the same value below. For bad historical
+ * reasons, some bytecodes below that could be overlayed have not been, but
+ * before using SRC_EXTENDED, consider compressing the existing note types.
+ *
+ * Don't forget to update JSXDR_BYTECODE_VERSION in jsxdrapi.h for all such
+ * incompatible source note or other bytecode changes.
+ */
+typedef enum JSSrcNoteType {
+ SRC_NULL = 0, /* terminates a note vector */
+ SRC_IF = 1, /* JSOP_IFEQ bytecode is from an if-then */
+ SRC_BREAK = 1, /* JSOP_GOTO is a break */
+ SRC_INITPROP = 1, /* disjoint meaning applied to JSOP_INITELEM or
+ to an index label in a regular (structuring)
+ or a destructuring object initialiser */
+ SRC_GENEXP = 1, /* JSOP_ANONFUNOBJ from generator expression */
+ SRC_IF_ELSE = 2, /* JSOP_IFEQ bytecode is from an if-then-else */
+ SRC_FOR_IN = 2, /* JSOP_GOTO to for-in loop condition from
+ before loop (same arity as SRC_IF_ELSE) */
+ SRC_FOR = 3, /* JSOP_NOP or JSOP_POP in for(;;) loop head */
+ SRC_WHILE = 4, /* JSOP_GOTO to for or while loop condition
+ from before loop, else JSOP_NOP at top of
+ do-while loop */
+ SRC_CONTINUE = 5, /* JSOP_GOTO is a continue, not a break;
+ also used on JSOP_ENDINIT if extra comma
+ at end of array literal: [1,2,,] */
+ SRC_DECL = 6, /* type of a declaration (var, const, let*) */
+ SRC_DESTRUCT = 6, /* JSOP_DUP starting a destructuring assignment
+ operation, with SRC_DECL_* offset operand */
+ SRC_PCDELTA = 7, /* distance forward from comma-operator to
+ next POP, or from CONDSWITCH to first CASE
+ opcode, etc. -- always a forward delta */
+ SRC_GROUPASSIGN = 7, /* SRC_DESTRUCT variant for [a, b] = [c, d] */
+ SRC_ASSIGNOP = 8, /* += or another assign-op follows */
+ SRC_COND = 9, /* JSOP_IFEQ is from conditional ?: operator */
+ SRC_BRACE = 10, /* mandatory brace, for scope or to avoid
+ dangling else */
+ SRC_HIDDEN = 11, /* opcode shouldn't be decompiled */
+ SRC_PCBASE = 12, /* distance back from annotated getprop or
+ setprop op to left-most obj.prop.subprop
+ bytecode -- always a backward delta */
+ SRC_LABEL = 13, /* JSOP_NOP for label: with atomid immediate */
+ SRC_LABELBRACE = 14, /* JSOP_NOP for label: {...} begin brace */
+ SRC_ENDBRACE = 15, /* JSOP_NOP for label: {...} end brace */
+ SRC_BREAK2LABEL = 16, /* JSOP_GOTO for 'break label' with atomid */
+ SRC_CONT2LABEL = 17, /* JSOP_GOTO for 'continue label' with atomid */
+ SRC_SWITCH = 18, /* JSOP_*SWITCH with offset to end of switch,
+ 2nd off to first JSOP_CASE if condswitch */
+ SRC_FUNCDEF = 19, /* JSOP_NOP for function f() with atomid */
+ SRC_CATCH = 20, /* catch block has guard */
+ SRC_EXTENDED = 21, /* extended source note, 32-159, in next byte */
+ SRC_NEWLINE = 22, /* bytecode follows a source newline */
+ SRC_SETLINE = 23, /* a file-absolute source line number note */
+ SRC_XDELTA = 24 /* 24-31 are for extended delta notes */
+} JSSrcNoteType;
+
+/*
+ * Constants for the SRC_DECL source note. Note that span-dependent bytecode
+ * selection means that any SRC_DECL offset greater than SRC_DECL_LET may need
+ * to be adjusted, but these "offsets" are too small to span a span-dependent
+ * instruction, so can be used to denote distinct declaration syntaxes to the
+ * decompiler.
+ *
+ * NB: the var_prefix array in jsopcode.c depends on these dense indexes from
+ * SRC_DECL_VAR through SRC_DECL_LET.
+ */
+#define SRC_DECL_VAR 0
+#define SRC_DECL_CONST 1
+#define SRC_DECL_LET 2
+#define SRC_DECL_NONE 3
+
+#define SN_TYPE_BITS 5
+#define SN_DELTA_BITS 3
+#define SN_XDELTA_BITS 6
+#define SN_TYPE_MASK (JS_BITMASK(SN_TYPE_BITS) << SN_DELTA_BITS)
+#define SN_DELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_DELTA_BITS))
+#define SN_XDELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_XDELTA_BITS))
+
+#define SN_MAKE_NOTE(sn,t,d) (*(sn) = (jssrcnote) \
+ (((t) << SN_DELTA_BITS) \
+ | ((d) & SN_DELTA_MASK)))
+#define SN_MAKE_XDELTA(sn,d) (*(sn) = (jssrcnote) \
+ ((SRC_XDELTA << SN_DELTA_BITS) \
+ | ((d) & SN_XDELTA_MASK)))
+
+#define SN_IS_XDELTA(sn) ((*(sn) >> SN_DELTA_BITS) >= SRC_XDELTA)
+#define SN_TYPE(sn) ((JSSrcNoteType)(SN_IS_XDELTA(sn) \
+ ? SRC_XDELTA \
+ : *(sn) >> SN_DELTA_BITS))
+#define SN_SET_TYPE(sn,type) SN_MAKE_NOTE(sn, type, SN_DELTA(sn))
+#define SN_IS_GETTABLE(sn) (SN_TYPE(sn) < SRC_NEWLINE)
+
+#define SN_DELTA(sn) ((ptrdiff_t)(SN_IS_XDELTA(sn) \
+ ? *(sn) & SN_XDELTA_MASK \
+ : *(sn) & SN_DELTA_MASK))
+#define SN_SET_DELTA(sn,delta) (SN_IS_XDELTA(sn) \
+ ? SN_MAKE_XDELTA(sn, delta) \
+ : SN_MAKE_NOTE(sn, SN_TYPE(sn), delta))
+
+#define SN_DELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_DELTA_BITS))
+#define SN_XDELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_XDELTA_BITS))
+
+/*
+ * Offset fields follow certain notes and are frequency-encoded: an offset in
+ * [0,0x7f] consumes one byte, an offset in [0x80,0x7fffff] takes three, and
+ * the high bit of the first byte is set.
+ */
+#define SN_3BYTE_OFFSET_FLAG 0x80
+#define SN_3BYTE_OFFSET_MASK 0x7f
+
+typedef struct JSSrcNoteSpec {
+ const char *name; /* name for disassembly/debugging output */
+ int8 arity; /* number of offset operands */
+ uint8 offsetBias; /* bias of offset(s) from annotated pc */
+ int8 isSpanDep; /* 1 or -1 if offsets could span extended ops,
+ 0 otherwise; sign tells span direction */
+} JSSrcNoteSpec;
+
+extern JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[];
+extern JS_FRIEND_API(uintN) js_SrcNoteLength(jssrcnote *sn);
+
+#define SN_LENGTH(sn) ((js_SrcNoteSpec[SN_TYPE(sn)].arity == 0) ? 1 \
+ : js_SrcNoteLength(sn))
+#define SN_NEXT(sn) ((sn) + SN_LENGTH(sn))
+
+/* A source note array is terminated by an all-zero element. */
+#define SN_MAKE_TERMINATOR(sn) (*(sn) = SRC_NULL)
+#define SN_IS_TERMINATOR(sn) (*(sn) == SRC_NULL)
+
+/*
+ * Append a new source note of the given type (and therefore size) to cg's
+ * notes dynamic array, updating cg->noteCount. Return the new note's index
+ * within the array pointed at by cg->current->notes. Return -1 if out of
+ * memory.
+ */
+extern intN
+js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type);
+
+extern intN
+js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
+ ptrdiff_t offset);
+
+extern intN
+js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
+ ptrdiff_t offset1, ptrdiff_t offset2);
+
+/*
+ * NB: this function can add at most one extra extended delta note.
+ */
+extern jssrcnote *
+js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn,
+ ptrdiff_t delta);
+
+/*
+ * Get and set the offset operand identified by which (0 for the first, etc.).
+ */
+extern JS_FRIEND_API(ptrdiff_t)
+js_GetSrcNoteOffset(jssrcnote *sn, uintN which);
+
+extern JSBool
+js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index,
+ uintN which, ptrdiff_t offset);
+
+/*
+ * Finish taking source notes in cx's notePool, copying final notes to the new
+ * stable store allocated by the caller and passed in via notes. Return false
+ * on malloc failure, which means this function reported an error.
+ *
+ * To compute the number of jssrcnotes to allocate and pass in via notes, use
+ * the CG_COUNT_FINAL_SRCNOTES macro. This macro knows a lot about details of
+ * js_FinishTakingSrcNotes, SO DON'T CHANGE jsemit.c's js_FinishTakingSrcNotes
+ * FUNCTION WITHOUT CHECKING WHETHER THIS MACRO NEEDS CORRESPONDING CHANGES!
+ */
+#define CG_COUNT_FINAL_SRCNOTES(cg, cnt) \
+ JS_BEGIN_MACRO \
+ ptrdiff_t diff_ = CG_PROLOG_OFFSET(cg) - (cg)->prolog.lastNoteOffset; \
+ cnt = (cg)->prolog.noteCount + (cg)->main.noteCount + 1; \
+ if ((cg)->prolog.noteCount && \
+ (cg)->prolog.currentLine != (cg)->firstLine) { \
+ if (diff_ > SN_DELTA_MASK) \
+ cnt += JS_HOWMANY(diff_ - SN_DELTA_MASK, SN_XDELTA_MASK); \
+ cnt += 2 + (((cg)->firstLine > SN_3BYTE_OFFSET_MASK) << 1); \
+ } else if (diff_ > 0) { \
+ if (cg->main.noteCount) { \
+ jssrcnote *sn_ = (cg)->main.notes; \
+ diff_ -= SN_IS_XDELTA(sn_) \
+ ? SN_XDELTA_MASK - (*sn_ & SN_XDELTA_MASK) \
+ : SN_DELTA_MASK - (*sn_ & SN_DELTA_MASK); \
+ } \
+ if (diff_ > 0) \
+ cnt += JS_HOWMANY(diff_, SN_XDELTA_MASK); \
+ } \
+ JS_END_MACRO
+
+extern JSBool
+js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes);
+
+extern void
+js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array);
+
+JS_END_EXTERN_C
+
+#endif /* jsemit_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsexn.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsexn.cpp
new file mode 100644
index 0000000..c61b724
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsexn.cpp
@@ -0,0 +1,1376 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS standard exception implementation.
+ */
+
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsexn.h"
+#include "jsfun.h"
+#include "jsinterp.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstaticcheck.h"
+
+/* Forward declarations for js_ErrorClass's initializer. */
+static JSBool
+Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+static void
+exn_finalize(JSContext *cx, JSObject *obj);
+
+static void
+exn_trace(JSTracer *trc, JSObject *obj);
+
+static void
+exn_finalize(JSContext *cx, JSObject *obj);
+
+static JSBool
+exn_enumerate(JSContext *cx, JSObject *obj);
+
+static JSBool
+exn_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp);
+
+JSClass js_ErrorClass = {
+ js_Error_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_MARK_IS_TRACE |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_Error),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ exn_enumerate, (JSResolveOp)exn_resolve, JS_ConvertStub, exn_finalize,
+ NULL, NULL, NULL, Exception,
+ NULL, NULL, JS_CLASS_TRACE(exn_trace), NULL
+};
+
+typedef struct JSStackTraceElem {
+ JSString *funName;
+ size_t argc;
+ const char *filename;
+ uintN ulineno;
+} JSStackTraceElem;
+
+typedef struct JSExnPrivate {
+ /* A copy of the JSErrorReport originally generated. */
+ JSErrorReport *errorReport;
+ JSString *message;
+ JSString *filename;
+ uintN lineno;
+ size_t stackDepth;
+ JSStackTraceElem stackElems[1];
+} JSExnPrivate;
+
+static JSString *
+StackTraceToString(JSContext *cx, JSExnPrivate *priv);
+
+static JSErrorReport *
+CopyErrorReport(JSContext *cx, JSErrorReport *report)
+{
+ /*
+ * We use a single malloc block to make a deep copy of JSErrorReport with
+ * the following layout:
+ * JSErrorReport
+ * array of copies of report->messageArgs
+ * jschar array with characters for all messageArgs
+ * jschar array with characters for ucmessage
+ * jschar array with characters for uclinebuf and uctokenptr
+ * char array with characters for linebuf and tokenptr
+ * char array with characters for filename
+ * Such layout together with the properties enforced by the following
+ * asserts does not need any extra alignment padding.
+ */
+ JS_STATIC_ASSERT(sizeof(JSErrorReport) % sizeof(const char *) == 0);
+ JS_STATIC_ASSERT(sizeof(const char *) % sizeof(jschar) == 0);
+
+ size_t filenameSize;
+ size_t linebufSize;
+ size_t uclinebufSize;
+ size_t ucmessageSize;
+ size_t i, argsArraySize, argsCopySize, argSize;
+ size_t mallocSize;
+ JSErrorReport *copy;
+ uint8 *cursor;
+
+#define JS_CHARS_SIZE(jschars) ((js_strlen(jschars) + 1) * sizeof(jschar))
+
+ filenameSize = report->filename ? strlen(report->filename) + 1 : 0;
+ linebufSize = report->linebuf ? strlen(report->linebuf) + 1 : 0;
+ uclinebufSize = report->uclinebuf ? JS_CHARS_SIZE(report->uclinebuf) : 0;
+ ucmessageSize = 0;
+ argsArraySize = 0;
+ argsCopySize = 0;
+ if (report->ucmessage) {
+ ucmessageSize = JS_CHARS_SIZE(report->ucmessage);
+ if (report->messageArgs) {
+ for (i = 0; report->messageArgs[i]; ++i)
+ argsCopySize += JS_CHARS_SIZE(report->messageArgs[i]);
+
+ /* Non-null messageArgs should have at least one non-null arg. */
+ JS_ASSERT(i != 0);
+ argsArraySize = (i + 1) * sizeof(const jschar *);
+ }
+ }
+
+ /*
+ * The mallocSize can not overflow since it represents the sum of the
+ * sizes of already allocated objects.
+ */
+ mallocSize = sizeof(JSErrorReport) + argsArraySize + argsCopySize +
+ ucmessageSize + uclinebufSize + linebufSize + filenameSize;
+ cursor = (uint8 *)JS_malloc(cx, mallocSize);
+ if (!cursor)
+ return NULL;
+
+ copy = (JSErrorReport *)cursor;
+ memset(cursor, 0, sizeof(JSErrorReport));
+ cursor += sizeof(JSErrorReport);
+
+ if (argsArraySize != 0) {
+ copy->messageArgs = (const jschar **)cursor;
+ cursor += argsArraySize;
+ for (i = 0; report->messageArgs[i]; ++i) {
+ copy->messageArgs[i] = (const jschar *)cursor;
+ argSize = JS_CHARS_SIZE(report->messageArgs[i]);
+ memcpy(cursor, report->messageArgs[i], argSize);
+ cursor += argSize;
+ }
+ copy->messageArgs[i] = NULL;
+ JS_ASSERT(cursor == (uint8 *)copy->messageArgs[0] + argsCopySize);
+ }
+
+ if (report->ucmessage) {
+ copy->ucmessage = (const jschar *)cursor;
+ memcpy(cursor, report->ucmessage, ucmessageSize);
+ cursor += ucmessageSize;
+ }
+
+ if (report->uclinebuf) {
+ copy->uclinebuf = (const jschar *)cursor;
+ memcpy(cursor, report->uclinebuf, uclinebufSize);
+ cursor += uclinebufSize;
+ if (report->uctokenptr) {
+ copy->uctokenptr = copy->uclinebuf + (report->uctokenptr -
+ report->uclinebuf);
+ }
+ }
+
+ if (report->linebuf) {
+ copy->linebuf = (const char *)cursor;
+ memcpy(cursor, report->linebuf, linebufSize);
+ cursor += linebufSize;
+ if (report->tokenptr) {
+ copy->tokenptr = copy->linebuf + (report->tokenptr -
+ report->linebuf);
+ }
+ }
+
+ if (report->filename) {
+ copy->filename = (const char *)cursor;
+ memcpy(cursor, report->filename, filenameSize);
+ }
+ JS_ASSERT(cursor + filenameSize == (uint8 *)copy + mallocSize);
+
+ /* Copy non-pointer members. */
+ copy->lineno = report->lineno;
+ copy->errorNumber = report->errorNumber;
+
+ /* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
+ copy->flags = report->flags;
+
+#undef JS_CHARS_SIZE
+ return copy;
+}
+
+static jsval *
+GetStackTraceValueBuffer(JSExnPrivate *priv)
+{
+ /*
+ * We use extra memory after JSExnPrivateInfo.stackElems to store jsvals
+ * that helps to produce more informative stack traces. The following
+ * assert allows us to assume that no gap after stackElems is necessary to
+ * align the buffer properly.
+ */
+ JS_STATIC_ASSERT(sizeof(JSStackTraceElem) % sizeof(jsval) == 0);
+
+ return (jsval *)(priv->stackElems + priv->stackDepth);
+}
+
+static JSBool
+InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
+ JSString *filename, uintN lineno, JSErrorReport *report)
+{
+ JSSecurityCallbacks *callbacks;
+ JSCheckAccessOp checkAccess;
+ JSErrorReporter older;
+ JSExceptionState *state;
+ jsval callerid, v;
+ JSStackFrame *fp, *fpstop;
+ size_t stackDepth, valueCount, size;
+ JSBool overflow;
+ JSExnPrivate *priv;
+ JSStackTraceElem *elem;
+ jsval *values;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, exnObject) == &js_ErrorClass);
+
+ /*
+ * Prepare stack trace data.
+ *
+ * Set aside any error reporter for cx and save its exception state
+ * so we can suppress any checkAccess failures. Such failures should stop
+ * the backtrace procedure, not result in a failure of this constructor.
+ */
+ callbacks = JS_GetSecurityCallbacks(cx);
+ checkAccess = callbacks
+ ? callbacks->checkObjectAccess
+ : NULL;
+ older = JS_SetErrorReporter(cx, NULL);
+ state = JS_SaveExceptionState(cx);
+
+ callerid = ATOM_KEY(cx->runtime->atomState.callerAtom);
+ stackDepth = 0;
+ valueCount = 0;
+ for (fp = cx->fp; fp; fp = fp->down) {
+ if (fp->fun && fp->argv) {
+ v = JSVAL_NULL;
+ if (checkAccess &&
+ !checkAccess(cx, fp->callee, callerid, JSACC_READ, &v)) {
+ break;
+ }
+ valueCount += fp->argc;
+ }
+ ++stackDepth;
+ }
+ JS_RestoreExceptionState(cx, state);
+ JS_SetErrorReporter(cx, older);
+ fpstop = fp;
+
+ size = offsetof(JSExnPrivate, stackElems);
+ overflow = (stackDepth > ((size_t)-1 - size) / sizeof(JSStackTraceElem));
+ size += stackDepth * sizeof(JSStackTraceElem);
+ overflow |= (valueCount > ((size_t)-1 - size) / sizeof(jsval));
+ size += valueCount * sizeof(jsval);
+ if (overflow) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+ priv = (JSExnPrivate *)JS_malloc(cx, size);
+ if (!priv)
+ return JS_FALSE;
+
+ /*
+ * We initialize errorReport with a copy of report after setting the
+ * private slot, to prevent GC accessing a junk value we clear the field
+ * here.
+ */
+ priv->errorReport = NULL;
+ priv->message = message;
+ priv->filename = filename;
+ priv->lineno = lineno;
+ priv->stackDepth = stackDepth;
+
+ values = GetStackTraceValueBuffer(priv);
+ elem = priv->stackElems;
+ for (fp = cx->fp; fp != fpstop; fp = fp->down) {
+ if (!fp->fun) {
+ elem->funName = NULL;
+ elem->argc = 0;
+ } else {
+ elem->funName = fp->fun->atom
+ ? ATOM_TO_STRING(fp->fun->atom)
+ : cx->runtime->emptyString;
+ elem->argc = fp->argc;
+ memcpy(values, fp->argv, fp->argc * sizeof(jsval));
+ values += fp->argc;
+ }
+ elem->ulineno = 0;
+ elem->filename = NULL;
+ if (fp->script) {
+ elem->filename = fp->script->filename;
+ if (fp->regs)
+ elem->ulineno = js_FramePCToLineNumber(cx, fp);
+ }
+ ++elem;
+ }
+ JS_ASSERT(priv->stackElems + stackDepth == elem);
+ JS_ASSERT(GetStackTraceValueBuffer(priv) + valueCount == values);
+
+ STOBJ_SET_SLOT(exnObject, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(priv));
+
+ if (report) {
+ /*
+ * Construct a new copy of the error report struct. We can't use the
+ * error report struct that was passed in, because it's allocated on
+ * the stack, and also because it may point to transient data in the
+ * JSTokenStream.
+ */
+ priv->errorReport = CopyErrorReport(cx, report);
+ if (!priv->errorReport) {
+ /* The finalizer realeases priv since it is in the private slot. */
+ return JS_FALSE;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSExnPrivate *
+GetExnPrivate(JSContext *cx, JSObject *obj)
+{
+ jsval privateValue;
+ JSExnPrivate *priv;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ErrorClass);
+ privateValue = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ if (JSVAL_IS_VOID(privateValue))
+ return NULL;
+ priv = (JSExnPrivate *)JSVAL_TO_PRIVATE(privateValue);
+ JS_ASSERT(priv);
+ return priv;
+}
+
+static void
+exn_trace(JSTracer *trc, JSObject *obj)
+{
+ JSExnPrivate *priv;
+ JSStackTraceElem *elem;
+ size_t vcount, i;
+ jsval *vp, v;
+
+ priv = GetExnPrivate(trc->context, obj);
+ if (priv) {
+ if (priv->message)
+ JS_CALL_STRING_TRACER(trc, priv->message, "exception message");
+ if (priv->filename)
+ JS_CALL_STRING_TRACER(trc, priv->filename, "exception filename");
+
+ elem = priv->stackElems;
+ for (vcount = i = 0; i != priv->stackDepth; ++i, ++elem) {
+ if (elem->funName) {
+ JS_CALL_STRING_TRACER(trc, elem->funName,
+ "stack trace function name");
+ }
+ if (IS_GC_MARKING_TRACER(trc) && elem->filename)
+ js_MarkScriptFilename(elem->filename);
+ vcount += elem->argc;
+ }
+ vp = GetStackTraceValueBuffer(priv);
+ for (i = 0; i != vcount; ++i, ++vp) {
+ v = *vp;
+ JS_CALL_VALUE_TRACER(trc, v, "stack trace argument");
+ }
+ }
+}
+
+static void
+exn_finalize(JSContext *cx, JSObject *obj)
+{
+ JSExnPrivate *priv;
+
+ priv = GetExnPrivate(cx, obj);
+ if (priv) {
+ if (priv->errorReport)
+ JS_free(cx, priv->errorReport);
+ JS_free(cx, priv);
+ }
+}
+
+static JSBool
+exn_enumerate(JSContext *cx, JSObject *obj)
+{
+ JSAtomState *atomState;
+ uintN i;
+ JSAtom *atom;
+ JSObject *pobj;
+ JSProperty *prop;
+
+ JS_STATIC_ASSERT(sizeof(JSAtomState) <= (size_t)(uint16)-1);
+ static const uint16 offsets[] = {
+ (uint16)offsetof(JSAtomState, messageAtom),
+ (uint16)offsetof(JSAtomState, fileNameAtom),
+ (uint16)offsetof(JSAtomState, lineNumberAtom),
+ (uint16)offsetof(JSAtomState, stackAtom),
+ };
+
+ atomState = &cx->runtime->atomState;
+ for (i = 0; i != JS_ARRAY_LENGTH(offsets); ++i) {
+ atom = *(JSAtom **)((uint8 *)atomState + offsets[i]);
+ if (!js_LookupProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop))
+ return JS_FALSE;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+exn_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ JSExnPrivate *priv;
+ JSString *str;
+ JSAtom *atom;
+ JSString *stack;
+ const char *prop;
+ jsval v;
+
+ *objp = NULL;
+ priv = GetExnPrivate(cx, obj);
+ if (priv && JSVAL_IS_STRING(id)) {
+ str = JSVAL_TO_STRING(id);
+
+ atom = cx->runtime->atomState.messageAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ prop = js_message_str;
+ v = STRING_TO_JSVAL(priv->message);
+ goto define;
+ }
+
+ atom = cx->runtime->atomState.fileNameAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ prop = js_fileName_str;
+ v = STRING_TO_JSVAL(priv->filename);
+ goto define;
+ }
+
+ atom = cx->runtime->atomState.lineNumberAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ prop = js_lineNumber_str;
+ v = INT_TO_JSVAL(priv->lineno);
+ goto define;
+ }
+
+ atom = cx->runtime->atomState.stackAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ stack = StackTraceToString(cx, priv);
+ if (!stack)
+ return JS_FALSE;
+
+ /* Allow to GC all things that were used to build stack trace. */
+ priv->stackDepth = 0;
+ prop = js_stack_str;
+ v = STRING_TO_JSVAL(stack);
+ goto define;
+ }
+ }
+ return JS_TRUE;
+
+ define:
+ if (!JS_DefineProperty(cx, obj, prop, v, NULL, NULL, JSPROP_ENUMERATE))
+ return JS_FALSE;
+ *objp = obj;
+ return JS_TRUE;
+}
+
+JSErrorReport *
+js_ErrorFromException(JSContext *cx, jsval exn)
+{
+ JSObject *obj;
+ JSExnPrivate *priv;
+
+ if (JSVAL_IS_PRIMITIVE(exn))
+ return NULL;
+ obj = JSVAL_TO_OBJECT(exn);
+ if (OBJ_GET_CLASS(cx, obj) != &js_ErrorClass)
+ return NULL;
+ priv = GetExnPrivate(cx, obj);
+ if (!priv)
+ return NULL;
+ return priv->errorReport;
+}
+
+struct JSExnSpec {
+ int protoIndex;
+ const char *name;
+ JSProtoKey key;
+ JSNative native;
+};
+
+/*
+ * All *Error constructors share the same JSClass, js_ErrorClass. But each
+ * constructor function for an *Error class must have a distinct native 'call'
+ * function pointer, in order for instanceof to work properly across multiple
+ * standard class sets. See jsfun.c:fun_hasInstance.
+ */
+#define MAKE_EXCEPTION_CTOR(name) \
+static JSBool \
+name(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) \
+{ \
+ return Exception(cx, obj, argc, argv, rval); \
+}
+
+MAKE_EXCEPTION_CTOR(Error)
+MAKE_EXCEPTION_CTOR(InternalError)
+MAKE_EXCEPTION_CTOR(EvalError)
+MAKE_EXCEPTION_CTOR(RangeError)
+MAKE_EXCEPTION_CTOR(ReferenceError)
+MAKE_EXCEPTION_CTOR(SyntaxError)
+MAKE_EXCEPTION_CTOR(TypeError)
+MAKE_EXCEPTION_CTOR(URIError)
+
+#undef MAKE_EXCEPTION_CTOR
+
+static struct JSExnSpec exceptions[] = {
+ {JSEXN_NONE, js_Error_str, JSProto_Error, Error},
+ {JSEXN_ERR, js_InternalError_str, JSProto_InternalError, InternalError},
+ {JSEXN_ERR, js_EvalError_str, JSProto_EvalError, EvalError},
+ {JSEXN_ERR, js_RangeError_str, JSProto_RangeError, RangeError},
+ {JSEXN_ERR, js_ReferenceError_str, JSProto_ReferenceError, ReferenceError},
+ {JSEXN_ERR, js_SyntaxError_str, JSProto_SyntaxError, SyntaxError},
+ {JSEXN_ERR, js_TypeError_str, JSProto_TypeError, TypeError},
+ {JSEXN_ERR, js_URIError_str, JSProto_URIError, URIError},
+ {0, NULL, JSProto_Null, NULL}
+};
+
+static JSString *
+ValueToShortSource(JSContext *cx, jsval v)
+{
+ JSString *str;
+
+ /* Avoid toSource bloat and fallibility for object types. */
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ str = js_ValueToSource(cx, v);
+ } else if (VALUE_IS_FUNCTION(cx, v)) {
+ /*
+ * XXX Avoid function decompilation bloat for now.
+ */
+ str = JS_GetFunctionId(JS_ValueToFunction(cx, v));
+ if (!str && !(str = js_ValueToSource(cx, v))) {
+ /*
+ * Continue to soldier on if the function couldn't be
+ * converted into a string.
+ */
+ JS_ClearPendingException(cx);
+ str = JS_NewStringCopyZ(cx, "[unknown function]");
+ }
+ } else {
+ /*
+ * XXX Avoid toString on objects, it takes too long and uses too much
+ * memory, for too many classes (see Mozilla bug 166743).
+ */
+ char buf[100];
+ JS_snprintf(buf, sizeof buf, "[object %s]",
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v))->name);
+ str = JS_NewStringCopyZ(cx, buf);
+ }
+ return str;
+}
+
+static JSString *
+StackTraceToString(JSContext *cx, JSExnPrivate *priv)
+{
+ jschar *stackbuf;
+ size_t stacklen, stackmax;
+ JSStackTraceElem *elem, *endElem;
+ jsval *values;
+ size_t i;
+ JSString *str;
+ const char *cp;
+ char ulnbuf[11];
+
+ /* After this point, failing control flow must goto bad. */
+ stackbuf = NULL;
+ stacklen = stackmax = 0;
+
+/* Limit the stackbuf length to a reasonable value to avoid overflow checks. */
+#define STACK_LENGTH_LIMIT JS_BIT(20)
+
+#define APPEND_CHAR_TO_STACK(c) \
+ JS_BEGIN_MACRO \
+ if (stacklen == stackmax) { \
+ void *ptr_; \
+ if (stackmax >= STACK_LENGTH_LIMIT) \
+ goto done; \
+ stackmax = stackmax ? 2 * stackmax : 64; \
+ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \
+ if (!ptr_) \
+ goto bad; \
+ stackbuf = (jschar *) ptr_; \
+ } \
+ stackbuf[stacklen++] = (c); \
+ JS_END_MACRO
+
+#define APPEND_STRING_TO_STACK(str) \
+ JS_BEGIN_MACRO \
+ JSString *str_ = str; \
+ jschar *chars_; \
+ size_t length_; \
+ \
+ JSSTRING_CHARS_AND_LENGTH(str_, chars_, length_); \
+ if (length_ > stackmax - stacklen) { \
+ void *ptr_; \
+ if (stackmax >= STACK_LENGTH_LIMIT || \
+ length_ >= STACK_LENGTH_LIMIT - stacklen) { \
+ goto done; \
+ } \
+ stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_)); \
+ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \
+ if (!ptr_) \
+ goto bad; \
+ stackbuf = (jschar *) ptr_; \
+ } \
+ js_strncpy(stackbuf + stacklen, chars_, length_); \
+ stacklen += length_; \
+ JS_END_MACRO
+
+ values = GetStackTraceValueBuffer(priv);
+ elem = priv->stackElems;
+ for (endElem = elem + priv->stackDepth; elem != endElem; elem++) {
+ if (elem->funName) {
+ APPEND_STRING_TO_STACK(elem->funName);
+ APPEND_CHAR_TO_STACK('(');
+ for (i = 0; i != elem->argc; i++, values++) {
+ if (i > 0)
+ APPEND_CHAR_TO_STACK(',');
+ str = ValueToShortSource(cx, *values);
+ if (!str)
+ goto bad;
+ APPEND_STRING_TO_STACK(str);
+ }
+ APPEND_CHAR_TO_STACK(')');
+ }
+ APPEND_CHAR_TO_STACK('@');
+ if (elem->filename) {
+ for (cp = elem->filename; *cp; cp++)
+ APPEND_CHAR_TO_STACK(*cp);
+ }
+ APPEND_CHAR_TO_STACK(':');
+ JS_snprintf(ulnbuf, sizeof ulnbuf, "%u", elem->ulineno);
+ for (cp = ulnbuf; *cp; cp++)
+ APPEND_CHAR_TO_STACK(*cp);
+ APPEND_CHAR_TO_STACK('\n');
+ }
+#undef APPEND_CHAR_TO_STACK
+#undef APPEND_STRING_TO_STACK
+#undef STACK_LENGTH_LIMIT
+
+ done:
+ if (stacklen == 0) {
+ JS_ASSERT(!stackbuf);
+ return cx->runtime->emptyString;
+ }
+ if (stacklen < stackmax) {
+ /*
+ * Realloc can fail when shrinking on some FreeBSD versions, so
+ * don't use JS_realloc here; simply let the oversized allocation
+ * be owned by the string in that rare case.
+ */
+ void *shrunk = JS_realloc(cx, stackbuf, (stacklen+1) * sizeof(jschar));
+ if (shrunk)
+ stackbuf = (jschar *) shrunk;
+ }
+
+ stackbuf[stacklen] = 0;
+ str = js_NewString(cx, stackbuf, stacklen);
+ if (str)
+ return str;
+
+ bad:
+ if (stackbuf)
+ JS_free(cx, stackbuf);
+ return NULL;
+}
+
+/* XXXbe Consolidate the ugly truth that we don't treat filename as UTF-8
+ with these two functions. */
+static JSString *
+FilenameToString(JSContext *cx, const char *filename)
+{
+ return JS_NewStringCopyZ(cx, filename);
+}
+
+static const char *
+StringToFilename(JSContext *cx, JSString *str)
+{
+ return js_GetStringBytes(cx, str);
+}
+
+static JSBool
+Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uint32 lineno;
+ JSString *message, *filename;
+ JSStackFrame *fp;
+
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ /*
+ * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when
+ * called as functions, without operator new. But as we do not give
+ * each constructor a distinct JSClass, whose .name member is used by
+ * js_NewObject to find the class prototype, we must get the class
+ * prototype ourselves.
+ */
+ if (!OBJ_GET_PROPERTY(cx, JSVAL_TO_OBJECT(argv[-2]),
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ rval))
+ return JS_FALSE;
+ obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+
+ /*
+ * If it's a new object of class Exception, then null out the private
+ * data so that the finalizer doesn't attempt to free it.
+ */
+ if (OBJ_GET_CLASS(cx, obj) == &js_ErrorClass)
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, JSVAL_VOID);
+
+ /* Set the 'message' property. */
+ if (argc != 0) {
+ message = js_ValueToString(cx, argv[0]);
+ if (!message)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(message);
+ } else {
+ message = cx->runtime->emptyString;
+ }
+
+ /* Set the 'fileName' property. */
+ if (argc > 1) {
+ filename = js_ValueToString(cx, argv[1]);
+ if (!filename)
+ return JS_FALSE;
+ argv[1] = STRING_TO_JSVAL(filename);
+ fp = NULL;
+ } else {
+ fp = JS_GetScriptedCaller(cx, NULL);
+ if (fp) {
+ filename = FilenameToString(cx, fp->script->filename);
+ if (!filename)
+ return JS_FALSE;
+ } else {
+ filename = cx->runtime->emptyString;
+ }
+ }
+
+ /* Set the 'lineNumber' property. */
+ if (argc > 2) {
+ lineno = js_ValueToECMAUint32(cx, &argv[2]);
+ if (JSVAL_IS_NULL(argv[2]))
+ return JS_FALSE;
+ } else {
+ if (!fp)
+ fp = JS_GetScriptedCaller(cx, NULL);
+ lineno = (fp && fp->regs) ? js_FramePCToLineNumber(cx, fp) : 0;
+ }
+
+ return (OBJ_GET_CLASS(cx, obj) != &js_ErrorClass) ||
+ InitExnPrivate(cx, obj, message, filename, lineno, NULL);
+}
+
+/*
+ * Convert to string.
+ *
+ * This method only uses JavaScript-modifiable properties name, message. It
+ * is left to the host to check for private data and report filename and line
+ * number information along with this message.
+ */
+static JSBool
+exn_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval v;
+ JSString *name, *message, *result;
+ jschar *chars, *cp;
+ size_t name_length, message_length, length;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj ||
+ !OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState.nameAtom),
+ &v)) {
+ return JS_FALSE;
+ }
+ name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString;
+ *vp = STRING_TO_JSVAL(name);
+
+ if (!JS_GetProperty(cx, obj, js_message_str, &v))
+ return JS_FALSE;
+ message = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v)
+ : cx->runtime->emptyString;
+
+ if (JSSTRING_LENGTH(message) != 0) {
+ name_length = JSSTRING_LENGTH(name);
+ message_length = JSSTRING_LENGTH(message);
+ length = (name_length ? name_length + 2 : 0) + message_length;
+ cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+
+ if (name_length) {
+ js_strncpy(cp, JSSTRING_CHARS(name), name_length);
+ cp += name_length;
+ *cp++ = ':'; *cp++ = ' ';
+ }
+ js_strncpy(cp, JSSTRING_CHARS(message), message_length);
+ cp += message_length;
+ *cp = 0;
+
+ result = js_NewString(cx, chars, length);
+ if (!result) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ } else {
+ result = name;
+ }
+
+ *vp = STRING_TO_JSVAL(result);
+ return JS_TRUE;
+}
+
+#if JS_HAS_TOSOURCE
+/*
+ * Return a string that may eval to something similar to the original object.
+ */
+static JSBool
+exn_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ JSString *name, *message, *filename, *lineno_as_str, *result;
+ jsval localroots[3] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
+ JSTempValueRooter tvr;
+ JSBool ok;
+ uint32 lineno;
+ size_t lineno_length, name_length, message_length, filename_length, length;
+ jschar *chars, *cp;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj ||
+ !OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState.nameAtom),
+ vp)) {
+ return JS_FALSE;
+ }
+ name = js_ValueToString(cx, *vp);
+ if (!name)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(name);
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_TEMP_ROOT(cx, 3, localroots, &tvr);
+
+#ifdef __GNUC__
+ message = filename = NULL;
+#endif
+ ok = JS_GetProperty(cx, obj, js_message_str, &localroots[0]) &&
+ (message = js_ValueToSource(cx, localroots[0]));
+ if (!ok)
+ goto out;
+ localroots[0] = STRING_TO_JSVAL(message);
+
+ ok = JS_GetProperty(cx, obj, js_fileName_str, &localroots[1]) &&
+ (filename = js_ValueToSource(cx, localroots[1]));
+ if (!ok)
+ goto out;
+ localroots[1] = STRING_TO_JSVAL(filename);
+
+ ok = JS_GetProperty(cx, obj, js_lineNumber_str, &localroots[2]);
+ if (!ok)
+ goto out;
+ lineno = js_ValueToECMAUint32 (cx, &localroots[2]);
+ ok = !JSVAL_IS_NULL(localroots[2]);
+ if (!ok)
+ goto out;
+
+ if (lineno != 0) {
+ lineno_as_str = js_ValueToString(cx, localroots[2]);
+ if (!lineno_as_str) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ lineno_length = JSSTRING_LENGTH(lineno_as_str);
+ } else {
+ lineno_as_str = NULL;
+ lineno_length = 0;
+ }
+
+ /* Magic 8, for the characters in ``(new ())''. */
+ name_length = JSSTRING_LENGTH(name);
+ message_length = JSSTRING_LENGTH(message);
+ length = 8 + name_length + message_length;
+
+ filename_length = JSSTRING_LENGTH(filename);
+ if (filename_length != 0) {
+ /* append filename as ``, {filename}'' */
+ length += 2 + filename_length;
+ if (lineno_as_str) {
+ /* append lineno as ``, {lineno_as_str}'' */
+ length += 2 + lineno_length;
+ }
+ } else {
+ if (lineno_as_str) {
+ /*
+ * no filename, but have line number,
+ * need to append ``, "", {lineno_as_str}''
+ */
+ length += 6 + lineno_length;
+ }
+ }
+
+ cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!chars) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ *cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' ';
+ js_strncpy(cp, JSSTRING_CHARS(name), name_length);
+ cp += name_length;
+ *cp++ = '(';
+ if (message_length != 0) {
+ js_strncpy(cp, JSSTRING_CHARS(message), message_length);
+ cp += message_length;
+ }
+
+ if (filename_length != 0) {
+ /* append filename as ``, {filename}'' */
+ *cp++ = ','; *cp++ = ' ';
+ js_strncpy(cp, JSSTRING_CHARS(filename), filename_length);
+ cp += filename_length;
+ } else {
+ if (lineno_as_str) {
+ /*
+ * no filename, but have line number,
+ * need to append ``, "", {lineno_as_str}''
+ */
+ *cp++ = ','; *cp++ = ' '; *cp++ = '"'; *cp++ = '"';
+ }
+ }
+ if (lineno_as_str) {
+ /* append lineno as ``, {lineno_as_str}'' */
+ *cp++ = ','; *cp++ = ' ';
+ js_strncpy(cp, JSSTRING_CHARS(lineno_as_str), lineno_length);
+ cp += lineno_length;
+ }
+
+ *cp++ = ')'; *cp++ = ')'; *cp = 0;
+
+ result = js_NewString(cx, chars, length);
+ if (!result) {
+ JS_free(cx, chars);
+ ok = JS_FALSE;
+ goto out;
+ }
+ *vp = STRING_TO_JSVAL(result);
+ ok = JS_TRUE;
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+#endif
+
+static JSFunctionSpec exception_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, exn_toSource, 0,0),
+#endif
+ JS_FN(js_toString_str, exn_toString, 0,0),
+ JS_FS_END
+};
+
+JSObject *
+js_InitExceptionClasses(JSContext *cx, JSObject *obj)
+{
+ JSObject *obj_proto, *protos[JSEXN_LIMIT];
+ int i;
+
+ /*
+ * If lazy class initialization occurs for any Error subclass, then all
+ * classes are initialized, starting with Error. To avoid reentry and
+ * redundant initialization, we must not pass a null proto parameter to
+ * js_NewObject below, when called for the Error superclass. We need to
+ * ensure that Object.prototype is the proto of Error.prototype.
+ *
+ * See the equivalent code to ensure that parent_proto is non-null when
+ * JS_InitClass calls js_NewObject, in jsapi.c.
+ */
+ if (!js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object),
+ &obj_proto)) {
+ return NULL;
+ }
+
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+
+ /* Initialize the prototypes first. */
+ for (i = 0; exceptions[i].name != 0; i++) {
+ JSAtom *atom;
+ JSFunction *fun;
+ JSString *nameString;
+ int protoIndex = exceptions[i].protoIndex;
+
+ /* Make the prototype for the current constructor name. */
+ protos[i] = js_NewObject(cx, &js_ErrorClass,
+ (protoIndex != JSEXN_NONE)
+ ? protos[protoIndex]
+ : obj_proto,
+ obj, 0);
+ if (!protos[i])
+ break;
+
+ /* So exn_finalize knows whether to destroy private data. */
+ STOBJ_SET_SLOT(protos[i], JSSLOT_PRIVATE, JSVAL_VOID);
+
+ /* Make a constructor function for the current name. */
+ atom = cx->runtime->atomState.classAtoms[exceptions[i].key];
+ fun = js_DefineFunction(cx, obj, atom, exceptions[i].native, 3, 0);
+ if (!fun)
+ break;
+
+ /* Make this constructor make objects of class Exception. */
+ FUN_CLASP(fun) = &js_ErrorClass;
+
+ /* Make the prototype and constructor links. */
+ if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), protos[i],
+ JSPROP_READONLY | JSPROP_PERMANENT)) {
+ break;
+ }
+
+ /* proto bootstrap bit from JS_InitClass omitted. */
+ nameString = JS_NewStringCopyZ(cx, exceptions[i].name);
+ if (!nameString)
+ break;
+
+ /* Add the name property to the prototype. */
+ if (!JS_DefineProperty(cx, protos[i], js_name_str,
+ STRING_TO_JSVAL(nameString),
+ NULL, NULL,
+ JSPROP_ENUMERATE)) {
+ break;
+ }
+
+ /* Finally, stash the constructor for later uses. */
+ if (!js_SetClassObject(cx, obj, exceptions[i].key, FUN_OBJECT(fun)))
+ break;
+ }
+
+ js_LeaveLocalRootScope(cx);
+ if (exceptions[i].name)
+ return NULL;
+
+ /*
+ * Add an empty message property. (To Exception.prototype only,
+ * because this property will be the same for all the exception
+ * protos.)
+ */
+ if (!JS_DefineProperty(cx, protos[0], js_message_str,
+ STRING_TO_JSVAL(cx->runtime->emptyString),
+ NULL, NULL, JSPROP_ENUMERATE)) {
+ return NULL;
+ }
+ if (!JS_DefineProperty(cx, protos[0], js_fileName_str,
+ STRING_TO_JSVAL(cx->runtime->emptyString),
+ NULL, NULL, JSPROP_ENUMERATE)) {
+ return NULL;
+ }
+ if (!JS_DefineProperty(cx, protos[0], js_lineNumber_str,
+ INT_TO_JSVAL(0),
+ NULL, NULL, JSPROP_ENUMERATE)) {
+ return NULL;
+ }
+
+ /*
+ * Add methods only to Exception.prototype, because ostensibly all
+ * exception types delegate to that.
+ */
+ if (!JS_DefineFunctions(cx, protos[0], exception_methods))
+ return NULL;
+
+ return protos[0];
+}
+
+const JSErrorFormatString*
+js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale,
+ const uintN errorNumber)
+{
+ const JSErrorFormatString *errorString = NULL;
+
+ if (cx->localeCallbacks && cx->localeCallbacks->localeGetErrorMessage) {
+ errorString = cx->localeCallbacks
+ ->localeGetErrorMessage(userRef, locale, errorNumber);
+ }
+ if (!errorString)
+ errorString = js_GetErrorMessage(userRef, locale, errorNumber);
+ return errorString;
+}
+
+#if defined ( DEBUG_mccabe ) && defined ( PRINTNAMES )
+/* For use below... get character strings for error name and exception name */
+static struct exnname { char *name; char *exception; } errortoexnname[] = {
+#define MSG_DEF(name, number, count, exception, format) \
+ {#name, #exception},
+#include "js.msg"
+#undef MSG_DEF
+};
+#endif /* DEBUG */
+
+JSBool
+js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
+{
+ JSErrNum errorNumber;
+ const JSErrorFormatString *errorString;
+ JSExnType exn;
+ jsval tv[4];
+ JSTempValueRooter tvr;
+ JSBool ok;
+ JSObject *errProto, *errObject;
+ JSString *messageStr, *filenameStr;
+
+ /*
+ * Tell our caller to report immediately if this report is just a warning.
+ */
+ JS_ASSERT(reportp);
+ if (JSREPORT_IS_WARNING(reportp->flags))
+ return JS_FALSE;
+
+ /* Find the exception index associated with this error. */
+ errorNumber = (JSErrNum) reportp->errorNumber;
+ errorString = js_GetLocalizedErrorMessage(cx, NULL, NULL, errorNumber);
+ exn = errorString ? (JSExnType) errorString->exnType : JSEXN_NONE;
+ JS_ASSERT(exn < JSEXN_LIMIT);
+
+#if defined( DEBUG_mccabe ) && defined ( PRINTNAMES )
+ /* Print the error name and the associated exception name to stderr */
+ fprintf(stderr, "%s\t%s\n",
+ errortoexnname[errorNumber].name,
+ errortoexnname[errorNumber].exception);
+#endif
+
+ /*
+ * Return false (no exception raised) if no exception is associated
+ * with the given error number.
+ */
+ if (exn == JSEXN_NONE)
+ return JS_FALSE;
+
+ /*
+ * Prevent runaway recursion, via cx->generatingError. If an out-of-memory
+ * error occurs, no exception object will be created, but we don't assume
+ * that OOM is the only kind of error that subroutines of this function
+ * called below might raise.
+ */
+ if (cx->generatingError)
+ return JS_FALSE;
+
+ MUST_FLOW_THROUGH("out");
+ cx->generatingError = JS_TRUE;
+
+ /* Protect the newly-created strings below from nesting GCs. */
+ memset(tv, 0, sizeof tv);
+ JS_PUSH_TEMP_ROOT(cx, JS_ARRAY_LENGTH(tv), tv, &tvr);
+
+ /*
+ * Try to get an appropriate prototype by looking up the corresponding
+ * exception constructor name in the scope chain of the current context's
+ * top stack frame, or in the global object if no frame is active.
+ */
+ ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(exceptions[exn].key),
+ &errProto);
+ if (!ok)
+ goto out;
+ tv[0] = OBJECT_TO_JSVAL(errProto);
+
+ errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL, 0);
+ if (!errObject) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ tv[1] = OBJECT_TO_JSVAL(errObject);
+
+ messageStr = JS_NewStringCopyZ(cx, message);
+ if (!messageStr) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ tv[2] = STRING_TO_JSVAL(messageStr);
+
+ filenameStr = JS_NewStringCopyZ(cx, reportp->filename);
+ if (!filenameStr) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ tv[3] = STRING_TO_JSVAL(filenameStr);
+
+ ok = InitExnPrivate(cx, errObject, messageStr, filenameStr,
+ reportp->lineno, reportp);
+ if (!ok)
+ goto out;
+
+ JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject));
+
+ /* Flag the error report passed in to indicate an exception was raised. */
+ reportp->flags |= JSREPORT_EXCEPTION;
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ cx->generatingError = JS_FALSE;
+ return ok;
+}
+
+JSBool
+js_ReportUncaughtException(JSContext *cx)
+{
+ jsval exn;
+ JSObject *exnObject;
+ jsval roots[5];
+ JSTempValueRooter tvr;
+ JSErrorReport *reportp, report;
+ JSString *str;
+ const char *bytes;
+ JSBool ok;
+
+ if (!JS_IsExceptionPending(cx))
+ return JS_TRUE;
+
+ if (!JS_GetPendingException(cx, &exn))
+ return JS_FALSE;
+
+ memset(roots, 0, sizeof roots);
+ JS_PUSH_TEMP_ROOT(cx, JS_ARRAY_LENGTH(roots), roots, &tvr);
+
+ /*
+ * Because js_ValueToString below could error and an exception object
+ * could become unrooted, we must root exnObject. Later, if exnObject is
+ * non-null, we need to root other intermediates, so allocate an operand
+ * stack segment to protect all of these values.
+ */
+ if (JSVAL_IS_PRIMITIVE(exn)) {
+ exnObject = NULL;
+ } else {
+ exnObject = JSVAL_TO_OBJECT(exn);
+ roots[0] = exn;
+ }
+
+ JS_ClearPendingException(cx);
+ reportp = js_ErrorFromException(cx, exn);
+
+ /* XXX L10N angels cry once again (see also jsemit.c, /L10N gaffes/) */
+ str = js_ValueToString(cx, exn);
+ if (!str) {
+ bytes = "unknown (can't convert to string)";
+ } else {
+ roots[1] = STRING_TO_JSVAL(str);
+ bytes = js_GetStringBytes(cx, str);
+ if (!bytes) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+ ok = JS_TRUE;
+
+ if (!reportp &&
+ exnObject &&
+ OBJ_GET_CLASS(cx, exnObject) == &js_ErrorClass) {
+ const char *filename;
+ uint32 lineno;
+
+ ok = JS_GetProperty(cx, exnObject, js_message_str, &roots[2]);
+ if (!ok)
+ goto out;
+ if (JSVAL_IS_STRING(roots[2])) {
+ bytes = js_GetStringBytes(cx, JSVAL_TO_STRING(roots[2]));
+ if (!bytes) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+
+ ok = JS_GetProperty(cx, exnObject, js_fileName_str, &roots[3]);
+ if (!ok)
+ goto out;
+ str = js_ValueToString(cx, roots[3]);
+ if (!str) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ filename = StringToFilename(cx, str);
+ if (!filename) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ ok = JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4]);
+ if (!ok)
+ goto out;
+ lineno = js_ValueToECMAUint32 (cx, &roots[4]);
+ ok = !JSVAL_IS_NULL(roots[4]);
+ if (!ok)
+ goto out;
+
+ reportp = &report;
+ memset(&report, 0, sizeof report);
+ report.filename = filename;
+ report.lineno = (uintN) lineno;
+ }
+
+ if (!reportp) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_UNCAUGHT_EXCEPTION, bytes);
+ } else {
+ /* Flag the error as an exception. */
+ reportp->flags |= JSREPORT_EXCEPTION;
+
+ /* Pass the exception object. */
+ JS_SetPendingException(cx, exn);
+ js_ReportErrorAgain(cx, bytes, reportp);
+ JS_ClearPendingException(cx);
+ }
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsexn.h b/tools/node_modules/expresso/deps/jscoverage/js/jsexn.h
new file mode 100644
index 0000000..867586d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsexn.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS runtime exception classes.
+ */
+
+#ifndef jsexn_h___
+#define jsexn_h___
+
+JS_BEGIN_EXTERN_C
+
+extern JSClass js_ErrorClass;
+
+/*
+ * Initialize the exception constructor/prototype hierarchy.
+ */
+extern JSObject *
+js_InitExceptionClasses(JSContext *cx, JSObject *obj);
+
+/*
+ * Given a JSErrorReport, check to see if there is an exception associated with
+ * the error number. If there is, then create an appropriate exception object,
+ * set it as the pending exception, and set the JSREPORT_EXCEPTION flag on the
+ * error report. Exception-aware host error reporters should probably ignore
+ * error reports so flagged. Returns JS_TRUE if an associated exception is
+ * found and set, JS_FALSE otherwise.
+ */
+extern JSBool
+js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp);
+
+/*
+ * Called if a JS API call to js_Execute or js_InternalCall fails; calls the
+ * error reporter with the error report associated with any uncaught exception
+ * that has been raised. Returns true if there was an exception pending, and
+ * the error reporter was actually called.
+ *
+ * The JSErrorReport * that the error reporter is called with is currently
+ * associated with a JavaScript object, and is not guaranteed to persist after
+ * the object is collected. Any persistent uses of the JSErrorReport contents
+ * should make their own copy.
+ *
+ * The flags field of the JSErrorReport will have the JSREPORT_EXCEPTION flag
+ * set; embeddings that want to silently propagate JavaScript exceptions to
+ * other contexts may want to use an error reporter that ignores errors with
+ * this flag.
+ */
+extern JSBool
+js_ReportUncaughtException(JSContext *cx);
+
+extern JSErrorReport *
+js_ErrorFromException(JSContext *cx, jsval exn);
+
+extern const JSErrorFormatString *
+js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale,
+ const uintN errorNumber);
+
+JS_END_EXTERN_C
+
+#endif /* jsexn_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsfile.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.cpp
new file mode 100644
index 0000000..c5f60ae
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.cpp
@@ -0,0 +1,2736 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS File object
+ */
+#if JS_HAS_FILE_OBJECT
+
+#include "jsstddef.h"
+#include "jsfile.h"
+
+/* ----------------- Platform-specific includes and defines ----------------- */
+#if defined(XP_WIN) || defined(XP_OS2)
+# include <direct.h>
+# include <io.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# define FILESEPARATOR '\\'
+# define FILESEPARATOR2 '/'
+# define CURRENT_DIR "c:\\"
+# define POPEN _popen
+# define PCLOSE _pclose
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+# include <strings.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
+# define FILESEPARATOR '/'
+# define FILESEPARATOR2 '\0'
+# define CURRENT_DIR "/"
+# define POPEN popen
+# define PCLOSE pclose
+#endif
+
+/* --------------- Platform-independent includes and defines ---------------- */
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsdate.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jslock.h"
+#include "jsobj.h"
+#include "jsparse.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include <string.h>
+
+/* NSPR dependencies */
+#include "prio.h"
+#include "prerror.h"
+
+#define SPECIAL_FILE_STRING "Special File"
+#define CURRENTDIR_PROPERTY "currentDir"
+#define SEPARATOR_PROPERTY "separator"
+#define FILE_CONSTRUCTOR "File"
+#define PIPE_SYMBOL '|'
+
+#define ASCII 0
+#define UTF8 1
+#define UCS2 2
+
+#define asciistring "text"
+#define utfstring "binary"
+#define unicodestring "unicode"
+
+#define MAX_PATH_LENGTH 1024
+#define MODE_SIZE 256
+#define NUMBER_SIZE 32
+#define MAX_LINE_LENGTH 256
+#define URL_PREFIX "file://"
+
+#define STDINPUT_NAME "Standard input stream"
+#define STDOUTPUT_NAME "Standard output stream"
+#define STDERROR_NAME "Standard error stream"
+
+#define RESOLVE_PATH js_canonicalPath /* js_absolutePath */
+
+/* Error handling */
+typedef enum JSFileErrNum {
+#define MSG_DEF(name, number, count, exception, format) \
+ name = number,
+#include "jsfile.msg"
+#undef MSG_DEF
+ JSFileErr_Limit
+#undef MSGDEF
+} JSFileErrNum;
+
+#define JSFILE_HAS_DFLT_MSG_STRINGS 1
+
+JSErrorFormatString JSFile_ErrorFormatString[JSFileErr_Limit] = {
+#if JSFILE_HAS_DFLT_MSG_STRINGS
+#define MSG_DEF(name, number, count, exception, format) \
+ { format, count },
+#else
+#define MSG_DEF(name, number, count, exception, format) \
+ { NULL, count },
+#endif
+#include "jsfile.msg"
+#undef MSG_DEF
+};
+
+const JSErrorFormatString *
+JSFile_GetErrorMessage(void *userRef, const char *locale,
+ const uintN errorNumber)
+{
+ if ((errorNumber > 0) && (errorNumber < JSFileErr_Limit))
+ return &JSFile_ErrorFormatString[errorNumber];
+ else
+ return NULL;
+}
+
+#define JSFILE_CHECK_NATIVE(op) \
+ if (file->isNative) { \
+ JS_ReportWarning(cx, "Cannot call or access \"%s\" on native file %s",\
+ op, file->path); \
+ goto out; \
+ }
+
+#define JSFILE_CHECK_WRITE \
+ if (!file->isOpen) { \
+ JS_ReportWarning(cx, \
+ "File %s is closed, will open it for writing, proceeding", \
+ file->path); \
+ js_FileOpen(cx, obj, file, "write,append,create"); \
+ } \
+ if (!js_canWrite(cx, file)) { \
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
+ JSFILEMSG_CANNOT_WRITE, file->path); \
+ goto out; \
+ }
+
+#define JSFILE_CHECK_READ \
+ if (!file->isOpen) { \
+ JS_ReportWarning(cx, \
+ "File %s is closed, will open it for reading, proceeding", \
+ file->path); \
+ js_FileOpen(cx, obj, file, "read"); \
+ } \
+ if (!js_canRead(cx, file)) { \
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
+ JSFILEMSG_CANNOT_READ, file->path); \
+ goto out; \
+ }
+
+#define JSFILE_CHECK_OPEN(op) \
+ if (!file->isOpen) { \
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
+ JSFILEMSG_FILE_MUST_BE_OPEN, op); \
+ goto out; \
+ }
+
+#define JSFILE_CHECK_CLOSED(op) \
+ if (file->isOpen) { \
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
+ JSFILEMSG_FILE_MUST_BE_CLOSED, op); \
+ goto out; \
+ }
+
+#define JSFILE_CHECK_ONE_ARG(op) \
+ if (argc != 1) { \
+ char str[NUMBER_SIZE]; \
+ sprintf(str, "%d", argc); \
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
+ JSFILEMSG_EXPECTS_ONE_ARG_ERROR, op, str); \
+ goto out; \
+ }
+
+
+/*
+ Security mechanism, should define a callback for this.
+ The parameters are as follows:
+ SECURITY_CHECK(JSContext *cx, JSPrincipals *ps, char *op_name, JSFile *file)
+ XXX Should this be a real function returning a JSBool result (and getting
+ some typesafety help from the compiler?).
+*/
+#define SECURITY_CHECK(cx, ps, op, file) \
+ /* Define a callback here... */
+
+
+/* Structure representing the file internally */
+typedef struct JSFile {
+ char *path; /* the path to the file. */
+ JSBool isOpen;
+ int32 mode; /* mode used to open the file: read, write, append, create, etc.. */
+ int32 type; /* Asciiz, utf, unicode */
+ char byteBuffer[3]; /* bytes read in advance by js_FileRead ( UTF8 encoding ) */
+ jsint nbBytesInBuf; /* number of bytes stored in the buffer above */
+ jschar charBuffer; /* character read in advance by readln ( mac files only ) */
+ JSBool charBufferUsed; /* flag indicating if the buffer above is being used */
+ JSBool hasRandomAccess;/* can the file be randomly accessed? false for stdin, and
+ UTF-encoded files. */
+ JSBool hasAutoflush; /* should we force a flush for each line break? */
+ JSBool isNative; /* if the file is using OS-specific file FILE type */
+ /* We can actually put the following two in a union since they should never be used at the same time */
+ PRFileDesc *handle; /* the handle for the file, if open. */
+ FILE *nativehandle; /* native handle, for stuff NSPR doesn't do. */
+ JSBool isPipe; /* if the file is really an OS pipe */
+} JSFile;
+
+/* a few forward declarations... */
+JS_PUBLIC_API(JSObject*) js_NewFileObject(JSContext *cx, char *filename);
+static JSBool file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+static JSBool file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+/* New filename manipulation procesures */
+/* assumes we don't have leading/trailing spaces */
+static JSBool
+js_filenameHasAPipe(const char *filename)
+{
+ if (!filename)
+ return JS_FALSE;
+
+ return filename[0] == PIPE_SYMBOL ||
+ filename[strlen(filename) - 1] == PIPE_SYMBOL;
+}
+
+static JSBool
+js_isAbsolute(const char *name)
+{
+#if defined(XP_WIN) || defined(XP_OS2)
+ return *name && name[1] == ':';
+#else
+ return (name[0]
+# if defined(XP_UNIX) || defined(XP_BEOS)
+ ==
+# else
+ !=
+# endif
+ FILESEPARATOR);
+#endif
+}
+
+/*
+ * Concatenates base and name to produce a valid filename.
+ * Returned string must be freed.
+*/
+static char*
+js_combinePath(JSContext *cx, const char *base, const char *name)
+{
+ int len = strlen(base);
+ char* result = JS_malloc(cx, len + strlen(name) + 2);
+
+ if (!result)
+ return NULL;
+
+ strcpy(result, base);
+
+ if (base[len - 1] != FILESEPARATOR && base[len - 1] != FILESEPARATOR2) {
+ result[len] = FILESEPARATOR;
+ result[len + 1] = '\0';
+ }
+ strcat(result, name);
+ return result;
+}
+
+/* Extract the last component from a path name. Returned string must be freed */
+static char *
+js_fileBaseName(JSContext *cx, const char *pathname)
+{
+ jsint index, aux;
+ char *result;
+
+ index = strlen(pathname)-1;
+
+ /* Chop off trailing seperators. */
+ while (index > 0 && (pathname[index]==FILESEPARATOR ||
+ pathname[index]==FILESEPARATOR2)) {
+ --index;
+ }
+
+ aux = index;
+
+ /* Now find the next separator. */
+ while (index >= 0 && pathname[index] != FILESEPARATOR &&
+ pathname[index] != FILESEPARATOR2) {
+ --index;
+ }
+
+ /* Allocate and copy. */
+ result = JS_malloc(cx, aux - index + 1);
+ if (!result)
+ return NULL;
+ strncpy(result, pathname + index + 1, aux - index);
+ result[aux - index] = '\0';
+ return result;
+}
+
+/*
+ * Returns everything but the last component from a path name.
+ * Returned string must be freed.
+ */
+static char *
+js_fileDirectoryName(JSContext *cx, const char *pathname)
+{
+ char *result;
+ const char *cp, *end;
+ size_t pathsize;
+
+ end = pathname + strlen(pathname);
+ cp = end - 1;
+
+ /* If this is already a directory, chop off the trailing /s. */
+ while (cp >= pathname) {
+ if (*cp != FILESEPARATOR && *cp != FILESEPARATOR2)
+ break;
+ --cp;
+ }
+
+ if (cp < pathname && end != pathname) {
+ /* There were just /s, return the root. */
+ result = JS_malloc(cx, 1 + 1); /* The separator + trailing NUL. */
+ result[0] = FILESEPARATOR;
+ result[1] = '\0';
+ return result;
+ }
+
+ /* Now chop off the last portion. */
+ while (cp >= pathname) {
+ if (*cp == FILESEPARATOR || *cp == FILESEPARATOR2)
+ break;
+ --cp;
+ }
+
+ /* Check if this is a leaf. */
+ if (cp < pathname) {
+ /* It is, return "pathname/". */
+ if (end[-1] == FILESEPARATOR || end[-1] == FILESEPARATOR2) {
+ /* Already has its terminating /. */
+ return JS_strdup(cx, pathname);
+ }
+
+ pathsize = end - pathname + 1;
+ result = JS_malloc(cx, pathsize + 1);
+ if (!result)
+ return NULL;
+
+ strcpy(result, pathname);
+ result[pathsize - 1] = FILESEPARATOR;
+ result[pathsize] = '\0';
+
+ return result;
+ }
+
+ /* Return everything up to and including the seperator. */
+ pathsize = cp - pathname + 1;
+ result = JS_malloc(cx, pathsize + 1);
+ if (!result)
+ return NULL;
+
+ strncpy(result, pathname, pathsize);
+ result[pathsize] = '\0';
+
+ return result;
+}
+
+static char *
+js_absolutePath(JSContext *cx, const char * path)
+{
+ JSObject *obj;
+ JSString *str;
+ jsval prop;
+
+ if (js_isAbsolute(path)) {
+ return JS_strdup(cx, path);
+ } else {
+ obj = JS_GetGlobalObject(cx);
+ if (!JS_GetProperty(cx, obj, FILE_CONSTRUCTOR, &prop)) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FILE_CONSTRUCTOR_UNDEFINED_ERROR);
+ return JS_strdup(cx, path);
+ }
+
+ obj = JSVAL_TO_OBJECT(prop);
+ if (!JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, &prop)) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FILE_CURRENTDIR_UNDEFINED_ERROR);
+ return JS_strdup(cx, path);
+ }
+
+ str = JS_ValueToString(cx, prop);
+ if (!str)
+ return JS_strdup(cx, path);
+
+ /* should we have an array of curr dirs indexed by drive for windows? */
+ return js_combinePath(cx, JS_GetStringBytes(str), path);
+ }
+}
+
+/* Side effect: will remove spaces in the beginning/end of the filename */
+static char *
+js_canonicalPath(JSContext *cx, char *oldpath)
+{
+ char *tmp;
+ char *path = oldpath;
+ char *base, *dir, *current, *result;
+ jsint c;
+ jsint back = 0;
+ unsigned int i = 0, j = strlen(path)-1;
+
+ /* This is probably optional */
+ /* Remove possible spaces in the beginning and end */
+ while (i < j && path[i] == ' ')
+ i++;
+ while (j >= 0 && path[j] == ' ')
+ j--;
+
+ tmp = JS_malloc(cx, j-i+2);
+ if (!tmp)
+ return NULL;
+
+ strncpy(tmp, path + i, j - i + 1);
+ tmp[j - i + 1] = '\0';
+
+ path = tmp;
+
+ /* Pipe support. */
+ if (js_filenameHasAPipe(path))
+ return path;
+
+ /* file:// support. */
+ if (!strncmp(path, URL_PREFIX, strlen(URL_PREFIX))) {
+ tmp = js_canonicalPath(cx, path + strlen(URL_PREFIX));
+ JS_free(cx, path);
+ return tmp;
+ }
+
+ if (!js_isAbsolute(path)) {
+ tmp = js_absolutePath(cx, path);
+ if (!tmp)
+ return NULL;
+ JS_free(cx, path);
+ path = tmp;
+ }
+
+ result = JS_strdup(cx, "");
+
+ current = path;
+
+ base = js_fileBaseName(cx, current);
+ dir = js_fileDirectoryName(cx, current);
+
+ while (strcmp(dir, current)) {
+ if (!strcmp(base, "..")) {
+ back++;
+ } else {
+ if (back > 0) {
+ back--;
+ } else {
+ tmp = result;
+ result = JS_malloc(cx, strlen(base) + 1 + strlen(tmp) + 1);
+ if (!result)
+ goto out;
+
+ strcpy(result, base);
+ c = strlen(result);
+ if (*tmp) {
+ result[c] = FILESEPARATOR;
+ result[c + 1] = '\0';
+ strcat(result, tmp);
+ }
+ JS_free(cx, tmp);
+ }
+ }
+ JS_free(cx, current);
+ JS_free(cx, base);
+ current = dir;
+ base = js_fileBaseName(cx, current);
+ dir = js_fileDirectoryName(cx, current);
+ }
+
+ tmp = result;
+ result = JS_malloc(cx, strlen(dir)+1+strlen(tmp)+1);
+ if (!result)
+ goto out;
+
+ strcpy(result, dir);
+ c = strlen(result);
+ if (tmp[0]!='\0') {
+ if ((result[c-1]!=FILESEPARATOR)&&(result[c-1]!=FILESEPARATOR2)) {
+ result[c] = FILESEPARATOR;
+ result[c+1] = '\0';
+ }
+ strcat(result, tmp);
+ }
+
+out:
+ if (tmp)
+ JS_free(cx, tmp);
+ if (dir)
+ JS_free(cx, dir);
+ if (base)
+ JS_free(cx, base);
+ if (current)
+ JS_free(cx, current);
+
+ return result;
+}
+
+/* -------------------------- Text conversion ------------------------------- */
+/* The following is ripped from libi18n/unicvt.c and include files.. */
+
+/*
+ * UTF8 defines and macros
+ */
+#define ONE_OCTET_BASE 0x00 /* 0xxxxxxx */
+#define ONE_OCTET_MASK 0x7F /* x1111111 */
+#define CONTINUING_OCTET_BASE 0x80 /* 10xxxxxx */
+#define CONTINUING_OCTET_MASK 0x3F /* 00111111 */
+#define TWO_OCTET_BASE 0xC0 /* 110xxxxx */
+#define TWO_OCTET_MASK 0x1F /* 00011111 */
+#define THREE_OCTET_BASE 0xE0 /* 1110xxxx */
+#define THREE_OCTET_MASK 0x0F /* 00001111 */
+#define FOUR_OCTET_BASE 0xF0 /* 11110xxx */
+#define FOUR_OCTET_MASK 0x07 /* 00000111 */
+#define FIVE_OCTET_BASE 0xF8 /* 111110xx */
+#define FIVE_OCTET_MASK 0x03 /* 00000011 */
+#define SIX_OCTET_BASE 0xFC /* 1111110x */
+#define SIX_OCTET_MASK 0x01 /* 00000001 */
+
+#define IS_UTF8_1ST_OF_1(x) (( (x)&~ONE_OCTET_MASK ) == ONE_OCTET_BASE)
+#define IS_UTF8_1ST_OF_2(x) (( (x)&~TWO_OCTET_MASK ) == TWO_OCTET_BASE)
+#define IS_UTF8_1ST_OF_3(x) (( (x)&~THREE_OCTET_MASK) == THREE_OCTET_BASE)
+#define IS_UTF8_1ST_OF_4(x) (( (x)&~FOUR_OCTET_MASK ) == FOUR_OCTET_BASE)
+#define IS_UTF8_1ST_OF_5(x) (( (x)&~FIVE_OCTET_MASK ) == FIVE_OCTET_BASE)
+#define IS_UTF8_1ST_OF_6(x) (( (x)&~SIX_OCTET_MASK ) == SIX_OCTET_BASE)
+#define IS_UTF8_2ND_THRU_6TH(x) \
+ (( (x)&~CONTINUING_OCTET_MASK ) == CONTINUING_OCTET_BASE)
+#define IS_UTF8_1ST_OF_UCS2(x) \
+ IS_UTF8_1ST_OF_1(x) \
+ || IS_UTF8_1ST_OF_2(x) \
+ || IS_UTF8_1ST_OF_3(x)
+
+
+#define MAX_UCS2 0xFFFF
+#define DEFAULT_CHAR 0x003F /* Default char is "?" */
+#define BYTE_MASK 0xBF
+#define BYTE_MARK 0x80
+
+
+/* Function: one_ucs2_to_utf8_char
+ *
+ * Function takes one UCS-2 char and writes it to a UTF-8 buffer.
+ * We need a UTF-8 buffer because we don't know before this
+ * function how many bytes of utf-8 data will be written. It also
+ * takes a pointer to the end of the UTF-8 buffer so that we don't
+ * overwrite data. This function returns the number of UTF-8 bytes
+ * of data written, or -1 if the buffer would have been overrun.
+ */
+
+#define LINE_SEPARATOR 0x2028
+#define PARAGRAPH_SEPARATOR 0x2029
+static int16 one_ucs2_to_utf8_char(unsigned char *tobufp,
+ unsigned char *tobufendp,
+ uint16 onechar)
+{
+ int16 numUTF8bytes = 0;
+
+ if (onechar == LINE_SEPARATOR || onechar == PARAGRAPH_SEPARATOR) {
+ strcpy((char*)tobufp, "\n");
+ return strlen((char*)tobufp);
+ }
+
+ if (onechar < 0x80) {
+ numUTF8bytes = 1;
+ } else if (onechar < 0x800) {
+ numUTF8bytes = 2;
+ } else {
+ /* 0x800 >= onechar <= MAX_UCS2 */
+ numUTF8bytes = 3;
+ }
+
+ tobufp += numUTF8bytes;
+
+ /* return error if we don't have space for the whole character */
+ if (tobufp > tobufendp) {
+ return(-1);
+ }
+
+ switch(numUTF8bytes) {
+ case 3: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
+ *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
+ *--tobufp = onechar | THREE_OCTET_BASE;
+ break;
+
+ case 2: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
+ *--tobufp = onechar | TWO_OCTET_BASE;
+ break;
+
+ case 1: *--tobufp = (unsigned char)onechar;
+ break;
+ }
+
+ return numUTF8bytes;
+}
+
+/*
+ * utf8_to_ucs2_char
+ *
+ * Convert a utf8 multibyte character to ucs2
+ *
+ * inputs: pointer to utf8 character(s)
+ * length of utf8 buffer ("read" length limit)
+ * pointer to return ucs2 character
+ *
+ * outputs: number of bytes in the utf8 character
+ * -1 if not a valid utf8 character sequence
+ * -2 if the buffer is too short
+ */
+static int16
+utf8_to_ucs2_char(const unsigned char *utf8p, int16 buflen, uint16 *ucs2p)
+{
+ uint16 lead, cont1, cont2;
+
+ /*
+ * Check for minimum buffer length
+ */
+ if ((buflen < 1) || (utf8p == NULL)) {
+ return -2;
+ }
+ lead = (uint16) (*utf8p);
+
+ /*
+ * Check for a one octet sequence
+ */
+ if (IS_UTF8_1ST_OF_1(lead)) {
+ *ucs2p = lead & ONE_OCTET_MASK;
+ return 1;
+ }
+
+ /*
+ * Check for a two octet sequence
+ */
+ if (IS_UTF8_1ST_OF_2(*utf8p)) {
+ if (buflen < 2)
+ return -2;
+ cont1 = (uint16) *(utf8p+1);
+ if (!IS_UTF8_2ND_THRU_6TH(cont1))
+ return -1;
+ *ucs2p = (lead & TWO_OCTET_MASK) << 6;
+ *ucs2p |= cont1 & CONTINUING_OCTET_MASK;
+ return 2;
+ }
+
+ /*
+ * Check for a three octet sequence
+ */
+ else if (IS_UTF8_1ST_OF_3(lead)) {
+ if (buflen < 3)
+ return -2;
+ cont1 = (uint16) *(utf8p+1);
+ cont2 = (uint16) *(utf8p+2);
+ if ( (!IS_UTF8_2ND_THRU_6TH(cont1))
+ || (!IS_UTF8_2ND_THRU_6TH(cont2)))
+ return -1;
+ *ucs2p = (lead & THREE_OCTET_MASK) << 12;
+ *ucs2p |= (cont1 & CONTINUING_OCTET_MASK) << 6;
+ *ucs2p |= cont2 & CONTINUING_OCTET_MASK;
+ return 3;
+ }
+ else { /* not a valid utf8/ucs2 character */
+ return -1;
+ }
+}
+
+/* ----------------------------- Helper functions --------------------------- */
+/* Ripped off from lm_win.c .. */
+/* where is strcasecmp?.. for now, it's case sensitive..
+ *
+ * strcasecmp is in strings.h, but on windows it's called _stricmp...
+ * will need to #ifdef this
+*/
+
+static int32
+js_FileHasOption(JSContext *cx, const char *oldoptions, const char *name)
+{
+ char *comma, *equal, *current;
+ char *options = JS_strdup(cx, oldoptions);
+ int32 found = 0;
+
+ current = options;
+ for (;;) {
+ comma = strchr(current, ',');
+ if (comma) *comma = '\0';
+ equal = strchr(current, '=');
+ if (equal) *equal = '\0';
+ if (strcmp(current, name) == 0) {
+ if (!equal || strcmp(equal + 1, "yes") == 0)
+ found = 1;
+ else
+ found = atoi(equal + 1);
+ }
+ if (equal) *equal = '=';
+ if (comma) *comma = ',';
+ if (found || !comma)
+ break;
+ current = comma + 1;
+ }
+ JS_free(cx, options);
+ return found;
+}
+
+/* empty the buffer */
+static void
+js_ResetBuffers(JSFile * file)
+{
+ file->charBufferUsed = JS_FALSE;
+ file->nbBytesInBuf = 0;
+}
+
+/* Reset file attributes */
+static void
+js_ResetAttributes(JSFile * file)
+{
+ file->mode = file->type = 0;
+ file->isOpen = JS_FALSE;
+ file->handle = NULL;
+ file->nativehandle = NULL;
+ file->hasRandomAccess = JS_TRUE; /* Innocent until proven guilty. */
+ file->hasAutoflush = JS_FALSE;
+ file->isNative = JS_FALSE;
+ file->isPipe = JS_FALSE;
+
+ js_ResetBuffers(file);
+}
+
+static JSBool
+js_FileOpen(JSContext *cx, JSObject *obj, JSFile *file, char *mode){
+ JSString *type, *mask;
+ jsval v[2];
+ jsval rval;
+
+ type = JS_InternString(cx, asciistring);
+ mask = JS_NewStringCopyZ(cx, mode);
+ v[0] = STRING_TO_JSVAL(mask);
+ v[1] = STRING_TO_JSVAL(type);
+
+ if (!file_open(cx, obj, 2, v, &rval))
+ return JS_FALSE;
+ return JS_TRUE;
+}
+
+/* Buffered version of PR_Read. Used by js_FileRead */
+static int32
+js_BufferedRead(JSFile *f, unsigned char *buf, int32 len)
+{
+ int32 count = 0;
+
+ while (f->nbBytesInBuf>0&&len>0) {
+ buf[0] = f->byteBuffer[0];
+ f->byteBuffer[0] = f->byteBuffer[1];
+ f->byteBuffer[1] = f->byteBuffer[2];
+ f->nbBytesInBuf--;
+ len--;
+ buf+=1;
+ count++;
+ }
+
+ if (len > 0) {
+ count += (!f->isNative)
+ ? PR_Read(f->handle, buf, len)
+ : fread(buf, 1, len, f->nativehandle);
+ }
+ return count;
+}
+
+static int32
+js_FileRead(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
+{
+ unsigned char *aux;
+ int32 count = 0, i;
+ jsint remainder;
+ unsigned char utfbuf[3];
+
+ if (file->charBufferUsed) {
+ buf[0] = file->charBuffer;
+ buf++;
+ len--;
+ file->charBufferUsed = JS_FALSE;
+ }
+
+ switch (mode) {
+ case ASCII:
+ aux = (unsigned char*)JS_malloc(cx, len);
+ if (!aux)
+ return 0;
+
+ count = js_BufferedRead(file, aux, len);
+ if (count == -1) {
+ JS_free(cx, aux);
+ return 0;
+ }
+
+ for (i = 0; i < len; i++)
+ buf[i] = (jschar)aux[i];
+
+ JS_free(cx, aux);
+ break;
+
+ case UTF8:
+ remainder = 0;
+ for (count = 0;count<len;count++) {
+ i = js_BufferedRead(file, utfbuf+remainder, 3-remainder);
+ if (i<=0) {
+ return count;
+ }
+ i = utf8_to_ucs2_char(utfbuf, (int16)i, &buf[count] );
+ if (i<0) {
+ return count;
+ } else {
+ if (i==1) {
+ utfbuf[0] = utfbuf[1];
+ utfbuf[1] = utfbuf[2];
+ remainder = 2;
+ } else if (i==2) {
+ utfbuf[0] = utfbuf[2];
+ remainder = 1;
+ } else if (i==3) {
+ remainder = 0;
+ }
+ }
+ }
+ while (remainder>0) {
+ file->byteBuffer[file->nbBytesInBuf] = utfbuf[0];
+ file->nbBytesInBuf++;
+ utfbuf[0] = utfbuf[1];
+ utfbuf[1] = utfbuf[2];
+ remainder--;
+ }
+ break;
+
+ case UCS2:
+ count = js_BufferedRead(file, (unsigned char *)buf, len * 2) >> 1;
+ if (count == -1)
+ return 0;
+
+ break;
+
+ default:
+ /* Not reached. */
+ JS_ASSERT(0);
+ }
+
+ if(count == -1) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "read", file->path);
+ }
+
+ return count;
+}
+
+static int32
+js_FileSeek(JSContext *cx, JSFile *file, int32 len, int32 mode)
+{
+ int32 count = 0, i;
+ jsint remainder;
+ unsigned char utfbuf[3];
+ jschar tmp;
+
+ switch (mode) {
+ case ASCII:
+ count = PR_Seek(file->handle, len, PR_SEEK_CUR);
+ break;
+
+ case UTF8:
+ remainder = 0;
+ for (count = 0;count<len;count++) {
+ i = js_BufferedRead(file, utfbuf+remainder, 3-remainder);
+ if (i<=0) {
+ return 0;
+ }
+ i = utf8_to_ucs2_char(utfbuf, (int16)i, &tmp );
+ if (i<0) {
+ return 0;
+ } else {
+ if (i==1) {
+ utfbuf[0] = utfbuf[1];
+ utfbuf[1] = utfbuf[2];
+ remainder = 2;
+ } else if (i==2) {
+ utfbuf[0] = utfbuf[2];
+ remainder = 1;
+ } else if (i==3) {
+ remainder = 0;
+ }
+ }
+ }
+ while (remainder>0) {
+ file->byteBuffer[file->nbBytesInBuf] = utfbuf[0];
+ file->nbBytesInBuf++;
+ utfbuf[0] = utfbuf[1];
+ utfbuf[1] = utfbuf[2];
+ remainder--;
+ }
+ break;
+
+ case UCS2:
+ count = PR_Seek(file->handle, len*2, PR_SEEK_CUR)/2;
+ break;
+
+ default:
+ /* Not reached. */
+ JS_ASSERT(0);
+ }
+
+ if(count == -1) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "seek", file->path);
+ }
+
+ return count;
+}
+
+static int32
+js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
+{
+ unsigned char *aux;
+ int32 count = 0, i, j;
+ unsigned char *utfbuf;
+
+ switch (mode) {
+ case ASCII:
+ aux = (unsigned char*)JS_malloc(cx, len);
+ if (!aux)
+ return 0;
+
+ for (i = 0; i<len; i++)
+ aux[i] = buf[i] % 256;
+
+ count = (!file->isNative)
+ ? PR_Write(file->handle, aux, len)
+ : fwrite(aux, 1, len, file->nativehandle);
+
+ if (count==-1) {
+ JS_free(cx, aux);
+ return 0;
+ }
+
+ JS_free(cx, aux);
+ break;
+
+ case UTF8:
+ utfbuf = (unsigned char*)JS_malloc(cx, len*3);
+ if (!utfbuf) return 0;
+ i = 0;
+ for (count = 0;count<len;count++) {
+ j = one_ucs2_to_utf8_char(utfbuf+i, utfbuf+len*3, buf[count]);
+ if (j==-1) {
+ JS_free(cx, utfbuf);
+ return 0;
+ }
+ i+=j;
+ }
+ j = (!file->isNative)
+ ? PR_Write(file->handle, utfbuf, i)
+ : fwrite(utfbuf, 1, i, file->nativehandle);
+
+ if (j<i) {
+ JS_free(cx, utfbuf);
+ return 0;
+ }
+ JS_free(cx, utfbuf);
+ break;
+
+ case UCS2:
+ count = (!file->isNative)
+ ? PR_Write(file->handle, buf, len*2) >> 1
+ : fwrite(buf, 1, len*2, file->nativehandle) >> 1;
+
+ if (count == -1)
+ return 0;
+ break;
+
+ default:
+ /* Not reached. */
+ JS_ASSERT(0);
+ }
+
+ if(count == -1) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "write", file->path);
+ }
+
+ return count;
+}
+
+/* ----------------------------- Property checkers -------------------------- */
+static JSBool
+js_exists(JSContext *cx, JSFile *file)
+{
+ if (file->isNative) {
+ /* It doesn't make sense for a pipe of stdstream. */
+ return JS_FALSE;
+ }
+
+ return PR_Access(file->path, PR_ACCESS_EXISTS) == PR_SUCCESS;
+}
+
+static JSBool
+js_canRead(JSContext *cx, JSFile *file)
+{
+ if (!file->isNative) {
+ if (file->isOpen && !(file->mode & PR_RDONLY))
+ return JS_FALSE;
+ return PR_Access(file->path, PR_ACCESS_READ_OK) == PR_SUCCESS;
+ }
+
+ if (file->isPipe) {
+ /* Is this pipe open for reading? */
+ return file->path[0] == PIPE_SYMBOL;
+ }
+
+ return !strcmp(file->path, STDINPUT_NAME);
+}
+
+static JSBool
+js_canWrite(JSContext *cx, JSFile *file)
+{
+ if (!file->isNative) {
+ if (file->isOpen && !(file->mode & PR_WRONLY))
+ return JS_FALSE;
+ return PR_Access(file->path, PR_ACCESS_WRITE_OK) == PR_SUCCESS;
+ }
+
+ if(file->isPipe) {
+ /* Is this pipe open for writing? */
+ return file->path[strlen(file->path)-1] == PIPE_SYMBOL;
+ }
+
+ return !strcmp(file->path, STDOUTPUT_NAME) ||
+ !strcmp(file->path, STDERROR_NAME);
+}
+
+static JSBool
+js_isFile(JSContext *cx, JSFile *file)
+{
+ if (!file->isNative) {
+ PRFileInfo info;
+
+ if (file->isOpen
+ ? PR_GetOpenFileInfo(file->handle, &info)
+ : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
+ return JS_FALSE;
+ }
+
+ return info.type == PR_FILE_FILE;
+ }
+
+ /* This doesn't make sense for a pipe of stdstream. */
+ return JS_FALSE;
+}
+
+static JSBool
+js_isDirectory(JSContext *cx, JSFile *file)
+{
+ if(!file->isNative){
+ PRFileInfo info;
+
+ /* Hack needed to get get_property to work. */
+ if (!js_exists(cx, file))
+ return JS_FALSE;
+
+ if (file->isOpen
+ ? PR_GetOpenFileInfo(file->handle, &info)
+ : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
+ return JS_FALSE;
+ }
+
+ return info.type == PR_FILE_DIRECTORY;
+ }
+
+ /* This doesn't make sense for a pipe of stdstream. */
+ return JS_FALSE;
+}
+
+static jsval
+js_size(JSContext *cx, JSFile *file)
+{
+ PRFileInfo info;
+
+ JSFILE_CHECK_NATIVE("size");
+
+ if (file->isOpen
+ ? PR_GetOpenFileInfo(file->handle, &info)
+ : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
+ return JSVAL_VOID;
+ }
+
+ return INT_TO_JSVAL(info.size);
+
+out:
+ return JSVAL_VOID;
+}
+
+/*
+ * Return the parent object
+ */
+static JSBool
+js_parent(JSContext *cx, JSFile *file, jsval *resultp)
+{
+ char *str;
+
+ /* Since we only care about pipes and native files, return NULL. */
+ if (file->isNative) {
+ *resultp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ str = js_fileDirectoryName(cx, file->path);
+ if (!str)
+ return JS_FALSE;
+
+ /* If the directory is equal to the original path, we're at the root. */
+ if (!strcmp(file->path, str)) {
+ *resultp = JSVAL_NULL;
+ } else {
+ JSObject *obj = js_NewFileObject(cx, str);
+ if (!obj) {
+ JS_free(cx, str);
+ return JS_FALSE;
+ }
+ *resultp = OBJECT_TO_JSVAL(obj);
+ }
+
+ JS_free(cx, str);
+ return JS_TRUE;
+}
+
+static JSBool
+js_name(JSContext *cx, JSFile *file, jsval *vp)
+{
+ char *name;
+ JSString *str;
+
+ if (file->isPipe) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ name = js_fileBaseName(cx, file->path);
+ if (!name)
+ return JS_FALSE;
+
+ str = JS_NewString(cx, name, strlen(name));
+ if (!str) {
+ JS_free(cx, name);
+ return JS_FALSE;
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+/* ------------------------------ File object methods ---------------------------- */
+static JSBool
+file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *strmode, *strtype;
+ char *ctype, *mode;
+ int32 mask, type;
+ int len;
+
+ mode = NULL;
+
+ SECURITY_CHECK(cx, NULL, "open", file);
+
+ /* A native file that is already open */
+ if(file->isOpen && file->isNative) {
+ JS_ReportWarning(cx, "Native file %s is already open, proceeding",
+ file->path);
+ goto good;
+ }
+
+ /* Close before proceeding */
+ if (file->isOpen) {
+ JS_ReportWarning(cx, "File %s is already open, we will close it and "
+ "reopen, proceeding", file->path);
+ if(!file_close(cx, obj, 0, NULL, rval))
+ goto out;
+ }
+
+ if (js_isDirectory(cx, file)) {
+ JS_ReportWarning(cx, "%s seems to be a directory, there is no point in "
+ "trying to open it, proceeding", file->path);
+ goto good;
+ }
+
+ /* Path must be defined at this point */
+ len = strlen(file->path);
+
+ /* Mode */
+ if (argc >= 1) {
+ strmode = JS_ValueToString(cx, argv[0]);
+ if (!strmode) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR,
+ argv[0]);
+ goto out;
+ }
+ mode = JS_strdup(cx, JS_GetStringBytes(strmode));
+ } else {
+ if(file->path[0]==PIPE_SYMBOL) {
+ /* pipe default mode */
+ mode = JS_strdup(cx, "read");
+ } else if(file->path[len-1]==PIPE_SYMBOL) {
+ /* pipe default mode */
+ mode = JS_strdup(cx, "write");
+ } else {
+ /* non-destructive, permissive defaults. */
+ mode = JS_strdup(cx, "readWrite,append,create");
+ }
+ }
+
+ /* Process the mode */
+ mask = 0;
+ /* TODO: this is pretty ugly, we walk thru the string too many times */
+ mask |= js_FileHasOption(cx, mode, "read") ? PR_RDONLY : 0;
+ mask |= js_FileHasOption(cx, mode, "write") ? PR_WRONLY : 0;
+ mask |= js_FileHasOption(cx, mode, "readWrite")? PR_RDWR : 0;
+ mask |= js_FileHasOption(cx, mode, "append") ? PR_APPEND : 0;
+ mask |= js_FileHasOption(cx, mode, "create") ? PR_CREATE_FILE : 0;
+ mask |= js_FileHasOption(cx, mode, "replace") ? PR_TRUNCATE : 0;
+
+ if (mask & PR_RDWR)
+ mask |= (PR_RDONLY | PR_WRONLY);
+ if ((mask & PR_RDONLY) && (mask & PR_WRONLY))
+ mask |= PR_RDWR;
+
+ file->hasAutoflush |= js_FileHasOption(cx, mode, "autoflush");
+
+ /* Type */
+ if (argc > 1) {
+ strtype = JS_ValueToString(cx, argv[1]);
+ if (!strtype) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR,
+ argv[1]);
+ goto out;
+ }
+ ctype = JS_GetStringBytes(strtype);
+
+ if(!strcmp(ctype, utfstring)) {
+ type = UTF8;
+ } else if (!strcmp(ctype, unicodestring)) {
+ type = UCS2;
+ } else {
+ if (strcmp(ctype, asciistring)) {
+ JS_ReportWarning(cx, "File type %s is not supported, using "
+ "'text' instead, proceeding", ctype);
+ }
+ type = ASCII;
+ }
+ } else {
+ type = ASCII;
+ }
+
+ /* Save the relevant fields */
+ file->type = type;
+ file->mode = mask;
+ file->nativehandle = NULL;
+ file->hasRandomAccess = (type != UTF8);
+
+ /*
+ * Deal with pipes here. We can't use NSPR for pipes, so we have to use
+ * POPEN.
+ */
+ if (file->path[0]==PIPE_SYMBOL || file->path[len-1]==PIPE_SYMBOL) {
+ if (file->path[0] == PIPE_SYMBOL && file->path[len-1] == PIPE_SYMBOL) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED);
+ goto out;
+ } else {
+ int i = 0;
+ char pipemode[3];
+ SECURITY_CHECK(cx, NULL, "pipe_open", file);
+
+ if(file->path[0] == PIPE_SYMBOL){
+ if(mask & (PR_WRONLY | PR_APPEND | PR_CREATE_FILE | PR_TRUNCATE)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OPEN_MODE_NOT_SUPPORTED_WITH_PIPES,
+ mode, file->path);
+ goto out;
+ }
+ /* open(SPOOLER, "| cat -v | lpr -h 2>/dev/null") -- pipe for writing */
+ pipemode[i++] = 'r';
+#ifndef XP_UNIX
+ pipemode[i++] = file->type==UTF8 ? 'b' : 't';
+#endif
+ pipemode[i++] = '\0';
+ file->nativehandle = POPEN(&file->path[1], pipemode);
+ } else if(file->path[len-1] == PIPE_SYMBOL) {
+ char *command = JS_malloc(cx, len);
+
+ strncpy(command, file->path, len-1);
+ command[len-1] = '\0';
+ /* open(STATUS, "netstat -an 2>&1 |") */
+ pipemode[i++] = 'w';
+#ifndef XP_UNIX
+ pipemode[i++] = file->type==UTF8 ? 'b' : 't';
+#endif
+ pipemode[i++] = '\0';
+ file->nativehandle = POPEN(command, pipemode);
+ JS_free(cx, command);
+ }
+ /* set the flags */
+ file->isNative = JS_TRUE;
+ file->isPipe = JS_TRUE;
+ file->hasRandomAccess = JS_FALSE;
+ }
+ } else {
+ /* TODO: what about the permissions?? Java ignores the problem... */
+ file->handle = PR_Open(file->path, mask, 0644);
+ }
+
+ js_ResetBuffers(file);
+ JS_free(cx, mode);
+ mode = NULL;
+
+ /* Set the open flag and return result */
+ if (file->handle == NULL && file->nativehandle == NULL) {
+ file->isOpen = JS_FALSE;
+
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "open", file->path);
+ goto out;
+ }
+
+good:
+ file->isOpen = JS_TRUE;
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+
+out:
+ if(mode)
+ JS_free(cx, mode);
+ return JS_FALSE;
+}
+
+static JSBool
+file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ SECURITY_CHECK(cx, NULL, "close", file);
+
+ if(!file->isOpen){
+ JS_ReportWarning(cx, "File %s is not open, can't close it, proceeding",
+ file->path);
+ goto out;
+ }
+
+ if(!file->isPipe){
+ if(file->isNative){
+ JS_ReportWarning(cx, "Unable to close a native file, proceeding", file->path);
+ goto out;
+ }else{
+ if(file->handle && PR_Close(file->handle)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "close", file->path);
+
+ goto out;
+ }
+ }
+ }else{
+ if(PCLOSE(file->nativehandle)==-1){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "pclose", file->path);
+ goto out;
+ }
+ }
+
+ js_ResetAttributes(file);
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+
+out:
+ return JS_FALSE;
+}
+
+
+static JSBool
+file_remove(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ SECURITY_CHECK(cx, NULL, "remove", file);
+ JSFILE_CHECK_NATIVE("remove");
+ JSFILE_CHECK_CLOSED("remove");
+
+ if ((js_isDirectory(cx, file) ?
+ PR_RmDir(file->path) : PR_Delete(file->path))==PR_SUCCESS) {
+ js_ResetAttributes(file);
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+ } else {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "remove", file->path);
+ goto out;
+ }
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+/* Raw PR-based function. No text processing. Just raw data copying. */
+static JSBool
+file_copyTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ char *dest = NULL;
+ PRFileDesc *handle = NULL;
+ char *buffer;
+ jsval count, size;
+ JSBool fileInitiallyOpen=JS_FALSE;
+
+ SECURITY_CHECK(cx, NULL, "copyTo", file); /* may need a second argument!*/
+ JSFILE_CHECK_ONE_ARG("copyTo");
+ JSFILE_CHECK_NATIVE("copyTo");
+ /* remeber the state */
+ fileInitiallyOpen = file->isOpen;
+ JSFILE_CHECK_READ;
+
+ dest = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
+
+ /* make sure we are not reading a file open for writing */
+ if (file->isOpen && !js_canRead(cx, file)) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_COPY_FILE_OPEN_FOR_WRITING_ERROR, file->path);
+ goto out;
+ }
+
+ if (file->handle==NULL){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "open", file->path);
+ goto out;
+ }
+
+ handle = PR_Open(dest, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0644);
+
+ if(!handle){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "open", dest);
+ goto out;
+ }
+
+ if ((size=js_size(cx, file))==JSVAL_VOID) {
+ goto out;
+ }
+
+ buffer = JS_malloc(cx, size);
+
+ count = INT_TO_JSVAL(PR_Read(file->handle, buffer, size));
+
+ /* reading panic */
+ if (count!=size) {
+ JS_free(cx, buffer);
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_COPY_READ_ERROR, file->path);
+ goto out;
+ }
+
+ count = INT_TO_JSVAL(PR_Write(handle, buffer, JSVAL_TO_INT(size)));
+
+ /* writing panic */
+ if (count!=size) {
+ JS_free(cx, buffer);
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_COPY_WRITE_ERROR, file->path);
+ goto out;
+ }
+
+ JS_free(cx, buffer);
+
+ if(!fileInitiallyOpen){
+ if(!file_close(cx, obj, 0, NULL, rval)) goto out;
+ }
+
+ if(PR_Close(handle)!=PR_SUCCESS){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "close", dest);
+ goto out;
+ }
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+out:
+ if(file->isOpen && !fileInitiallyOpen){
+ if(PR_Close(file->handle)!=PR_SUCCESS){
+ JS_ReportWarning(cx, "Can't close %s, proceeding", file->path);
+ }
+ }
+
+ if(handle && PR_Close(handle)!=PR_SUCCESS){
+ JS_ReportWarning(cx, "Can't close %s, proceeding", dest);
+ }
+
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_renameTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ char *dest;
+
+ SECURITY_CHECK(cx, NULL, "renameTo", file); /* may need a second argument!*/
+ JSFILE_CHECK_ONE_ARG("renameTo");
+ JSFILE_CHECK_NATIVE("renameTo");
+ JSFILE_CHECK_CLOSED("renameTo");
+
+ dest = RESOLVE_PATH(cx, JS_GetStringBytes(JS_ValueToString(cx, argv[0])));
+
+ if (PR_Rename(file->path, dest)==PR_SUCCESS){
+ /* copy the new filename */
+ JS_free(cx, file->path);
+ file->path = dest;
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_RENAME_FAILED, file->path, dest);
+ goto out;
+ }
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_flush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ SECURITY_CHECK(cx, NULL, "flush", file);
+ JSFILE_CHECK_NATIVE("flush");
+ JSFILE_CHECK_OPEN("flush");
+
+ if (PR_Sync(file->handle)==PR_SUCCESS){
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "flush", file->path);
+ goto out;
+ }
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *str;
+ int32 count;
+ uintN i;
+
+ SECURITY_CHECK(cx, NULL, "write", file);
+ JSFILE_CHECK_WRITE;
+
+ for (i = 0; i<argc; i++) {
+ str = JS_ValueToString(cx, argv[i]);
+ count = js_FileWrite(cx, file, JS_GetStringChars(str),
+ JS_GetStringLength(str), file->type);
+ if (count==-1){
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+ }
+ }
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *str;
+
+ SECURITY_CHECK(cx, NULL, "writeln", file);
+ JSFILE_CHECK_WRITE;
+
+ /* don't report an error here */
+ if(!file_write(cx, obj, argc, argv, rval)) return JS_FALSE;
+ /* don't do security here -- we passed the check in file_write */
+ str = JS_NewStringCopyZ(cx, "\n");
+
+ if (js_FileWrite(cx, file, JS_GetStringChars(str), JS_GetStringLength(str),
+ file->type)==-1){
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+ }
+
+ /* eol causes flush if hasAutoflush is turned on */
+ if (file->hasAutoflush)
+ file_flush(cx, obj, 0, NULL, rval);
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_writeAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ jsuint i;
+ jsuint limit;
+ JSObject *array;
+ JSObject *elem;
+ jsval elemval;
+
+ SECURITY_CHECK(cx, NULL, "writeAll", file);
+ JSFILE_CHECK_ONE_ARG("writeAll");
+ JSFILE_CHECK_WRITE;
+
+ if (!JS_IsArrayObject(cx, JSVAL_TO_OBJECT(argv[0]))) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_WRITEALL_NOT_ARRAY_ERROR);
+ goto out;
+ }
+
+ array = JSVAL_TO_OBJECT(argv[0]);
+
+ JS_GetArrayLength(cx, array, &limit);
+
+ for (i = 0; i<limit; i++) {
+ if (!JS_GetElement(cx, array, i, &elemval)) return JS_FALSE;
+ elem = JSVAL_TO_OBJECT(elemval);
+ file_writeln(cx, obj, 1, &elemval, rval);
+ }
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *str;
+ int32 want, count;
+ jschar *buf;
+
+ SECURITY_CHECK(cx, NULL, "read", file);
+ JSFILE_CHECK_ONE_ARG("read");
+ JSFILE_CHECK_READ;
+
+ if (!JS_ValueToInt32(cx, argv[0], &want)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "read", argv[0]);
+ goto out;
+ }
+
+ /* want = (want>262144)?262144:want; * arbitrary size limitation */
+
+ buf = JS_malloc(cx, want*sizeof buf[0]);
+ if (!buf) goto out;
+
+ count = js_FileRead(cx, file, buf, want, file->type);
+ if (count>0) {
+ str = JS_NewUCStringCopyN(cx, buf, count);
+ *rval = STRING_TO_JSVAL(str);
+ JS_free(cx, buf);
+ return JS_TRUE;
+ } else {
+ JS_free(cx, buf);
+ goto out;
+ }
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *str;
+ jschar *buf = NULL, *tmp;
+ int32 offset, read;
+ intN room;
+ jschar data, data2;
+
+ SECURITY_CHECK(cx, NULL, "readln", file);
+ JSFILE_CHECK_READ;
+
+ buf = JS_malloc(cx, MAX_LINE_LENGTH * sizeof data);
+ if (!buf)
+ return JS_FALSE;
+
+ room = MAX_LINE_LENGTH - 1;
+ offset = 0;
+
+ for (;;) {
+ read = js_FileRead(cx, file, &data, 1, file->type);
+ if (read < 0)
+ goto out;
+ if (read == 0)
+ goto eof;
+
+ switch (data) {
+ case '\r':
+ read = js_FileRead(cx, file, &data2, 1, file->type);
+ if (read < 0)
+ goto out;
+
+ if (read == 1 && data2 != '\n') {
+ /* We read one char too far. Buffer it. */
+ file->charBuffer = data2;
+ file->charBufferUsed = JS_TRUE;
+ }
+
+ /* Fall through. */
+ case '\n':
+ goto done;
+
+ default:
+ if (--room < 0) {
+ tmp = JS_realloc(cx, buf,
+ (offset + MAX_LINE_LENGTH) * sizeof data);
+ if (!tmp)
+ goto out;
+
+ room = MAX_LINE_LENGTH - 1;
+ buf = tmp;
+ }
+
+ buf[offset++] = data;
+ break;
+ }
+ }
+
+eof:
+ if (offset == 0) {
+ *rval = JSVAL_NULL;
+ return JS_TRUE;
+ }
+
+done:
+ buf[offset] = 0;
+ tmp = JS_realloc(cx, buf, (offset + 1) * sizeof data);
+ if (!tmp)
+ goto out;
+
+ str = JS_NewUCString(cx, tmp, offset);
+ if (!str)
+ goto out;
+
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+
+out:
+ if (buf)
+ JS_free(cx, buf);
+
+ return JS_FALSE;
+}
+
+static JSBool
+file_readAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSObject *array;
+ jsint len;
+ jsval line;
+ JSBool lineok = JS_FALSE;
+
+ SECURITY_CHECK(cx, NULL, "readAll", file);
+ JSFILE_CHECK_READ;
+
+ array = JS_NewArrayObject(cx, 0, NULL);
+ if (!array)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(array);
+
+ len = 0;
+
+ lineok = file_readln(cx, obj, 0, NULL, &line);
+ while (lineok && !JSVAL_IS_NULL(line)) {
+ JS_SetElement(cx, array, len++, &line);
+ lineok = file_readln(cx, obj, 0, NULL, &line);
+ }
+
+out:
+ return lineok;
+}
+
+static JSBool
+file_seek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ int32 toskip;
+ int32 pos;
+
+ SECURITY_CHECK(cx, NULL, "seek", file);
+ JSFILE_CHECK_ONE_ARG("seek");
+ JSFILE_CHECK_NATIVE("seek");
+ JSFILE_CHECK_READ;
+
+ if (!JS_ValueToInt32(cx, argv[0], &toskip)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "seek", argv[0]);
+ goto out;
+ }
+
+ if(!file->hasRandomAccess){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_NO_RANDOM_ACCESS, file->path);
+ goto out;
+ }
+
+ if(js_isDirectory(cx, file)){
+ JS_ReportWarning(cx,"Seek on directories is not supported, proceeding");
+ goto out;
+ }
+
+ pos = js_FileSeek(cx, file, toskip, file->type);
+
+ if (pos!=-1) {
+ *rval = INT_TO_JSVAL(pos);
+ return JS_TRUE;
+ }
+out:
+ *rval = JSVAL_VOID;
+ return JS_FALSE;
+}
+
+static JSBool
+file_list(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ PRDir *dir;
+ PRDirEntry *entry;
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSObject *array;
+ JSObject *eachFile;
+ jsint len;
+ jsval v;
+ JSRegExp *re = NULL;
+ JSFunction *func = NULL;
+ JSString *str;
+ jsval args[1];
+ char *filePath;
+
+ SECURITY_CHECK(cx, NULL, "list", file);
+ JSFILE_CHECK_NATIVE("list");
+
+ if (argc==1) {
+ if (VALUE_IS_REGEXP(cx, argv[0])) {
+ re = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ }else
+ if (VALUE_IS_FUNCTION(cx, argv[0])) {
+ func = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_FUNCTION_OR_REGEX, argv[0]);
+ goto out;
+ }
+ }
+
+ if (!js_isDirectory(cx, file)) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_DO_LIST_ON_A_FILE, file->path);
+ goto out;
+ }
+
+ dir = PR_OpenDir(file->path);
+ if(!dir){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "open", file->path);
+ goto out;
+ }
+
+ /* create JSArray here... */
+ array = JS_NewArrayObject(cx, 0, NULL);
+ len = 0;
+
+ while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))!=NULL) {
+ /* first, check if we have a regexp */
+ if (re!=NULL) {
+ size_t index = 0;
+
+ str = JS_NewStringCopyZ(cx, entry->name);
+ if(!js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, &v)){
+ /* don't report anything here */
+ goto out;
+ }
+ /* not matched! */
+ if (JSVAL_IS_NULL(v)) {
+ continue;
+ }
+ }else
+ if (func!=NULL) {
+ str = JS_NewStringCopyZ(cx, entry->name);
+ args[0] = STRING_TO_JSVAL(str);
+ if(!JS_CallFunction(cx, obj, func, 1, args, &v)){
+ goto out;
+ }
+
+ if (v==JSVAL_FALSE) {
+ continue;
+ }
+ }
+
+ filePath = js_combinePath(cx, file->path, (char*)entry->name);
+
+ eachFile = js_NewFileObject(cx, filePath);
+ JS_free(cx, filePath);
+ if (!eachFile){
+ JS_ReportWarning(cx, "File %s cannot be retrieved", filePath);
+ continue;
+ }
+ v = OBJECT_TO_JSVAL(eachFile);
+ JS_SetElement(cx, array, len, &v);
+ JS_SetProperty(cx, array, entry->name, &v);
+ len++;
+ }
+
+ if(PR_CloseDir(dir)!=PR_SUCCESS){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "close", file->path);
+ goto out;
+ }
+ *rval = OBJECT_TO_JSVAL(array);
+ return JS_TRUE;
+out:
+ *rval = JSVAL_NULL;
+ return JS_FALSE;
+}
+
+static JSBool
+file_mkdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ SECURITY_CHECK(cx, NULL, "mkdir", file);
+ JSFILE_CHECK_ONE_ARG("mkdir");
+ JSFILE_CHECK_NATIVE("mkdir");
+
+ /* if the current file is not a directory, find out the directory name */
+ if (!js_isDirectory(cx, file)) {
+ char *dir = js_fileDirectoryName(cx, file->path);
+ JSObject *dirObj = js_NewFileObject(cx, dir);
+
+ JS_free(cx, dir);
+
+ /* call file_mkdir with the right set of parameters if needed */
+ if (file_mkdir(cx, dirObj, argc, argv, rval))
+ return JS_TRUE;
+ else
+ goto out;
+ }else{
+ char *dirName = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
+ char *fullName;
+
+ fullName = js_combinePath(cx, file->path, dirName);
+ if (PR_MkDir(fullName, 0755)==PR_SUCCESS){
+ *rval = JSVAL_TRUE;
+ JS_free(cx, fullName);
+ return JS_TRUE;
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "mkdir", fullName);
+ JS_free(cx, fullName);
+ goto out;
+ }
+ }
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval*rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *str;
+
+ str = JS_NewStringCopyZ(cx, file->path);
+ if (!str)
+ return JS_FALSE;
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+file_toURL(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ char url[MAX_PATH_LENGTH];
+ jschar *urlChars;
+ size_t len;
+ JSString *str;
+
+ JSFILE_CHECK_NATIVE("toURL");
+
+ sprintf(url, "file://%s", file->path);
+
+ len = strlen(url);
+ urlChars = js_InflateString(cx, url, &len);
+ if (!urlChars)
+ return JS_FALSE;
+ str = js_NewString(cx, urlChars, len);
+ if (!str) {
+ JS_free(cx, urlChars);
+ return JS_FALSE;
+ }
+ *rval = STRING_TO_JSVAL(str);
+
+ /* TODO: js_escape in jsstr.h may go away at some point */
+ return js_str_escape(cx, obj, 0, rval, rval);
+
+out:
+ *rval = JSVAL_VOID;
+ return JS_FALSE;
+}
+
+
+static void
+file_finalize(JSContext *cx, JSObject *obj)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ if(file) {
+ /* Close the file before exiting. */
+ if(file->isOpen && !file->isNative) {
+ jsval vp;
+ file_close(cx, obj, 0, NULL, &vp);
+ }
+
+ if (file->path)
+ JS_free(cx, file->path);
+
+ JS_free(cx, file);
+ }
+}
+
+/*
+ Allocates memory for the file object, sets fields to defaults.
+*/
+static JSFile*
+file_init(JSContext *cx, JSObject *obj, char *bytes)
+{
+ JSFile *file;
+
+ file = JS_malloc(cx, sizeof *file);
+ if (!file)
+ return NULL;
+ memset(file, 0 , sizeof *file);
+
+ js_ResetAttributes(file);
+
+ file->path = RESOLVE_PATH(cx, bytes);
+
+ if (!JS_SetPrivate(cx, obj, file)) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_SET_PRIVATE_FILE, file->path);
+ JS_free(cx, file);
+ return NULL;
+ }
+
+ return file;
+}
+
+/* Returns a JSObject. This function is globally visible */
+JS_PUBLIC_API(JSObject*)
+js_NewFileObject(JSContext *cx, char *filename)
+{
+ JSObject *obj;
+ JSFile *file;
+
+ obj = JS_NewObject(cx, &js_FileClass, NULL, NULL);
+ if (!obj){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OBJECT_CREATION_FAILED, "js_NewFileObject");
+ return NULL;
+ }
+ file = file_init(cx, obj, filename);
+ if(!file) return NULL;
+ return obj;
+}
+
+/* Internal function, used for cases which NSPR file support doesn't cover */
+JSObject*
+js_NewFileObjectFromFILE(JSContext *cx, FILE *nativehandle, char *filename,
+ int32 mode, JSBool open, JSBool randomAccess)
+{
+ JSObject *obj;
+ JSFile *file;
+
+ obj = JS_NewObject(cx, &js_FileClass, NULL, NULL);
+ if (!obj){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OBJECT_CREATION_FAILED, "js_NewFileObjectFromFILE");
+ return NULL;
+ }
+ file = file_init(cx, obj, filename);
+ if(!file) return NULL;
+
+ file->nativehandle = nativehandle;
+
+ /* free result of RESOLVE_PATH from file_init. */
+ JS_ASSERT(file->path != NULL);
+ JS_free(cx, file->path);
+
+ file->path = strdup(filename);
+ file->isOpen = open;
+ file->mode = mode;
+ file->hasRandomAccess = randomAccess;
+ file->isNative = JS_TRUE;
+ return obj;
+}
+
+/*
+ Real file constructor that is called from JavaScript.
+ Basically, does error processing and calls file_init.
+*/
+static JSBool
+file_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSString *str;
+ JSFile *file;
+
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ /* Replace obj with a new File object. */
+ obj = JS_NewObject(cx, &js_FileClass, NULL, NULL);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+
+ str = (argc == 0)
+ ? JS_InternString(cx, "")
+ : JS_ValueToString(cx, argv[0]);
+
+ if (!str) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR,
+ argv[0]);
+ return JS_FALSE;
+ }
+
+ file = file_init(cx, obj, JS_GetStringBytes(str));
+ if (!file)
+ return JS_FALSE;
+
+ SECURITY_CHECK(cx, NULL, "constructor", file);
+
+ return JS_TRUE;
+}
+
+/* -------------------- File methods and properties ------------------------- */
+static JSFunctionSpec file_functions[] = {
+ { "open", file_open, 0},
+ { "close", file_close, 0},
+ { "remove", file_remove, 0},
+ { "copyTo", file_copyTo, 0},
+ { "renameTo", file_renameTo, 0},
+ { "flush", file_flush, 0},
+ { "seek", file_seek, 0},
+ { "read", file_read, 0},
+ { "readln", file_readln, 0},
+ { "readAll", file_readAll, 0},
+ { "write", file_write, 0},
+ { "writeln", file_writeln, 0},
+ { "writeAll", file_writeAll, 0},
+ { "list", file_list, 0},
+ { "mkdir", file_mkdir, 0},
+ { "toString", file_toString, 0},
+ { "toURL", file_toURL, 0},
+ {0}
+};
+
+enum file_tinyid {
+ FILE_LENGTH = -2,
+ FILE_PARENT = -3,
+ FILE_PATH = -4,
+ FILE_NAME = -5,
+ FILE_ISDIR = -6,
+ FILE_ISFILE = -7,
+ FILE_EXISTS = -8,
+ FILE_CANREAD = -9,
+ FILE_CANWRITE = -10,
+ FILE_OPEN = -11,
+ FILE_TYPE = -12,
+ FILE_MODE = -13,
+ FILE_CREATED = -14,
+ FILE_MODIFIED = -15,
+ FILE_SIZE = -16,
+ FILE_RANDOMACCESS = -17,
+ FILE_POSITION = -18,
+ FILE_APPEND = -19,
+ FILE_REPLACE = -20,
+ FILE_AUTOFLUSH = -21,
+ FILE_ISNATIVE = -22,
+};
+
+static JSPropertySpec file_props[] = {
+ {"length", FILE_LENGTH, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"parent", FILE_PARENT, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"path", FILE_PATH, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"name", FILE_NAME, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"isDirectory", FILE_ISDIR, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"isFile", FILE_ISFILE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"exists", FILE_EXISTS, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"canRead", FILE_CANREAD, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"canWrite", FILE_CANWRITE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"canAppend", FILE_APPEND, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"canReplace", FILE_REPLACE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"isOpen", FILE_OPEN, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"type", FILE_TYPE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"mode", FILE_MODE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"creationTime", FILE_CREATED, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"lastModified", FILE_MODIFIED, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"size", FILE_SIZE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"hasRandomAccess", FILE_RANDOMACCESS, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"hasAutoFlush", FILE_AUTOFLUSH, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"position", FILE_POSITION, JSPROP_ENUMERATE },
+ {"isNative", FILE_ISNATIVE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {0}
+};
+
+/* ------------------------- Property getter/setter ------------------------- */
+static JSBool
+file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ char *bytes;
+ JSString *str;
+ jsint tiny;
+ PRFileInfo info;
+ JSBool flag;
+ PRExplodedTime expandedTime;
+
+ tiny = JSVAL_TO_INT(id);
+ if (!file)
+ return JS_TRUE;
+
+ switch (tiny) {
+ case FILE_PARENT:
+ SECURITY_CHECK(cx, NULL, "parent", file);
+ if (!js_parent(cx, file, vp))
+ return JS_FALSE;
+ break;
+ case FILE_PATH:
+ str = JS_NewStringCopyZ(cx, file->path);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ break;
+ case FILE_NAME:
+ if (!js_name(cx, file, vp))
+ return JS_FALSE;
+ break;
+ case FILE_ISDIR:
+ SECURITY_CHECK(cx, NULL, "isDirectory", file);
+ *vp = BOOLEAN_TO_JSVAL(js_isDirectory(cx, file));
+ break;
+ case FILE_ISFILE:
+ SECURITY_CHECK(cx, NULL, "isFile", file);
+ *vp = BOOLEAN_TO_JSVAL(js_isFile(cx, file));
+ break;
+ case FILE_EXISTS:
+ SECURITY_CHECK(cx, NULL, "exists", file);
+ *vp = BOOLEAN_TO_JSVAL(js_exists(cx, file));
+ break;
+ case FILE_ISNATIVE:
+ SECURITY_CHECK(cx, NULL, "isNative", file);
+ *vp = BOOLEAN_TO_JSVAL(file->isNative);
+ break;
+ case FILE_CANREAD:
+ SECURITY_CHECK(cx, NULL, "canRead", file);
+ *vp = BOOLEAN_TO_JSVAL(js_canRead(cx, file));
+ break;
+ case FILE_CANWRITE:
+ SECURITY_CHECK(cx, NULL, "canWrite", file);
+ *vp = BOOLEAN_TO_JSVAL(js_canWrite(cx, file));
+ break;
+ case FILE_OPEN:
+ SECURITY_CHECK(cx, NULL, "isOpen", file);
+ *vp = BOOLEAN_TO_JSVAL(file->isOpen);
+ break;
+ case FILE_APPEND :
+ SECURITY_CHECK(cx, NULL, "canAppend", file);
+ JSFILE_CHECK_OPEN("canAppend");
+ *vp = BOOLEAN_TO_JSVAL(!file->isNative &&
+ (file->mode&PR_APPEND)==PR_APPEND);
+ break;
+ case FILE_REPLACE :
+ SECURITY_CHECK(cx, NULL, "canReplace", file);
+ JSFILE_CHECK_OPEN("canReplace");
+ *vp = BOOLEAN_TO_JSVAL(!file->isNative &&
+ (file->mode&PR_TRUNCATE)==PR_TRUNCATE);
+ break;
+ case FILE_AUTOFLUSH :
+ SECURITY_CHECK(cx, NULL, "hasAutoFlush", file);
+ JSFILE_CHECK_OPEN("hasAutoFlush");
+ *vp = BOOLEAN_TO_JSVAL(!file->isNative && file->hasAutoflush);
+ break;
+ case FILE_TYPE:
+ SECURITY_CHECK(cx, NULL, "type", file);
+ JSFILE_CHECK_OPEN("type");
+ if(js_isDirectory(cx, file)){
+ *vp = JSVAL_VOID;
+ break;
+ }
+
+ switch (file->type) {
+ case ASCII:
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, asciistring));
+ break;
+ case UTF8:
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, utfstring));
+ break;
+ case UCS2:
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, unicodestring));
+ break;
+ default:
+ JS_ReportWarning(cx, "Unsupported file type %d, proceeding",
+ file->type);
+ }
+ break;
+ case FILE_MODE:
+ SECURITY_CHECK(cx, NULL, "mode", file);
+ JSFILE_CHECK_OPEN("mode");
+ bytes = JS_malloc(cx, MODE_SIZE);
+ bytes[0] = '\0';
+ flag = JS_FALSE;
+
+ if ((file->mode&PR_RDONLY)==PR_RDONLY) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "read");
+ flag = JS_TRUE;
+ }
+ if ((file->mode&PR_WRONLY)==PR_WRONLY) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "write");
+ flag = JS_TRUE;
+ }
+ if ((file->mode&PR_RDWR)==PR_RDWR) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "readWrite");
+ flag = JS_TRUE;
+ }
+ if ((file->mode&PR_APPEND)==PR_APPEND) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "append");
+ flag = JS_TRUE;
+ }
+ if ((file->mode&PR_CREATE_FILE)==PR_CREATE_FILE) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "create");
+ flag = JS_TRUE;
+ }
+ if ((file->mode&PR_TRUNCATE)==PR_TRUNCATE) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "replace");
+ flag = JS_TRUE;
+ }
+ if (file->hasAutoflush) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "hasAutoFlush");
+ flag = JS_TRUE;
+ }
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, bytes));
+ JS_free(cx, bytes);
+ break;
+ case FILE_CREATED:
+ SECURITY_CHECK(cx, NULL, "creationTime", file);
+ JSFILE_CHECK_NATIVE("creationTime");
+ if(((file->isOpen)?
+ PR_GetOpenFileInfo(file->handle, &info):
+ PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
+ goto out;
+ }
+
+ PR_ExplodeTime(info.creationTime, PR_LocalTimeParameters,&expandedTime);
+ *vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year,
+ expandedTime.tm_month,
+ expandedTime.tm_mday,
+ expandedTime.tm_hour,
+ expandedTime.tm_min,
+ expandedTime.tm_sec));
+ break;
+ case FILE_MODIFIED:
+ SECURITY_CHECK(cx, NULL, "lastModified", file);
+ JSFILE_CHECK_NATIVE("lastModified");
+ if(((file->isOpen)?
+ PR_GetOpenFileInfo(file->handle, &info):
+ PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
+ goto out;
+ }
+
+ PR_ExplodeTime(info.modifyTime, PR_LocalTimeParameters, &expandedTime);
+ *vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year,
+ expandedTime.tm_month,
+ expandedTime.tm_mday,
+ expandedTime.tm_hour,
+ expandedTime.tm_min,
+ expandedTime.tm_sec));
+ break;
+ case FILE_SIZE:
+ SECURITY_CHECK(cx, NULL, "size", file);
+ *vp = js_size(cx, file);
+ break;
+ case FILE_LENGTH:
+ SECURITY_CHECK(cx, NULL, "length", file);
+ JSFILE_CHECK_NATIVE("length");
+
+ if (js_isDirectory(cx, file)) { /* XXX debug me */
+ PRDir *dir;
+ PRDirEntry *entry;
+ jsint count = 0;
+
+ if(!(dir = PR_OpenDir(file->path))){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_OPEN_DIR, file->path);
+ goto out;
+ }
+
+ while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
+ count++;
+ }
+
+ if(!PR_CloseDir(dir)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "close", file->path);
+
+ goto out;
+ }
+
+ *vp = INT_TO_JSVAL(count);
+ break;
+ }else{
+ /* return file size */
+ *vp = js_size(cx, file);
+ }
+ break;
+ case FILE_RANDOMACCESS:
+ SECURITY_CHECK(cx, NULL, "hasRandomAccess", file);
+ JSFILE_CHECK_OPEN("hasRandomAccess");
+ *vp = BOOLEAN_TO_JSVAL(file->hasRandomAccess);
+ break;
+ case FILE_POSITION:
+ SECURITY_CHECK(cx, NULL, "position", file);
+ JSFILE_CHECK_NATIVE("position");
+ JSFILE_CHECK_OPEN("position");
+
+ if(!file->hasRandomAccess){
+ JS_ReportWarning(cx, "File %s doesn't support random access, can't report the position, proceeding");
+ *vp = JSVAL_VOID;
+ break;
+ }
+
+ if (file->isOpen && js_isFile(cx, file)) {
+ int pos = PR_Seek(file->handle, 0, PR_SEEK_CUR);
+ if(pos!=-1){
+ *vp = INT_TO_JSVAL(pos);
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_REPORT_POSITION, file->path);
+ goto out;
+ }
+ }else {
+ JS_ReportWarning(cx, "File %s is closed or not a plain file,"
+ " can't report position, proceeding");
+ goto out;
+ }
+ break;
+ default:
+ SECURITY_CHECK(cx, NULL, "file_access", file);
+
+ /* this is some other property -- try to use the dir["file"] syntax */
+ if (js_isDirectory(cx, file)) {
+ PRDir *dir = NULL;
+ PRDirEntry *entry = NULL;
+ char *prop_name;
+
+ str = JS_ValueToString(cx, id);
+ if (!str)
+ return JS_FALSE;
+
+ prop_name = JS_GetStringBytes(str);
+
+ /* no native files past this point */
+ dir = PR_OpenDir(file->path);
+ if(!dir) {
+ /* This is probably not a directory */
+ JS_ReportWarning(cx, "Can't open directory %s", file->path);
+ return JS_FALSE;
+ }
+
+ while ((entry = PR_ReadDir(dir, PR_SKIP_NONE)) != NULL) {
+ if (!strcmp(entry->name, prop_name)){
+ bytes = js_combinePath(cx, file->path, prop_name);
+ *vp = OBJECT_TO_JSVAL(js_NewFileObject(cx, bytes));
+ PR_CloseDir(dir);
+ JS_free(cx, bytes);
+ return !JSVAL_IS_NULL(*vp);
+ }
+ }
+ PR_CloseDir(dir);
+ }
+ }
+ return JS_TRUE;
+
+out:
+ return JS_FALSE;
+}
+
+static JSBool
+file_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ jsint slot;
+
+ if (JSVAL_IS_STRING(id)){
+ return JS_TRUE;
+ }
+
+ slot = JSVAL_TO_INT(id);
+
+ switch (slot) {
+ /* File.position = 10 */
+ case FILE_POSITION:
+ SECURITY_CHECK(cx, NULL, "set_position", file);
+ JSFILE_CHECK_NATIVE("set_position");
+
+ if(!file->hasRandomAccess){
+ JS_ReportWarning(cx, "File %s doesn't support random access, can't "
+ "report the position, proceeding");
+ goto out;
+ }
+
+ if (file->isOpen && js_isFile(cx, file)) {
+ int32 pos;
+ int32 offset;
+
+ if (!JS_ValueToInt32(cx, *vp, &offset)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "position", *vp);
+ goto out;
+ }
+
+ pos = PR_Seek(file->handle, offset, PR_SEEK_SET);
+
+ if(pos!=-1){
+ *vp = INT_TO_JSVAL(pos);
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_SET_POSITION, file->path);
+ goto out;
+ }
+ } else {
+ JS_ReportWarning(cx, "File %s is closed or not a file, can't set "
+ "position, proceeding", file->path);
+ goto out;
+ }
+ }
+
+ return JS_TRUE;
+out:
+ return JS_FALSE;
+}
+
+/*
+ File.currentDir = new File("D:\") or File.currentDir = "D:\"
+*/
+static JSBool
+file_currentDirSetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSFile *file;
+
+ file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ /* Look at the rhs and extract a file object from it */
+ if (JSVAL_IS_OBJECT(*vp)) {
+ if (JS_InstanceOf(cx, obj, &js_FileClass, NULL)) {
+ /* Braindamaged rhs -- just return the old value */
+ if (file && (!js_exists(cx, file) || !js_isDirectory(cx, file))) {
+ JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
+ return JS_FALSE;
+ } else {
+ chdir(file->path);
+ return JS_TRUE;
+ }
+ } else {
+ return JS_FALSE;
+ }
+ } else {
+ JSObject *rhsObject;
+ char *path;
+
+ path = JS_GetStringBytes(JS_ValueToString(cx, *vp));
+ rhsObject = js_NewFileObject(cx, path);
+ if (!rhsObject)
+ return JS_FALSE;
+
+ if (!file || !js_exists(cx, file) || !js_isDirectory(cx, file)){
+ JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
+ } else {
+ *vp = OBJECT_TO_JSVAL(rhsObject);
+ chdir(path);
+ }
+ }
+
+ return JS_TRUE;
+}
+
+/* Declare class */
+JSClass js_FileClass = {
+ "File", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_File),
+ JS_PropertyStub, JS_PropertyStub, file_getProperty, file_setProperty,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, file_finalize
+};
+
+/* -------------------- Functions exposed to the outside -------------------- */
+JS_PUBLIC_API(JSObject*)
+js_InitFileClass(JSContext *cx, JSObject* obj)
+{
+ JSObject *file, *ctor, *afile;
+ jsval vp;
+ char *currentdir;
+ char separator[2];
+
+ file = JS_InitClass(cx, obj, NULL, &js_FileClass, file_constructor, 1,
+ file_props, file_functions, NULL, NULL);
+ if (!file) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_INIT_FAILED);
+ return NULL;
+ }
+
+ ctor = JS_GetConstructor(cx, file);
+ if (!ctor) return NULL;
+
+ /* Define CURRENTDIR property. We are doing this to get a
+ slash at the end of the current dir */
+ afile = js_NewFileObject(cx, CURRENT_DIR);
+ currentdir = JS_malloc(cx, MAX_PATH_LENGTH);
+ currentdir = getcwd(currentdir, MAX_PATH_LENGTH);
+ afile = js_NewFileObject(cx, currentdir);
+ JS_free(cx, currentdir);
+ vp = OBJECT_TO_JSVAL(afile);
+ JS_DefinePropertyWithTinyId(cx, ctor, CURRENTDIR_PROPERTY, 0, vp,
+ JS_PropertyStub, file_currentDirSetter,
+ JSPROP_ENUMERATE | JSPROP_READONLY );
+
+ /* Define input */
+ vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdin,
+ STDINPUT_NAME, PR_RDONLY, JS_TRUE, JS_FALSE));
+ JS_SetProperty(cx, ctor, "input", &vp);
+
+ /* Define output */
+ vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdout,
+ STDOUTPUT_NAME, PR_WRONLY, JS_TRUE, JS_FALSE));
+ JS_SetProperty(cx, ctor, "output", &vp);
+
+ /* Define error */
+ vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stderr,
+ STDERROR_NAME, PR_WRONLY, JS_TRUE, JS_FALSE));
+ JS_SetProperty(cx, ctor, "error", &vp);
+
+ separator[0] = FILESEPARATOR;
+ separator[1] = '\0';
+ vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, separator));
+ JS_DefinePropertyWithTinyId(cx, ctor, SEPARATOR_PROPERTY, 0, vp,
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_ENUMERATE | JSPROP_READONLY );
+ return file;
+}
+#endif /* JS_HAS_FILE_OBJECT */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsfile.h b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.h
new file mode 100644
index 0000000..78707e8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _jsfile_h__
+#define _jsfile_h__
+
+#if JS_HAS_FILE_OBJECT
+
+#include "jsobj.h"
+
+extern JS_PUBLIC_API(JSObject*)
+js_InitFileClass(JSContext *cx, JSObject* obj);
+
+extern JS_PUBLIC_API(JSObject*)
+js_NewFileObject(JSContext *cx, char *bytes);
+
+extern JSClass js_FileClass;
+
+#endif /* JS_HAS_FILE_OBJECT */
+#endif /* _jsfile_h__ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsfile.msg b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.msg
new file mode 100644
index 0000000..137b35d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.msg
@@ -0,0 +1,90 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ Error messages for jsfile.c. See js.msg for format specification.
+*/
+
+MSG_DEF(JSFILEMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
+MSG_DEF(JSFILEMSG_FILE_CONSTRUCTOR_UNDEFINED_ERROR, 1, 0, JSEXN_NONE, "File constructor is undefined")
+MSG_DEF(JSFILEMSG_FILE_CURRENTDIR_UNDEFINED_ERROR, 2, 0, JSEXN_NONE, "File.currentDir is undefined")
+MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR, 3, 1, JSEXN_NONE, "The first argument {0} to file.open must be a string")
+MSG_DEF(JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR, 4, 0, JSEXN_NONE, "The second argument to file.open must be a string")
+MSG_DEF(JSFILEMSG_CANNOT_COPY_FILE_OPEN_FOR_WRITING_ERROR, 5, 1, JSEXN_NONE, "Cannot copy file {0} open for writing")
+MSG_DEF(JSFILEMSG_CANNOT_ACCESS_FILE_INFO_ERROR, 6, 1, JSEXN_NONE, "Cannot access file information for {0}")
+MSG_DEF(JSFILEMSG_COPY_READ_ERROR, 7, 1, JSEXN_NONE, "An error occured while attempting to read a file {0} to copy")
+MSG_DEF(JSFILEMSG_COPY_WRITE_ERROR, 8, 1, JSEXN_NONE, "An error occured while attempting to copy into file {0}")
+MSG_DEF(JSFILEMSG_EXPECTS_ONE_ARG_ERROR, 9, 0, JSEXN_NONE, "Operation {0} expects one argument, not {1}")
+MSG_DEF(JSFILEMSG_CANNOT_FLUSH_CLOSE_FILE_ERROR, 10, 1, JSEXN_NONE, "Cannot flush closed file {0}")
+MSG_DEF(JSFILEMSG_CANNOT_OPEN_WRITING_ERROR, 11, 1, JSEXN_NONE, "Cannot open file {0} for writing")
+MSG_DEF(JSFILEMSG_WRITEALL_EXPECTS_ONE_ARG_ERROR, 12, 0, JSEXN_NONE, "writeAll expects one argument")
+MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_WRITEALL_NOT_ARRAY_ERROR, 13, 0, JSEXN_NONE, "writeAll expects an array as an argument")
+MSG_DEF(JSFILEMSG_UNUSED0, 14, 0, JSEXN_NONE, "Unused error message slot")
+MSG_DEF(JSFILEMSG_CANNOT_OPEN_FILE_ERROR, 15, 1, JSEXN_NONE, "Cannot open file {0}")
+MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR, 16, 1, JSEXN_NONE, "The argument to the File constructor {0} must be a string")
+MSG_DEF(JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED, 17, 0, JSEXN_NONE, "Bidirectional pipes are not supported")
+MSG_DEF(JSFILEMSG_OPEN_MODE_NOT_SUPPORTED_WITH_PIPES, 18, 2, JSEXN_NONE, "The opening mode you have chosen {0} is not supported by the pipe you are trying to open: {1}")
+MSG_DEF(JSFILEMSG_OPEN_FAILED, 19, 1, JSEXN_NONE, "open on file {0} failed")
+MSG_DEF(JSFILEMSG_CLOSE_FAILED, 20, 1, JSEXN_NONE, "close on file {0} failed")
+MSG_DEF(JSFILEMSG_PCLOSE_FAILED, 21, 1, JSEXN_NONE, "pclose on file {0} failed")
+MSG_DEF(JSFILEMSG_REMOVE_FAILED, 22, 1, JSEXN_NONE, "remove on file {0} failed")
+MSG_DEF(JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, 23, 1, JSEXN_NONE, "Cannot access file status for {0}")
+MSG_DEF(JSFILEMSG_RENAME_FAILED, 24, 2, JSEXN_NONE, "Cannot rename {0} to {1}")
+MSG_DEF(JSFILEMSG_WRITE_FAILED, 25, 1, JSEXN_NONE, "Write failed on file {0}")
+MSG_DEF(JSFILEMSG_READ_FAILED, 26, 1, JSEXN_NONE, "Read failed on file {0}")
+MSG_DEF(JSFILEMSG_SKIP_FAILED, 27, 1, JSEXN_NONE, "Skip failed on file {0}")
+MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_FUNCTION_OR_REGEX, 28, 1, JSEXN_NONE, "The first argument to file.list must be a function or a regex")
+MSG_DEF(JSFILEMSG_CANNOT_DO_LIST_ON_A_FILE, 29, 1, JSEXN_NONE, "{0} must be a directory, cannot do list")
+MSG_DEF(JSFILEMSG_NATIVE_OPERATION_IS_NOT_SUPPORTED, 30, 2, JSEXN_NONE, "Native operation {0} is not supported on {1}")
+MSG_DEF(JSFILEMSG_CANNOT_SET_PRIVATE_FILE, 31, 1, JSEXN_NONE, "Cannot set private data for file {0}")
+MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, 32, 2, JSEXN_NONE, "First argument to {0} must be a number, not {1}")
+MSG_DEF(JSFILEMSG_CANNOT_WRITE, 33, 1, JSEXN_NONE, "Cannot write to {0}, file mode is different")
+MSG_DEF(JSFILEMSG_CANNOT_READ, 34, 1, JSEXN_NONE, "Cannot read from {0}, file mode is different")
+MSG_DEF(JSFILEMSG_CANNOT_FLUSH, 35, 1, JSEXN_NONE, "Flush failed on {0}")
+MSG_DEF(JSFILEMSG_OP_FAILED, 36, 1, JSEXN_NONE, "File operation {0} failed")
+MSG_DEF(JSFILEMSG_FILE_MUST_BE_OPEN, 37, 1, JSEXN_NONE, "File must be open for {0}")
+MSG_DEF(JSFILEMSG_FILE_MUST_BE_CLOSED, 38, 1, JSEXN_NONE, "File must be closed for {0}")
+MSG_DEF(JSFILEMSG_NO_RANDOM_ACCESS, 39, 1, JSEXN_NONE, "File {0} doesn't allow random access")
+MSG_DEF(JSFILEMSG_OBJECT_CREATION_FAILED, 40, 1, JSEXN_NONE, "Couldn't create {0}")
+MSG_DEF(JSFILEMSG_CANNOT_OPEN_DIR, 41, 1, JSEXN_NONE, "Couldn't open directory {0}")
+MSG_DEF(JSFILEMSG_CANNOT_REPORT_POSITION, 42, 1, JSEXN_NONE, "Couldn't report position for {0}")
+MSG_DEF(JSFILEMSG_CANNOT_SET_POSITION, 43, 1, JSEXN_NONE, "Couldn't set position for {0}")
+MSG_DEF(JSFILEMSG_INIT_FAILED, 44, 0, JSEXN_NONE, "File class initialization failed")
+
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsfun.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsfun.cpp
new file mode 100644
index 0000000..a492bcc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsfun.cpp
@@ -0,0 +1,2706 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS function support.
+ */
+#include "jsstddef.h"
+#include <string.h>
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsexn.h"
+#include "jsstaticcheck.h"
+
+#if JS_HAS_GENERATORS
+# include "jsiter.h"
+#endif
+
+#if JS_HAS_XDR
+# include "jsxdrapi.h"
+#endif
+
+/* Generic function/call/arguments tinyids -- also reflected bit numbers. */
+enum {
+ CALL_ARGUMENTS = -1, /* predefined arguments local variable */
+ ARGS_LENGTH = -2, /* number of actual args, arity if inactive */
+ ARGS_CALLEE = -3, /* reference from arguments to active funobj */
+ FUN_ARITY = -4, /* number of formal parameters; desired argc */
+ FUN_NAME = -5, /* function name, "" if anonymous */
+ FUN_CALLER = -6 /* Function.prototype.caller, backward compat */
+};
+
+#if JSFRAME_OVERRIDE_BITS < 8
+# error "not enough override bits in JSStackFrame.flags!"
+#endif
+
+#define TEST_OVERRIDE_BIT(fp, tinyid) \
+ ((fp)->flags & JS_BIT(JSFRAME_OVERRIDE_SHIFT - ((tinyid) + 1)))
+
+#define SET_OVERRIDE_BIT(fp, tinyid) \
+ ((fp)->flags |= JS_BIT(JSFRAME_OVERRIDE_SHIFT - ((tinyid) + 1)))
+
+JSBool
+js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp)
+{
+ JSObject *argsobj;
+
+ if (TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
+ JS_ASSERT(fp->callobj);
+ return OBJ_GET_PROPERTY(cx, fp->callobj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .argumentsAtom),
+ vp);
+ }
+ argsobj = js_GetArgsObject(cx, fp);
+ if (!argsobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(argsobj);
+ return JS_TRUE;
+}
+
+static JSBool
+MarkArgDeleted(JSContext *cx, JSStackFrame *fp, uintN slot)
+{
+ JSObject *argsobj;
+ jsval bmapval, bmapint;
+ size_t nbits, nbytes;
+ jsbitmap *bitmap;
+
+ argsobj = fp->argsobj;
+ (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);
+ nbits = fp->argc;
+ JS_ASSERT(slot < nbits);
+ if (JSVAL_IS_VOID(bmapval)) {
+ if (nbits <= JSVAL_INT_BITS) {
+ bmapint = 0;
+ bitmap = (jsbitmap *) &bmapint;
+ } else {
+ nbytes = JS_HOWMANY(nbits, JS_BITS_PER_WORD) * sizeof(jsbitmap);
+ bitmap = (jsbitmap *) JS_malloc(cx, nbytes);
+ if (!bitmap)
+ return JS_FALSE;
+ memset(bitmap, 0, nbytes);
+ bmapval = PRIVATE_TO_JSVAL(bitmap);
+ JS_SetReservedSlot(cx, argsobj, 0, bmapval);
+ }
+ } else {
+ if (nbits <= JSVAL_INT_BITS) {
+ bmapint = JSVAL_TO_INT(bmapval);
+ bitmap = (jsbitmap *) &bmapint;
+ } else {
+ bitmap = (jsbitmap *) JSVAL_TO_PRIVATE(bmapval);
+ }
+ }
+ JS_SET_BIT(bitmap, slot);
+ if (bitmap == (jsbitmap *) &bmapint) {
+ bmapval = INT_TO_JSVAL(bmapint);
+ JS_SetReservedSlot(cx, argsobj, 0, bmapval);
+ }
+ return JS_TRUE;
+}
+
+/* NB: Infallible predicate, false does not mean error/exception. */
+static JSBool
+ArgWasDeleted(JSContext *cx, JSStackFrame *fp, uintN slot)
+{
+ JSObject *argsobj;
+ jsval bmapval, bmapint;
+ jsbitmap *bitmap;
+
+ argsobj = fp->argsobj;
+ (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);
+ if (JSVAL_IS_VOID(bmapval))
+ return JS_FALSE;
+ if (fp->argc <= JSVAL_INT_BITS) {
+ bmapint = JSVAL_TO_INT(bmapval);
+ bitmap = (jsbitmap *) &bmapint;
+ } else {
+ bitmap = (jsbitmap *) JSVAL_TO_PRIVATE(bmapval);
+ }
+ return JS_TEST_BIT(bitmap, slot) != 0;
+}
+
+JSBool
+js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, jsval *vp)
+{
+ jsval val;
+ JSObject *obj;
+ uintN slot;
+
+ if (TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
+ JS_ASSERT(fp->callobj);
+ if (!OBJ_GET_PROPERTY(cx, fp->callobj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .argumentsAtom),
+ &val)) {
+ return JS_FALSE;
+ }
+ if (JSVAL_IS_PRIMITIVE(val)) {
+ obj = js_ValueToNonNullObject(cx, val);
+ if (!obj)
+ return JS_FALSE;
+ } else {
+ obj = JSVAL_TO_OBJECT(val);
+ }
+ return OBJ_GET_PROPERTY(cx, obj, id, vp);
+ }
+
+ *vp = JSVAL_VOID;
+ if (JSID_IS_INT(id)) {
+ slot = (uintN) JSID_TO_INT(id);
+ if (slot < fp->argc) {
+ if (fp->argsobj && ArgWasDeleted(cx, fp, slot))
+ return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);
+ *vp = fp->argv[slot];
+ } else {
+ /*
+ * Per ECMA-262 Ed. 3, 10.1.8, last bulleted item, do not share
+ * storage between the formal parameter and arguments[k] for all
+ * fp->argc <= k && k < fp->fun->nargs. For example, in
+ *
+ * function f(x) { x = 42; return arguments[0]; }
+ * f();
+ *
+ * the call to f should return undefined, not 42. If fp->argsobj
+ * is null at this point, as it would be in the example, return
+ * undefined in *vp.
+ */
+ if (fp->argsobj)
+ return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);
+ }
+ } else {
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) {
+ if (fp->argsobj && TEST_OVERRIDE_BIT(fp, ARGS_LENGTH))
+ return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);
+ *vp = INT_TO_JSVAL((jsint) fp->argc);
+ }
+ }
+ return JS_TRUE;
+}
+
+JSObject *
+js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
+{
+ JSObject *argsobj, *global, *parent;
+
+ /*
+ * We must be in a function activation; the function must be lightweight
+ * or else fp must have a variable object.
+ */
+ JS_ASSERT(fp->fun && (!(fp->fun->flags & JSFUN_HEAVYWEIGHT) || fp->varobj));
+
+ /* Skip eval and debugger frames. */
+ while (fp->flags & JSFRAME_SPECIAL)
+ fp = fp->down;
+
+ /* Create an arguments object for fp only if it lacks one. */
+ argsobj = fp->argsobj;
+ if (argsobj)
+ return argsobj;
+
+ /* Link the new object to fp so it can get actual argument values. */
+ argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL, 0);
+ if (!argsobj || !JS_SetPrivate(cx, argsobj, fp)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+ }
+
+ /*
+ * Give arguments an intrinsic scope chain link to fp's global object.
+ * Since the arguments object lacks a prototype because js_ArgumentsClass
+ * is not initialized, js_NewObject won't assign a default parent to it.
+ *
+ * Therefore if arguments is used as the head of an eval scope chain (via
+ * a direct or indirect call to eval(program, arguments)), any reference
+ * to a standard class object in the program will fail to resolve due to
+ * js_GetClassPrototype not being able to find a global object containing
+ * the standard prototype by starting from arguments and following parent.
+ */
+ global = fp->scopeChain;
+ while ((parent = OBJ_GET_PARENT(cx, global)) != NULL)
+ global = parent;
+ STOBJ_SET_PARENT(argsobj, global);
+ fp->argsobj = argsobj;
+ return argsobj;
+}
+
+static JSBool
+args_enumerate(JSContext *cx, JSObject *obj);
+
+JS_FRIEND_API(JSBool)
+js_PutArgsObject(JSContext *cx, JSStackFrame *fp)
+{
+ JSObject *argsobj;
+ jsval bmapval, rval;
+ JSBool ok;
+ JSRuntime *rt;
+
+ /*
+ * Reuse args_enumerate here to reflect fp's actual arguments as indexed
+ * elements of argsobj. Do this first, before clearing and freeing the
+ * deleted argument slot bitmap, because args_enumerate depends on that.
+ */
+ argsobj = fp->argsobj;
+ ok = args_enumerate(cx, argsobj);
+
+ /*
+ * Now clear the deleted argument number bitmap slot and free the bitmap,
+ * if one was actually created due to 'delete arguments[0]' or similar.
+ */
+ (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);
+ if (!JSVAL_IS_VOID(bmapval)) {
+ JS_SetReservedSlot(cx, argsobj, 0, JSVAL_VOID);
+ if (fp->argc > JSVAL_INT_BITS)
+ JS_free(cx, JSVAL_TO_PRIVATE(bmapval));
+ }
+
+ /*
+ * Now get the prototype properties so we snapshot fp->fun and fp->argc
+ * before fp goes away.
+ */
+ rt = cx->runtime;
+ ok &= js_GetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.calleeAtom),
+ &rval);
+ ok &= js_SetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.calleeAtom),
+ &rval);
+ ok &= js_GetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.lengthAtom),
+ &rval);
+ ok &= js_SetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.lengthAtom),
+ &rval);
+
+ /*
+ * Clear the private pointer to fp, which is about to go away (js_Invoke).
+ * Do this last because the args_enumerate and js_GetProperty calls above
+ * need to follow the private slot to find fp.
+ */
+ ok &= JS_SetPrivate(cx, argsobj, NULL);
+ fp->argsobj = NULL;
+ return ok;
+}
+
+static JSBool
+args_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsint slot;
+ JSStackFrame *fp;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ fp = (JSStackFrame *)
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
+ if (!fp)
+ return JS_TRUE;
+ JS_ASSERT(fp->argsobj);
+
+ slot = JSVAL_TO_INT(id);
+ switch (slot) {
+ case ARGS_CALLEE:
+ case ARGS_LENGTH:
+ SET_OVERRIDE_BIT(fp, slot);
+ break;
+
+ default:
+ if ((uintN)slot < fp->argc && !MarkArgDeleted(cx, fp, slot))
+ return JS_FALSE;
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+args_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsint slot;
+ JSStackFrame *fp;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ fp = (JSStackFrame *)
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
+ if (!fp)
+ return JS_TRUE;
+ JS_ASSERT(fp->argsobj);
+
+ slot = JSVAL_TO_INT(id);
+ switch (slot) {
+ case ARGS_CALLEE:
+ if (!TEST_OVERRIDE_BIT(fp, slot))
+ *vp = OBJECT_TO_JSVAL(fp->callee);
+ break;
+
+ case ARGS_LENGTH:
+ if (!TEST_OVERRIDE_BIT(fp, slot))
+ *vp = INT_TO_JSVAL((jsint)fp->argc);
+ break;
+
+ default:
+ if ((uintN)slot < fp->argc && !ArgWasDeleted(cx, fp, slot))
+ *vp = fp->argv[slot];
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+args_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSStackFrame *fp;
+ jsint slot;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ fp = (JSStackFrame *)
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
+ if (!fp)
+ return JS_TRUE;
+ JS_ASSERT(fp->argsobj);
+
+ slot = JSVAL_TO_INT(id);
+ switch (slot) {
+ case ARGS_CALLEE:
+ case ARGS_LENGTH:
+ SET_OVERRIDE_BIT(fp, slot);
+ break;
+
+ default:
+ if (FUN_INTERPRETED(fp->fun) &&
+ (uintN)slot < fp->argc &&
+ !ArgWasDeleted(cx, fp, slot)) {
+ fp->argv[slot] = *vp;
+ }
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+args_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ JSStackFrame *fp;
+ uintN slot;
+ JSString *str;
+ JSAtom *atom;
+ intN tinyid;
+ jsval value;
+
+ *objp = NULL;
+ fp = (JSStackFrame *)
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
+ if (!fp)
+ return JS_TRUE;
+ JS_ASSERT(fp->argsobj);
+
+ if (JSVAL_IS_INT(id)) {
+ slot = JSVAL_TO_INT(id);
+ if (slot < fp->argc && !ArgWasDeleted(cx, fp, slot)) {
+ /* XXX ECMA specs DontEnum, contrary to other array-like objects */
+ if (!js_DefineProperty(cx, obj, INT_JSVAL_TO_JSID(id),
+ fp->argv[slot],
+ args_getProperty, args_setProperty,
+ 0, NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ }
+ } else {
+ str = JSVAL_TO_STRING(id);
+ atom = cx->runtime->atomState.lengthAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ tinyid = ARGS_LENGTH;
+ value = INT_TO_JSVAL(fp->argc);
+ } else {
+ atom = cx->runtime->atomState.calleeAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ tinyid = ARGS_CALLEE;
+ value = OBJECT_TO_JSVAL(fp->callee);
+ } else {
+ atom = NULL;
+
+ /* Quell GCC overwarnings. */
+ tinyid = 0;
+ value = JSVAL_NULL;
+ }
+ }
+
+ if (atom && !TEST_OVERRIDE_BIT(fp, tinyid)) {
+ if (!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value,
+ args_getProperty, args_setProperty, 0,
+ SPROP_HAS_SHORTID, tinyid, NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+args_enumerate(JSContext *cx, JSObject *obj)
+{
+ JSStackFrame *fp;
+ JSObject *pobj;
+ JSProperty *prop;
+ uintN slot, argc;
+
+ fp = (JSStackFrame *)
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
+ if (!fp)
+ return JS_TRUE;
+ JS_ASSERT(fp->argsobj);
+
+ /*
+ * Trigger reflection with value snapshot in args_resolve using a series
+ * of js_LookupProperty calls. We handle length, callee, and the indexed
+ * argument properties. We know that args_resolve covers all these cases
+ * and creates direct properties of obj, but that it may fail to resolve
+ * length or callee if overridden.
+ */
+ if (!js_LookupProperty(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState.lengthAtom),
+ &pobj, &prop)) {
+ return JS_FALSE;
+ }
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+
+ if (!js_LookupProperty(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState.calleeAtom),
+ &pobj, &prop)) {
+ return JS_FALSE;
+ }
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+
+ argc = fp->argc;
+ for (slot = 0; slot < argc; slot++) {
+ if (!js_LookupProperty(cx, obj, INT_TO_JSID((jsint)slot), &pobj, &prop))
+ return JS_FALSE;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ return JS_TRUE;
+}
+
+#if JS_HAS_GENERATORS
+/*
+ * If a generator-iterator's arguments or call object escapes, it needs to
+ * mark its generator object.
+ */
+static void
+args_or_call_trace(JSTracer *trc, JSObject *obj)
+{
+ JSStackFrame *fp;
+
+ fp = (JSStackFrame *) JS_GetPrivate(trc->context, obj);
+ if (fp && (fp->flags & JSFRAME_GENERATOR)) {
+ JS_CALL_OBJECT_TRACER(trc, FRAME_TO_GENERATOR(fp)->obj,
+ "FRAME_TO_GENERATOR(fp)->obj");
+ }
+}
+#else
+# define args_or_call_trace NULL
+#endif
+
+/*
+ * The Arguments class is not initialized via JS_InitClass, and must not be,
+ * because its name is "Object". Per ECMA, that causes instances of it to
+ * delegate to the object named by Object.prototype. It also ensures that
+ * arguments.toString() returns "[object Object]".
+ *
+ * The JSClass functions below collaborate to lazily reflect and synchronize
+ * actual argument values, argument count, and callee function object stored
+ * in a JSStackFrame with their corresponding property values in the frame's
+ * arguments object.
+ */
+JSClass js_ArgumentsClass = {
+ js_Object_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
+ JS_PropertyStub, args_delProperty,
+ args_getProperty, args_setProperty,
+ args_enumerate, (JSResolveOp) args_resolve,
+ JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL,
+ JS_CLASS_TRACE(args_or_call_trace), NULL
+};
+
+#define JSSLOT_SCRIPTED_FUNCTION (JSSLOT_PRIVATE + 1)
+#define JSSLOT_CALL_ARGUMENTS (JSSLOT_PRIVATE + 2)
+#define CALL_CLASS_FIXED_RESERVED_SLOTS 2
+
+JSObject *
+js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent)
+{
+ JSObject *callobj, *funobj;
+
+ /* Create a call object for fp only if it lacks one. */
+ JS_ASSERT(fp->fun);
+ callobj = fp->callobj;
+ if (callobj)
+ return callobj;
+
+ /* The default call parent is its function's parent (static link). */
+ if (!parent) {
+ funobj = fp->callee;
+ if (funobj)
+ parent = OBJ_GET_PARENT(cx, funobj);
+ }
+
+ /* Create the call object and link it to its stack frame. */
+ callobj = js_NewObject(cx, &js_CallClass, NULL, parent, 0);
+ if (!callobj)
+ return NULL;
+
+ JS_SetPrivate(cx, callobj, fp);
+ STOBJ_SET_SLOT(callobj, JSSLOT_SCRIPTED_FUNCTION,
+ OBJECT_TO_JSVAL(FUN_OBJECT(fp->fun)));
+ fp->callobj = callobj;
+
+ /* Make callobj be the scope chain and the variables object. */
+ JS_ASSERT(fp->scopeChain == parent);
+ fp->scopeChain = callobj;
+ fp->varobj = callobj;
+ return callobj;
+}
+
+JSFunction *
+js_GetCallObjectFunction(JSObject *obj)
+{
+ jsval v;
+
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_CallClass);
+ v = STOBJ_GET_SLOT(obj, JSSLOT_SCRIPTED_FUNCTION);
+ if (JSVAL_IS_VOID(v)) {
+ /* Newborn or prototype object. */
+ return NULL;
+ }
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ return (JSFunction *) JSVAL_TO_OBJECT(v);
+}
+
+JS_FRIEND_API(JSBool)
+js_PutCallObject(JSContext *cx, JSStackFrame *fp)
+{
+ JSObject *callobj;
+ JSBool ok;
+ JSFunction *fun;
+ uintN n;
+ JSScope *scope;
+
+ /*
+ * Since for a call object all fixed slots happen to be taken, we can copy
+ * arguments and variables straight into JSObject.dslots.
+ */
+ JS_STATIC_ASSERT(JS_INITIAL_NSLOTS - JSSLOT_PRIVATE ==
+ 1 + CALL_CLASS_FIXED_RESERVED_SLOTS);
+
+ callobj = fp->callobj;
+ if (!callobj)
+ return JS_TRUE;
+
+ /*
+ * Get the arguments object to snapshot fp's actual argument values.
+ */
+ ok = JS_TRUE;
+ if (fp->argsobj) {
+ if (!TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
+ STOBJ_SET_SLOT(callobj, JSSLOT_CALL_ARGUMENTS,
+ OBJECT_TO_JSVAL(fp->argsobj));
+ }
+ ok &= js_PutArgsObject(cx, fp);
+ }
+
+ fun = fp->fun;
+ JS_ASSERT(fun == js_GetCallObjectFunction(callobj));
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ if (n != 0) {
+ JS_LOCK_OBJ(cx, callobj);
+ n += JS_INITIAL_NSLOTS;
+ if (n > STOBJ_NSLOTS(callobj))
+ ok &= js_ReallocSlots(cx, callobj, n, JS_TRUE);
+ scope = OBJ_SCOPE(callobj);
+ if (ok) {
+ memcpy(callobj->dslots, fp->argv, fun->nargs * sizeof(jsval));
+ memcpy(callobj->dslots + fun->nargs, fp->slots,
+ fun->u.i.nvars * sizeof(jsval));
+ if (scope->object == callobj && n > scope->map.freeslot)
+ scope->map.freeslot = n;
+ }
+ JS_UNLOCK_SCOPE(cx, scope);
+ }
+
+ /*
+ * Clear the private pointer to fp, which is about to go away (js_Invoke).
+ * Do this last because js_GetProperty calls above need to follow the
+ * private slot to find fp.
+ */
+ JS_SetPrivate(cx, callobj, NULL);
+ fp->callobj = NULL;
+ return ok;
+}
+
+static JSBool
+call_enumerate(JSContext *cx, JSObject *obj)
+{
+ JSFunction *fun;
+ uintN n, i;
+ void *mark;
+ jsuword *names;
+ JSBool ok;
+ JSAtom *name;
+ JSObject *pobj;
+ JSProperty *prop;
+
+ fun = js_GetCallObjectFunction(obj);
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ if (n == 0)
+ return JS_TRUE;
+
+ mark = JS_ARENA_MARK(&cx->tempPool);
+
+ MUST_FLOW_THROUGH("out");
+ names = js_GetLocalNameArray(cx, fun, &cx->tempPool);
+ if (!names) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ for (i = 0; i != n; ++i) {
+ name = JS_LOCAL_NAME_TO_ATOM(names[i]);
+ if (!name)
+ continue;
+
+ /*
+ * Trigger reflection by looking up the name of the argument or
+ * variable.
+ */
+ ok = js_LookupProperty(cx, obj, ATOM_TO_JSID(name), &pobj, &prop);
+ if (!ok)
+ goto out;
+
+ /*
+ * At this point the call object always has a property corresponding
+ * to the local name because call_resolve creates the property using
+ * JSPROP_PERMANENT.
+ */
+ JS_ASSERT(prop && pobj == obj);
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ ok = JS_TRUE;
+
+ out:
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return ok;
+}
+
+typedef enum JSCallPropertyKind {
+ JSCPK_ARGUMENTS,
+ JSCPK_ARG,
+ JSCPK_VAR
+} JSCallPropertyKind;
+
+static JSBool
+CallPropertyOp(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+ JSCallPropertyKind kind, JSBool setter)
+{
+ JSFunction *fun;
+ JSStackFrame *fp;
+ uintN i;
+ jsval *array;
+
+ if (STOBJ_GET_CLASS(obj) != &js_CallClass)
+ return JS_TRUE;
+
+ fun = js_GetCallObjectFunction(obj);
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+
+ if (kind == JSCPK_ARGUMENTS) {
+ if (setter) {
+ if (fp)
+ SET_OVERRIDE_BIT(fp, CALL_ARGUMENTS);
+ STOBJ_SET_SLOT(obj, JSSLOT_CALL_ARGUMENTS, *vp);
+ } else {
+ if (fp && !TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
+ JSObject *argsobj;
+
+ argsobj = js_GetArgsObject(cx, fp);
+ if (!argsobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(argsobj);
+ } else {
+ *vp = STOBJ_GET_SLOT(obj, JSSLOT_CALL_ARGUMENTS);
+ }
+ }
+ return JS_TRUE;
+ }
+
+ JS_ASSERT((int16) JSVAL_TO_INT(id) == JSVAL_TO_INT(id));
+ i = (uint16) JSVAL_TO_INT(id);
+ JS_ASSERT_IF(kind == JSCPK_ARG, i < fun->nargs);
+ JS_ASSERT_IF(kind == JSCPK_VAR, i < fun->u.i.nvars);
+
+ if (!fp) {
+ i += CALL_CLASS_FIXED_RESERVED_SLOTS;
+ if (kind == JSCPK_VAR)
+ i += fun->nargs;
+ else
+ JS_ASSERT(kind == JSCPK_ARG);
+ return setter
+ ? JS_SetReservedSlot(cx, obj, i, *vp)
+ : JS_GetReservedSlot(cx, obj, i, vp);
+ }
+
+ if (kind == JSCPK_ARG) {
+ array = fp->argv;
+ } else {
+ JS_ASSERT(kind == JSCPK_VAR);
+ array = fp->slots;
+ }
+ if (setter)
+ array[i] = *vp;
+ else
+ *vp = array[i];
+ return JS_TRUE;
+}
+
+static JSBool
+GetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_FALSE);
+}
+
+static JSBool
+SetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_TRUE);
+}
+
+JSBool
+js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_FALSE);
+}
+
+static JSBool
+SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_TRUE);
+}
+
+JSBool
+js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_FALSE);
+}
+
+static JSBool
+SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_TRUE);
+}
+
+static JSBool
+call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
+ JSObject **objp)
+{
+ JSFunction *fun;
+ jsid id;
+ JSLocalKind localKind;
+ JSPropertyOp getter, setter;
+ uintN slot, attrs;
+
+ if (!JSVAL_IS_STRING(idval))
+ return JS_TRUE;
+
+ fun = js_GetCallObjectFunction(obj);
+ if (!fun)
+ return JS_TRUE;
+
+ if (!js_ValueToStringId(cx, idval, &id))
+ return JS_FALSE;
+
+ localKind = js_LookupLocal(cx, fun, JSID_TO_ATOM(id), &slot);
+ if (localKind != JSLOCAL_NONE) {
+ JS_ASSERT((uint16) slot == slot);
+ attrs = JSPROP_PERMANENT | JSPROP_SHARED;
+ if (localKind == JSLOCAL_ARG) {
+ JS_ASSERT(slot < fun->nargs);
+ getter = js_GetCallArg;
+ setter = SetCallArg;
+ } else {
+ JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
+ JS_ASSERT(slot < fun->u.i.nvars);
+ getter = js_GetCallVar;
+ setter = SetCallVar;
+ if (localKind == JSLOCAL_CONST)
+ attrs |= JSPROP_READONLY;
+ }
+ if (!js_DefineNativeProperty(cx, obj, id, JSVAL_VOID, getter, setter,
+ attrs, SPROP_HAS_SHORTID, (int16) slot,
+ NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ return JS_TRUE;
+ }
+
+ /*
+ * Resolve arguments so that we never store a particular Call object's
+ * arguments object reference in a Call prototype's |arguments| slot.
+ */
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom)) {
+ if (!js_DefineNativeProperty(cx, obj, id, JSVAL_VOID,
+ GetCallArguments, SetCallArguments,
+ JSPROP_PERMANENT | JSPROP_SHARED,
+ 0, 0, NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ return JS_TRUE;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+call_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+{
+ JSStackFrame *fp;
+
+ if (type == JSTYPE_FUNCTION) {
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+ if (fp) {
+ JS_ASSERT(fp->fun);
+ *vp = OBJECT_TO_JSVAL(fp->callee);
+ }
+ }
+ return JS_TRUE;
+}
+
+static uint32
+call_reserveSlots(JSContext *cx, JSObject *obj)
+{
+ JSFunction *fun;
+
+ fun = js_GetCallObjectFunction(obj);
+ return JS_GET_LOCAL_NAME_COUNT(fun);
+}
+
+JS_FRIEND_DATA(JSClass) js_CallClass = {
+ js_Call_str,
+ JSCLASS_HAS_PRIVATE |
+ JSCLASS_HAS_RESERVED_SLOTS(CALL_CLASS_FIXED_RESERVED_SLOTS) |
+ JSCLASS_NEW_RESOLVE | JSCLASS_IS_ANONYMOUS |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Call),
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, JS_PropertyStub,
+ call_enumerate, (JSResolveOp)call_resolve,
+ call_convert, JS_FinalizeStub,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL,
+ JS_CLASS_TRACE(args_or_call_trace), call_reserveSlots
+};
+
+static JSBool
+fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsint slot;
+ JSFunction *fun;
+ JSStackFrame *fp;
+ JSSecurityCallbacks *callbacks;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ slot = JSVAL_TO_INT(id);
+
+ /*
+ * Loop because getter and setter can be delegated from another class,
+ * but loop only for ARGS_LENGTH because we must pretend that f.length
+ * is in each function instance f, per ECMA-262, instead of only in the
+ * Function.prototype object (we use JSPROP_PERMANENT with JSPROP_SHARED
+ * to make it appear so).
+ *
+ * This code couples tightly to the attributes for the function_props[]
+ * initializers above, and to js_SetProperty and js_HasOwnProperty.
+ *
+ * It's important to allow delegating objects, even though they inherit
+ * this getter (fun_getProperty), to override arguments, arity, caller,
+ * and name. If we didn't return early for slot != ARGS_LENGTH, we would
+ * clobber *vp with the native property value, instead of letting script
+ * override that value in delegating objects.
+ *
+ * Note how that clobbering is what simulates JSPROP_READONLY for all of
+ * the non-standard properties when the directly addressed object (obj)
+ * is a function object (i.e., when this loop does not iterate).
+ */
+ while (!(fun = (JSFunction *)
+ JS_GetInstancePrivate(cx, obj, &js_FunctionClass, NULL))) {
+ if (slot != ARGS_LENGTH)
+ return JS_TRUE;
+ obj = OBJ_GET_PROTO(cx, obj);
+ if (!obj)
+ return JS_TRUE;
+ }
+
+ /* Find fun's top-most activation record. */
+ for (fp = cx->fp; fp && (fp->fun != fun || (fp->flags & JSFRAME_SPECIAL));
+ fp = fp->down) {
+ continue;
+ }
+
+ switch (slot) {
+ case CALL_ARGUMENTS:
+ /* Warn if strict about f.arguments or equivalent unqualified uses. */
+ if (!JS_ReportErrorFlagsAndNumber(cx,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ js_GetErrorMessage, NULL,
+ JSMSG_DEPRECATED_USAGE,
+ js_arguments_str)) {
+ return JS_FALSE;
+ }
+ if (fp) {
+ if (!js_GetArgsValue(cx, fp, vp))
+ return JS_FALSE;
+ } else {
+ *vp = JSVAL_NULL;
+ }
+ break;
+
+ case ARGS_LENGTH:
+ case FUN_ARITY:
+ *vp = INT_TO_JSVAL((jsint)fun->nargs);
+ break;
+
+ case FUN_NAME:
+ *vp = fun->atom
+ ? ATOM_KEY(fun->atom)
+ : STRING_TO_JSVAL(cx->runtime->emptyString);
+ break;
+
+ case FUN_CALLER:
+ if (fp && fp->down && fp->down->fun)
+ *vp = OBJECT_TO_JSVAL(fp->down->callee);
+ else
+ *vp = JSVAL_NULL;
+ if (!JSVAL_IS_PRIMITIVE(*vp)) {
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks && callbacks->checkObjectAccess) {
+ id = ATOM_KEY(cx->runtime->atomState.callerAtom);
+ if (!callbacks->checkObjectAccess(cx, obj, id, JSACC_READ, vp))
+ return JS_FALSE;
+ }
+ }
+ break;
+
+ default:
+ /* XXX fun[0] and fun.arguments[0] are equivalent. */
+ if (fp && fp->fun && (uintN)slot < fp->fun->nargs)
+ *vp = fp->argv[slot];
+ break;
+ }
+
+ return JS_TRUE;
+}
+
+/*
+ * ECMA-262 specifies that length is a property of function object instances,
+ * but we can avoid that space cost by delegating to a prototype property that
+ * is JSPROP_PERMANENT and JSPROP_SHARED. Each fun_getProperty call computes
+ * a fresh length value based on the arity of the individual function object's
+ * private data.
+ *
+ * The extensions below other than length, i.e., the ones not in ECMA-262,
+ * are neither JSPROP_READONLY nor JSPROP_SHARED, because for compatibility
+ * with ECMA we must allow a delegating object to override them. Therefore to
+ * avoid entraining garbage in Function.prototype slots, they must be resolved
+ * in non-prototype function objects, wherefore the lazy_function_props table
+ * and fun_resolve's use of it.
+ */
+#define LENGTH_PROP_ATTRS (JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED)
+
+static JSPropertySpec function_props[] = {
+ {js_length_str, ARGS_LENGTH, LENGTH_PROP_ATTRS, fun_getProperty, JS_PropertyStub},
+ {0,0,0,0,0}
+};
+
+typedef struct LazyFunctionProp {
+ uint16 atomOffset;
+ int8 tinyid;
+ uint8 attrs;
+} LazyFunctionProp;
+
+/* NB: no sentinel at the end -- use JS_ARRAY_LENGTH to bound loops. */
+static LazyFunctionProp lazy_function_props[] = {
+ {ATOM_OFFSET(arguments), CALL_ARGUMENTS, JSPROP_PERMANENT},
+ {ATOM_OFFSET(arity), FUN_ARITY, JSPROP_PERMANENT},
+ {ATOM_OFFSET(caller), FUN_CALLER, JSPROP_PERMANENT},
+ {ATOM_OFFSET(name), FUN_NAME, JSPROP_PERMANENT},
+};
+
+static JSBool
+fun_enumerate(JSContext *cx, JSObject *obj)
+{
+ jsid prototypeId;
+ JSObject *pobj;
+ JSProperty *prop;
+
+ prototypeId = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, prototypeId, &pobj, &prop))
+ return JS_FALSE;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ return JS_TRUE;
+}
+
+static JSBool
+fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ JSFunction *fun;
+ JSAtom *atom;
+ uintN i;
+
+ if (!JSVAL_IS_STRING(id))
+ return JS_TRUE;
+
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
+
+ /*
+ * No need to reflect fun.prototype in 'fun.prototype = ... '.
+ *
+ * This is not just an optimization, because we must not resolve when
+ * defining hidden properties during compilation. The setup code for the
+ * prototype and the lazy properties below eventually calls the property
+ * hooks for the function object. That in turn calls fun_reserveSlots to
+ * get the number of the reserved slots which is just the number of
+ * regular expressions literals in the function. When compiling, that
+ * number is not yet ready so we must make sure that fun_resolve does
+ * nothing until the code for the function is generated.
+ */
+ if (flags & JSRESOLVE_ASSIGNING)
+ return JS_TRUE;
+
+ /*
+ * Ok, check whether id is 'prototype' and bootstrap the function object's
+ * prototype property.
+ */
+ atom = cx->runtime->atomState.classPrototypeAtom;
+ if (id == ATOM_KEY(atom)) {
+ JSObject *proto;
+
+ /*
+ * Beware of the wacky case of a user function named Object -- trying
+ * to find a prototype for that will recur back here _ad perniciem_.
+ */
+ if (fun->atom == CLASS_ATOM(cx, Object))
+ return JS_TRUE;
+
+ /*
+ * Make the prototype object to have the same parent as the function
+ * object itself.
+ */
+ proto = js_NewObject(cx, &js_ObjectClass, NULL, OBJ_GET_PARENT(cx, obj),
+ 0);
+ if (!proto)
+ return JS_FALSE;
+
+ /*
+ * ECMA (15.3.5.2) says that constructor.prototype is DontDelete for
+ * user-defined functions, but DontEnum | ReadOnly | DontDelete for
+ * native "system" constructors such as Object or Function. So lazily
+ * set the former here in fun_resolve, but eagerly define the latter
+ * in JS_InitClass, with the right attributes.
+ */
+ if (!js_SetClassPrototype(cx, obj, proto,
+ JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return JS_FALSE;
+ }
+ *objp = obj;
+ return JS_TRUE;
+ }
+
+ for (i = 0; i < JS_ARRAY_LENGTH(lazy_function_props); i++) {
+ LazyFunctionProp *lfp = &lazy_function_props[i];
+
+ atom = OFFSET_TO_ATOM(cx->runtime, lfp->atomOffset);
+ if (id == ATOM_KEY(atom)) {
+ if (!js_DefineNativeProperty(cx, obj,
+ ATOM_TO_JSID(atom), JSVAL_VOID,
+ fun_getProperty, JS_PropertyStub,
+ lfp->attrs, SPROP_HAS_SHORTID,
+ lfp->tinyid, NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ return JS_TRUE;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+fun_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+{
+ switch (type) {
+ case JSTYPE_FUNCTION:
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+ default:
+ return js_TryValueOf(cx, obj, type, vp);
+ }
+}
+
+#if JS_HAS_XDR
+
+/* XXX store parent and proto, if defined */
+static JSBool
+fun_xdrObject(JSXDRState *xdr, JSObject **objp)
+{
+ JSContext *cx;
+ JSFunction *fun;
+ uint32 nullAtom; /* flag to indicate if fun->atom is NULL */
+ uintN nargs, nvars, n;
+ uint32 localsword; /* word to xdr argument and variable counts */
+ uint32 flagsword; /* originally only flags was JS_XDRUint8'd */
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ cx = xdr->cx;
+ if (xdr->mode == JSXDR_ENCODE) {
+ fun = GET_FUNCTION_PRIVATE(cx, *objp);
+ if (!FUN_INTERPRETED(fun)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_NOT_SCRIPTED_FUNCTION,
+ JS_GetFunctionName(fun));
+ return JS_FALSE;
+ }
+ nullAtom = !fun->atom;
+ nargs = fun->nargs;
+ nvars = fun->u.i.nvars;
+ localsword = (nargs << 16) | nvars;
+ flagsword = fun->flags;
+ } else {
+ fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
+ if (!fun)
+ return JS_FALSE;
+ STOBJ_CLEAR_PARENT(FUN_OBJECT(fun));
+ STOBJ_CLEAR_PROTO(FUN_OBJECT(fun));
+#ifdef __GNUC__
+ nvars = nargs = 0; /* quell GCC uninitialized warning */
+#endif
+ }
+
+ /* From here on, control flow must flow through label out. */
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, FUN_OBJECT(fun), &tvr);
+ ok = JS_TRUE;
+
+ if (!JS_XDRUint32(xdr, &nullAtom))
+ goto bad;
+ if (!nullAtom && !js_XDRStringAtom(xdr, &fun->atom))
+ goto bad;
+ if (!JS_XDRUint32(xdr, &localsword) ||
+ !JS_XDRUint32(xdr, &flagsword)) {
+ goto bad;
+ }
+
+ if (xdr->mode == JSXDR_DECODE) {
+ nargs = localsword >> 16;
+ nvars = localsword & JS_BITMASK(16);
+ JS_ASSERT(flagsword | JSFUN_INTERPRETED);
+ fun->flags = (uint16) flagsword;
+ }
+
+ /* do arguments and local vars */
+ n = nargs + nvars;
+ if (n != 0) {
+ void *mark;
+ uintN i;
+ uintN bitmapLength;
+ uint32 *bitmap;
+ jsuword *names;
+ JSAtom *name;
+ JSLocalKind localKind;
+
+ mark = JS_ARENA_MARK(&xdr->cx->tempPool);
+
+ /*
+ * From this point the control must flow via the label release_mark.
+ *
+ * To xdr the names we prefix the names with a bitmap descriptor and
+ * then xdr the names as strings. For argument names (indexes below
+ * nargs) the corresponding bit in the bitmap is unset when the name
+ * is null. Such null names are not encoded or decoded. For variable
+ * names (indexes starting from nargs) bitmap's bit is set when the
+ * name is declared as const, not as ordinary var.
+ * */
+ bitmapLength = JS_HOWMANY(n, JS_BITS_PER_UINT32);
+ JS_ARENA_ALLOCATE_CAST(bitmap, uint32 *, &xdr->cx->tempPool,
+ bitmapLength * sizeof *bitmap);
+ if (!bitmap) {
+ js_ReportOutOfScriptQuota(xdr->cx);
+ ok = JS_FALSE;
+ goto release_mark;
+ }
+ if (xdr->mode == JSXDR_ENCODE) {
+ names = js_GetLocalNameArray(xdr->cx, fun, &xdr->cx->tempPool);
+ if (!names) {
+ ok = JS_FALSE;
+ goto release_mark;
+ }
+ memset(bitmap, 0, bitmapLength * sizeof *bitmap);
+ for (i = 0; i != n; ++i) {
+ if (i < fun->nargs
+ ? JS_LOCAL_NAME_TO_ATOM(names[i]) != NULL
+ : JS_LOCAL_NAME_IS_CONST(names[i])) {
+ bitmap[i >> JS_BITS_PER_UINT32_LOG2] |=
+ JS_BIT(i & (JS_BITS_PER_UINT32 - 1));
+ }
+ }
+ }
+#ifdef __GNUC__
+ else {
+ names = NULL; /* quell GCC uninitialized warning */
+ }
+#endif
+ for (i = 0; i != bitmapLength; ++i) {
+ ok = JS_XDRUint32(xdr, &bitmap[i]);
+ if (!ok)
+ goto release_mark;
+ }
+ for (i = 0; i != n; ++i) {
+ if (i < nargs &&
+ !(bitmap[i >> JS_BITS_PER_UINT32_LOG2] &
+ JS_BIT(i & (JS_BITS_PER_UINT32 - 1)))) {
+ if (xdr->mode == JSXDR_DECODE) {
+ ok = js_AddLocal(xdr->cx, fun, NULL, JSLOCAL_ARG);
+ if (!ok)
+ goto release_mark;
+ } else {
+ JS_ASSERT(!JS_LOCAL_NAME_TO_ATOM(names[i]));
+ }
+ continue;
+ }
+ if (xdr->mode == JSXDR_ENCODE)
+ name = JS_LOCAL_NAME_TO_ATOM(names[i]);
+ ok = js_XDRStringAtom(xdr, &name);
+ if (!ok)
+ goto release_mark;
+ if (xdr->mode == JSXDR_DECODE) {
+ localKind = (i < nargs)
+ ? JSLOCAL_ARG
+ : bitmap[i >> JS_BITS_PER_UINT32_LOG2] &
+ JS_BIT(i & (JS_BITS_PER_UINT32 - 1))
+ ? JSLOCAL_CONST
+ : JSLOCAL_VAR;
+ ok = js_AddLocal(xdr->cx, fun, name, localKind);
+ if (!ok)
+ goto release_mark;
+ }
+ }
+ ok = JS_TRUE;
+
+ release_mark:
+ JS_ARENA_RELEASE(&xdr->cx->tempPool, mark);
+ if (!ok)
+ goto out;
+
+ if (xdr->mode == JSXDR_DECODE)
+ js_FreezeLocalNames(cx, fun);
+ }
+
+ if (!js_XDRScript(xdr, &fun->u.i.script, NULL))
+ goto bad;
+
+ if (xdr->mode == JSXDR_DECODE) {
+ *objp = FUN_OBJECT(fun);
+#ifdef CHECK_SCRIPT_OWNER
+ fun->u.i.script->owner = NULL;
+#endif
+ js_CallNewScriptHook(cx, fun->u.i.script, fun);
+ }
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+
+bad:
+ ok = JS_FALSE;
+ goto out;
+}
+
+#else /* !JS_HAS_XDR */
+
+#define fun_xdrObject NULL
+
+#endif /* !JS_HAS_XDR */
+
+/*
+ * [[HasInstance]] internal method for Function objects: fetch the .prototype
+ * property of its 'this' parameter, and walks the prototype chain of v (only
+ * if v is an object) returning true if .prototype is found.
+ */
+static JSBool
+fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ jsval pval;
+
+ if (!OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &pval)) {
+ return JS_FALSE;
+ }
+
+ if (JSVAL_IS_PRIMITIVE(pval)) {
+ /*
+ * Throw a runtime error if instanceof is called on a function that
+ * has a non-object as its .prototype value.
+ */
+ js_ReportValueError(cx, JSMSG_BAD_PROTOTYPE,
+ -1, OBJECT_TO_JSVAL(obj), NULL);
+ return JS_FALSE;
+ }
+
+ return js_IsDelegate(cx, JSVAL_TO_OBJECT(pval), v, bp);
+}
+
+static void
+TraceLocalNames(JSTracer *trc, JSFunction *fun);
+
+static void
+DestroyLocalNames(JSContext *cx, JSFunction *fun);
+
+static void
+fun_trace(JSTracer *trc, JSObject *obj)
+{
+ JSFunction *fun;
+
+ /* A newborn function object may have a not yet initialized private slot. */
+ fun = (JSFunction *) JS_GetPrivate(trc->context, obj);
+ if (!fun)
+ return;
+
+ if (FUN_OBJECT(fun) != obj) {
+ /* obj is cloned function object, trace the original. */
+ JS_CALL_TRACER(trc, FUN_OBJECT(fun), JSTRACE_OBJECT, "private");
+ return;
+ }
+ if (fun->atom)
+ JS_CALL_STRING_TRACER(trc, ATOM_TO_STRING(fun->atom), "atom");
+ if (FUN_INTERPRETED(fun)) {
+ if (fun->u.i.script)
+ js_TraceScript(trc, fun->u.i.script);
+ TraceLocalNames(trc, fun);
+ }
+}
+
+static void
+fun_finalize(JSContext *cx, JSObject *obj)
+{
+ JSFunction *fun;
+
+ /* Ignore newborn and cloned function objects. */
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
+ if (!fun || FUN_OBJECT(fun) != obj)
+ return;
+
+ /*
+ * Null-check of u.i.script is required since the parser sets interpreted
+ * very early.
+ */
+ if (FUN_INTERPRETED(fun)) {
+ if (fun->u.i.script)
+ js_DestroyScript(cx, fun->u.i.script);
+ DestroyLocalNames(cx, fun);
+ }
+}
+
+static uint32
+fun_reserveSlots(JSContext *cx, JSObject *obj)
+{
+ JSFunction *fun;
+ uint32 nslots;
+
+ /*
+ * We use JS_GetPrivate and not GET_FUNCTION_PRIVATE because during
+ * js_InitFunctionClass invocation the function is called before the
+ * private slot of the function object is set.
+ */
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
+ nslots = 0;
+ if (fun && FUN_INTERPRETED(fun) && fun->u.i.script) {
+ if (fun->u.i.script->upvarsOffset != 0)
+ nslots = JS_SCRIPT_UPVARS(fun->u.i.script)->length;
+ if (fun->u.i.script->regexpsOffset != 0)
+ nslots += JS_SCRIPT_REGEXPS(fun->u.i.script)->length;
+ }
+ return nslots;
+}
+
+/*
+ * Reserve two slots in all function objects for XPConnect. Note that this
+ * does not bloat every instance, only those on which reserved slots are set,
+ * and those on which ad-hoc properties are defined.
+ */
+JS_FRIEND_DATA(JSClass) js_FunctionClass = {
+ js_Function_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(2) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, JS_PropertyStub,
+ fun_enumerate, (JSResolveOp)fun_resolve,
+ fun_convert, fun_finalize,
+ NULL, NULL,
+ NULL, NULL,
+ fun_xdrObject, fun_hasInstance,
+ JS_CLASS_TRACE(fun_trace), fun_reserveSlots
+};
+
+static JSBool
+fun_toStringHelper(JSContext *cx, uint32 indent, uintN argc, jsval *vp)
+{
+ jsval fval;
+ JSObject *obj;
+ JSFunction *fun;
+ JSString *str;
+
+ fval = JS_THIS(cx, vp);
+ if (JSVAL_IS_NULL(fval))
+ return JS_FALSE;
+
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
+ /*
+ * If we don't have a function to start off with, try converting the
+ * object to a function. If that doesn't work, complain.
+ */
+ if (!JSVAL_IS_PRIMITIVE(fval)) {
+ obj = JSVAL_TO_OBJECT(fval);
+ if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, JSTYPE_FUNCTION,
+ &fval)) {
+ return JS_FALSE;
+ }
+ vp[1] = fval;
+ }
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_INCOMPATIBLE_PROTO,
+ js_Function_str, js_toString_str,
+ JS_GetTypeName(cx, JS_TypeOfValue(cx, fval)));
+ return JS_FALSE;
+ }
+ }
+
+ obj = JSVAL_TO_OBJECT(fval);
+ if (argc != 0) {
+ indent = js_ValueToECMAUint32(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(JS_ObjectIsFunction(cx, obj));
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
+ if (!fun)
+ return JS_TRUE;
+ str = JS_DecompileFunction(cx, fun, (uintN)indent);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+fun_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ return fun_toStringHelper(cx, 0, argc, vp);
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+fun_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ return fun_toStringHelper(cx, JS_DONT_PRETTY_PRINT, argc, vp);
+}
+#endif
+
+JSBool
+js_fun_call(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval fval, *argv, *invokevp;
+ JSString *str;
+ void *mark;
+ JSBool ok;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &vp[1]))
+ return JS_FALSE;
+ fval = vp[1];
+
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
+ str = JS_ValueToString(cx, fval);
+ if (str) {
+ const char *bytes = js_GetStringBytes(cx, str);
+
+ if (bytes) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_INCOMPATIBLE_PROTO,
+ js_Function_str, js_call_str,
+ bytes);
+ }
+ }
+ return JS_FALSE;
+ }
+
+ argv = vp + 2;
+ if (argc == 0) {
+ /* Call fun with its global object as the 'this' param if no args. */
+ obj = NULL;
+ } else {
+ /* Otherwise convert the first arg to 'this' and skip over it. */
+ if (!JSVAL_IS_PRIMITIVE(argv[0]))
+ obj = JSVAL_TO_OBJECT(argv[0]);
+ else if (!js_ValueToObject(cx, argv[0], &obj))
+ return JS_FALSE;
+ argc--;
+ argv++;
+ }
+
+ /* Allocate stack space for fval, obj, and the args. */
+ invokevp = js_AllocStack(cx, 2 + argc, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ /* Push fval, obj, and the args. */
+ invokevp[0] = fval;
+ invokevp[1] = OBJECT_TO_JSVAL(obj);
+ memcpy(invokevp + 2, argv, argc * sizeof *argv);
+
+ ok = js_Invoke(cx, argc, invokevp, 0);
+ *vp = *invokevp;
+ js_FreeStack(cx, mark);
+ return ok;
+}
+
+JSBool
+js_fun_apply(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj, *aobj;
+ jsval fval, *invokevp, *sp;
+ JSString *str;
+ jsuint length;
+ JSBool arraylike, ok;
+ void *mark;
+ uintN i;
+
+ if (argc == 0) {
+ /* Will get globalObject as 'this' and no other arguments. */
+ return js_fun_call(cx, argc, vp);
+ }
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &vp[1]))
+ return JS_FALSE;
+ fval = vp[1];
+
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
+ str = JS_ValueToString(cx, fval);
+ if (str) {
+ const char *bytes = js_GetStringBytes(cx, str);
+
+ if (bytes) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_INCOMPATIBLE_PROTO,
+ js_Function_str, js_apply_str,
+ bytes);
+ }
+ }
+ return JS_FALSE;
+ }
+
+ /* Quell GCC overwarnings. */
+ aobj = NULL;
+ length = 0;
+
+ if (argc >= 2) {
+ /* If the 2nd arg is null or void, call the function with 0 args. */
+ if (JSVAL_IS_NULL(vp[3]) || JSVAL_IS_VOID(vp[3])) {
+ argc = 0;
+ } else {
+ /* The second arg must be an array (or arguments object). */
+ arraylike = JS_FALSE;
+ if (!JSVAL_IS_PRIMITIVE(vp[3])) {
+ aobj = JSVAL_TO_OBJECT(vp[3]);
+ if (!js_IsArrayLike(cx, aobj, &arraylike, &length))
+ return JS_FALSE;
+ }
+ if (!arraylike) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_APPLY_ARGS, js_apply_str);
+ return JS_FALSE;
+ }
+ }
+ }
+
+ /* Convert the first arg to 'this' and skip over it. */
+ if (!JSVAL_IS_PRIMITIVE(vp[2]))
+ obj = JSVAL_TO_OBJECT(vp[2]);
+ else if (!js_ValueToObject(cx, vp[2], &obj))
+ return JS_FALSE;
+
+ /* Allocate stack space for fval, obj, and the args. */
+ argc = (uintN)JS_MIN(length, ARRAY_INIT_LIMIT - 1);
+ invokevp = js_AllocStack(cx, 2 + argc, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ /* Push fval, obj, and aobj's elements as args. */
+ sp = invokevp;
+ *sp++ = fval;
+ *sp++ = OBJECT_TO_JSVAL(obj);
+ for (i = 0; i < argc; i++) {
+ ok = JS_GetElement(cx, aobj, (jsint)i, sp);
+ if (!ok)
+ goto out;
+ sp++;
+ }
+
+ ok = js_Invoke(cx, argc, invokevp, 0);
+ *vp = *invokevp;
+out:
+ js_FreeStack(cx, mark);
+ return ok;
+}
+
+#ifdef NARCISSUS
+static JSBool
+fun_applyConstructor(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *aobj;
+ uintN length, i;
+ void *mark;
+ jsval *invokevp, *sp;
+ JSBool ok;
+
+ if (JSVAL_IS_PRIMITIVE(vp[2]) ||
+ (aobj = JSVAL_TO_OBJECT(vp[2]),
+ OBJ_GET_CLASS(cx, aobj) != &js_ArrayClass &&
+ OBJ_GET_CLASS(cx, aobj) != &js_ArgumentsClass)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_APPLY_ARGS, "__applyConstruct__");
+ return JS_FALSE;
+ }
+
+ if (!js_GetLengthProperty(cx, aobj, &length))
+ return JS_FALSE;
+
+ if (length >= ARRAY_INIT_LIMIT)
+ length = ARRAY_INIT_LIMIT - 1;
+ invokevp = js_AllocStack(cx, 2 + length, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ sp = invokevp;
+ *sp++ = vp[1];
+ *sp++ = JSVAL_NULL; /* this is filled automagically */
+ for (i = 0; i < length; i++) {
+ ok = JS_GetElement(cx, aobj, (jsint)i, sp);
+ if (!ok)
+ goto out;
+ sp++;
+ }
+
+ ok = js_InvokeConstructor(cx, length, JS_TRUE, invokevp);
+ *vp = *invokevp;
+out:
+ js_FreeStack(cx, mark);
+ return ok;
+}
+#endif
+
+static JSFunctionSpec function_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, fun_toSource, 0,0),
+#endif
+ JS_FN(js_toString_str, fun_toString, 0,0),
+ JS_FN(js_apply_str, js_fun_apply, 2,0),
+ JS_FN(js_call_str, js_fun_call, 1,0),
+#ifdef NARCISSUS
+ JS_FN("__applyConstructor__", fun_applyConstructor, 1,0),
+#endif
+ JS_FS_END
+};
+
+static JSBool
+Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSStackFrame *fp, *caller;
+ JSFunction *fun;
+ JSObject *parent;
+ uintN i, n, lineno;
+ JSAtom *atom;
+ const char *filename;
+ JSBool ok;
+ JSString *str, *arg;
+ JSTokenStream ts;
+ JSPrincipals *principals;
+ jschar *collected_args, *cp;
+ void *mark;
+ size_t arg_length, args_length, old_args_length;
+ JSTokenType tt;
+
+ fp = cx->fp;
+ if (!(fp->flags & JSFRAME_CONSTRUCTING)) {
+ obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ } else {
+ /*
+ * The constructor is called before the private slot is initialized so
+ * we must use JS_GetPrivate, not GET_FUNCTION_PRIVATE here.
+ */
+ if (JS_GetPrivate(cx, obj))
+ return JS_TRUE;
+ }
+
+ /*
+ * NB: (new Function) is not lexically closed by its caller, it's just an
+ * anonymous function in the top-level scope that its constructor inhabits.
+ * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
+ * and so would a call to f from another top-level's script or function.
+ *
+ * In older versions, before call objects, a new Function was adopted by
+ * its running context's globalObject, which might be different from the
+ * top-level reachable from scopeChain (in HTML frames, e.g.).
+ */
+ parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2]));
+
+ fun = js_NewFunction(cx, obj, NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
+ parent, cx->runtime->atomState.anonymousAtom);
+
+ if (!fun)
+ return JS_FALSE;
+
+ /*
+ * Function is static and not called directly by other functions in this
+ * file, therefore it is callable only as a native function by js_Invoke.
+ * Find the scripted caller, possibly skipping other native frames such as
+ * are built for Function.prototype.call or .apply activations that invoke
+ * Function indirectly from a script.
+ */
+ JS_ASSERT(!fp->script && fp->fun && fp->fun->u.n.native == Function);
+ caller = JS_GetScriptedCaller(cx, fp);
+ if (caller) {
+ principals = JS_EvalFramePrincipals(cx, fp, caller);
+ filename = js_ComputeFilename(cx, caller, principals, &lineno);
+ } else {
+ filename = NULL;
+ lineno = 0;
+ principals = NULL;
+ }
+
+ /* Belt-and-braces: check that the caller has access to parent. */
+ if (!js_CheckPrincipalsAccess(cx, parent, principals,
+ CLASS_ATOM(cx, Function))) {
+ return JS_FALSE;
+ }
+
+ n = argc ? argc - 1 : 0;
+ if (n > 0) {
+ enum { OK, BAD, BAD_FORMAL } state;
+
+ /*
+ * Collect the function-argument arguments into one string, separated
+ * by commas, then make a tokenstream from that string, and scan it to
+ * get the arguments. We need to throw the full scanner at the
+ * problem, because the argument string can legitimately contain
+ * comments and linefeeds. XXX It might be better to concatenate
+ * everything up into a function definition and pass it to the
+ * compiler, but doing it this way is less of a delta from the old
+ * code. See ECMA 15.3.2.1.
+ */
+ state = BAD_FORMAL;
+ args_length = 0;
+ for (i = 0; i < n; i++) {
+ /* Collect the lengths for all the function-argument arguments. */
+ arg = js_ValueToString(cx, argv[i]);
+ if (!arg)
+ return JS_FALSE;
+ argv[i] = STRING_TO_JSVAL(arg);
+
+ /*
+ * Check for overflow. The < test works because the maximum
+ * JSString length fits in 2 fewer bits than size_t has.
+ */
+ old_args_length = args_length;
+ args_length = old_args_length + JSSTRING_LENGTH(arg);
+ if (args_length < old_args_length) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+ }
+
+ /* Add 1 for each joining comma and check for overflow (two ways). */
+ old_args_length = args_length;
+ args_length = old_args_length + n - 1;
+ if (args_length < old_args_length ||
+ args_length >= ~(size_t)0 / sizeof(jschar)) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+
+ /*
+ * Allocate a string to hold the concatenated arguments, including room
+ * for a terminating 0. Mark cx->tempPool for later release, to free
+ * collected_args and its tokenstream in one swoop.
+ */
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ JS_ARENA_ALLOCATE_CAST(cp, jschar *, &cx->tempPool,
+ (args_length+1) * sizeof(jschar));
+ if (!cp) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ collected_args = cp;
+
+ /*
+ * Concatenate the arguments into the new string, separated by commas.
+ */
+ for (i = 0; i < n; i++) {
+ arg = JSVAL_TO_STRING(argv[i]);
+ arg_length = JSSTRING_LENGTH(arg);
+ (void) js_strncpy(cp, JSSTRING_CHARS(arg), arg_length);
+ cp += arg_length;
+
+ /* Add separating comma or terminating 0. */
+ *cp++ = (i + 1 < n) ? ',' : 0;
+ }
+
+ /* Initialize a tokenstream that reads from the given string. */
+ if (!js_InitTokenStream(cx, &ts, collected_args, args_length,
+ NULL, filename, lineno)) {
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return JS_FALSE;
+ }
+
+ /* The argument string may be empty or contain no tokens. */
+ tt = js_GetToken(cx, &ts);
+ if (tt != TOK_EOF) {
+ for (;;) {
+ /*
+ * Check that it's a name. This also implicitly guards against
+ * TOK_ERROR, which was already reported.
+ */
+ if (tt != TOK_NAME)
+ goto after_args;
+
+ /*
+ * Get the atom corresponding to the name from the token
+ * stream; we're assured at this point that it's a valid
+ * identifier.
+ */
+ atom = CURRENT_TOKEN(&ts).t_atom;
+
+ /* Check for a duplicate parameter name. */
+ if (js_LookupLocal(cx, fun, atom, NULL) != JSLOCAL_NONE) {
+ const char *name;
+
+ name = js_AtomToPrintableString(cx, atom);
+ ok = name &&
+ js_ReportCompileErrorNumber(cx, &ts, NULL,
+ JSREPORT_WARNING |
+ JSREPORT_STRICT,
+ JSMSG_DUPLICATE_FORMAL,
+ name);
+ if (!ok)
+ goto after_args;
+ }
+ if (!js_AddLocal(cx, fun, atom, JSLOCAL_ARG))
+ goto after_args;
+
+ /*
+ * Get the next token. Stop on end of stream. Otherwise
+ * insist on a comma, get another name, and iterate.
+ */
+ tt = js_GetToken(cx, &ts);
+ if (tt == TOK_EOF)
+ break;
+ if (tt != TOK_COMMA)
+ goto after_args;
+ tt = js_GetToken(cx, &ts);
+ }
+ }
+
+ state = OK;
+ after_args:
+ if (state == BAD_FORMAL && !(ts.flags & TSF_ERROR)) {
+ /*
+ * Report "malformed formal parameter" iff no illegal char or
+ * similar scanner error was already reported.
+ */
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_FORMAL);
+ }
+ js_CloseTokenStream(cx, &ts);
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ if (state != OK)
+ return JS_FALSE;
+ }
+
+ if (argc) {
+ str = js_ValueToString(cx, argv[argc-1]);
+ if (!str)
+ return JS_FALSE;
+ argv[argc-1] = STRING_TO_JSVAL(str);
+ } else {
+ str = cx->runtime->emptyString;
+ }
+
+ return js_CompileFunctionBody(cx, fun, principals,
+ JSSTRING_CHARS(str), JSSTRING_LENGTH(str),
+ filename, lineno);
+}
+
+JSObject *
+js_InitFunctionClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+ JSFunction *fun;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1,
+ function_props, function_methods, NULL, NULL);
+ if (!proto)
+ return NULL;
+ fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL);
+ if (!fun)
+ goto bad;
+ fun->u.i.script = js_NewScript(cx, 1, 1, 0, 0, 0, 0, 0);
+ if (!fun->u.i.script)
+ goto bad;
+ fun->u.i.script->code[0] = JSOP_STOP;
+ *SCRIPT_NOTES(fun->u.i.script) = SRC_NULL;
+#ifdef CHECK_SCRIPT_OWNER
+ fun->u.i.script->owner = NULL;
+#endif
+ return proto;
+
+bad:
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+}
+
+JSObject *
+js_InitCallClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_CallClass, NULL, 0,
+ NULL, NULL, NULL, NULL);
+ if (!proto)
+ return NULL;
+
+ /*
+ * Null Call.prototype's proto slot so that Object.prototype.* does not
+ * pollute the scope of heavyweight functions.
+ */
+ OBJ_CLEAR_PROTO(cx, proto);
+ return proto;
+}
+
+JSFunction *
+js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
+ uintN flags, JSObject *parent, JSAtom *atom)
+{
+ JSFunction *fun;
+
+ if (funobj) {
+ JS_ASSERT(HAS_FUNCTION_CLASS(funobj));
+ OBJ_SET_PARENT(cx, funobj, parent);
+ } else {
+ funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent, 0);
+ if (!funobj)
+ return NULL;
+ }
+ JS_ASSERT(JSVAL_IS_VOID(funobj->fslots[JSSLOT_PRIVATE]));
+ fun = (JSFunction *) funobj;
+
+ /* Initialize all function members. */
+ fun->nargs = nargs;
+ fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_INTERPRETED | JSFUN_TRACEABLE);
+ if (flags & JSFUN_INTERPRETED) {
+ JS_ASSERT(!native);
+ JS_ASSERT(nargs == 0);
+ fun->u.i.nvars = 0;
+ fun->u.i.nupvars = 0;
+ fun->u.i.script = NULL;
+#ifdef DEBUG
+ fun->u.i.names.taggedAtom = 0;
+#endif
+ } else {
+ fun->u.n.extra = 0;
+ fun->u.n.spare = 0;
+ if (flags & JSFUN_TRACEABLE) {
+#ifdef JS_TRACER
+ JSTraceableNative *trcinfo = (JSTraceableNative *) native;
+ fun->u.n.native = (JSNative) trcinfo->native;
+ FUN_TRCINFO(fun) = trcinfo;
+#else
+ JS_ASSERT(0);
+#endif
+ } else {
+ fun->u.n.native = native;
+ FUN_CLASP(fun) = NULL;
+ }
+ }
+ fun->atom = atom;
+
+ /* Set private to self to indicate non-cloned fully initialized function. */
+ FUN_OBJECT(fun)->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
+ return fun;
+}
+
+JSObject *
+js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
+{
+ JSObject *clone;
+
+ /*
+ * The cloned function object does not need the extra fields beyond
+ * JSObject as it points to fun via the private slot.
+ */
+ clone = js_NewObject(cx, &js_FunctionClass, NULL, parent,
+ sizeof(JSObject));
+ if (!clone)
+ return NULL;
+ clone->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
+ return clone;
+}
+
+JSFunction *
+js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
+ uintN nargs, uintN attrs)
+{
+ JSFunction *fun;
+ JSPropertyOp gsop;
+
+ fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom);
+ if (!fun)
+ return NULL;
+ gsop = (attrs & JSFUN_STUB_GSOPS) ? JS_PropertyStub : NULL;
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
+ OBJECT_TO_JSVAL(FUN_OBJECT(fun)),
+ gsop, gsop,
+ attrs & ~JSFUN_FLAGS_MASK, NULL)) {
+ return NULL;
+ }
+ return fun;
+}
+
+#if (JSV2F_CONSTRUCT & JSV2F_SEARCH_STACK)
+# error "JSINVOKE_CONSTRUCT and JSV2F_SEARCH_STACK are not disjoint!"
+#endif
+
+JSFunction *
+js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags)
+{
+ jsval v;
+ JSObject *obj;
+
+ v = *vp;
+ obj = NULL;
+ if (JSVAL_IS_OBJECT(v)) {
+ obj = JSVAL_TO_OBJECT(v);
+ if (obj && OBJ_GET_CLASS(cx, obj) != &js_FunctionClass) {
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &v))
+ return NULL;
+ obj = VALUE_IS_FUNCTION(cx, v) ? JSVAL_TO_OBJECT(v) : NULL;
+ }
+ }
+ if (!obj) {
+ js_ReportIsNotFunction(cx, vp, flags);
+ return NULL;
+ }
+ return GET_FUNCTION_PRIVATE(cx, obj);
+}
+
+JSObject *
+js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
+{
+ JSFunction *fun;
+ JSStackFrame *caller;
+ JSPrincipals *principals;
+
+ if (VALUE_IS_FUNCTION(cx, *vp))
+ return JSVAL_TO_OBJECT(*vp);
+
+ fun = js_ValueToFunction(cx, vp, flags);
+ if (!fun)
+ return NULL;
+ *vp = OBJECT_TO_JSVAL(FUN_OBJECT(fun));
+
+ caller = JS_GetScriptedCaller(cx, cx->fp);
+ if (caller) {
+ principals = JS_StackFramePrincipals(cx, caller);
+ } else {
+ /* No scripted caller, don't allow access. */
+ principals = NULL;
+ }
+
+ if (!js_CheckPrincipalsAccess(cx, FUN_OBJECT(fun), principals,
+ fun->atom
+ ? fun->atom
+ : cx->runtime->atomState.anonymousAtom)) {
+ return NULL;
+ }
+ return FUN_OBJECT(fun);
+}
+
+JSObject *
+js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags)
+{
+ JSObject *callable;
+
+ callable = JSVAL_IS_PRIMITIVE(*vp) ? NULL : JSVAL_TO_OBJECT(*vp);
+ if (callable &&
+ ((callable->map->ops == &js_ObjectOps)
+ ? OBJ_GET_CLASS(cx, callable)->call
+ : callable->map->ops->call)) {
+ *vp = OBJECT_TO_JSVAL(callable);
+ } else {
+ callable = js_ValueToFunctionObject(cx, vp, flags);
+ }
+ return callable;
+}
+
+void
+js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags)
+{
+ JSStackFrame *fp;
+ uintN error;
+ const char *name, *source;
+ JSTempValueRooter tvr;
+
+ for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
+ continue;
+ name = source = NULL;
+ JS_PUSH_TEMP_ROOT_STRING(cx, NULL, &tvr);
+ if (flags & JSV2F_ITERATOR) {
+ error = JSMSG_BAD_ITERATOR;
+ name = js_iterator_str;
+ tvr.u.string = js_ValueToSource(cx, *vp);
+ if (!tvr.u.string)
+ goto out;
+ tvr.u.string = js_QuoteString(cx, tvr.u.string, 0);
+ if (!tvr.u.string)
+ goto out;
+ source = js_GetStringBytes(cx, tvr.u.string);
+ if (!source)
+ goto out;
+ } else if (flags & JSV2F_CONSTRUCT) {
+ error = JSMSG_NOT_CONSTRUCTOR;
+ } else {
+ error = JSMSG_NOT_FUNCTION;
+ }
+
+ js_ReportValueError3(cx, error,
+ (fp && fp->regs &&
+ StackBase(fp) <= vp && vp < fp->regs->sp)
+ ? vp - fp->regs->sp
+ : (flags & JSV2F_SEARCH_STACK)
+ ? JSDVG_SEARCH_STACK
+ : JSDVG_IGNORE_STACK,
+ *vp, NULL,
+ name, source);
+
+ out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+}
+
+/*
+ * When a function has between 2 and MAX_ARRAY_LOCALS arguments and variables,
+ * their name are stored as the JSLocalNames.array.
+ */
+#define MAX_ARRAY_LOCALS 8
+
+JS_STATIC_ASSERT(2 <= MAX_ARRAY_LOCALS);
+JS_STATIC_ASSERT(MAX_ARRAY_LOCALS < JS_BITMASK(16));
+
+/*
+ * We use the lowest bit of the string atom to distinguish const from var
+ * name when there is only single name or when names are stored as an array.
+ */
+JS_STATIC_ASSERT((JSVAL_STRING & 1) == 0);
+
+/*
+ * When we use a hash table to store the local names, we use a singly linked
+ * list to record the indexes of duplicated parameter names to preserve the
+ * duplicates for the decompiler.
+ */
+typedef struct JSNameIndexPair JSNameIndexPair;
+
+struct JSNameIndexPair {
+ JSAtom *name;
+ uint16 index;
+ JSNameIndexPair *link;
+};
+
+struct JSLocalNameMap {
+ JSDHashTable names;
+ JSNameIndexPair *lastdup;
+};
+
+typedef struct JSLocalNameHashEntry {
+ JSDHashEntryHdr hdr;
+ JSAtom *name;
+ uint16 index;
+ uint8 localKind;
+} JSLocalNameHashEntry;
+
+static void
+FreeLocalNameHash(JSContext *cx, JSLocalNameMap *map)
+{
+ JSNameIndexPair *dup, *next;
+
+ for (dup = map->lastdup; dup; dup = next) {
+ next = dup->link;
+ JS_free(cx, dup);
+ }
+ JS_DHashTableFinish(&map->names);
+ JS_free(cx, map);
+}
+
+static JSBool
+HashLocalName(JSContext *cx, JSLocalNameMap *map, JSAtom *name,
+ JSLocalKind localKind, uintN index)
+{
+ JSLocalNameHashEntry *entry;
+ JSNameIndexPair *dup;
+
+ JS_ASSERT(index <= JS_BITMASK(16));
+#if JS_HAS_DESTRUCTURING
+ if (!name) {
+ /* A destructuring pattern does not need a hash entry. */
+ JS_ASSERT(localKind == JSLOCAL_ARG);
+ return JS_TRUE;
+ }
+#endif
+ JS_ASSERT(ATOM_IS_STRING(name));
+ entry = (JSLocalNameHashEntry *)
+ JS_DHashTableOperate(&map->names, name, JS_DHASH_ADD);
+ if (!entry) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ if (entry->name) {
+ JS_ASSERT(entry->name == name);
+ JS_ASSERT(entry->localKind == JSLOCAL_ARG);
+ dup = (JSNameIndexPair *) JS_malloc(cx, sizeof *dup);
+ if (!dup)
+ return JS_FALSE;
+ dup->name = entry->name;
+ dup->index = entry->index;
+ dup->link = map->lastdup;
+ map->lastdup = dup;
+ }
+ entry->name = name;
+ entry->index = (uint16) index;
+ entry->localKind = (uint8) localKind;
+ return JS_TRUE;
+}
+
+JSBool
+js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
+{
+ jsuword taggedAtom;
+ uint16 *indexp;
+ uintN n, i;
+ jsuword *array;
+ JSLocalNameMap *map;
+
+ JS_ASSERT(FUN_INTERPRETED(fun));
+ JS_ASSERT(!fun->u.i.script);
+ JS_ASSERT(((jsuword) atom & 1) == 0);
+ taggedAtom = (jsuword) atom;
+ if (kind == JSLOCAL_ARG) {
+ indexp = &fun->nargs;
+ } else if (kind == JSLOCAL_UPVAR) {
+ indexp = &fun->u.i.nupvars;
+ } else {
+ indexp = &fun->u.i.nvars;
+ if (kind == JSLOCAL_CONST)
+ taggedAtom |= 1;
+ else
+ JS_ASSERT(kind == JSLOCAL_VAR);
+ }
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ if (n == 0) {
+ JS_ASSERT(fun->u.i.names.taggedAtom == 0);
+ fun->u.i.names.taggedAtom = taggedAtom;
+ } else if (n < MAX_ARRAY_LOCALS) {
+ if (n > 1) {
+ array = fun->u.i.names.array;
+ } else {
+ array = (jsuword *) JS_malloc(cx, MAX_ARRAY_LOCALS * sizeof *array);
+ if (!array)
+ return JS_FALSE;
+ array[0] = fun->u.i.names.taggedAtom;
+ fun->u.i.names.array = array;
+ }
+ if (kind == JSLOCAL_ARG) {
+ /*
+ * A destructuring argument pattern adds variables, not arguments,
+ * so for the following arguments nvars != 0.
+ */
+#if JS_HAS_DESTRUCTURING
+ if (fun->u.i.nvars != 0) {
+ memmove(array + fun->nargs + 1, array + fun->nargs,
+ fun->u.i.nvars * sizeof *array);
+ }
+#else
+ JS_ASSERT(fun->u.i.nvars == 0);
+#endif
+ array[fun->nargs] = taggedAtom;
+ } else {
+ array[n] = taggedAtom;
+ }
+ } else if (n == MAX_ARRAY_LOCALS) {
+ array = fun->u.i.names.array;
+ map = (JSLocalNameMap *) JS_malloc(cx, sizeof *map);
+ if (!map)
+ return JS_FALSE;
+ if (!JS_DHashTableInit(&map->names, JS_DHashGetStubOps(),
+ NULL, sizeof(JSLocalNameHashEntry),
+ JS_DHASH_DEFAULT_CAPACITY(MAX_ARRAY_LOCALS
+ * 2))) {
+ JS_ReportOutOfMemory(cx);
+ JS_free(cx, map);
+ return JS_FALSE;
+ }
+
+ map->lastdup = NULL;
+ for (i = 0; i != MAX_ARRAY_LOCALS; ++i) {
+ taggedAtom = array[i];
+ if (!HashLocalName(cx, map, (JSAtom *) (taggedAtom & ~1),
+ (i < fun->nargs)
+ ? JSLOCAL_ARG
+ : (taggedAtom & 1) ? JSLOCAL_CONST : JSLOCAL_VAR,
+ (i < fun->nargs) ? i : i - fun->nargs)) {
+ FreeLocalNameHash(cx, map);
+ return JS_FALSE;
+ }
+ }
+ if (!HashLocalName(cx, map, atom, kind, *indexp)) {
+ FreeLocalNameHash(cx, map);
+ return JS_FALSE;
+ }
+
+ /*
+ * At this point the entry is added and we cannot fail. It is time
+ * to replace fun->u.i.names with the built map.
+ */
+ fun->u.i.names.map = map;
+ JS_free(cx, array);
+ } else {
+ if (*indexp == JS_BITMASK(16)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ (kind == JSLOCAL_ARG)
+ ? JSMSG_TOO_MANY_FUN_ARGS
+ : JSMSG_TOO_MANY_LOCALS);
+ return JS_FALSE;
+ }
+ if (!HashLocalName(cx, fun->u.i.names.map, atom, kind, *indexp))
+ return JS_FALSE;
+ }
+
+ /* Update the argument or variable counter. */
+ ++*indexp;
+ return JS_TRUE;
+}
+
+JSLocalKind
+js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp)
+{
+ uintN n, i, upvar_base;
+ jsuword *array;
+ JSLocalNameHashEntry *entry;
+
+ JS_ASSERT(FUN_INTERPRETED(fun));
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ if (n == 0)
+ return JSLOCAL_NONE;
+ if (n <= MAX_ARRAY_LOCALS) {
+ array = (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
+
+ /* Search from the tail to pick up the last duplicated name. */
+ i = n;
+ upvar_base = JS_UPVAR_LOCAL_NAME_START(fun);
+ do {
+ --i;
+ if (atom == JS_LOCAL_NAME_TO_ATOM(array[i])) {
+ if (i < fun->nargs) {
+ if (indexp)
+ *indexp = i;
+ return JSLOCAL_ARG;
+ }
+ if (i >= upvar_base) {
+ if (indexp)
+ *indexp = i - upvar_base;
+ return JSLOCAL_UPVAR;
+ }
+ if (indexp)
+ *indexp = i - fun->nargs;
+ return JS_LOCAL_NAME_IS_CONST(array[i])
+ ? JSLOCAL_CONST
+ : JSLOCAL_VAR;
+ }
+ } while (i != 0);
+ } else {
+ entry = (JSLocalNameHashEntry *)
+ JS_DHashTableOperate(&fun->u.i.names.map->names, atom,
+ JS_DHASH_LOOKUP);
+ if (JS_DHASH_ENTRY_IS_BUSY(&entry->hdr)) {
+ JS_ASSERT(entry->localKind != JSLOCAL_NONE);
+ if (indexp)
+ *indexp = entry->index;
+ return (JSLocalKind) entry->localKind;
+ }
+ }
+ return JSLOCAL_NONE;
+}
+
+typedef struct JSLocalNameEnumeratorArgs {
+ JSFunction *fun;
+ jsuword *names;
+#ifdef DEBUG
+ uintN nCopiedArgs;
+ uintN nCopiedVars;
+#endif
+} JSLocalNameEnumeratorArgs;
+
+static JSDHashOperator
+get_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSLocalNameHashEntry *entry;
+ JSLocalNameEnumeratorArgs *args;
+ uint i;
+ jsuword constFlag;
+
+ entry = (JSLocalNameHashEntry *) hdr;
+ args = (JSLocalNameEnumeratorArgs *) arg;
+ JS_ASSERT(entry->name);
+ if (entry->localKind == JSLOCAL_ARG) {
+ JS_ASSERT(entry->index < args->fun->nargs);
+ JS_ASSERT(args->nCopiedArgs++ < args->fun->nargs);
+ i = entry->index;
+ constFlag = 0;
+ } else {
+ JS_ASSERT(entry->localKind == JSLOCAL_VAR ||
+ entry->localKind == JSLOCAL_CONST);
+ JS_ASSERT(entry->index < args->fun->u.i.nvars);
+ JS_ASSERT(args->nCopiedVars++ < args->fun->u.i.nvars);
+ i = args->fun->nargs + entry->index;
+ constFlag = (entry->localKind == JSLOCAL_CONST);
+ }
+ args->names[i] = (jsuword) entry->name | constFlag;
+ return JS_DHASH_NEXT;
+}
+
+jsuword *
+js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
+{
+ uintN n;
+ jsuword *names;
+ JSLocalNameMap *map;
+ JSLocalNameEnumeratorArgs args;
+ JSNameIndexPair *dup;
+
+ JS_ASSERT(FUN_INTERPRETED(fun));
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ JS_ASSERT(n != 0);
+
+ if (n <= MAX_ARRAY_LOCALS)
+ return (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
+
+ /*
+ * No need to check for overflow of the allocation size as we are making a
+ * copy of already allocated data. As such it must fit size_t.
+ */
+ JS_ARENA_ALLOCATE_CAST(names, jsuword *, pool, (size_t) n * sizeof *names);
+ if (!names) {
+ js_ReportOutOfScriptQuota(cx);
+ return NULL;
+ }
+
+#if JS_HAS_DESTRUCTURING
+ /* Some parameter names can be NULL due to destructuring patterns. */
+ memset(names, 0, fun->nargs * sizeof *names);
+#endif
+ map = fun->u.i.names.map;
+ args.fun = fun;
+ args.names = names;
+#ifdef DEBUG
+ args.nCopiedArgs = 0;
+ args.nCopiedVars = 0;
+#endif
+ JS_DHashTableEnumerate(&map->names, get_local_names_enumerator, &args);
+ for (dup = map->lastdup; dup; dup = dup->link) {
+ JS_ASSERT(dup->index < fun->nargs);
+ JS_ASSERT(args.nCopiedArgs++ < fun->nargs);
+ names[dup->index] = (jsuword) dup->name;
+ }
+#if !JS_HAS_DESTRUCTURING
+ JS_ASSERT(args.nCopiedArgs == fun->nargs);
+#endif
+ JS_ASSERT(args.nCopiedVars == fun->u.i.nvars);
+
+ return names;
+}
+
+static JSDHashOperator
+trace_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSLocalNameHashEntry *entry;
+ JSTracer *trc;
+
+ entry = (JSLocalNameHashEntry *) hdr;
+ JS_ASSERT(entry->name);
+ trc = (JSTracer *) arg;
+ JS_SET_TRACING_INDEX(trc,
+ entry->localKind == JSLOCAL_ARG ? "arg" : "var",
+ entry->index);
+ JS_CallTracer(trc, ATOM_TO_STRING(entry->name), JSTRACE_STRING);
+ return JS_DHASH_NEXT;
+}
+
+static void
+TraceLocalNames(JSTracer *trc, JSFunction *fun)
+{
+ uintN n, i;
+ JSAtom *atom;
+ jsuword *array;
+
+ JS_ASSERT(FUN_INTERPRETED(fun));
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ if (n == 0)
+ return;
+ if (n <= MAX_ARRAY_LOCALS) {
+ array = (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
+ i = n;
+ do {
+ --i;
+ atom = (JSAtom *) (array[i] & ~1);
+ if (atom) {
+ JS_SET_TRACING_INDEX(trc,
+ i < fun->nargs ? "arg" : "var",
+ i < fun->nargs ? i : i - fun->nargs);
+ JS_CallTracer(trc, ATOM_TO_STRING(atom), JSTRACE_STRING);
+ }
+ } while (i != 0);
+ } else {
+ JS_DHashTableEnumerate(&fun->u.i.names.map->names,
+ trace_local_names_enumerator, trc);
+
+ /*
+ * No need to trace the list of duplicates in map->lastdup as the
+ * names there are traced when enumerating the hash table.
+ */
+ }
+}
+
+void
+DestroyLocalNames(JSContext *cx, JSFunction *fun)
+{
+ uintN n;
+
+ n = fun->nargs + fun->u.i.nvars;
+ if (n <= 1)
+ return;
+ if (n <= MAX_ARRAY_LOCALS)
+ JS_free(cx, fun->u.i.names.array);
+ else
+ FreeLocalNameHash(cx, fun->u.i.names.map);
+}
+
+void
+js_FreezeLocalNames(JSContext *cx, JSFunction *fun)
+{
+ uintN n;
+ jsuword *array;
+
+ JS_ASSERT(FUN_INTERPRETED(fun));
+ JS_ASSERT(!fun->u.i.script);
+ n = fun->nargs + fun->u.i.nvars + fun->u.i.nupvars;
+ if (2 <= n && n < MAX_ARRAY_LOCALS) {
+ /* Shrink over-allocated array ignoring realloc failures. */
+ array = (jsuword *) JS_realloc(cx, fun->u.i.names.array,
+ n * sizeof *array);
+ if (array)
+ fun->u.i.names.array = array;
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsfun.h b/tools/node_modules/expresso/deps/jscoverage/js/jsfun.h
new file mode 100644
index 0000000..d13ccfd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsfun.h
@@ -0,0 +1,296 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsfun_h___
+#define jsfun_h___
+/*
+ * JS function definitions.
+ */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsobj.h"
+
+JS_BEGIN_EXTERN_C
+
+typedef struct JSLocalNameMap JSLocalNameMap;
+
+/*
+ * Depending on the number of arguments and variables in the function their
+ * names and attributes are stored either as a single atom or as an array of
+ * tagged atoms (when there are few locals) or as a hash-based map (when there
+ * are many locals). In the first 2 cases the lowest bit of the atom is used
+ * as a tag to distinguish const from var. See jsfun.c for details.
+ */
+typedef union JSLocalNames {
+ jsuword taggedAtom;
+ jsuword *array;
+ JSLocalNameMap *map;
+} JSLocalNames;
+
+struct JSFunction {
+ JSObject object; /* GC'ed object header */
+ uint16 nargs; /* maximum number of specified arguments,
+ reflected as f.length/f.arity */
+ uint16 flags; /* flags, see JSFUN_* below and in jsapi.h */
+ union {
+ struct {
+ uint16 extra; /* number of arg slots for local GC roots */
+ uint16 spare; /* reserved for future use */
+ JSNative native; /* native method pointer or null */
+ union {
+ JSClass *clasp; /* class of objects constructed
+ by this function */
+ JSTraceableNative *trcinfo; /* tracer metadata; can be first
+ element of array */
+ } u;
+ } n;
+ struct {
+ uint16 nvars; /* number of local variables */
+ uint16 nupvars; /* number of upvars (computable from script
+ but here for faster access) */
+ JSScript *script; /* interpreted bytecode descriptor or null */
+ JSLocalNames names; /* argument and variable names */
+ } i;
+ } u;
+ JSAtom *atom; /* name for diagnostics and decompiling */
+};
+
+#define JSFUN_TRACEABLE 0x2000 /* can trace across calls to this native
+ function; use FUN_TRCINFO if set,
+ FUN_CLASP if unset */
+#define JSFUN_EXPR_CLOSURE 0x4000 /* expression closure: function(x)x*x */
+#define JSFUN_INTERPRETED 0x8000 /* use u.i if set, u.n if unset */
+
+#define JSFUN_SCRIPT_OR_FAST_NATIVE (JSFUN_INTERPRETED | JSFUN_FAST_NATIVE)
+
+#define FUN_OBJECT(fun) (&(fun)->object)
+#define FUN_INTERPRETED(fun) ((fun)->flags & JSFUN_INTERPRETED)
+#define FUN_SLOW_NATIVE(fun) (!((fun)->flags & JSFUN_SCRIPT_OR_FAST_NATIVE))
+#define FUN_SCRIPT(fun) (FUN_INTERPRETED(fun) ? (fun)->u.i.script : NULL)
+#define FUN_NATIVE(fun) (FUN_SLOW_NATIVE(fun) ? (fun)->u.n.native : NULL)
+#define FUN_FAST_NATIVE(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
+ ? (JSFastNative) (fun)->u.n.native \
+ : NULL)
+#define FUN_MINARGS(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
+ ? 0 \
+ : (fun)->nargs)
+#define FUN_CLASP(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
+ JS_ASSERT(!((fun)->flags & JSFUN_TRACEABLE)), \
+ fun->u.n.u.clasp)
+#define FUN_TRCINFO(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
+ JS_ASSERT((fun)->flags & JSFUN_TRACEABLE), \
+ fun->u.n.u.trcinfo)
+
+/*
+ * Traceable native. This expands to a JSFunctionSpec initializer (like JS_FN
+ * in jsapi.h). fastcall is a JSFastNative; trcinfo is a JSTraceableNative *.
+ */
+#ifdef JS_TRACER
+/* MSVC demands the intermediate (void *) cast here. */
+# define JS_TN(name,fastcall,nargs,flags,trcinfo) \
+ {name, (JSNative)(void *)(trcinfo), nargs, \
+ (flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS | JSFUN_TRACEABLE, 0}
+#else
+# define JS_TN(name,fastcall,nargs,flags,trcinfo) \
+ JS_FN(name, fastcall, nargs, flags)
+#endif
+
+extern JSClass js_ArgumentsClass;
+extern JS_FRIEND_DATA(JSClass) js_CallClass;
+
+/* JS_FRIEND_DATA so that VALUE_IS_FUNCTION is callable from the shell. */
+extern JS_FRIEND_DATA(JSClass) js_FunctionClass;
+
+#define HAS_FUNCTION_CLASS(obj) (STOBJ_GET_CLASS(obj) == &js_FunctionClass)
+
+/*
+ * NB: jsapi.h and jsobj.h must be included before any call to this macro.
+ */
+#define VALUE_IS_FUNCTION(cx, v) \
+ (!JSVAL_IS_PRIMITIVE(v) && HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(v)))
+
+/*
+ * Macro to access the private slot of the function object after the slot is
+ * initialized.
+ */
+#define GET_FUNCTION_PRIVATE(cx, funobj) \
+ (JS_ASSERT(HAS_FUNCTION_CLASS(funobj)), \
+ (JSFunction *) OBJ_GET_PRIVATE(cx, funobj))
+
+extern JSObject *
+js_InitFunctionClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitArgumentsClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitCallClass(JSContext *cx, JSObject *obj);
+
+extern JSFunction *
+js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
+ uintN flags, JSObject *parent, JSAtom *atom);
+
+extern void
+js_TraceFunction(JSTracer *trc, JSFunction *fun);
+
+extern void
+js_FinalizeFunction(JSContext *cx, JSFunction *fun);
+
+extern JSObject *
+js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent);
+
+extern JSBool
+js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *object);
+
+extern JSFunction *
+js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
+ uintN nargs, uintN flags);
+
+/*
+ * Flags for js_ValueToFunction and js_ReportIsNotFunction. We depend on the
+ * fact that JSINVOKE_CONSTRUCT (aka JSFRAME_CONSTRUCTING) is 1, and test that
+ * with #if/#error in jsfun.c.
+ */
+#define JSV2F_CONSTRUCT JSINVOKE_CONSTRUCT
+#define JSV2F_ITERATOR JSINVOKE_ITERATOR
+#define JSV2F_SEARCH_STACK 0x10000
+
+extern JSFunction *
+js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags);
+
+extern JSObject *
+js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags);
+
+extern JSObject *
+js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags);
+
+extern void
+js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags);
+
+extern JSObject *
+js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent);
+
+extern JS_FRIEND_API(JSBool)
+js_PutCallObject(JSContext *cx, JSStackFrame *fp);
+
+extern JSBool
+js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSBool
+js_GetCallVar(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+extern JSBool
+js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp);
+
+extern JSBool
+js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, jsval *vp);
+
+extern JSObject *
+js_GetArgsObject(JSContext *cx, JSStackFrame *fp);
+
+extern JS_FRIEND_API(JSBool)
+js_PutArgsObject(JSContext *cx, JSStackFrame *fp);
+
+extern JSBool
+js_XDRFunction(JSXDRState *xdr, JSObject **objp);
+
+typedef enum JSLocalKind {
+ JSLOCAL_NONE,
+ JSLOCAL_ARG,
+ JSLOCAL_VAR,
+ JSLOCAL_CONST,
+ JSLOCAL_UPVAR
+} JSLocalKind;
+
+#define JS_UPVAR_LOCAL_NAME_START(fun) ((fun)->nargs + (fun)->u.i.nvars)
+#define JS_GET_LOCAL_NAME_COUNT(fun) (JS_UPVAR_LOCAL_NAME_START(fun) + \
+ (fun)->u.i.nupvars)
+
+extern JSBool
+js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind);
+
+/*
+ * Look up an argument or variable name returning its kind when found or
+ * JSLOCAL_NONE when no such name exists. When indexp is not null and the name
+ * exists, *indexp will receive the index of the corresponding argument or
+ * variable.
+ */
+extern JSLocalKind
+js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp);
+
+/*
+ * Functions to work with local names as an array of words.
+ *
+ * js_GetLocalNameArray returns the array, or null if we are out of memory.
+ * This function must not be called when JS_GET_LOCAL_NAME_COUNT(fun) is zero.
+ *
+ * The supplied pool is used to allocate the returned array, so the caller is
+ * obligated to mark and release to free it.
+ *
+ * The elements of the array with index less than fun->nargs correspond to the
+ * names of function formal parameters. An index >= fun->nargs addresses a var
+ * binding. Use JS_LOCAL_NAME_TO_ATOM to convert array's element to an atom
+ * pointer. This pointer can be null when the element is for a formal parameter
+ * corresponding to a destructuring pattern.
+ *
+ * If nameWord does not name a formal parameter, use JS_LOCAL_NAME_IS_CONST to
+ * check if nameWord corresponds to the const declaration.
+ */
+extern jsuword *
+js_GetLocalNameArray(JSContext *cx, JSFunction *fun, struct JSArenaPool *pool);
+
+#define JS_LOCAL_NAME_TO_ATOM(nameWord) \
+ ((JSAtom *) ((nameWord) & ~(jsuword) 1))
+
+#define JS_LOCAL_NAME_IS_CONST(nameWord) \
+ ((((nameWord) & (jsuword) 1)) != 0)
+
+extern void
+js_FreezeLocalNames(JSContext *cx, JSFunction *fun);
+
+extern JSBool
+js_fun_apply(JSContext *cx, uintN argc, jsval *vp);
+
+extern JSBool
+js_fun_call(JSContext *cx, uintN argc, jsval *vp);
+
+
+JS_END_EXTERN_C
+
+#endif /* jsfun_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsgc.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsgc.cpp
new file mode 100644
index 0000000..ac29021
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsgc.cpp
@@ -0,0 +1,3763 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS Mark-and-Sweep Garbage Collector.
+ *
+ * This GC allocates fixed-sized things with sizes up to GC_NBYTES_MAX (see
+ * jsgc.h). It allocates from a special GC arena pool with each arena allocated
+ * using malloc. It uses an ideally parallel array of flag bytes to hold the
+ * mark bit, finalizer type index, etc.
+ *
+ * XXX swizzle page to freelist for better locality of reference
+ */
+#include "jsstddef.h"
+#include <stdlib.h> /* for free */
+#include <math.h>
+#include <string.h> /* for memset used when DEBUG */
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jshash.h" /* Added by JSIFY */
+#include "jsbit.h"
+#include "jsclist.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsexn.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsparse.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jstracer.h"
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+/*
+ * Check if posix_memalign is available.
+ */
+#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || MOZ_MEMORY
+# define HAS_POSIX_MEMALIGN 1
+#else
+# define HAS_POSIX_MEMALIGN 0
+#endif
+
+/*
+ * jemalloc provides posix_memalign.
+ */
+#ifdef MOZ_MEMORY
+extern "C" {
+#include "../../memory/jemalloc/jemalloc.h"
+}
+#endif
+
+/*
+ * Include the headers for mmap unless we have posix_memalign and do not
+ * insist on mmap.
+ */
+#if JS_GC_USE_MMAP || (!defined JS_GC_USE_MMAP && !HAS_POSIX_MEMALIGN)
+# if defined(XP_WIN)
+# ifndef JS_GC_USE_MMAP
+# define JS_GC_USE_MMAP 1
+# endif
+# include <windows.h>
+# else
+# if defined(XP_UNIX) || defined(XP_BEOS)
+# include <unistd.h>
+# endif
+# if _POSIX_MAPPED_FILES > 0
+# ifndef JS_GC_USE_MMAP
+# define JS_GC_USE_MMAP 1
+# endif
+# include <sys/mman.h>
+
+/* On Mac OS X MAP_ANONYMOUS is not defined. */
+# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+# define MAP_ANONYMOUS MAP_ANON
+# endif
+# else
+# if JS_GC_USE_MMAP
+# error "JS_GC_USE_MMAP is set when mmap is not available"
+# endif
+# endif
+# endif
+#endif
+
+/*
+ * A GC arena contains a fixed number of flag bits for each thing in its heap,
+ * and supports O(1) lookup of a flag given its thing's address.
+ *
+ * To implement this, we allocate things of the same size from a GC arena
+ * containing GC_ARENA_SIZE bytes aligned on GC_ARENA_SIZE boundary. The
+ * following picture shows arena's layout:
+ *
+ * +------------------------------+--------------------+---------------+
+ * | allocation area for GC thing | flags of GC things | JSGCArenaInfo |
+ * +------------------------------+--------------------+---------------+
+ *
+ * To find the flag bits for the thing we calculate the thing index counting
+ * from arena's start using:
+ *
+ * thingIndex = (thingAddress & GC_ARENA_MASK) / thingSize
+ *
+ * The details of flag's lookup depend on thing's kind. For all GC things
+ * except doubles we use one byte of flags where the 4 bits determine thing's
+ * type and the rest is used to implement GC marking, finalization and
+ * locking. We calculate the address of flag's byte using:
+ *
+ * flagByteAddress =
+ * (thingAddress | GC_ARENA_MASK) - sizeof(JSGCArenaInfo) - thingIndex
+ *
+ * where
+ *
+ * (thingAddress | GC_ARENA_MASK) - sizeof(JSGCArenaInfo)
+ *
+ * is the last byte of flags' area.
+ *
+ * This implies that the things are allocated from the start of their area and
+ * flags are allocated from the end. This arrangement avoids a relatively
+ * expensive calculation of the location of the boundary separating things and
+ * flags. The boundary's offset from the start of the arena is given by:
+ *
+ * thingsPerArena * thingSize
+ *
+ * where thingsPerArena is the number of things that the arena can hold:
+ *
+ * (GC_ARENA_SIZE - sizeof(JSGCArenaInfo)) / (thingSize + 1).
+ *
+ * To allocate doubles we use a specialized arena. It can contain only numbers
+ * so we do not need the type bits. Moreover, since the doubles do not require
+ * a finalizer and very few of them are locked via js_LockGCThing API, we use
+ * just one bit of flags per double to denote if it was marked during the
+ * marking phase of the GC. The locking is implemented via a hash table. Thus
+ * for doubles the flag area becomes a bitmap.
+ *
+ * JS_GC_USE_MMAP macro governs the choice of the aligned arena allocator.
+ * When it is true, a platform-dependent function like mmap is used to get
+ * memory aligned on CPU page boundaries. If the macro is false or undefined,
+ * posix_memalign is used when available. Otherwise the code uses malloc to
+ * over-allocate a chunk with js_gcArenasPerChunk aligned arenas. The
+ * approximate space overhead of this is 1/js_gcArenasPerChunk. For details,
+ * see NewGCChunk/DestroyGCChunk below.
+ *
+ * The code also allocates arenas in chunks when JS_GC_USE_MMAP is 1 to
+ * minimize the overhead of mmap/munmap. In this case js_gcArenasPerChunk can
+ * not be a compile-time constant as the system page size is not known until
+ * runtime.
+ */
+#if JS_GC_USE_MMAP
+static uint32 js_gcArenasPerChunk = 0;
+static JSBool js_gcUseMmap = JS_FALSE;
+#elif HAS_POSIX_MEMALIGN
+# define js_gcArenasPerChunk 1
+#else
+# define js_gcArenasPerChunk 7
+#endif
+
+#if defined(js_gcArenasPerChunk) && js_gcArenasPerChunk == 1
+# define CHUNKED_ARENA_ALLOCATION 0
+#else
+# define CHUNKED_ARENA_ALLOCATION 1
+#endif
+
+#define GC_ARENA_SHIFT 12
+#define GC_ARENA_MASK ((jsuword) JS_BITMASK(GC_ARENA_SHIFT))
+#define GC_ARENA_SIZE JS_BIT(GC_ARENA_SHIFT)
+
+/*
+ * JS_GC_ARENA_PAD defines the number of bytes to pad JSGCArenaInfo structure.
+ * It is used to improve allocation efficiency when using posix_memalign. If
+ * malloc's implementation uses internal headers, then calling
+ *
+ * posix_memalign(&p, GC_ARENA_SIZE, GC_ARENA_SIZE * js_gcArenasPerChunk)
+ *
+ * in a sequence leaves holes between allocations of the size GC_ARENA_SIZE
+ * due to the need to fit headers. JS_GC_ARENA_PAD mitigates that so the code
+ * calls
+ *
+ * posix_memalign(&p, GC_ARENA_SIZE,
+ * GC_ARENA_SIZE * js_gcArenasPerChunk - JS_GC_ARENA_PAD)
+ *
+ * When JS_GC_ARENA_PAD is equal or greater than the number of words in the
+ * system header, the system can pack all allocations together without holes.
+ *
+ * With JS_GC_USE_MEMALIGN we want at least 2 word pad unless posix_memalign
+ * comes from jemalloc that does not use any headers/trailers.
+ */
+#ifndef JS_GC_ARENA_PAD
+# if HAS_POSIX_MEMALIGN && !MOZ_MEMORY
+# define JS_GC_ARENA_PAD (2 * JS_BYTES_PER_WORD)
+# else
+# define JS_GC_ARENA_PAD 0
+# endif
+#endif
+
+struct JSGCArenaInfo {
+ /*
+ * Allocation list for the arena or NULL if the arena holds double values.
+ */
+ JSGCArenaList *list;
+
+ /*
+ * Pointer to the previous arena in a linked list. The arena can either
+ * belong to one of JSContext.gcArenaList lists or, when it does not have
+ * any allocated GC things, to the list of free arenas in the chunk with
+ * head stored in JSGCChunkInfo.lastFreeArena.
+ */
+ JSGCArenaInfo *prev;
+
+#if !CHUNKED_ARENA_ALLOCATION
+ jsuword prevUntracedPage;
+#else
+ /*
+ * A link field for the list of arenas with marked but not yet traced
+ * things. The field is encoded as arena's page to share the space with
+ * firstArena and arenaIndex fields.
+ */
+ jsuword prevUntracedPage : JS_BITS_PER_WORD - GC_ARENA_SHIFT;
+
+ /*
+ * When firstArena is false, the index of arena in the chunk. When
+ * firstArena is true, the index of a free arena holding JSGCChunkInfo or
+ * NO_FREE_ARENAS if there are no free arenas in the chunk.
+ *
+ * GET_ARENA_INDEX and GET_CHUNK_INFO_INDEX are convenience macros to
+ * access either of indexes.
+ */
+ jsuword arenaIndex : GC_ARENA_SHIFT - 1;
+
+ /* Flag indicating if the arena is the first in the chunk. */
+ jsuword firstArena : 1;
+#endif
+
+ union {
+ jsuword untracedThings; /* bitset for fast search of marked
+ but not yet traced things */
+ JSBool hasMarkedDoubles; /* the arena has marked doubles */
+ } u;
+
+#if JS_GC_ARENA_PAD != 0
+ uint8 pad[JS_GC_ARENA_PAD];
+#endif
+};
+
+/*
+ * Verify that the bit fields are indeed shared and JSGCArenaInfo is as small
+ * as possible. The code does not rely on this check so if on a particular
+ * platform this does not compile, then, as a workaround, comment the assert
+ * out and submit a bug report.
+ */
+JS_STATIC_ASSERT(offsetof(JSGCArenaInfo, u) == 3 * sizeof(jsuword));
+
+/*
+ * Macros to convert between JSGCArenaInfo, the start address of the arena and
+ * arena's page defined as (start address) >> GC_ARENA_SHIFT.
+ */
+#define ARENA_INFO_OFFSET (GC_ARENA_SIZE - (uint32) sizeof(JSGCArenaInfo))
+
+#define IS_ARENA_INFO_ADDRESS(arena) \
+ (((jsuword) (arena) & GC_ARENA_MASK) == ARENA_INFO_OFFSET)
+
+#define ARENA_START_TO_INFO(arenaStart) \
+ (JS_ASSERT(((arenaStart) & (jsuword) GC_ARENA_MASK) == 0), \
+ (JSGCArenaInfo *) ((arenaStart) + (jsuword) ARENA_INFO_OFFSET))
+
+#define ARENA_INFO_TO_START(arena) \
+ (JS_ASSERT(IS_ARENA_INFO_ADDRESS(arena)), \
+ (jsuword) (arena) & ~(jsuword) GC_ARENA_MASK)
+
+#define ARENA_PAGE_TO_INFO(arenaPage) \
+ (JS_ASSERT(arenaPage != 0), \
+ JS_ASSERT(!((jsuword)(arenaPage) >> (JS_BITS_PER_WORD-GC_ARENA_SHIFT))), \
+ ARENA_START_TO_INFO((arenaPage) << GC_ARENA_SHIFT))
+
+#define ARENA_INFO_TO_PAGE(arena) \
+ (JS_ASSERT(IS_ARENA_INFO_ADDRESS(arena)), \
+ ((jsuword) (arena) >> GC_ARENA_SHIFT))
+
+#define GET_ARENA_INFO(chunk, index) \
+ (JS_ASSERT((index) < js_gcArenasPerChunk), \
+ ARENA_START_TO_INFO(chunk + ((index) << GC_ARENA_SHIFT)))
+
+#if CHUNKED_ARENA_ALLOCATION
+/*
+ * Definitions for allocating arenas in chunks.
+ *
+ * All chunks that have at least one free arena are put on the doubly-linked
+ * list with the head stored in JSRuntime.gcChunkList. JSGCChunkInfo contains
+ * the head of the chunk's free arena list together with the link fields for
+ * gcChunkList.
+ *
+ * Structure stored in one of chunk's free arenas. GET_CHUNK_INFO_INDEX gives
+ * the index of this arena. When all arenas in the chunk are used, it is
+ * removed from the list and the index is set to NO_FREE_ARENAS indicating
+ * that the chunk is not on gcChunkList and has no JSGCChunkInfo available.
+ */
+
+struct JSGCChunkInfo {
+ JSGCChunkInfo **prevp;
+ JSGCChunkInfo *next;
+ JSGCArenaInfo *lastFreeArena;
+ uint32 numFreeArenas;
+};
+
+#define NO_FREE_ARENAS JS_BITMASK(GC_ARENA_SHIFT - 1)
+
+#ifdef js_gcArenasPerChunk
+JS_STATIC_ASSERT(1 <= js_gcArenasPerChunk &&
+ js_gcArenasPerChunk <= NO_FREE_ARENAS);
+#endif
+
+#define GET_ARENA_CHUNK(arena, index) \
+ (JS_ASSERT(GET_ARENA_INDEX(arena) == index), \
+ ARENA_INFO_TO_START(arena) - ((index) << GC_ARENA_SHIFT))
+
+#define GET_ARENA_INDEX(arena) \
+ ((arena)->firstArena ? 0 : (uint32) (arena)->arenaIndex)
+
+#define GET_CHUNK_INFO_INDEX(chunk) \
+ ((uint32) ARENA_START_TO_INFO(chunk)->arenaIndex)
+
+#define SET_CHUNK_INFO_INDEX(chunk, index) \
+ (JS_ASSERT((index) < js_gcArenasPerChunk || (index) == NO_FREE_ARENAS), \
+ (void) (ARENA_START_TO_INFO(chunk)->arenaIndex = (jsuword) (index)))
+
+#define GET_CHUNK_INFO(chunk, infoIndex) \
+ (JS_ASSERT(GET_CHUNK_INFO_INDEX(chunk) == (infoIndex)), \
+ JS_ASSERT((uint32) (infoIndex) < js_gcArenasPerChunk), \
+ (JSGCChunkInfo *) ((chunk) + ((infoIndex) << GC_ARENA_SHIFT)))
+
+#define CHUNK_INFO_TO_INDEX(ci) \
+ GET_ARENA_INDEX(ARENA_START_TO_INFO((jsuword)ci))
+
+#endif
+
+/*
+ * Macros for GC-thing operations.
+ */
+#define THINGS_PER_ARENA(thingSize) \
+ ((GC_ARENA_SIZE - (uint32) sizeof(JSGCArenaInfo)) / ((thingSize) + 1U))
+
+#define THING_TO_ARENA(thing) \
+ ((JSGCArenaInfo *)(((jsuword) (thing) | GC_ARENA_MASK) + \
+ 1 - sizeof(JSGCArenaInfo)))
+
+#define THING_TO_INDEX(thing, thingSize) \
+ ((uint32) ((jsuword) (thing) & GC_ARENA_MASK) / (uint32) (thingSize))
+
+#define THING_FLAGS_END(arena) ((uint8 *)(arena))
+
+#define THING_FLAGP(arena, thingIndex) \
+ (JS_ASSERT((jsuword) (thingIndex) \
+ < (jsuword) THINGS_PER_ARENA((arena)->list->thingSize)), \
+ (uint8 *)(arena) - 1 - (thingIndex))
+
+#define THING_TO_FLAGP(thing, thingSize) \
+ THING_FLAGP(THING_TO_ARENA(thing), THING_TO_INDEX(thing, thingSize))
+
+#define FLAGP_TO_ARENA(flagp) THING_TO_ARENA(flagp)
+
+#define FLAGP_TO_INDEX(flagp) \
+ (JS_ASSERT(((jsuword) (flagp) & GC_ARENA_MASK) < ARENA_INFO_OFFSET), \
+ (ARENA_INFO_OFFSET - 1 - (uint32) ((jsuword) (flagp) & GC_ARENA_MASK)))
+
+#define FLAGP_TO_THING(flagp, thingSize) \
+ (JS_ASSERT(((jsuword) (flagp) & GC_ARENA_MASK) >= \
+ (ARENA_INFO_OFFSET - THINGS_PER_ARENA(thingSize))), \
+ (JSGCThing *)(((jsuword) (flagp) & ~GC_ARENA_MASK) + \
+ (thingSize) * FLAGP_TO_INDEX(flagp)))
+
+/*
+ * Macros for the specialized arena for doubles.
+ *
+ * DOUBLES_PER_ARENA defines the maximum number of doubles that the arena can
+ * hold. We find it as the following. Let n be the number of doubles in the
+ * arena. Together with the bitmap of flags and JSGCArenaInfo they should fit
+ * the arena. Hence DOUBLES_PER_ARENA or n_max is the maximum value of n for
+ * which the following holds:
+ *
+ * n*s + ceil(n/B) <= M (1)
+ *
+ * where "/" denotes normal real division,
+ * ceil(r) gives the least integer not smaller than the number r,
+ * s is the number of words in jsdouble,
+ * B is number of bits per word or B == JS_BITS_PER_WORD
+ * M is the number of words in the arena before JSGCArenaInfo or
+ * M == (GC_ARENA_SIZE - sizeof(JSGCArenaInfo)) / sizeof(jsuword).
+ * M == ARENA_INFO_OFFSET / sizeof(jsuword)
+ *
+ * We rewrite the inequality as
+ *
+ * n*B*s/B + ceil(n/B) <= M,
+ * ceil(n*B*s/B + n/B) <= M,
+ * ceil(n*(B*s + 1)/B) <= M (2)
+ *
+ * We define a helper function e(n, s, B),
+ *
+ * e(n, s, B) := ceil(n*(B*s + 1)/B) - n*(B*s + 1)/B, 0 <= e(n, s, B) < 1.
+ *
+ * It gives:
+ *
+ * n*(B*s + 1)/B + e(n, s, B) <= M,
+ * n + e*B/(B*s + 1) <= M*B/(B*s + 1)
+ *
+ * We apply the floor function to both sides of the last equation, where
+ * floor(r) gives the biggest integer not greater than r. As a consequence we
+ * have:
+ *
+ * floor(n + e*B/(B*s + 1)) <= floor(M*B/(B*s + 1)),
+ * n + floor(e*B/(B*s + 1)) <= floor(M*B/(B*s + 1)),
+ * n <= floor(M*B/(B*s + 1)), (3)
+ *
+ * where floor(e*B/(B*s + 1)) is zero as e*B/(B*s + 1) < B/(B*s + 1) < 1.
+ * Thus any n that satisfies the original constraint (1) or its equivalent (2),
+ * must also satisfy (3). That is, we got an upper estimate for the maximum
+ * value of n. Lets show that this upper estimate,
+ *
+ * floor(M*B/(B*s + 1)), (4)
+ *
+ * also satisfies (1) and, as such, gives the required maximum value.
+ * Substituting it into (2) gives:
+ *
+ * ceil(floor(M*B/(B*s + 1))*(B*s + 1)/B) == ceil(floor(M/X)*X)
+ *
+ * where X == (B*s + 1)/B > 1. But then floor(M/X)*X <= M/X*X == M and
+ *
+ * ceil(floor(M/X)*X) <= ceil(M) == M.
+ *
+ * Thus the value of (4) gives the maximum n satisfying (1).
+ *
+ * For the final result we observe that in (4)
+ *
+ * M*B == ARENA_INFO_OFFSET / sizeof(jsuword) * JS_BITS_PER_WORD
+ * == ARENA_INFO_OFFSET * JS_BITS_PER_BYTE
+ *
+ * and
+ *
+ * B*s == JS_BITS_PER_WORD * sizeof(jsdouble) / sizeof(jsuword)
+ * == JS_BITS_PER_DOUBLE.
+ */
+#define DOUBLES_PER_ARENA \
+ ((ARENA_INFO_OFFSET * JS_BITS_PER_BYTE) / (JS_BITS_PER_DOUBLE + 1))
+
+/*
+ * Check that ARENA_INFO_OFFSET and sizeof(jsdouble) divides sizeof(jsuword).
+ */
+JS_STATIC_ASSERT(ARENA_INFO_OFFSET % sizeof(jsuword) == 0);
+JS_STATIC_ASSERT(sizeof(jsdouble) % sizeof(jsuword) == 0);
+JS_STATIC_ASSERT(sizeof(jsbitmap) == sizeof(jsuword));
+
+#define DOUBLES_ARENA_BITMAP_WORDS \
+ (JS_HOWMANY(DOUBLES_PER_ARENA, JS_BITS_PER_WORD))
+
+/* Check that DOUBLES_PER_ARENA indeed maximises (1). */
+JS_STATIC_ASSERT(DOUBLES_PER_ARENA * sizeof(jsdouble) +
+ DOUBLES_ARENA_BITMAP_WORDS * sizeof(jsuword) <=
+ ARENA_INFO_OFFSET);
+
+JS_STATIC_ASSERT((DOUBLES_PER_ARENA + 1) * sizeof(jsdouble) +
+ sizeof(jsuword) *
+ JS_HOWMANY((DOUBLES_PER_ARENA + 1), JS_BITS_PER_WORD) >
+ ARENA_INFO_OFFSET);
+
+/*
+ * When DOUBLES_PER_ARENA % BITS_PER_DOUBLE_FLAG_UNIT != 0, some bits in the
+ * last byte of the occupation bitmap are unused.
+ */
+#define UNUSED_DOUBLE_BITMAP_BITS \
+ (DOUBLES_ARENA_BITMAP_WORDS * JS_BITS_PER_WORD - DOUBLES_PER_ARENA)
+
+JS_STATIC_ASSERT(UNUSED_DOUBLE_BITMAP_BITS < JS_BITS_PER_WORD);
+
+#define DOUBLES_ARENA_BITMAP_OFFSET \
+ (ARENA_INFO_OFFSET - DOUBLES_ARENA_BITMAP_WORDS * sizeof(jsuword))
+
+#define CHECK_DOUBLE_ARENA_INFO(arenaInfo) \
+ (JS_ASSERT(IS_ARENA_INFO_ADDRESS(arenaInfo)), \
+ JS_ASSERT(!(arenaInfo)->list)) \
+
+/*
+ * Get the start of the bitmap area containing double mark flags in the arena.
+ * To access the flag the code uses
+ *
+ * JS_TEST_BIT(bitmapStart, index)
+ *
+ * That is, compared with the case of arenas with non-double things, we count
+ * flags from the start of the bitmap area, not from the end.
+ */
+#define DOUBLE_ARENA_BITMAP(arenaInfo) \
+ (CHECK_DOUBLE_ARENA_INFO(arenaInfo), \
+ (jsbitmap *) arenaInfo - DOUBLES_ARENA_BITMAP_WORDS)
+
+#define DOUBLE_THING_TO_INDEX(thing) \
+ (CHECK_DOUBLE_ARENA_INFO(THING_TO_ARENA(thing)), \
+ JS_ASSERT(((jsuword) (thing) & GC_ARENA_MASK) < \
+ DOUBLES_ARENA_BITMAP_OFFSET), \
+ ((uint32) (((jsuword) (thing) & GC_ARENA_MASK) / sizeof(jsdouble))))
+
+static void
+ClearDoubleArenaFlags(JSGCArenaInfo *a)
+{
+ jsbitmap *bitmap, mask;
+ uintN nused;
+
+ /*
+ * When some high bits in the last byte of the double occupation bitmap
+ * are unused, we must set them. Otherwise RefillDoubleFreeList will
+ * assume that they corresponds to some free cells and tries to allocate
+ * them.
+ *
+ * Note that the code works correctly with UNUSED_DOUBLE_BITMAP_BITS == 0.
+ */
+ bitmap = DOUBLE_ARENA_BITMAP(a);
+ memset(bitmap, 0, (DOUBLES_ARENA_BITMAP_WORDS - 1) * sizeof *bitmap);
+ mask = ((jsbitmap) 1 << UNUSED_DOUBLE_BITMAP_BITS) - 1;
+ nused = JS_BITS_PER_WORD - UNUSED_DOUBLE_BITMAP_BITS;
+ bitmap[DOUBLES_ARENA_BITMAP_WORDS - 1] = mask << nused;
+}
+
+static JS_ALWAYS_INLINE JSBool
+IsMarkedDouble(JSGCArenaInfo *a, uint32 index)
+{
+ jsbitmap *bitmap;
+
+ JS_ASSERT(a->u.hasMarkedDoubles);
+ bitmap = DOUBLE_ARENA_BITMAP(a);
+ return JS_TEST_BIT(bitmap, index);
+}
+
+/*
+ * JSRuntime.gcDoubleArenaList.nextDoubleFlags points either to:
+ *
+ * 1. The next byte in the bitmap area for doubles to check for unmarked
+ * (or free) doubles.
+ * 2. Or to the end of the bitmap area when all GC cells of the arena are
+ * allocated.
+ * 3. Or to a special sentinel value indicating that there are no arenas
+ * to check for unmarked doubles.
+ *
+ * We set the sentinel to ARENA_INFO_OFFSET so the single check
+ *
+ * ((jsuword) nextDoubleFlags & GC_ARENA_MASK) == ARENA_INFO_OFFSET
+ *
+ * will cover both the second and the third cases.
+ */
+#define DOUBLE_BITMAP_SENTINEL ((jsbitmap *) ARENA_INFO_OFFSET)
+
+#ifdef JS_THREADSAFE
+/*
+ * The maximum number of things to put on the local free list by taking
+ * several things from the global free list or from the tail of the last
+ * allocated arena to amortize the cost of rt->gcLock.
+ *
+ * We use number 8 based on benchmarks from bug 312238.
+ */
+#define MAX_THREAD_LOCAL_THINGS 8
+
+#endif
+
+JS_STATIC_ASSERT(sizeof(JSStackHeader) >= 2 * sizeof(jsval));
+
+JS_STATIC_ASSERT(sizeof(JSGCThing) >= sizeof(JSString));
+JS_STATIC_ASSERT(sizeof(JSGCThing) >= sizeof(jsdouble));
+
+/* We want to use all the available GC thing space for object's slots. */
+JS_STATIC_ASSERT(sizeof(JSObject) % sizeof(JSGCThing) == 0);
+
+/*
+ * Ensure that JSObject is allocated from a different GC-list rather than
+ * jsdouble and JSString so we can easily finalize JSObject before these 2
+ * types of GC things. See comments in js_GC.
+ */
+JS_STATIC_ASSERT(GC_FREELIST_INDEX(sizeof(JSString)) !=
+ GC_FREELIST_INDEX(sizeof(JSObject)));
+JS_STATIC_ASSERT(GC_FREELIST_INDEX(sizeof(jsdouble)) !=
+ GC_FREELIST_INDEX(sizeof(JSObject)));
+
+/*
+ * JSPtrTable capacity growth descriptor. The table grows by powers of two
+ * starting from capacity JSPtrTableInfo.minCapacity, but switching to linear
+ * growth when capacity reaches JSPtrTableInfo.linearGrowthThreshold.
+ */
+typedef struct JSPtrTableInfo {
+ uint16 minCapacity;
+ uint16 linearGrowthThreshold;
+} JSPtrTableInfo;
+
+#define GC_ITERATOR_TABLE_MIN 4
+#define GC_ITERATOR_TABLE_LINEAR 1024
+
+static const JSPtrTableInfo iteratorTableInfo = {
+ GC_ITERATOR_TABLE_MIN,
+ GC_ITERATOR_TABLE_LINEAR
+};
+
+/* Calculate table capacity based on the current value of JSPtrTable.count. */
+static size_t
+PtrTableCapacity(size_t count, const JSPtrTableInfo *info)
+{
+ size_t linear, log, capacity;
+
+ linear = info->linearGrowthThreshold;
+ JS_ASSERT(info->minCapacity <= linear);
+
+ if (count == 0) {
+ capacity = 0;
+ } else if (count < linear) {
+ log = JS_CEILING_LOG2W(count);
+ JS_ASSERT(log != JS_BITS_PER_WORD);
+ capacity = (size_t)1 << log;
+ if (capacity < info->minCapacity)
+ capacity = info->minCapacity;
+ } else {
+ capacity = JS_ROUNDUP(count, linear);
+ }
+
+ JS_ASSERT(capacity >= count);
+ return capacity;
+}
+
+static void
+FreePtrTable(JSPtrTable *table, const JSPtrTableInfo *info)
+{
+ if (table->array) {
+ JS_ASSERT(table->count > 0);
+ free(table->array);
+ table->array = NULL;
+ table->count = 0;
+ }
+ JS_ASSERT(table->count == 0);
+}
+
+static JSBool
+AddToPtrTable(JSContext *cx, JSPtrTable *table, const JSPtrTableInfo *info,
+ void *ptr)
+{
+ size_t count, capacity;
+ void **array;
+
+ count = table->count;
+ capacity = PtrTableCapacity(count, info);
+
+ if (count == capacity) {
+ if (capacity < info->minCapacity) {
+ JS_ASSERT(capacity == 0);
+ JS_ASSERT(!table->array);
+ capacity = info->minCapacity;
+ } else {
+ /*
+ * Simplify the overflow detection assuming pointer is bigger
+ * than byte.
+ */
+ JS_STATIC_ASSERT(2 <= sizeof table->array[0]);
+ capacity = (capacity < info->linearGrowthThreshold)
+ ? 2 * capacity
+ : capacity + info->linearGrowthThreshold;
+ if (capacity > (size_t)-1 / sizeof table->array[0])
+ goto bad;
+ }
+ array = (void **) realloc(table->array,
+ capacity * sizeof table->array[0]);
+ if (!array)
+ goto bad;
+#ifdef DEBUG
+ memset(array + count, JS_FREE_PATTERN,
+ (capacity - count) * sizeof table->array[0]);
+#endif
+ table->array = array;
+ }
+
+ table->array[count] = ptr;
+ table->count = count + 1;
+
+ return JS_TRUE;
+
+ bad:
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+}
+
+static void
+ShrinkPtrTable(JSPtrTable *table, const JSPtrTableInfo *info,
+ size_t newCount)
+{
+ size_t oldCapacity, capacity;
+ void **array;
+
+ JS_ASSERT(newCount <= table->count);
+ if (newCount == table->count)
+ return;
+
+ oldCapacity = PtrTableCapacity(table->count, info);
+ table->count = newCount;
+ capacity = PtrTableCapacity(newCount, info);
+
+ if (oldCapacity != capacity) {
+ array = table->array;
+ JS_ASSERT(array);
+ if (capacity == 0) {
+ free(array);
+ table->array = NULL;
+ return;
+ }
+ array = (void **) realloc(array, capacity * sizeof array[0]);
+ if (array)
+ table->array = array;
+ }
+#ifdef DEBUG
+ memset(table->array + newCount, JS_FREE_PATTERN,
+ (capacity - newCount) * sizeof table->array[0]);
+#endif
+}
+
+#ifdef JS_GCMETER
+# define METER(x) ((void) (x))
+# define METER_IF(condition, x) ((void) ((condition) && (x)))
+#else
+# define METER(x) ((void) 0)
+# define METER_IF(condition, x) ((void) 0)
+#endif
+
+#define METER_UPDATE_MAX(maxLval, rval) \
+ METER_IF((maxLval) < (rval), (maxLval) = (rval))
+
+#if JS_GC_USE_MMAP || !HAS_POSIX_MEMALIGN
+
+/*
+ * For chunks allocated via over-sized malloc, get a pointer to store the gap
+ * between the malloc's result and the first arena in the chunk.
+ */
+static uint32 *
+GetMallocedChunkGapPtr(jsuword chunk)
+{
+ JS_ASSERT((chunk & GC_ARENA_MASK) == 0);
+
+ /* Use the memory after the chunk, see NewGCChunk for details. */
+ return (uint32 *) (chunk + (js_gcArenasPerChunk << GC_ARENA_SHIFT));
+}
+
+#endif
+
+static jsuword
+NewGCChunk(void)
+{
+ void *p;
+
+#if JS_GC_USE_MMAP
+ if (js_gcUseMmap) {
+# if defined(XP_WIN)
+ p = VirtualAlloc(NULL, js_gcArenasPerChunk << GC_ARENA_SHIFT,
+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+ return (jsuword) p;
+# else
+ p = mmap(NULL, js_gcArenasPerChunk << GC_ARENA_SHIFT,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ return (p == MAP_FAILED) ? 0 : (jsuword) p;
+# endif
+ }
+#endif
+
+#if HAS_POSIX_MEMALIGN
+ if (0 != posix_memalign(&p, GC_ARENA_SIZE,
+ GC_ARENA_SIZE * js_gcArenasPerChunk -
+ JS_GC_ARENA_PAD)) {
+ return 0;
+ }
+ return (jsuword) p;
+#else
+ /*
+ * Implement chunk allocation using oversized malloc if mmap and
+ * posix_memalign are not available.
+ *
+ * Since malloc allocates pointers aligned on the word boundary, to get
+ * js_gcArenasPerChunk aligned arenas, we need to malloc only
+ *
+ * ((js_gcArenasPerChunk + 1) << GC_ARENA_SHIFT) - sizeof(size_t)
+ *
+ * bytes. But since we stores the gap between the malloced pointer and the
+ * first arena in the chunk after the chunk, we need to ask for
+ *
+ * ((js_gcArenasPerChunk + 1) << GC_ARENA_SHIFT)
+ *
+ * bytes to ensure that we always have room to store the gap.
+ */
+ p = malloc((js_gcArenasPerChunk + 1) << GC_ARENA_SHIFT);
+ if (!p)
+ return 0;
+
+ {
+ jsuword chunk;
+
+ chunk = ((jsuword) p + GC_ARENA_MASK) & ~GC_ARENA_MASK;
+ *GetMallocedChunkGapPtr(chunk) = (uint32) (chunk - (jsuword) p);
+ return chunk;
+ }
+#endif
+}
+
+static void
+DestroyGCChunk(jsuword chunk)
+{
+ JS_ASSERT((chunk & GC_ARENA_MASK) == 0);
+#if JS_GC_USE_MMAP
+ if (js_gcUseMmap) {
+# if defined(XP_WIN)
+ VirtualFree((void *) chunk, 0, MEM_RELEASE);
+# elif defined(SOLARIS)
+ munmap((char *) chunk, js_gcArenasPerChunk << GC_ARENA_SHIFT);
+# else
+ munmap((void *) chunk, js_gcArenasPerChunk << GC_ARENA_SHIFT);
+# endif
+ return;
+ }
+#endif
+
+#if HAS_POSIX_MEMALIGN
+ free((void *) chunk);
+#else
+ /* See comments in NewGCChunk. */
+ JS_ASSERT(*GetMallocedChunkGapPtr(chunk) < GC_ARENA_SIZE);
+ free((void *) (chunk - *GetMallocedChunkGapPtr(chunk)));
+#endif
+}
+
+#if CHUNKED_ARENA_ALLOCATION
+
+static void
+AddChunkToList(JSRuntime *rt, JSGCChunkInfo *ci)
+{
+ ci->prevp = &rt->gcChunkList;
+ ci->next = rt->gcChunkList;
+ if (rt->gcChunkList) {
+ JS_ASSERT(rt->gcChunkList->prevp == &rt->gcChunkList);
+ rt->gcChunkList->prevp = &ci->next;
+ }
+ rt->gcChunkList = ci;
+}
+
+static void
+RemoveChunkFromList(JSRuntime *rt, JSGCChunkInfo *ci)
+{
+ *ci->prevp = ci->next;
+ if (ci->next) {
+ JS_ASSERT(ci->next->prevp == &ci->next);
+ ci->next->prevp = ci->prevp;
+ }
+}
+
+#endif
+
+static JSGCArenaInfo *
+NewGCArena(JSRuntime *rt)
+{
+ jsuword chunk;
+ JSGCArenaInfo *a;
+
+ if (rt->gcBytes >= rt->gcMaxBytes)
+ return NULL;
+
+#if CHUNKED_ARENA_ALLOCATION
+ if (js_gcArenasPerChunk == 1) {
+#endif
+ chunk = NewGCChunk();
+ if (chunk == 0)
+ return NULL;
+ a = ARENA_START_TO_INFO(chunk);
+#if CHUNKED_ARENA_ALLOCATION
+ } else {
+ JSGCChunkInfo *ci;
+ uint32 i;
+ JSGCArenaInfo *aprev;
+
+ ci = rt->gcChunkList;
+ if (!ci) {
+ chunk = NewGCChunk();
+ if (chunk == 0)
+ return NULL;
+ JS_ASSERT((chunk & GC_ARENA_MASK) == 0);
+ a = GET_ARENA_INFO(chunk, 0);
+ a->firstArena = JS_TRUE;
+ a->arenaIndex = 0;
+ aprev = NULL;
+ i = 0;
+ do {
+ a->prev = aprev;
+ aprev = a;
+ ++i;
+ a = GET_ARENA_INFO(chunk, i);
+ a->firstArena = JS_FALSE;
+ a->arenaIndex = i;
+ } while (i != js_gcArenasPerChunk - 1);
+ ci = GET_CHUNK_INFO(chunk, 0);
+ ci->lastFreeArena = aprev;
+ ci->numFreeArenas = js_gcArenasPerChunk - 1;
+ AddChunkToList(rt, ci);
+ } else {
+ JS_ASSERT(ci->prevp == &rt->gcChunkList);
+ a = ci->lastFreeArena;
+ aprev = a->prev;
+ if (!aprev) {
+ JS_ASSERT(ci->numFreeArenas == 1);
+ JS_ASSERT(ARENA_INFO_TO_START(a) == (jsuword) ci);
+ RemoveChunkFromList(rt, ci);
+ chunk = GET_ARENA_CHUNK(a, GET_ARENA_INDEX(a));
+ SET_CHUNK_INFO_INDEX(chunk, NO_FREE_ARENAS);
+ } else {
+ JS_ASSERT(ci->numFreeArenas >= 2);
+ JS_ASSERT(ARENA_INFO_TO_START(a) != (jsuword) ci);
+ ci->lastFreeArena = aprev;
+ ci->numFreeArenas--;
+ }
+ }
+ }
+#endif
+
+ rt->gcBytes += GC_ARENA_SIZE;
+ a->prevUntracedPage = 0;
+ memset(&a->u, 0, sizeof(a->u));
+
+ return a;
+}
+
+static void
+DestroyGCArenas(JSRuntime *rt, JSGCArenaInfo *last)
+{
+ JSGCArenaInfo *a;
+
+ while (last) {
+ a = last;
+ last = last->prev;
+
+ METER(rt->gcStats.afree++);
+ JS_ASSERT(rt->gcBytes >= GC_ARENA_SIZE);
+ rt->gcBytes -= GC_ARENA_SIZE;
+
+#if CHUNKED_ARENA_ALLOCATION
+ if (js_gcArenasPerChunk == 1) {
+#endif
+ DestroyGCChunk(ARENA_INFO_TO_START(a));
+#if CHUNKED_ARENA_ALLOCATION
+ } else {
+ uint32 arenaIndex;
+ jsuword chunk;
+ uint32 chunkInfoIndex;
+ JSGCChunkInfo *ci;
+# ifdef DEBUG
+ jsuword firstArena;
+
+ firstArena = a->firstArena;
+ arenaIndex = a->arenaIndex;
+ memset((void *) ARENA_INFO_TO_START(a), JS_FREE_PATTERN,
+ GC_ARENA_SIZE - JS_GC_ARENA_PAD);
+ a->firstArena = firstArena;
+ a->arenaIndex = arenaIndex;
+# endif
+ arenaIndex = GET_ARENA_INDEX(a);
+ chunk = GET_ARENA_CHUNK(a, arenaIndex);
+ chunkInfoIndex = GET_CHUNK_INFO_INDEX(chunk);
+ if (chunkInfoIndex == NO_FREE_ARENAS) {
+ chunkInfoIndex = arenaIndex;
+ SET_CHUNK_INFO_INDEX(chunk, arenaIndex);
+ ci = GET_CHUNK_INFO(chunk, chunkInfoIndex);
+ a->prev = NULL;
+ ci->lastFreeArena = a;
+ ci->numFreeArenas = 1;
+ AddChunkToList(rt, ci);
+ } else {
+ JS_ASSERT(chunkInfoIndex != arenaIndex);
+ ci = GET_CHUNK_INFO(chunk, chunkInfoIndex);
+ JS_ASSERT(ci->numFreeArenas != 0);
+ JS_ASSERT(ci->lastFreeArena);
+ JS_ASSERT(a != ci->lastFreeArena);
+ if (ci->numFreeArenas == js_gcArenasPerChunk - 1) {
+ RemoveChunkFromList(rt, ci);
+ DestroyGCChunk(chunk);
+ } else {
+ ++ci->numFreeArenas;
+ a->prev = ci->lastFreeArena;
+ ci->lastFreeArena = a;
+ }
+ }
+ }
+# endif
+ }
+}
+
+static void
+InitGCArenaLists(JSRuntime *rt)
+{
+ uintN i, thingSize;
+ JSGCArenaList *arenaList;
+
+ for (i = 0; i < GC_NUM_FREELISTS; i++) {
+ arenaList = &rt->gcArenaList[i];
+ thingSize = GC_FREELIST_NBYTES(i);
+ JS_ASSERT((size_t)(uint16)thingSize == thingSize);
+ arenaList->last = NULL;
+ arenaList->lastCount = (uint16) THINGS_PER_ARENA(thingSize);
+ arenaList->thingSize = (uint16) thingSize;
+ arenaList->freeList = NULL;
+ }
+ rt->gcDoubleArenaList.first = NULL;
+ rt->gcDoubleArenaList.nextDoubleFlags = DOUBLE_BITMAP_SENTINEL;
+}
+
+static void
+FinishGCArenaLists(JSRuntime *rt)
+{
+ uintN i;
+ JSGCArenaList *arenaList;
+
+ for (i = 0; i < GC_NUM_FREELISTS; i++) {
+ arenaList = &rt->gcArenaList[i];
+ DestroyGCArenas(rt, arenaList->last);
+ arenaList->last = NULL;
+ arenaList->lastCount = THINGS_PER_ARENA(arenaList->thingSize);
+ arenaList->freeList = NULL;
+ }
+ DestroyGCArenas(rt, rt->gcDoubleArenaList.first);
+ rt->gcDoubleArenaList.first = NULL;
+ rt->gcDoubleArenaList.nextDoubleFlags = DOUBLE_BITMAP_SENTINEL;
+
+ rt->gcBytes = 0;
+ JS_ASSERT(rt->gcChunkList == 0);
+}
+
+/*
+ * This function must not be called when thing is jsdouble.
+ */
+static uint8 *
+GetGCThingFlags(void *thing)
+{
+ JSGCArenaInfo *a;
+ uint32 index;
+
+ a = THING_TO_ARENA(thing);
+ index = THING_TO_INDEX(thing, a->list->thingSize);
+ return THING_FLAGP(a, index);
+}
+
+/*
+ * This function returns null when thing is jsdouble.
+ */
+static uint8 *
+GetGCThingFlagsOrNull(void *thing)
+{
+ JSGCArenaInfo *a;
+ uint32 index;
+
+ a = THING_TO_ARENA(thing);
+ if (!a->list)
+ return NULL;
+ index = THING_TO_INDEX(thing, a->list->thingSize);
+ return THING_FLAGP(a, index);
+}
+
+intN
+js_GetExternalStringGCType(JSString *str)
+{
+ uintN type;
+
+ type = (uintN) *GetGCThingFlags(str) & GCF_TYPEMASK;
+ JS_ASSERT(type == GCX_STRING || type >= GCX_EXTERNAL_STRING);
+ return (type == GCX_STRING) ? -1 : (intN) (type - GCX_EXTERNAL_STRING);
+}
+
+static uint32
+MapGCFlagsToTraceKind(uintN flags)
+{
+ uint32 type;
+
+ type = flags & GCF_TYPEMASK;
+ JS_ASSERT(type != GCX_DOUBLE);
+ JS_ASSERT(type < GCX_NTYPES);
+ return (type < GCX_EXTERNAL_STRING) ? type : JSTRACE_STRING;
+}
+
+JS_FRIEND_API(uint32)
+js_GetGCThingTraceKind(void *thing)
+{
+ JSGCArenaInfo *a;
+ uint32 index;
+
+ a = THING_TO_ARENA(thing);
+ if (!a->list)
+ return JSTRACE_DOUBLE;
+
+ index = THING_TO_INDEX(thing, a->list->thingSize);
+ return MapGCFlagsToTraceKind(*THING_FLAGP(a, index));
+}
+
+JSRuntime*
+js_GetGCStringRuntime(JSString *str)
+{
+ JSGCArenaList *list;
+
+ list = THING_TO_ARENA(str)->list;
+
+ JS_ASSERT(list->thingSize == sizeof(JSGCThing));
+ JS_ASSERT(GC_FREELIST_INDEX(sizeof(JSGCThing)) == 0);
+
+ return (JSRuntime *)((uint8 *)list - offsetof(JSRuntime, gcArenaList));
+}
+
+JSBool
+js_IsAboutToBeFinalized(JSContext *cx, void *thing)
+{
+ JSGCArenaInfo *a;
+ uint32 index, flags;
+
+ a = THING_TO_ARENA(thing);
+ if (!a->list) {
+ /*
+ * Check if arena has no marked doubles. In that case the bitmap with
+ * the mark flags contains all garbage as it is initialized only when
+ * marking the first double in the arena.
+ */
+ if (!a->u.hasMarkedDoubles)
+ return JS_TRUE;
+ index = DOUBLE_THING_TO_INDEX(thing);
+ return !IsMarkedDouble(a, index);
+ }
+ index = THING_TO_INDEX(thing, a->list->thingSize);
+ flags = *THING_FLAGP(a, index);
+ return !(flags & (GCF_MARK | GCF_LOCK | GCF_FINAL));
+}
+
+/* This is compatible with JSDHashEntryStub. */
+typedef struct JSGCRootHashEntry {
+ JSDHashEntryHdr hdr;
+ void *root;
+ const char *name;
+} JSGCRootHashEntry;
+
+/* Initial size of the gcRootsHash table (SWAG, small enough to amortize). */
+#define GC_ROOTS_SIZE 256
+
+#if CHUNKED_ARENA_ALLOCATION
+
+/*
+ * For a CPU with extremely large pages using them for GC things wastes
+ * too much memory.
+ */
+# define GC_ARENAS_PER_CPU_PAGE_LIMIT JS_BIT(18 - GC_ARENA_SHIFT)
+
+JS_STATIC_ASSERT(GC_ARENAS_PER_CPU_PAGE_LIMIT <= NO_FREE_ARENAS);
+
+#endif
+
+JSBool
+js_InitGC(JSRuntime *rt, uint32 maxbytes)
+{
+#if JS_GC_USE_MMAP
+ if (js_gcArenasPerChunk == 0) {
+ size_t cpuPageSize, arenasPerPage;
+# if defined(XP_WIN)
+ SYSTEM_INFO si;
+
+ GetSystemInfo(&si);
+ cpuPageSize = si.dwPageSize;
+
+# elif defined(XP_UNIX) || defined(XP_BEOS)
+ cpuPageSize = (size_t) sysconf(_SC_PAGESIZE);
+# else
+# error "Not implemented"
+# endif
+ /* cpuPageSize is a power of 2. */
+ JS_ASSERT((cpuPageSize & (cpuPageSize - 1)) == 0);
+ arenasPerPage = cpuPageSize >> GC_ARENA_SHIFT;
+#ifdef DEBUG
+ if (arenasPerPage == 0) {
+ fprintf(stderr,
+"JS engine warning: the size of the CPU page, %u bytes, is too low to use\n"
+"paged allocation for the garbage collector. Please report this.\n",
+ (unsigned) cpuPageSize);
+ }
+#endif
+ if (arenasPerPage - 1 <= (size_t) (GC_ARENAS_PER_CPU_PAGE_LIMIT - 1)) {
+ /*
+ * Use at least 4 GC arenas per paged allocation chunk to minimize
+ * the overhead of mmap/VirtualAlloc.
+ */
+ js_gcUseMmap = JS_TRUE;
+ js_gcArenasPerChunk = JS_MAX((uint32) arenasPerPage, 4);
+ } else {
+ js_gcUseMmap = JS_FALSE;
+ js_gcArenasPerChunk = 7;
+ }
+ }
+ JS_ASSERT(1 <= js_gcArenasPerChunk &&
+ js_gcArenasPerChunk <= NO_FREE_ARENAS);
+#endif
+
+ InitGCArenaLists(rt);
+ if (!JS_DHashTableInit(&rt->gcRootsHash, JS_DHashGetStubOps(), NULL,
+ sizeof(JSGCRootHashEntry), GC_ROOTS_SIZE)) {
+ rt->gcRootsHash.ops = NULL;
+ return JS_FALSE;
+ }
+ rt->gcLocksHash = NULL; /* create lazily */
+
+ /*
+ * Separate gcMaxMallocBytes from gcMaxBytes but initialize to maxbytes
+ * for default backward API compatibility.
+ */
+ rt->gcMaxBytes = rt->gcMaxMallocBytes = maxbytes;
+ rt->gcEmptyArenaPoolLifespan = 30000;
+
+ METER(memset(&rt->gcStats, 0, sizeof rt->gcStats));
+ return JS_TRUE;
+}
+
+#ifdef JS_GCMETER
+
+static void
+UpdateArenaStats(JSGCArenaStats *st, uint32 nlivearenas, uint32 nkilledArenas,
+ uint32 nthings)
+{
+ size_t narenas;
+
+ narenas = nlivearenas + nkilledArenas;
+ JS_ASSERT(narenas >= st->livearenas);
+
+ st->newarenas = narenas - st->livearenas;
+ st->narenas = narenas;
+ st->livearenas = nlivearenas;
+ if (st->maxarenas < narenas)
+ st->maxarenas = narenas;
+ st->totalarenas += narenas;
+
+ st->nthings = nthings;
+ if (st->maxthings < nthings)
+ st->maxthings = nthings;
+ st->totalthings += nthings;
+}
+
+JS_FRIEND_API(void)
+js_DumpGCStats(JSRuntime *rt, FILE *fp)
+{
+ int i;
+ size_t sumArenas, sumTotalArenas;
+ size_t sumThings, sumMaxThings;
+ size_t sumThingSize, sumTotalThingSize;
+ size_t sumArenaCapacity, sumTotalArenaCapacity;
+ JSGCArenaStats *st;
+ size_t thingSize, thingsPerArena;
+ size_t sumAlloc, sumLocalAlloc, sumFail, sumRetry;
+
+ fprintf(fp, "\nGC allocation statistics:\n");
+
+#define UL(x) ((unsigned long)(x))
+#define ULSTAT(x) UL(rt->gcStats.x)
+#define PERCENT(x,y) (100.0 * (double) (x) / (double) (y))
+
+ sumArenas = 0;
+ sumTotalArenas = 0;
+ sumThings = 0;
+ sumMaxThings = 0;
+ sumThingSize = 0;
+ sumTotalThingSize = 0;
+ sumArenaCapacity = 0;
+ sumTotalArenaCapacity = 0;
+ sumAlloc = 0;
+ sumLocalAlloc = 0;
+ sumFail = 0;
+ sumRetry = 0;
+ for (i = -1; i < (int) GC_NUM_FREELISTS; i++) {
+ if (i == -1) {
+ thingSize = sizeof(jsdouble);
+ thingsPerArena = DOUBLES_PER_ARENA;
+ st = &rt->gcStats.doubleArenaStats;
+ fprintf(fp,
+ "Arena list for double values (%lu doubles per arena):",
+ UL(thingsPerArena));
+ } else {
+ thingSize = rt->gcArenaList[i].thingSize;
+ thingsPerArena = THINGS_PER_ARENA(thingSize);
+ st = &rt->gcStats.arenaStats[i];
+ fprintf(fp,
+ "Arena list %d (thing size %lu, %lu things per arena):",
+ i, UL(GC_FREELIST_NBYTES(i)), UL(thingsPerArena));
+ }
+ if (st->maxarenas == 0) {
+ fputs(" NEVER USED\n", fp);
+ continue;
+ }
+ putc('\n', fp);
+ fprintf(fp, " arenas before GC: %lu\n", UL(st->narenas));
+ fprintf(fp, " new arenas before GC: %lu (%.1f%%)\n",
+ UL(st->newarenas), PERCENT(st->newarenas, st->narenas));
+ fprintf(fp, " arenas after GC: %lu (%.1f%%)\n",
+ UL(st->livearenas), PERCENT(st->livearenas, st->narenas));
+ fprintf(fp, " max arenas: %lu\n", UL(st->maxarenas));
+ fprintf(fp, " things: %lu\n", UL(st->nthings));
+ fprintf(fp, " GC cell utilization: %.1f%%\n",
+ PERCENT(st->nthings, thingsPerArena * st->narenas));
+ fprintf(fp, " average cell utilization: %.1f%%\n",
+ PERCENT(st->totalthings, thingsPerArena * st->totalarenas));
+ fprintf(fp, " max things: %lu\n", UL(st->maxthings));
+ fprintf(fp, " alloc attempts: %lu\n", UL(st->alloc));
+ fprintf(fp, " alloc without locks: %1u (%.1f%%)\n",
+ UL(st->localalloc), PERCENT(st->localalloc, st->alloc));
+ sumArenas += st->narenas;
+ sumTotalArenas += st->totalarenas;
+ sumThings += st->nthings;
+ sumMaxThings += st->maxthings;
+ sumThingSize += thingSize * st->nthings;
+ sumTotalThingSize += thingSize * st->totalthings;
+ sumArenaCapacity += thingSize * thingsPerArena * st->narenas;
+ sumTotalArenaCapacity += thingSize * thingsPerArena * st->totalarenas;
+ sumAlloc += st->alloc;
+ sumLocalAlloc += st->localalloc;
+ sumFail += st->fail;
+ sumRetry += st->retry;
+ }
+ fprintf(fp, "TOTAL STATS:\n");
+ fprintf(fp, " bytes allocated: %lu\n", UL(rt->gcBytes));
+ fprintf(fp, " total GC arenas: %lu\n", UL(sumArenas));
+ fprintf(fp, " total GC things: %lu\n", UL(sumThings));
+ fprintf(fp, " max total GC things: %lu\n", UL(sumMaxThings));
+ fprintf(fp, " GC cell utilization: %.1f%%\n",
+ PERCENT(sumThingSize, sumArenaCapacity));
+ fprintf(fp, " average cell utilization: %.1f%%\n",
+ PERCENT(sumTotalThingSize, sumTotalArenaCapacity));
+ fprintf(fp, "allocation retries after GC: %lu\n", UL(sumRetry));
+ fprintf(fp, " alloc attempts: %lu\n", UL(sumAlloc));
+ fprintf(fp, " alloc without locks: %1u (%.1f%%)\n",
+ UL(sumLocalAlloc), PERCENT(sumLocalAlloc, sumAlloc));
+ fprintf(fp, " allocation failures: %lu\n", UL(sumFail));
+ fprintf(fp, " things born locked: %lu\n", ULSTAT(lockborn));
+ fprintf(fp, " valid lock calls: %lu\n", ULSTAT(lock));
+ fprintf(fp, " valid unlock calls: %lu\n", ULSTAT(unlock));
+ fprintf(fp, " mark recursion depth: %lu\n", ULSTAT(depth));
+ fprintf(fp, " maximum mark recursion: %lu\n", ULSTAT(maxdepth));
+ fprintf(fp, " mark C recursion depth: %lu\n", ULSTAT(cdepth));
+ fprintf(fp, " maximum mark C recursion: %lu\n", ULSTAT(maxcdepth));
+ fprintf(fp, " delayed tracing calls: %lu\n", ULSTAT(untraced));
+#ifdef DEBUG
+ fprintf(fp, " max trace later count: %lu\n", ULSTAT(maxuntraced));
+#endif
+ fprintf(fp, " maximum GC nesting level: %lu\n", ULSTAT(maxlevel));
+ fprintf(fp, "potentially useful GC calls: %lu\n", ULSTAT(poke));
+ fprintf(fp, " thing arenas freed so far: %lu\n", ULSTAT(afree));
+ fprintf(fp, " stack segments scanned: %lu\n", ULSTAT(stackseg));
+ fprintf(fp, "stack segment slots scanned: %lu\n", ULSTAT(segslots));
+ fprintf(fp, "reachable closeable objects: %lu\n", ULSTAT(nclose));
+ fprintf(fp, " max reachable closeable: %lu\n", ULSTAT(maxnclose));
+ fprintf(fp, " scheduled close hooks: %lu\n", ULSTAT(closelater));
+ fprintf(fp, " max scheduled close hooks: %lu\n", ULSTAT(maxcloselater));
+
+#undef UL
+#undef ULSTAT
+#undef PERCENT
+
+#ifdef JS_ARENAMETER
+ JS_DumpArenaStats(fp);
+#endif
+}
+#endif
+
+#ifdef DEBUG
+static void
+CheckLeakedRoots(JSRuntime *rt);
+#endif
+
+#ifdef JS_THREADSAFE
+static void
+TrimGCFreeListsPool(JSRuntime *rt, uintN keepCount);
+#endif
+
+void
+js_FinishGC(JSRuntime *rt)
+{
+#ifdef JS_ARENAMETER
+ JS_DumpArenaStats(stdout);
+#endif
+#ifdef JS_GCMETER
+ js_DumpGCStats(rt, stdout);
+#endif
+
+ FreePtrTable(&rt->gcIteratorTable, &iteratorTableInfo);
+#ifdef JS_THREADSAFE
+ TrimGCFreeListsPool(rt, 0);
+ JS_ASSERT(!rt->gcFreeListsPool);
+#endif
+ FinishGCArenaLists(rt);
+
+ if (rt->gcRootsHash.ops) {
+#ifdef DEBUG
+ CheckLeakedRoots(rt);
+#endif
+ JS_DHashTableFinish(&rt->gcRootsHash);
+ rt->gcRootsHash.ops = NULL;
+ }
+ if (rt->gcLocksHash) {
+ JS_DHashTableDestroy(rt->gcLocksHash);
+ rt->gcLocksHash = NULL;
+ }
+}
+
+JSBool
+js_AddRoot(JSContext *cx, void *rp, const char *name)
+{
+ JSBool ok = js_AddRootRT(cx->runtime, rp, name);
+ if (!ok)
+ JS_ReportOutOfMemory(cx);
+ return ok;
+}
+
+JSBool
+js_AddRootRT(JSRuntime *rt, void *rp, const char *name)
+{
+ JSBool ok;
+ JSGCRootHashEntry *rhe;
+
+ /*
+ * Due to the long-standing, but now removed, use of rt->gcLock across the
+ * bulk of js_GC, API users have come to depend on JS_AddRoot etc. locking
+ * properly with a racing GC, without calling JS_AddRoot from a request.
+ * We have to preserve API compatibility here, now that we avoid holding
+ * rt->gcLock across the mark phase (including the root hashtable mark).
+ *
+ * If the GC is running and we're called on another thread, wait for this
+ * GC activation to finish. We can safely wait here (in the case where we
+ * are called within a request on another thread's context) without fear
+ * of deadlock because the GC doesn't set rt->gcRunning until after it has
+ * waited for all active requests to end.
+ */
+ JS_LOCK_GC(rt);
+#ifdef JS_THREADSAFE
+ JS_ASSERT(!rt->gcRunning || rt->gcLevel > 0);
+ if (rt->gcRunning && rt->gcThread->id != js_CurrentThreadId()) {
+ do {
+ JS_AWAIT_GC_DONE(rt);
+ } while (rt->gcLevel > 0);
+ }
+#endif
+ rhe = (JSGCRootHashEntry *)
+ JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_ADD);
+ if (rhe) {
+ rhe->root = rp;
+ rhe->name = name;
+ ok = JS_TRUE;
+ } else {
+ ok = JS_FALSE;
+ }
+ JS_UNLOCK_GC(rt);
+ return ok;
+}
+
+JSBool
+js_RemoveRoot(JSRuntime *rt, void *rp)
+{
+ /*
+ * Due to the JS_RemoveRootRT API, we may be called outside of a request.
+ * Same synchronization drill as above in js_AddRoot.
+ */
+ JS_LOCK_GC(rt);
+#ifdef JS_THREADSAFE
+ JS_ASSERT(!rt->gcRunning || rt->gcLevel > 0);
+ if (rt->gcRunning && rt->gcThread->id != js_CurrentThreadId()) {
+ do {
+ JS_AWAIT_GC_DONE(rt);
+ } while (rt->gcLevel > 0);
+ }
+#endif
+ (void) JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_REMOVE);
+ rt->gcPoke = JS_TRUE;
+ JS_UNLOCK_GC(rt);
+ return JS_TRUE;
+}
+
+#ifdef DEBUG
+
+static JSDHashOperator
+js_root_printer(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 i, void *arg)
+{
+ uint32 *leakedroots = (uint32 *)arg;
+ JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
+
+ (*leakedroots)++;
+ fprintf(stderr,
+ "JS engine warning: leaking GC root \'%s\' at %p\n",
+ rhe->name ? (char *)rhe->name : "", rhe->root);
+
+ return JS_DHASH_NEXT;
+}
+
+static void
+CheckLeakedRoots(JSRuntime *rt)
+{
+ uint32 leakedroots = 0;
+
+ /* Warn (but don't assert) debug builds of any remaining roots. */
+ JS_DHashTableEnumerate(&rt->gcRootsHash, js_root_printer,
+ &leakedroots);
+ if (leakedroots > 0) {
+ if (leakedroots == 1) {
+ fprintf(stderr,
+"JS engine warning: 1 GC root remains after destroying the JSRuntime at %p.\n"
+" This root may point to freed memory. Objects reachable\n"
+" through it have not been finalized.\n",
+ (void *) rt);
+ } else {
+ fprintf(stderr,
+"JS engine warning: %lu GC roots remain after destroying the JSRuntime at %p.\n"
+" These roots may point to freed memory. Objects reachable\n"
+" through them have not been finalized.\n",
+ (unsigned long) leakedroots, (void *) rt);
+ }
+ }
+}
+
+typedef struct NamedRootDumpArgs {
+ void (*dump)(const char *name, void *rp, void *data);
+ void *data;
+} NamedRootDumpArgs;
+
+static JSDHashOperator
+js_named_root_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
+ void *arg)
+{
+ NamedRootDumpArgs *args = (NamedRootDumpArgs *) arg;
+ JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
+
+ if (rhe->name)
+ args->dump(rhe->name, rhe->root, args->data);
+ return JS_DHASH_NEXT;
+}
+
+JS_BEGIN_EXTERN_C
+void
+js_DumpNamedRoots(JSRuntime *rt,
+ void (*dump)(const char *name, void *rp, void *data),
+ void *data)
+{
+ NamedRootDumpArgs args;
+
+ args.dump = dump;
+ args.data = data;
+ JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args);
+}
+JS_END_EXTERN_C
+
+#endif /* DEBUG */
+
+typedef struct GCRootMapArgs {
+ JSGCRootMapFun map;
+ void *data;
+} GCRootMapArgs;
+
+static JSDHashOperator
+js_gcroot_mapper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
+ void *arg)
+{
+ GCRootMapArgs *args = (GCRootMapArgs *) arg;
+ JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
+ intN mapflags;
+ int op;
+
+ mapflags = args->map(rhe->root, rhe->name, args->data);
+
+#if JS_MAP_GCROOT_NEXT == JS_DHASH_NEXT && \
+ JS_MAP_GCROOT_STOP == JS_DHASH_STOP && \
+ JS_MAP_GCROOT_REMOVE == JS_DHASH_REMOVE
+ op = (JSDHashOperator)mapflags;
+#else
+ op = JS_DHASH_NEXT;
+ if (mapflags & JS_MAP_GCROOT_STOP)
+ op |= JS_DHASH_STOP;
+ if (mapflags & JS_MAP_GCROOT_REMOVE)
+ op |= JS_DHASH_REMOVE;
+#endif
+
+ return (JSDHashOperator) op;
+}
+
+uint32
+js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
+{
+ GCRootMapArgs args;
+ uint32 rv;
+
+ args.map = map;
+ args.data = data;
+ JS_LOCK_GC(rt);
+ rv = JS_DHashTableEnumerate(&rt->gcRootsHash, js_gcroot_mapper, &args);
+ JS_UNLOCK_GC(rt);
+ return rv;
+}
+
+JSBool
+js_RegisterCloseableIterator(JSContext *cx, JSObject *obj)
+{
+ JSRuntime *rt;
+ JSBool ok;
+
+ rt = cx->runtime;
+ JS_ASSERT(!rt->gcRunning);
+
+ JS_LOCK_GC(rt);
+ ok = AddToPtrTable(cx, &rt->gcIteratorTable, &iteratorTableInfo, obj);
+ JS_UNLOCK_GC(rt);
+ return ok;
+}
+
+static void
+CloseNativeIterators(JSContext *cx)
+{
+ JSRuntime *rt;
+ size_t count, newCount, i;
+ void **array;
+ JSObject *obj;
+
+ rt = cx->runtime;
+ count = rt->gcIteratorTable.count;
+ array = rt->gcIteratorTable.array;
+
+ newCount = 0;
+ for (i = 0; i != count; ++i) {
+ obj = (JSObject *)array[i];
+ if (js_IsAboutToBeFinalized(cx, obj))
+ js_CloseNativeIterator(cx, obj);
+ else
+ array[newCount++] = obj;
+ }
+ ShrinkPtrTable(&rt->gcIteratorTable, &iteratorTableInfo, newCount);
+}
+
+#if defined(DEBUG_brendan) || defined(DEBUG_timeless)
+#define DEBUG_gchist
+#endif
+
+#ifdef DEBUG_gchist
+#define NGCHIST 64
+
+static struct GCHist {
+ JSBool lastDitch;
+ JSGCThing *freeList;
+} gchist[NGCHIST];
+
+unsigned gchpos = 0;
+#endif
+
+#ifdef JS_THREADSAFE
+
+const JSGCFreeListSet js_GCEmptyFreeListSet = {
+ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, NULL
+};
+
+static void
+TrimGCFreeListsPool(JSRuntime *rt, uintN keepCount)
+{
+ JSGCFreeListSet **cursor, *freeLists, *link;
+
+ cursor = &rt->gcFreeListsPool;
+ while (keepCount != 0) {
+ --keepCount;
+ freeLists = *cursor;
+ if (!freeLists)
+ return;
+ memset(freeLists->array, 0, sizeof freeLists->array);
+ cursor = &freeLists->link;
+ }
+ freeLists = *cursor;
+ if (freeLists) {
+ *cursor = NULL;
+ do {
+ link = freeLists->link;
+ free(freeLists);
+ } while ((freeLists = link) != NULL);
+ }
+}
+
+void
+js_RevokeGCLocalFreeLists(JSContext *cx)
+{
+ JS_ASSERT(!cx->gcLocalFreeLists->link);
+ if (cx->gcLocalFreeLists != &js_GCEmptyFreeListSet) {
+ cx->gcLocalFreeLists->link = cx->runtime->gcFreeListsPool;
+ cx->runtime->gcFreeListsPool = cx->gcLocalFreeLists;
+ cx->gcLocalFreeLists = (JSGCFreeListSet *) &js_GCEmptyFreeListSet;
+ }
+}
+
+static JSGCFreeListSet *
+EnsureLocalFreeList(JSContext *cx)
+{
+ JSGCFreeListSet *freeLists;
+
+ freeLists = cx->gcLocalFreeLists;
+ if (freeLists != &js_GCEmptyFreeListSet) {
+ JS_ASSERT(freeLists);
+ return freeLists;
+ }
+
+ freeLists = cx->runtime->gcFreeListsPool;
+ if (freeLists) {
+ cx->runtime->gcFreeListsPool = freeLists->link;
+ freeLists->link = NULL;
+ } else {
+ /* JS_malloc is not used as the caller reports out-of-memory itself. */
+ freeLists = (JSGCFreeListSet *) calloc(1, sizeof *freeLists);
+ if (!freeLists)
+ return NULL;
+ }
+ cx->gcLocalFreeLists = freeLists;
+ return freeLists;
+}
+
+#endif
+
+void *
+js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
+{
+ JSRuntime *rt;
+ uintN flindex;
+ JSBool doGC;
+ JSGCThing *thing;
+ uint8 *flagp;
+ JSGCArenaList *arenaList;
+ JSGCArenaInfo *a;
+ uintN thingsLimit;
+ JSLocalRootStack *lrs;
+#ifdef JS_GCMETER
+ JSGCArenaStats *astats;
+#endif
+#ifdef JS_THREADSAFE
+ JSBool gcLocked;
+ uintN localMallocBytes;
+ JSGCFreeListSet *freeLists;
+ JSGCThing **lastptr;
+ JSGCThing *tmpthing;
+ uint8 *tmpflagp;
+ uintN maxFreeThings; /* max to take from the global free list */
+#endif
+
+ JS_ASSERT((flags & GCF_TYPEMASK) != GCX_DOUBLE);
+ rt = cx->runtime;
+ nbytes = JS_ROUNDUP(nbytes, sizeof(JSGCThing));
+ flindex = GC_FREELIST_INDEX(nbytes);
+
+ /* Updates of metering counters here may not be thread-safe. */
+ METER(astats = &cx->runtime->gcStats.arenaStats[flindex]);
+ METER(astats->alloc++);
+
+#ifdef JS_THREADSAFE
+ gcLocked = JS_FALSE;
+ JS_ASSERT(cx->thread);
+ freeLists = cx->gcLocalFreeLists;
+ thing = freeLists->array[flindex];
+ localMallocBytes = cx->thread->gcMallocBytes;
+ if (thing && rt->gcMaxMallocBytes - rt->gcMallocBytes > localMallocBytes) {
+ flagp = thing->flagp;
+ freeLists->array[flindex] = thing->next;
+ METER(astats->localalloc++);
+ goto success;
+ }
+
+ JS_LOCK_GC(rt);
+ gcLocked = JS_TRUE;
+
+ /* Transfer thread-local counter to global one. */
+ if (localMallocBytes != 0) {
+ cx->thread->gcMallocBytes = 0;
+ if (rt->gcMaxMallocBytes - rt->gcMallocBytes < localMallocBytes)
+ rt->gcMallocBytes = rt->gcMaxMallocBytes;
+ else
+ rt->gcMallocBytes += localMallocBytes;
+ }
+#endif
+ JS_ASSERT(!rt->gcRunning);
+ if (rt->gcRunning) {
+ METER(rt->gcStats.finalfail++);
+ JS_UNLOCK_GC(rt);
+ return NULL;
+ }
+
+ doGC = (rt->gcMallocBytes >= rt->gcMaxMallocBytes && rt->gcPoke);
+#ifdef JS_GC_ZEAL
+ doGC = doGC || rt->gcZeal >= 2 || (rt->gcZeal >= 1 && rt->gcPoke);
+#endif
+
+ arenaList = &rt->gcArenaList[flindex];
+ for (;;) {
+ if (doGC && !JS_ON_TRACE(cx)) {
+ /*
+ * Keep rt->gcLock across the call into js_GC so we don't starve
+ * and lose to racing threads who deplete the heap just after
+ * js_GC has replenished it (or has synchronized with a racing
+ * GC that collected a bunch of garbage). This unfair scheduling
+ * can happen on certain operating systems. For the gory details,
+ * see bug 162779 at https://bugzilla.mozilla.org/.
+ */
+ js_GC(cx, GC_LAST_DITCH);
+ METER(astats->retry++);
+ }
+
+ /* Try to get thing from the free list. */
+ thing = arenaList->freeList;
+ if (thing) {
+ arenaList->freeList = thing->next;
+ flagp = thing->flagp;
+ JS_ASSERT(*flagp & GCF_FINAL);
+
+#ifdef JS_THREADSAFE
+ /*
+ * Refill the local free list by taking several things from the
+ * global free list unless we are still at rt->gcMaxMallocBytes
+ * barrier or the free list is already populated. The former
+ * happens when GC is canceled due to !gcCallback(cx, JSGC_BEGIN)
+ * or no gcPoke. The latter is caused via allocating new things
+ * in gcCallback(cx, JSGC_END).
+ */
+ if (rt->gcMallocBytes >= rt->gcMaxMallocBytes)
+ break;
+
+ freeLists = EnsureLocalFreeList(cx);
+ if (!freeLists)
+ goto fail;
+ if (freeLists->array[flindex])
+ break;
+
+ tmpthing = arenaList->freeList;
+ if (tmpthing) {
+ maxFreeThings = MAX_THREAD_LOCAL_THINGS;
+ do {
+ if (!tmpthing->next)
+ break;
+ tmpthing = tmpthing->next;
+ } while (--maxFreeThings != 0);
+
+ freeLists->array[flindex] = arenaList->freeList;
+ arenaList->freeList = tmpthing->next;
+ tmpthing->next = NULL;
+ }
+#endif
+ break;
+ }
+
+ /*
+ * Try to allocate things from the last arena. If it is fully used,
+ * check if we can allocate a new one and, if we cannot, consider
+ * doing a "last ditch" GC unless already tried.
+ */
+ thingsLimit = THINGS_PER_ARENA(nbytes);
+ if (arenaList->lastCount != thingsLimit) {
+ JS_ASSERT(arenaList->lastCount < thingsLimit);
+ a = arenaList->last;
+ } else {
+ a = NewGCArena(rt);
+ if (!a) {
+ if (doGC || JS_ON_TRACE(cx))
+ goto fail;
+ doGC = JS_TRUE;
+ continue;
+ }
+ a->list = arenaList;
+ a->prev = arenaList->last;
+ a->prevUntracedPage = 0;
+ a->u.untracedThings = 0;
+ arenaList->last = a;
+ arenaList->lastCount = 0;
+ }
+
+ flagp = THING_FLAGP(a, arenaList->lastCount);
+ thing = FLAGP_TO_THING(flagp, nbytes);
+ arenaList->lastCount++;
+
+#ifdef JS_THREADSAFE
+ /*
+ * Refill the local free list by taking free things from the last
+ * arena. Prefer to order free things by ascending address in the
+ * (unscientific) hope of better cache locality.
+ */
+ if (rt->gcMallocBytes >= rt->gcMaxMallocBytes)
+ break;
+
+ freeLists = EnsureLocalFreeList(cx);
+ if (!freeLists)
+ goto fail;
+ if (freeLists->array[flindex])
+ break;
+ lastptr = &freeLists->array[flindex];
+ maxFreeThings = thingsLimit - arenaList->lastCount;
+ if (maxFreeThings > MAX_THREAD_LOCAL_THINGS)
+ maxFreeThings = MAX_THREAD_LOCAL_THINGS;
+ while (maxFreeThings != 0) {
+ --maxFreeThings;
+
+ tmpflagp = THING_FLAGP(a, arenaList->lastCount);
+ tmpthing = FLAGP_TO_THING(tmpflagp, nbytes);
+ arenaList->lastCount++;
+ tmpthing->flagp = tmpflagp;
+ *tmpflagp = GCF_FINAL; /* signifying that thing is free */
+
+ *lastptr = tmpthing;
+ lastptr = &tmpthing->next;
+ }
+ *lastptr = NULL;
+#endif
+ break;
+ }
+
+ /* We successfully allocated the thing. */
+#ifdef JS_THREADSAFE
+ success:
+#endif
+ lrs = cx->localRootStack;
+ if (lrs) {
+ /*
+ * If we're in a local root scope, don't set newborn[type] at all, to
+ * avoid entraining garbage from it for an unbounded amount of time
+ * on this context. A caller will leave the local root scope and pop
+ * this reference, allowing thing to be GC'd if it has no other refs.
+ * See JS_EnterLocalRootScope and related APIs.
+ */
+ if (js_PushLocalRoot(cx, lrs, (jsval) thing) < 0) {
+ /*
+ * When we fail for a thing allocated through the tail of the last
+ * arena, thing's flag byte is not initialized. So to prevent GC
+ * accessing the uninitialized flags during the finalization, we
+ * always mark the thing as final. See bug 337407.
+ */
+ *flagp = GCF_FINAL;
+ goto fail;
+ }
+ } else {
+ /*
+ * No local root scope, so we're stuck with the old, fragile model of
+ * depending on a pigeon-hole newborn per type per context.
+ */
+ cx->weakRoots.newborn[flags & GCF_TYPEMASK] = thing;
+ }
+
+ /* We can't fail now, so update flags. */
+ *flagp = (uint8)flags;
+
+#ifdef DEBUG_gchist
+ gchist[gchpos].lastDitch = doGC;
+ gchist[gchpos].freeList = rt->gcArenaList[flindex].freeList;
+ if (++gchpos == NGCHIST)
+ gchpos = 0;
+#endif
+
+ /* This is not thread-safe for thread-local allocations. */
+ METER_IF(flags & GCF_LOCK, rt->gcStats.lockborn++);
+
+#ifdef JS_THREADSAFE
+ if (gcLocked)
+ JS_UNLOCK_GC(rt);
+#endif
+ JS_COUNT_OPERATION(cx, JSOW_ALLOCATION);
+ return thing;
+
+fail:
+#ifdef JS_THREADSAFE
+ if (gcLocked)
+ JS_UNLOCK_GC(rt);
+#endif
+ METER(astats->fail++);
+ if (!JS_ON_TRACE(cx))
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+}
+
+static JSGCDoubleCell *
+RefillDoubleFreeList(JSContext *cx)
+{
+ JSRuntime *rt;
+ jsbitmap *doubleFlags, usedBits;
+ JSBool didGC = JS_FALSE;
+ JSGCArenaInfo *a;
+ uintN bit, index;
+ JSGCDoubleCell *cell, *list, *lastcell;
+
+ JS_ASSERT(!cx->doubleFreeList);
+
+ rt = cx->runtime;
+ JS_LOCK_GC(rt);
+
+ JS_ASSERT(!rt->gcRunning);
+ if (rt->gcRunning) {
+ METER(rt->gcStats.finalfail++);
+ JS_UNLOCK_GC(rt);
+ return NULL;
+ }
+
+ if (rt->gcMallocBytes >= rt->gcMaxMallocBytes && rt->gcPoke
+#ifdef JS_GC_ZEAL
+ && (rt->gcZeal >= 2 || (rt->gcZeal >= 1 && rt->gcPoke))
+#endif
+ ) {
+ goto do_gc;
+ }
+
+ /*
+ * Loop until we find a flag bitmap byte with unset bits indicating free
+ * double cells, then set all bits as used and put the cells to the free
+ * list for the current context.
+ */
+ doubleFlags = rt->gcDoubleArenaList.nextDoubleFlags;
+ for (;;) {
+ if (((jsuword) doubleFlags & GC_ARENA_MASK) ==
+ ARENA_INFO_OFFSET) {
+ if (doubleFlags == DOUBLE_BITMAP_SENTINEL ||
+ !((JSGCArenaInfo *) doubleFlags)->prev) {
+ a = NewGCArena(rt);
+ if (!a) {
+ do_gc:
+ if (didGC || JS_ON_TRACE(cx)) {
+ METER(rt->gcStats.doubleArenaStats.fail++);
+ JS_UNLOCK_GC(rt);
+ if (!JS_ON_TRACE(cx))
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ js_GC(cx, GC_LAST_DITCH);
+ METER(rt->gcStats.doubleArenaStats.retry++);
+ doubleFlags = rt->gcDoubleArenaList.nextDoubleFlags;
+ didGC = JS_TRUE;
+ continue;
+ }
+ a->list = NULL;
+ a->prev = NULL;
+ if (doubleFlags == DOUBLE_BITMAP_SENTINEL) {
+ JS_ASSERT(!rt->gcDoubleArenaList.first);
+ rt->gcDoubleArenaList.first = a;
+ } else {
+ JS_ASSERT(rt->gcDoubleArenaList.first);
+ ((JSGCArenaInfo *) doubleFlags)->prev = a;
+ }
+ ClearDoubleArenaFlags(a);
+ doubleFlags = DOUBLE_ARENA_BITMAP(a);
+ break;
+ }
+ doubleFlags =
+ DOUBLE_ARENA_BITMAP(((JSGCArenaInfo *) doubleFlags)->prev);
+ }
+
+ /*
+ * When doubleFlags points the last bitmap's word in the arena, its
+ * high bits corresponds to non-existing cells. ClearDoubleArenaFlags
+ * sets such bits to 1. Thus even for this last word its bit is unset
+ * iff the corresponding cell exists and free.
+ */
+ if (*doubleFlags != (jsbitmap) -1)
+ break;
+ ++doubleFlags;
+ }
+
+ rt->gcDoubleArenaList.nextDoubleFlags = doubleFlags + 1;
+ usedBits = *doubleFlags;
+ JS_ASSERT(usedBits != (jsbitmap) -1);
+ *doubleFlags = (jsbitmap) -1;
+ JS_UNLOCK_GC(rt);
+
+ /*
+ * Find the index corresponding to the first bit in *doubleFlags. The last
+ * bit will have "index + JS_BITS_PER_WORD - 1".
+ */
+ index = ((uintN) ((jsuword) doubleFlags & GC_ARENA_MASK) -
+ DOUBLES_ARENA_BITMAP_OFFSET) * JS_BITS_PER_BYTE;
+ cell = (JSGCDoubleCell *) ((jsuword) doubleFlags & ~GC_ARENA_MASK) + index;
+
+ if (usedBits == 0) {
+ /* The common case when all doubles from *doubleFlags are free. */
+ JS_ASSERT(index + JS_BITS_PER_WORD <= DOUBLES_PER_ARENA);
+ list = cell;
+ for (lastcell = cell + JS_BITS_PER_WORD - 1; cell != lastcell; ++cell)
+ cell->link = cell + 1;
+ lastcell->link = NULL;
+ } else {
+ /*
+ * Assemble the free list from free cells from *doubleFlags starting
+ * from the tail. In the loop
+ *
+ * index + bit >= DOUBLES_PER_ARENA
+ *
+ * when bit is one of the unused bits. We do not check for such bits
+ * explicitly as they must be set and the "if" check filters them out.
+ */
+ JS_ASSERT(index + JS_BITS_PER_WORD <=
+ DOUBLES_PER_ARENA + UNUSED_DOUBLE_BITMAP_BITS);
+ bit = JS_BITS_PER_WORD;
+ cell += bit;
+ list = NULL;
+ do {
+ --bit;
+ --cell;
+ if (!(((jsbitmap) 1 << bit) & usedBits)) {
+ JS_ASSERT(index + bit < DOUBLES_PER_ARENA);
+ JS_ASSERT_IF(index + bit == DOUBLES_PER_ARENA - 1, !list);
+ cell->link = list;
+ list = cell;
+ }
+ } while (bit != 0);
+ }
+ JS_ASSERT(list);
+ JS_COUNT_OPERATION(cx, JSOW_ALLOCATION * JS_BITS_PER_WORD);
+
+ /*
+ * We delegate assigning cx->doubleFreeList to js_NewDoubleInRootedValue as
+ * it immediately consumes the head of the list.
+ */
+ return list;
+}
+
+JSBool
+js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
+{
+#ifdef JS_GCMETER
+ JSGCArenaStats *astats;
+#endif
+ JSGCDoubleCell *cell;
+
+ /* Updates of metering counters here are not thread-safe. */
+ METER(astats = &cx->runtime->gcStats.doubleArenaStats);
+ METER(astats->alloc++);
+ cell = cx->doubleFreeList;
+ if (!cell) {
+ cell = RefillDoubleFreeList(cx);
+ if (!cell) {
+ METER(astats->fail++);
+ return JS_FALSE;
+ }
+ } else {
+ METER(astats->localalloc++);
+ }
+ cx->doubleFreeList = cell->link;
+ cell->number = d;
+ *vp = DOUBLE_TO_JSVAL(&cell->number);
+ return JS_TRUE;
+}
+
+jsdouble *
+js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d)
+{
+ jsval v;
+ jsdouble *dp;
+
+ if (!js_NewDoubleInRootedValue(cx, d, &v))
+ return NULL;
+
+ JS_ASSERT(JSVAL_IS_DOUBLE(v));
+ dp = JSVAL_TO_DOUBLE(v);
+ if (cx->localRootStack) {
+ if (js_PushLocalRoot(cx, cx->localRootStack, v) < 0)
+ return NULL;
+ } else {
+ cx->weakRoots.newborn[GCX_DOUBLE] = dp;
+ }
+ return dp;
+}
+
+JSBool
+js_AddAsGCBytes(JSContext *cx, size_t sz)
+{
+ JSRuntime *rt;
+
+ rt = cx->runtime;
+ if (rt->gcBytes >= rt->gcMaxBytes ||
+ sz > (size_t) (rt->gcMaxBytes - rt->gcBytes)
+#ifdef JS_GC_ZEAL
+ || rt->gcZeal >= 2 || (rt->gcZeal >= 1 && rt->gcPoke)
+#endif
+ ) {
+ if (JS_ON_TRACE(cx)) {
+ JS_UNLOCK_GC(rt);
+ return JS_FALSE;
+ }
+ js_GC(cx, GC_LAST_DITCH);
+ if (rt->gcBytes >= rt->gcMaxBytes ||
+ sz > (size_t) (rt->gcMaxBytes - rt->gcBytes)) {
+ JS_UNLOCK_GC(rt);
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ }
+ rt->gcBytes += (uint32) sz;
+ return JS_TRUE;
+}
+
+void
+js_RemoveAsGCBytes(JSRuntime *rt, size_t sz)
+{
+ JS_ASSERT((size_t) rt->gcBytes >= sz);
+ rt->gcBytes -= (uint32) sz;
+}
+
+/*
+ * Shallow GC-things can be locked just by setting the GCF_LOCK bit, because
+ * they have no descendants to mark during the GC. Currently the optimization
+ * is only used for non-dependant strings.
+ */
+#define GC_THING_IS_SHALLOW(flagp, thing) \
+ ((flagp) && \
+ ((*(flagp) & GCF_TYPEMASK) >= GCX_EXTERNAL_STRING || \
+ ((*(flagp) & GCF_TYPEMASK) == GCX_STRING && \
+ !JSSTRING_IS_DEPENDENT((JSString *) (thing)))))
+
+/* This is compatible with JSDHashEntryStub. */
+typedef struct JSGCLockHashEntry {
+ JSDHashEntryHdr hdr;
+ const void *thing;
+ uint32 count;
+} JSGCLockHashEntry;
+
+JSBool
+js_LockGCThingRT(JSRuntime *rt, void *thing)
+{
+ JSBool shallow, ok;
+ uint8 *flagp;
+ JSGCLockHashEntry *lhe;
+
+ if (!thing)
+ return JS_TRUE;
+
+ flagp = GetGCThingFlagsOrNull(thing);
+ JS_LOCK_GC(rt);
+ shallow = GC_THING_IS_SHALLOW(flagp, thing);
+
+ /*
+ * Avoid adding a rt->gcLocksHash entry for shallow things until someone
+ * nests a lock.
+ */
+ if (shallow && !(*flagp & GCF_LOCK)) {
+ *flagp |= GCF_LOCK;
+ METER(rt->gcStats.lock++);
+ ok = JS_TRUE;
+ goto out;
+ }
+
+ if (!rt->gcLocksHash) {
+ rt->gcLocksHash = JS_NewDHashTable(JS_DHashGetStubOps(), NULL,
+ sizeof(JSGCLockHashEntry),
+ GC_ROOTS_SIZE);
+ if (!rt->gcLocksHash) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+
+ lhe = (JSGCLockHashEntry *)
+ JS_DHashTableOperate(rt->gcLocksHash, thing, JS_DHASH_ADD);
+ if (!lhe) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ if (!lhe->thing) {
+ lhe->thing = thing;
+ lhe->count = 1;
+ } else {
+ JS_ASSERT(lhe->count >= 1);
+ lhe->count++;
+ }
+
+ METER(rt->gcStats.lock++);
+ ok = JS_TRUE;
+ out:
+ JS_UNLOCK_GC(rt);
+ return ok;
+}
+
+JSBool
+js_UnlockGCThingRT(JSRuntime *rt, void *thing)
+{
+ uint8 *flagp;
+ JSBool shallow;
+ JSGCLockHashEntry *lhe;
+
+ if (!thing)
+ return JS_TRUE;
+
+ flagp = GetGCThingFlagsOrNull(thing);
+ JS_LOCK_GC(rt);
+ shallow = GC_THING_IS_SHALLOW(flagp, thing);
+
+ if (shallow && !(*flagp & GCF_LOCK))
+ goto out;
+ if (!rt->gcLocksHash ||
+ (lhe = (JSGCLockHashEntry *)
+ JS_DHashTableOperate(rt->gcLocksHash, thing,
+ JS_DHASH_LOOKUP),
+ JS_DHASH_ENTRY_IS_FREE(&lhe->hdr))) {
+ /* Shallow entry is not in the hash -> clear its lock bit. */
+ if (shallow)
+ *flagp &= ~GCF_LOCK;
+ else
+ goto out;
+ } else {
+ if (--lhe->count != 0)
+ goto out;
+ JS_DHashTableOperate(rt->gcLocksHash, thing, JS_DHASH_REMOVE);
+ }
+
+ rt->gcPoke = JS_TRUE;
+ METER(rt->gcStats.unlock++);
+ out:
+ JS_UNLOCK_GC(rt);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(void)
+JS_TraceChildren(JSTracer *trc, void *thing, uint32 kind)
+{
+ JSObject *obj;
+ size_t nslots, i;
+ jsval v;
+ JSString *str;
+
+ switch (kind) {
+ case JSTRACE_OBJECT:
+ /* If obj has no map, it must be a newborn. */
+ obj = (JSObject *) thing;
+ if (!obj->map)
+ break;
+ if (obj->map->ops->trace) {
+ obj->map->ops->trace(trc, obj);
+ } else {
+ nslots = STOBJ_NSLOTS(obj);
+ for (i = 0; i != nslots; ++i) {
+ v = STOBJ_GET_SLOT(obj, i);
+ if (JSVAL_IS_TRACEABLE(v)) {
+ JS_SET_TRACING_INDEX(trc, "slot", i);
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v),
+ JSVAL_TRACE_KIND(v));
+ }
+ }
+ }
+ break;
+
+ case JSTRACE_STRING:
+ str = (JSString *)thing;
+ if (JSSTRING_IS_DEPENDENT(str))
+ JS_CALL_STRING_TRACER(trc, JSSTRDEP_BASE(str), "base");
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case JSTRACE_XML:
+ js_TraceXML(trc, (JSXML *)thing);
+ break;
+#endif
+ }
+}
+
+/*
+ * Number of things covered by a single bit of JSGCArenaInfo.u.untracedThings.
+ */
+#define THINGS_PER_UNTRACED_BIT(thingSize) \
+ JS_HOWMANY(THINGS_PER_ARENA(thingSize), JS_BITS_PER_WORD)
+
+static void
+DelayTracingChildren(JSRuntime *rt, uint8 *flagp)
+{
+ JSGCArenaInfo *a;
+ uint32 untracedBitIndex;
+ jsuword bit;
+
+ /*
+ * Things with children to be traced later are marked with
+ * GCF_MARK | GCF_FINAL flags.
+ */
+ JS_ASSERT((*flagp & (GCF_MARK | GCF_FINAL)) == GCF_MARK);
+ *flagp |= GCF_FINAL;
+
+ METER(rt->gcStats.untraced++);
+#ifdef DEBUG
+ ++rt->gcTraceLaterCount;
+ METER_UPDATE_MAX(rt->gcStats.maxuntraced, rt->gcTraceLaterCount);
+#endif
+
+ a = FLAGP_TO_ARENA(flagp);
+ untracedBitIndex = FLAGP_TO_INDEX(flagp) /
+ THINGS_PER_UNTRACED_BIT(a->list->thingSize);
+ JS_ASSERT(untracedBitIndex < JS_BITS_PER_WORD);
+ bit = (jsuword)1 << untracedBitIndex;
+ if (a->u.untracedThings != 0) {
+ JS_ASSERT(rt->gcUntracedArenaStackTop);
+ if (a->u.untracedThings & bit) {
+ /* bit already covers things with children to trace later. */
+ return;
+ }
+ a->u.untracedThings |= bit;
+ } else {
+ /*
+ * The thing is the first thing with not yet traced children in the
+ * whole arena, so push the arena on the stack of arenas with things
+ * to be traced later unless the arena has already been pushed. We
+ * detect that through checking prevUntracedPage as the field is 0
+ * only for not yet pushed arenas. To ensure that
+ * prevUntracedPage != 0
+ * even when the stack contains one element, we make prevUntracedPage
+ * for the arena at the bottom to point to itself.
+ *
+ * See comments in TraceDelayedChildren.
+ */
+ a->u.untracedThings = bit;
+ if (a->prevUntracedPage == 0) {
+ if (!rt->gcUntracedArenaStackTop) {
+ /* Stack was empty, mark the arena as the bottom element. */
+ a->prevUntracedPage = ARENA_INFO_TO_PAGE(a);
+ } else {
+ JS_ASSERT(rt->gcUntracedArenaStackTop->prevUntracedPage != 0);
+ a->prevUntracedPage =
+ ARENA_INFO_TO_PAGE(rt->gcUntracedArenaStackTop);
+ }
+ rt->gcUntracedArenaStackTop = a;
+ }
+ }
+ JS_ASSERT(rt->gcUntracedArenaStackTop);
+}
+
+static void
+TraceDelayedChildren(JSTracer *trc)
+{
+ JSRuntime *rt;
+ JSGCArenaInfo *a, *aprev;
+ uint32 thingSize;
+ uint32 thingsPerUntracedBit;
+ uint32 untracedBitIndex, thingIndex, indexLimit, endIndex;
+ JSGCThing *thing;
+ uint8 *flagp;
+
+ rt = trc->context->runtime;
+ a = rt->gcUntracedArenaStackTop;
+ if (!a) {
+ JS_ASSERT(rt->gcTraceLaterCount == 0);
+ return;
+ }
+
+ for (;;) {
+ /*
+ * The following assert verifies that the current arena belongs to the
+ * untraced stack, since DelayTracingChildren ensures that even for
+ * stack's bottom prevUntracedPage != 0 but rather points to itself.
+ */
+ JS_ASSERT(a->prevUntracedPage != 0);
+ JS_ASSERT(rt->gcUntracedArenaStackTop->prevUntracedPage != 0);
+ thingSize = a->list->thingSize;
+ indexLimit = (a == a->list->last)
+ ? a->list->lastCount
+ : THINGS_PER_ARENA(thingSize);
+ thingsPerUntracedBit = THINGS_PER_UNTRACED_BIT(thingSize);
+
+ /*
+ * We cannot use do-while loop here as a->u.untracedThings can be zero
+ * before the loop as a leftover from the previous iterations. See
+ * comments after the loop.
+ */
+ while (a->u.untracedThings != 0) {
+ untracedBitIndex = JS_FLOOR_LOG2W(a->u.untracedThings);
+ a->u.untracedThings &= ~((jsuword)1 << untracedBitIndex);
+ thingIndex = untracedBitIndex * thingsPerUntracedBit;
+ endIndex = thingIndex + thingsPerUntracedBit;
+
+ /*
+ * endIndex can go beyond the last allocated thing as the real
+ * limit can be "inside" the bit.
+ */
+ if (endIndex > indexLimit)
+ endIndex = indexLimit;
+ JS_ASSERT(thingIndex < indexLimit);
+
+ do {
+ /*
+ * Skip free or already traced things that share the bit
+ * with untraced ones.
+ */
+ flagp = THING_FLAGP(a, thingIndex);
+ if ((*flagp & (GCF_MARK|GCF_FINAL)) != (GCF_MARK|GCF_FINAL))
+ continue;
+ *flagp &= ~GCF_FINAL;
+#ifdef DEBUG
+ JS_ASSERT(rt->gcTraceLaterCount != 0);
+ --rt->gcTraceLaterCount;
+#endif
+ thing = FLAGP_TO_THING(flagp, thingSize);
+ JS_TraceChildren(trc, thing, MapGCFlagsToTraceKind(*flagp));
+ } while (++thingIndex != endIndex);
+ }
+
+ /*
+ * We finished tracing of all things in the the arena but we can only
+ * pop it from the stack if the arena is the stack's top.
+ *
+ * When JS_TraceChildren from the above calls JS_CallTracer that in
+ * turn on low C stack calls DelayTracingChildren and the latter
+ * pushes new arenas to the untraced stack, we have to skip popping
+ * of this arena until it becomes the top of the stack again.
+ */
+ if (a == rt->gcUntracedArenaStackTop) {
+ aprev = ARENA_PAGE_TO_INFO(a->prevUntracedPage);
+ a->prevUntracedPage = 0;
+ if (a == aprev) {
+ /*
+ * prevUntracedPage points to itself and we reached the
+ * bottom of the stack.
+ */
+ break;
+ }
+ rt->gcUntracedArenaStackTop = a = aprev;
+ } else {
+ a = rt->gcUntracedArenaStackTop;
+ }
+ }
+ JS_ASSERT(rt->gcUntracedArenaStackTop);
+ JS_ASSERT(rt->gcUntracedArenaStackTop->prevUntracedPage == 0);
+ rt->gcUntracedArenaStackTop = NULL;
+ JS_ASSERT(rt->gcTraceLaterCount == 0);
+}
+
+JS_PUBLIC_API(void)
+JS_CallTracer(JSTracer *trc, void *thing, uint32 kind)
+{
+ JSContext *cx;
+ JSRuntime *rt;
+ JSGCArenaInfo *a;
+ uintN index;
+ uint8 *flagp;
+
+ JS_ASSERT(thing);
+ JS_ASSERT(JS_IS_VALID_TRACE_KIND(kind));
+ JS_ASSERT(trc->debugPrinter || trc->debugPrintArg);
+
+ if (!IS_GC_MARKING_TRACER(trc)) {
+ trc->callback(trc, thing, kind);
+ goto out;
+ }
+
+ cx = trc->context;
+ rt = cx->runtime;
+ JS_ASSERT(rt->gcMarkingTracer == trc);
+ JS_ASSERT(rt->gcLevel > 0);
+
+ /*
+ * Optimize for string and double as their size is known and their tracing
+ * is not recursive.
+ */
+ switch (kind) {
+ case JSTRACE_DOUBLE:
+ a = THING_TO_ARENA(thing);
+ JS_ASSERT(!a->list);
+ if (!a->u.hasMarkedDoubles) {
+ ClearDoubleArenaFlags(a);
+ a->u.hasMarkedDoubles = JS_TRUE;
+ }
+ index = DOUBLE_THING_TO_INDEX(thing);
+ JS_SET_BIT(DOUBLE_ARENA_BITMAP(a), index);
+ goto out;
+
+ case JSTRACE_STRING:
+ for (;;) {
+ flagp = THING_TO_FLAGP(thing, sizeof(JSGCThing));
+ JS_ASSERT((*flagp & GCF_FINAL) == 0);
+ JS_ASSERT(kind == MapGCFlagsToTraceKind(*flagp));
+ if (!JSSTRING_IS_DEPENDENT((JSString *) thing)) {
+ *flagp |= GCF_MARK;
+ goto out;
+ }
+ if (*flagp & GCF_MARK)
+ goto out;
+ *flagp |= GCF_MARK;
+ thing = JSSTRDEP_BASE((JSString *) thing);
+ }
+ /* NOTREACHED */
+ }
+
+ flagp = GetGCThingFlags(thing);
+ JS_ASSERT(kind == MapGCFlagsToTraceKind(*flagp));
+ if (*flagp & GCF_MARK)
+ goto out;
+
+ /*
+ * We check for non-final flag only if mark is unset as
+ * DelayTracingChildren uses the flag. See comments in the function.
+ */
+ JS_ASSERT(*flagp != GCF_FINAL);
+ *flagp |= GCF_MARK;
+ if (!cx->insideGCMarkCallback) {
+ /*
+ * With JS_GC_ASSUME_LOW_C_STACK defined the mark phase of GC always
+ * uses the non-recursive code that otherwise would be called only on
+ * a low C stack condition.
+ */
+#ifdef JS_GC_ASSUME_LOW_C_STACK
+# define RECURSION_TOO_DEEP() JS_TRUE
+#else
+ int stackDummy;
+# define RECURSION_TOO_DEEP() (!JS_CHECK_STACK_SIZE(cx, stackDummy))
+#endif
+ if (RECURSION_TOO_DEEP())
+ DelayTracingChildren(rt, flagp);
+ else
+ JS_TraceChildren(trc, thing, kind);
+ } else {
+ /*
+ * For API compatibility we allow for the callback to assume that
+ * after it calls JS_MarkGCThing for the last time, the callback can
+ * start to finalize its own objects that are only referenced by
+ * unmarked GC things.
+ *
+ * Since we do not know which call from inside the callback is the
+ * last, we ensure that children of all marked things are traced and
+ * call TraceDelayedChildren(trc) after tracing the thing.
+ *
+ * As TraceDelayedChildren unconditionally invokes JS_TraceChildren
+ * for the things with untraced children, calling DelayTracingChildren
+ * is useless here. Hence we always trace thing's children even with a
+ * low native stack.
+ */
+ cx->insideGCMarkCallback = JS_FALSE;
+ JS_TraceChildren(trc, thing, kind);
+ TraceDelayedChildren(trc);
+ cx->insideGCMarkCallback = JS_TRUE;
+ }
+
+ out:
+#ifdef DEBUG
+ trc->debugPrinter = NULL;
+ trc->debugPrintArg = NULL;
+#endif
+ return; /* to avoid out: right_curl when DEBUG is not defined */
+}
+
+void
+js_CallValueTracerIfGCThing(JSTracer *trc, jsval v)
+{
+ void *thing;
+ uint32 kind;
+
+ if (JSVAL_IS_DOUBLE(v) || JSVAL_IS_STRING(v)) {
+ thing = JSVAL_TO_TRACEABLE(v);
+ kind = JSVAL_TRACE_KIND(v);
+ JS_ASSERT(kind == js_GetGCThingTraceKind(JSVAL_TO_GCTHING(v)));
+ } else if (JSVAL_IS_OBJECT(v) && v != JSVAL_NULL) {
+ /* v can be an arbitrary GC thing reinterpreted as an object. */
+ thing = JSVAL_TO_OBJECT(v);
+ kind = js_GetGCThingTraceKind(thing);
+ } else {
+ return;
+ }
+ JS_CallTracer(trc, thing, kind);
+}
+
+static JSDHashOperator
+gc_root_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num,
+ void *arg)
+{
+ JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
+ JSTracer *trc = (JSTracer *)arg;
+ jsval *rp = (jsval *)rhe->root;
+ jsval v = *rp;
+
+ /* Ignore null object and scalar values. */
+ if (!JSVAL_IS_NULL(v) && JSVAL_IS_GCTHING(v)) {
+#ifdef DEBUG
+ JSBool root_points_to_gcArenaList = JS_FALSE;
+ jsuword thing = (jsuword) JSVAL_TO_GCTHING(v);
+ JSRuntime *rt;
+ uintN i;
+ JSGCArenaList *arenaList;
+ uint32 thingSize;
+ JSGCArenaInfo *a;
+ size_t limit;
+
+ rt = trc->context->runtime;
+ for (i = 0; i < GC_NUM_FREELISTS; i++) {
+ arenaList = &rt->gcArenaList[i];
+ thingSize = arenaList->thingSize;
+ limit = (size_t) arenaList->lastCount * thingSize;
+ for (a = arenaList->last; a; a = a->prev) {
+ if (thing - ARENA_INFO_TO_START(a) < limit) {
+ root_points_to_gcArenaList = JS_TRUE;
+ break;
+ }
+ limit = (size_t) THINGS_PER_ARENA(thingSize) * thingSize;
+ }
+ }
+ if (!root_points_to_gcArenaList) {
+ for (a = rt->gcDoubleArenaList.first; a; a = a->prev) {
+ if (thing - ARENA_INFO_TO_START(a) <
+ DOUBLES_PER_ARENA * sizeof(jsdouble)) {
+ root_points_to_gcArenaList = JS_TRUE;
+ break;
+ }
+ }
+ }
+ if (!root_points_to_gcArenaList && rhe->name) {
+ fprintf(stderr,
+"JS API usage error: the address passed to JS_AddNamedRoot currently holds an\n"
+"invalid jsval. This is usually caused by a missing call to JS_RemoveRoot.\n"
+"The root's name is \"%s\".\n",
+ rhe->name);
+ }
+ JS_ASSERT(root_points_to_gcArenaList);
+#endif
+ JS_SET_TRACING_NAME(trc, rhe->name ? rhe->name : "root");
+ js_CallValueTracerIfGCThing(trc, v);
+ }
+
+ return JS_DHASH_NEXT;
+}
+
+static JSDHashOperator
+gc_lock_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num,
+ void *arg)
+{
+ JSGCLockHashEntry *lhe = (JSGCLockHashEntry *)hdr;
+ void *thing = (void *)lhe->thing;
+ JSTracer *trc = (JSTracer *)arg;
+ uint32 traceKind;
+
+ JS_ASSERT(lhe->count >= 1);
+ traceKind = js_GetGCThingTraceKind(thing);
+ JS_CALL_TRACER(trc, thing, traceKind, "locked object");
+ return JS_DHASH_NEXT;
+}
+
+#define TRACE_JSVALS(trc, len, vec, name) \
+ JS_BEGIN_MACRO \
+ jsval _v, *_vp, *_end; \
+ \
+ for (_vp = vec, _end = _vp + len; _vp < _end; _vp++) { \
+ _v = *_vp; \
+ if (JSVAL_IS_TRACEABLE(_v)) { \
+ JS_SET_TRACING_INDEX(trc, name, _vp - (vec)); \
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(_v), \
+ JSVAL_TRACE_KIND(_v)); \
+ } \
+ } \
+ JS_END_MACRO
+
+void
+js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
+{
+ uintN nslots, minargs, skip;
+
+ if (fp->callobj)
+ JS_CALL_OBJECT_TRACER(trc, fp->callobj, "call");
+ if (fp->argsobj)
+ JS_CALL_OBJECT_TRACER(trc, fp->argsobj, "arguments");
+ if (fp->varobj)
+ JS_CALL_OBJECT_TRACER(trc, fp->varobj, "variables");
+ if (fp->script) {
+ js_TraceScript(trc, fp->script);
+ if (fp->regs) {
+ /*
+ * Don't mark what has not been pushed yet, or what has been
+ * popped already.
+ */
+ nslots = (uintN) (fp->regs->sp - fp->slots);
+ TRACE_JSVALS(trc, nslots, fp->slots, "slot");
+ }
+ } else {
+ JS_ASSERT(!fp->slots);
+ JS_ASSERT(!fp->regs);
+ }
+
+ /* Allow for primitive this parameter due to JSFUN_THISP_* flags. */
+ JS_ASSERT(JSVAL_IS_OBJECT((jsval)fp->thisp) ||
+ (fp->fun && JSFUN_THISP_FLAGS(fp->fun->flags)));
+ JS_CALL_VALUE_TRACER(trc, (jsval)fp->thisp, "this");
+
+ if (fp->callee)
+ JS_CALL_OBJECT_TRACER(trc, fp->callee, "callee");
+
+ if (fp->argv) {
+ nslots = fp->argc;
+ skip = 0;
+ if (fp->fun) {
+ minargs = FUN_MINARGS(fp->fun);
+ if (minargs > nslots)
+ nslots = minargs;
+ if (!FUN_INTERPRETED(fp->fun)) {
+ JS_ASSERT(!(fp->fun->flags & JSFUN_FAST_NATIVE));
+ nslots += fp->fun->u.n.extra;
+ }
+ if (fp->fun->flags & JSFRAME_ROOTED_ARGV)
+ skip = 2 + fp->argc;
+ }
+ TRACE_JSVALS(trc, 2 + nslots - skip, fp->argv - 2 + skip, "operand");
+ }
+
+ JS_CALL_VALUE_TRACER(trc, fp->rval, "rval");
+ if (fp->scopeChain)
+ JS_CALL_OBJECT_TRACER(trc, fp->scopeChain, "scope chain");
+ if (fp->sharpArray)
+ JS_CALL_OBJECT_TRACER(trc, fp->sharpArray, "sharp array");
+
+ if (fp->xmlNamespace)
+ JS_CALL_OBJECT_TRACER(trc, fp->xmlNamespace, "xmlNamespace");
+}
+
+static void
+TraceWeakRoots(JSTracer *trc, JSWeakRoots *wr)
+{
+ uint32 i;
+ void *thing;
+
+#ifdef DEBUG
+ static const char *weakRootNames[JSTRACE_LIMIT] = {
+ "newborn object",
+ "newborn double",
+ "newborn string",
+ "newborn xml"
+ };
+#endif
+
+ for (i = 0; i != JSTRACE_LIMIT; i++) {
+ thing = wr->newborn[i];
+ if (thing)
+ JS_CALL_TRACER(trc, thing, i, weakRootNames[i]);
+ }
+ JS_ASSERT(i == GCX_EXTERNAL_STRING);
+ for (; i != GCX_NTYPES; ++i) {
+ thing = wr->newborn[i];
+ if (thing) {
+ JS_SET_TRACING_INDEX(trc, "newborn external string",
+ i - GCX_EXTERNAL_STRING);
+ JS_CallTracer(trc, thing, JSTRACE_STRING);
+ }
+ }
+
+ JS_CALL_VALUE_TRACER(trc, wr->lastAtom, "lastAtom");
+ JS_SET_TRACING_NAME(trc, "lastInternalResult");
+ js_CallValueTracerIfGCThing(trc, wr->lastInternalResult);
+}
+
+JS_FRIEND_API(void)
+js_TraceContext(JSTracer *trc, JSContext *acx)
+{
+ JSStackFrame *fp, *nextChain;
+ JSStackHeader *sh;
+ JSTempValueRooter *tvr;
+
+ if (IS_GC_MARKING_TRACER(trc)) {
+
+#define FREE_OLD_ARENAS(pool) \
+ JS_BEGIN_MACRO \
+ int64 _age; \
+ JSArena * _a = (pool).current; \
+ if (_a == (pool).first.next && \
+ _a->avail == _a->base + sizeof(int64)) { \
+ _age = JS_Now() - *(int64 *) _a->base; \
+ if (_age > (int64) acx->runtime->gcEmptyArenaPoolLifespan * \
+ 1000) \
+ JS_FreeArenaPool(&(pool)); \
+ } \
+ JS_END_MACRO
+
+#ifdef JS_THREADSAFE
+ js_RevokeGCLocalFreeLists(acx);
+#endif
+
+ /*
+ * Release the stackPool's arenas if the stackPool has existed for
+ * longer than the limit specified by gcEmptyArenaPoolLifespan.
+ */
+ FREE_OLD_ARENAS(acx->stackPool);
+
+ /*
+ * Release the regexpPool's arenas based on the same criterion as for
+ * the stackPool.
+ */
+ FREE_OLD_ARENAS(acx->regexpPool);
+
+ /*
+ * Clear the double free list to release all the pre-allocated doubles.
+ */
+ acx->doubleFreeList = NULL;
+ }
+
+ /*
+ * Iterate frame chain and dormant chains.
+ *
+ * (NB: see comment on this whole "dormant" thing in js_Execute.)
+ */
+ fp = acx->fp;
+ nextChain = acx->dormantFrameChain;
+ if (!fp)
+ goto next_chain;
+
+ /* The top frame must not be dormant. */
+ JS_ASSERT(!fp->dormantNext);
+ for (;;) {
+ do {
+ js_TraceStackFrame(trc, fp);
+ } while ((fp = fp->down) != NULL);
+
+ next_chain:
+ if (!nextChain)
+ break;
+ fp = nextChain;
+ nextChain = nextChain->dormantNext;
+ }
+
+ /* Mark other roots-by-definition in acx. */
+ if (acx->globalObject)
+ JS_CALL_OBJECT_TRACER(trc, acx->globalObject, "global object");
+ TraceWeakRoots(trc, &acx->weakRoots);
+ if (acx->throwing) {
+ JS_CALL_VALUE_TRACER(trc, acx->exception, "exception");
+ } else {
+ /* Avoid keeping GC-ed junk stored in JSContext.exception. */
+ acx->exception = JSVAL_NULL;
+ }
+#if JS_HAS_LVALUE_RETURN
+ if (acx->rval2set)
+ JS_CALL_VALUE_TRACER(trc, acx->rval2, "rval2");
+#endif
+
+ for (sh = acx->stackHeaders; sh; sh = sh->down) {
+ METER(trc->context->runtime->gcStats.stackseg++);
+ METER(trc->context->runtime->gcStats.segslots += sh->nslots);
+ TRACE_JSVALS(trc, sh->nslots, JS_STACK_SEGMENT(sh), "stack");
+ }
+
+ if (acx->localRootStack)
+ js_TraceLocalRoots(trc, acx->localRootStack);
+
+ for (tvr = acx->tempValueRooters; tvr; tvr = tvr->down) {
+ switch (tvr->count) {
+ case JSTVU_SINGLE:
+ JS_SET_TRACING_NAME(trc, "tvr->u.value");
+ js_CallValueTracerIfGCThing(trc, tvr->u.value);
+ break;
+ case JSTVU_TRACE:
+ tvr->u.trace(trc, tvr);
+ break;
+ case JSTVU_SPROP:
+ TRACE_SCOPE_PROPERTY(trc, tvr->u.sprop);
+ break;
+ case JSTVU_WEAK_ROOTS:
+ TraceWeakRoots(trc, tvr->u.weakRoots);
+ break;
+ case JSTVU_PARSE_CONTEXT:
+ js_TraceParseContext(trc, tvr->u.parseContext);
+ break;
+ case JSTVU_SCRIPT:
+ js_TraceScript(trc, tvr->u.script);
+ break;
+ default:
+ JS_ASSERT(tvr->count >= 0);
+ TRACE_JSVALS(trc, tvr->count, tvr->u.array, "tvr->u.array");
+ }
+ }
+
+ if (acx->sharpObjectMap.depth > 0)
+ js_TraceSharpMap(trc, &acx->sharpObjectMap);
+}
+
+void
+js_TraceTraceMonitor(JSTracer *trc, JSTraceMonitor *tm)
+{
+ if (IS_GC_MARKING_TRACER(trc)) {
+ tm->recoveryDoublePoolPtr = tm->recoveryDoublePool;
+ /* Make sure the global shape changes and will force a flush
+ of the code cache. */
+ tm->globalShape = -1;
+ }
+}
+
+void
+js_TraceRuntime(JSTracer *trc, JSBool allAtoms)
+{
+ JSRuntime *rt = trc->context->runtime;
+ JSContext *iter, *acx;
+
+ JS_DHashTableEnumerate(&rt->gcRootsHash, gc_root_traversal, trc);
+ if (rt->gcLocksHash)
+ JS_DHashTableEnumerate(rt->gcLocksHash, gc_lock_traversal, trc);
+ js_TraceAtomState(trc, allAtoms);
+ js_TraceNativeEnumerators(trc);
+ js_TraceRuntimeNumberState(trc);
+
+ iter = NULL;
+ while ((acx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL)
+ js_TraceContext(trc, acx);
+
+ if (rt->gcExtraRootsTraceOp)
+ rt->gcExtraRootsTraceOp(trc, rt->gcExtraRootsData);
+
+#ifdef JS_THREADSAFE
+ /* Trace the loop table(s) which can contain pointers to code objects. */
+ while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
+ if (!acx->thread)
+ continue;
+ js_TraceTraceMonitor(trc, &acx->thread->traceMonitor);
+ }
+#else
+ js_TraceTraceMonitor(trc, &rt->traceMonitor);
+#endif
+}
+
+static void
+ProcessSetSlotRequest(JSContext *cx, JSSetSlotRequest *ssr)
+{
+ JSObject *obj, *pobj;
+ uint32 slot;
+
+ obj = ssr->obj;
+ pobj = ssr->pobj;
+ slot = ssr->slot;
+
+ while (pobj) {
+ pobj = js_GetWrappedObject(cx, pobj);
+ if (pobj == obj) {
+ ssr->errnum = JSMSG_CYCLIC_VALUE;
+ return;
+ }
+ pobj = JSVAL_TO_OBJECT(STOBJ_GET_SLOT(pobj, slot));
+ }
+
+ pobj = ssr->pobj;
+
+ if (slot == JSSLOT_PROTO && OBJ_IS_NATIVE(obj)) {
+ JSScope *scope, *newscope;
+ JSObject *oldproto;
+
+ /* Check to see whether obj shares its prototype's scope. */
+ scope = OBJ_SCOPE(obj);
+ oldproto = STOBJ_GET_PROTO(obj);
+ if (oldproto && OBJ_SCOPE(oldproto) == scope) {
+ /* Either obj needs a new empty scope, or it should share pobj's. */
+ if (!pobj ||
+ !OBJ_IS_NATIVE(pobj) ||
+ OBJ_GET_CLASS(cx, pobj) != STOBJ_GET_CLASS(oldproto)) {
+ /*
+ * With no proto and no scope of its own, obj is truly empty.
+ *
+ * If pobj is not native, obj needs its own empty scope -- it
+ * should not continue to share oldproto's scope once oldproto
+ * is not on obj's prototype chain. That would put properties
+ * from oldproto's scope ahead of properties defined by pobj,
+ * in lookup order.
+ *
+ * If pobj's class differs from oldproto's, we may need a new
+ * scope to handle differences in private and reserved slots,
+ * so we suboptimally but safely make one.
+ */
+ if (!js_GetMutableScope(cx, obj)) {
+ ssr->errnum = JSMSG_OUT_OF_MEMORY;
+ return;
+ }
+ } else if (OBJ_SCOPE(pobj) != scope) {
+ newscope = (JSScope *) js_HoldObjectMap(cx, pobj->map);
+ obj->map = &newscope->map;
+ js_DropObjectMap(cx, &scope->map, obj);
+ JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope);
+ }
+ }
+
+ /*
+ * Regenerate property cache shape ids for all of the scopes along the
+ * old prototype chain, in case any property cache entries were filled
+ * by looking up starting from obj.
+ */
+ while (oldproto && OBJ_IS_NATIVE(oldproto)) {
+ scope = OBJ_SCOPE(oldproto);
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ oldproto = STOBJ_GET_PROTO(scope->object);
+ }
+ }
+
+ /* Finally, do the deed. */
+ STOBJ_SET_SLOT(obj, slot, OBJECT_TO_JSVAL(pobj));
+}
+
+static void
+DestroyScriptsToGC(JSContext *cx, JSScript **listp)
+{
+ JSScript *script;
+
+ while ((script = *listp) != NULL) {
+ *listp = script->u.nextToGC;
+ script->u.nextToGC = NULL;
+ js_DestroyScript(cx, script);
+ }
+}
+
+/*
+ * The gckind flag bit GC_LOCK_HELD indicates a call from js_NewGCThing with
+ * rt->gcLock already held, so the lock should be kept on return.
+ */
+void
+js_GC(JSContext *cx, JSGCInvocationKind gckind)
+{
+ JSRuntime *rt;
+ JSBool keepAtoms;
+ JSGCCallback callback;
+ uintN i, type;
+ JSTracer trc;
+ uint32 thingSize, indexLimit;
+ JSGCArenaInfo *a, **ap, *emptyArenas;
+ uint8 flags, *flagp;
+ JSGCThing *thing, *freeList;
+ JSGCArenaList *arenaList;
+ JSBool allClear;
+#ifdef JS_THREADSAFE
+ uint32 requestDebit;
+ JSContext *acx, *iter;
+#endif
+#ifdef JS_GCMETER
+ uint32 nlivearenas, nkilledarenas, nthings;
+#endif
+
+ JS_ASSERT_IF(gckind == GC_LAST_DITCH, !JS_ON_TRACE(cx));
+ rt = cx->runtime;
+#ifdef JS_THREADSAFE
+ /* Avoid deadlock. */
+ JS_ASSERT(!JS_IS_RUNTIME_LOCKED(rt));
+#endif
+
+ if (gckind & GC_KEEP_ATOMS) {
+ /*
+ * The set slot request and last ditch GC kinds preserve all atoms and
+ * weak roots.
+ */
+ keepAtoms = JS_TRUE;
+ } else {
+ /* Keep atoms when a suspended compile is running on another context. */
+ keepAtoms = (rt->gcKeepAtoms != 0);
+ JS_CLEAR_WEAK_ROOTS(&cx->weakRoots);
+ }
+
+ /*
+ * Don't collect garbage if the runtime isn't up, and cx is not the last
+ * context in the runtime. The last context must force a GC, and nothing
+ * should suppress that final collection or there may be shutdown leaks,
+ * or runtime bloat until the next context is created.
+ */
+ if (rt->state != JSRTS_UP && gckind != GC_LAST_CONTEXT)
+ return;
+
+ restart_at_beginning:
+ /*
+ * Let the API user decide to defer a GC if it wants to (unless this
+ * is the last context). Invoke the callback regardless. Sample the
+ * callback in case we are freely racing with a JS_SetGCCallback{,RT} on
+ * another thread.
+ */
+ if (gckind != GC_SET_SLOT_REQUEST && (callback = rt->gcCallback)) {
+ JSBool ok;
+
+ if (gckind & GC_LOCK_HELD)
+ JS_UNLOCK_GC(rt);
+ ok = callback(cx, JSGC_BEGIN);
+ if (gckind & GC_LOCK_HELD)
+ JS_LOCK_GC(rt);
+ if (!ok && gckind != GC_LAST_CONTEXT) {
+ /*
+ * It's possible that we've looped back to this code from the 'goto
+ * restart_at_beginning' below in the GC_SET_SLOT_REQUEST code and
+ * that rt->gcLevel is now 0. Don't return without notifying!
+ */
+ if (rt->gcLevel == 0 && (gckind & GC_LOCK_HELD))
+ JS_NOTIFY_GC_DONE(rt);
+ return;
+ }
+ }
+
+ /* Lock out other GC allocator and collector invocations. */
+ if (!(gckind & GC_LOCK_HELD))
+ JS_LOCK_GC(rt);
+
+ METER(rt->gcStats.poke++);
+ rt->gcPoke = JS_FALSE;
+
+#ifdef JS_THREADSAFE
+ JS_ASSERT(cx->thread->id == js_CurrentThreadId());
+
+ /* Bump gcLevel and return rather than nest on this thread. */
+ if (rt->gcThread == cx->thread) {
+ JS_ASSERT(rt->gcLevel > 0);
+ rt->gcLevel++;
+ METER_UPDATE_MAX(rt->gcStats.maxlevel, rt->gcLevel);
+ if (!(gckind & GC_LOCK_HELD))
+ JS_UNLOCK_GC(rt);
+ return;
+ }
+
+ /*
+ * If we're in one or more requests (possibly on more than one context)
+ * running on the current thread, indicate, temporarily, that all these
+ * requests are inactive. If cx->thread is NULL, then cx is not using
+ * the request model, and does not contribute to rt->requestCount.
+ */
+ requestDebit = 0;
+ if (cx->thread) {
+ JSCList *head, *link;
+
+ /*
+ * Check all contexts on cx->thread->contextList for active requests,
+ * counting each such context against requestDebit.
+ */
+ head = &cx->thread->contextList;
+ for (link = head->next; link != head; link = link->next) {
+ acx = CX_FROM_THREAD_LINKS(link);
+ JS_ASSERT(acx->thread == cx->thread);
+ if (acx->requestDepth)
+ requestDebit++;
+ }
+ } else {
+ /*
+ * We assert, but check anyway, in case someone is misusing the API.
+ * Avoiding the loop over all of rt's contexts is a win in the event
+ * that the GC runs only on request-less contexts with null threads,
+ * in a special thread such as might be used by the UI/DOM/Layout
+ * "mozilla" or "main" thread in Mozilla-the-browser.
+ */
+ JS_ASSERT(cx->requestDepth == 0);
+ if (cx->requestDepth)
+ requestDebit = 1;
+ }
+ if (requestDebit) {
+ JS_ASSERT(requestDebit <= rt->requestCount);
+ rt->requestCount -= requestDebit;
+ if (rt->requestCount == 0)
+ JS_NOTIFY_REQUEST_DONE(rt);
+ }
+
+ /* If another thread is already in GC, don't attempt GC; wait instead. */
+ if (rt->gcLevel > 0) {
+ /* Bump gcLevel to restart the current GC, so it finds new garbage. */
+ rt->gcLevel++;
+ METER_UPDATE_MAX(rt->gcStats.maxlevel, rt->gcLevel);
+
+ /* Wait for the other thread to finish, then resume our request. */
+ while (rt->gcLevel > 0)
+ JS_AWAIT_GC_DONE(rt);
+ if (requestDebit)
+ rt->requestCount += requestDebit;
+ if (!(gckind & GC_LOCK_HELD))
+ JS_UNLOCK_GC(rt);
+ return;
+ }
+
+ /* No other thread is in GC, so indicate that we're now in GC. */
+ rt->gcLevel = 1;
+ rt->gcThread = cx->thread;
+
+ /* Wait for all other requests to finish. */
+ while (rt->requestCount > 0)
+ JS_AWAIT_REQUEST_DONE(rt);
+
+#else /* !JS_THREADSAFE */
+
+ /* Bump gcLevel and return rather than nest; the outer gc will restart. */
+ rt->gcLevel++;
+ METER_UPDATE_MAX(rt->gcStats.maxlevel, rt->gcLevel);
+ if (rt->gcLevel > 1)
+ return;
+
+#endif /* !JS_THREADSAFE */
+
+ /*
+ * Set rt->gcRunning here within the GC lock, and after waiting for any
+ * active requests to end, so that new requests that try to JS_AddRoot,
+ * JS_RemoveRoot, or JS_RemoveRootRT block in JS_BeginRequest waiting for
+ * rt->gcLevel to drop to zero, while request-less calls to the *Root*
+ * APIs block in js_AddRoot or js_RemoveRoot (see above in this file),
+ * waiting for GC to finish.
+ */
+ rt->gcRunning = JS_TRUE;
+
+ if (gckind == GC_SET_SLOT_REQUEST) {
+ JSSetSlotRequest *ssr;
+
+ while ((ssr = rt->setSlotRequests) != NULL) {
+ rt->setSlotRequests = ssr->next;
+ JS_UNLOCK_GC(rt);
+ ssr->next = NULL;
+ ProcessSetSlotRequest(cx, ssr);
+ JS_LOCK_GC(rt);
+ }
+
+ /*
+ * We assume here that killing links to parent and prototype objects
+ * does not create garbage (such objects typically are long-lived and
+ * widely shared, e.g. global objects, Function.prototype, etc.). We
+ * collect garbage only if a racing thread attempted GC and is waiting
+ * for us to finish (gcLevel > 1) or if someone already poked us.
+ */
+ if (rt->gcLevel == 1 && !rt->gcPoke)
+ goto done_running;
+
+ rt->gcLevel = 0;
+ rt->gcPoke = JS_FALSE;
+ rt->gcRunning = JS_FALSE;
+#ifdef JS_THREADSAFE
+ rt->gcThread = NULL;
+ rt->requestCount += requestDebit;
+#endif
+ gckind = GC_LOCK_HELD;
+ goto restart_at_beginning;
+ }
+
+ JS_UNLOCK_GC(rt);
+
+#ifdef JS_TRACER
+ if (JS_ON_TRACE(cx))
+ goto out;
+#endif
+
+ /* Reset malloc counter. */
+ rt->gcMallocBytes = 0;
+
+#ifdef JS_DUMP_SCOPE_METERS
+ { extern void js_DumpScopeMeters(JSRuntime *rt);
+ js_DumpScopeMeters(rt);
+ }
+#endif
+
+ /* Clear property and JIT oracle caches (only for cx->thread if JS_THREADSAFE). */
+ js_FlushPropertyCache(cx);
+#ifdef JS_TRACER
+ js_FlushJITOracle(cx);
+#endif
+
+ /* Destroy eval'ed scripts. */
+ DestroyScriptsToGC(cx, &JS_SCRIPTS_TO_GC(cx));
+
+#ifdef JS_THREADSAFE
+ /*
+ * Clear thread-based caches. To avoid redundant clearing we unroll the
+ * current thread's step.
+ *
+ * In case a JSScript wrapped within an object was finalized, we null
+ * acx->thread->gsnCache.script and finish the cache's hashtable. Note
+ * that js_DestroyScript, called from script_finalize, will have already
+ * cleared cx->thread->gsnCache above during finalization, so we don't
+ * have to here.
+ */
+ iter = NULL;
+ while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
+ if (!acx->thread || acx->thread == cx->thread)
+ continue;
+ GSN_CACHE_CLEAR(&acx->thread->gsnCache);
+ js_FlushPropertyCache(acx);
+#ifdef JS_TRACER
+ js_FlushJITOracle(acx);
+#endif
+ DestroyScriptsToGC(cx, &acx->thread->scriptsToGC);
+ }
+#else
+ /* The thread-unsafe case just has to clear the runtime's GSN cache. */
+ GSN_CACHE_CLEAR(&rt->gsnCache);
+#endif
+
+ restart:
+ rt->gcNumber++;
+ JS_ASSERT(!rt->gcUntracedArenaStackTop);
+ JS_ASSERT(rt->gcTraceLaterCount == 0);
+
+ /* Reset the property cache's type id generator so we can compress ids. */
+ rt->shapeGen = 0;
+
+ /*
+ * Mark phase.
+ */
+ JS_TRACER_INIT(&trc, cx, NULL);
+ rt->gcMarkingTracer = &trc;
+ JS_ASSERT(IS_GC_MARKING_TRACER(&trc));
+
+ for (a = rt->gcDoubleArenaList.first; a; a = a->prev)
+ a->u.hasMarkedDoubles = JS_FALSE;
+
+ js_TraceRuntime(&trc, keepAtoms);
+ js_MarkScriptFilenames(rt, keepAtoms);
+
+ /*
+ * Mark children of things that caused too deep recursion during the above
+ * tracing.
+ */
+ TraceDelayedChildren(&trc);
+
+ JS_ASSERT(!cx->insideGCMarkCallback);
+ if (rt->gcCallback) {
+ cx->insideGCMarkCallback = JS_TRUE;
+ (void) rt->gcCallback(cx, JSGC_MARK_END);
+ JS_ASSERT(cx->insideGCMarkCallback);
+ cx->insideGCMarkCallback = JS_FALSE;
+ }
+ JS_ASSERT(rt->gcTraceLaterCount == 0);
+
+ rt->gcMarkingTracer = NULL;
+
+ /*
+ * Sweep phase.
+ *
+ * Finalize as we sweep, outside of rt->gcLock but with rt->gcRunning set
+ * so that any attempt to allocate a GC-thing from a finalizer will fail,
+ * rather than nest badly and leave the unmarked newborn to be swept.
+ *
+ * We first sweep atom state so we can use js_IsAboutToBeFinalized on
+ * JSString or jsdouble held in a hashtable to check if the hashtable
+ * entry can be freed. Note that even after the entry is freed, JSObject
+ * finalizers can continue to access the corresponding jsdouble* and
+ * JSString* assuming that they are unique. This works since the
+ * atomization API must not be called during GC.
+ */
+ js_SweepAtomState(cx);
+
+ /* Finalize iterator states before the objects they iterate over. */
+ CloseNativeIterators(cx);
+
+ /* Finalize watch points associated with unreachable objects. */
+ js_SweepWatchPoints(cx);
+
+#ifdef DEBUG
+ /* Save the pre-sweep count of scope-mapped properties. */
+ rt->liveScopePropsPreSweep = rt->liveScopeProps;
+#endif
+
+ /*
+ * Here we need to ensure that JSObject instances are finalized before GC-
+ * allocated JSString and jsdouble instances so object's finalizer can
+ * access them even if they will be freed. For that we simply finalize the
+ * list containing JSObject first since the static assert at the beginning
+ * of the file guarantees that JSString and jsdouble instances are
+ * allocated from a different list.
+ */
+ emptyArenas = NULL;
+ for (i = 0; i < GC_NUM_FREELISTS; i++) {
+ arenaList = &rt->gcArenaList[i == 0
+ ? GC_FREELIST_INDEX(sizeof(JSObject))
+ : i == GC_FREELIST_INDEX(sizeof(JSObject))
+ ? 0
+ : i];
+ ap = &arenaList->last;
+ if (!(a = *ap))
+ continue;
+
+ JS_ASSERT(arenaList->lastCount > 0);
+ arenaList->freeList = NULL;
+ freeList = NULL;
+ thingSize = arenaList->thingSize;
+ indexLimit = THINGS_PER_ARENA(thingSize);
+ flagp = THING_FLAGP(a, arenaList->lastCount - 1);
+ METER((nlivearenas = 0, nkilledarenas = 0, nthings = 0));
+ for (;;) {
+ JS_ASSERT(a->prevUntracedPage == 0);
+ JS_ASSERT(a->u.untracedThings == 0);
+ allClear = JS_TRUE;
+ do {
+ flags = *flagp;
+ if (flags & (GCF_MARK | GCF_LOCK)) {
+ *flagp &= ~GCF_MARK;
+ allClear = JS_FALSE;
+ METER(nthings++);
+ } else {
+ thing = FLAGP_TO_THING(flagp, thingSize);
+ if (!(flags & GCF_FINAL)) {
+ /*
+ * Call the finalizer with GCF_FINAL ORed into flags.
+ */
+ *flagp = (uint8)(flags | GCF_FINAL);
+ type = flags & GCF_TYPEMASK;
+ switch (type) {
+ case GCX_OBJECT:
+ js_FinalizeObject(cx, (JSObject *) thing);
+ break;
+ case GCX_DOUBLE:
+ /* Do nothing. */
+ break;
+#if JS_HAS_XML_SUPPORT
+ case GCX_XML:
+ js_FinalizeXML(cx, (JSXML *) thing);
+ break;
+#endif
+ default:
+ JS_ASSERT(type == GCX_STRING ||
+ type - GCX_EXTERNAL_STRING <
+ GCX_NTYPES - GCX_EXTERNAL_STRING);
+ js_FinalizeStringRT(rt, (JSString *) thing,
+ (intN) (type -
+ GCX_EXTERNAL_STRING),
+ cx);
+ break;
+ }
+#ifdef DEBUG
+ memset(thing, JS_FREE_PATTERN, thingSize);
+#endif
+ }
+ thing->flagp = flagp;
+ thing->next = freeList;
+ freeList = thing;
+ }
+ } while (++flagp != THING_FLAGS_END(a));
+
+ if (allClear) {
+ /*
+ * Forget just assembled free list head for the arena and
+ * add the arena itself to the destroy list.
+ */
+ freeList = arenaList->freeList;
+ if (a == arenaList->last)
+ arenaList->lastCount = (uint16) indexLimit;
+ *ap = a->prev;
+ a->prev = emptyArenas;
+ emptyArenas = a;
+ METER(nkilledarenas++);
+ } else {
+ arenaList->freeList = freeList;
+ ap = &a->prev;
+ METER(nlivearenas++);
+ }
+ if (!(a = *ap))
+ break;
+ flagp = THING_FLAGP(a, indexLimit - 1);
+ }
+
+ /*
+ * We use arenaList - &rt->gcArenaList[0], not i, as the stat index
+ * due to the enumeration reorder at the beginning of the loop.
+ */
+ METER(UpdateArenaStats(&rt->gcStats.arenaStats[arenaList -
+ &rt->gcArenaList[0]],
+ nlivearenas, nkilledarenas, nthings));
+ }
+
+#ifdef JS_THREADSAFE
+ /*
+ * Release all but two free list sets to avoid allocating a new set in
+ * js_NewGCThing.
+ */
+ TrimGCFreeListsPool(rt, 2);
+#endif
+
+ ap = &rt->gcDoubleArenaList.first;
+ METER((nlivearenas = 0, nkilledarenas = 0, nthings = 0));
+ while ((a = *ap) != NULL) {
+ if (!a->u.hasMarkedDoubles) {
+ /* No marked double values in the arena. */
+ *ap = a->prev;
+ a->prev = emptyArenas;
+ emptyArenas = a;
+ METER(nkilledarenas++);
+ } else {
+ ap = &a->prev;
+#ifdef JS_GCMETER
+ for (i = 0; i != DOUBLES_PER_ARENA; ++i) {
+ if (IsMarkedDouble(a, index))
+ METER(nthings++);
+ }
+ METER(nlivearenas++);
+#endif
+ }
+ }
+ METER(UpdateArenaStats(&rt->gcStats.doubleArenaStats,
+ nlivearenas, nkilledarenas, nthings));
+ rt->gcDoubleArenaList.nextDoubleFlags =
+ rt->gcDoubleArenaList.first
+ ? DOUBLE_ARENA_BITMAP(rt->gcDoubleArenaList.first)
+ : DOUBLE_BITMAP_SENTINEL;
+
+ /*
+ * Sweep the runtime's property tree after finalizing objects, in case any
+ * had watchpoints referencing tree nodes.
+ */
+ js_SweepScopeProperties(cx);
+
+ /*
+ * Sweep script filenames after sweeping functions in the generic loop
+ * above. In this way when a scripted function's finalizer destroys the
+ * script and calls rt->destroyScriptHook, the hook can still access the
+ * script's filename. See bug 323267.
+ */
+ js_SweepScriptFilenames(rt);
+
+ /*
+ * Destroy arenas after we finished the sweeping sofinalizers can safely
+ * use js_IsAboutToBeFinalized().
+ */
+ DestroyGCArenas(rt, emptyArenas);
+
+ if (rt->gcCallback)
+ (void) rt->gcCallback(cx, JSGC_FINALIZE_END);
+#ifdef DEBUG_srcnotesize
+ { extern void DumpSrcNoteSizeHist();
+ DumpSrcNoteSizeHist();
+ printf("GC HEAP SIZE %lu\n", (unsigned long)rt->gcBytes);
+ }
+#endif
+
+#ifdef JS_SCOPE_DEPTH_METER
+ { static FILE *fp;
+ if (!fp)
+ fp = fopen("/tmp/scopedepth.stats", "w");
+
+ if (fp) {
+ JS_DumpBasicStats(&rt->protoLookupDepthStats, "proto-lookup depth", fp);
+ JS_DumpBasicStats(&rt->scopeSearchDepthStats, "scope-search depth", fp);
+ JS_DumpBasicStats(&rt->hostenvScopeDepthStats, "hostenv scope depth", fp);
+ JS_DumpBasicStats(&rt->lexicalScopeDepthStats, "lexical scope depth", fp);
+
+ putc('\n', fp);
+ fflush(fp);
+ }
+ }
+#endif /* JS_SCOPE_DEPTH_METER */
+
+#ifdef JS_DUMP_LOOP_STATS
+ { static FILE *lsfp;
+ if (!lsfp)
+ lsfp = fopen("/tmp/loopstats", "w");
+ if (lsfp) {
+ JS_DumpBasicStats(&rt->loopStats, "loops", lsfp);
+ fflush(lsfp);
+ }
+ }
+#endif /* JS_DUMP_LOOP_STATS */
+
+#ifdef JS_TRACER
+out:
+#endif
+ JS_LOCK_GC(rt);
+
+ /*
+ * We want to restart GC if js_GC was called recursively or if any of the
+ * finalizers called js_RemoveRoot or js_UnlockGCThingRT.
+ */
+ if (rt->gcLevel > 1 || rt->gcPoke) {
+ rt->gcLevel = 1;
+ rt->gcPoke = JS_FALSE;
+ JS_UNLOCK_GC(rt);
+ goto restart;
+ }
+
+ if (rt->shapeGen >= SHAPE_OVERFLOW_BIT - 1) {
+ /*
+ * FIXME bug 440834: The shape id space has overflowed. Currently we
+ * cope badly with this. Every call to js_GenerateShape does GC, and
+ * we never re-enable the property cache.
+ */
+ js_DisablePropertyCache(cx);
+#ifdef JS_THREADSAFE
+ iter = NULL;
+ while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
+ if (!acx->thread || acx->thread == cx->thread)
+ continue;
+ js_DisablePropertyCache(acx);
+ }
+#endif
+ }
+
+ rt->gcLastBytes = rt->gcBytes;
+ done_running:
+ rt->gcLevel = 0;
+ rt->gcRunning = JS_FALSE;
+
+#ifdef JS_THREADSAFE
+ /* If we were invoked during a request, pay back the temporary debit. */
+ if (requestDebit)
+ rt->requestCount += requestDebit;
+ rt->gcThread = NULL;
+ JS_NOTIFY_GC_DONE(rt);
+
+ /*
+ * Unlock unless we have GC_LOCK_HELD which requires locked GC on return.
+ */
+ if (!(gckind & GC_LOCK_HELD))
+ JS_UNLOCK_GC(rt);
+#endif
+
+ /*
+ * Execute JSGC_END callback outside the lock. Again, sample the callback
+ * pointer in case it changes, since we are outside of the GC vs. requests
+ * interlock mechanism here.
+ */
+ if (gckind != GC_SET_SLOT_REQUEST && (callback = rt->gcCallback)) {
+ JSWeakRoots savedWeakRoots;
+ JSTempValueRooter tvr;
+
+ if (gckind & GC_KEEP_ATOMS) {
+ /*
+ * We allow JSGC_END implementation to force a full GC or allocate
+ * new GC things. Thus we must protect the weak roots from garbage
+ * collection and overwrites.
+ */
+ savedWeakRoots = cx->weakRoots;
+ JS_PUSH_TEMP_ROOT_WEAK_COPY(cx, &savedWeakRoots, &tvr);
+ JS_KEEP_ATOMS(rt);
+ JS_UNLOCK_GC(rt);
+ }
+
+ (void) callback(cx, JSGC_END);
+
+ if (gckind & GC_KEEP_ATOMS) {
+ JS_LOCK_GC(rt);
+ JS_UNKEEP_ATOMS(rt);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ } else if (gckind == GC_LAST_CONTEXT && rt->gcPoke) {
+ /*
+ * On shutdown iterate until JSGC_END callback stops creating
+ * garbage.
+ */
+ goto restart_at_beginning;
+ }
+ }
+}
+
+void
+js_UpdateMallocCounter(JSContext *cx, size_t nbytes)
+{
+ uint32 *pbytes, bytes;
+
+#ifdef JS_THREADSAFE
+ pbytes = &cx->thread->gcMallocBytes;
+#else
+ pbytes = &cx->runtime->gcMallocBytes;
+#endif
+ bytes = *pbytes;
+ *pbytes = ((uint32)-1 - bytes <= nbytes) ? (uint32)-1 : bytes + nbytes;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsgc.h b/tools/node_modules/expresso/deps/jscoverage/js/jsgc.h
new file mode 100644
index 0000000..a0634b2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsgc.h
@@ -0,0 +1,427 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsgc_h___
+#define jsgc_h___
+/*
+ * JS Garbage Collector.
+ */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsdhash.h"
+#include "jsbit.h"
+#include "jsutil.h"
+
+JS_BEGIN_EXTERN_C
+
+JS_STATIC_ASSERT(JSTRACE_STRING == 2);
+
+#define JSTRACE_XML 3
+
+/*
+ * One past the maximum trace kind.
+ */
+#define JSTRACE_LIMIT 4
+
+/*
+ * We use the trace kinds as the types for all GC things except external
+ * strings.
+ */
+#define GCX_OBJECT JSTRACE_OBJECT /* JSObject */
+#define GCX_DOUBLE JSTRACE_DOUBLE /* jsdouble */
+#define GCX_STRING JSTRACE_STRING /* JSString */
+#define GCX_XML JSTRACE_XML /* JSXML */
+#define GCX_EXTERNAL_STRING JSTRACE_LIMIT /* JSString with external
+ chars */
+/*
+ * The number of defined GC types.
+ */
+#define GCX_NTYPES (GCX_EXTERNAL_STRING + 8)
+
+/*
+ * The maximum limit for the number of GC types.
+ */
+#define GCX_LIMIT_LOG2 4 /* type index bits */
+#define GCX_LIMIT JS_BIT(GCX_LIMIT_LOG2)
+
+JS_STATIC_ASSERT(GCX_NTYPES <= GCX_LIMIT);
+
+/* GC flag definitions, must fit in 8 bits (type index goes in the low bits). */
+#define GCF_TYPEMASK JS_BITMASK(GCX_LIMIT_LOG2)
+#define GCF_MARK JS_BIT(GCX_LIMIT_LOG2)
+#define GCF_FINAL JS_BIT(GCX_LIMIT_LOG2 + 1)
+#define GCF_LOCKSHIFT (GCX_LIMIT_LOG2 + 2) /* lock bit shift */
+#define GCF_LOCK JS_BIT(GCF_LOCKSHIFT) /* lock request bit in API */
+
+/*
+ * Get the type of the external string or -1 if the string was not created
+ * with JS_NewExternalString.
+ */
+extern intN
+js_GetExternalStringGCType(JSString *str);
+
+extern JS_FRIEND_API(uint32)
+js_GetGCThingTraceKind(void *thing);
+
+/*
+ * The sole purpose of the function is to preserve public API compatibility
+ * in JS_GetStringBytes which takes only single JSString* argument.
+ */
+JSRuntime*
+js_GetGCStringRuntime(JSString *str);
+
+#if 1
+/*
+ * Since we're forcing a GC from JS_GC anyway, don't bother wasting cycles
+ * loading oldval. XXX remove implied force, fix jsinterp.c's "second arg
+ * ignored", etc.
+ */
+#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JS_TRUE)
+#else
+#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JSVAL_IS_GCTHING(oldval))
+#endif
+
+/*
+ * Write barrier macro monitoring property update from oldval to newval in
+ * scope->object.
+ *
+ * Since oldval is used only for the branded scope case, and the oldval actual
+ * argument expression is typically not used otherwise by callers, performance
+ * benefits if oldval is *not* evaluated into a callsite temporary variable,
+ * and instead passed to GC_WRITE_BARRIER for conditional evaluation (we rely
+ * on modern compilers to do a good CSE job). Yay, C macros.
+ */
+#define GC_WRITE_BARRIER(cx,scope,oldval,newval) \
+ JS_BEGIN_MACRO \
+ if (SCOPE_IS_BRANDED(scope) && \
+ (oldval) != (newval) && \
+ (VALUE_IS_FUNCTION(cx,oldval) || VALUE_IS_FUNCTION(cx,newval))) { \
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope); \
+ } \
+ GC_POKE(cx, oldval); \
+ JS_END_MACRO
+
+extern JSBool
+js_InitGC(JSRuntime *rt, uint32 maxbytes);
+
+extern void
+js_FinishGC(JSRuntime *rt);
+
+extern intN
+js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
+ JSStringFinalizeOp newop);
+
+extern JSBool
+js_AddRoot(JSContext *cx, void *rp, const char *name);
+
+extern JSBool
+js_AddRootRT(JSRuntime *rt, void *rp, const char *name);
+
+extern JSBool
+js_RemoveRoot(JSRuntime *rt, void *rp);
+
+#ifdef DEBUG
+extern void
+js_DumpNamedRoots(JSRuntime *rt,
+ void (*dump)(const char *name, void *rp, void *data),
+ void *data);
+#endif
+
+extern uint32
+js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data);
+
+/* Table of pointers with count valid members. */
+typedef struct JSPtrTable {
+ size_t count;
+ void **array;
+} JSPtrTable;
+
+extern JSBool
+js_RegisterCloseableIterator(JSContext *cx, JSObject *obj);
+
+/*
+ * The private JSGCThing struct, which describes a gcFreeList element.
+ */
+struct JSGCThing {
+ JSGCThing *next;
+ uint8 *flagp;
+};
+
+#define GC_NBYTES_MAX (10 * sizeof(JSGCThing))
+#define GC_NUM_FREELISTS (GC_NBYTES_MAX / sizeof(JSGCThing))
+#define GC_FREELIST_NBYTES(i) (((i) + 1) * sizeof(JSGCThing))
+#define GC_FREELIST_INDEX(n) (((n) / sizeof(JSGCThing)) - 1)
+
+/*
+ * Allocates a new GC thing of the given size. After a successful allocation
+ * the caller must fully initialize the thing before calling any function that
+ * can potentially trigger GC. This will ensure that GC tracing never sees junk
+ * values stored in the partially initialized thing.
+ */
+extern void *
+js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes);
+
+/*
+ * Allocate a new double jsval and store the result in *vp. vp must be a root.
+ * The function does not copy the result into any weak root.
+ */
+extern JSBool
+js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp);
+
+/*
+ * Return a pointer to a new GC-allocated and weakly-rooted jsdouble number,
+ * or null when the allocation fails.
+ */
+extern jsdouble *
+js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d);
+
+extern JSBool
+js_LockGCThingRT(JSRuntime *rt, void *thing);
+
+extern JSBool
+js_UnlockGCThingRT(JSRuntime *rt, void *thing);
+
+extern JSBool
+js_IsAboutToBeFinalized(JSContext *cx, void *thing);
+
+/*
+ * Macro to test if a traversal is the marking phase of GC to avoid exposing
+ * ScriptFilenameEntry to traversal implementations.
+ */
+#define IS_GC_MARKING_TRACER(trc) ((trc)->callback == NULL)
+
+#if JS_HAS_XML_SUPPORT
+# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) < JSTRACE_LIMIT)
+#else
+# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_STRING)
+#endif
+
+/*
+ * JS_IS_VALID_TRACE_KIND assumes that JSTRACE_STRING is the last non-xml
+ * trace kind when JS_HAS_XML_SUPPORT is false.
+ */
+JS_STATIC_ASSERT(JSTRACE_STRING + 1 == JSTRACE_XML);
+
+/*
+ * Trace jsval when JSVAL_IS_OBJECT(v) can be an arbitrary GC thing casted as
+ * JSVAL_OBJECT and js_GetGCThingTraceKind has to be used to find the real
+ * type behind v.
+ */
+extern void
+js_CallValueTracerIfGCThing(JSTracer *trc, jsval v);
+
+extern void
+js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp);
+
+extern void
+js_TraceRuntime(JSTracer *trc, JSBool allAtoms);
+
+extern JS_FRIEND_API(void)
+js_TraceContext(JSTracer *trc, JSContext *acx);
+
+/*
+ * Kinds of js_GC invocation.
+ */
+typedef enum JSGCInvocationKind {
+ /* Normal invocation. */
+ GC_NORMAL = 0,
+
+ /*
+ * Called from js_DestroyContext for last JSContext in a JSRuntime, when
+ * it is imperative that rt->gcPoke gets cleared early in js_GC.
+ */
+ GC_LAST_CONTEXT = 1,
+
+ /*
+ * Flag bit telling js_GC that the caller has already acquired rt->gcLock.
+ * Currently, this flag is set for the invocation kinds that also preserve
+ * atoms and weak roots, so we don't need another bit for GC_KEEP_ATOMS.
+ */
+ GC_LOCK_HELD = 0x10,
+ GC_KEEP_ATOMS = GC_LOCK_HELD,
+
+ /*
+ * Called from js_SetProtoOrParent with a request to set an object's proto
+ * or parent slot inserted on rt->setSlotRequests.
+ */
+ GC_SET_SLOT_REQUEST = GC_LOCK_HELD | 1,
+
+ /*
+ * Called from js_NewGCThing as a last-ditch GC attempt. See comments in
+ * jsgc.c just before js_GC's definition for details.
+ */
+ GC_LAST_DITCH = GC_LOCK_HELD | 2
+} JSGCInvocationKind;
+
+extern void
+js_GC(JSContext *cx, JSGCInvocationKind gckind);
+
+/* Call this after succesful malloc of memory for GC-related things. */
+extern void
+js_UpdateMallocCounter(JSContext *cx, size_t nbytes);
+
+typedef struct JSGCArenaInfo JSGCArenaInfo;
+typedef struct JSGCArenaList JSGCArenaList;
+typedef struct JSGCChunkInfo JSGCChunkInfo;
+
+struct JSGCArenaList {
+ JSGCArenaInfo *last; /* last allocated GC arena */
+ uint16 lastCount; /* number of allocated things in the last
+ arena */
+ uint16 thingSize; /* size of things to allocate on this list
+ */
+ JSGCThing *freeList; /* list of free GC things */
+};
+
+typedef union JSGCDoubleCell JSGCDoubleCell;
+
+union JSGCDoubleCell {
+ double number;
+ JSGCDoubleCell *link;
+};
+
+JS_STATIC_ASSERT(sizeof(JSGCDoubleCell) == sizeof(double));
+
+typedef struct JSGCDoubleArenaList {
+ JSGCArenaInfo *first; /* first allocated GC arena */
+ jsbitmap *nextDoubleFlags; /* bitmask with flags to check for free
+ things */
+} JSGCDoubleArenaList;
+
+typedef struct JSGCFreeListSet JSGCFreeListSet;
+
+struct JSGCFreeListSet {
+ JSGCThing *array[GC_NUM_FREELISTS];
+ JSGCFreeListSet *link;
+};
+
+extern const JSGCFreeListSet js_GCEmptyFreeListSet;
+
+extern void
+js_RevokeGCLocalFreeLists(JSContext *cx);
+
+struct JSWeakRoots {
+ /* Most recently created things by type, members of the GC's root set. */
+ void *newborn[GCX_NTYPES];
+
+ /* Atom root for the last-looked-up atom on this context. */
+ jsval lastAtom;
+
+ /* Root for the result of the most recent js_InternalInvoke call. */
+ jsval lastInternalResult;
+};
+
+JS_STATIC_ASSERT(JSVAL_NULL == 0);
+#define JS_CLEAR_WEAK_ROOTS(wr) (memset((wr), 0, sizeof(JSWeakRoots)))
+
+/*
+ * Increase runtime->gcBytes by sz bytes to account for an allocation outside
+ * the GC that will be freed only after the GC is run. The function may run
+ * the last ditch GC to ensure that gcBytes does not exceed gcMaxBytes. It will
+ * fail if the latter is not possible.
+ *
+ * This function requires that runtime->gcLock is held on entry. On successful
+ * return the lock is still held and on failure it will be released with
+ * the error reported.
+ */
+extern JSBool
+js_AddAsGCBytes(JSContext *cx, size_t sz);
+
+extern void
+js_RemoveAsGCBytes(JSRuntime* rt, size_t sz);
+
+#ifdef DEBUG_notme
+#define JS_GCMETER 1
+#endif
+
+#ifdef JS_GCMETER
+
+typedef struct JSGCArenaStats {
+ uint32 alloc; /* allocation attempts */
+ uint32 localalloc; /* allocations from local lists */
+ uint32 retry; /* allocation retries after running the GC */
+ uint32 fail; /* allocation failures */
+ uint32 nthings; /* live GC things */
+ uint32 maxthings; /* maximum of live GC cells */
+ double totalthings; /* live GC things the GC scanned so far */
+ uint32 narenas; /* number of arena in list before the GC */
+ uint32 newarenas; /* new arenas allocated before the last GC */
+ uint32 livearenas; /* number of live arenas after the last GC */
+ uint32 maxarenas; /* maximum of allocated arenas */
+ uint32 totalarenas; /* total number of arenas with live things that
+ GC scanned so far */
+} JSGCArenaStats;
+
+typedef struct JSGCStats {
+ uint32 finalfail; /* finalizer calls allocator failures */
+ uint32 lockborn; /* things born locked */
+ uint32 lock; /* valid lock calls */
+ uint32 unlock; /* valid unlock calls */
+ uint32 depth; /* mark tail recursion depth */
+ uint32 maxdepth; /* maximum mark tail recursion depth */
+ uint32 cdepth; /* mark recursion depth of C functions */
+ uint32 maxcdepth; /* maximum mark recursion depth of C functions */
+ uint32 untraced; /* number of times tracing of GC thing's children were
+ delayed due to a low C stack */
+#ifdef DEBUG
+ uint32 maxuntraced;/* maximum number of things with children to trace
+ later */
+#endif
+ uint32 maxlevel; /* maximum GC nesting (indirect recursion) level */
+ uint32 poke; /* number of potentially useful GC calls */
+ uint32 afree; /* thing arenas freed so far */
+ uint32 stackseg; /* total extraordinary stack segments scanned */
+ uint32 segslots; /* total stack segment jsval slots scanned */
+ uint32 nclose; /* number of objects with close hooks */
+ uint32 maxnclose; /* max number of objects with close hooks */
+ uint32 closelater; /* number of close hooks scheduled to run */
+ uint32 maxcloselater; /* max number of close hooks scheduled to run */
+
+ JSGCArenaStats arenaStats[GC_NUM_FREELISTS];
+ JSGCArenaStats doubleArenaStats;
+} JSGCStats;
+
+extern JS_FRIEND_API(void)
+js_DumpGCStats(JSRuntime *rt, FILE *fp);
+
+#endif /* JS_GCMETER */
+
+JS_END_EXTERN_C
+
+#endif /* jsgc_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jshash.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jshash.cpp
new file mode 100644
index 0000000..5fe5f78
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jshash.cpp
@@ -0,0 +1,476 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * PR hash table package.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jshash.h" /* Added by JSIFY */
+
+/* Compute the number of buckets in ht */
+#define NBUCKETS(ht) JS_BIT(JS_HASH_BITS - (ht)->shift)
+
+/* The smallest table has 16 buckets */
+#define MINBUCKETSLOG2 4
+#define MINBUCKETS JS_BIT(MINBUCKETSLOG2)
+
+/* Compute the maximum entries given n buckets that we will tolerate, ~90% */
+#define OVERLOADED(n) ((n) - ((n) >> 3))
+
+/* Compute the number of entries below which we shrink the table by half */
+#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
+
+/*
+** Stubs for default hash allocator ops.
+*/
+static void *
+DefaultAllocTable(void *pool, size_t size)
+{
+ return malloc(size);
+}
+
+static void
+DefaultFreeTable(void *pool, void *item)
+{
+ free(item);
+}
+
+static JSHashEntry *
+DefaultAllocEntry(void *pool, const void *key)
+{
+ return (JSHashEntry*) malloc(sizeof(JSHashEntry));
+}
+
+static void
+DefaultFreeEntry(void *pool, JSHashEntry *he, uintN flag)
+{
+ if (flag == HT_FREE_ENTRY)
+ free(he);
+}
+
+static JSHashAllocOps defaultHashAllocOps = {
+ DefaultAllocTable, DefaultFreeTable,
+ DefaultAllocEntry, DefaultFreeEntry
+};
+
+JS_PUBLIC_API(JSHashTable *)
+JS_NewHashTable(uint32 n, JSHashFunction keyHash,
+ JSHashComparator keyCompare, JSHashComparator valueCompare,
+ JSHashAllocOps *allocOps, void *allocPriv)
+{
+ JSHashTable *ht;
+ size_t nb;
+
+ if (n <= MINBUCKETS) {
+ n = MINBUCKETSLOG2;
+ } else {
+ n = JS_CeilingLog2(n);
+ if ((int32)n < 0)
+ return NULL;
+ }
+
+ if (!allocOps) allocOps = &defaultHashAllocOps;
+
+ ht = (JSHashTable*) allocOps->allocTable(allocPriv, sizeof *ht);
+ if (!ht)
+ return NULL;
+ memset(ht, 0, sizeof *ht);
+ ht->shift = JS_HASH_BITS - n;
+ n = JS_BIT(n);
+ nb = n * sizeof(JSHashEntry *);
+ ht->buckets = (JSHashEntry**) allocOps->allocTable(allocPriv, nb);
+ if (!ht->buckets) {
+ allocOps->freeTable(allocPriv, ht);
+ return NULL;
+ }
+ memset(ht->buckets, 0, nb);
+
+ ht->keyHash = keyHash;
+ ht->keyCompare = keyCompare;
+ ht->valueCompare = valueCompare;
+ ht->allocOps = allocOps;
+ ht->allocPriv = allocPriv;
+ return ht;
+}
+
+JS_PUBLIC_API(void)
+JS_HashTableDestroy(JSHashTable *ht)
+{
+ uint32 i, n;
+ JSHashEntry *he, **hep;
+ JSHashAllocOps *allocOps = ht->allocOps;
+ void *allocPriv = ht->allocPriv;
+
+ n = NBUCKETS(ht);
+ for (i = 0; i < n; i++) {
+ hep = &ht->buckets[i];
+ while ((he = *hep) != NULL) {
+ *hep = he->next;
+ allocOps->freeEntry(allocPriv, he, HT_FREE_ENTRY);
+ }
+ }
+#ifdef DEBUG
+ memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
+#endif
+ allocOps->freeTable(allocPriv, ht->buckets);
+#ifdef DEBUG
+ memset(ht, 0xDB, sizeof *ht);
+#endif
+ allocOps->freeTable(allocPriv, ht);
+}
+
+/*
+ * Multiplicative hash, from Knuth 6.4.
+ */
+#define BUCKET_HEAD(ht, keyHash) \
+ (&(ht)->buckets[((keyHash) * JS_GOLDEN_RATIO) >> (ht)->shift])
+
+JS_PUBLIC_API(JSHashEntry **)
+JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key)
+{
+ JSHashEntry *he, **hep, **hep0;
+
+#ifdef JS_HASHMETER
+ ht->nlookups++;
+#endif
+ hep = hep0 = BUCKET_HEAD(ht, keyHash);
+ while ((he = *hep) != NULL) {
+ if (he->keyHash == keyHash && ht->keyCompare(key, he->key)) {
+ /* Move to front of chain if not already there */
+ if (hep != hep0) {
+ *hep = he->next;
+ he->next = *hep0;
+ *hep0 = he;
+ }
+ return hep0;
+ }
+ hep = &he->next;
+#ifdef JS_HASHMETER
+ ht->nsteps++;
+#endif
+ }
+ return hep;
+}
+
+static JSBool
+Resize(JSHashTable *ht, uint32 newshift)
+{
+ size_t nb, nentries, i;
+ JSHashEntry **oldbuckets, *he, *next, **hep;
+#ifdef DEBUG
+ size_t nold = NBUCKETS(ht);
+#endif
+
+ JS_ASSERT(newshift < JS_HASH_BITS);
+
+ nb = (size_t)1 << (JS_HASH_BITS - newshift);
+
+ /* Integer overflow protection. */
+ if (nb > (size_t)-1 / sizeof(JSHashEntry*))
+ return JS_FALSE;
+ nb *= sizeof(JSHashEntry*);
+
+ oldbuckets = ht->buckets;
+ ht->buckets = (JSHashEntry**)ht->allocOps->allocTable(ht->allocPriv, nb);
+ if (!ht->buckets) {
+ ht->buckets = oldbuckets;
+ return JS_FALSE;
+ }
+ memset(ht->buckets, 0, nb);
+
+ ht->shift = newshift;
+ nentries = ht->nentries;
+
+ for (i = 0; nentries != 0; i++) {
+ for (he = oldbuckets[i]; he; he = next) {
+ JS_ASSERT(nentries != 0);
+ --nentries;
+ next = he->next;
+ hep = BUCKET_HEAD(ht, he->keyHash);
+
+ /*
+ * Since he comes from the old table, it must be unique and we
+ * simply add it to the head of bucket chain without chain lookup.
+ */
+ he->next = *hep;
+ *hep = he;
+ }
+ }
+#ifdef DEBUG
+ memset(oldbuckets, 0xDB, nold * sizeof oldbuckets[0]);
+#endif
+ ht->allocOps->freeTable(ht->allocPriv, oldbuckets);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSHashEntry *)
+JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **hep,
+ JSHashNumber keyHash, const void *key, void *value)
+{
+ uint32 n;
+ JSHashEntry *he;
+
+ /* Grow the table if it is overloaded */
+ n = NBUCKETS(ht);
+ if (ht->nentries >= OVERLOADED(n)) {
+ if (!Resize(ht, ht->shift - 1))
+ return NULL;
+#ifdef JS_HASHMETER
+ ht->ngrows++;
+#endif
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
+ }
+
+ /* Make a new key value entry */
+ he = ht->allocOps->allocEntry(ht->allocPriv, key);
+ if (!he)
+ return NULL;
+ he->keyHash = keyHash;
+ he->key = key;
+ he->value = value;
+ he->next = *hep;
+ *hep = he;
+ ht->nentries++;
+ return he;
+}
+
+JS_PUBLIC_API(JSHashEntry *)
+JS_HashTableAdd(JSHashTable *ht, const void *key, void *value)
+{
+ JSHashNumber keyHash;
+ JSHashEntry *he, **hep;
+
+ keyHash = ht->keyHash(key);
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) != NULL) {
+ /* Hit; see if values match */
+ if (ht->valueCompare(he->value, value)) {
+ /* key,value pair is already present in table */
+ return he;
+ }
+ if (he->value)
+ ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_VALUE);
+ he->value = value;
+ return he;
+ }
+ return JS_HashTableRawAdd(ht, hep, keyHash, key, value);
+}
+
+JS_PUBLIC_API(void)
+JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he)
+{
+ uint32 n;
+
+ *hep = he->next;
+ ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_ENTRY);
+
+ /* Shrink table if it's underloaded */
+ n = NBUCKETS(ht);
+ if (--ht->nentries < UNDERLOADED(n)) {
+ Resize(ht, ht->shift + 1);
+#ifdef JS_HASHMETER
+ ht->nshrinks++;
+#endif
+ }
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HashTableRemove(JSHashTable *ht, const void *key)
+{
+ JSHashNumber keyHash;
+ JSHashEntry *he, **hep;
+
+ keyHash = ht->keyHash(key);
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) == NULL)
+ return JS_FALSE;
+
+ /* Hit; remove element */
+ JS_HashTableRawRemove(ht, hep, he);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(void *)
+JS_HashTableLookup(JSHashTable *ht, const void *key)
+{
+ JSHashNumber keyHash;
+ JSHashEntry *he, **hep;
+
+ keyHash = ht->keyHash(key);
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) != NULL) {
+ return he->value;
+ }
+ return NULL;
+}
+
+/*
+** Iterate over the entries in the hash table calling func for each
+** entry found. Stop if "f" says to (return value & JS_ENUMERATE_STOP).
+** Return a count of the number of elements scanned.
+*/
+JS_PUBLIC_API(int)
+JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg)
+{
+ JSHashEntry *he, **hep, **bucket;
+ uint32 nlimit, n, nbuckets, newlog2;
+ int rv;
+
+ nlimit = ht->nentries;
+ n = 0;
+ for (bucket = ht->buckets; n != nlimit; ++bucket) {
+ hep = bucket;
+ while ((he = *hep) != NULL) {
+ JS_ASSERT(n < nlimit);
+ rv = f(he, n, arg);
+ n++;
+ if (rv & HT_ENUMERATE_REMOVE) {
+ *hep = he->next;
+ ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_ENTRY);
+ --ht->nentries;
+ } else {
+ hep = &he->next;
+ }
+ if (rv & HT_ENUMERATE_STOP) {
+ goto out;
+ }
+ }
+ }
+
+out:
+ /* Shrink table if removal of entries made it underloaded */
+ if (ht->nentries != nlimit) {
+ JS_ASSERT(ht->nentries < nlimit);
+ nbuckets = NBUCKETS(ht);
+ if (MINBUCKETS < nbuckets && ht->nentries < UNDERLOADED(nbuckets)) {
+ newlog2 = JS_CeilingLog2(ht->nentries);
+ if (newlog2 < MINBUCKETSLOG2)
+ newlog2 = MINBUCKETSLOG2;
+
+ /* Check that we really shrink the table. */
+ JS_ASSERT(JS_HASH_BITS - ht->shift > newlog2);
+ Resize(ht, JS_HASH_BITS - newlog2);
+ }
+ }
+ return (int)n;
+}
+
+#ifdef JS_HASHMETER
+#include <stdio.h>
+
+JS_PUBLIC_API(void)
+JS_HashTableDumpMeter(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
+{
+ double sqsum, mean, sigma;
+ uint32 nchains, nbuckets;
+ uint32 i, n, maxChain, maxChainLen;
+ JSHashEntry *he;
+
+ sqsum = 0;
+ nchains = 0;
+ maxChain = maxChainLen = 0;
+ nbuckets = NBUCKETS(ht);
+ for (i = 0; i < nbuckets; i++) {
+ he = ht->buckets[i];
+ if (!he)
+ continue;
+ nchains++;
+ for (n = 0; he; he = he->next)
+ n++;
+ sqsum += n * n;
+ if (n > maxChainLen) {
+ maxChainLen = n;
+ maxChain = i;
+ }
+ }
+
+ mean = JS_MeanAndStdDev(nchains, ht->nentries, sqsum, &sigma);
+
+ fprintf(fp, "\nHash table statistics:\n");
+ fprintf(fp, " number of lookups: %u\n", ht->nlookups);
+ fprintf(fp, " number of entries: %u\n", ht->nentries);
+ fprintf(fp, " number of grows: %u\n", ht->ngrows);
+ fprintf(fp, " number of shrinks: %u\n", ht->nshrinks);
+ fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps
+ / ht->nlookups);
+ fprintf(fp, "mean hash chain length: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sigma);
+ fprintf(fp, " max hash chain length: %u\n", maxChainLen);
+ fprintf(fp, " max hash chain: [%u]\n", maxChain);
+
+ for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
+ if (dump(he, i, fp) != HT_ENUMERATE_NEXT)
+ break;
+}
+#endif /* JS_HASHMETER */
+
+JS_PUBLIC_API(int)
+JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
+{
+ int count;
+
+ count = JS_HashTableEnumerateEntries(ht, dump, fp);
+#ifdef JS_HASHMETER
+ JS_HashTableDumpMeter(ht, dump, fp);
+#endif
+ return count;
+}
+
+JS_PUBLIC_API(JSHashNumber)
+JS_HashString(const void *key)
+{
+ JSHashNumber h;
+ const unsigned char *s;
+
+ h = 0;
+ for (s = (const unsigned char *)key; *s; s++)
+ h = JS_ROTATE_LEFT32(h, 4) ^ *s;
+ return h;
+}
+
+JS_PUBLIC_API(int)
+JS_CompareValues(const void *v1, const void *v2)
+{
+ return v1 == v2;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jshash.h b/tools/node_modules/expresso/deps/jscoverage/js/jshash.h
new file mode 100644
index 0000000..defc193
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jshash.h
@@ -0,0 +1,151 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jshash_h___
+#define jshash_h___
+/*
+ * API to portable hash table code.
+ */
+#include <stddef.h>
+#include <stdio.h>
+#include "jstypes.h"
+#include "jscompat.h"
+
+JS_BEGIN_EXTERN_C
+
+typedef uint32 JSHashNumber;
+typedef struct JSHashEntry JSHashEntry;
+typedef struct JSHashTable JSHashTable;
+
+#define JS_HASH_BITS 32
+#define JS_GOLDEN_RATIO 0x9E3779B9U
+
+typedef JSHashNumber (* JSHashFunction)(const void *key);
+typedef intN (* JSHashComparator)(const void *v1, const void *v2);
+typedef intN (* JSHashEnumerator)(JSHashEntry *he, intN i, void *arg);
+
+/* Flag bits in JSHashEnumerator's return value */
+#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
+#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */
+#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */
+
+typedef struct JSHashAllocOps {
+ void * (*allocTable)(void *pool, size_t size);
+ void (*freeTable)(void *pool, void *item);
+ JSHashEntry * (*allocEntry)(void *pool, const void *key);
+ void (*freeEntry)(void *pool, JSHashEntry *he, uintN flag);
+} JSHashAllocOps;
+
+#define HT_FREE_VALUE 0 /* just free the entry's value */
+#define HT_FREE_ENTRY 1 /* free value and entire entry */
+
+struct JSHashEntry {
+ JSHashEntry *next; /* hash chain linkage */
+ JSHashNumber keyHash; /* key hash function result */
+ const void *key; /* ptr to opaque key */
+ void *value; /* ptr to opaque value */
+};
+
+struct JSHashTable {
+ JSHashEntry **buckets; /* vector of hash buckets */
+ uint32 nentries; /* number of entries in table */
+ uint32 shift; /* multiplicative hash shift */
+ JSHashFunction keyHash; /* key hash function */
+ JSHashComparator keyCompare; /* key comparison function */
+ JSHashComparator valueCompare; /* value comparison function */
+ JSHashAllocOps *allocOps; /* allocation operations */
+ void *allocPriv; /* allocation private data */
+#ifdef JS_HASHMETER
+ uint32 nlookups; /* total number of lookups */
+ uint32 nsteps; /* number of hash chains traversed */
+ uint32 ngrows; /* number of table expansions */
+ uint32 nshrinks; /* number of table contractions */
+#endif
+};
+
+/*
+ * Create a new hash table.
+ * If allocOps is null, use default allocator ops built on top of malloc().
+ */
+extern JS_PUBLIC_API(JSHashTable *)
+JS_NewHashTable(uint32 n, JSHashFunction keyHash,
+ JSHashComparator keyCompare, JSHashComparator valueCompare,
+ JSHashAllocOps *allocOps, void *allocPriv);
+
+extern JS_PUBLIC_API(void)
+JS_HashTableDestroy(JSHashTable *ht);
+
+/* Low level access methods */
+extern JS_PUBLIC_API(JSHashEntry **)
+JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key);
+
+extern JS_PUBLIC_API(JSHashEntry *)
+JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **hep, JSHashNumber keyHash,
+ const void *key, void *value);
+
+extern JS_PUBLIC_API(void)
+JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he);
+
+/* Higher level access methods */
+extern JS_PUBLIC_API(JSHashEntry *)
+JS_HashTableAdd(JSHashTable *ht, const void *key, void *value);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HashTableRemove(JSHashTable *ht, const void *key);
+
+extern JS_PUBLIC_API(intN)
+JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg);
+
+extern JS_PUBLIC_API(void *)
+JS_HashTableLookup(JSHashTable *ht, const void *key);
+
+extern JS_PUBLIC_API(intN)
+JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp);
+
+/* General-purpose C string hash function. */
+extern JS_PUBLIC_API(JSHashNumber)
+JS_HashString(const void *key);
+
+/* Stub function just returns v1 == v2 */
+extern JS_PUBLIC_API(intN)
+JS_CompareValues(const void *v1, const void *v2);
+
+JS_END_EXTERN_C
+
+#endif /* jshash_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsify.pl b/tools/node_modules/expresso/deps/jscoverage/js/jsify.pl
new file mode 100644
index 0000000..0ce2186
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsify.pl
@@ -0,0 +1,483 @@
+#!/usr/local/bin/perl
+
+# This script modifies C code to use the hijacked NSPR routines that are
+# now baked into the JavaScript engine rather than using the NSPR
+# routines that they were based on, i.e. types like PRArenaPool are changed
+# to JSArenaPool.
+#
+# This script was used in 9/98 to facilitate the incorporation of some NSPR
+# code into the JS engine so as to minimize dependency on NSPR.
+#
+
+# Command-line: jsify.pl [options] [filename]*
+#
+# Options:
+# -r Reverse direction of transformation, i.e. JS ==> NSPR2
+# -outdir Directory in which to place output files
+
+
+# NSPR2 symbols that will be modified to JS symbols, e.g.
+# PRArena <==> JSArena
+
+@NSPR_symbols = (
+"PRArena",
+"PRArenaPool",
+"PRArenaStats",
+"PR_ARENAMETER",
+"PR_ARENA_",
+"PR_ARENA_ALIGN",
+"PR_ARENA_ALLOCATE",
+"PR_ARENA_CONST_ALIGN_MASK",
+"PR_ARENA_DEFAULT_ALIGN",
+"PR_ARENA_DESTROY",
+"PR_ARENA_GROW",
+"PR_ARENA_MARK",
+"PR_ARENA_RELEASE",
+
+"PR_smprintf",
+"PR_smprintf_free",
+"PR_snprintf",
+"PR_sprintf_append",
+"PR_sscanf",
+"PR_sxprintf",
+"PR_vsmprintf",
+"PR_vsnprintf",
+"PR_vsprintf_append",
+"PR_vsxprintf",
+
+"PRCList",
+"PRCListStr",
+"PRCLists",
+
+"PRDestroyEventProc",
+"PREvent",
+"PREventFunProc",
+"PREventQueue",
+"PRHandleEventProc",
+"PR_PostEvent",
+"PR_PostSynchronousEvent",
+"PR_ProcessPendingEvents",
+"PR_CreateEventQueue",
+"PR_DequeueEvent",
+"PR_DestroyEvent",
+"PR_DestroyEventQueue",
+"PR_EventAvailable",
+"PR_EventLoop",
+"PR_GetEvent",
+"PR_GetEventOwner",
+"PR_GetEventQueueMonitor",
+"PR_GetEventQueueSelectFD",
+"PR_GetMainEventQueue",
+"PR_HandleEvent",
+"PR_InitEvent",
+"PR_ENTER_EVENT_QUEUE_MONITOR",
+"PR_EXIT_EVENT_QUEUE_MONITOR",
+"PR_MapEvents",
+"PR_RevokeEvents",
+
+"PR_cnvtf",
+"PR_dtoa",
+"PR_strtod",
+
+"PRFileDesc",
+
+"PR_HASH_BITS",
+"PR_GOLDEN_RATIO",
+"PRHashAllocOps",
+"PRHashComparator",
+"PRHashEntry",
+"PRHashEnumerator",
+"PRHashFunction",
+"PRHashNumber",
+"PRHashTable",
+"PR_HashString",
+"PR_HashTableAdd",
+"PR_HashTableDestroy",
+"PR_HashTableDump",
+"PR_HashTableEnumerateEntries",
+"PR_HashTableLookup",
+"PR_HashTableRawAdd",
+"PR_HashTableRawLookup",
+"PR_HashTableRawRemove",
+"PR_HashTableRemove",
+
+"PRBool",
+"PRFloat64",
+"PRInt16",
+"PRInt32",
+"PRInt64",
+"PRInt8",
+"PRIntn",
+"PRUint16",
+"PRUint32",
+"PRUint64",
+"PRUint8",
+"PRUintn",
+"PRPtrDiff",
+"PRPtrdiff",
+"PRUptrdiff",
+"PRUword",
+"PRWord",
+"PRPackedBool",
+"PRSize",
+"PRStatus",
+"pruword",
+"prword",
+"prword_t",
+
+"PR_ALIGN_OF_DOUBLE",
+"PR_ALIGN_OF_FLOAT",
+"PR_ALIGN_OF_INT",
+"PR_ALIGN_OF_INT64",
+"PR_ALIGN_OF_LONG",
+"PR_ALIGN_OF_POINTER",
+"PR_ALIGN_OF_SHORT",
+"PR_ALIGN_OF_WORD",
+"PR_BITS_PER_BYTE",
+"PR_BITS_PER_BYTE_LOG2",
+"PR_BITS_PER_DOUBLE",
+"PR_BITS_PER_DOUBLE_LOG2",
+"PR_BITS_PER_FLOAT",
+"PR_BITS_PER_FLOAT_LOG2",
+"PR_BITS_PER_INT",
+"PR_BITS_PER_INT64",
+"PR_BITS_PER_INT64_LOG2",
+"PR_BITS_PER_INT_LOG2",
+"PR_BITS_PER_LONG",
+"PR_BITS_PER_LONG_LOG2",
+"PR_BITS_PER_SHORT",
+"PR_BITS_PER_SHORT_LOG2",
+"PR_BITS_PER_WORD",
+"PR_BITS_PER_WORD_LOG2",
+"PR_BYTES_PER_BYTE",
+"PR_BYTES_PER_DOUBLE",
+"PR_BYTES_PER_DWORD",
+"PR_BYTES_PER_DWORD_LOG2",
+"PR_BYTES_PER_FLOAT",
+"PR_BYTES_PER_INT",
+"PR_BYTES_PER_INT64",
+"PR_BYTES_PER_LONG",
+"PR_BYTES_PER_SHORT",
+"PR_BYTES_PER_WORD",
+"PR_BYTES_PER_WORD_LOG2",
+
+"PRSegment",
+"PRSegmentAccess",
+"PRStuffFunc",
+"PRThread",
+
+"PR_APPEND_LINK",
+
+"PR_ASSERT",
+
+"PR_ATOMIC_DWORD_LOAD",
+"PR_ATOMIC_DWORD_STORE",
+
+"PR_Abort",
+
+"PR_ArenaAllocate",
+"PR_ArenaCountAllocation",
+"PR_ArenaCountGrowth",
+"PR_ArenaCountInplaceGrowth",
+"PR_ArenaCountRelease",
+"PR_ArenaCountRetract",
+"PR_ArenaFinish",
+"PR_ArenaGrow",
+"PR_ArenaRelease",
+"PR_CompactArenaPool",
+"PR_DumpArenaStats",
+"PR_FinishArenaPool",
+"PR_FreeArenaPool",
+"PR_InitArenaPool",
+
+"PR_Assert",
+
+"PR_AttachThread",
+
+"PR_BEGIN_EXTERN_C",
+"PR_BEGIN_MACRO",
+
+"PR_BIT",
+"PR_BITMASK",
+
+"PR_BUFFER_OVERFLOW_ERROR",
+
+"PR_CALLBACK",
+"PR_CALLBACK_DECL",
+"PR_CALLOC",
+"PR_CEILING_LOG2",
+"PR_CLEAR_ARENA",
+"PR_CLEAR_BIT",
+"PR_CLEAR_UNUSED",
+"PR_CLIST_IS_EMPTY",
+"PR_COUNT_ARENA",
+"PR_CURRENT_THREAD",
+
+"PR_GetSegmentAccess",
+"PR_GetSegmentSize",
+"PR_GetSegmentVaddr",
+"PR_GrowSegment",
+"PR_DestroySegment",
+"PR_MapSegment",
+"PR_NewSegment",
+"PR_Segment",
+"PR_Seg",
+"PR_SEGMENT_NONE",
+"PR_SEGMENT_RDONLY",
+"PR_SEGMENT_RDWR",
+
+"PR_Calloc",
+"PR_CeilingLog2",
+"PR_CompareStrings",
+"PR_CompareValues",
+"PR_DELETE",
+"PR_END_EXTERN_C",
+"PR_END_MACRO",
+"PR_ENUMERATE_STOP",
+"PR_FAILURE",
+"PR_FALSE",
+"PR_FLOOR_LOG2",
+"PR_FREEIF",
+"PR_FREE_PATTERN",
+"PR_FloorLog2",
+"PR_FormatTime",
+"PR_Free",
+
+"PR_GetEnv",
+"PR_GetError",
+"PR_INIT_ARENA_POOL",
+"PR_INIT_CLIST",
+"PR_INIT_STATIC_CLIST",
+"PR_INLINE",
+"PR_INSERT_AFTER",
+"PR_INSERT_BEFORE",
+"PR_INSERT_LINK",
+"PR_INT32",
+"PR_INTERVAL_NO_TIMEOUT",
+"PR_INTERVAL_NO_WAIT",
+"PR_Init",
+"PR_LIST_HEAD",
+"PR_LIST_TAIL",
+"PR_LOG",
+"PR_LOGGING",
+"PR_LOG_ALWAYS",
+"PR_LOG_BEGIN",
+"PR_LOG_DEBUG",
+"PR_LOG_DEFINE",
+"PR_LOG_END",
+"PR_LOG_ERROR",
+"PR_LOG_MAX",
+"PR_LOG_MIN",
+"PR_LOG_NONE",
+"PR_LOG_NOTICE",
+"PR_LOG_TEST",
+"PR_LOG_WARN",
+"PR_LOG_WARNING",
+"PR_LogFlush",
+"PR_LogPrint",
+"PR_MALLOC",
+"PR_MAX",
+"PR_MD_calloc",
+"PR_MD_free",
+"PR_MD_malloc",
+"PR_MD_realloc",
+"PR_MIN",
+"PR_Malloc",
+"PR_NEW",
+"PR_NEWZAP",
+"PR_NEXT_LINK",
+"PR_NOT_REACHED",
+"PR_NewCondVar",
+"PR_NewHashTable",
+"PR_NewLogModule",
+"PR_PREV_LINK",
+"PR_PUBLIC_API",
+"PR_PUBLIC_DATA",
+"PR_RANGE_ERROR",
+"PR_REALLOC",
+"PR_REMOVE_AND_INIT_LINK",
+"PR_REMOVE_LINK",
+"PR_ROUNDUP",
+"PR_Realloc",
+
+"PR_SET_BIT",
+"PR_STATIC_CALLBACK",
+"PR_SUCCESS",
+"PR_SetError",
+"PR_SetLogBuffering",
+"PR_SetLogFile",
+
+"PR_TEST_BIT",
+"PR_TRUE",
+"PR_UINT32",
+"PR_UPTRDIFF",
+
+"prarena_h___",
+"prbit_h___",
+"prclist_h___",
+"prdtoa_h___",
+"prlog_h___",
+"prlong_h___",
+"prmacos_h___",
+"prmem_h___",
+"prprf_h___",
+"prtypes_h___",
+
+"prarena",
+"prbit",
+"prbitmap_t",
+"prclist",
+"prcpucfg",
+"prdtoa",
+"prhash",
+"plhash",
+"prlong",
+"prmacos",
+"prmem",
+"prosdep",
+"protypes",
+"prprf",
+"prtypes"
+);
+
+while ($ARGV[0] =~ /^-/) {
+ if ($ARGV[0] eq "-r") {
+ shift;
+ $reverse_conversion = 1;
+ } elsif ($ARGV[0] eq "-outdir") {
+ shift;
+ $outdir = shift;
+ }
+}
+
+# Given an NSPR symbol compute the JS equivalent or
+# vice-versa
+sub subst {
+ local ($replacement);
+ local ($sym) = @_;
+
+ $replacement = substr($sym,0,2) eq "pr" ? "js" : "JS";
+ $replacement .= substr($sym, 2);
+ return $replacement;
+}
+
+# Build the regular expression that will convert between the NSPR
+# types and the JS types
+if ($reverse_conversion) {
+ die "Not implemented yet";
+} else {
+ foreach $sym (@NSPR_symbols) {
+ $regexp .= $sym . "|"
+ }
+ # Get rid of the last "!"
+ chop $regexp;
+
+ # Replace PR* with JS* and replace pr* with js*
+ $regexp = 's/(^|\\W)(' . $regexp . ')/$1 . &subst($2)/eg';
+# print $regexp;
+}
+
+# Pre-compile a little subroutine to perform the regexp substitution
+# between NSPR types and JS types
+eval('sub convert_from_NSPR {($line) = @_; $line =~ ' . $regexp . ';}');
+
+sub convert_mallocs {
+ ($line) = @_;
+ $line =~ s/PR_MALLOC/malloc/g;
+ $line =~ s/PR_REALLOC/realloc/g;
+ $line =~ s/PR_FREE/free/g;
+ return $line;
+}
+
+sub convert_includes {
+ ($line) = @_;
+ if ($line !~ /include/) {
+ return $line;
+ }
+
+ if ($line =~ /prlog\.h/) {
+ $line = '#include "jsutil.h"'. " /* Added by JSIFY */\n";
+ } elsif ($line =~ /plhash\.h/) {
+ $line = '#include "jshash.h"'. " /* Added by JSIFY */\n";
+ } elsif ($line =~ /plarena\.h/) {
+ $line = '#include "jsarena.h"'. " /* Added by JSIFY */\n";
+ } elsif ($line =~ /prmem\.h/) {
+ $line = "";
+ } elsif ($line =~ /jsmsg\.def/) {
+ $line = '#include "js.msg"' . "\n";
+ } elsif ($line =~ /shellmsg\.def/) {
+ $line = '#include "jsshell.msg"' . "\n";
+ } elsif ($line =~ /jsopcode\.def/) {
+ $line = '#include "jsopcode.tbl"' . "\n";
+ }
+ return $line;
+}
+
+sub convert_declarations {
+ ($line) = @_;
+ $line =~ s/PR_EXTERN/JS_EXTERN_API/g;
+ $line =~ s/PR_IMPLEMENT_DATA/JS_EXPORT_DATA/g;
+ $line =~ s/PR_IMPLEMENT/JS_EXPORT_API/g;
+ $line =~ s/PR_IMPORT/JS_IMPORT/g;
+ $line =~ s/PR_PUBLIC_API/JS_EXPORT_API/g;
+ $line =~ s/PR_PUBLIC_DATA/JS_EXPORT_DATA/g;
+ return $line;
+}
+
+sub convert_long_long_macros {
+ ($line) = @_;
+ $line =~ s/\b(LL_)/JSLL_/g;
+ return $line;
+}
+
+sub convert_asserts {
+ ($line) = @_;
+ $line =~ s/\bPR_ASSERT/JS_ASSERT/g;
+ return $line;
+}
+
+while ($#ARGV >= 0) {
+ $infile = shift;
+
+ # Change filename, e.g. prtime.h to jsprtime.h, except for legacy
+ # files that start with 'prmj', like prmjtime.h.
+ $outfile = $infile;
+ if ($infile !~ /^prmj/) {
+ $outfile =~ s/^pr/js/;
+ $outfile =~ s/^pl/js/;
+ }
+
+ if ($outdir) {
+ $outfile = $outdir . '/' . $outfile;
+ }
+
+ if ($infile eq $outfile) {
+ die "Error: refuse to overwrite $outfile, use -outdir option."
+ }
+ die "Can't open $infile" if !open(INFILE, "<$infile");
+ die "Can't open $outfile for writing" if !open(OUTFILE, ">$outfile");
+
+ while (<INFILE>) {
+ $line = $_;
+
+ #Get rid of #include "prlog.h"
+ &convert_includes($line);
+
+ # Rename PR_EXTERN, PR_IMPORT, etc.
+ &convert_declarations($line);
+
+ # Convert from PR_MALLOC to malloc, etc.
+ &convert_mallocs($line);
+
+ # Convert from PR_ASSERT to JS_ASSERT
+# &convert_asserts($line);
+
+ # Convert from, e.g. PRArena to JSPRArena
+ &convert_from_NSPR($line);
+
+ # Change LL_* macros to JSLL_*
+ &convert_long_long_macros($line);
+
+ print OUTFILE $line;
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.cpp
new file mode 100644
index 0000000..3131507
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.cpp
@@ -0,0 +1,7225 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JavaScript bytecode interpreter.
+ */
+#include "jsstddef.h"
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsstaticcheck.h"
+#include "jstracer.h"
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+#include "jsdtracef.h"
+#endif
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#include "jsautooplen.h"
+
+/* jsinvoke_cpp___ indicates inclusion from jsinvoke.cpp. */
+#if !JS_LONE_INTERPRET ^ defined jsinvoke_cpp___
+
+uint32
+js_GenerateShape(JSContext *cx, JSBool gcLocked, JSScopeProperty *sprop)
+{
+ JSRuntime *rt;
+ uint32 shape;
+ JSTempValueRooter tvr;
+
+ rt = cx->runtime;
+ shape = JS_ATOMIC_INCREMENT(&rt->shapeGen);
+ JS_ASSERT(shape != 0);
+ if (shape & SHAPE_OVERFLOW_BIT) {
+ rt->gcPoke = JS_TRUE;
+ if (sprop)
+ JS_PUSH_TEMP_ROOT_SPROP(cx, sprop, &tvr);
+ js_GC(cx, gcLocked ? GC_LOCK_HELD : GC_NORMAL);
+ if (sprop)
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ shape = JS_ATOMIC_INCREMENT(&rt->shapeGen);
+ JS_ASSERT(shape != 0);
+ JS_ASSERT_IF(shape & SHAPE_OVERFLOW_BIT,
+ JS_PROPERTY_CACHE(cx).disabled);
+ }
+ return shape;
+}
+
+void
+js_FillPropertyCache(JSContext *cx, JSObject *obj, jsuword kshape,
+ uintN scopeIndex, uintN protoIndex,
+ JSObject *pobj, JSScopeProperty *sprop,
+ JSPropCacheEntry **entryp)
+{
+ JSPropertyCache *cache;
+ jsbytecode *pc;
+ JSScope *scope;
+ JSOp op;
+ const JSCodeSpec *cs;
+ jsuword vword;
+ ptrdiff_t pcoff;
+ jsuword khash;
+ JSAtom *atom;
+ JSPropCacheEntry *entry;
+
+ JS_ASSERT(!cx->runtime->gcRunning);
+ cache = &JS_PROPERTY_CACHE(cx);
+ pc = cx->fp->regs->pc;
+ if (cache->disabled || (cx->fp->flags & JSFRAME_EVAL)) {
+ PCMETER(cache->disfills++);
+ *entryp = NULL;
+ return;
+ }
+
+ /*
+ * Check for fill from js_SetPropertyHelper where the setter removed sprop
+ * from pobj's scope (via unwatch or delete, e.g.).
+ */
+ scope = OBJ_SCOPE(pobj);
+ JS_ASSERT(scope->object == pobj);
+ if (!SCOPE_HAS_PROPERTY(scope, sprop)) {
+ PCMETER(cache->oddfills++);
+ *entryp = NULL;
+ return;
+ }
+
+ /*
+ * Check for overdeep scope and prototype chain. Because resolve, getter,
+ * and setter hooks can change the prototype chain using JS_SetPrototype
+ * after js_LookupPropertyWithFlags has returned the nominal protoIndex,
+ * we have to validate protoIndex if it is non-zero. If it is zero, then
+ * we know thanks to the SCOPE_HAS_PROPERTY test above, and from the fact
+ * that obj == pobj, that protoIndex is invariant.
+ *
+ * The scopeIndex can't be wrong. We require JS_SetParent calls to happen
+ * before any running script might consult a parent-linked scope chain. If
+ * this requirement is not satisfied, the fill in progress will never hit,
+ * but vcap vs. scope shape tests ensure nothing malfunctions.
+ */
+ JS_ASSERT_IF(scopeIndex == 0 && protoIndex == 0, obj == pobj);
+ if (protoIndex != 0) {
+ JSObject *tmp;
+
+ JS_ASSERT(pobj != obj);
+ protoIndex = 1;
+ tmp = obj;
+ for (;;) {
+ tmp = OBJ_GET_PROTO(cx, tmp);
+ if (!tmp) {
+ PCMETER(cache->noprotos++);
+ *entryp = NULL;
+ return;
+ }
+ if (tmp == pobj)
+ break;
+ ++protoIndex;
+ }
+ }
+ if (scopeIndex > PCVCAP_SCOPEMASK || protoIndex > PCVCAP_PROTOMASK) {
+ PCMETER(cache->longchains++);
+ *entryp = NULL;
+ return;
+ }
+
+ /*
+ * Optimize the cached vword based on our parameters and the current pc's
+ * opcode format flags.
+ */
+ op = (JSOp) *pc;
+ cs = &js_CodeSpec[op];
+
+ do {
+ /*
+ * Check for a prototype "plain old method" callee computation. What
+ * is a plain old method? It's a function-valued property with stub
+ * getter and setter, so get of a function is idempotent and set is
+ * transparent.
+ */
+ if (cs->format & JOF_CALLOP) {
+ if (SPROP_HAS_STUB_GETTER(sprop) &&
+ SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ jsval v;
+
+ v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
+ if (VALUE_IS_FUNCTION(cx, v)) {
+ /*
+ * Great, we have a function-valued prototype property
+ * where the getter is JS_PropertyStub. The type id in
+ * pobj's scope does not evolve with changes to property
+ * values, however.
+ *
+ * So here, on first cache fill for this method, we brand
+ * the scope with a new shape and set the SCOPE_BRANDED
+ * flag. Once this scope flag is set, any write that adds
+ * or deletes a function-valued plain old property in
+ * scope->object will result in shape being regenerated.
+ */
+ if (!SCOPE_IS_BRANDED(scope)) {
+ PCMETER(cache->brandfills++);
+#ifdef DEBUG_notme
+ fprintf(stderr,
+ "branding %p (%s) for funobj %p (%s), kshape %lu\n",
+ pobj, LOCKED_OBJ_GET_CLASS(pobj)->name,
+ JSVAL_TO_OBJECT(v),
+ JS_GetFunctionName(GET_FUNCTION_PRIVATE(cx,
+ JSVAL_TO_OBJECT(v))),
+ kshape);
+#endif
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ SCOPE_SET_BRANDED(scope);
+ kshape = scope->shape;
+ }
+ vword = JSVAL_OBJECT_TO_PCVAL(v);
+ break;
+ }
+ }
+ }
+
+ /* If getting a value via a stub getter, we can cache the slot. */
+ if (!(cs->format & JOF_SET) &&
+ SPROP_HAS_STUB_GETTER(sprop) &&
+ SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ /* Great, let's cache sprop's slot and use it on cache hit. */
+ vword = SLOT_TO_PCVAL(sprop->slot);
+ } else {
+ /* Best we can do is to cache sprop (still a nice speedup). */
+ vword = SPROP_TO_PCVAL(sprop);
+ }
+ } while (0);
+
+ /*
+ * Our caller preserved the scope shape prior to the js_GetPropertyHelper
+ * or similar call out of the interpreter. We want to cache under that
+ * shape if op is overtly mutating, to bias for the case where the mutator
+ * udpates shape predictably.
+ *
+ * Note that an apparently non-mutating op such as JSOP_NAME may still
+ * mutate the base object via, e.g., lazy standard class initialization,
+ * but that is a one-time event and we'll have to miss the old shape and
+ * re-fill under the new one.
+ */
+ if (!(cs->format & (JOF_SET | JOF_INCDEC)) && obj == pobj)
+ kshape = scope->shape;
+
+ khash = PROPERTY_CACHE_HASH_PC(pc, kshape);
+ if (obj == pobj) {
+ JS_ASSERT(kshape != 0 || scope->shape != 0);
+ JS_ASSERT(scopeIndex == 0 && protoIndex == 0);
+ JS_ASSERT(OBJ_SCOPE(obj)->object == obj);
+ } else {
+ if (op == JSOP_LENGTH) {
+ atom = cx->runtime->atomState.lengthAtom;
+ } else {
+ pcoff = (JOF_TYPE(cs->format) == JOF_SLOTATOM) ? 2 : 0;
+ GET_ATOM_FROM_BYTECODE(cx->fp->script, pc, pcoff, atom);
+ }
+ JS_ASSERT_IF(scopeIndex == 0,
+ protoIndex != 1 || OBJ_GET_PROTO(cx, obj) == pobj);
+ if (scopeIndex != 0 || protoIndex != 1) {
+ khash = PROPERTY_CACHE_HASH_ATOM(atom, obj, pobj);
+ PCMETER(if (PCVCAP_TAG(cache->table[khash].vcap) <= 1)
+ cache->pcrecycles++);
+ pc = (jsbytecode *) atom;
+ kshape = (jsuword) obj;
+ }
+ }
+
+ entry = &cache->table[khash];
+ PCMETER(if (entry != *entryp) cache->modfills++);
+ PCMETER(if (!PCVAL_IS_NULL(entry->vword)) cache->recycles++);
+ entry->kpc = pc;
+ entry->kshape = kshape;
+ entry->vcap = PCVCAP_MAKE(scope->shape, scopeIndex, protoIndex);
+ entry->vword = vword;
+ *entryp = entry;
+
+ cache->empty = JS_FALSE;
+ PCMETER(cache->fills++);
+}
+
+JSAtom *
+js_FullTestPropertyCache(JSContext *cx, jsbytecode *pc,
+ JSObject **objp, JSObject **pobjp,
+ JSPropCacheEntry **entryp)
+{
+ JSOp op;
+ const JSCodeSpec *cs;
+ ptrdiff_t pcoff;
+ JSAtom *atom;
+ JSObject *obj, *pobj, *tmp;
+ JSPropCacheEntry *entry;
+ uint32 vcap;
+
+ JS_ASSERT(uintN((cx->fp->imacpc ? cx->fp->imacpc : pc) - cx->fp->script->code)
+ < cx->fp->script->length);
+
+ op = (JSOp) *pc;
+ cs = &js_CodeSpec[op];
+ if (op == JSOP_LENGTH) {
+ atom = cx->runtime->atomState.lengthAtom;
+ } else {
+ pcoff = (JOF_TYPE(cs->format) == JOF_SLOTATOM) ? 2 : 0;
+ GET_ATOM_FROM_BYTECODE(cx->fp->script, pc, pcoff, atom);
+ }
+
+ obj = *objp;
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ entry = &JS_PROPERTY_CACHE(cx).table[PROPERTY_CACHE_HASH_ATOM(atom, obj, NULL)];
+ *entryp = entry;
+ vcap = entry->vcap;
+
+ if (entry->kpc != (jsbytecode *) atom) {
+ PCMETER(JS_PROPERTY_CACHE(cx).idmisses++);
+
+#ifdef DEBUG_notme
+ entry = &JS_PROPERTY_CACHE(cx).table[PROPERTY_CACHE_HASH_PC(pc, OBJ_SHAPE(obj))];
+ fprintf(stderr,
+ "id miss for %s from %s:%u"
+ " (pc %u, kpc %u, kshape %u, shape %u)\n",
+ js_AtomToPrintableString(cx, atom),
+ cx->fp->script->filename,
+ js_PCToLineNumber(cx, cx->fp->script, pc),
+ pc - cx->fp->script->code,
+ entry->kpc - cx->fp->script->code,
+ entry->kshape,
+ OBJ_SHAPE(obj));
+ js_Disassemble1(cx, cx->fp->script, pc,
+ PTRDIFF(pc, cx->fp->script->code, jsbytecode),
+ JS_FALSE, stderr);
+#endif
+
+ return atom;
+ }
+
+ if (entry->kshape != (jsuword) obj) {
+ PCMETER(JS_PROPERTY_CACHE(cx).komisses++);
+ return atom;
+ }
+
+ pobj = obj;
+ JS_LOCK_OBJ(cx, pobj);
+
+ if (JOF_MODE(cs->format) == JOF_NAME) {
+ while (vcap & (PCVCAP_SCOPEMASK << PCVCAP_PROTOBITS)) {
+ tmp = LOCKED_OBJ_GET_PARENT(pobj);
+ if (!tmp || !OBJ_IS_NATIVE(tmp))
+ break;
+ JS_UNLOCK_OBJ(cx, pobj);
+ pobj = tmp;
+ JS_LOCK_OBJ(cx, pobj);
+ vcap -= PCVCAP_PROTOSIZE;
+ }
+
+ *objp = pobj;
+ }
+
+ while (vcap & PCVCAP_PROTOMASK) {
+ tmp = LOCKED_OBJ_GET_PROTO(pobj);
+ if (!tmp || !OBJ_IS_NATIVE(tmp))
+ break;
+ JS_UNLOCK_OBJ(cx, pobj);
+ pobj = tmp;
+ JS_LOCK_OBJ(cx, pobj);
+ --vcap;
+ }
+
+ if (PCVCAP_SHAPE(vcap) == OBJ_SHAPE(pobj)) {
+#ifdef DEBUG
+ jsid id = ATOM_TO_JSID(atom);
+
+ CHECK_FOR_STRING_INDEX(id);
+ JS_ASSERT(SCOPE_GET_PROPERTY(OBJ_SCOPE(pobj), id));
+ JS_ASSERT(OBJ_SCOPE(pobj)->object == pobj);
+#endif
+ *pobjp = pobj;
+ return NULL;
+ }
+
+ PCMETER(JS_PROPERTY_CACHE(cx).vcmisses++);
+ JS_UNLOCK_OBJ(cx, pobj);
+ return atom;
+}
+
+#ifdef DEBUG
+#define ASSERT_CACHE_IS_EMPTY(cache) \
+ JS_BEGIN_MACRO \
+ JSPropertyCache *cache_ = (cache); \
+ uintN i_; \
+ JS_ASSERT(cache_->empty); \
+ for (i_ = 0; i_ < PROPERTY_CACHE_SIZE; i_++) { \
+ JS_ASSERT(!cache_->table[i_].kpc); \
+ JS_ASSERT(!cache_->table[i_].kshape); \
+ JS_ASSERT(!cache_->table[i_].vcap); \
+ JS_ASSERT(!cache_->table[i_].vword); \
+ } \
+ JS_END_MACRO
+#else
+#define ASSERT_CACHE_IS_EMPTY(cache) ((void)0)
+#endif
+
+JS_STATIC_ASSERT(PCVAL_NULL == 0);
+
+void
+js_FlushPropertyCache(JSContext *cx)
+{
+ JSPropertyCache *cache;
+
+ cache = &JS_PROPERTY_CACHE(cx);
+ if (cache->empty) {
+ ASSERT_CACHE_IS_EMPTY(cache);
+ return;
+ }
+
+ memset(cache->table, 0, sizeof cache->table);
+ cache->empty = JS_TRUE;
+
+#ifdef JS_PROPERTY_CACHE_METERING
+ { static FILE *fp;
+ if (!fp)
+ fp = fopen("/tmp/propcache.stats", "w");
+ if (fp) {
+ fputs("Property cache stats for ", fp);
+#ifdef JS_THREADSAFE
+ fprintf(fp, "thread %lu, ", (unsigned long) cx->thread->id);
+#endif
+ fprintf(fp, "GC %u\n", cx->runtime->gcNumber);
+
+# define P(mem) fprintf(fp, "%11s %10lu\n", #mem, (unsigned long)cache->mem)
+ P(fills);
+ P(nofills);
+ P(rofills);
+ P(disfills);
+ P(oddfills);
+ P(modfills);
+ P(brandfills);
+ P(noprotos);
+ P(longchains);
+ P(recycles);
+ P(pcrecycles);
+ P(tests);
+ P(pchits);
+ P(protopchits);
+ P(initests);
+ P(inipchits);
+ P(inipcmisses);
+ P(settests);
+ P(addpchits);
+ P(setpchits);
+ P(setpcmisses);
+ P(slotchanges);
+ P(setmisses);
+ P(idmisses);
+ P(komisses);
+ P(vcmisses);
+ P(misses);
+ P(flushes);
+ P(pcpurges);
+# undef P
+
+ fprintf(fp, "hit rates: pc %g%% (proto %g%%), set %g%%, ini %g%%, full %g%%\n",
+ (100. * cache->pchits) / cache->tests,
+ (100. * cache->protopchits) / cache->tests,
+ (100. * (cache->addpchits + cache->setpchits))
+ / cache->settests,
+ (100. * cache->inipchits) / cache->initests,
+ (100. * (cache->tests - cache->misses)) / cache->tests);
+ fflush(fp);
+ }
+ }
+#endif
+
+ PCMETER(cache->flushes++);
+}
+
+void
+js_FlushPropertyCacheForScript(JSContext *cx, JSScript *script)
+{
+ JSPropertyCache *cache;
+ JSPropCacheEntry *entry;
+
+ cache = &JS_PROPERTY_CACHE(cx);
+ for (entry = cache->table; entry < cache->table + PROPERTY_CACHE_SIZE;
+ entry++) {
+ if (JS_UPTRDIFF(entry->kpc, script->code) < script->length) {
+ entry->kpc = NULL;
+ entry->kshape = 0;
+#ifdef DEBUG
+ entry->vcap = entry->vword = 0;
+#endif
+ }
+ }
+}
+
+void
+js_DisablePropertyCache(JSContext *cx)
+{
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0);
+ ++JS_PROPERTY_CACHE(cx).disabled;
+}
+
+void
+js_EnablePropertyCache(JSContext *cx)
+{
+ --JS_PROPERTY_CACHE(cx).disabled;
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0);
+}
+
+/*
+ * Check if the current arena has enough space to fit nslots after sp and, if
+ * so, reserve the necessary space.
+ */
+static JSBool
+AllocateAfterSP(JSContext *cx, jsval *sp, uintN nslots)
+{
+ uintN surplus;
+ jsval *sp2;
+
+ JS_ASSERT((jsval *) cx->stackPool.current->base <= sp);
+ JS_ASSERT(sp <= (jsval *) cx->stackPool.current->avail);
+ surplus = (jsval *) cx->stackPool.current->avail - sp;
+ if (nslots <= surplus)
+ return JS_TRUE;
+
+ /*
+ * No room before current->avail, check if the arena has enough space to
+ * fit the missing slots before the limit.
+ */
+ if (nslots > (size_t) ((jsval *) cx->stackPool.current->limit - sp))
+ return JS_FALSE;
+
+ JS_ARENA_ALLOCATE_CAST(sp2, jsval *, &cx->stackPool,
+ (nslots - surplus) * sizeof(jsval));
+ JS_ASSERT(sp2 == sp + surplus);
+ return JS_TRUE;
+}
+
+JS_STATIC_INTERPRET jsval *
+js_AllocRawStack(JSContext *cx, uintN nslots, void **markp)
+{
+ jsval *sp;
+
+ if (!cx->stackPool.first.next) {
+ int64 *timestamp;
+
+ JS_ARENA_ALLOCATE_CAST(timestamp, int64 *,
+ &cx->stackPool, sizeof *timestamp);
+ if (!timestamp) {
+ js_ReportOutOfScriptQuota(cx);
+ return NULL;
+ }
+ *timestamp = JS_Now();
+ }
+
+ if (markp)
+ *markp = JS_ARENA_MARK(&cx->stackPool);
+ JS_ARENA_ALLOCATE_CAST(sp, jsval *, &cx->stackPool, nslots * sizeof(jsval));
+ if (!sp)
+ js_ReportOutOfScriptQuota(cx);
+ return sp;
+}
+
+JS_STATIC_INTERPRET void
+js_FreeRawStack(JSContext *cx, void *mark)
+{
+ JS_ARENA_RELEASE(&cx->stackPool, mark);
+}
+
+JS_FRIEND_API(jsval *)
+js_AllocStack(JSContext *cx, uintN nslots, void **markp)
+{
+ jsval *sp;
+ JSArena *a;
+ JSStackHeader *sh;
+
+ /* Callers don't check for zero nslots: we do to avoid empty segments. */
+ if (nslots == 0) {
+ *markp = NULL;
+ return (jsval *) JS_ARENA_MARK(&cx->stackPool);
+ }
+
+ /* Allocate 2 extra slots for the stack segment header we'll likely need. */
+ sp = js_AllocRawStack(cx, 2 + nslots, markp);
+ if (!sp)
+ return NULL;
+
+ /* Try to avoid another header if we can piggyback on the last segment. */
+ a = cx->stackPool.current;
+ sh = cx->stackHeaders;
+ if (sh && JS_STACK_SEGMENT(sh) + sh->nslots == sp) {
+ /* Extend the last stack segment, give back the 2 header slots. */
+ sh->nslots += nslots;
+ a->avail -= 2 * sizeof(jsval);
+ } else {
+ /*
+ * Need a new stack segment, so allocate and push a stack segment
+ * header from the 2 extra slots.
+ */
+ sh = (JSStackHeader *)sp;
+ sh->nslots = nslots;
+ sh->down = cx->stackHeaders;
+ cx->stackHeaders = sh;
+ sp += 2;
+ }
+
+ /*
+ * Store JSVAL_NULL using memset, to let compilers optimize as they see
+ * fit, in case a caller allocates and pushes GC-things one by one, which
+ * could nest a last-ditch GC that will scan this segment.
+ */
+ memset(sp, 0, nslots * sizeof(jsval));
+ return sp;
+}
+
+JS_FRIEND_API(void)
+js_FreeStack(JSContext *cx, void *mark)
+{
+ JSStackHeader *sh;
+ jsuword slotdiff;
+
+ /* Check for zero nslots allocation special case. */
+ if (!mark)
+ return;
+
+ /* We can assert because js_FreeStack always balances js_AllocStack. */
+ sh = cx->stackHeaders;
+ JS_ASSERT(sh);
+
+ /* If mark is in the current segment, reduce sh->nslots, else pop sh. */
+ slotdiff = JS_UPTRDIFF(mark, JS_STACK_SEGMENT(sh)) / sizeof(jsval);
+ if (slotdiff < (jsuword)sh->nslots)
+ sh->nslots = slotdiff;
+ else
+ cx->stackHeaders = sh->down;
+
+ /* Release the stackPool space allocated since mark was set. */
+ JS_ARENA_RELEASE(&cx->stackPool, mark);
+}
+
+JSObject *
+js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
+{
+ JSObject *obj, *cursor, *clonedChild, *parent;
+ JSTempValueRooter tvr;
+
+ obj = fp->blockChain;
+ if (!obj) {
+ /*
+ * Don't force a call object for a lightweight function call, but do
+ * insist that there is a call object for a heavyweight function call.
+ */
+ JS_ASSERT(!fp->fun ||
+ !(fp->fun->flags & JSFUN_HEAVYWEIGHT) ||
+ fp->callobj);
+ JS_ASSERT(fp->scopeChain);
+ return fp->scopeChain;
+ }
+
+ /*
+ * We have one or more lexical scopes to reflect into fp->scopeChain, so
+ * make sure there's a call object at the current head of the scope chain,
+ * if this frame is a call frame.
+ */
+ if (fp->fun && !fp->callobj) {
+ JS_ASSERT(OBJ_GET_CLASS(cx, fp->scopeChain) != &js_BlockClass ||
+ OBJ_GET_PRIVATE(cx, fp->scopeChain) != fp);
+ if (!js_GetCallObject(cx, fp, fp->scopeChain))
+ return NULL;
+ }
+
+ /*
+ * Clone the block chain. To avoid recursive cloning we set the parent of
+ * the cloned child after we clone the parent. In the following loop when
+ * clonedChild is null it indicates the first iteration when no special GC
+ * rooting is necessary. On the second and the following iterations we
+ * have to protect cloned so far chain against the GC during cloning of
+ * the cursor object.
+ */
+ cursor = obj;
+ clonedChild = NULL;
+ for (;;) {
+ parent = OBJ_GET_PARENT(cx, cursor);
+
+ /*
+ * We pass fp->scopeChain and not null even if we override the parent
+ * slot later as null triggers useless calculations of slot's value in
+ * js_NewObject that js_CloneBlockObject calls.
+ */
+ cursor = js_CloneBlockObject(cx, cursor, fp->scopeChain, fp);
+ if (!cursor) {
+ if (clonedChild)
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return NULL;
+ }
+ if (!clonedChild) {
+ /*
+ * The first iteration. Check if other follow and root obj if so
+ * to protect the whole cloned chain against GC.
+ */
+ obj = cursor;
+ if (!parent)
+ break;
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);
+ } else {
+ /*
+ * Avoid OBJ_SET_PARENT overhead as clonedChild cannot escape to
+ * other threads.
+ */
+ STOBJ_SET_PARENT(clonedChild, cursor);
+ if (!parent) {
+ JS_ASSERT(tvr.u.value == OBJECT_TO_JSVAL(obj));
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ break;
+ }
+ }
+ clonedChild = cursor;
+ cursor = parent;
+ }
+ fp->flags |= JSFRAME_POP_BLOCKS;
+ fp->scopeChain = obj;
+ fp->blockChain = NULL;
+ return obj;
+}
+
+JSBool
+js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp)
+{
+ jsval v;
+ JSObject *obj;
+
+ v = vp[1];
+ if (JSVAL_IS_OBJECT(v)) {
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, clasp, vp + 2))
+ return JS_FALSE;
+ v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ }
+ *thisvp = v;
+ return JS_TRUE;
+}
+
+/*
+ * ECMA requires "the global object", but in embeddings such as the browser,
+ * which have multiple top-level objects (windows, frames, etc. in the DOM),
+ * we prefer fun's parent. An example that causes this code to run:
+ *
+ * // in window w1
+ * function f() { return this }
+ * function g() { return f }
+ *
+ * // in window w2
+ * var h = w1.g()
+ * alert(h() == w1)
+ *
+ * The alert should display "true".
+ */
+JS_STATIC_INTERPRET JSObject *
+js_ComputeGlobalThis(JSContext *cx, JSBool lazy, jsval *argv)
+{
+ JSObject *thisp;
+
+ if (JSVAL_IS_PRIMITIVE(argv[-2]) ||
+ !OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2]))) {
+ thisp = cx->globalObject;
+ } else {
+ JSStackFrame *fp;
+ jsid id;
+ jsval v;
+ uintN attrs;
+ JSBool ok;
+ JSObject *parent;
+
+ /*
+ * Walk up the parent chain, first checking that the running script
+ * has access to the callee's parent object. Note that if lazy, the
+ * running script whose principals we want to check is the script
+ * associated with fp->down, not with fp.
+ *
+ * FIXME: 417851 -- this access check should not be required, as it
+ * imposes a performance penalty on all js_ComputeGlobalThis calls,
+ * and it represents a maintenance hazard.
+ */
+ fp = cx->fp; /* quell GCC overwarning */
+ if (lazy) {
+ JS_ASSERT(fp->argv == argv);
+ fp->dormantNext = cx->dormantFrameChain;
+ cx->dormantFrameChain = fp;
+ cx->fp = fp->down;
+ fp->down = NULL;
+ }
+ thisp = JSVAL_TO_OBJECT(argv[-2]);
+ id = ATOM_TO_JSID(cx->runtime->atomState.parentAtom);
+
+ ok = OBJ_CHECK_ACCESS(cx, thisp, id, JSACC_PARENT, &v, &attrs);
+ if (lazy) {
+ cx->dormantFrameChain = fp->dormantNext;
+ fp->dormantNext = NULL;
+ fp->down = cx->fp;
+ cx->fp = fp;
+ }
+ if (!ok)
+ return NULL;
+
+ thisp = JSVAL_IS_VOID(v)
+ ? OBJ_GET_PARENT(cx, thisp)
+ : JSVAL_TO_OBJECT(v);
+ while ((parent = OBJ_GET_PARENT(cx, thisp)) != NULL)
+ thisp = parent;
+ }
+
+ OBJ_TO_OUTER_OBJECT(cx, thisp);
+ if (!thisp)
+ return NULL;
+ argv[-1] = OBJECT_TO_JSVAL(thisp);
+ return thisp;
+}
+
+static JSObject *
+ComputeThis(JSContext *cx, JSBool lazy, jsval *argv)
+{
+ JSObject *thisp;
+
+ JS_ASSERT(!JSVAL_IS_NULL(argv[-1]));
+ if (!JSVAL_IS_OBJECT(argv[-1])) {
+ if (!js_PrimitiveToObject(cx, &argv[-1]))
+ return NULL;
+ thisp = JSVAL_TO_OBJECT(argv[-1]);
+ } else {
+ thisp = JSVAL_TO_OBJECT(argv[-1]);
+ if (OBJ_GET_CLASS(cx, thisp) == &js_CallClass)
+ return js_ComputeGlobalThis(cx, lazy, argv);
+
+ if (thisp->map->ops->thisObject) {
+ /* Some objects (e.g., With) delegate 'this' to another object. */
+ thisp = thisp->map->ops->thisObject(cx, thisp);
+ if (!thisp)
+ return NULL;
+ }
+ OBJ_TO_OUTER_OBJECT(cx, thisp);
+ if (!thisp)
+ return NULL;
+ argv[-1] = OBJECT_TO_JSVAL(thisp);
+ }
+ return thisp;
+}
+
+JSObject *
+js_ComputeThis(JSContext *cx, JSBool lazy, jsval *argv)
+{
+ if (JSVAL_IS_NULL(argv[-1]))
+ return js_ComputeGlobalThis(cx, lazy, argv);
+ return ComputeThis(cx, lazy, argv);
+}
+
+#if JS_HAS_NO_SUCH_METHOD
+
+#define JSSLOT_FOUND_FUNCTION JSSLOT_PRIVATE
+#define JSSLOT_SAVED_ID (JSSLOT_PRIVATE + 1)
+
+JSClass js_NoSuchMethodClass = {
+ "NoSuchMethod",
+ JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_NoSuchMethod),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+JS_BEGIN_EXTERN_C
+
+JSObject*
+js_InitNoSuchMethodClass(JSContext *cx, JSObject* obj);
+
+JS_END_EXTERN_C
+
+JSObject*
+js_InitNoSuchMethodClass(JSContext *cx, JSObject* obj)
+{
+ JSObject *proto;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_NoSuchMethodClass, NULL, 0, NULL,
+ NULL, NULL, NULL);
+ if (!proto)
+ return NULL;
+
+ OBJ_CLEAR_PROTO(cx, proto);
+ return proto;
+}
+
+/*
+ * When JSOP_CALLPROP or JSOP_CALLELEM does not find the method property of
+ * the base object, we search for the __noSuchMethod__ method in the base.
+ * If it exists, we store the method and the property's id into an object of
+ * NoSuchMethod class and store this object into the callee's stack slot.
+ * Later, js_Invoke will recognise such an object and transfer control to
+ * NoSuchMethod that invokes the method like:
+ *
+ * this.__noSuchMethod__(id, args)
+ *
+ * where id is the name of the method that this invocation attempted to
+ * call by name, and args is an Array containing this invocation's actual
+ * parameters.
+ */
+JS_STATIC_INTERPRET JSBool
+js_OnUnknownMethod(JSContext *cx, jsval *vp)
+{
+ JSObject *obj;
+ jsid id;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1]));
+ obj = JSVAL_TO_OBJECT(vp[1]);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+
+ MUST_FLOW_THROUGH("out");
+ id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom);
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ JSXMLObjectOps *ops;
+
+ ops = (JSXMLObjectOps *) obj->map->ops;
+ obj = ops->getMethod(cx, obj, id, &tvr.u.value);
+ if (!obj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ vp[1] = OBJECT_TO_JSVAL(obj);
+ } else
+#endif
+ {
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ if (JSVAL_IS_PRIMITIVE(tvr.u.value)) {
+ vp[0] = tvr.u.value;
+ } else {
+#if JS_HAS_XML_SUPPORT
+ /* Extract the function name from function::name qname. */
+ if (!JSVAL_IS_PRIMITIVE(vp[0])) {
+ obj = JSVAL_TO_OBJECT(vp[0]);
+ ok = js_IsFunctionQName(cx, obj, &id);
+ if (!ok)
+ goto out;
+ if (id != 0)
+ vp[0] = ID_TO_VALUE(id);
+ }
+#endif
+ obj = js_NewObject(cx, &js_NoSuchMethodClass, NULL, NULL, 0);
+ if (!obj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ obj->fslots[JSSLOT_FOUND_FUNCTION] = tvr.u.value;
+ obj->fslots[JSSLOT_SAVED_ID] = vp[0];
+ vp[0] = OBJECT_TO_JSVAL(obj);
+ }
+ ok = JS_TRUE;
+
+ out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSBool
+NoSuchMethod(JSContext *cx, uintN argc, jsval *vp, uint32 flags)
+{
+ jsval *invokevp;
+ void *mark;
+ JSBool ok;
+ JSObject *obj, *argsobj;
+
+ invokevp = js_AllocStack(cx, 2 + 2, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[0]));
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1]));
+ obj = JSVAL_TO_OBJECT(vp[0]);
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_NoSuchMethodClass);
+
+ invokevp[0] = obj->fslots[JSSLOT_FOUND_FUNCTION];
+ invokevp[1] = vp[1];
+ invokevp[2] = obj->fslots[JSSLOT_SAVED_ID];
+ argsobj = js_NewArrayObject(cx, argc, vp + 2);
+ if (!argsobj) {
+ ok = JS_FALSE;
+ } else {
+ invokevp[3] = OBJECT_TO_JSVAL(argsobj);
+ ok = (flags & JSINVOKE_CONSTRUCT)
+ ? js_InvokeConstructor(cx, 2, JS_TRUE, invokevp)
+ : js_Invoke(cx, 2, invokevp, flags);
+ vp[0] = invokevp[0];
+ }
+ js_FreeStack(cx, mark);
+ return ok;
+}
+
+#endif /* JS_HAS_NO_SUCH_METHOD */
+
+/*
+ * We check if the function accepts a primitive value as |this|. For that we
+ * use a table that maps value's tag into the corresponding function flag.
+ */
+JS_STATIC_ASSERT(JSVAL_INT == 1);
+JS_STATIC_ASSERT(JSVAL_DOUBLE == 2);
+JS_STATIC_ASSERT(JSVAL_STRING == 4);
+JS_STATIC_ASSERT(JSVAL_BOOLEAN == 6);
+
+const uint16 js_PrimitiveTestFlags[] = {
+ JSFUN_THISP_NUMBER, /* INT */
+ JSFUN_THISP_NUMBER, /* DOUBLE */
+ JSFUN_THISP_NUMBER, /* INT */
+ JSFUN_THISP_STRING, /* STRING */
+ JSFUN_THISP_NUMBER, /* INT */
+ JSFUN_THISP_BOOLEAN, /* BOOLEAN */
+ JSFUN_THISP_NUMBER /* INT */
+};
+
+/*
+ * Find a function reference and its 'this' object implicit first parameter
+ * under argc arguments on cx's stack, and call the function. Push missing
+ * required arguments, allocate declared local variables, and pop everything
+ * when done. Then push the return value.
+ */
+JS_FRIEND_API(JSBool)
+js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags)
+{
+ void *mark;
+ JSStackFrame frame;
+ jsval *sp, *argv, *newvp;
+ jsval v;
+ JSObject *funobj, *parent;
+ JSBool ok;
+ JSClass *clasp;
+ JSObjectOps *ops;
+ JSNative native;
+ JSFunction *fun;
+ JSScript *script;
+ uintN nslots, i;
+ uint32 rootedArgsFlag;
+ JSInterpreterHook hook;
+ void *hookData;
+
+ /* [vp .. vp + 2 + argc) must belong to the last JS stack arena. */
+ JS_ASSERT((jsval *) cx->stackPool.current->base <= vp);
+ JS_ASSERT(vp + 2 + argc <= (jsval *) cx->stackPool.current->avail);
+
+ /*
+ * Mark the top of stack and load frequently-used registers. After this
+ * point the control should flow through label out2: to return.
+ */
+ mark = JS_ARENA_MARK(&cx->stackPool);
+ v = *vp;
+
+ if (JSVAL_IS_PRIMITIVE(v))
+ goto bad;
+
+ funobj = JSVAL_TO_OBJECT(v);
+ parent = OBJ_GET_PARENT(cx, funobj);
+ clasp = OBJ_GET_CLASS(cx, funobj);
+ if (clasp != &js_FunctionClass) {
+#if JS_HAS_NO_SUCH_METHOD
+ if (clasp == &js_NoSuchMethodClass) {
+ ok = NoSuchMethod(cx, argc, vp, flags);
+ goto out2;
+ }
+#endif
+
+ /* Function is inlined, all other classes use object ops. */
+ ops = funobj->map->ops;
+
+ /*
+ * XXX this makes no sense -- why convert to function if clasp->call?
+ * XXX better to call that hook without converting
+ * XXX the only thing that needs fixing is liveconnect
+ *
+ * Try converting to function, for closure and API compatibility.
+ * We attempt the conversion under all circumstances for 1.2, but
+ * only if there is a call op defined otherwise.
+ */
+ if ((ops == &js_ObjectOps) ? clasp->call : ops->call) {
+ ok = clasp->convert(cx, funobj, JSTYPE_FUNCTION, &v);
+ if (!ok)
+ goto out2;
+
+ if (VALUE_IS_FUNCTION(cx, v)) {
+ /* Make vp refer to funobj to keep it available as argv[-2]. */
+ *vp = v;
+ funobj = JSVAL_TO_OBJECT(v);
+ parent = OBJ_GET_PARENT(cx, funobj);
+ goto have_fun;
+ }
+ }
+ fun = NULL;
+ script = NULL;
+ nslots = 0;
+
+ /* Try a call or construct native object op. */
+ if (flags & JSINVOKE_CONSTRUCT) {
+ if (!JSVAL_IS_OBJECT(vp[1])) {
+ ok = js_PrimitiveToObject(cx, &vp[1]);
+ if (!ok)
+ goto out2;
+ }
+ native = ops->construct;
+ } else {
+ native = ops->call;
+ }
+ if (!native)
+ goto bad;
+ } else {
+have_fun:
+ /* Get private data and set derived locals from it. */
+ fun = GET_FUNCTION_PRIVATE(cx, funobj);
+ nslots = FUN_MINARGS(fun);
+ nslots = (nslots > argc) ? nslots - argc : 0;
+ if (FUN_INTERPRETED(fun)) {
+ native = NULL;
+ script = fun->u.i.script;
+ } else {
+ native = fun->u.n.native;
+ script = NULL;
+ nslots += fun->u.n.extra;
+ }
+
+ if (JSFUN_BOUND_METHOD_TEST(fun->flags)) {
+ /* Handle bound method special case. */
+ vp[1] = OBJECT_TO_JSVAL(parent);
+ } else if (!JSVAL_IS_OBJECT(vp[1])) {
+ JS_ASSERT(!(flags & JSINVOKE_CONSTRUCT));
+ if (PRIMITIVE_THIS_TEST(fun, vp[1]))
+ goto start_call;
+ }
+ }
+
+ if (flags & JSINVOKE_CONSTRUCT) {
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1]));
+ } else {
+ /*
+ * We must call js_ComputeThis in case we are not called from the
+ * interpreter, where a prior bytecode has computed an appropriate
+ * |this| already.
+ *
+ * But we need to compute |this| eagerly only for so-called "slow"
+ * (i.e., not fast) native functions. Fast natives must use either
+ * JS_THIS or JS_THIS_OBJECT, and scripted functions will go through
+ * the appropriate this-computing bytecode, e.g., JSOP_THIS.
+ */
+ if (native && (!fun || !(fun->flags & JSFUN_FAST_NATIVE))) {
+ if (!js_ComputeThis(cx, JS_FALSE, vp + 2)) {
+ ok = JS_FALSE;
+ goto out2;
+ }
+ flags |= JSFRAME_COMPUTED_THIS;
+ }
+ }
+
+ start_call:
+ if (native && fun && (fun->flags & JSFUN_FAST_NATIVE)) {
+#ifdef DEBUG_NOT_THROWING
+ JSBool alreadyThrowing = cx->throwing;
+#endif
+ JS_ASSERT(nslots == 0);
+#if JS_HAS_LVALUE_RETURN
+ /* Set by JS_SetCallReturnValue2, used to return reference types. */
+ cx->rval2set = JS_FALSE;
+#endif
+ ok = ((JSFastNative) native)(cx, argc, vp);
+ JS_RUNTIME_METER(cx->runtime, nativeCalls);
+#ifdef DEBUG_NOT_THROWING
+ if (ok && !alreadyThrowing)
+ ASSERT_NOT_THROWING(cx);
+#endif
+ goto out2;
+ }
+
+ argv = vp + 2;
+ sp = argv + argc;
+
+ rootedArgsFlag = JSFRAME_ROOTED_ARGV;
+ if (nslots != 0) {
+ /*
+ * The extra slots required by the function continue with argument
+ * slots. Thus, when the last stack pool arena does not have room to
+ * fit nslots right after sp and AllocateAfterSP fails, we have to copy
+ * [vp..vp+2+argc) slots and clear rootedArgsFlag to root the copy.
+ */
+ if (!AllocateAfterSP(cx, sp, nslots)) {
+ rootedArgsFlag = 0;
+ newvp = js_AllocRawStack(cx, 2 + argc + nslots, NULL);
+ if (!newvp) {
+ ok = JS_FALSE;
+ goto out2;
+ }
+ memcpy(newvp, vp, (2 + argc) * sizeof(jsval));
+ argv = newvp + 2;
+ sp = argv + argc;
+ }
+
+ /* Push void to initialize missing args. */
+ i = nslots;
+ do {
+ *sp++ = JSVAL_VOID;
+ } while (--i != 0);
+ }
+
+ /* Allocate space for local variables and stack of interpreted function. */
+ if (script && script->nslots != 0) {
+ if (!AllocateAfterSP(cx, sp, script->nslots)) {
+ /* NB: Discontinuity between argv and slots, stack slots. */
+ sp = js_AllocRawStack(cx, script->nslots, NULL);
+ if (!sp) {
+ ok = JS_FALSE;
+ goto out2;
+ }
+ }
+
+ /* Push void to initialize local variables. */
+ for (jsval *end = sp + fun->u.i.nvars; sp != end; ++sp)
+ *sp = JSVAL_VOID;
+ }
+
+ /*
+ * Initialize the frame.
+ *
+ * To set thisp we use an explicit cast and not JSVAL_TO_OBJECT, as vp[1]
+ * can be a primitive value here for those native functions specified with
+ * JSFUN_THISP_(NUMBER|STRING|BOOLEAN) flags.
+ */
+ frame.thisp = (JSObject *)vp[1];
+ frame.varobj = NULL;
+ frame.callobj = frame.argsobj = NULL;
+ frame.script = script;
+ frame.callee = funobj;
+ frame.fun = fun;
+ frame.argc = argc;
+ frame.argv = argv;
+
+ /* Default return value for a constructor is the new object. */
+ frame.rval = (flags & JSINVOKE_CONSTRUCT) ? vp[1] : JSVAL_VOID;
+ frame.down = cx->fp;
+ frame.annotation = NULL;
+ frame.scopeChain = NULL; /* set below for real, after cx->fp is set */
+ frame.regs = NULL;
+ frame.imacpc = NULL;
+ frame.slots = NULL;
+ frame.sharpDepth = 0;
+ frame.sharpArray = NULL;
+ frame.flags = flags | rootedArgsFlag;
+ frame.dormantNext = NULL;
+ frame.xmlNamespace = NULL;
+ frame.blockChain = NULL;
+
+ MUST_FLOW_THROUGH("out");
+ cx->fp = &frame;
+
+ /* Init these now in case we goto out before first hook call. */
+ hook = cx->debugHooks->callHook;
+ hookData = NULL;
+
+ /* call the hook if present */
+ if (hook && (native || script))
+ hookData = hook(cx, &frame, JS_TRUE, 0, cx->debugHooks->callHookData);
+
+ /* Call the function, either a native method or an interpreted script. */
+ if (native) {
+#ifdef DEBUG_NOT_THROWING
+ JSBool alreadyThrowing = cx->throwing;
+#endif
+
+#if JS_HAS_LVALUE_RETURN
+ /* Set by JS_SetCallReturnValue2, used to return reference types. */
+ cx->rval2set = JS_FALSE;
+#endif
+
+ /* If native, use caller varobj and scopeChain for eval. */
+ JS_ASSERT(!frame.varobj);
+ JS_ASSERT(!frame.scopeChain);
+ if (frame.down) {
+ frame.varobj = frame.down->varobj;
+ frame.scopeChain = frame.down->scopeChain;
+ }
+
+ /* But ensure that we have a scope chain. */
+ if (!frame.scopeChain)
+ frame.scopeChain = parent;
+
+ frame.displaySave = NULL;
+ ok = native(cx, frame.thisp, argc, frame.argv, &frame.rval);
+ JS_RUNTIME_METER(cx->runtime, nativeCalls);
+#ifdef DEBUG_NOT_THROWING
+ if (ok && !alreadyThrowing)
+ ASSERT_NOT_THROWING(cx);
+#endif
+ } else if (script) {
+ /* Use parent scope so js_GetCallObject can find the right "Call". */
+ frame.scopeChain = parent;
+ if (JSFUN_HEAVYWEIGHT_TEST(fun->flags)) {
+ /* Scope with a call object parented by the callee's parent. */
+ if (!js_GetCallObject(cx, &frame, parent)) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+ frame.slots = sp - fun->u.i.nvars;
+
+ ok = js_Interpret(cx);
+ } else {
+ /* fun might be onerror trying to report a syntax error in itself. */
+ frame.scopeChain = NULL;
+ frame.displaySave = NULL;
+ ok = JS_TRUE;
+ }
+
+out:
+ if (hookData) {
+ hook = cx->debugHooks->callHook;
+ if (hook)
+ hook(cx, &frame, JS_FALSE, &ok, hookData);
+ }
+
+ /* If frame has a call object, sync values and clear back-pointer. */
+ if (frame.callobj)
+ ok &= js_PutCallObject(cx, &frame);
+
+ /* If frame has an arguments object, sync values and clear back-pointer. */
+ if (frame.argsobj)
+ ok &= js_PutArgsObject(cx, &frame);
+
+ *vp = frame.rval;
+
+ /* Restore cx->fp now that we're done releasing frame objects. */
+ cx->fp = frame.down;
+
+out2:
+ /* Pop everything we may have allocated off the stack. */
+ JS_ARENA_RELEASE(&cx->stackPool, mark);
+ if (!ok)
+ *vp = JSVAL_NULL;
+ return ok;
+
+bad:
+ js_ReportIsNotFunction(cx, vp, flags & JSINVOKE_FUNFLAGS);
+ ok = JS_FALSE;
+ goto out2;
+}
+
+JSBool
+js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ jsval *invokevp;
+ void *mark;
+ JSBool ok;
+
+ invokevp = js_AllocStack(cx, 2 + argc, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ invokevp[0] = fval;
+ invokevp[1] = OBJECT_TO_JSVAL(obj);
+ memcpy(invokevp + 2, argv, argc * sizeof *argv);
+
+ ok = js_Invoke(cx, argc, invokevp, flags);
+ if (ok) {
+ /*
+ * Store *rval in the a scoped local root if a scope is open, else in
+ * the lastInternalResult pigeon-hole GC root, solely so users of
+ * js_InternalInvoke and its direct and indirect (js_ValueToString for
+ * example) callers do not need to manage roots for local, temporary
+ * references to such results.
+ */
+ *rval = *invokevp;
+ if (JSVAL_IS_GCTHING(*rval) && *rval != JSVAL_NULL) {
+ if (cx->localRootStack) {
+ if (js_PushLocalRoot(cx, cx->localRootStack, *rval) < 0)
+ ok = JS_FALSE;
+ } else {
+ cx->weakRoots.lastInternalResult = *rval;
+ }
+ }
+ }
+
+ js_FreeStack(cx, mark);
+ return ok;
+}
+
+JSBool
+js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
+ JSAccessMode mode, uintN argc, jsval *argv, jsval *rval)
+{
+ JSSecurityCallbacks *callbacks;
+
+ /*
+ * js_InternalInvoke could result in another try to get or set the same id
+ * again, see bug 355497.
+ */
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ /*
+ * Check general (not object-ops/class-specific) access from the running
+ * script to obj.id only if id has a scripted getter or setter that we're
+ * about to invoke. If we don't check this case, nothing else will -- no
+ * other native code has the chance to check.
+ *
+ * Contrast this non-native (scripted) case with native getter and setter
+ * accesses, where the native itself must do an access check, if security
+ * policies requires it. We make a checkAccess or checkObjectAccess call
+ * back to the embedding program only in those cases where we're not going
+ * to call an embedding-defined native function, getter, setter, or class
+ * hook anyway. Where we do call such a native, there's no need for the
+ * engine to impose a separate access check callback on all embeddings --
+ * many embeddings have no security policy at all.
+ */
+ JS_ASSERT(mode == JSACC_READ || mode == JSACC_WRITE);
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks &&
+ callbacks->checkObjectAccess &&
+ VALUE_IS_FUNCTION(cx, fval) &&
+ FUN_INTERPRETED(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fval))) &&
+ !callbacks->checkObjectAccess(cx, obj, ID_TO_VALUE(id), mode, &fval)) {
+ return JS_FALSE;
+ }
+
+ return js_InternalCall(cx, obj, fval, argc, argv, rval);
+}
+
+JSBool
+js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
+ JSStackFrame *down, uintN flags, jsval *result)
+{
+ JSInterpreterHook hook;
+ void *hookData, *mark;
+ JSStackFrame *oldfp, frame;
+ JSObject *obj, *tmp;
+ JSBool ok;
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_EXECUTE_START_ENABLED())
+ jsdtrace_execute_start(script);
+#endif
+
+ hook = cx->debugHooks->executeHook;
+ hookData = mark = NULL;
+ oldfp = cx->fp;
+ frame.script = script;
+ if (down) {
+ /* Propagate arg state for eval and the debugger API. */
+ frame.callobj = down->callobj;
+ frame.argsobj = down->argsobj;
+ frame.varobj = down->varobj;
+ frame.callee = down->callee;
+ frame.fun = down->fun;
+ frame.thisp = down->thisp;
+ if (down->flags & JSFRAME_COMPUTED_THIS)
+ flags |= JSFRAME_COMPUTED_THIS;
+ frame.argc = down->argc;
+ frame.argv = down->argv;
+ frame.annotation = down->annotation;
+ frame.sharpArray = down->sharpArray;
+ JS_ASSERT(script->nfixed == 0);
+ } else {
+ frame.callobj = frame.argsobj = NULL;
+ obj = chain;
+ if (cx->options & JSOPTION_VAROBJFIX) {
+ while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL)
+ obj = tmp;
+ }
+ frame.varobj = obj;
+ frame.callee = NULL;
+ frame.fun = NULL;
+ frame.thisp = chain;
+ frame.argc = 0;
+ frame.argv = NULL;
+ frame.annotation = NULL;
+ frame.sharpArray = NULL;
+ }
+
+ frame.imacpc = NULL;
+ if (script->nslots != 0) {
+ frame.slots = js_AllocRawStack(cx, script->nslots, &mark);
+ if (!frame.slots) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ memset(frame.slots, 0, script->nfixed * sizeof(jsval));
+ } else {
+ frame.slots = NULL;
+ }
+
+ frame.rval = JSVAL_VOID;
+ frame.down = down;
+ frame.scopeChain = chain;
+ frame.regs = NULL;
+ frame.sharpDepth = 0;
+ frame.flags = flags;
+ frame.dormantNext = NULL;
+ frame.xmlNamespace = NULL;
+ frame.blockChain = NULL;
+
+ /*
+ * Here we wrap the call to js_Interpret with code to (conditionally)
+ * save and restore the old stack frame chain into a chain of 'dormant'
+ * frame chains. Since we are replacing cx->fp, we were running into
+ * the problem that if GC was called under this frame, some of the GC
+ * things associated with the old frame chain (available here only in
+ * the C variable 'oldfp') were not rooted and were being collected.
+ *
+ * So, now we preserve the links to these 'dormant' frame chains in cx
+ * before calling js_Interpret and cleanup afterwards. The GC walks
+ * these dormant chains and marks objects in the same way that it marks
+ * objects in the primary cx->fp chain.
+ */
+ if (oldfp && oldfp != down) {
+ JS_ASSERT(!oldfp->dormantNext);
+ oldfp->dormantNext = cx->dormantFrameChain;
+ cx->dormantFrameChain = oldfp;
+ }
+
+ cx->fp = &frame;
+ if (!down) {
+ OBJ_TO_OUTER_OBJECT(cx, frame.thisp);
+ if (!frame.thisp) {
+ ok = JS_FALSE;
+ goto out2;
+ }
+ frame.flags |= JSFRAME_COMPUTED_THIS;
+ }
+
+ if (hook) {
+ hookData = hook(cx, &frame, JS_TRUE, 0,
+ cx->debugHooks->executeHookData);
+ }
+
+ ok = js_Interpret(cx);
+ if (result)
+ *result = frame.rval;
+
+ if (hookData) {
+ hook = cx->debugHooks->executeHook;
+ if (hook)
+ hook(cx, &frame, JS_FALSE, &ok, hookData);
+ }
+
+out2:
+ if (mark)
+ js_FreeRawStack(cx, mark);
+ cx->fp = oldfp;
+
+ if (oldfp && oldfp != down) {
+ JS_ASSERT(cx->dormantFrameChain == oldfp);
+ cx->dormantFrameChain = oldfp->dormantNext;
+ oldfp->dormantNext = NULL;
+ }
+
+out:
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_EXECUTE_DONE_ENABLED())
+ jsdtrace_execute_done(script);
+#endif
+ return ok;
+}
+
+JSBool
+js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
+ JSObject **objp, JSProperty **propp)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ uintN oldAttrs, report;
+ JSBool isFunction;
+ jsval value;
+ const char *type, *name;
+
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ return JS_FALSE;
+ if (propp) {
+ *objp = obj2;
+ *propp = prop;
+ }
+ if (!prop)
+ return JS_TRUE;
+
+ /*
+ * Use prop as a speedup hint to OBJ_GET_ATTRIBUTES, but drop it on error.
+ * An assertion at label bad: will insist that it is null.
+ */
+ if (!OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &oldAttrs)) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+#ifdef DEBUG
+ prop = NULL;
+#endif
+ goto bad;
+ }
+
+ /*
+ * From here, return true, or else goto bad on failure to null out params.
+ * If our caller doesn't want prop, drop it (we don't need it any longer).
+ */
+ if (!propp) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ prop = NULL;
+ }
+
+ if (attrs == JSPROP_INITIALIZER) {
+ /* Allow the new object to override properties. */
+ if (obj2 != obj)
+ return JS_TRUE;
+ report = JSREPORT_WARNING | JSREPORT_STRICT;
+ } else {
+ /* We allow redeclaring some non-readonly properties. */
+ if (((oldAttrs | attrs) & JSPROP_READONLY) == 0) {
+ /*
+ * Allow redeclaration of variables and functions, but insist that
+ * the new value is not a getter if the old value was, ditto for
+ * setters -- unless prop is impermanent (in which case anyone
+ * could delete it and redefine it, willy-nilly).
+ */
+ if (!(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
+ return JS_TRUE;
+ if ((~(oldAttrs ^ attrs) & (JSPROP_GETTER | JSPROP_SETTER)) == 0)
+ return JS_TRUE;
+ if (!(oldAttrs & JSPROP_PERMANENT))
+ return JS_TRUE;
+ }
+
+ report = JSREPORT_ERROR;
+ isFunction = (oldAttrs & (JSPROP_GETTER | JSPROP_SETTER)) != 0;
+ if (!isFunction) {
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &value))
+ goto bad;
+ isFunction = VALUE_IS_FUNCTION(cx, value);
+ }
+ }
+
+ type = (attrs == JSPROP_INITIALIZER)
+ ? "property"
+ : (oldAttrs & attrs & JSPROP_GETTER)
+ ? js_getter_str
+ : (oldAttrs & attrs & JSPROP_SETTER)
+ ? js_setter_str
+ : (oldAttrs & JSPROP_READONLY)
+ ? js_const_str
+ : isFunction
+ ? js_function_str
+ : js_var_str;
+ name = js_ValueToPrintableString(cx, ID_TO_VALUE(id));
+ if (!name)
+ goto bad;
+ return JS_ReportErrorFlagsAndNumber(cx, report,
+ js_GetErrorMessage, NULL,
+ JSMSG_REDECLARED_VAR,
+ type, name);
+
+bad:
+ if (propp) {
+ *objp = NULL;
+ *propp = NULL;
+ }
+ JS_ASSERT(!prop);
+ return JS_FALSE;
+}
+
+JSBool
+js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval)
+{
+ jsval ltag = JSVAL_TAG(lval), rtag = JSVAL_TAG(rval);
+ jsdouble ld, rd;
+
+ if (ltag == rtag) {
+ if (ltag == JSVAL_STRING) {
+ JSString *lstr = JSVAL_TO_STRING(lval),
+ *rstr = JSVAL_TO_STRING(rval);
+ return js_EqualStrings(lstr, rstr);
+ }
+ if (ltag == JSVAL_DOUBLE) {
+ ld = *JSVAL_TO_DOUBLE(lval);
+ rd = *JSVAL_TO_DOUBLE(rval);
+ return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
+ }
+ if (ltag == JSVAL_OBJECT &&
+ lval != rval &&
+ !JSVAL_IS_NULL(lval) &&
+ !JSVAL_IS_NULL(rval)) {
+ JSObject *lobj, *robj;
+
+ lobj = js_GetWrappedObject(cx, JSVAL_TO_OBJECT(lval));
+ robj = js_GetWrappedObject(cx, JSVAL_TO_OBJECT(rval));
+ lval = OBJECT_TO_JSVAL(lobj);
+ rval = OBJECT_TO_JSVAL(robj);
+ }
+ return lval == rval;
+ }
+ if (ltag == JSVAL_DOUBLE && JSVAL_IS_INT(rval)) {
+ ld = *JSVAL_TO_DOUBLE(lval);
+ rd = JSVAL_TO_INT(rval);
+ return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
+ }
+ if (JSVAL_IS_INT(lval) && rtag == JSVAL_DOUBLE) {
+ ld = JSVAL_TO_INT(lval);
+ rd = *JSVAL_TO_DOUBLE(rval);
+ return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
+ }
+ return lval == rval;
+}
+
+JSBool
+js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp)
+{
+ JSFunction *fun, *fun2;
+ JSObject *obj, *obj2, *proto, *parent;
+ jsval lval, rval;
+ JSClass *clasp;
+
+ fun = NULL;
+ obj2 = NULL;
+ lval = *vp;
+ if (!JSVAL_IS_OBJECT(lval) ||
+ (obj2 = JSVAL_TO_OBJECT(lval)) == NULL ||
+ /* XXX clean up to avoid special cases above ObjectOps layer */
+ OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass ||
+ !obj2->map->ops->construct)
+ {
+ fun = js_ValueToFunction(cx, vp, JSV2F_CONSTRUCT);
+ if (!fun)
+ return JS_FALSE;
+ }
+
+ clasp = &js_ObjectClass;
+ if (!obj2) {
+ proto = parent = NULL;
+ fun = NULL;
+ } else {
+ /*
+ * Get the constructor prototype object for this function.
+ * Use the nominal 'this' parameter slot, vp[1], as a local
+ * root to protect this prototype, in case it has no other
+ * strong refs.
+ */
+ if (!OBJ_GET_PROPERTY(cx, obj2,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &vp[1])) {
+ return JS_FALSE;
+ }
+ rval = vp[1];
+ proto = JSVAL_IS_OBJECT(rval) ? JSVAL_TO_OBJECT(rval) : NULL;
+ parent = OBJ_GET_PARENT(cx, obj2);
+
+ if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) {
+ fun2 = GET_FUNCTION_PRIVATE(cx, obj2);
+ if (!FUN_INTERPRETED(fun2) &&
+ !(fun2->flags & JSFUN_TRACEABLE) &&
+ fun2->u.n.u.clasp) {
+ clasp = fun2->u.n.u.clasp;
+ }
+ }
+ }
+ obj = js_NewObject(cx, clasp, proto, parent, 0);
+ if (!obj)
+ return JS_FALSE;
+
+ /* Now we have an object with a constructor method; call it. */
+ vp[1] = OBJECT_TO_JSVAL(obj);
+ if (!js_Invoke(cx, argc, vp, JSINVOKE_CONSTRUCT)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return JS_FALSE;
+ }
+
+ /* Check the return value and if it's primitive, force it to be obj. */
+ rval = *vp;
+ if (clampReturn && JSVAL_IS_PRIMITIVE(rval)) {
+ if (!fun) {
+ /* native [[Construct]] returning primitive is error */
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_NEW_RESULT,
+ js_ValueToPrintableString(cx, rval));
+ return JS_FALSE;
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ }
+
+ JS_RUNTIME_METER(cx->runtime, constructs);
+ return JS_TRUE;
+}
+
+JSBool
+js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp)
+{
+ JS_ASSERT(!JSVAL_IS_INT(idval));
+
+#if JS_HAS_XML_SUPPORT
+ if (!JSVAL_IS_PRIMITIVE(idval)) {
+ if (OBJECT_IS_XML(cx, obj)) {
+ *idp = OBJECT_JSVAL_TO_JSID(idval);
+ return JS_TRUE;
+ }
+ if (!js_IsFunctionQName(cx, JSVAL_TO_OBJECT(idval), idp))
+ return JS_FALSE;
+ if (*idp != 0)
+ return JS_TRUE;
+ }
+#endif
+
+ return js_ValueToStringId(cx, idval, idp);
+}
+
+/*
+ * Enter the new with scope using an object at sp[-1] and associate the depth
+ * of the with block with sp + stackIndex.
+ */
+JS_STATIC_INTERPRET JSBool
+js_EnterWith(JSContext *cx, jsint stackIndex)
+{
+ JSStackFrame *fp;
+ jsval *sp;
+ JSObject *obj, *parent, *withobj;
+
+ fp = cx->fp;
+ sp = fp->regs->sp;
+ JS_ASSERT(stackIndex < 0);
+ JS_ASSERT(StackBase(fp) <= sp + stackIndex);
+
+ if (!JSVAL_IS_PRIMITIVE(sp[-1])) {
+ obj = JSVAL_TO_OBJECT(sp[-1]);
+ } else {
+ obj = js_ValueToNonNullObject(cx, sp[-1]);
+ if (!obj)
+ return JS_FALSE;
+ sp[-1] = OBJECT_TO_JSVAL(obj);
+ }
+
+ parent = js_GetScopeChain(cx, fp);
+ if (!parent)
+ return JS_FALSE;
+
+ OBJ_TO_INNER_OBJECT(cx, obj);
+ if (!obj)
+ return JS_FALSE;
+
+ withobj = js_NewWithObject(cx, obj, parent,
+ sp + stackIndex - StackBase(fp));
+ if (!withobj)
+ return JS_FALSE;
+
+ fp->scopeChain = withobj;
+ js_DisablePropertyCache(cx);
+ return JS_TRUE;
+}
+
+JS_STATIC_INTERPRET void
+js_LeaveWith(JSContext *cx)
+{
+ JSObject *withobj;
+
+ withobj = cx->fp->scopeChain;
+ JS_ASSERT(OBJ_GET_CLASS(cx, withobj) == &js_WithClass);
+ JS_ASSERT(OBJ_GET_PRIVATE(cx, withobj) == cx->fp);
+ JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);
+ cx->fp->scopeChain = OBJ_GET_PARENT(cx, withobj);
+ JS_SetPrivate(cx, withobj, NULL);
+ js_EnablePropertyCache(cx);
+}
+
+JSClass *
+js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if ((clasp == &js_WithClass || clasp == &js_BlockClass) &&
+ OBJ_GET_PRIVATE(cx, obj) == cx->fp &&
+ OBJ_BLOCK_DEPTH(cx, obj) >= stackDepth) {
+ return clasp;
+ }
+ return NULL;
+}
+
+JS_STATIC_INTERPRET jsint
+js_CountWithBlocks(JSContext *cx, JSStackFrame *fp)
+{
+ jsint n;
+ JSObject *obj;
+ JSClass *clasp;
+
+ n = 0;
+ for (obj = fp->scopeChain;
+ (clasp = js_IsActiveWithOrBlock(cx, obj, 0)) != NULL;
+ obj = OBJ_GET_PARENT(cx, obj)) {
+ if (clasp == &js_WithClass)
+ ++n;
+ }
+ return n;
+}
+
+/*
+ * Unwind block and scope chains to match the given depth. The function sets
+ * fp->sp on return to stackDepth.
+ */
+JSBool
+js_UnwindScope(JSContext *cx, JSStackFrame *fp, jsint stackDepth,
+ JSBool normalUnwind)
+{
+ JSObject *obj;
+ JSClass *clasp;
+
+ JS_ASSERT(stackDepth >= 0);
+ JS_ASSERT(StackBase(fp) + stackDepth <= fp->regs->sp);
+
+ for (obj = fp->blockChain; obj; obj = OBJ_GET_PARENT(cx, obj)) {
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_BlockClass);
+ if (OBJ_BLOCK_DEPTH(cx, obj) < stackDepth)
+ break;
+ }
+ fp->blockChain = obj;
+
+ for (;;) {
+ obj = fp->scopeChain;
+ clasp = js_IsActiveWithOrBlock(cx, obj, stackDepth);
+ if (!clasp)
+ break;
+ if (clasp == &js_BlockClass) {
+ /* Don't fail until after we've updated all stacks. */
+ normalUnwind &= js_PutBlockObject(cx, normalUnwind);
+ } else {
+ js_LeaveWith(cx);
+ }
+ }
+
+ fp->regs->sp = StackBase(fp) + stackDepth;
+ return normalUnwind;
+}
+
+JS_STATIC_INTERPRET JSBool
+js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2)
+{
+ jsval v;
+ jsdouble d;
+
+ v = *vp;
+ if (JSVAL_IS_DOUBLE(v)) {
+ d = *JSVAL_TO_DOUBLE(v);
+ } else if (JSVAL_IS_INT(v)) {
+ d = JSVAL_TO_INT(v);
+ } else {
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_NUMBER(*vp) || *vp == JSVAL_TRUE);
+
+ /* Store the result of v conversion back in vp for post increments. */
+ if ((cs->format & JOF_POST) &&
+ *vp == JSVAL_TRUE
+ && !js_NewNumberInRootedValue(cx, d, vp)) {
+ return JS_FALSE;
+ }
+ }
+
+ (cs->format & JOF_INC) ? d++ : d--;
+ if (!js_NewNumberInRootedValue(cx, d, vp2))
+ return JS_FALSE;
+
+ if (!(cs->format & JOF_POST))
+ *vp = *vp2;
+ return JS_TRUE;
+}
+
+#ifdef DEBUG
+
+JS_STATIC_INTERPRET void
+js_TraceOpcode(JSContext *cx, jsint len)
+{
+ FILE *tracefp;
+ JSStackFrame *fp;
+ JSFrameRegs *regs;
+ JSOp prevop;
+ intN ndefs, n, nuses;
+ jsval *siter;
+ JSString *str;
+ JSOp op;
+
+ tracefp = (FILE *) cx->tracefp;
+ JS_ASSERT(tracefp);
+ fp = cx->fp;
+ regs = fp->regs;
+ if (len != 0) {
+ prevop = (JSOp) regs->pc[-len];
+ ndefs = js_CodeSpec[prevop].ndefs;
+ if (ndefs != 0) {
+ for (n = -ndefs; n < 0; n++) {
+ char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n],
+ NULL);
+ if (bytes) {
+ fprintf(tracefp, "%s %s",
+ (n == -ndefs) ? " output:" : ",",
+ bytes);
+ JS_free(cx, bytes);
+ }
+ }
+ fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));
+ }
+ fprintf(tracefp, " stack: ");
+ for (siter = StackBase(fp); siter < regs->sp; siter++) {
+ str = js_ValueToString(cx, *siter);
+ if (!str)
+ fputs("<null>", tracefp);
+ else
+ js_FileEscapedString(tracefp, str, 0);
+ fputc(' ', tracefp);
+ }
+ fputc('\n', tracefp);
+ }
+
+ fprintf(tracefp, "%4u: ",
+ js_PCToLineNumber(cx, fp->script, fp->imacpc ? fp->imacpc : regs->pc));
+ js_Disassemble1(cx, fp->script, regs->pc,
+ PTRDIFF(regs->pc, fp->script->code, jsbytecode),
+ JS_FALSE, tracefp);
+ op = (JSOp) *regs->pc;
+ nuses = js_CodeSpec[op].nuses;
+ if (nuses != 0) {
+ for (n = -nuses; n < 0; n++) {
+ char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n],
+ NULL);
+ if (bytes) {
+ fprintf(tracefp, "%s %s",
+ (n == -nuses) ? " inputs:" : ",",
+ bytes);
+ JS_free(cx, bytes);
+ }
+ }
+ fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));
+ }
+}
+
+#endif /* DEBUG */
+
+#ifdef JS_OPMETER
+
+# include <stdlib.h>
+
+# define HIST_NSLOTS 8
+
+/*
+ * The second dimension is hardcoded at 256 because we know that many bits fit
+ * in a byte, and mainly to optimize away multiplying by JSOP_LIMIT to address
+ * any particular row.
+ */
+static uint32 succeeds[JSOP_LIMIT][256];
+static uint32 slot_ops[JSOP_LIMIT][HIST_NSLOTS];
+
+JS_STATIC_INTERPRET void
+js_MeterOpcodePair(JSOp op1, JSOp op2)
+{
+ if (op1 != JSOP_STOP)
+ ++succeeds[op1][op2];
+}
+
+JS_STATIC_INTERPRET void
+js_MeterSlotOpcode(JSOp op, uint32 slot)
+{
+ if (slot < HIST_NSLOTS)
+ ++slot_ops[op][slot];
+}
+
+typedef struct Edge {
+ const char *from;
+ const char *to;
+ uint32 count;
+} Edge;
+
+static int
+compare_edges(const void *a, const void *b)
+{
+ const Edge *ea = (const Edge *) a;
+ const Edge *eb = (const Edge *) b;
+
+ return (int32)eb->count - (int32)ea->count;
+}
+
+void
+js_DumpOpMeters()
+{
+ const char *name, *from, *style;
+ FILE *fp;
+ uint32 total, count;
+ uint32 i, j, nedges;
+ Edge *graph;
+
+ name = getenv("JS_OPMETER_FILE");
+ if (!name)
+ name = "/tmp/ops.dot";
+ fp = fopen(name, "w");
+ if (!fp) {
+ perror(name);
+ return;
+ }
+
+ total = nedges = 0;
+ for (i = 0; i < JSOP_LIMIT; i++) {
+ for (j = 0; j < JSOP_LIMIT; j++) {
+ count = succeeds[i][j];
+ if (count != 0) {
+ total += count;
+ ++nedges;
+ }
+ }
+ }
+
+# define SIGNIFICANT(count,total) (200. * (count) >= (total))
+
+ graph = (Edge *) calloc(nedges, sizeof graph[0]);
+ for (i = nedges = 0; i < JSOP_LIMIT; i++) {
+ from = js_CodeName[i];
+ for (j = 0; j < JSOP_LIMIT; j++) {
+ count = succeeds[i][j];
+ if (count != 0 && SIGNIFICANT(count, total)) {
+ graph[nedges].from = from;
+ graph[nedges].to = js_CodeName[j];
+ graph[nedges].count = count;
+ ++nedges;
+ }
+ }
+ }
+ qsort(graph, nedges, sizeof(Edge), compare_edges);
+
+# undef SIGNIFICANT
+
+ fputs("digraph {\n", fp);
+ for (i = 0, style = NULL; i < nedges; i++) {
+ JS_ASSERT(i == 0 || graph[i-1].count >= graph[i].count);
+ if (!style || graph[i-1].count != graph[i].count) {
+ style = (i > nedges * .75) ? "dotted" :
+ (i > nedges * .50) ? "dashed" :
+ (i > nedges * .25) ? "solid" : "bold";
+ }
+ fprintf(fp, " %s -> %s [label=\"%lu\" style=%s]\n",
+ graph[i].from, graph[i].to,
+ (unsigned long)graph[i].count, style);
+ }
+ free(graph);
+ fputs("}\n", fp);
+ fclose(fp);
+
+ name = getenv("JS_OPMETER_HIST");
+ if (!name)
+ name = "/tmp/ops.hist";
+ fp = fopen(name, "w");
+ if (!fp) {
+ perror(name);
+ return;
+ }
+ fputs("bytecode", fp);
+ for (j = 0; j < HIST_NSLOTS; j++)
+ fprintf(fp, " slot %1u", (unsigned)j);
+ putc('\n', fp);
+ fputs("========", fp);
+ for (j = 0; j < HIST_NSLOTS; j++)
+ fputs(" =======", fp);
+ putc('\n', fp);
+ for (i = 0; i < JSOP_LIMIT; i++) {
+ for (j = 0; j < HIST_NSLOTS; j++) {
+ if (slot_ops[i][j] != 0) {
+ /* Reuse j in the next loop, since we break after. */
+ fprintf(fp, "%-8.8s", js_CodeName[i]);
+ for (j = 0; j < HIST_NSLOTS; j++)
+ fprintf(fp, " %7lu", (unsigned long)slot_ops[i][j]);
+ putc('\n', fp);
+ break;
+ }
+ }
+ }
+ fclose(fp);
+}
+
+#endif /* JS_OPSMETER */
+
+#endif /* !JS_LONE_INTERPRET ^ defined jsinvoke_cpp___ */
+
+#ifndef jsinvoke_cpp___
+
+#define PUSH(v) (*regs.sp++ = (v))
+#define PUSH_OPND(v) PUSH(v)
+#define STORE_OPND(n,v) (regs.sp[n] = (v))
+#define POP() (*--regs.sp)
+#define POP_OPND() POP()
+#define FETCH_OPND(n) (regs.sp[n])
+
+/*
+ * Push the jsdouble d using sp from the lexical environment. Try to convert d
+ * to a jsint that fits in a jsval, otherwise GC-alloc space for it and push a
+ * reference.
+ */
+#define STORE_NUMBER(cx, n, d) \
+ JS_BEGIN_MACRO \
+ jsint i_; \
+ \
+ if (JSDOUBLE_IS_INT(d, i_) && INT_FITS_IN_JSVAL(i_)) \
+ regs.sp[n] = INT_TO_JSVAL(i_); \
+ else if (!js_NewDoubleInRootedValue(cx, d, &regs.sp[n])) \
+ goto error; \
+ JS_END_MACRO
+
+#define STORE_INT(cx, n, i) \
+ JS_BEGIN_MACRO \
+ if (INT_FITS_IN_JSVAL(i)) \
+ regs.sp[n] = INT_TO_JSVAL(i); \
+ else if (!js_NewDoubleInRootedValue(cx, (jsdouble) (i), &regs.sp[n])) \
+ goto error; \
+ JS_END_MACRO
+
+#define STORE_UINT(cx, n, u) \
+ JS_BEGIN_MACRO \
+ if ((u) <= JSVAL_INT_MAX) \
+ regs.sp[n] = INT_TO_JSVAL(u); \
+ else if (!js_NewDoubleInRootedValue(cx, (jsdouble) (u), &regs.sp[n])) \
+ goto error; \
+ JS_END_MACRO
+
+#define FETCH_NUMBER(cx, n, d) \
+ JS_BEGIN_MACRO \
+ jsval v_; \
+ \
+ v_ = FETCH_OPND(n); \
+ VALUE_TO_NUMBER(cx, n, v_, d); \
+ JS_END_MACRO
+
+#define FETCH_INT(cx, n, i) \
+ JS_BEGIN_MACRO \
+ jsval v_; \
+ \
+ v_= FETCH_OPND(n); \
+ if (JSVAL_IS_INT(v_)) { \
+ i = JSVAL_TO_INT(v_); \
+ } else { \
+ i = js_ValueToECMAInt32(cx, &regs.sp[n]); \
+ if (JSVAL_IS_NULL(regs.sp[n])) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+#define FETCH_UINT(cx, n, ui) \
+ JS_BEGIN_MACRO \
+ jsval v_; \
+ \
+ v_= FETCH_OPND(n); \
+ if (JSVAL_IS_INT(v_)) { \
+ ui = (uint32) JSVAL_TO_INT(v_); \
+ } else { \
+ ui = js_ValueToECMAUint32(cx, &regs.sp[n]); \
+ if (JSVAL_IS_NULL(regs.sp[n])) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+/*
+ * Optimized conversion macros that test for the desired type in v before
+ * homing sp and calling a conversion function.
+ */
+#define VALUE_TO_NUMBER(cx, n, v, d) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT(v == regs.sp[n]); \
+ if (JSVAL_IS_INT(v)) { \
+ d = (jsdouble)JSVAL_TO_INT(v); \
+ } else if (JSVAL_IS_DOUBLE(v)) { \
+ d = *JSVAL_TO_DOUBLE(v); \
+ } else { \
+ d = js_ValueToNumber(cx, &regs.sp[n]); \
+ if (JSVAL_IS_NULL(regs.sp[n])) \
+ goto error; \
+ JS_ASSERT(JSVAL_IS_NUMBER(regs.sp[n]) || \
+ regs.sp[n] == JSVAL_TRUE); \
+ } \
+ JS_END_MACRO
+
+#define POP_BOOLEAN(cx, v, b) \
+ JS_BEGIN_MACRO \
+ v = FETCH_OPND(-1); \
+ if (v == JSVAL_NULL) { \
+ b = JS_FALSE; \
+ } else if (JSVAL_IS_BOOLEAN(v)) { \
+ b = JSVAL_TO_BOOLEAN(v); \
+ } else { \
+ b = js_ValueToBoolean(v); \
+ } \
+ regs.sp--; \
+ JS_END_MACRO
+
+#define VALUE_TO_OBJECT(cx, n, v, obj) \
+ JS_BEGIN_MACRO \
+ if (!JSVAL_IS_PRIMITIVE(v)) { \
+ obj = JSVAL_TO_OBJECT(v); \
+ } else { \
+ obj = js_ValueToNonNullObject(cx, v); \
+ if (!obj) \
+ goto error; \
+ STORE_OPND(n, OBJECT_TO_JSVAL(obj)); \
+ } \
+ JS_END_MACRO
+
+#define FETCH_OBJECT(cx, n, v, obj) \
+ JS_BEGIN_MACRO \
+ v = FETCH_OPND(n); \
+ VALUE_TO_OBJECT(cx, n, v, obj); \
+ JS_END_MACRO
+
+#define DEFAULT_VALUE(cx, n, hint, v) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v)); \
+ JS_ASSERT(v == regs.sp[n]); \
+ if (!OBJ_DEFAULT_VALUE(cx, JSVAL_TO_OBJECT(v), hint, &regs.sp[n])) \
+ goto error; \
+ v = regs.sp[n]; \
+ JS_END_MACRO
+
+/*
+ * Quickly test if v is an int from the [-2**29, 2**29) range, that is, when
+ * the lowest bit of v is 1 and the bits 30 and 31 are both either 0 or 1. For
+ * such v we can do increment or decrement via adding or subtracting two
+ * without checking that the result overflows JSVAL_INT_MIN or JSVAL_INT_MAX.
+ */
+#define CAN_DO_FAST_INC_DEC(v) (((((v) << 1) ^ v) & 0x80000001) == 1)
+
+JS_STATIC_ASSERT(JSVAL_INT == 1);
+JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MIN)));
+JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MAX)));
+
+/*
+ * Conditional assert to detect failure to clear a pending exception that is
+ * suppressed (or unintentional suppression of a wanted exception).
+ */
+#if defined DEBUG_brendan || defined DEBUG_mrbkap || defined DEBUG_shaver
+# define DEBUG_NOT_THROWING 1
+#endif
+
+#ifdef DEBUG_NOT_THROWING
+# define ASSERT_NOT_THROWING(cx) JS_ASSERT(!(cx)->throwing)
+#else
+# define ASSERT_NOT_THROWING(cx) /* nothing */
+#endif
+
+/*
+ * Define JS_OPMETER to instrument bytecode succession, generating a .dot file
+ * on shutdown that shows the graph of significant predecessor/successor pairs
+ * executed, where the edge labels give the succession counts. The .dot file
+ * is named by the JS_OPMETER_FILE envariable, and defaults to /tmp/ops.dot.
+ *
+ * Bonus feature: JS_OPMETER also enables counters for stack-addressing ops
+ * such as JSOP_GETLOCAL, JSOP_INCARG, via METER_SLOT_OP. The resulting counts
+ * are written to JS_OPMETER_HIST, defaulting to /tmp/ops.hist.
+ */
+#ifndef JS_OPMETER
+# define METER_OP_INIT(op) /* nothing */
+# define METER_OP_PAIR(op1,op2) /* nothing */
+# define METER_SLOT_OP(op,slot) /* nothing */
+#else
+
+/*
+ * The second dimension is hardcoded at 256 because we know that many bits fit
+ * in a byte, and mainly to optimize away multiplying by JSOP_LIMIT to address
+ * any particular row.
+ */
+# define METER_OP_INIT(op) ((op) = JSOP_STOP)
+# define METER_OP_PAIR(op1,op2) (js_MeterOpcodePair(op1, op2))
+# define METER_SLOT_OP(op,slot) (js_MeterSlotOpcode(op, slot))
+
+#endif
+
+#define MAX_INLINE_CALL_COUNT 3000
+
+/*
+ * Threaded interpretation via computed goto appears to be well-supported by
+ * GCC 3 and higher. IBM's C compiler when run with the right options (e.g.,
+ * -qlanglvl=extended) also supports threading. Ditto the SunPro C compiler.
+ * Currently it's broken for JS_VERSION < 160, though this isn't worth fixing.
+ * Add your compiler support macros here.
+ */
+#ifndef JS_THREADED_INTERP
+# if JS_VERSION >= 160 && ( \
+ __GNUC__ >= 3 || \
+ (__IBMC__ >= 700 && defined __IBM_COMPUTED_GOTO) || \
+ __SUNPRO_C >= 0x570)
+# define JS_THREADED_INTERP 1
+# else
+# define JS_THREADED_INTERP 0
+# endif
+#endif
+
+/*
+ * Interpreter assumes the following to implement condition-free interrupt
+ * implementation when !JS_THREADED_INTERP.
+ */
+JS_STATIC_ASSERT(JSOP_INTERRUPT == 0);
+
+/*
+ * Ensure that the intrepreter switch can close call-bytecode cases in the
+ * same way as non-call bytecodes.
+ */
+JS_STATIC_ASSERT(JSOP_NAME_LENGTH == JSOP_CALLNAME_LENGTH);
+JS_STATIC_ASSERT(JSOP_GETGVAR_LENGTH == JSOP_CALLGVAR_LENGTH);
+JS_STATIC_ASSERT(JSOP_GETUPVAR_LENGTH == JSOP_CALLUPVAR_LENGTH);
+JS_STATIC_ASSERT(JSOP_GETARG_LENGTH == JSOP_CALLARG_LENGTH);
+JS_STATIC_ASSERT(JSOP_GETLOCAL_LENGTH == JSOP_CALLLOCAL_LENGTH);
+JS_STATIC_ASSERT(JSOP_XMLNAME_LENGTH == JSOP_CALLXMLNAME_LENGTH);
+
+/*
+ * Same for JSOP_SETNAME and JSOP_SETPROP, which differ only slightly but
+ * remain distinct for the decompiler. Ditto for JSOP_NULL{,THIS}.
+ */
+JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH);
+JS_STATIC_ASSERT(JSOP_NULL_LENGTH == JSOP_NULLTHIS_LENGTH);
+
+/* See TRY_BRANCH_AFTER_COND. */
+JS_STATIC_ASSERT(JSOP_IFNE_LENGTH == JSOP_IFEQ_LENGTH);
+JS_STATIC_ASSERT(JSOP_IFNE == JSOP_IFEQ + 1);
+
+/* For the fastest case inder JSOP_INCNAME, etc. */
+JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_DECNAME_LENGTH);
+JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEINC_LENGTH);
+JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEDEC_LENGTH);
+
+JSBool
+js_Interpret(JSContext *cx)
+{
+ JSRuntime *rt;
+ JSStackFrame *fp;
+ JSScript *script;
+ uintN inlineCallCount;
+ JSAtom **atoms;
+ JSVersion currentVersion, originalVersion;
+ JSFrameRegs regs;
+ JSObject *obj, *obj2, *parent;
+ JSBool ok, cond;
+ jsint len;
+ jsbytecode *endpc, *pc2;
+ JSOp op, op2;
+ jsatomid index;
+ JSAtom *atom;
+ uintN argc, attrs, flags;
+ uint32 slot;
+ jsval *vp, lval, rval, ltmp, rtmp;
+ jsid id;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ JSString *str, *str2;
+ jsint i, j;
+ jsdouble d, d2;
+ JSClass *clasp;
+ JSFunction *fun;
+ JSType type;
+#if JS_THREADED_INTERP
+ register void * const *jumpTable;
+#else
+ register uint32 switchMask;
+ uintN switchOp;
+#endif
+ jsint low, high, off, npairs;
+ JSBool match;
+#if JS_HAS_GETTER_SETTER
+ JSPropertyOp getter, setter;
+#endif
+ JSAutoResolveFlags rf(cx, JSRESOLVE_INFER);
+
+#ifdef __GNUC__
+# define JS_EXTENSION __extension__
+# define JS_EXTENSION_(s) __extension__ ({ s; })
+#else
+# define JS_EXTENSION
+# define JS_EXTENSION_(s) s
+#endif
+
+#if JS_THREADED_INTERP
+ static void *const normalJumpTable[] = {
+# define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ JS_EXTENSION &&L_##op,
+# include "jsopcode.tbl"
+# undef OPDEF
+ };
+
+#ifdef JS_TRACER
+ static void *const recordingJumpTable[] = {
+# define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ JS_EXTENSION &&R_##op,
+# include "jsopcode.tbl"
+# undef OPDEF
+ };
+#endif /* JS_TRACER */
+
+ static void *const interruptJumpTable[] = {
+# define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ JS_EXTENSION &&L_JSOP_INTERRUPT,
+# include "jsopcode.tbl"
+# undef OPDEF
+ };
+
+ METER_OP_INIT(op); /* to nullify first METER_OP_PAIR */
+
+# ifdef JS_TRACER
+# define CHECK_RECORDER() JS_BEGIN_MACRO \
+ JS_ASSERT(!TRACE_RECORDER(cx) ^ \
+ (jumpTable == recordingJumpTable)); \
+ JS_END_MACRO
+# else
+# define CHECK_RECORDER() ((void)0)
+# endif
+
+# define DO_OP() JS_BEGIN_MACRO \
+ CHECK_RECORDER(); \
+ JS_EXTENSION_(goto *jumpTable[op]); \
+ JS_END_MACRO
+# define DO_NEXT_OP(n) JS_BEGIN_MACRO \
+ METER_OP_PAIR(op, regs.pc[n]); \
+ op = (JSOp) *(regs.pc += (n)); \
+ DO_OP(); \
+ JS_END_MACRO
+
+# define BEGIN_CASE(OP) L_##OP: \
+ CHECK_RECORDER();
+# define END_CASE(OP) DO_NEXT_OP(OP##_LENGTH);
+# define END_VARLEN_CASE DO_NEXT_OP(len);
+# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) \
+ JS_ASSERT(js_CodeSpec[OP].length == 1); \
+ op = (JSOp) *++regs.pc; \
+ DO_OP();
+
+# define END_EMPTY_CASES
+
+#else /* !JS_THREADED_INTERP */
+
+# define DO_OP() goto do_op
+# define DO_NEXT_OP(n) JS_BEGIN_MACRO \
+ JS_ASSERT((n) == len); \
+ goto advance_pc; \
+ JS_END_MACRO
+
+# define BEGIN_CASE(OP) case OP:
+# define END_CASE(OP) END_CASE_LEN(OP##_LENGTH)
+# define END_CASE_LEN(n) END_CASE_LENX(n)
+# define END_CASE_LENX(n) END_CASE_LEN##n
+
+/*
+ * To share the code for all len == 1 cases we use the specialized label with
+ * code that falls through to advance_pc: .
+ */
+# define END_CASE_LEN1 goto advance_pc_by_one;
+# define END_CASE_LEN2 len = 2; goto advance_pc;
+# define END_CASE_LEN3 len = 3; goto advance_pc;
+# define END_CASE_LEN4 len = 4; goto advance_pc;
+# define END_CASE_LEN5 len = 5; goto advance_pc;
+# define END_VARLEN_CASE goto advance_pc;
+# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)
+# define END_EMPTY_CASES goto advance_pc_by_one;
+
+#endif /* !JS_THREADED_INTERP */
+
+#ifdef JS_TRACER
+ /* We had better not be entering the interpreter from JIT-compiled code. */
+ TraceRecorder *tr = NULL;
+ if (JS_ON_TRACE(cx)) {
+ tr = TRACE_RECORDER(cx);
+ SET_TRACE_RECORDER(cx, NULL);
+ JS_TRACE_MONITOR(cx).onTrace = JS_FALSE;
+ /*
+ * ON_TRACE means either recording or coming from traced code.
+ * If there's no recorder (the latter case), don't care.
+ */
+ if (tr) {
+ if (tr->wasDeepAborted())
+ tr->removeFragmentoReferences();
+ else
+ tr->pushAbortStack();
+ }
+ }
+#endif
+
+ /* Check for too deep of a native thread stack. */
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ rt = cx->runtime;
+
+ /* Set registerized frame pointer and derived script pointer. */
+ fp = cx->fp;
+ script = fp->script;
+ JS_ASSERT(script->length != 0);
+
+ /* Count of JS function calls that nest in this C js_Interpret frame. */
+ inlineCallCount = 0;
+
+ /*
+ * Initialize the index segment register used by LOAD_ATOM and
+ * GET_FULL_INDEX macros below. As a register we use a pointer based on
+ * the atom map to turn frequently executed LOAD_ATOM into simple array
+ * access. For less frequent object and regexp loads we have to recover
+ * the segment from atoms pointer first.
+ */
+ atoms = script->atomMap.vector;
+
+#define LOAD_ATOM(PCOFF) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT(fp->imacpc \
+ ? atoms == COMMON_ATOMS_START(&rt->atomState) && \
+ GET_INDEX(regs.pc + PCOFF) < js_common_atom_count \
+ : (size_t)(atoms - script->atomMap.vector) < \
+ (size_t)(script->atomMap.length - \
+ GET_INDEX(regs.pc + PCOFF))); \
+ atom = atoms[GET_INDEX(regs.pc + PCOFF)]; \
+ JS_END_MACRO
+
+#define GET_FULL_INDEX(PCOFF) \
+ (atoms - script->atomMap.vector + GET_INDEX(regs.pc + PCOFF))
+
+#define LOAD_OBJECT(PCOFF) \
+ JS_GET_SCRIPT_OBJECT(script, GET_FULL_INDEX(PCOFF), obj)
+
+#define LOAD_FUNCTION(PCOFF) \
+ JS_GET_SCRIPT_FUNCTION(script, GET_FULL_INDEX(PCOFF), fun)
+
+#ifdef JS_TRACER
+
+#define MONITOR_BRANCH() \
+ JS_BEGIN_MACRO \
+ if (TRACING_ENABLED(cx)) { \
+ ENABLE_TRACER(js_MonitorLoopEdge(cx, inlineCallCount)); \
+ fp = cx->fp; \
+ script = fp->script; \
+ atoms = script->atomMap.vector; \
+ currentVersion = (JSVersion) script->version; \
+ JS_ASSERT(fp->regs == &regs); \
+ if (cx->throwing) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+#else /* !JS_TRACER */
+
+#define MONITOR_BRANCH() ((void) 0)
+
+#endif /* !JS_TRACER */
+
+ /*
+ * Prepare to call a user-supplied branch handler, and abort the script
+ * if it returns false.
+ */
+#define CHECK_BRANCH() \
+ JS_BEGIN_MACRO \
+ if ((cx->operationCount -= JSOW_SCRIPT_JUMP) <= 0) { \
+ if (!js_ResetOperationCount(cx)) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+#define BRANCH(n) \
+ JS_BEGIN_MACRO \
+ regs.pc += n; \
+ if (n <= 0) { \
+ CHECK_BRANCH(); \
+ MONITOR_BRANCH(); \
+ } \
+ op = (JSOp) *regs.pc; \
+ DO_OP(); \
+ JS_END_MACRO
+
+ MUST_FLOW_THROUGH("exit");
+ ++cx->interpLevel;
+
+ /*
+ * Optimized Get and SetVersion for proper script language versioning.
+ *
+ * If any native method or JSClass/JSObjectOps hook calls js_SetVersion
+ * and changes cx->version, the effect will "stick" and we will stop
+ * maintaining currentVersion. This is relied upon by testsuites, for
+ * the most part -- web browsers select version before compiling and not
+ * at run-time.
+ */
+ currentVersion = (JSVersion) script->version;
+ originalVersion = (JSVersion) cx->version;
+ if (currentVersion != originalVersion)
+ js_SetVersion(cx, currentVersion);
+
+ /* Update the static-link display. */
+ if (script->staticDepth < JS_DISPLAY_SIZE) {
+ JSStackFrame **disp = &cx->display[script->staticDepth];
+ fp->displaySave = *disp;
+ *disp = fp;
+ }
+#ifdef DEBUG
+ fp->pcDisabledSave = JS_PROPERTY_CACHE(cx).disabled;
+#endif
+
+ /*
+ * Load the debugger's interrupt hook here and after calling out to native
+ * functions (but not to getters, setters, or other native hooks), so we do
+ * not have to reload it each time through the interpreter loop -- we hope
+ * the compiler can keep it in a register when it is non-null.
+ */
+#if JS_THREADED_INTERP
+#ifdef JS_TRACER
+# define LOAD_INTERRUPT_HANDLER(cx) \
+ ((void) (jumpTable = (cx)->debugHooks->interruptHandler \
+ ? interruptJumpTable \
+ : TRACE_RECORDER(cx) \
+ ? recordingJumpTable \
+ : normalJumpTable))
+# define ENABLE_TRACER(flag) \
+ JS_BEGIN_MACRO \
+ bool flag_ = (flag); \
+ JS_ASSERT(flag_ == !!TRACE_RECORDER(cx)); \
+ jumpTable = flag_ ? recordingJumpTable : normalJumpTable; \
+ JS_END_MACRO
+#else /* !JS_TRACER */
+# define LOAD_INTERRUPT_HANDLER(cx) \
+ ((void) (jumpTable = (cx)->debugHooks->interruptHandler \
+ ? interruptJumpTable \
+ : normalJumpTable))
+# define ENABLE_TRACER(flag) ((void)0)
+#endif /* !JS_TRACER */
+#else /* !JS_THREADED_INTERP */
+#ifdef JS_TRACER
+# define LOAD_INTERRUPT_HANDLER(cx) \
+ ((void) (switchMask = ((cx)->debugHooks->interruptHandler || \
+ TRACE_RECORDER(cx)) ? 0 : 255))
+# define ENABLE_TRACER(flag) \
+ JS_BEGIN_MACRO \
+ bool flag_ = (flag); \
+ JS_ASSERT(flag_ == !!TRACE_RECORDER(cx)); \
+ switchMask = flag_ ? 0 : 255; \
+ JS_END_MACRO
+#else /* !JS_TRACER */
+# define LOAD_INTERRUPT_HANDLER(cx) \
+ ((void) (switchMask = ((cx)->debugHooks->interruptHandler \
+ ? 0 : 255)))
+# define ENABLE_TRACER(flag) ((void)0)
+#endif /* !JS_TRACER */
+#endif /* !JS_THREADED_INTERP */
+
+ LOAD_INTERRUPT_HANDLER(cx);
+
+#if !JS_HAS_GENERATORS
+ JS_ASSERT(!fp->regs);
+#else
+ /* Initialize the pc and sp registers unless we're resuming a generator. */
+ if (JS_LIKELY(!fp->regs)) {
+#endif
+ ASSERT_NOT_THROWING(cx);
+ regs.pc = script->code;
+ regs.sp = StackBase(fp);
+ fp->regs = &regs;
+#if JS_HAS_GENERATORS
+ } else {
+ JSGenerator *gen;
+
+ JS_ASSERT(fp->flags & JSFRAME_GENERATOR);
+ gen = FRAME_TO_GENERATOR(fp);
+ JS_ASSERT(fp->regs == &gen->savedRegs);
+ regs = gen->savedRegs;
+ fp->regs = &regs;
+ JS_ASSERT((size_t) (regs.pc - script->code) <= script->length);
+ JS_ASSERT((size_t) (regs.sp - StackBase(fp)) <= StackDepth(script));
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0);
+ JS_PROPERTY_CACHE(cx).disabled += js_CountWithBlocks(cx, fp);
+
+ /*
+ * To support generator_throw and to catch ignored exceptions,
+ * fail if cx->throwing is set.
+ */
+ if (cx->throwing) {
+#ifdef DEBUG_NOT_THROWING
+ if (cx->exception != JSVAL_ARETURN) {
+ printf("JS INTERPRETER CALLED WITH PENDING EXCEPTION %lx\n",
+ (unsigned long) cx->exception);
+ }
+#endif
+ goto error;
+ }
+ }
+#endif /* JS_HAS_GENERATORS */
+
+ /*
+ * It is important that "op" be initialized before calling DO_OP because
+ * it is possible for "op" to be specially assigned during the normal
+ * processing of an opcode while looping. We rely on DO_NEXT_OP to manage
+ * "op" correctly in all other cases.
+ */
+ len = 0;
+ DO_NEXT_OP(len);
+
+#if JS_THREADED_INTERP
+ /*
+ * This is a loop, but it does not look like a loop. The loop-closing
+ * jump is distributed throughout goto *jumpTable[op] inside of DO_OP.
+ * When interrupts are enabled, jumpTable is set to interruptJumpTable
+ * where all jumps point to the JSOP_INTERRUPT case. The latter, after
+ * calling the interrupt handler, dispatches through normalJumpTable to
+ * continue the normal bytecode processing.
+ */
+#else
+ for (;;) {
+ advance_pc_by_one:
+ JS_ASSERT(js_CodeSpec[op].length == 1);
+ len = 1;
+ advance_pc:
+ regs.pc += len;
+ op = (JSOp) *regs.pc;
+#ifdef DEBUG
+ if (cx->tracefp)
+ js_TraceOpcode(cx, len);
+#endif
+
+ do_op:
+ switchOp = op & switchMask;
+ do_switch:
+ switch (switchOp) {
+#endif /* !JS_THREADED_INTERP */
+
+ BEGIN_CASE(JSOP_INTERRUPT)
+ {
+ JSTrapHandler handler;
+
+ handler = cx->debugHooks->interruptHandler;
+ if (handler) {
+ switch (handler(cx, script, regs.pc, &rval,
+ cx->debugHooks->interruptHandlerData)) {
+ case JSTRAP_ERROR:
+ goto error;
+ case JSTRAP_CONTINUE:
+ break;
+ case JSTRAP_RETURN:
+ fp->rval = rval;
+ ok = JS_TRUE;
+ goto forced_return;
+ case JSTRAP_THROW:
+ cx->throwing = JS_TRUE;
+ cx->exception = rval;
+ goto error;
+ default:;
+ }
+#if !JS_THREADED_INTERP
+ } else {
+ /* this was not a real interrupt, the tracer is trying to
+ record a trace */
+ switchOp = op + 256;
+ goto do_switch;
+#endif
+ }
+ LOAD_INTERRUPT_HANDLER(cx);
+
+#if JS_THREADED_INTERP
+ JS_EXTENSION_(goto *normalJumpTable[op]);
+#else
+ switchOp = op;
+ goto do_switch;
+#endif
+ }
+
+ /* No-ops for ease of decompilation. */
+ ADD_EMPTY_CASE(JSOP_NOP)
+ ADD_EMPTY_CASE(JSOP_CONDSWITCH)
+ ADD_EMPTY_CASE(JSOP_TRY)
+ ADD_EMPTY_CASE(JSOP_FINALLY)
+#if JS_HAS_XML_SUPPORT
+ ADD_EMPTY_CASE(JSOP_STARTXML)
+ ADD_EMPTY_CASE(JSOP_STARTXMLEXPR)
+#endif
+ END_EMPTY_CASES
+
+ /* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */
+ BEGIN_CASE(JSOP_LINENO)
+ END_CASE(JSOP_LINENO)
+
+ BEGIN_CASE(JSOP_PUSH)
+ PUSH_OPND(JSVAL_VOID);
+ END_CASE(JSOP_PUSH)
+
+ BEGIN_CASE(JSOP_POP)
+ regs.sp--;
+ END_CASE(JSOP_POP)
+
+ BEGIN_CASE(JSOP_POPN)
+ regs.sp -= GET_UINT16(regs.pc);
+#ifdef DEBUG
+ JS_ASSERT(StackBase(fp) <= regs.sp);
+ obj = fp->blockChain;
+ JS_ASSERT_IF(obj,
+ OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
+ <= (size_t) (regs.sp - StackBase(fp)));
+ for (obj = fp->scopeChain; obj; obj = OBJ_GET_PARENT(cx, obj)) {
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp != &js_BlockClass && clasp != &js_WithClass)
+ continue;
+ if (OBJ_GET_PRIVATE(cx, obj) != fp)
+ break;
+ JS_ASSERT(StackBase(fp) + OBJ_BLOCK_DEPTH(cx, obj)
+ + ((clasp == &js_BlockClass)
+ ? OBJ_BLOCK_COUNT(cx, obj)
+ : 1)
+ <= regs.sp);
+ }
+#endif
+ END_CASE(JSOP_POPN)
+
+ BEGIN_CASE(JSOP_SETRVAL)
+ BEGIN_CASE(JSOP_POPV)
+ ASSERT_NOT_THROWING(cx);
+ fp->rval = POP_OPND();
+ END_CASE(JSOP_POPV)
+
+ BEGIN_CASE(JSOP_ENTERWITH)
+ if (!js_EnterWith(cx, -1))
+ goto error;
+
+ /*
+ * We must ensure that different "with" blocks have different
+ * stack depth associated with them. This allows the try handler
+ * search to properly recover the scope chain. Thus we must keep
+ * the stack at least at the current level.
+ *
+ * We set sp[-1] to the current "with" object to help asserting
+ * the enter/leave balance in [leavewith].
+ */
+ regs.sp[-1] = OBJECT_TO_JSVAL(fp->scopeChain);
+ END_CASE(JSOP_ENTERWITH)
+
+ BEGIN_CASE(JSOP_LEAVEWITH)
+ JS_ASSERT(regs.sp[-1] == OBJECT_TO_JSVAL(fp->scopeChain));
+ regs.sp--;
+ js_LeaveWith(cx);
+ END_CASE(JSOP_LEAVEWITH)
+
+ BEGIN_CASE(JSOP_RETURN)
+ CHECK_BRANCH();
+ fp->rval = POP_OPND();
+ /* FALL THROUGH */
+
+ BEGIN_CASE(JSOP_RETRVAL) /* fp->rval already set */
+ BEGIN_CASE(JSOP_STOP)
+ /*
+ * When the inlined frame exits with an exception or an error, ok
+ * will be false after the inline_return label.
+ */
+ ASSERT_NOT_THROWING(cx);
+
+ if (fp->imacpc) {
+ /*
+ * If we are at the end of an imacro, return to its caller in
+ * the current frame.
+ */
+ JS_ASSERT(op == JSOP_STOP);
+
+ end_imacro:
+ JS_ASSERT((uintN)(regs.sp - fp->slots) <= script->nslots);
+ regs.pc = fp->imacpc + js_CodeSpec[*fp->imacpc].length;
+ fp->imacpc = NULL;
+ atoms = script->atomMap.vector;
+ op = JSOp(*regs.pc);
+ DO_OP();
+ }
+
+ JS_ASSERT(regs.sp == StackBase(fp));
+ if ((fp->flags & JSFRAME_CONSTRUCTING) &&
+ JSVAL_IS_PRIMITIVE(fp->rval)) {
+ if (!fp->fun) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_NEW_RESULT,
+ js_ValueToPrintableString(cx, rval));
+ goto error;
+ }
+ fp->rval = OBJECT_TO_JSVAL(fp->thisp);
+ }
+ ok = JS_TRUE;
+ if (inlineCallCount)
+ inline_return:
+ {
+ JSInlineFrame *ifp = (JSInlineFrame *) fp;
+ void *hookData = ifp->hookData;
+
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled == fp->pcDisabledSave);
+ JS_ASSERT(!fp->blockChain);
+ JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->scopeChain, 0));
+
+ if (script->staticDepth < JS_DISPLAY_SIZE)
+ cx->display[script->staticDepth] = fp->displaySave;
+
+ if (hookData) {
+ JSInterpreterHook hook;
+ JSBool status;
+
+ hook = cx->debugHooks->callHook;
+ if (hook) {
+ /*
+ * Do not pass &ok directly as exposing the address
+ * inhibits optimizations and uninitialised warnings.
+ */
+ status = ok;
+ hook(cx, fp, JS_FALSE, &status, hookData);
+ ok = status;
+ LOAD_INTERRUPT_HANDLER(cx);
+ }
+ }
+
+ /*
+ * If fp has a call object, sync values and clear the back-
+ * pointer. This can happen for a lightweight function if it
+ * calls eval unexpectedly (in a way that is hidden from the
+ * compiler). See bug 325540.
+ */
+ if (fp->callobj)
+ ok &= js_PutCallObject(cx, fp);
+
+ if (fp->argsobj)
+ ok &= js_PutArgsObject(cx, fp);
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ /* DTrace function return, inlines */
+ if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
+ jsdtrace_function_rval(cx, fp, fp->fun);
+ if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
+ jsdtrace_function_return(cx, fp, fp->fun);
+#endif
+
+ /* Restore context version only if callee hasn't set version. */
+ if (JS_LIKELY(cx->version == currentVersion)) {
+ currentVersion = ifp->callerVersion;
+ if (currentVersion != cx->version)
+ js_SetVersion(cx, currentVersion);
+ }
+
+ /*
+ * If inline-constructing, replace primitive rval with the new
+ * object passed in via |this|, and instrument this constructor
+ * invocation
+ */
+ if (fp->flags & JSFRAME_CONSTRUCTING) {
+ if (JSVAL_IS_PRIMITIVE(fp->rval))
+ fp->rval = OBJECT_TO_JSVAL(fp->thisp);
+ JS_RUNTIME_METER(cx->runtime, constructs);
+ }
+
+ /* Restore caller's registers. */
+ regs = ifp->callerRegs;
+
+ /* Store the return value in the caller's operand frame. */
+ regs.sp -= 1 + (size_t) ifp->frame.argc;
+ regs.sp[-1] = fp->rval;
+
+ /* Restore cx->fp and release the inline frame's space. */
+ cx->fp = fp = fp->down;
+ JS_ASSERT(fp->regs == &ifp->callerRegs);
+ fp->regs = &regs;
+ JS_ARENA_RELEASE(&cx->stackPool, ifp->mark);
+
+ /* Restore the calling script's interpreter registers. */
+ script = fp->script;
+ atoms = script->atomMap.vector;
+
+ /* Resume execution in the calling frame. */
+ inlineCallCount--;
+ if (JS_LIKELY(ok)) {
+ TRACE_0(LeaveFrame);
+ JS_ASSERT(js_CodeSpec[*regs.pc].length == JSOP_CALL_LENGTH);
+ len = JSOP_CALL_LENGTH;
+ DO_NEXT_OP(len);
+ }
+ goto error;
+ }
+ goto exit;
+
+ BEGIN_CASE(JSOP_DEFAULT)
+ (void) POP();
+ /* FALL THROUGH */
+ BEGIN_CASE(JSOP_GOTO)
+ len = GET_JUMP_OFFSET(regs.pc);
+ BRANCH(len);
+ END_CASE(JSOP_GOTO)
+
+ BEGIN_CASE(JSOP_IFEQ)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_FALSE) {
+ len = GET_JUMP_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ END_CASE(JSOP_IFEQ)
+
+ BEGIN_CASE(JSOP_IFNE)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond != JS_FALSE) {
+ len = GET_JUMP_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ END_CASE(JSOP_IFNE)
+
+ BEGIN_CASE(JSOP_OR)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_TRUE) {
+ len = GET_JUMP_OFFSET(regs.pc);
+ PUSH_OPND(rval);
+ DO_NEXT_OP(len);
+ }
+ END_CASE(JSOP_OR)
+
+ BEGIN_CASE(JSOP_AND)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_FALSE) {
+ len = GET_JUMP_OFFSET(regs.pc);
+ PUSH_OPND(rval);
+ DO_NEXT_OP(len);
+ }
+ END_CASE(JSOP_AND)
+
+ BEGIN_CASE(JSOP_DEFAULTX)
+ (void) POP();
+ /* FALL THROUGH */
+ BEGIN_CASE(JSOP_GOTOX)
+ len = GET_JUMPX_OFFSET(regs.pc);
+ BRANCH(len);
+ END_CASE(JSOP_GOTOX);
+
+ BEGIN_CASE(JSOP_IFEQX)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_FALSE) {
+ len = GET_JUMPX_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ END_CASE(JSOP_IFEQX)
+
+ BEGIN_CASE(JSOP_IFNEX)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond != JS_FALSE) {
+ len = GET_JUMPX_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ END_CASE(JSOP_IFNEX)
+
+ BEGIN_CASE(JSOP_ORX)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_TRUE) {
+ len = GET_JUMPX_OFFSET(regs.pc);
+ PUSH_OPND(rval);
+ DO_NEXT_OP(len);
+ }
+ END_CASE(JSOP_ORX)
+
+ BEGIN_CASE(JSOP_ANDX)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_FALSE) {
+ len = GET_JUMPX_OFFSET(regs.pc);
+ PUSH_OPND(rval);
+ DO_NEXT_OP(len);
+ }
+ END_CASE(JSOP_ANDX)
+
+/*
+ * If the index value at sp[n] is not an int that fits in a jsval, it could
+ * be an object (an XML QName, AttributeName, or AnyName), but only if we are
+ * compiling with JS_HAS_XML_SUPPORT. Otherwise convert the index value to a
+ * string atom id.
+ */
+#define FETCH_ELEMENT_ID(obj, n, id) \
+ JS_BEGIN_MACRO \
+ jsval idval_ = FETCH_OPND(n); \
+ if (JSVAL_IS_INT(idval_)) { \
+ id = INT_JSVAL_TO_JSID(idval_); \
+ } else { \
+ if (!js_InternNonIntElementId(cx, obj, idval_, &id)) \
+ goto error; \
+ regs.sp[n] = ID_TO_VALUE(id); \
+ } \
+ JS_END_MACRO
+
+#define TRY_BRANCH_AFTER_COND(cond,spdec) \
+ JS_BEGIN_MACRO \
+ uintN diff_; \
+ JS_ASSERT(js_CodeSpec[op].length == 1); \
+ diff_ = (uintN) regs.pc[1] - (uintN) JSOP_IFEQ; \
+ if (diff_ <= 1) { \
+ regs.sp -= spdec; \
+ if (cond == (diff_ != 0)) { \
+ ++regs.pc; \
+ len = GET_JUMP_OFFSET(regs.pc); \
+ BRANCH(len); \
+ } \
+ len = 1 + JSOP_IFEQ_LENGTH; \
+ DO_NEXT_OP(len); \
+ } \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_IN)
+ rval = FETCH_OPND(-1);
+ if (JSVAL_IS_PRIMITIVE(rval)) {
+ js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rval, NULL);
+ goto error;
+ }
+ obj = JSVAL_TO_OBJECT(rval);
+ FETCH_ELEMENT_ID(obj, -2, id);
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ goto error;
+ cond = prop != NULL;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ TRY_BRANCH_AFTER_COND(cond, 2);
+ regs.sp--;
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));
+ END_CASE(JSOP_IN)
+
+ BEGIN_CASE(JSOP_ITER)
+ JS_ASSERT(regs.sp > StackBase(fp));
+ flags = regs.pc[1];
+ if (!js_ValueToIterator(cx, flags, &regs.sp[-1]))
+ goto error;
+ LOAD_INTERRUPT_HANDLER(cx);
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-1]));
+ PUSH(JSVAL_VOID);
+ END_CASE(JSOP_ITER)
+
+ BEGIN_CASE(JSOP_NEXTITER)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-2]));
+ if (!js_CallIteratorNext(cx, JSVAL_TO_OBJECT(regs.sp[-2]), &regs.sp[-1]))
+ goto error;
+ LOAD_INTERRUPT_HANDLER(cx);
+ rval = BOOLEAN_TO_JSVAL(regs.sp[-1] != JSVAL_HOLE);
+ PUSH(rval);
+ TRACE_0(IteratorNextComplete);
+ END_CASE(JSOP_NEXTITER)
+
+ BEGIN_CASE(JSOP_ENDITER)
+ /*
+ * Decrease the stack pointer even when !ok -- see comments in the
+ * exception capturing code for details.
+ */
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ ok = js_CloseIterator(cx, regs.sp[-2]);
+ regs.sp -= 2;
+ if (!ok)
+ goto error;
+ END_CASE(JSOP_ENDITER)
+
+ BEGIN_CASE(JSOP_FORARG)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ slot = GET_ARGNO(regs.pc);
+ JS_ASSERT(slot < fp->fun->nargs);
+ fp->argv[slot] = regs.sp[-1];
+ END_CASE(JSOP_FORARG)
+
+ BEGIN_CASE(JSOP_FORLOCAL)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < fp->script->nslots);
+ vp = &fp->slots[slot];
+ GC_POKE(cx, *vp);
+ *vp = regs.sp[-1];
+ END_CASE(JSOP_FORLOCAL)
+
+ BEGIN_CASE(JSOP_FORNAME)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
+ goto error;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-1]);
+ if (!ok)
+ goto error;
+ END_CASE(JSOP_FORNAME)
+
+ BEGIN_CASE(JSOP_FORPROP)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ FETCH_OBJECT(cx, -1, lval, obj);
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-2]);
+ if (!ok)
+ goto error;
+ regs.sp--;
+ END_CASE(JSOP_FORPROP)
+
+ BEGIN_CASE(JSOP_FORELEM)
+ /*
+ * JSOP_FORELEM simply dups the property identifier at top of stack
+ * and lets the subsequent JSOP_ENUMELEM opcode sequence handle the
+ * left-hand side expression evaluation and assignment. This opcode
+ * exists solely to help the decompiler.
+ */
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ rval = FETCH_OPND(-1);
+ PUSH(rval);
+ END_CASE(JSOP_FORELEM)
+
+ BEGIN_CASE(JSOP_DUP)
+ JS_ASSERT(regs.sp > StackBase(fp));
+ rval = FETCH_OPND(-1);
+ PUSH(rval);
+ END_CASE(JSOP_DUP)
+
+ BEGIN_CASE(JSOP_DUP2)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ lval = FETCH_OPND(-2);
+ rval = FETCH_OPND(-1);
+ PUSH(lval);
+ PUSH(rval);
+ END_CASE(JSOP_DUP2)
+
+ BEGIN_CASE(JSOP_SWAP)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ lval = FETCH_OPND(-2);
+ rval = FETCH_OPND(-1);
+ STORE_OPND(-1, lval);
+ STORE_OPND(-2, rval);
+ END_CASE(JSOP_SWAP)
+
+#define PROPERTY_OP(n, call) \
+ JS_BEGIN_MACRO \
+ /* Fetch the left part and resolve it to a non-null object. */ \
+ FETCH_OBJECT(cx, n, lval, obj); \
+ \
+ /* Get or set the property. */ \
+ if (!call) \
+ goto error; \
+ JS_END_MACRO
+
+#define ELEMENT_OP(n, call) \
+ JS_BEGIN_MACRO \
+ /* Fetch the left part and resolve it to a non-null object. */ \
+ FETCH_OBJECT(cx, n - 1, lval, obj); \
+ \
+ /* Fetch index and convert it to id suitable for use with obj. */ \
+ FETCH_ELEMENT_ID(obj, n, id); \
+ \
+ /* Get or set the element. */ \
+ if (!call) \
+ goto error; \
+ JS_END_MACRO
+
+#define NATIVE_GET(cx,obj,pobj,sprop,vp) \
+ JS_BEGIN_MACRO \
+ if (SPROP_HAS_STUB_GETTER(sprop)) { \
+ /* Fast path for Object instance properties. */ \
+ JS_ASSERT((sprop)->slot != SPROP_INVALID_SLOT || \
+ !SPROP_HAS_STUB_SETTER(sprop)); \
+ *vp = ((sprop)->slot != SPROP_INVALID_SLOT) \
+ ? LOCKED_OBJ_GET_SLOT(pobj, (sprop)->slot) \
+ : JSVAL_VOID; \
+ } else { \
+ if (!js_NativeGet(cx, obj, pobj, sprop, vp)) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+#define NATIVE_SET(cx,obj,sprop,vp) \
+ JS_BEGIN_MACRO \
+ if (SPROP_HAS_STUB_SETTER(sprop) && \
+ (sprop)->slot != SPROP_INVALID_SLOT) { \
+ /* Fast path for, e.g., Object instance properties. */ \
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, (sprop)->slot, *vp); \
+ } else { \
+ if (!js_NativeSet(cx, obj, sprop, vp)) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+/*
+ * Deadlocks or else bad races are likely if JS_THREADSAFE, so we must rely on
+ * single-thread DEBUG js shell testing to verify property cache hits.
+ */
+#if defined DEBUG && !defined JS_THREADSAFE
+# define ASSERT_VALID_PROPERTY_CACHE_HIT(pcoff,obj,pobj,entry) \
+ do { \
+ JSAtom *atom_; \
+ JSObject *obj_, *pobj_; \
+ JSProperty *prop_; \
+ JSScopeProperty *sprop_; \
+ uint32 sample_ = rt->gcNumber; \
+ if (pcoff >= 0) \
+ GET_ATOM_FROM_BYTECODE(script, regs.pc, pcoff, atom_); \
+ else \
+ atom_ = rt->atomState.lengthAtom; \
+ if (JOF_OPMODE(*regs.pc) == JOF_NAME) { \
+ ok = js_FindProperty(cx, ATOM_TO_JSID(atom_), &obj_, &pobj_, \
+ &prop_); \
+ } else { \
+ obj_ = obj; \
+ ok = js_LookupProperty(cx, obj, ATOM_TO_JSID(atom_), &pobj_, \
+ &prop_); \
+ } \
+ if (!ok) \
+ goto error; \
+ if (rt->gcNumber != sample_) \
+ break; \
+ JS_ASSERT(prop_); \
+ JS_ASSERT(pobj_ == pobj); \
+ sprop_ = (JSScopeProperty *) prop_; \
+ if (PCVAL_IS_SLOT(entry->vword)) { \
+ JS_ASSERT(PCVAL_TO_SLOT(entry->vword) == sprop_->slot); \
+ } else if (PCVAL_IS_SPROP(entry->vword)) { \
+ JS_ASSERT(PCVAL_TO_SPROP(entry->vword) == sprop_); \
+ } else { \
+ jsval v_; \
+ JS_ASSERT(PCVAL_IS_OBJECT(entry->vword)); \
+ JS_ASSERT(entry->vword != PCVAL_NULL); \
+ JS_ASSERT(SCOPE_IS_BRANDED(OBJ_SCOPE(pobj))); \
+ JS_ASSERT(SPROP_HAS_STUB_GETTER(sprop_)); \
+ JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop_, OBJ_SCOPE(pobj_))); \
+ v_ = LOCKED_OBJ_GET_SLOT(pobj_, sprop_->slot); \
+ JS_ASSERT(VALUE_IS_FUNCTION(cx, v_)); \
+ JS_ASSERT(PCVAL_TO_OBJECT(entry->vword) == JSVAL_TO_OBJECT(v_)); \
+ } \
+ OBJ_DROP_PROPERTY(cx, pobj_, prop_); \
+ } while (0)
+#else
+# define ASSERT_VALID_PROPERTY_CACHE_HIT(pcoff,obj,pobj,entry) ((void) 0)
+#endif
+
+/*
+ * Skip the JSOP_POP typically found after a JSOP_SET* opcode, where oplen is
+ * the constant length of the SET opcode sequence, and spdec is the constant
+ * by which to decrease the stack pointer to pop all of the SET op's operands.
+ *
+ * NB: unlike macros that could conceivably be replaced by functions (ignoring
+ * goto error), where a call should not have to be braced in order to expand
+ * correctly (e.g., in if (cond) FOO(); else BAR()), these three macros lack
+ * JS_{BEGIN,END}_MACRO brackets. They are also indented so as to align with
+ * nearby opcode code.
+ */
+#define SKIP_POP_AFTER_SET(oplen,spdec) \
+ if (regs.pc[oplen] == JSOP_POP) { \
+ regs.sp -= spdec; \
+ regs.pc += oplen + JSOP_POP_LENGTH; \
+ op = (JSOp) *regs.pc; \
+ DO_OP(); \
+ }
+
+#define END_SET_CASE(OP) \
+ SKIP_POP_AFTER_SET(OP##_LENGTH, 1); \
+ END_CASE(OP)
+
+#define END_SET_CASE_STORE_RVAL(OP,spdec) \
+ SKIP_POP_AFTER_SET(OP##_LENGTH, spdec); \
+ rval = FETCH_OPND(-1); \
+ regs.sp -= (spdec) - 1; \
+ STORE_OPND(-1, rval); \
+ END_CASE(OP)
+
+ BEGIN_CASE(JSOP_SETCONST)
+ LOAD_ATOM(0);
+ obj = fp->varobj;
+ rval = FETCH_OPND(-1);
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval,
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_ENUMERATE | JSPROP_PERMANENT |
+ JSPROP_READONLY,
+ NULL)) {
+ goto error;
+ }
+ END_SET_CASE(JSOP_SETCONST);
+
+#if JS_HAS_DESTRUCTURING
+ BEGIN_CASE(JSOP_ENUMCONSTELEM)
+ rval = FETCH_OPND(-3);
+ FETCH_OBJECT(cx, -2, lval, obj);
+ FETCH_ELEMENT_ID(obj, -1, id);
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, id, rval,
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_ENUMERATE | JSPROP_PERMANENT |
+ JSPROP_READONLY,
+ NULL)) {
+ goto error;
+ }
+ regs.sp -= 3;
+ END_CASE(JSOP_ENUMCONSTELEM)
+#endif
+
+ BEGIN_CASE(JSOP_BINDNAME)
+ do {
+ JSPropCacheEntry *entry;
+
+ obj = fp->scopeChain;
+ if (JS_LIKELY(OBJ_IS_NATIVE(obj))) {
+ PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);
+ if (!atom) {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
+ JS_UNLOCK_OBJ(cx, obj2);
+ break;
+ }
+ } else {
+ entry = NULL;
+ LOAD_ATOM(0);
+ }
+ id = ATOM_TO_JSID(atom);
+ obj = js_FindIdentifierBase(cx, id, entry);
+ if (!obj)
+ goto error;
+ } while (0);
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_BINDNAME)
+
+ BEGIN_CASE(JSOP_IMACOP)
+ JS_ASSERT(JS_UPTRDIFF(fp->imacpc, script->code) < script->length);
+ op = JSOp(*fp->imacpc);
+ DO_OP();
+
+#define BITWISE_OP(OP) \
+ JS_BEGIN_MACRO \
+ FETCH_INT(cx, -2, i); \
+ FETCH_INT(cx, -1, j); \
+ i = i OP j; \
+ regs.sp--; \
+ STORE_INT(cx, -1, i); \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_BITOR)
+ BITWISE_OP(|);
+ END_CASE(JSOP_BITOR)
+
+ BEGIN_CASE(JSOP_BITXOR)
+ BITWISE_OP(^);
+ END_CASE(JSOP_BITXOR)
+
+ BEGIN_CASE(JSOP_BITAND)
+ BITWISE_OP(&);
+ END_CASE(JSOP_BITAND)
+
+#define RELATIONAL_OP(OP) \
+ JS_BEGIN_MACRO \
+ rval = FETCH_OPND(-1); \
+ lval = FETCH_OPND(-2); \
+ /* Optimize for two int-tagged operands (typical loop control). */ \
+ if ((lval & rval) & JSVAL_INT) { \
+ cond = JSVAL_TO_INT(lval) OP JSVAL_TO_INT(rval); \
+ } else { \
+ if (!JSVAL_IS_PRIMITIVE(lval)) \
+ DEFAULT_VALUE(cx, -2, JSTYPE_NUMBER, lval); \
+ if (!JSVAL_IS_PRIMITIVE(rval)) \
+ DEFAULT_VALUE(cx, -1, JSTYPE_NUMBER, rval); \
+ if (JSVAL_IS_STRING(lval) && JSVAL_IS_STRING(rval)) { \
+ str = JSVAL_TO_STRING(lval); \
+ str2 = JSVAL_TO_STRING(rval); \
+ cond = js_CompareStrings(str, str2) OP 0; \
+ } else { \
+ VALUE_TO_NUMBER(cx, -2, lval, d); \
+ VALUE_TO_NUMBER(cx, -1, rval, d2); \
+ cond = JSDOUBLE_COMPARE(d, OP, d2, JS_FALSE); \
+ } \
+ } \
+ TRY_BRANCH_AFTER_COND(cond, 2); \
+ regs.sp--; \
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \
+ JS_END_MACRO
+
+/*
+ * NB: These macros can't use JS_BEGIN_MACRO/JS_END_MACRO around their bodies
+ * because they begin if/else chains, so callers must not put semicolons after
+ * the call expressions!
+ */
+#if JS_HAS_XML_SUPPORT
+#define XML_EQUALITY_OP(OP) \
+ if ((ltmp == JSVAL_OBJECT && \
+ (obj2 = JSVAL_TO_OBJECT(lval)) && \
+ OBJECT_IS_XML(cx, obj2)) || \
+ (rtmp == JSVAL_OBJECT && \
+ (obj2 = JSVAL_TO_OBJECT(rval)) && \
+ OBJECT_IS_XML(cx, obj2))) { \
+ JSXMLObjectOps *ops; \
+ \
+ ops = (JSXMLObjectOps *) obj2->map->ops; \
+ if (obj2 == JSVAL_TO_OBJECT(rval)) \
+ rval = lval; \
+ if (!ops->equality(cx, obj2, rval, &cond)) \
+ goto error; \
+ cond = cond OP JS_TRUE; \
+ } else
+
+#define EXTENDED_EQUALITY_OP(OP) \
+ if (ltmp == JSVAL_OBJECT && \
+ (obj2 = JSVAL_TO_OBJECT(lval)) && \
+ ((clasp = OBJ_GET_CLASS(cx, obj2))->flags & JSCLASS_IS_EXTENDED)) { \
+ JSExtendedClass *xclasp; \
+ \
+ xclasp = (JSExtendedClass *) clasp; \
+ if (!xclasp->equality(cx, obj2, rval, &cond)) \
+ goto error; \
+ cond = cond OP JS_TRUE; \
+ } else
+#else
+#define XML_EQUALITY_OP(OP) /* nothing */
+#define EXTENDED_EQUALITY_OP(OP) /* nothing */
+#endif
+
+#define EQUALITY_OP(OP, IFNAN) \
+ JS_BEGIN_MACRO \
+ rval = FETCH_OPND(-1); \
+ lval = FETCH_OPND(-2); \
+ ltmp = JSVAL_TAG(lval); \
+ rtmp = JSVAL_TAG(rval); \
+ XML_EQUALITY_OP(OP) \
+ if (ltmp == rtmp) { \
+ if (ltmp == JSVAL_STRING) { \
+ str = JSVAL_TO_STRING(lval); \
+ str2 = JSVAL_TO_STRING(rval); \
+ cond = js_EqualStrings(str, str2) OP JS_TRUE; \
+ } else if (ltmp == JSVAL_DOUBLE) { \
+ d = *JSVAL_TO_DOUBLE(lval); \
+ d2 = *JSVAL_TO_DOUBLE(rval); \
+ cond = JSDOUBLE_COMPARE(d, OP, d2, IFNAN); \
+ } else { \
+ EXTENDED_EQUALITY_OP(OP) \
+ /* Handle all undefined (=>NaN) and int combinations. */ \
+ cond = lval OP rval; \
+ } \
+ } else { \
+ if (JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval)) { \
+ cond = (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) OP 1; \
+ } else if (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) { \
+ cond = 1 OP 0; \
+ } else { \
+ if (ltmp == JSVAL_OBJECT) { \
+ DEFAULT_VALUE(cx, -2, JSTYPE_VOID, lval); \
+ ltmp = JSVAL_TAG(lval); \
+ } else if (rtmp == JSVAL_OBJECT) { \
+ DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval); \
+ rtmp = JSVAL_TAG(rval); \
+ } \
+ if (ltmp == JSVAL_STRING && rtmp == JSVAL_STRING) { \
+ str = JSVAL_TO_STRING(lval); \
+ str2 = JSVAL_TO_STRING(rval); \
+ cond = js_EqualStrings(str, str2) OP JS_TRUE; \
+ } else { \
+ VALUE_TO_NUMBER(cx, -2, lval, d); \
+ VALUE_TO_NUMBER(cx, -1, rval, d2); \
+ cond = JSDOUBLE_COMPARE(d, OP, d2, IFNAN); \
+ } \
+ } \
+ } \
+ TRY_BRANCH_AFTER_COND(cond, 2); \
+ regs.sp--; \
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_EQ)
+ EQUALITY_OP(==, JS_FALSE);
+ END_CASE(JSOP_EQ)
+
+ BEGIN_CASE(JSOP_NE)
+ EQUALITY_OP(!=, JS_TRUE);
+ END_CASE(JSOP_NE)
+
+#define STRICT_EQUALITY_OP(OP) \
+ JS_BEGIN_MACRO \
+ rval = FETCH_OPND(-1); \
+ lval = FETCH_OPND(-2); \
+ cond = js_StrictlyEqual(cx, lval, rval) OP JS_TRUE; \
+ regs.sp--; \
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_STRICTEQ)
+ STRICT_EQUALITY_OP(==);
+ END_CASE(JSOP_STRICTEQ)
+
+ BEGIN_CASE(JSOP_STRICTNE)
+ STRICT_EQUALITY_OP(!=);
+ END_CASE(JSOP_STRICTNE)
+
+ BEGIN_CASE(JSOP_CASE)
+ STRICT_EQUALITY_OP(==);
+ (void) POP();
+ if (cond) {
+ len = GET_JUMP_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ PUSH(lval);
+ END_CASE(JSOP_CASE)
+
+ BEGIN_CASE(JSOP_CASEX)
+ STRICT_EQUALITY_OP(==);
+ (void) POP();
+ if (cond) {
+ len = GET_JUMPX_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ PUSH(lval);
+ END_CASE(JSOP_CASEX)
+
+ BEGIN_CASE(JSOP_LT)
+ RELATIONAL_OP(<);
+ END_CASE(JSOP_LT)
+
+ BEGIN_CASE(JSOP_LE)
+ RELATIONAL_OP(<=);
+ END_CASE(JSOP_LE)
+
+ BEGIN_CASE(JSOP_GT)
+ RELATIONAL_OP(>);
+ END_CASE(JSOP_GT)
+
+ BEGIN_CASE(JSOP_GE)
+ RELATIONAL_OP(>=);
+ END_CASE(JSOP_GE)
+
+#undef EQUALITY_OP
+#undef RELATIONAL_OP
+
+#define SIGNED_SHIFT_OP(OP) \
+ JS_BEGIN_MACRO \
+ FETCH_INT(cx, -2, i); \
+ FETCH_INT(cx, -1, j); \
+ i = i OP (j & 31); \
+ regs.sp--; \
+ STORE_INT(cx, -1, i); \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_LSH)
+ SIGNED_SHIFT_OP(<<);
+ END_CASE(JSOP_LSH)
+
+ BEGIN_CASE(JSOP_RSH)
+ SIGNED_SHIFT_OP(>>);
+ END_CASE(JSOP_RSH)
+
+ BEGIN_CASE(JSOP_URSH)
+ {
+ uint32 u;
+
+ FETCH_UINT(cx, -2, u);
+ FETCH_INT(cx, -1, j);
+ u >>= (j & 31);
+ regs.sp--;
+ STORE_UINT(cx, -1, u);
+ }
+ END_CASE(JSOP_URSH)
+
+#undef BITWISE_OP
+#undef SIGNED_SHIFT_OP
+
+ BEGIN_CASE(JSOP_ADD)
+ rval = FETCH_OPND(-1);
+ lval = FETCH_OPND(-2);
+#if JS_HAS_XML_SUPPORT
+ if (!JSVAL_IS_PRIMITIVE(lval) &&
+ (obj2 = JSVAL_TO_OBJECT(lval), OBJECT_IS_XML(cx, obj2)) &&
+ VALUE_IS_XML(cx, rval)) {
+ JSXMLObjectOps *ops;
+
+ ops = (JSXMLObjectOps *) obj2->map->ops;
+ if (!ops->concatenate(cx, obj2, rval, &rval))
+ goto error;
+ regs.sp--;
+ STORE_OPND(-1, rval);
+ } else
+#endif
+ {
+ if (!JSVAL_IS_PRIMITIVE(lval))
+ DEFAULT_VALUE(cx, -2, JSTYPE_VOID, lval);
+ if (!JSVAL_IS_PRIMITIVE(rval))
+ DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval);
+ if ((cond = JSVAL_IS_STRING(lval)) || JSVAL_IS_STRING(rval)) {
+ if (cond) {
+ str = JSVAL_TO_STRING(lval);
+ str2 = js_ValueToString(cx, rval);
+ if (!str2)
+ goto error;
+ regs.sp[-1] = STRING_TO_JSVAL(str2);
+ } else {
+ str2 = JSVAL_TO_STRING(rval);
+ str = js_ValueToString(cx, lval);
+ if (!str)
+ goto error;
+ regs.sp[-2] = STRING_TO_JSVAL(str);
+ }
+ str = js_ConcatStrings(cx, str, str2);
+ if (!str)
+ goto error;
+ regs.sp--;
+ STORE_OPND(-1, STRING_TO_JSVAL(str));
+ } else {
+ VALUE_TO_NUMBER(cx, -2, lval, d);
+ VALUE_TO_NUMBER(cx, -1, rval, d2);
+ d += d2;
+ regs.sp--;
+ STORE_NUMBER(cx, -1, d);
+ }
+ }
+ END_CASE(JSOP_ADD)
+
+#define BINARY_OP(OP) \
+ JS_BEGIN_MACRO \
+ FETCH_NUMBER(cx, -2, d); \
+ FETCH_NUMBER(cx, -1, d2); \
+ d = d OP d2; \
+ regs.sp--; \
+ STORE_NUMBER(cx, -1, d); \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_SUB)
+ BINARY_OP(-);
+ END_CASE(JSOP_SUB)
+
+ BEGIN_CASE(JSOP_MUL)
+ BINARY_OP(*);
+ END_CASE(JSOP_MUL)
+
+ BEGIN_CASE(JSOP_DIV)
+ FETCH_NUMBER(cx, -1, d2);
+ FETCH_NUMBER(cx, -2, d);
+ regs.sp--;
+ if (d2 == 0) {
+#ifdef XP_WIN
+ /* XXX MSVC miscompiles such that (NaN == 0) */
+ if (JSDOUBLE_IS_NaN(d2))
+ rval = DOUBLE_TO_JSVAL(rt->jsNaN);
+ else
+#endif
+ if (d == 0 || JSDOUBLE_IS_NaN(d))
+ rval = DOUBLE_TO_JSVAL(rt->jsNaN);
+ else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)
+ rval = DOUBLE_TO_JSVAL(rt->jsNegativeInfinity);
+ else
+ rval = DOUBLE_TO_JSVAL(rt->jsPositiveInfinity);
+ STORE_OPND(-1, rval);
+ } else {
+ d /= d2;
+ STORE_NUMBER(cx, -1, d);
+ }
+ END_CASE(JSOP_DIV)
+
+ BEGIN_CASE(JSOP_MOD)
+ FETCH_NUMBER(cx, -1, d2);
+ FETCH_NUMBER(cx, -2, d);
+ regs.sp--;
+ if (d2 == 0) {
+ STORE_OPND(-1, DOUBLE_TO_JSVAL(rt->jsNaN));
+ } else {
+#ifdef XP_WIN
+ /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
+ if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)))
+#endif
+ d = fmod(d, d2);
+ STORE_NUMBER(cx, -1, d);
+ }
+ END_CASE(JSOP_MOD)
+
+ BEGIN_CASE(JSOP_NOT)
+ POP_BOOLEAN(cx, rval, cond);
+ PUSH_OPND(BOOLEAN_TO_JSVAL(!cond));
+ END_CASE(JSOP_NOT)
+
+ BEGIN_CASE(JSOP_BITNOT)
+ FETCH_INT(cx, -1, i);
+ i = ~i;
+ STORE_INT(cx, -1, i);
+ END_CASE(JSOP_BITNOT)
+
+ BEGIN_CASE(JSOP_NEG)
+ /*
+ * When the operand is int jsval, INT_FITS_IN_JSVAL(i) implies
+ * INT_FITS_IN_JSVAL(-i) unless i is 0 or JSVAL_INT_MIN when the
+ * results, -0.0 or JSVAL_INT_MAX + 1, are jsdouble values.
+ */
+ rval = FETCH_OPND(-1);
+ if (JSVAL_IS_INT(rval) &&
+ rval != INT_TO_JSVAL(JSVAL_INT_MIN) &&
+ (i = JSVAL_TO_INT(rval)) != 0) {
+ JS_STATIC_ASSERT(!INT_FITS_IN_JSVAL(-JSVAL_INT_MIN));
+ i = -i;
+ JS_ASSERT(INT_FITS_IN_JSVAL(i));
+ regs.sp[-1] = INT_TO_JSVAL(i);
+ } else {
+ if (JSVAL_IS_DOUBLE(rval)) {
+ d = *JSVAL_TO_DOUBLE(rval);
+ } else {
+ d = js_ValueToNumber(cx, &regs.sp[-1]);
+ if (JSVAL_IS_NULL(regs.sp[-1]))
+ goto error;
+ JS_ASSERT(JSVAL_IS_NUMBER(regs.sp[-1]) ||
+ regs.sp[-1] == JSVAL_TRUE);
+ }
+#ifdef HPUX
+ /*
+ * Negation of a zero doesn't produce a negative
+ * zero on HPUX. Perform the operation by bit
+ * twiddling.
+ */
+ JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT;
+#else
+ d = -d;
+#endif
+ if (!js_NewNumberInRootedValue(cx, d, &regs.sp[-1]))
+ goto error;
+ }
+ END_CASE(JSOP_NEG)
+
+ BEGIN_CASE(JSOP_POS)
+ rval = FETCH_OPND(-1);
+ if (!JSVAL_IS_NUMBER(rval)) {
+ d = js_ValueToNumber(cx, &regs.sp[-1]);
+ rval = regs.sp[-1];
+ if (JSVAL_IS_NULL(rval))
+ goto error;
+ if (rval == JSVAL_TRUE) {
+ if (!js_NewNumberInRootedValue(cx, d, &regs.sp[-1]))
+ goto error;
+ } else {
+ JS_ASSERT(JSVAL_IS_NUMBER(rval));
+ }
+ }
+ END_CASE(JSOP_POS)
+
+ BEGIN_CASE(JSOP_DELNAME)
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
+ goto error;
+
+ /* ECMA says to return true if name is undefined or inherited. */
+ PUSH_OPND(JSVAL_TRUE);
+ if (prop) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!OBJ_DELETE_PROPERTY(cx, obj, id, &regs.sp[-1]))
+ goto error;
+ }
+ END_CASE(JSOP_DELNAME)
+
+ BEGIN_CASE(JSOP_DELPROP)
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ PROPERTY_OP(-1, OBJ_DELETE_PROPERTY(cx, obj, id, &rval));
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_DELPROP)
+
+ BEGIN_CASE(JSOP_DELELEM)
+ ELEMENT_OP(-1, OBJ_DELETE_PROPERTY(cx, obj, id, &rval));
+ regs.sp--;
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_DELELEM)
+
+ BEGIN_CASE(JSOP_TYPEOFEXPR)
+ BEGIN_CASE(JSOP_TYPEOF)
+ rval = FETCH_OPND(-1);
+ type = JS_TypeOfValue(cx, rval);
+ atom = rt->atomState.typeAtoms[type];
+ STORE_OPND(-1, ATOM_KEY(atom));
+ END_CASE(JSOP_TYPEOF)
+
+ BEGIN_CASE(JSOP_VOID)
+ STORE_OPND(-1, JSVAL_VOID);
+ END_CASE(JSOP_VOID)
+
+ BEGIN_CASE(JSOP_INCELEM)
+ BEGIN_CASE(JSOP_DECELEM)
+ BEGIN_CASE(JSOP_ELEMINC)
+ BEGIN_CASE(JSOP_ELEMDEC)
+ /*
+ * Delay fetching of id until we have the object to ensure
+ * the proper evaluation order. See bug 372331.
+ */
+ id = 0;
+ i = -2;
+ goto fetch_incop_obj;
+
+ BEGIN_CASE(JSOP_INCPROP)
+ BEGIN_CASE(JSOP_DECPROP)
+ BEGIN_CASE(JSOP_PROPINC)
+ BEGIN_CASE(JSOP_PROPDEC)
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ i = -1;
+
+ fetch_incop_obj:
+ FETCH_OBJECT(cx, i, lval, obj);
+ if (id == 0)
+ FETCH_ELEMENT_ID(obj, -1, id);
+ goto do_incop;
+
+ BEGIN_CASE(JSOP_INCNAME)
+ BEGIN_CASE(JSOP_DECNAME)
+ BEGIN_CASE(JSOP_NAMEINC)
+ BEGIN_CASE(JSOP_NAMEDEC)
+ {
+ JSPropCacheEntry *entry;
+
+ obj = fp->scopeChain;
+ if (JS_LIKELY(OBJ_IS_NATIVE(obj))) {
+ PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);
+ if (!atom) {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
+ if (obj == obj2 && PCVAL_IS_SLOT(entry->vword)) {
+ slot = PCVAL_TO_SLOT(entry->vword);
+ JS_ASSERT(slot < obj->map->freeslot);
+ rval = LOCKED_OBJ_GET_SLOT(obj, slot);
+ if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {
+ rtmp = rval;
+ rval += (js_CodeSpec[op].format & JOF_INC) ? 2 : -2;
+ if (!(js_CodeSpec[op].format & JOF_POST))
+ rtmp = rval;
+ LOCKED_OBJ_SET_SLOT(obj, slot, rval);
+ JS_UNLOCK_OBJ(cx, obj);
+ PUSH_OPND(rtmp);
+ len = JSOP_INCNAME_LENGTH;
+ DO_NEXT_OP(len);
+ }
+ }
+ JS_UNLOCK_OBJ(cx, obj2);
+ LOAD_ATOM(0);
+ }
+ } else {
+ entry = NULL;
+ LOAD_ATOM(0);
+ }
+ id = ATOM_TO_JSID(atom);
+ if (js_FindPropertyHelper(cx, id, &obj, &obj2, &prop, &entry) < 0)
+ goto error;
+ if (!prop)
+ goto atom_not_defined;
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+
+ do_incop:
+ {
+ const JSCodeSpec *cs;
+ jsval v;
+
+ /*
+ * We need a root to store the value to leave on the stack until
+ * we have done with OBJ_SET_PROPERTY.
+ */
+ PUSH_OPND(JSVAL_NULL);
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &regs.sp[-1]))
+ goto error;
+
+ cs = &js_CodeSpec[op];
+ JS_ASSERT(cs->ndefs == 1);
+ JS_ASSERT((cs->format & JOF_TMPSLOT_MASK) == JOF_TMPSLOT2);
+ v = regs.sp[-1];
+ if (JS_LIKELY(CAN_DO_FAST_INC_DEC(v))) {
+ jsval incr;
+
+ incr = (cs->format & JOF_INC) ? 2 : -2;
+ if (cs->format & JOF_POST) {
+ regs.sp[-1] = v + incr;
+ } else {
+ v += incr;
+ regs.sp[-1] = v;
+ }
+ fp->flags |= JSFRAME_ASSIGNING;
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-1]);
+ fp->flags &= ~JSFRAME_ASSIGNING;
+ if (!ok)
+ goto error;
+
+ /*
+ * We must set regs.sp[-1] to v for both post and pre increments
+ * as the setter overwrites regs.sp[-1].
+ */
+ regs.sp[-1] = v;
+ } else {
+ /* We need an extra root for the result. */
+ PUSH_OPND(JSVAL_NULL);
+ if (!js_DoIncDec(cx, cs, &regs.sp[-2], &regs.sp[-1]))
+ goto error;
+ fp->flags |= JSFRAME_ASSIGNING;
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-1]);
+ fp->flags &= ~JSFRAME_ASSIGNING;
+ if (!ok)
+ goto error;
+ regs.sp--;
+ }
+
+ if (cs->nuses == 0) {
+ /* regs.sp[-1] already contains the result of name increment. */
+ } else {
+ rtmp = regs.sp[-1];
+ regs.sp -= cs->nuses;
+ regs.sp[-1] = rtmp;
+ }
+ len = cs->length;
+ DO_NEXT_OP(len);
+ }
+
+ {
+ jsval incr, incr2;
+
+ /* Position cases so the most frequent i++ does not need a jump. */
+ BEGIN_CASE(JSOP_DECARG)
+ incr = -2; incr2 = -2; goto do_arg_incop;
+ BEGIN_CASE(JSOP_ARGDEC)
+ incr = -2; incr2 = 0; goto do_arg_incop;
+ BEGIN_CASE(JSOP_INCARG)
+ incr = 2; incr2 = 2; goto do_arg_incop;
+ BEGIN_CASE(JSOP_ARGINC)
+ incr = 2; incr2 = 0;
+
+ do_arg_incop:
+ slot = GET_ARGNO(regs.pc);
+ JS_ASSERT(slot < fp->fun->nargs);
+ METER_SLOT_OP(op, slot);
+ vp = fp->argv + slot;
+ goto do_int_fast_incop;
+
+ BEGIN_CASE(JSOP_DECLOCAL)
+ incr = -2; incr2 = -2; goto do_local_incop;
+ BEGIN_CASE(JSOP_LOCALDEC)
+ incr = -2; incr2 = 0; goto do_local_incop;
+ BEGIN_CASE(JSOP_INCLOCAL)
+ incr = 2; incr2 = 2; goto do_local_incop;
+ BEGIN_CASE(JSOP_LOCALINC)
+ incr = 2; incr2 = 0;
+
+ /*
+ * do_local_incop comes right before do_int_fast_incop as we want to
+ * avoid an extra jump for variable cases as local++ is more frequent
+ * than arg++.
+ */
+ do_local_incop:
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < fp->script->nslots);
+ vp = fp->slots + slot;
+ METER_SLOT_OP(op, slot);
+ vp = fp->slots + slot;
+
+ do_int_fast_incop:
+ rval = *vp;
+ if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {
+ *vp = rval + incr;
+ JS_ASSERT(JSOP_INCARG_LENGTH == js_CodeSpec[op].length);
+ SKIP_POP_AFTER_SET(JSOP_INCARG_LENGTH, 0);
+ PUSH_OPND(rval + incr2);
+ } else {
+ PUSH_OPND(rval);
+ if (!js_DoIncDec(cx, &js_CodeSpec[op], &regs.sp[-1], vp))
+ goto error;
+ }
+ len = JSOP_INCARG_LENGTH;
+ JS_ASSERT(len == js_CodeSpec[op].length);
+ DO_NEXT_OP(len);
+ }
+
+/* NB: This macro doesn't use JS_BEGIN_MACRO/JS_END_MACRO around its body. */
+#define FAST_GLOBAL_INCREMENT_OP(SLOWOP,INCR,INCR2) \
+ op2 = SLOWOP; \
+ incr = INCR; \
+ incr2 = INCR2; \
+ goto do_global_incop
+
+ {
+ jsval incr, incr2;
+
+ BEGIN_CASE(JSOP_DECGVAR)
+ FAST_GLOBAL_INCREMENT_OP(JSOP_DECNAME, -2, -2);
+ BEGIN_CASE(JSOP_GVARDEC)
+ FAST_GLOBAL_INCREMENT_OP(JSOP_NAMEDEC, -2, 0);
+ BEGIN_CASE(JSOP_INCGVAR)
+ FAST_GLOBAL_INCREMENT_OP(JSOP_INCNAME, 2, 2);
+ BEGIN_CASE(JSOP_GVARINC)
+ FAST_GLOBAL_INCREMENT_OP(JSOP_NAMEINC, 2, 0);
+
+#undef FAST_GLOBAL_INCREMENT_OP
+
+ do_global_incop:
+ JS_ASSERT((js_CodeSpec[op].format & JOF_TMPSLOT_MASK) ==
+ JOF_TMPSLOT2);
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < GlobalVarCount(fp));
+ METER_SLOT_OP(op, slot);
+ lval = fp->slots[slot];
+ if (JSVAL_IS_NULL(lval)) {
+ op = op2;
+ DO_OP();
+ }
+ slot = JSVAL_TO_INT(lval);
+ rval = OBJ_GET_SLOT(cx, fp->varobj, slot);
+ if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {
+ PUSH_OPND(rval + incr2);
+ rval += incr;
+ } else {
+ PUSH_OPND(rval);
+ PUSH_OPND(JSVAL_NULL); /* Extra root */
+ if (!js_DoIncDec(cx, &js_CodeSpec[op], &regs.sp[-2], &regs.sp[-1]))
+ goto error;
+ rval = regs.sp[-1];
+ --regs.sp;
+ }
+ OBJ_SET_SLOT(cx, fp->varobj, slot, rval);
+ len = JSOP_INCGVAR_LENGTH; /* all gvar incops are same length */
+ JS_ASSERT(len == js_CodeSpec[op].length);
+ DO_NEXT_OP(len);
+ }
+
+#define COMPUTE_THIS(cx, fp, obj) \
+ JS_BEGIN_MACRO \
+ if (fp->flags & JSFRAME_COMPUTED_THIS) { \
+ obj = fp->thisp; \
+ } else { \
+ obj = js_ComputeThis(cx, JS_TRUE, fp->argv); \
+ if (!obj) \
+ goto error; \
+ fp->thisp = obj; \
+ fp->flags |= JSFRAME_COMPUTED_THIS; \
+ } \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_THIS)
+ COMPUTE_THIS(cx, fp, obj);
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_THIS)
+
+ BEGIN_CASE(JSOP_GETTHISPROP)
+ i = 0;
+ COMPUTE_THIS(cx, fp, obj);
+ PUSH(JSVAL_NULL);
+ goto do_getprop_with_obj;
+
+#undef COMPUTE_THIS
+
+ BEGIN_CASE(JSOP_GETARGPROP)
+ i = ARGNO_LEN;
+ slot = GET_ARGNO(regs.pc);
+ JS_ASSERT(slot < fp->fun->nargs);
+ PUSH_OPND(fp->argv[slot]);
+ goto do_getprop_body;
+
+ BEGIN_CASE(JSOP_GETLOCALPROP)
+ i = SLOTNO_LEN;
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < script->nslots);
+ PUSH_OPND(fp->slots[slot]);
+ goto do_getprop_body;
+
+ BEGIN_CASE(JSOP_GETPROP)
+ BEGIN_CASE(JSOP_GETXPROP)
+ i = 0;
+
+ do_getprop_body:
+ lval = FETCH_OPND(-1);
+
+ do_getprop_with_lval:
+ VALUE_TO_OBJECT(cx, -1, lval, obj);
+
+ do_getprop_with_obj:
+ do {
+ JSObject *aobj;
+ JSPropCacheEntry *entry;
+
+ aobj = OBJ_IS_DENSE_ARRAY(cx, obj) ? OBJ_GET_PROTO(cx, obj) : obj;
+ if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)) {
+ PROPERTY_CACHE_TEST(cx, regs.pc, aobj, obj2, entry, atom);
+ if (!atom) {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(i, aobj, obj2, entry);
+ if (PCVAL_IS_OBJECT(entry->vword)) {
+ rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);
+ } else if (PCVAL_IS_SLOT(entry->vword)) {
+ slot = PCVAL_TO_SLOT(entry->vword);
+ JS_ASSERT(slot < obj2->map->freeslot);
+ rval = LOCKED_OBJ_GET_SLOT(obj2, slot);
+ } else {
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ NATIVE_GET(cx, obj, obj2, sprop, &rval);
+ }
+ JS_UNLOCK_OBJ(cx, obj2);
+ break;
+ }
+ } else {
+ entry = NULL;
+ if (i < 0)
+ atom = rt->atomState.lengthAtom;
+ else
+ LOAD_ATOM(i);
+ }
+ id = ATOM_TO_JSID(atom);
+ if (entry
+ ? !js_GetPropertyHelper(cx, aobj, id, &rval, &entry)
+ : !OBJ_GET_PROPERTY(cx, obj, id, &rval)) {
+ goto error;
+ }
+ } while (0);
+
+ STORE_OPND(-1, rval);
+ JS_ASSERT(JSOP_GETPROP_LENGTH + i == js_CodeSpec[op].length);
+ len = JSOP_GETPROP_LENGTH + i;
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_LENGTH)
+ lval = FETCH_OPND(-1);
+ if (JSVAL_IS_STRING(lval)) {
+ str = JSVAL_TO_STRING(lval);
+ regs.sp[-1] = INT_TO_JSVAL(JSSTRING_LENGTH(str));
+ } else if (!JSVAL_IS_PRIMITIVE(lval) &&
+ (obj = JSVAL_TO_OBJECT(lval), OBJ_IS_ARRAY(cx, obj))) {
+ jsuint length;
+
+ /*
+ * We know that the array is created with only its 'length'
+ * private data in a fixed slot at JSSLOT_ARRAY_LENGTH. See
+ * also JSOP_ARRAYPUSH, far below.
+ */
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length <= JSVAL_INT_MAX) {
+ regs.sp[-1] = INT_TO_JSVAL(length);
+ } else if (!js_NewDoubleInRootedValue(cx, (jsdouble) length,
+ &regs.sp[-1])) {
+ goto error;
+ }
+ } else {
+ i = -2;
+ goto do_getprop_with_lval;
+ }
+ END_CASE(JSOP_LENGTH)
+
+ BEGIN_CASE(JSOP_CALLPROP)
+ {
+ JSObject *aobj;
+ JSPropCacheEntry *entry;
+
+ lval = FETCH_OPND(-1);
+ if (!JSVAL_IS_PRIMITIVE(lval)) {
+ obj = JSVAL_TO_OBJECT(lval);
+ } else {
+ if (JSVAL_IS_STRING(lval)) {
+ i = JSProto_String;
+ } else if (JSVAL_IS_NUMBER(lval)) {
+ i = JSProto_Number;
+ } else if (JSVAL_IS_BOOLEAN(lval)) {
+ i = JSProto_Boolean;
+ } else {
+ JS_ASSERT(JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval));
+ js_ReportIsNullOrUndefined(cx, -1, lval, NULL);
+ goto error;
+ }
+
+ if (!js_GetClassPrototype(cx, NULL, INT_TO_JSID(i), &obj))
+ goto error;
+ }
+
+ aobj = OBJ_IS_DENSE_ARRAY(cx, obj) ? OBJ_GET_PROTO(cx, obj) : obj;
+ if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)) {
+ PROPERTY_CACHE_TEST(cx, regs.pc, aobj, obj2, entry, atom);
+ if (!atom) {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(0, aobj, obj2, entry);
+ if (PCVAL_IS_OBJECT(entry->vword)) {
+ rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);
+ } else if (PCVAL_IS_SLOT(entry->vword)) {
+ slot = PCVAL_TO_SLOT(entry->vword);
+ JS_ASSERT(slot < obj2->map->freeslot);
+ rval = LOCKED_OBJ_GET_SLOT(obj2, slot);
+ } else {
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ NATIVE_GET(cx, obj, obj2, sprop, &rval);
+ }
+ JS_UNLOCK_OBJ(cx, obj2);
+ STORE_OPND(-1, rval);
+ PUSH_OPND(lval);
+ goto end_callprop;
+ }
+ } else {
+ entry = NULL;
+ LOAD_ATOM(0);
+ }
+
+ /*
+ * Cache miss: use the immediate atom that was loaded for us under
+ * PROPERTY_CACHE_TEST.
+ */
+ id = ATOM_TO_JSID(atom);
+ PUSH(JSVAL_NULL);
+ if (!JSVAL_IS_PRIMITIVE(lval)) {
+#if JS_HAS_XML_SUPPORT
+ /* Special-case XML object method lookup, per ECMA-357. */
+ if (OBJECT_IS_XML(cx, obj)) {
+ JSXMLObjectOps *ops;
+
+ ops = (JSXMLObjectOps *) obj->map->ops;
+ obj = ops->getMethod(cx, obj, id, &rval);
+ if (!obj)
+ goto error;
+ } else
+#endif
+ if (entry
+ ? !js_GetPropertyHelper(cx, aobj, id, &rval, &entry)
+ : !OBJ_GET_PROPERTY(cx, obj, id, &rval)) {
+ goto error;
+ }
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ STORE_OPND(-2, rval);
+ } else {
+ JS_ASSERT(obj->map->ops->getProperty == js_GetProperty);
+ if (!js_GetPropertyHelper(cx, obj, id, &rval, &entry))
+ goto error;
+ STORE_OPND(-1, lval);
+ STORE_OPND(-2, rval);
+ }
+
+ end_callprop:
+ /* Wrap primitive lval in object clothing if necessary. */
+ if (JSVAL_IS_PRIMITIVE(lval)) {
+ /* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */
+ if (!VALUE_IS_FUNCTION(cx, rval) ||
+ (obj = JSVAL_TO_OBJECT(rval),
+ fun = GET_FUNCTION_PRIVATE(cx, obj),
+ !PRIMITIVE_THIS_TEST(fun, lval))) {
+ if (!js_PrimitiveToObject(cx, &regs.sp[-1]))
+ goto error;
+ }
+ }
+#if JS_HAS_NO_SUCH_METHOD
+ if (JS_UNLIKELY(JSVAL_IS_VOID(rval))) {
+ LOAD_ATOM(0);
+ regs.sp[-2] = ATOM_KEY(atom);
+ if (!js_OnUnknownMethod(cx, regs.sp - 2))
+ goto error;
+ }
+#endif
+ }
+ END_CASE(JSOP_CALLPROP)
+
+ BEGIN_CASE(JSOP_SETNAME)
+ BEGIN_CASE(JSOP_SETPROP)
+ rval = FETCH_OPND(-1);
+ lval = FETCH_OPND(-2);
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(lval) || op == JSOP_SETPROP);
+ VALUE_TO_OBJECT(cx, -2, lval, obj);
+
+ do {
+ JSPropCacheEntry *entry;
+
+ entry = NULL;
+ atom = NULL;
+ if (JS_LIKELY(obj->map->ops->setProperty == js_SetProperty)) {
+ JSPropertyCache *cache = &JS_PROPERTY_CACHE(cx);
+ uint32 kshape = OBJ_SHAPE(obj);
+
+ /*
+ * Open-code JS_PROPERTY_CACHE_TEST, specializing for two
+ * important set-property cases. First:
+ *
+ * function f(a, b, c) {
+ * var o = {p:a, q:b, r:c};
+ * return o;
+ * }
+ *
+ * or similar real-world cases, which evolve a newborn
+ * native object predicatably through some bounded number
+ * of property additions. And second:
+ *
+ * o.p = x;
+ *
+ * in a frequently executed method or loop body, where p
+ * will (possibly after the first iteration) always exist
+ * in native object o.
+ */
+ entry = &cache->table[PROPERTY_CACHE_HASH_PC(regs.pc, kshape)];
+ PCMETER(cache->tests++);
+ PCMETER(cache->settests++);
+ if (entry->kpc == regs.pc && entry->kshape == kshape) {
+ JSScope *scope;
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ if (scope->shape == kshape) {
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));
+ JS_ASSERT(!SCOPE_IS_SEALED(OBJ_SCOPE(obj)));
+
+ if (scope->object == obj) {
+ /*
+ * Fastest path: the cached sprop is already
+ * in scope. Just NATIVE_SET and break to get
+ * out of the do-while(0).
+ */
+ if (sprop == scope->lastProp ||
+ SCOPE_HAS_PROPERTY(scope, sprop)) {
+ PCMETER(cache->pchits++);
+ PCMETER(cache->setpchits++);
+ NATIVE_SET(cx, obj, sprop, &rval);
+ JS_UNLOCK_SCOPE(cx, scope);
+ TRACE_2(SetPropHit, entry, sprop);
+ break;
+ }
+ } else {
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ JS_UNLOCK_OBJ(cx, obj);
+ goto error;
+ }
+ }
+
+ if (sprop->parent == scope->lastProp &&
+ !SCOPE_HAD_MIDDLE_DELETE(scope) &&
+ SPROP_HAS_STUB_SETTER(sprop) &&
+ (slot = sprop->slot) == scope->map.freeslot) {
+ /*
+ * Fast path: adding a plain old property that
+ * was once at the frontier of the property
+ * tree, whose slot is next to claim among the
+ * allocated slots in obj, where scope->table
+ * has not been created yet.
+ *
+ * We may want to remove hazard conditions
+ * above and inline compensation code here,
+ * depending on real-world workloads.
+ */
+ JS_ASSERT(!(LOCKED_OBJ_GET_CLASS(obj)->flags &
+ JSCLASS_SHARE_ALL_PROPERTIES));
+
+ PCMETER(cache->pchits++);
+ PCMETER(cache->addpchits++);
+
+ /*
+ * Beware classes such as Function that use
+ * the reserveSlots hook to allocate a number
+ * of reserved slots that may vary with obj.
+ */
+ if (slot < STOBJ_NSLOTS(obj) &&
+ !OBJ_GET_CLASS(cx, obj)->reserveSlots) {
+ ++scope->map.freeslot;
+ } else {
+ if (!js_AllocSlot(cx, obj, &slot)) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ goto error;
+ }
+ }
+
+ /*
+ * If this obj's number of reserved slots
+ * differed, or if something created a hash
+ * table for scope, we must pay the price of
+ * js_AddScopeProperty.
+ *
+ * If slot does not match the cached sprop's
+ * slot, update the cache entry in the hope
+ * that obj and other instances with the same
+ * number of reserved slots are now "hot".
+ */
+ if (slot != sprop->slot || scope->table) {
+ JSScopeProperty *sprop2 =
+ js_AddScopeProperty(cx, scope,
+ sprop->id,
+ sprop->getter,
+ sprop->setter,
+ slot,
+ sprop->attrs,
+ sprop->flags,
+ sprop->shortid);
+ if (!sprop2) {
+ js_FreeSlot(cx, obj, slot);
+ JS_UNLOCK_SCOPE(cx, scope);
+ goto error;
+ }
+ if (sprop2 != sprop) {
+ PCMETER(cache->slotchanges++);
+ JS_ASSERT(slot != sprop->slot &&
+ slot == sprop2->slot &&
+ sprop2->id == sprop->id);
+ entry->vword = SPROP_TO_PCVAL(sprop2);
+ }
+ sprop = sprop2;
+ } else {
+ SCOPE_EXTEND_SHAPE(cx, scope, sprop);
+ ++scope->entryCount;
+ scope->lastProp = sprop;
+ }
+
+ GC_WRITE_BARRIER(cx, scope,
+ LOCKED_OBJ_GET_SLOT(obj, slot),
+ rval);
+ LOCKED_OBJ_SET_SLOT(obj, slot, rval);
+ JS_UNLOCK_SCOPE(cx, scope);
+ TRACE_2(SetPropHit, entry, sprop);
+ break;
+ }
+
+ PCMETER(cache->setpcmisses++);
+ atom = NULL;
+ }
+
+ JS_UNLOCK_OBJ(cx, obj);
+ }
+
+ atom = js_FullTestPropertyCache(cx, regs.pc, &obj, &obj2,
+ &entry);
+ if (atom) {
+ PCMETER(cache->misses++);
+ PCMETER(cache->setmisses++);
+ } else {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
+ sprop = NULL;
+ if (obj == obj2) {
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));
+ JS_ASSERT(!SCOPE_IS_SEALED(OBJ_SCOPE(obj2)));
+ NATIVE_SET(cx, obj, sprop, &rval);
+ }
+ JS_UNLOCK_OBJ(cx, obj2);
+ if (sprop) {
+ TRACE_2(SetPropHit, entry, sprop);
+ break;
+ }
+ }
+ }
+
+ if (!atom)
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ if (entry) {
+ if (!js_SetPropertyHelper(cx, obj, id, &rval, &entry))
+ goto error;
+#ifdef JS_TRACER
+ if (entry)
+ TRACE_1(SetPropMiss, entry);
+#endif
+ } else {
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ }
+#ifdef JS_TRACER
+ if (!entry && TRACE_RECORDER(cx)) {
+ js_AbortRecording(cx, "SetPropUncached");
+ ENABLE_TRACER(0);
+ }
+#endif
+ } while (0);
+ END_SET_CASE_STORE_RVAL(JSOP_SETPROP, 2);
+
+ BEGIN_CASE(JSOP_GETELEM)
+ /* Open-coded ELEMENT_OP optimized for strings and dense arrays. */
+ lval = FETCH_OPND(-2);
+ rval = FETCH_OPND(-1);
+ if (JSVAL_IS_STRING(lval) && JSVAL_IS_INT(rval)) {
+ str = JSVAL_TO_STRING(lval);
+ i = JSVAL_TO_INT(rval);
+ if ((size_t)i < JSSTRING_LENGTH(str)) {
+ str = js_GetUnitString(cx, str, (size_t)i);
+ if (!str)
+ goto error;
+ rval = STRING_TO_JSVAL(str);
+ goto end_getelem;
+ }
+ }
+
+ VALUE_TO_OBJECT(cx, -2, lval, obj);
+ if (JSVAL_IS_INT(rval)) {
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ jsuint length;
+
+ length = ARRAY_DENSE_LENGTH(obj);
+ i = JSVAL_TO_INT(rval);
+ if ((jsuint)i < length &&
+ i < obj->fslots[JSSLOT_ARRAY_LENGTH]) {
+ rval = obj->dslots[i];
+ if (rval != JSVAL_HOLE)
+ goto end_getelem;
+
+ /* Reload rval from the stack in the rare hole case. */
+ rval = FETCH_OPND(-1);
+ }
+ }
+ id = INT_JSVAL_TO_JSID(rval);
+ } else {
+ if (!js_InternNonIntElementId(cx, obj, rval, &id))
+ goto error;
+ }
+
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ end_getelem:
+ regs.sp--;
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_GETELEM)
+
+ BEGIN_CASE(JSOP_CALLELEM)
+ /*
+ * FIXME: JSOP_CALLELEM should call getMethod on XML objects as
+ * CALLPROP does. See bug 362910.
+ */
+ ELEMENT_OP(-1, OBJ_GET_PROPERTY(cx, obj, id, &rval));
+#if JS_HAS_NO_SUCH_METHOD
+ if (JS_UNLIKELY(JSVAL_IS_VOID(rval))) {
+ regs.sp[-2] = regs.sp[-1];
+ regs.sp[-1] = OBJECT_TO_JSVAL(obj);
+ if (!js_OnUnknownMethod(cx, regs.sp - 2))
+ goto error;
+ } else
+#endif
+ {
+ STORE_OPND(-2, rval);
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ }
+ END_CASE(JSOP_CALLELEM)
+
+ BEGIN_CASE(JSOP_SETELEM)
+ rval = FETCH_OPND(-1);
+ FETCH_OBJECT(cx, -3, lval, obj);
+ FETCH_ELEMENT_ID(obj, -2, id);
+ do {
+ if (OBJ_IS_DENSE_ARRAY(cx, obj) && JSID_IS_INT(id)) {
+ jsuint length;
+
+ length = ARRAY_DENSE_LENGTH(obj);
+ i = JSID_TO_INT(id);
+ if ((jsuint)i < length) {
+ if (obj->dslots[i] == JSVAL_HOLE) {
+ if (rt->anyArrayProtoHasElement)
+ break;
+ if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH])
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
+ obj->fslots[JSSLOT_ARRAY_COUNT]++;
+ }
+ obj->dslots[i] = rval;
+ goto end_setelem;
+ }
+ }
+ } while (0);
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ end_setelem:
+ END_SET_CASE_STORE_RVAL(JSOP_SETELEM, 3)
+
+ BEGIN_CASE(JSOP_ENUMELEM)
+ /* Funky: the value to set is under the [obj, id] pair. */
+ rval = FETCH_OPND(-3);
+ FETCH_OBJECT(cx, -2, lval, obj);
+ FETCH_ELEMENT_ID(obj, -1, id);
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ regs.sp -= 3;
+ END_CASE(JSOP_ENUMELEM)
+
+ BEGIN_CASE(JSOP_NEW)
+ /* Get immediate argc and find the constructor function. */
+ argc = GET_ARGC(regs.pc);
+ vp = regs.sp - (2 + argc);
+ JS_ASSERT(vp >= StackBase(fp));
+
+ /*
+ * Assign lval, obj, and fun exactly as the code at inline_call:
+ * expects to find them, to avoid nesting a js_Interpret call via
+ * js_InvokeConstructor.
+ */
+ lval = *vp;
+ if (VALUE_IS_FUNCTION(cx, lval)) {
+ obj = JSVAL_TO_OBJECT(lval);
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
+ if (FUN_INTERPRETED(fun)) {
+ /* Root as we go using vp[1]. */
+ if (!OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &vp[1])) {
+ goto error;
+ }
+ rval = vp[1];
+ obj2 = js_NewObject(cx, &js_ObjectClass,
+ JSVAL_IS_OBJECT(rval)
+ ? JSVAL_TO_OBJECT(rval)
+ : NULL,
+ OBJ_GET_PARENT(cx, obj),
+ 0);
+ if (!obj2)
+ goto error;
+ vp[1] = OBJECT_TO_JSVAL(obj2);
+ flags = JSFRAME_CONSTRUCTING;
+ goto inline_call;
+ }
+ }
+
+ if (!js_InvokeConstructor(cx, argc, JS_FALSE, vp))
+ goto error;
+ regs.sp = vp + 1;
+ LOAD_INTERRUPT_HANDLER(cx);
+ END_CASE(JSOP_NEW)
+
+ BEGIN_CASE(JSOP_APPLY)
+ {
+ argc = GET_ARGC(regs.pc);
+ vp = regs.sp - (argc + 2);
+ lval = *vp;
+ if (!VALUE_IS_FUNCTION(cx, lval))
+ goto do_call;
+ obj = JSVAL_TO_OBJECT(lval);
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
+ if (FUN_INTERPRETED(fun))
+ goto do_call;
+
+ bool apply = (JSFastNative)fun->u.n.native == js_fun_apply;
+ if (!apply && (JSFastNative)fun->u.n.native != js_fun_call)
+ goto do_call;
+
+ /*
+ * If the second arg to apply is null or void, treat it as an empty
+ * array.
+ */
+ jsuint applylen = 0;
+ if (apply && argc >= 2 &&
+ !JSVAL_IS_VOID(vp[3]) && !JSVAL_IS_NULL(vp[3])) {
+ /*
+ * Fall back on js_Invoke when the array argument has a wrong
+ * type or when it has too many elements to fit into the
+ * current stack chunk.
+ */
+ if (!JSVAL_IS_OBJECT(vp[3]))
+ goto do_call;
+
+ JSBool arraylike;
+ JSObject* aobj = JSVAL_TO_OBJECT(vp[3]);
+ if (!js_IsArrayLike(cx, aobj, &arraylike, &applylen))
+ goto error;
+ if (!arraylike || applylen > ARGC_LIMIT)
+ goto do_call;
+
+ JSArena *a = cx->stackPool.current;
+ JS_ASSERT(jsuword(vp + 2) <= a->limit);
+
+ /*
+ * We need space for applylen elements plus an extra slot to
+ * temporary root the array object when we unpack its elements
+ * using OBJ_GET_PROPERTY below.
+ */
+ if (a->limit - jsuword(vp + 2) < (applylen + 1) * sizeof(jsval))
+ goto do_call;
+ }
+
+ if (!VALUE_IS_FUNCTION(cx, vp[1]))
+ goto do_call;
+ vp[0] = vp[1];
+
+ if (argc == 0) {
+ /*
+ * Call fun with its global object as the 'this' param if
+ * no args.
+ */
+ obj = NULL;
+ } else {
+ /* Convert the first arg to 'this'. */
+ if (!JSVAL_IS_PRIMITIVE(vp[2]))
+ obj = JSVAL_TO_OBJECT(vp[2]);
+ else if (!js_ValueToObject(cx, vp[2], &obj))
+ goto error;
+ }
+ vp[1] = OBJECT_TO_JSVAL(obj);
+
+ if (!apply) {
+ if (argc != 0) {
+ --argc;
+ memmove(vp + 2, vp + 3, argc * sizeof *vp);
+ }
+ } else if (applylen == 0) {
+ argc = 0;
+ } else {
+ /*
+ * Make room for missing arguments to the right including the
+ * temporary root nulling any extra stack slots for GC safety.
+ */
+ jsval* newsp = vp + 2 + applylen + 1;
+ if (newsp > regs.sp) {
+ JSArena *a = cx->stackPool.current;
+ JS_ASSERT(jsuword(newsp) <= a->limit); /* see above */
+ if ((jsuword) newsp > a->avail)
+ a->avail = (jsuword) newsp;
+ memset(vp + 2 + argc, 0, (applylen - argc) * sizeof(jsval));
+ }
+
+ JSObject *aobj = JSVAL_TO_OBJECT(vp[3]);
+ newsp[-1] = vp[3];
+ regs.sp = newsp;
+
+ /* Expand array content onto the stack. */
+ for (i = 0; i < jsint(applylen); i++) {
+ id = INT_TO_JSID(i);
+ if (!OBJ_GET_PROPERTY(cx, aobj, id, &vp[2 + i])) {
+ /*
+ * There is no good way to restore the original stack
+ * state here, but it is in a reasonable state with
+ * either original elements or nulls for all arguments
+ * we didn't unpack yet, so we leave it at that.
+ */
+ goto error;
+ }
+ }
+ argc = applylen;
+ }
+ regs.sp = vp + 2 + argc;
+ goto do_call_with_specified_vp_and_argc;
+ }
+
+ BEGIN_CASE(JSOP_CALL)
+ BEGIN_CASE(JSOP_EVAL)
+ do_call:
+ argc = GET_ARGC(regs.pc);
+ vp = regs.sp - (argc + 2);
+
+ do_call_with_specified_vp_and_argc:
+ lval = *vp;
+ if (VALUE_IS_FUNCTION(cx, lval)) {
+ obj = JSVAL_TO_OBJECT(lval);
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
+
+ /* Clear frame flags since this is not a constructor call. */
+ flags = 0;
+ if (FUN_INTERPRETED(fun))
+ inline_call:
+ {
+ uintN nframeslots, nvars, missing;
+ JSArena *a;
+ jsuword nbytes;
+ void *newmark;
+ jsval *newsp;
+ JSInlineFrame *newifp;
+ JSInterpreterHook hook;
+
+ /* Restrict recursion of lightweight functions. */
+ if (inlineCallCount == MAX_INLINE_CALL_COUNT) {
+ js_ReportOverRecursed(cx);
+ goto error;
+ }
+
+ /* Compute the total number of stack slots needed by fun. */
+ nframeslots = JS_HOWMANY(sizeof(JSInlineFrame),
+ sizeof(jsval));
+ script = fun->u.i.script;
+ atoms = script->atomMap.vector;
+ nbytes = (nframeslots + script->nslots) * sizeof(jsval);
+
+ /* Allocate missing expected args adjacent to actuals. */
+ a = cx->stackPool.current;
+ newmark = (void *) a->avail;
+ if (fun->nargs <= argc) {
+ missing = 0;
+ } else {
+ newsp = vp + 2 + fun->nargs;
+ JS_ASSERT(newsp > regs.sp);
+ if ((jsuword) newsp <= a->limit) {
+ if ((jsuword) newsp > a->avail)
+ a->avail = (jsuword) newsp;
+ jsval *argsp = newsp;
+ do {
+ *--argsp = JSVAL_VOID;
+ } while (argsp != regs.sp);
+ missing = 0;
+ } else {
+ missing = fun->nargs - argc;
+ nbytes += (2 + fun->nargs) * sizeof(jsval);
+ }
+ }
+
+ /* Allocate the inline frame with its slots and operands. */
+ if (a->avail + nbytes <= a->limit) {
+ newsp = (jsval *) a->avail;
+ a->avail += nbytes;
+ JS_ASSERT(missing == 0);
+ } else {
+ JS_ARENA_ALLOCATE_CAST(newsp, jsval *, &cx->stackPool,
+ nbytes);
+ if (!newsp) {
+ js_ReportOutOfScriptQuota(cx);
+ goto bad_inline_call;
+ }
+
+ /*
+ * Move args if the missing ones overflow arena a, then
+ * push undefined for the missing args.
+ */
+ if (missing) {
+ memcpy(newsp, vp, (2 + argc) * sizeof(jsval));
+ vp = newsp;
+ newsp = vp + 2 + argc;
+ do {
+ *newsp++ = JSVAL_VOID;
+ } while (--missing != 0);
+ }
+ }
+
+ /* Claim space for the stack frame and initialize it. */
+ newifp = (JSInlineFrame *) newsp;
+ newsp += nframeslots;
+ newifp->frame.callobj = NULL;
+ newifp->frame.argsobj = NULL;
+ newifp->frame.varobj = NULL;
+ newifp->frame.script = script;
+ newifp->frame.callee = obj;
+ newifp->frame.fun = fun;
+ newifp->frame.argc = argc;
+ newifp->frame.argv = vp + 2;
+ newifp->frame.rval = JSVAL_VOID;
+ newifp->frame.down = fp;
+ newifp->frame.annotation = NULL;
+ newifp->frame.scopeChain = parent = OBJ_GET_PARENT(cx, obj);
+ newifp->frame.sharpDepth = 0;
+ newifp->frame.sharpArray = NULL;
+ newifp->frame.flags = flags;
+ newifp->frame.dormantNext = NULL;
+ newifp->frame.xmlNamespace = NULL;
+ newifp->frame.blockChain = NULL;
+ if (script->staticDepth < JS_DISPLAY_SIZE) {
+ JSStackFrame **disp = &cx->display[script->staticDepth];
+ newifp->frame.displaySave = *disp;
+ *disp = &newifp->frame;
+ }
+#ifdef DEBUG
+ newifp->frame.pcDisabledSave =
+ JS_PROPERTY_CACHE(cx).disabled;
+#endif
+ newifp->mark = newmark;
+
+ /* Compute the 'this' parameter now that argv is set. */
+ JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(fun->flags));
+ JS_ASSERT(JSVAL_IS_OBJECT(vp[1]));
+ newifp->frame.thisp = (JSObject *)vp[1];
+
+ newifp->frame.regs = NULL;
+ newifp->frame.imacpc = NULL;
+ newifp->frame.slots = newsp;
+
+ /* Push void to initialize local variables. */
+ nvars = fun->u.i.nvars;
+ while (nvars--)
+ *newsp++ = JSVAL_VOID;
+
+ /* Call the debugger hook if present. */
+ hook = cx->debugHooks->callHook;
+ if (hook) {
+ newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0,
+ cx->debugHooks->callHookData);
+ LOAD_INTERRUPT_HANDLER(cx);
+ } else {
+ newifp->hookData = NULL;
+ }
+
+ /* Scope with a call object parented by callee's parent. */
+ if (JSFUN_HEAVYWEIGHT_TEST(fun->flags) &&
+ !js_GetCallObject(cx, &newifp->frame, parent)) {
+ goto bad_inline_call;
+ }
+
+ /* Switch version if currentVersion wasn't overridden. */
+ newifp->callerVersion = (JSVersion) cx->version;
+ if (JS_LIKELY(cx->version == currentVersion)) {
+ currentVersion = (JSVersion) script->version;
+ if (currentVersion != cx->version)
+ js_SetVersion(cx, currentVersion);
+ }
+
+ /* Push the frame and set interpreter registers. */
+ newifp->callerRegs = regs;
+ fp->regs = &newifp->callerRegs;
+ regs.sp = newsp;
+ regs.pc = script->code;
+ newifp->frame.regs = &regs;
+ cx->fp = fp = &newifp->frame;
+
+ TRACE_0(EnterFrame);
+
+ inlineCallCount++;
+ JS_RUNTIME_METER(rt, inlineCalls);
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ /* DTrace function entry, inlines */
+ if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
+ jsdtrace_function_entry(cx, fp, fun);
+ if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
+ jsdtrace_function_info(cx, fp, fp->down, fun);
+ if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
+ jsdtrace_function_args(cx, fp, fun);
+#endif
+
+ /* Load first op and dispatch it (safe since JSOP_STOP). */
+ op = (JSOp) *regs.pc;
+ DO_OP();
+
+ bad_inline_call:
+ JS_ASSERT(fp->regs == &regs);
+ script = fp->script;
+ atoms = script->atomMap.vector;
+ js_FreeRawStack(cx, newmark);
+ goto error;
+ }
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ /* DTrace function entry, non-inlines */
+ if (VALUE_IS_FUNCTION(cx, lval)) {
+ if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
+ jsdtrace_function_entry(cx, fp, fun);
+ if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
+ jsdtrace_function_info(cx, fp, fp, fun);
+ if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
+ jsdtrace_function_args(cx, fp, fun);
+ }
+#endif
+
+ if (fun->flags & JSFUN_FAST_NATIVE) {
+ JS_ASSERT(fun->u.n.extra == 0);
+ JS_ASSERT(JSVAL_IS_OBJECT(vp[1]) ||
+ PRIMITIVE_THIS_TEST(fun, vp[1]));
+ ok = ((JSFastNative) fun->u.n.native)(cx, argc, vp);
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (VALUE_IS_FUNCTION(cx, lval)) {
+ if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
+ jsdtrace_function_rval(cx, fp, fun);
+ if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
+ jsdtrace_function_return(cx, fp, fun);
+ }
+#endif
+ regs.sp = vp + 1;
+ if (!ok)
+ goto error;
+ TRACE_0(FastNativeCallComplete);
+ goto end_call;
+ }
+ }
+
+ ok = js_Invoke(cx, argc, vp, 0);
+#ifdef INCLUDE_MOZILLA_DTRACE
+ /* DTrace function return, non-inlines */
+ if (VALUE_IS_FUNCTION(cx, lval)) {
+ if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
+ jsdtrace_function_rval(cx, fp, fun);
+ if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
+ jsdtrace_function_return(cx, fp, fun);
+ }
+#endif
+ regs.sp = vp + 1;
+ LOAD_INTERRUPT_HANDLER(cx);
+ if (!ok)
+ goto error;
+ JS_RUNTIME_METER(rt, nonInlineCalls);
+
+ end_call:
+#if JS_HAS_LVALUE_RETURN
+ if (cx->rval2set) {
+ /*
+ * Use the stack depth we didn't claim in our budget, but that
+ * we know is there on account of [fun, this] already having
+ * been pushed, at a minimum (if no args). Those two slots
+ * have been popped and [rval] has been pushed, which leaves
+ * one more slot for rval2 before we might overflow.
+ *
+ * NB: rval2 must be the property identifier, and rval the
+ * object from which to get the property. The pair form an
+ * ECMA "reference type", which can be used on the right- or
+ * left-hand side of assignment ops. Note well: only native
+ * methods can return reference types. See JSOP_SETCALL just
+ * below for the left-hand-side case.
+ */
+ PUSH_OPND(cx->rval2);
+ ELEMENT_OP(-1, OBJ_GET_PROPERTY(cx, obj, id, &rval));
+
+ regs.sp--;
+ STORE_OPND(-1, rval);
+ cx->rval2set = JS_FALSE;
+ }
+#endif /* JS_HAS_LVALUE_RETURN */
+ END_CASE(JSOP_CALL)
+
+#if JS_HAS_LVALUE_RETURN
+ BEGIN_CASE(JSOP_SETCALL)
+ argc = GET_ARGC(regs.pc);
+ vp = regs.sp - argc - 2;
+ ok = js_Invoke(cx, argc, vp, 0);
+ regs.sp = vp + 1;
+ LOAD_INTERRUPT_HANDLER(cx);
+ if (!ok)
+ goto error;
+ if (!cx->rval2set) {
+ op2 = (JSOp) regs.pc[JSOP_SETCALL_LENGTH];
+ if (op2 != JSOP_DELELEM) {
+ JS_ASSERT(!(js_CodeSpec[op2].format & JOF_DEL));
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_LEFTSIDE_OF_ASS);
+ goto error;
+ }
+
+ /*
+ * Store true as the result of the emulated delete of a
+ * non-existent property. NB: We don't METER_OP_PAIR here;
+ * it doesn't seem worth the code for this obscure case.
+ */
+ *vp = JSVAL_TRUE;
+ regs.pc += JSOP_SETCALL_LENGTH + JSOP_DELELEM_LENGTH;
+ op = (JSOp) *regs.pc;
+ DO_OP();
+ }
+ PUSH_OPND(cx->rval2);
+ cx->rval2set = JS_FALSE;
+ END_CASE(JSOP_SETCALL)
+#endif
+
+ BEGIN_CASE(JSOP_NAME)
+ BEGIN_CASE(JSOP_CALLNAME)
+ {
+ JSPropCacheEntry *entry;
+
+ obj = fp->scopeChain;
+ if (JS_LIKELY(OBJ_IS_NATIVE(obj))) {
+ PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);
+ if (!atom) {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
+ if (PCVAL_IS_OBJECT(entry->vword)) {
+ rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);
+ JS_UNLOCK_OBJ(cx, obj2);
+ goto do_push_rval;
+ }
+
+ if (PCVAL_IS_SLOT(entry->vword)) {
+ slot = PCVAL_TO_SLOT(entry->vword);
+ JS_ASSERT(slot < obj2->map->freeslot);
+ rval = LOCKED_OBJ_GET_SLOT(obj2, slot);
+ JS_UNLOCK_OBJ(cx, obj2);
+ goto do_push_rval;
+ }
+
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ goto do_native_get;
+ }
+ } else {
+ entry = NULL;
+ LOAD_ATOM(0);
+ }
+
+ id = ATOM_TO_JSID(atom);
+ if (js_FindPropertyHelper(cx, id, &obj, &obj2, &prop, &entry) < 0)
+ goto error;
+ if (!prop) {
+ /* Kludge to allow (typeof foo == "undefined") tests. */
+ endpc = script->code + script->length;
+ op2 = (JSOp) regs.pc[JSOP_NAME_LENGTH];
+ if (op2 == JSOP_TYPEOF) {
+ PUSH_OPND(JSVAL_VOID);
+ len = JSOP_NAME_LENGTH;
+ DO_NEXT_OP(len);
+ }
+ goto atom_not_defined;
+ }
+
+ /* Take the slow path if prop was not found in a native object. */
+ if (!OBJ_IS_NATIVE(obj) || !OBJ_IS_NATIVE(obj2)) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ entry = NULL;
+ } else {
+ sprop = (JSScopeProperty *)prop;
+ do_native_get:
+ NATIVE_GET(cx, obj, obj2, sprop, &rval);
+ OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *) sprop);
+ }
+
+ do_push_rval:
+ PUSH_OPND(rval);
+ if (op == JSOP_CALLNAME)
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ }
+ END_CASE(JSOP_NAME)
+
+ BEGIN_CASE(JSOP_UINT16)
+ i = (jsint) GET_UINT16(regs.pc);
+ rval = INT_TO_JSVAL(i);
+ PUSH_OPND(rval);
+ END_CASE(JSOP_UINT16)
+
+ BEGIN_CASE(JSOP_UINT24)
+ i = (jsint) GET_UINT24(regs.pc);
+ rval = INT_TO_JSVAL(i);
+ PUSH_OPND(rval);
+ END_CASE(JSOP_UINT24)
+
+ BEGIN_CASE(JSOP_INT8)
+ i = GET_INT8(regs.pc);
+ rval = INT_TO_JSVAL(i);
+ PUSH_OPND(rval);
+ END_CASE(JSOP_INT8)
+
+ BEGIN_CASE(JSOP_INT32)
+ i = GET_INT32(regs.pc);
+ rval = INT_TO_JSVAL(i);
+ PUSH_OPND(rval);
+ END_CASE(JSOP_INT32)
+
+ BEGIN_CASE(JSOP_INDEXBASE)
+ /*
+ * Here atoms can exceed script->atomMap.length as we use atoms
+ * as a segment register for object literals as well.
+ */
+ atoms += GET_INDEXBASE(regs.pc);
+ END_CASE(JSOP_INDEXBASE)
+
+ BEGIN_CASE(JSOP_INDEXBASE1)
+ BEGIN_CASE(JSOP_INDEXBASE2)
+ BEGIN_CASE(JSOP_INDEXBASE3)
+ atoms += (op - JSOP_INDEXBASE1 + 1) << 16;
+ END_CASE(JSOP_INDEXBASE3)
+
+ BEGIN_CASE(JSOP_RESETBASE0)
+ BEGIN_CASE(JSOP_RESETBASE)
+ atoms = script->atomMap.vector;
+ END_CASE(JSOP_RESETBASE)
+
+ BEGIN_CASE(JSOP_DOUBLE)
+ BEGIN_CASE(JSOP_STRING)
+ LOAD_ATOM(0);
+ PUSH_OPND(ATOM_KEY(atom));
+ END_CASE(JSOP_DOUBLE)
+
+ BEGIN_CASE(JSOP_OBJECT)
+ LOAD_OBJECT(0);
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_OBJECT)
+
+ BEGIN_CASE(JSOP_REGEXP)
+ {
+ JSObject *funobj;
+
+ /*
+ * Push a regexp object for the atom mapped by the bytecode at pc,
+ * cloning the literal's regexp object if necessary, to simulate in
+ * the pre-compile/execute-later case what ECMA specifies for the
+ * compile-and-go case: that scanning each regexp literal creates
+ * a single corresponding RegExp object.
+ *
+ * To support pre-compilation transparently, we must handle the
+ * case where a regexp object literal is used in a different global
+ * at execution time from the global with which it was scanned at
+ * compile time. We do this by re-wrapping the JSRegExp private
+ * data struct with a cloned object having the right prototype and
+ * parent, and having its own lastIndex property value storage.
+ *
+ * Unlike JSOP_DEFFUN and other prolog bytecodes that may clone
+ * literal objects, we don't want to pay a script prolog execution
+ * price for all regexp literals in a script (many may not be used
+ * by a particular execution of that script, depending on control
+ * flow), so we initialize lazily here.
+ *
+ * XXX This code is specific to regular expression objects. If we
+ * need a similar op for other kinds of object literals, we should
+ * push cloning down under JSObjectOps and reuse code here.
+ */
+ index = GET_FULL_INDEX(0);
+ JS_ASSERT(index < JS_SCRIPT_REGEXPS(script)->length);
+
+ slot = index;
+ if (fp->fun) {
+ /*
+ * We're in function code, not global or eval code (in eval
+ * code, JSOP_REGEXP is never emitted). The cloned funobj
+ * contains JS_SCRIPT_REGEXPS(script)->length reserved slots
+ * for the cloned regexps; see fun_reserveSlots, jsfun.c.
+ */
+ funobj = fp->callee;
+ slot += JSCLASS_RESERVED_SLOTS(&js_FunctionClass);
+ if (script->upvarsOffset != 0)
+ slot += JS_SCRIPT_UPVARS(script)->length;
+ if (!JS_GetReservedSlot(cx, funobj, slot, &rval))
+ goto error;
+ if (JSVAL_IS_VOID(rval))
+ rval = JSVAL_NULL;
+ } else {
+ /*
+ * We're in global code. The code generator reserved a slot
+ * for the regexp among script->nfixed slots. All such slots
+ * are initialized to null, not void, for faster testing in
+ * JSOP_*GVAR cases. To simplify index calculations we count
+ * regexps in the reverse order down from script->nslots - 1.
+ */
+ JS_ASSERT(slot < script->nfixed);
+ slot = script->nfixed - slot - 1;
+ rval = fp->slots[slot];
+#ifdef __GNUC__
+ funobj = NULL; /* suppress bogus gcc warnings */
+#endif
+ }
+
+ if (JSVAL_IS_NULL(rval)) {
+ /* Compute the current global object in obj2. */
+ obj2 = fp->scopeChain;
+ while ((parent = OBJ_GET_PARENT(cx, obj2)) != NULL)
+ obj2 = parent;
+
+ /*
+ * If obj's parent is not obj2, we must clone obj so that it
+ * has the right parent, and therefore, the right prototype.
+ *
+ * Yes, this means we assume that the correct RegExp.prototype
+ * to which regexp instances (including literals) delegate can
+ * be distinguished solely by the instance's parent, which was
+ * set to the parent of the RegExp constructor function object
+ * when the instance was created. In other words,
+ *
+ * (/x/.__parent__ == RegExp.__parent__) implies
+ * (/x/.__proto__ == RegExp.prototype)
+ *
+ * (unless you assign a different object to RegExp.prototype
+ * at runtime, in which case, ECMA doesn't specify operation,
+ * and you get what you deserve).
+ *
+ * This same coupling between instance parent and constructor
+ * parent turns up everywhere (see jsobj.c's FindClassObject,
+ * js_ConstructObject, and js_NewObject). It's fundamental to
+ * the design of the language when you consider multiple global
+ * objects and separate compilation and execution, even though
+ * it is not specified fully in ECMA.
+ */
+ JS_GET_SCRIPT_REGEXP(script, index, obj);
+ if (OBJ_GET_PARENT(cx, obj) != obj2) {
+ obj = js_CloneRegExpObject(cx, obj, obj2);
+ if (!obj)
+ goto error;
+ }
+ rval = OBJECT_TO_JSVAL(obj);
+
+ /* Store the regexp object value in its cloneIndex slot. */
+ if (fp->fun) {
+ if (!JS_SetReservedSlot(cx, funobj, slot, rval))
+ goto error;
+ } else {
+ fp->slots[slot] = rval;
+ }
+ }
+
+ PUSH_OPND(rval);
+ }
+ END_CASE(JSOP_REGEXP)
+
+ BEGIN_CASE(JSOP_ZERO)
+ PUSH_OPND(JSVAL_ZERO);
+ END_CASE(JSOP_ZERO)
+
+ BEGIN_CASE(JSOP_ONE)
+ PUSH_OPND(JSVAL_ONE);
+ END_CASE(JSOP_ONE)
+
+ BEGIN_CASE(JSOP_NULL)
+ BEGIN_CASE(JSOP_NULLTHIS)
+ PUSH_OPND(JSVAL_NULL);
+ END_CASE(JSOP_NULL)
+
+ BEGIN_CASE(JSOP_FALSE)
+ PUSH_OPND(JSVAL_FALSE);
+ END_CASE(JSOP_FALSE)
+
+ BEGIN_CASE(JSOP_TRUE)
+ PUSH_OPND(JSVAL_TRUE);
+ END_CASE(JSOP_TRUE)
+
+ BEGIN_CASE(JSOP_TABLESWITCH)
+ pc2 = regs.pc;
+ len = GET_JUMP_OFFSET(pc2);
+
+ /*
+ * ECMAv2+ forbids conversion of discriminant, so we will skip to
+ * the default case if the discriminant isn't already an int jsval.
+ * (This opcode is emitted only for dense jsint-domain switches.)
+ */
+ rval = POP_OPND();
+ if (JSVAL_IS_INT(rval)) {
+ i = JSVAL_TO_INT(rval);
+ } else if (JSVAL_IS_DOUBLE(rval) && *JSVAL_TO_DOUBLE(rval) == 0) {
+ /* Treat -0 (double) as 0. */
+ i = 0;
+ } else {
+ DO_NEXT_OP(len);
+ }
+
+ pc2 += JUMP_OFFSET_LEN;
+ low = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc2);
+
+ i -= low;
+ if ((jsuint)i < (jsuint)(high - low + 1)) {
+ pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i;
+ off = (jsint) GET_JUMP_OFFSET(pc2);
+ if (off)
+ len = off;
+ }
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_TABLESWITCHX)
+ pc2 = regs.pc;
+ len = GET_JUMPX_OFFSET(pc2);
+
+ /*
+ * ECMAv2+ forbids conversion of discriminant, so we will skip to
+ * the default case if the discriminant isn't already an int jsval.
+ * (This opcode is emitted only for dense jsint-domain switches.)
+ */
+ rval = POP_OPND();
+ if (JSVAL_IS_INT(rval)) {
+ i = JSVAL_TO_INT(rval);
+ } else if (JSVAL_IS_DOUBLE(rval) && *JSVAL_TO_DOUBLE(rval) == 0) {
+ /* Treat -0 (double) as 0. */
+ i = 0;
+ } else {
+ DO_NEXT_OP(len);
+ }
+
+ pc2 += JUMPX_OFFSET_LEN;
+ low = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc2);
+
+ i -= low;
+ if ((jsuint)i < (jsuint)(high - low + 1)) {
+ pc2 += JUMP_OFFSET_LEN + JUMPX_OFFSET_LEN * i;
+ off = (jsint) GET_JUMPX_OFFSET(pc2);
+ if (off)
+ len = off;
+ }
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_LOOKUPSWITCHX)
+ off = JUMPX_OFFSET_LEN;
+ goto do_lookup_switch;
+
+ BEGIN_CASE(JSOP_LOOKUPSWITCH)
+ off = JUMP_OFFSET_LEN;
+
+ do_lookup_switch:
+ /*
+ * JSOP_LOOKUPSWITCH and JSOP_LOOKUPSWITCHX are never used if
+ * any atom index in it would exceed 64K limit.
+ */
+ JS_ASSERT(atoms == script->atomMap.vector);
+ pc2 = regs.pc;
+ lval = POP_OPND();
+
+ if (!JSVAL_IS_NUMBER(lval) &&
+ !JSVAL_IS_STRING(lval) &&
+ !JSVAL_IS_BOOLEAN(lval)) {
+ goto end_lookup_switch;
+ }
+
+ pc2 += off;
+ npairs = (jsint) GET_UINT16(pc2);
+ pc2 += UINT16_LEN;
+ JS_ASSERT(npairs); /* empty switch uses JSOP_TABLESWITCH */
+
+#define SEARCH_PAIRS(MATCH_CODE) \
+ for (;;) { \
+ JS_ASSERT(GET_INDEX(pc2) < script->atomMap.length); \
+ atom = atoms[GET_INDEX(pc2)]; \
+ rval = ATOM_KEY(atom); \
+ MATCH_CODE \
+ pc2 += INDEX_LEN; \
+ if (match) \
+ break; \
+ pc2 += off; \
+ if (--npairs == 0) { \
+ pc2 = regs.pc; \
+ break; \
+ } \
+ }
+ if (JSVAL_IS_STRING(lval)) {
+ str = JSVAL_TO_STRING(lval);
+ SEARCH_PAIRS(
+ match = (JSVAL_IS_STRING(rval) &&
+ ((str2 = JSVAL_TO_STRING(rval)) == str ||
+ js_EqualStrings(str2, str)));
+ )
+ } else if (JSVAL_IS_DOUBLE(lval)) {
+ d = *JSVAL_TO_DOUBLE(lval);
+ SEARCH_PAIRS(
+ match = (JSVAL_IS_DOUBLE(rval) &&
+ *JSVAL_TO_DOUBLE(rval) == d);
+ )
+ } else {
+ SEARCH_PAIRS(
+ match = (lval == rval);
+ )
+ }
+#undef SEARCH_PAIRS
+
+ end_lookup_switch:
+ len = (op == JSOP_LOOKUPSWITCH)
+ ? GET_JUMP_OFFSET(pc2)
+ : GET_JUMPX_OFFSET(pc2);
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_TRAP)
+ {
+ JSTrapStatus status;
+
+ status = JS_HandleTrap(cx, script, regs.pc, &rval);
+ switch (status) {
+ case JSTRAP_ERROR:
+ goto error;
+ case JSTRAP_RETURN:
+ fp->rval = rval;
+ ok = JS_TRUE;
+ goto forced_return;
+ case JSTRAP_THROW:
+ cx->throwing = JS_TRUE;
+ cx->exception = rval;
+ goto error;
+ default:;
+ break;
+ }
+ JS_ASSERT(status == JSTRAP_CONTINUE);
+ LOAD_INTERRUPT_HANDLER(cx);
+ JS_ASSERT(JSVAL_IS_INT(rval));
+ op = (JSOp) JSVAL_TO_INT(rval);
+ JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT);
+ DO_OP();
+ }
+
+ BEGIN_CASE(JSOP_ARGUMENTS)
+ if (!js_GetArgsValue(cx, fp, &rval))
+ goto error;
+ PUSH_OPND(rval);
+ END_CASE(JSOP_ARGUMENTS)
+
+ BEGIN_CASE(JSOP_ARGSUB)
+ id = INT_TO_JSID(GET_ARGNO(regs.pc));
+ if (!js_GetArgsProperty(cx, fp, id, &rval))
+ goto error;
+ PUSH_OPND(rval);
+ END_CASE(JSOP_ARGSUB)
+
+ BEGIN_CASE(JSOP_ARGCNT)
+ id = ATOM_TO_JSID(rt->atomState.lengthAtom);
+ if (!js_GetArgsProperty(cx, fp, id, &rval))
+ goto error;
+ PUSH_OPND(rval);
+ END_CASE(JSOP_ARGCNT)
+
+ BEGIN_CASE(JSOP_GETARG)
+ BEGIN_CASE(JSOP_CALLARG)
+ slot = GET_ARGNO(regs.pc);
+ JS_ASSERT(slot < fp->fun->nargs);
+ METER_SLOT_OP(op, slot);
+ PUSH_OPND(fp->argv[slot]);
+ if (op == JSOP_CALLARG)
+ PUSH_OPND(JSVAL_NULL);
+ END_CASE(JSOP_GETARG)
+
+ BEGIN_CASE(JSOP_SETARG)
+ slot = GET_ARGNO(regs.pc);
+ JS_ASSERT(slot < fp->fun->nargs);
+ METER_SLOT_OP(op, slot);
+ vp = &fp->argv[slot];
+ GC_POKE(cx, *vp);
+ *vp = FETCH_OPND(-1);
+ END_SET_CASE(JSOP_SETARG)
+
+ BEGIN_CASE(JSOP_GETLOCAL)
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < script->nslots);
+ PUSH_OPND(fp->slots[slot]);
+ END_CASE(JSOP_GETLOCAL)
+
+ BEGIN_CASE(JSOP_CALLLOCAL)
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < script->nslots);
+ PUSH_OPND(fp->slots[slot]);
+ PUSH_OPND(JSVAL_NULL);
+ END_CASE(JSOP_CALLLOCAL)
+
+ BEGIN_CASE(JSOP_SETLOCAL)
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < script->nslots);
+ vp = &fp->slots[slot];
+ GC_POKE(cx, *vp);
+ *vp = FETCH_OPND(-1);
+ END_SET_CASE(JSOP_SETLOCAL)
+
+ BEGIN_CASE(JSOP_GETUPVAR)
+ BEGIN_CASE(JSOP_CALLUPVAR)
+ {
+ JSUpvarArray *uva;
+ uint32 skip;
+ JSStackFrame *fp2;
+
+ index = GET_UINT16(regs.pc);
+ uva = JS_SCRIPT_UPVARS(script);
+ JS_ASSERT(index < uva->length);
+ skip = UPVAR_FRAME_SKIP(uva->vector[index]);
+ fp2 = cx->display[script->staticDepth - skip];
+ JS_ASSERT(fp2->fun && fp2->script);
+
+ slot = UPVAR_FRAME_SLOT(uva->vector[index]);
+ if (slot < fp2->fun->nargs) {
+ vp = fp2->argv;
+ } else {
+ slot -= fp2->fun->nargs;
+ JS_ASSERT(slot < fp2->script->nslots);
+ vp = fp2->slots;
+ }
+
+ PUSH_OPND(vp[slot]);
+ if (op == JSOP_CALLUPVAR)
+ PUSH_OPND(JSVAL_NULL);
+ }
+ END_CASE(JSOP_GETUPVAR)
+
+ BEGIN_CASE(JSOP_GETGVAR)
+ BEGIN_CASE(JSOP_CALLGVAR)
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < GlobalVarCount(fp));
+ METER_SLOT_OP(op, slot);
+ lval = fp->slots[slot];
+ if (JSVAL_IS_NULL(lval)) {
+ op = (op == JSOP_GETGVAR) ? JSOP_NAME : JSOP_CALLNAME;
+ DO_OP();
+ }
+ obj = fp->varobj;
+ slot = JSVAL_TO_INT(lval);
+ rval = OBJ_GET_SLOT(cx, obj, slot);
+ PUSH_OPND(rval);
+ if (op == JSOP_CALLGVAR)
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_GETGVAR)
+
+ BEGIN_CASE(JSOP_SETGVAR)
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < GlobalVarCount(fp));
+ METER_SLOT_OP(op, slot);
+ rval = FETCH_OPND(-1);
+ obj = fp->varobj;
+ lval = fp->slots[slot];
+ if (JSVAL_IS_NULL(lval)) {
+ /*
+ * Inline-clone and deoptimize JSOP_SETNAME code here because
+ * JSOP_SETGVAR has arity 1: [rval], not arity 2: [obj, rval]
+ * as JSOP_SETNAME does, where [obj] is due to JSOP_BINDNAME.
+ */
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ } else {
+ slot = JSVAL_TO_INT(lval);
+ JS_LOCK_OBJ(cx, obj);
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, rval);
+ JS_UNLOCK_OBJ(cx, obj);
+ }
+ END_SET_CASE(JSOP_SETGVAR)
+
+ BEGIN_CASE(JSOP_DEFCONST)
+ BEGIN_CASE(JSOP_DEFVAR)
+ index = GET_INDEX(regs.pc);
+ atom = atoms[index];
+
+ /*
+ * index is relative to atoms at this point but for global var
+ * code below we need the absolute value.
+ */
+ index += atoms - script->atomMap.vector;
+ obj = fp->varobj;
+ attrs = JSPROP_ENUMERATE;
+ if (!(fp->flags & JSFRAME_EVAL))
+ attrs |= JSPROP_PERMANENT;
+ if (op == JSOP_DEFCONST)
+ attrs |= JSPROP_READONLY;
+
+ /* Lookup id in order to check for redeclaration problems. */
+ id = ATOM_TO_JSID(atom);
+ if (!js_CheckRedeclaration(cx, obj, id, attrs, &obj2, &prop))
+ goto error;
+
+ /* Bind a variable only if it's not yet defined. */
+ if (!prop) {
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
+ JS_PropertyStub, JS_PropertyStub,
+ attrs, &prop)) {
+ goto error;
+ }
+ JS_ASSERT(prop);
+ obj2 = obj;
+ }
+
+ /*
+ * Try to optimize a property we either just created, or found
+ * directly in the global object, that is permanent, has a slot,
+ * and has stub getter and setter, into a "fast global" accessed
+ * by the JSOP_*GVAR opcodes.
+ */
+ if (!fp->fun &&
+ index < GlobalVarCount(fp) &&
+ (attrs & JSPROP_PERMANENT) &&
+ obj2 == obj &&
+ OBJ_IS_NATIVE(obj)) {
+ sprop = (JSScopeProperty *) prop;
+ if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)) &&
+ SPROP_HAS_STUB_GETTER(sprop) &&
+ SPROP_HAS_STUB_SETTER(sprop)) {
+ /*
+ * Fast globals use frame variables to map the global
+ * name's atom index to the permanent fp->varobj slot
+ * number, tagged as a jsval. The atom index for the
+ * global's name literal is identical to its variable
+ * index.
+ */
+ fp->slots[index] = INT_TO_JSVAL(sprop->slot);
+ }
+ }
+
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ END_CASE(JSOP_DEFVAR)
+
+ BEGIN_CASE(JSOP_DEFFUN)
+ /*
+ * A top-level function defined in Global or Eval code (see
+ * ECMA-262 Ed. 3), or else a SpiderMonkey extension: a named
+ * function statement in a compound statement (not at the top
+ * statement level of global code, or at the top level of a
+ * function body).
+ */
+ LOAD_FUNCTION(0);
+
+ if (!fp->blockChain) {
+ obj2 = fp->scopeChain;
+ } else {
+ obj2 = js_GetScopeChain(cx, fp);
+ if (!obj2)
+ goto error;
+ }
+
+ /*
+ * If static link is not current scope, clone fun's object to link
+ * to the current scope via parent. This clause exists to enable
+ * sharing of compiled functions among multiple equivalent scopes,
+ * splitting the cost of compilation evenly among the scopes and
+ * amortizing it over a number of executions. Examples include XUL
+ * scripts and event handlers shared among Mozilla chrome windows,
+ * and server-side JS user-defined functions shared among requests.
+ */
+ obj = FUN_OBJECT(fun);
+ if (OBJ_GET_PARENT(cx, obj) != obj2) {
+ obj = js_CloneFunctionObject(cx, fun, obj2);
+ if (!obj)
+ goto error;
+ }
+
+ /*
+ * Protect obj from any GC hiding below OBJ_DEFINE_PROPERTY. All
+ * paths from here must flow through the "Restore fp->scopeChain"
+ * code below the OBJ_DEFINE_PROPERTY call.
+ */
+ MUST_FLOW_THROUGH("restore");
+ fp->scopeChain = obj;
+ rval = OBJECT_TO_JSVAL(obj);
+
+ /*
+ * ECMA requires functions defined when entering Eval code to be
+ * impermanent.
+ */
+ attrs = (fp->flags & JSFRAME_EVAL)
+ ? JSPROP_ENUMERATE
+ : JSPROP_ENUMERATE | JSPROP_PERMANENT;
+
+ /*
+ * Load function flags that are also property attributes. Getters
+ * and setters do not need a slot, their value is stored elsewhere
+ * in the property itself, not in obj slots.
+ */
+ flags = JSFUN_GSFLAG2ATTR(fun->flags);
+ if (flags) {
+ attrs |= flags | JSPROP_SHARED;
+ rval = JSVAL_VOID;
+ }
+
+ /*
+ * We define the function as a property of the variable object and
+ * not the current scope chain even for the case of function
+ * expression statements and functions defined by eval inside let
+ * or with blocks.
+ */
+ parent = fp->varobj;
+ JS_ASSERT(parent);
+
+ /*
+ * Check for a const property of the same name -- or any kind
+ * of property if executing with the strict option. We check
+ * here at runtime as well as at compile-time, to handle eval
+ * as well as multiple HTML script tags.
+ */
+ id = ATOM_TO_JSID(fun->atom);
+ ok = js_CheckRedeclaration(cx, parent, id, attrs, NULL, NULL);
+ if (ok) {
+ if (attrs == JSPROP_ENUMERATE) {
+ JS_ASSERT(fp->flags & JSFRAME_EVAL);
+ ok = OBJ_SET_PROPERTY(cx, parent, id, &rval);
+ } else {
+ JS_ASSERT(attrs & JSPROP_PERMANENT);
+
+ ok = OBJ_DEFINE_PROPERTY(cx, parent, id, rval,
+ (flags & JSPROP_GETTER)
+ ? JS_EXTENSION (JSPropertyOp) obj
+ : JS_PropertyStub,
+ (flags & JSPROP_SETTER)
+ ? JS_EXTENSION (JSPropertyOp) obj
+ : JS_PropertyStub,
+ attrs,
+ NULL);
+ }
+ }
+
+ /* Restore fp->scopeChain now that obj is defined in fp->varobj. */
+ MUST_FLOW_LABEL(restore)
+ fp->scopeChain = obj2;
+ if (!ok) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ goto error;
+ }
+ END_CASE(JSOP_DEFFUN)
+
+ BEGIN_CASE(JSOP_DEFLOCALFUN)
+ LOAD_FUNCTION(SLOTNO_LEN);
+
+ /*
+ * Define a local function (i.e., one nested at the top level of
+ * another function), parented by the current scope chain, and
+ * stored in a local variable slot that the compiler allocated.
+ * This is an optimization over JSOP_DEFFUN that avoids requiring
+ * a call object for the outer function's activation.
+ */
+ slot = GET_SLOTNO(regs.pc);
+
+ parent = js_GetScopeChain(cx, fp);
+ if (!parent)
+ goto error;
+
+ obj = FUN_OBJECT(fun);
+ if (OBJ_GET_PARENT(cx, obj) != parent) {
+ obj = js_CloneFunctionObject(cx, fun, parent);
+ if (!obj)
+ goto error;
+ }
+
+ TRACE_2(DefLocalFunSetSlot, slot, obj);
+
+ fp->slots[slot] = OBJECT_TO_JSVAL(obj);
+ END_CASE(JSOP_DEFLOCALFUN)
+
+ BEGIN_CASE(JSOP_ANONFUNOBJ)
+ /* Load the specified function object literal. */
+ LOAD_FUNCTION(0);
+
+ /* If re-parenting, push a clone of the function object. */
+ parent = js_GetScopeChain(cx, fp);
+ if (!parent)
+ goto error;
+ obj = FUN_OBJECT(fun);
+ if (OBJ_GET_PARENT(cx, obj) != parent) {
+ obj = js_CloneFunctionObject(cx, fun, parent);
+ if (!obj)
+ goto error;
+ }
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_ANONFUNOBJ)
+
+ BEGIN_CASE(JSOP_NAMEDFUNOBJ)
+ LOAD_FUNCTION(0);
+
+ /*
+ * ECMA ed. 3 FunctionExpression: function Identifier [etc.].
+ *
+ * 1. Create a new object as if by the expression new Object().
+ * 2. Add Result(1) to the front of the scope chain.
+ *
+ * Step 2 is achieved by making the new object's parent be the
+ * current scope chain, and then making the new object the parent
+ * of the Function object clone.
+ */
+ obj2 = js_GetScopeChain(cx, fp);
+ if (!obj2)
+ goto error;
+ parent = js_NewObject(cx, &js_ObjectClass, NULL, obj2, 0);
+ if (!parent)
+ goto error;
+
+ /*
+ * 3. Create a new Function object as specified in section 13.2
+ * with [parameters and body specified by the function expression
+ * that was parsed by the compiler into a Function object, and
+ * saved in the script's atom map].
+ *
+ * Protect parent from the GC.
+ */
+ fp->scopeChain = parent;
+ obj = js_CloneFunctionObject(cx, fun, parent);
+ if (!obj)
+ goto error;
+
+ /*
+ * Protect obj from any GC hiding below OBJ_DEFINE_PROPERTY. All
+ * paths from here must flow through the "Restore fp->scopeChain"
+ * code below the OBJ_DEFINE_PROPERTY call.
+ */
+ MUST_FLOW_THROUGH("restore2");
+ fp->scopeChain = obj;
+ rval = OBJECT_TO_JSVAL(obj);
+
+ /*
+ * 4. Create a property in the object Result(1). The property's
+ * name is [fun->atom, the identifier parsed by the compiler],
+ * value is Result(3), and attributes are { DontDelete, ReadOnly }.
+ */
+ attrs = JSFUN_GSFLAG2ATTR(fun->flags);
+ if (attrs) {
+ attrs |= JSPROP_SHARED;
+ rval = JSVAL_VOID;
+ }
+ ok = OBJ_DEFINE_PROPERTY(cx, parent, ATOM_TO_JSID(fun->atom), rval,
+ (attrs & JSPROP_GETTER)
+ ? JS_EXTENSION (JSPropertyOp) obj
+ : JS_PropertyStub,
+ (attrs & JSPROP_SETTER)
+ ? JS_EXTENSION (JSPropertyOp) obj
+ : JS_PropertyStub,
+ attrs |
+ JSPROP_ENUMERATE | JSPROP_PERMANENT |
+ JSPROP_READONLY,
+ NULL);
+
+ /* Restore fp->scopeChain now that obj is defined in parent. */
+ MUST_FLOW_LABEL(restore2)
+ fp->scopeChain = obj2;
+ if (!ok) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ goto error;
+ }
+
+ /*
+ * 5. Remove Result(1) from the front of the scope chain [no-op].
+ * 6. Return Result(3).
+ */
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_NAMEDFUNOBJ)
+
+#if JS_HAS_GETTER_SETTER
+ BEGIN_CASE(JSOP_GETTER)
+ BEGIN_CASE(JSOP_SETTER)
+ do_getter_setter:
+ op2 = (JSOp) *++regs.pc;
+ switch (op2) {
+ case JSOP_INDEXBASE:
+ atoms += GET_INDEXBASE(regs.pc);
+ regs.pc += JSOP_INDEXBASE_LENGTH - 1;
+ goto do_getter_setter;
+ case JSOP_INDEXBASE1:
+ case JSOP_INDEXBASE2:
+ case JSOP_INDEXBASE3:
+ atoms += (op2 - JSOP_INDEXBASE1 + 1) << 16;
+ goto do_getter_setter;
+
+ case JSOP_SETNAME:
+ case JSOP_SETPROP:
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ rval = FETCH_OPND(-1);
+ i = -1;
+ goto gs_pop_lval;
+
+ case JSOP_SETELEM:
+ rval = FETCH_OPND(-1);
+ id = 0;
+ i = -2;
+ gs_pop_lval:
+ FETCH_OBJECT(cx, i - 1, lval, obj);
+ break;
+
+ case JSOP_INITPROP:
+ JS_ASSERT(regs.sp - StackBase(fp) >= 2);
+ rval = FETCH_OPND(-1);
+ i = -1;
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ goto gs_get_lval;
+
+ default:
+ JS_ASSERT(op2 == JSOP_INITELEM);
+
+ JS_ASSERT(regs.sp - StackBase(fp) >= 3);
+ rval = FETCH_OPND(-1);
+ id = 0;
+ i = -2;
+ gs_get_lval:
+ lval = FETCH_OPND(i-1);
+ JS_ASSERT(JSVAL_IS_OBJECT(lval));
+ obj = JSVAL_TO_OBJECT(lval);
+ break;
+ }
+
+ /* Ensure that id has a type suitable for use with obj. */
+ if (id == 0)
+ FETCH_ELEMENT_ID(obj, i, id);
+
+ if (JS_TypeOfValue(cx, rval) != JSTYPE_FUNCTION) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_GETTER_OR_SETTER,
+ (op == JSOP_GETTER)
+ ? js_getter_str
+ : js_setter_str);
+ goto error;
+ }
+
+ /*
+ * Getters and setters are just like watchpoints from an access
+ * control point of view.
+ */
+ if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &rtmp, &attrs))
+ goto error;
+
+ if (op == JSOP_GETTER) {
+ getter = JS_EXTENSION (JSPropertyOp) JSVAL_TO_OBJECT(rval);
+ setter = JS_PropertyStub;
+ attrs = JSPROP_GETTER;
+ } else {
+ getter = JS_PropertyStub;
+ setter = JS_EXTENSION (JSPropertyOp) JSVAL_TO_OBJECT(rval);
+ attrs = JSPROP_SETTER;
+ }
+ attrs |= JSPROP_ENUMERATE | JSPROP_SHARED;
+
+ /* Check for a readonly or permanent property of the same name. */
+ if (!js_CheckRedeclaration(cx, obj, id, attrs, NULL, NULL))
+ goto error;
+
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, getter, setter,
+ attrs, NULL)) {
+ goto error;
+ }
+
+ regs.sp += i;
+ if (js_CodeSpec[op2].ndefs)
+ STORE_OPND(-1, rval);
+ len = js_CodeSpec[op2].length;
+ DO_NEXT_OP(len);
+#endif /* JS_HAS_GETTER_SETTER */
+
+ BEGIN_CASE(JSOP_HOLE)
+ PUSH_OPND(JSVAL_HOLE);
+ END_CASE(JSOP_HOLE)
+
+ BEGIN_CASE(JSOP_NEWARRAY)
+ len = GET_UINT24(regs.pc);
+ JS_ASSERT(len <= regs.sp - StackBase(fp));
+ obj = js_NewArrayObject(cx, len, regs.sp - len, JS_TRUE);
+ if (!obj)
+ goto error;
+ regs.sp -= len - 1;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_NEWARRAY)
+
+ BEGIN_CASE(JSOP_NEWINIT)
+ i = GET_INT8(regs.pc);
+ JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
+ obj = (i == JSProto_Array)
+ ? js_NewArrayObject(cx, 0, NULL)
+ : js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
+ if (!obj)
+ goto error;
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ fp->sharpDepth++;
+ LOAD_INTERRUPT_HANDLER(cx);
+ END_CASE(JSOP_NEWINIT)
+
+ BEGIN_CASE(JSOP_ENDINIT)
+ if (--fp->sharpDepth == 0)
+ fp->sharpArray = NULL;
+
+ /* Re-set the newborn root to the top of this object tree. */
+ JS_ASSERT(regs.sp - StackBase(fp) >= 1);
+ lval = FETCH_OPND(-1);
+ JS_ASSERT(JSVAL_IS_OBJECT(lval));
+ cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(lval);
+ END_CASE(JSOP_ENDINIT)
+
+ BEGIN_CASE(JSOP_INITPROP)
+ /* Load the property's initial value into rval. */
+ JS_ASSERT(regs.sp - StackBase(fp) >= 2);
+ rval = FETCH_OPND(-1);
+
+ /* Load the object being initialized into lval/obj. */
+ lval = FETCH_OPND(-2);
+ obj = JSVAL_TO_OBJECT(lval);
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ JS_ASSERT(!OBJ_GET_CLASS(cx, obj)->reserveSlots);
+ JS_ASSERT(!(LOCKED_OBJ_GET_CLASS(obj)->flags &
+ JSCLASS_SHARE_ALL_PROPERTIES));
+
+ do {
+ JSScope *scope;
+ uint32 kshape;
+ JSPropertyCache *cache;
+ JSPropCacheEntry *entry;
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ JS_ASSERT(!SCOPE_IS_SEALED(scope));
+ kshape = scope->shape;
+ cache = &JS_PROPERTY_CACHE(cx);
+ entry = &cache->table[PROPERTY_CACHE_HASH_PC(regs.pc, kshape)];
+ PCMETER(cache->tests++);
+ PCMETER(cache->initests++);
+
+ if (entry->kpc == regs.pc && entry->kshape == kshape) {
+ PCMETER(cache->pchits++);
+ PCMETER(cache->inipchits++);
+
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));
+
+ /*
+ * If this property has a non-stub setter, it must be
+ * __proto__, __parent__, or another "shared prototype"
+ * built-in. Force a miss to save code size here and let
+ * the standard code path take care of business.
+ */
+ if (!SPROP_HAS_STUB_SETTER(sprop))
+ goto do_initprop_miss;
+
+ if (scope->object != obj) {
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ JS_UNLOCK_OBJ(cx, obj);
+ goto error;
+ }
+ }
+
+ /*
+ * Detect a repeated property name and force a miss to
+ * share the strict warning code and cope with complexity
+ * managed by js_AddScopeProperty.
+ */
+ if (sprop->parent != scope->lastProp)
+ goto do_initprop_miss;
+
+ TRACE_2(SetPropHit, entry, sprop);
+
+ /*
+ * Otherwise this entry must be for a direct property of
+ * obj, not a proto-property, and there cannot have been
+ * any deletions of prior properties.
+ */
+ JS_ASSERT(PCVCAP_MAKE(sprop->shape, 0, 0) == entry->vcap);
+ JS_ASSERT(!SCOPE_HAD_MIDDLE_DELETE(scope));
+ JS_ASSERT(!scope->table ||
+ !SCOPE_HAS_PROPERTY(scope, sprop));
+
+ slot = sprop->slot;
+ JS_ASSERT(slot == scope->map.freeslot);
+ if (slot < STOBJ_NSLOTS(obj)) {
+ ++scope->map.freeslot;
+ } else {
+ if (!js_AllocSlot(cx, obj, &slot)) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ goto error;
+ }
+ JS_ASSERT(slot == sprop->slot);
+ }
+
+ JS_ASSERT(!scope->lastProp ||
+ scope->shape == scope->lastProp->shape);
+ if (scope->table) {
+ JSScopeProperty *sprop2 =
+ js_AddScopeProperty(cx, scope, sprop->id,
+ sprop->getter, sprop->setter,
+ slot, sprop->attrs,
+ sprop->flags, sprop->shortid);
+ if (!sprop2) {
+ js_FreeSlot(cx, obj, slot);
+ JS_UNLOCK_SCOPE(cx, scope);
+ goto error;
+ }
+ JS_ASSERT(sprop2 == sprop);
+ } else {
+ scope->shape = sprop->shape;
+ ++scope->entryCount;
+ scope->lastProp = sprop;
+ }
+
+ GC_WRITE_BARRIER(cx, scope,
+ LOCKED_OBJ_GET_SLOT(obj, slot),
+ rval);
+ LOCKED_OBJ_SET_SLOT(obj, slot, rval);
+ JS_UNLOCK_SCOPE(cx, scope);
+ break;
+ }
+
+ do_initprop_miss:
+ PCMETER(cache->inipcmisses++);
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ /* Get the immediate property name into id. */
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+
+ /* Set the property named by obj[id] to rval. */
+ if (!js_CheckRedeclaration(cx, obj, id, JSPROP_INITIALIZER,
+ NULL, NULL)) {
+ goto error;
+ }
+ if (!js_SetPropertyHelper(cx, obj, id, &rval, &entry))
+ goto error;
+#ifdef JS_TRACER
+ if (entry)
+ TRACE_1(SetPropMiss, entry);
+#endif
+ } while (0);
+
+ /* Common tail for property cache hit and miss cases. */
+ regs.sp--;
+ END_CASE(JSOP_INITPROP);
+
+ BEGIN_CASE(JSOP_INITELEM)
+ /* Pop the element's value into rval. */
+ JS_ASSERT(regs.sp - StackBase(fp) >= 3);
+ rval = FETCH_OPND(-1);
+
+ /* Find the object being initialized at top of stack. */
+ lval = FETCH_OPND(-3);
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(lval));
+ obj = JSVAL_TO_OBJECT(lval);
+
+ /* Fetch id now that we have obj. */
+ FETCH_ELEMENT_ID(obj, -2, id);
+
+ /*
+ * Check for property redeclaration strict warning (we may be in
+ * an object initialiser, not an array initialiser).
+ */
+ if (!js_CheckRedeclaration(cx, obj, id, JSPROP_INITIALIZER, NULL,
+ NULL)) {
+ goto error;
+ }
+
+ /*
+ * If rval is a hole, do not call OBJ_SET_PROPERTY. In this case,
+ * obj must be an array, so if the current op is the last element
+ * initialiser, set the array length to one greater than id.
+ */
+ if (rval == JSVAL_HOLE) {
+ JS_ASSERT(OBJ_IS_ARRAY(cx, obj));
+ JS_ASSERT(JSID_IS_INT(id));
+ JS_ASSERT((jsuint) JSID_TO_INT(id) < ARRAY_INIT_LIMIT);
+ if ((JSOp) regs.pc[JSOP_INITELEM_LENGTH] == JSOP_ENDINIT &&
+ !js_SetLengthProperty(cx, obj,
+ (jsuint) (JSID_TO_INT(id) + 1))) {
+ goto error;
+ }
+ } else {
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ }
+ regs.sp -= 2;
+ END_CASE(JSOP_INITELEM)
+
+#if JS_HAS_SHARP_VARS
+ BEGIN_CASE(JSOP_DEFSHARP)
+ obj = fp->sharpArray;
+ if (!obj) {
+ obj = js_NewArrayObject(cx, 0, NULL);
+ if (!obj)
+ goto error;
+ fp->sharpArray = obj;
+ }
+ i = (jsint) GET_UINT16(regs.pc);
+ id = INT_TO_JSID(i);
+ rval = FETCH_OPND(-1);
+ if (JSVAL_IS_PRIMITIVE(rval)) {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_SHARP_DEF, numBuf);
+ goto error;
+ }
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ END_CASE(JSOP_DEFSHARP)
+
+ BEGIN_CASE(JSOP_USESHARP)
+ i = (jsint) GET_UINT16(regs.pc);
+ id = INT_TO_JSID(i);
+ obj = fp->sharpArray;
+ if (!obj) {
+ rval = JSVAL_VOID;
+ } else {
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ }
+ if (!JSVAL_IS_OBJECT(rval)) {
+ char numBuf[12];
+
+ JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_SHARP_USE, numBuf);
+ goto error;
+ }
+ PUSH_OPND(rval);
+ END_CASE(JSOP_USESHARP)
+#endif /* JS_HAS_SHARP_VARS */
+
+ BEGIN_CASE(JSOP_GOSUB)
+ PUSH(JSVAL_FALSE);
+ i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUB_LENGTH;
+ PUSH(INT_TO_JSVAL(i));
+ len = GET_JUMP_OFFSET(regs.pc);
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_GOSUBX)
+ PUSH(JSVAL_FALSE);
+ i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUBX_LENGTH;
+ len = GET_JUMPX_OFFSET(regs.pc);
+ PUSH(INT_TO_JSVAL(i));
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_RETSUB)
+ /* Pop [exception or hole, retsub pc-index]. */
+ rval = POP();
+ lval = POP();
+ JS_ASSERT(JSVAL_IS_BOOLEAN(lval));
+ if (JSVAL_TO_BOOLEAN(lval)) {
+ /*
+ * Exception was pending during finally, throw it *before* we
+ * adjust pc, because pc indexes into script->trynotes. This
+ * turns out not to be necessary, but it seems clearer. And
+ * it points out a FIXME: 350509, due to Igor Bukanov.
+ */
+ cx->throwing = JS_TRUE;
+ cx->exception = rval;
+ goto error;
+ }
+ JS_ASSERT(JSVAL_IS_INT(rval));
+ len = JSVAL_TO_INT(rval);
+ regs.pc = script->main;
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_EXCEPTION)
+ JS_ASSERT(cx->throwing);
+ PUSH(cx->exception);
+ cx->throwing = JS_FALSE;
+ END_CASE(JSOP_EXCEPTION)
+
+ BEGIN_CASE(JSOP_THROWING)
+ JS_ASSERT(!cx->throwing);
+ cx->throwing = JS_TRUE;
+ cx->exception = POP_OPND();
+ END_CASE(JSOP_THROWING)
+
+ BEGIN_CASE(JSOP_THROW)
+ JS_ASSERT(!cx->throwing);
+ cx->throwing = JS_TRUE;
+ cx->exception = POP_OPND();
+ /* let the code at error try to catch the exception. */
+ goto error;
+
+ BEGIN_CASE(JSOP_SETLOCALPOP)
+ /*
+ * The stack must have a block with at least one local slot below
+ * the exception object.
+ */
+ JS_ASSERT((size_t) (regs.sp - StackBase(fp)) >= 2);
+ slot = GET_UINT16(regs.pc);
+ JS_ASSERT(slot + 1 < script->nslots);
+ fp->slots[slot] = POP_OPND();
+ END_CASE(JSOP_SETLOCALPOP)
+
+ BEGIN_CASE(JSOP_INSTANCEOF)
+ rval = FETCH_OPND(-1);
+ if (JSVAL_IS_PRIMITIVE(rval) ||
+ !(obj = JSVAL_TO_OBJECT(rval))->map->ops->hasInstance) {
+ js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
+ -1, rval, NULL);
+ goto error;
+ }
+ lval = FETCH_OPND(-2);
+ cond = JS_FALSE;
+ if (!obj->map->ops->hasInstance(cx, obj, lval, &cond))
+ goto error;
+ regs.sp--;
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));
+ END_CASE(JSOP_INSTANCEOF)
+
+#if JS_HAS_DEBUGGER_KEYWORD
+ BEGIN_CASE(JSOP_DEBUGGER)
+ {
+ JSTrapHandler handler = cx->debugHooks->debuggerHandler;
+ if (handler) {
+ switch (handler(cx, script, regs.pc, &rval,
+ cx->debugHooks->debuggerHandlerData)) {
+ case JSTRAP_ERROR:
+ goto error;
+ case JSTRAP_CONTINUE:
+ break;
+ case JSTRAP_RETURN:
+ fp->rval = rval;
+ ok = JS_TRUE;
+ goto forced_return;
+ case JSTRAP_THROW:
+ cx->throwing = JS_TRUE;
+ cx->exception = rval;
+ goto error;
+ default:;
+ }
+ LOAD_INTERRUPT_HANDLER(cx);
+ }
+ }
+ END_CASE(JSOP_DEBUGGER)
+#endif /* JS_HAS_DEBUGGER_KEYWORD */
+
+#if JS_HAS_XML_SUPPORT
+ BEGIN_CASE(JSOP_DEFXMLNS)
+ rval = POP();
+ if (!js_SetDefaultXMLNamespace(cx, rval))
+ goto error;
+ END_CASE(JSOP_DEFXMLNS)
+
+ BEGIN_CASE(JSOP_ANYNAME)
+ if (!js_GetAnyName(cx, &rval))
+ goto error;
+ PUSH_OPND(rval);
+ END_CASE(JSOP_ANYNAME)
+
+ BEGIN_CASE(JSOP_QNAMEPART)
+ LOAD_ATOM(0);
+ PUSH_OPND(ATOM_KEY(atom));
+ END_CASE(JSOP_QNAMEPART)
+
+ BEGIN_CASE(JSOP_QNAMECONST)
+ LOAD_ATOM(0);
+ rval = ATOM_KEY(atom);
+ lval = FETCH_OPND(-1);
+ obj = js_ConstructXMLQNameObject(cx, lval, rval);
+ if (!obj)
+ goto error;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_QNAMECONST)
+
+ BEGIN_CASE(JSOP_QNAME)
+ rval = FETCH_OPND(-1);
+ lval = FETCH_OPND(-2);
+ obj = js_ConstructXMLQNameObject(cx, lval, rval);
+ if (!obj)
+ goto error;
+ regs.sp--;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_QNAME)
+
+ BEGIN_CASE(JSOP_TOATTRNAME)
+ rval = FETCH_OPND(-1);
+ if (!js_ToAttributeName(cx, &rval))
+ goto error;
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_TOATTRNAME)
+
+ BEGIN_CASE(JSOP_TOATTRVAL)
+ rval = FETCH_OPND(-1);
+ JS_ASSERT(JSVAL_IS_STRING(rval));
+ str = js_EscapeAttributeValue(cx, JSVAL_TO_STRING(rval), JS_FALSE);
+ if (!str)
+ goto error;
+ STORE_OPND(-1, STRING_TO_JSVAL(str));
+ END_CASE(JSOP_TOATTRVAL)
+
+ BEGIN_CASE(JSOP_ADDATTRNAME)
+ BEGIN_CASE(JSOP_ADDATTRVAL)
+ rval = FETCH_OPND(-1);
+ lval = FETCH_OPND(-2);
+ str = JSVAL_TO_STRING(lval);
+ str2 = JSVAL_TO_STRING(rval);
+ str = js_AddAttributePart(cx, op == JSOP_ADDATTRNAME, str, str2);
+ if (!str)
+ goto error;
+ regs.sp--;
+ STORE_OPND(-1, STRING_TO_JSVAL(str));
+ END_CASE(JSOP_ADDATTRNAME)
+
+ BEGIN_CASE(JSOP_BINDXMLNAME)
+ lval = FETCH_OPND(-1);
+ if (!js_FindXMLProperty(cx, lval, &obj, &id))
+ goto error;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ PUSH_OPND(ID_TO_VALUE(id));
+ END_CASE(JSOP_BINDXMLNAME)
+
+ BEGIN_CASE(JSOP_SETXMLNAME)
+ obj = JSVAL_TO_OBJECT(FETCH_OPND(-3));
+ rval = FETCH_OPND(-1);
+ FETCH_ELEMENT_ID(obj, -2, id);
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ rval = FETCH_OPND(-1);
+ regs.sp -= 2;
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_SETXMLNAME)
+
+ BEGIN_CASE(JSOP_CALLXMLNAME)
+ BEGIN_CASE(JSOP_XMLNAME)
+ lval = FETCH_OPND(-1);
+ if (!js_FindXMLProperty(cx, lval, &obj, &id))
+ goto error;
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ STORE_OPND(-1, rval);
+ if (op == JSOP_CALLXMLNAME)
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_XMLNAME)
+
+ BEGIN_CASE(JSOP_DESCENDANTS)
+ BEGIN_CASE(JSOP_DELDESC)
+ FETCH_OBJECT(cx, -2, lval, obj);
+ rval = FETCH_OPND(-1);
+ if (!js_GetXMLDescendants(cx, obj, rval, &rval))
+ goto error;
+
+ if (op == JSOP_DELDESC) {
+ regs.sp[-1] = rval; /* set local root */
+ if (!js_DeleteXMLListElements(cx, JSVAL_TO_OBJECT(rval)))
+ goto error;
+ rval = JSVAL_TRUE; /* always succeed */
+ }
+
+ regs.sp--;
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_DESCENDANTS)
+
+ BEGIN_CASE(JSOP_FILTER)
+ /*
+ * We push the hole value before jumping to [enditer] so we can
+ * detect the first iteration and direct js_StepXMLListFilter to
+ * initialize filter's state.
+ */
+ PUSH_OPND(JSVAL_HOLE);
+ len = GET_JUMP_OFFSET(regs.pc);
+ JS_ASSERT(len > 0);
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_ENDFILTER)
+ cond = (regs.sp[-1] != JSVAL_HOLE);
+ if (cond) {
+ /* Exit the "with" block left from the previous iteration. */
+ js_LeaveWith(cx);
+ }
+ if (!js_StepXMLListFilter(cx, cond))
+ goto error;
+ if (regs.sp[-1] != JSVAL_NULL) {
+ /*
+ * Decrease sp after EnterWith returns as we use sp[-1] there
+ * to root temporaries.
+ */
+ JS_ASSERT(VALUE_IS_XML(cx, regs.sp[-1]));
+ if (!js_EnterWith(cx, -2))
+ goto error;
+ regs.sp--;
+ len = GET_JUMP_OFFSET(regs.pc);
+ JS_ASSERT(len < 0);
+ BRANCH(len);
+ }
+ regs.sp--;
+ END_CASE(JSOP_ENDFILTER);
+
+ BEGIN_CASE(JSOP_TOXML)
+ rval = FETCH_OPND(-1);
+ obj = js_ValueToXMLObject(cx, rval);
+ if (!obj)
+ goto error;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_TOXML)
+
+ BEGIN_CASE(JSOP_TOXMLLIST)
+ rval = FETCH_OPND(-1);
+ obj = js_ValueToXMLListObject(cx, rval);
+ if (!obj)
+ goto error;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_TOXMLLIST)
+
+ BEGIN_CASE(JSOP_XMLTAGEXPR)
+ rval = FETCH_OPND(-1);
+ str = js_ValueToString(cx, rval);
+ if (!str)
+ goto error;
+ STORE_OPND(-1, STRING_TO_JSVAL(str));
+ END_CASE(JSOP_XMLTAGEXPR)
+
+ BEGIN_CASE(JSOP_XMLELTEXPR)
+ rval = FETCH_OPND(-1);
+ if (VALUE_IS_XML(cx, rval)) {
+ str = js_ValueToXMLString(cx, rval);
+ } else {
+ str = js_ValueToString(cx, rval);
+ if (str)
+ str = js_EscapeElementValue(cx, str);
+ }
+ if (!str)
+ goto error;
+ STORE_OPND(-1, STRING_TO_JSVAL(str));
+ END_CASE(JSOP_XMLELTEXPR)
+
+ BEGIN_CASE(JSOP_XMLOBJECT)
+ LOAD_OBJECT(0);
+ obj = js_CloneXMLObject(cx, obj);
+ if (!obj)
+ goto error;
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_XMLOBJECT)
+
+ BEGIN_CASE(JSOP_XMLCDATA)
+ LOAD_ATOM(0);
+ str = ATOM_TO_STRING(atom);
+ obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, str);
+ if (!obj)
+ goto error;
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_XMLCDATA)
+
+ BEGIN_CASE(JSOP_XMLCOMMENT)
+ LOAD_ATOM(0);
+ str = ATOM_TO_STRING(atom);
+ obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, str);
+ if (!obj)
+ goto error;
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_XMLCOMMENT)
+
+ BEGIN_CASE(JSOP_XMLPI)
+ LOAD_ATOM(0);
+ str = ATOM_TO_STRING(atom);
+ rval = FETCH_OPND(-1);
+ str2 = JSVAL_TO_STRING(rval);
+ obj = js_NewXMLSpecialObject(cx,
+ JSXML_CLASS_PROCESSING_INSTRUCTION,
+ str, str2);
+ if (!obj)
+ goto error;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_XMLPI)
+
+ BEGIN_CASE(JSOP_GETFUNNS)
+ if (!js_GetFunctionNamespace(cx, &rval))
+ goto error;
+ PUSH_OPND(rval);
+ END_CASE(JSOP_GETFUNNS)
+#endif /* JS_HAS_XML_SUPPORT */
+
+ BEGIN_CASE(JSOP_ENTERBLOCK)
+ LOAD_OBJECT(0);
+ JS_ASSERT(!OBJ_IS_CLONED_BLOCK(obj));
+ JS_ASSERT(StackBase(fp) + OBJ_BLOCK_DEPTH(cx, obj) == regs.sp);
+ vp = regs.sp + OBJ_BLOCK_COUNT(cx, obj);
+ JS_ASSERT(regs.sp < vp);
+ JS_ASSERT(vp <= fp->slots + script->nslots);
+ while (regs.sp < vp) {
+ STORE_OPND(0, JSVAL_VOID);
+ regs.sp++;
+ }
+
+ /*
+ * If this frame had to reflect the compile-time block chain into
+ * the runtime scope chain, we can't optimize block scopes out of
+ * runtime any longer, because an outer block that parents obj has
+ * been cloned onto the scope chain. To avoid re-cloning such a
+ * parent and accumulating redundant clones via js_GetScopeChain,
+ * we must clone each block eagerly on entry, and push it on the
+ * scope chain, until this frame pops.
+ */
+ if (fp->flags & JSFRAME_POP_BLOCKS) {
+ JS_ASSERT(!fp->blockChain);
+ obj = js_CloneBlockObject(cx, obj, fp->scopeChain, fp);
+ if (!obj)
+ goto error;
+ fp->scopeChain = obj;
+ } else {
+ JS_ASSERT(!fp->blockChain ||
+ OBJ_GET_PARENT(cx, obj) == fp->blockChain);
+ fp->blockChain = obj;
+ }
+ END_CASE(JSOP_ENTERBLOCK)
+
+ BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
+ BEGIN_CASE(JSOP_LEAVEBLOCK)
+ {
+#ifdef DEBUG
+ uintN blockDepth = OBJ_BLOCK_DEPTH(cx,
+ fp->blockChain
+ ? fp->blockChain
+ : fp->scopeChain);
+
+ JS_ASSERT(blockDepth <= StackDepth(script));
+#endif
+ if (fp->blockChain) {
+ JS_ASSERT(OBJ_GET_CLASS(cx, fp->blockChain) == &js_BlockClass);
+ fp->blockChain = OBJ_GET_PARENT(cx, fp->blockChain);
+ } else {
+ /*
+ * This block was cloned into fp->scopeChain, so clear its
+ * private data and sync its locals to their property slots.
+ */
+ if (!js_PutBlockObject(cx, JS_TRUE))
+ goto error;
+ }
+
+ /*
+ * We will move the result of the expression to the new topmost
+ * stack slot.
+ */
+ if (op == JSOP_LEAVEBLOCKEXPR)
+ rval = FETCH_OPND(-1);
+ regs.sp -= GET_UINT16(regs.pc);
+ if (op == JSOP_LEAVEBLOCKEXPR) {
+ JS_ASSERT(StackBase(fp) + blockDepth == regs.sp - 1);
+ STORE_OPND(-1, rval);
+ } else {
+ JS_ASSERT(StackBase(fp) + blockDepth == regs.sp);
+ }
+ }
+ END_CASE(JSOP_LEAVEBLOCK)
+
+#if JS_HAS_GENERATORS
+ BEGIN_CASE(JSOP_GENERATOR)
+ ASSERT_NOT_THROWING(cx);
+ regs.pc += JSOP_GENERATOR_LENGTH;
+ obj = js_NewGenerator(cx, fp);
+ if (!obj)
+ goto error;
+ JS_ASSERT(!fp->callobj && !fp->argsobj);
+ fp->rval = OBJECT_TO_JSVAL(obj);
+ ok = JS_TRUE;
+ if (inlineCallCount != 0)
+ goto inline_return;
+ goto exit;
+
+ BEGIN_CASE(JSOP_YIELD)
+ ASSERT_NOT_THROWING(cx);
+ if (FRAME_TO_GENERATOR(fp)->state == JSGEN_CLOSING) {
+ js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD,
+ JSDVG_SEARCH_STACK, fp->argv[-2], NULL);
+ goto error;
+ }
+ fp->rval = FETCH_OPND(-1);
+ fp->flags |= JSFRAME_YIELDING;
+ regs.pc += JSOP_YIELD_LENGTH;
+ ok = JS_TRUE;
+ goto exit;
+
+ BEGIN_CASE(JSOP_ARRAYPUSH)
+ slot = GET_UINT16(regs.pc);
+ JS_ASSERT(script->nfixed <= slot);
+ JS_ASSERT(slot < script->nslots);
+ lval = fp->slots[slot];
+ obj = JSVAL_TO_OBJECT(lval);
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ArrayClass);
+ rval = FETCH_OPND(-1);
+
+ /*
+ * We know that the array is created with only a 'length' private
+ * data slot at JSSLOT_ARRAY_LENGTH, and that previous iterations
+ * of the comprehension have added the only properties directly in
+ * the array object.
+ */
+ i = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (i == ARRAY_INIT_LIMIT) {
+ JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL,
+ JSMSG_ARRAY_INIT_TOO_BIG);
+ goto error;
+ }
+ id = INT_TO_JSID(i);
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ regs.sp--;
+ END_CASE(JSOP_ARRAYPUSH)
+#endif /* JS_HAS_GENERATORS */
+
+#if JS_THREADED_INTERP
+ L_JSOP_BACKPATCH:
+ L_JSOP_BACKPATCH_POP:
+
+# if !JS_HAS_GENERATORS
+ L_JSOP_GENERATOR:
+ L_JSOP_YIELD:
+ L_JSOP_ARRAYPUSH:
+# endif
+
+# if !JS_HAS_DESTRUCTURING
+ L_JSOP_ENUMCONSTELEM:
+# endif
+
+# if !JS_HAS_XML_SUPPORT
+ L_JSOP_CALLXMLNAME:
+ L_JSOP_STARTXMLEXPR:
+ L_JSOP_STARTXML:
+ L_JSOP_DELDESC:
+ L_JSOP_GETFUNNS:
+ L_JSOP_XMLPI:
+ L_JSOP_XMLCOMMENT:
+ L_JSOP_XMLCDATA:
+ L_JSOP_XMLOBJECT:
+ L_JSOP_XMLELTEXPR:
+ L_JSOP_XMLTAGEXPR:
+ L_JSOP_TOXMLLIST:
+ L_JSOP_TOXML:
+ L_JSOP_ENDFILTER:
+ L_JSOP_FILTER:
+ L_JSOP_DESCENDANTS:
+ L_JSOP_XMLNAME:
+ L_JSOP_SETXMLNAME:
+ L_JSOP_BINDXMLNAME:
+ L_JSOP_ADDATTRVAL:
+ L_JSOP_ADDATTRNAME:
+ L_JSOP_TOATTRVAL:
+ L_JSOP_TOATTRNAME:
+ L_JSOP_QNAME:
+ L_JSOP_QNAMECONST:
+ L_JSOP_QNAMEPART:
+ L_JSOP_ANYNAME:
+ L_JSOP_DEFXMLNS:
+# endif
+
+ L_JSOP_UNUSED131:
+ L_JSOP_UNUSED201:
+ L_JSOP_UNUSED202:
+ L_JSOP_UNUSED203:
+ L_JSOP_UNUSED204:
+ L_JSOP_UNUSED205:
+ L_JSOP_UNUSED206:
+ L_JSOP_UNUSED207:
+ L_JSOP_UNUSED208:
+ L_JSOP_UNUSED209:
+ L_JSOP_UNUSED219:
+ L_JSOP_UNUSED226:
+
+#else /* !JS_THREADED_INTERP */
+ default:
+#endif
+ {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%d", op);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_BYTECODE, numBuf);
+ goto error;
+ }
+
+#ifdef JS_TRACER
+
+#if JS_THREADED_INTERP
+# define OPDEF(x,val,name,token,length,nuses,ndefs,prec,format) \
+ R_##x: RECORD(x); goto L_##x;
+#else
+# define OPDEF(x,val,name,token,length,nuses,ndefs,prec,format) \
+ case 256 + x: RECORD(x); op = x; switchOp = x; goto do_switch;
+#endif
+#include "jsopcode.tbl"
+#undef OPDEF
+
+#endif /* JS_TRACER */
+
+#if !JS_THREADED_INTERP
+
+ } /* switch (op) */
+ }
+#endif /* !JS_THREADED_INTERP */
+
+ error:
+ if (fp->imacpc && cx->throwing) {
+ // To keep things simple, we hard-code imacro exception handlers here.
+ if (*fp->imacpc == JSOP_NEXTITER) {
+ JS_ASSERT(*regs.pc == JSOP_CALL);
+ if (js_ValueIsStopIteration(cx->exception)) {
+ cx->throwing = JS_FALSE;
+ cx->exception = JSVAL_VOID;
+ regs.sp[-1] = JSVAL_HOLE;
+ PUSH(JSVAL_FALSE);
+ goto end_imacro;
+ }
+ }
+
+ // Handle other exceptions as if they came from the imacro-calling pc.
+ regs.pc = fp->imacpc;
+ fp->imacpc = NULL;
+ atoms = script->atomMap.vector;
+ }
+
+ JS_ASSERT((size_t)(regs.pc - script->code) < script->length);
+ if (!cx->throwing) {
+ /* This is an error, not a catchable exception, quit the frame ASAP. */
+ ok = JS_FALSE;
+ } else {
+ JSTrapHandler handler;
+ JSTryNote *tn, *tnlimit;
+ uint32 offset;
+
+ /* Call debugger throw hook if set. */
+ handler = cx->debugHooks->throwHook;
+ if (handler) {
+ switch (handler(cx, script, regs.pc, &rval,
+ cx->debugHooks->throwHookData)) {
+ case JSTRAP_ERROR:
+ cx->throwing = JS_FALSE;
+ goto error;
+ case JSTRAP_RETURN:
+ cx->throwing = JS_FALSE;
+ fp->rval = rval;
+ ok = JS_TRUE;
+ goto forced_return;
+ case JSTRAP_THROW:
+ cx->exception = rval;
+ case JSTRAP_CONTINUE:
+ default:;
+ }
+ LOAD_INTERRUPT_HANDLER(cx);
+ }
+
+ /*
+ * Look for a try block in script that can catch this exception.
+ */
+ if (script->trynotesOffset == 0)
+ goto no_catch;
+
+ offset = (uint32)(regs.pc - script->main);
+ tn = JS_SCRIPT_TRYNOTES(script)->vector;
+ tnlimit = tn + JS_SCRIPT_TRYNOTES(script)->length;
+ do {
+ if (offset - tn->start >= tn->length)
+ continue;
+
+ /*
+ * We have a note that covers the exception pc but we must check
+ * whether the interpreter has already executed the corresponding
+ * handler. This is possible when the executed bytecode
+ * implements break or return from inside a for-in loop.
+ *
+ * In this case the emitter generates additional [enditer] and
+ * [gosub] opcodes to close all outstanding iterators and execute
+ * the finally blocks. If such an [enditer] throws an exception,
+ * its pc can still be inside several nested for-in loops and
+ * try-finally statements even if we have already closed the
+ * corresponding iterators and invoked the finally blocks.
+ *
+ * To address this, we make [enditer] always decrease the stack
+ * even when its implementation throws an exception. Thus already
+ * executed [enditer] and [gosub] opcodes will have try notes
+ * with the stack depth exceeding the current one and this
+ * condition is what we use to filter them out.
+ */
+ if (tn->stackDepth > regs.sp - StackBase(fp))
+ continue;
+
+ /*
+ * Set pc to the first bytecode after the the try note to point
+ * to the beginning of catch or finally or to [enditer] closing
+ * the for-in loop.
+ */
+ regs.pc = (script)->main + tn->start + tn->length;
+
+ ok = js_UnwindScope(cx, fp, tn->stackDepth, JS_TRUE);
+ JS_ASSERT(fp->regs->sp == StackBase(fp) + tn->stackDepth);
+ if (!ok) {
+ /*
+ * Restart the handler search with updated pc and stack depth
+ * to properly notify the debugger.
+ */
+ goto error;
+ }
+
+ switch (tn->kind) {
+ case JSTRY_CATCH:
+ JS_ASSERT(*regs.pc == JSOP_ENTERBLOCK);
+
+#if JS_HAS_GENERATORS
+ /* Catch cannot intercept the closing of a generator. */
+ if (JS_UNLIKELY(cx->exception == JSVAL_ARETURN))
+ break;
+#endif
+
+ /*
+ * Don't clear cx->throwing to save cx->exception from GC
+ * until it is pushed to the stack via [exception] in the
+ * catch block.
+ */
+ len = 0;
+ DO_NEXT_OP(len);
+
+ case JSTRY_FINALLY:
+ /*
+ * Push (true, exception) pair for finally to indicate that
+ * [retsub] should rethrow the exception.
+ */
+ PUSH(JSVAL_TRUE);
+ PUSH(cx->exception);
+ cx->throwing = JS_FALSE;
+ len = 0;
+ DO_NEXT_OP(len);
+
+ case JSTRY_ITER:
+ /*
+ * This is similar to JSOP_ENDITER in the interpreter loop,
+ * except the code now uses the stack slot normally used by
+ * JSOP_NEXTITER, namely regs.sp[-1] before the regs.sp -= 2
+ * adjustment and regs.sp[1] after, to save and restore the
+ * pending exception.
+ */
+ JS_ASSERT(*regs.pc == JSOP_ENDITER);
+ regs.sp[-1] = cx->exception;
+ cx->throwing = JS_FALSE;
+ ok = js_CloseIterator(cx, regs.sp[-2]);
+ regs.sp -= 2;
+ if (!ok)
+ goto error;
+ cx->throwing = JS_TRUE;
+ cx->exception = regs.sp[1];
+ }
+ } while (++tn != tnlimit);
+
+ no_catch:
+ /*
+ * Propagate the exception or error to the caller unless the exception
+ * is an asynchronous return from a generator.
+ */
+ ok = JS_FALSE;
+#if JS_HAS_GENERATORS
+ if (JS_UNLIKELY(cx->throwing && cx->exception == JSVAL_ARETURN)) {
+ cx->throwing = JS_FALSE;
+ ok = JS_TRUE;
+ fp->rval = JSVAL_VOID;
+ }
+#endif
+ }
+
+ forced_return:
+ /*
+ * Unwind the scope making sure that ok stays false even when UnwindScope
+ * returns true.
+ *
+ * When a trap handler returns JSTRAP_RETURN, we jump here with ok set to
+ * true bypassing any finally blocks.
+ */
+ ok &= js_UnwindScope(cx, fp, 0, ok || cx->throwing);
+ JS_ASSERT(regs.sp == StackBase(fp));
+
+ if (inlineCallCount)
+ goto inline_return;
+
+ exit:
+ /*
+ * At this point we are inevitably leaving an interpreted function or a
+ * top-level script, and returning to one of:
+ * (a) an "out of line" call made through js_Invoke;
+ * (b) a js_Execute activation;
+ * (c) a generator (SendToGenerator, jsiter.c).
+ *
+ * We must not be in an inline frame. The check above ensures that for the
+ * error case and for a normal return, the code jumps directly to parent's
+ * frame pc.
+ */
+ JS_ASSERT(inlineCallCount == 0);
+ JS_ASSERT(fp->regs == &regs);
+#ifdef JS_TRACER
+ if (TRACE_RECORDER(cx))
+ js_AbortRecording(cx, "recording out of js_Interpret");
+#endif
+#if JS_HAS_GENERATORS
+ if (JS_UNLIKELY(fp->flags & JSFRAME_YIELDING)) {
+ JSGenerator *gen;
+
+ gen = FRAME_TO_GENERATOR(fp);
+ gen->savedRegs = regs;
+ gen->frame.regs = &gen->savedRegs;
+ JS_PROPERTY_CACHE(cx).disabled -= js_CountWithBlocks(cx, fp);
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0);
+ } else
+#endif /* JS_HAS_GENERATORS */
+ {
+ JS_ASSERT(!fp->blockChain);
+ JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->scopeChain, 0));
+ fp->regs = NULL;
+ }
+
+ /* Undo the remaining effects committed on entry to js_Interpret. */
+ if (script->staticDepth < JS_DISPLAY_SIZE)
+ cx->display[script->staticDepth] = fp->displaySave;
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled == fp->pcDisabledSave);
+ if (cx->version == currentVersion && currentVersion != originalVersion)
+ js_SetVersion(cx, originalVersion);
+ --cx->interpLevel;
+
+#ifdef JS_TRACER
+ if (tr) {
+ JS_TRACE_MONITOR(cx).onTrace = JS_TRUE;
+ SET_TRACE_RECORDER(cx, tr);
+ if (!tr->wasDeepAborted()) {
+ tr->popAbortStack();
+ tr->deepAbort();
+ }
+ }
+#endif
+ return ok;
+
+ atom_not_defined:
+ {
+ const char *printable;
+
+ printable = js_AtomToPrintableString(cx, atom);
+ if (printable)
+ js_ReportIsNotDefined(cx, printable);
+ goto error;
+ }
+}
+
+#endif /* !defined jsinvoke_cpp___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.h b/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.h
new file mode 100644
index 0000000..a016c47
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.h
@@ -0,0 +1,591 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsinterp_h___
+#define jsinterp_h___
+/*
+ * JS interpreter interface.
+ */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsfun.h"
+#include "jsopcode.h"
+#include "jsscript.h"
+
+JS_BEGIN_EXTERN_C
+
+typedef struct JSFrameRegs {
+ jsbytecode *pc; /* program counter */
+ jsval *sp; /* stack pointer */
+} JSFrameRegs;
+
+/*
+ * JS stack frame, may be allocated on the C stack by native callers. Always
+ * allocated on cx->stackPool for calls from the interpreter to an interpreted
+ * function.
+ *
+ * NB: This struct is manually initialized in jsinterp.c and jsiter.c. If you
+ * add new members, update both files. But first, try to remove members. The
+ * sharp* and xml* members should be moved onto the stack as local variables
+ * with well-known slots, if possible.
+ */
+struct JSStackFrame {
+ JSFrameRegs *regs;
+ jsbytecode *imacpc; /* null or interpreter macro call pc */
+ jsval *slots; /* variables, locals and operand stack */
+ JSObject *callobj; /* lazily created Call object */
+ JSObject *argsobj; /* lazily created arguments object */
+ JSObject *varobj; /* variables object, where vars go */
+ JSObject *callee; /* function or script object */
+ JSScript *script; /* script being interpreted */
+ JSFunction *fun; /* function being called or null */
+ JSObject *thisp; /* "this" pointer if in method */
+ uintN argc; /* actual argument count */
+ jsval *argv; /* base of argument stack slots */
+ jsval rval; /* function return value */
+ JSStackFrame *down; /* previous frame */
+ void *annotation; /* used by Java security */
+ JSObject *scopeChain; /* scope chain */
+ uintN sharpDepth; /* array/object initializer depth */
+ JSObject *sharpArray; /* scope for #n= initializer vars */
+ uint32 flags; /* frame flags -- see below */
+ JSStackFrame *dormantNext; /* next dormant frame chain */
+ JSObject *xmlNamespace; /* null or default xml namespace in E4X */
+ JSObject *blockChain; /* active compile-time block scopes */
+ JSStackFrame *displaySave; /* previous value of display entry for
+ script->staticDepth */
+#ifdef DEBUG
+ jsrefcount pcDisabledSave; /* for balanced property cache control */
+#endif
+};
+
+#ifdef DEBUG
+#ifdef __cplusplus
+static JS_INLINE uintN
+FramePCOffset(JSStackFrame* fp)
+{
+ return uintN((fp->imacpc ? fp->imacpc : fp->regs->pc) - fp->script->code);
+}
+#endif
+#endif
+
+static JS_INLINE jsval *
+StackBase(JSStackFrame *fp)
+{
+ return fp->slots + fp->script->nfixed;
+}
+
+static JS_INLINE uintN
+GlobalVarCount(JSStackFrame *fp)
+{
+ uintN n;
+
+ JS_ASSERT(!fp->fun);
+ n = fp->script->nfixed;
+ if (fp->script->regexpsOffset != 0)
+ n -= JS_SCRIPT_REGEXPS(fp->script)->length;
+ return n;
+}
+
+typedef struct JSInlineFrame {
+ JSStackFrame frame; /* base struct */
+ JSFrameRegs callerRegs; /* parent's frame registers */
+ void *mark; /* mark before inline frame */
+ void *hookData; /* debugger call hook data */
+ JSVersion callerVersion; /* dynamic version of calling script */
+} JSInlineFrame;
+
+/* JS stack frame flags. */
+#define JSFRAME_CONSTRUCTING 0x01 /* frame is for a constructor invocation */
+#define JSFRAME_COMPUTED_THIS 0x02 /* frame.thisp was computed already */
+#define JSFRAME_ASSIGNING 0x04 /* a complex (not simplex JOF_ASSIGNING) op
+ is currently assigning to a property */
+#define JSFRAME_DEBUGGER 0x08 /* frame for JS_EvaluateInStackFrame */
+#define JSFRAME_EVAL 0x10 /* frame for obj_eval */
+#define JSFRAME_ROOTED_ARGV 0x20 /* frame.argv is rooted by the caller */
+#define JSFRAME_YIELDING 0x40 /* js_Interpret dispatched JSOP_YIELD */
+#define JSFRAME_ITERATOR 0x80 /* trying to get an iterator for for-in */
+#define JSFRAME_POP_BLOCKS 0x100 /* scope chain contains blocks to pop */
+#define JSFRAME_GENERATOR 0x200 /* frame belongs to generator-iterator */
+#define JSFRAME_IMACRO_START 0x400 /* imacro starting -- see jstracer.h */
+
+#define JSFRAME_OVERRIDE_SHIFT 24 /* override bit-set params; see jsfun.c */
+#define JSFRAME_OVERRIDE_BITS 8
+
+#define JSFRAME_SPECIAL (JSFRAME_DEBUGGER | JSFRAME_EVAL)
+
+/*
+ * Property cache with structurally typed capabilities for invalidation, for
+ * polymorphic callsite method/get/set speedups.
+ *
+ * See bug https://bugzilla.mozilla.org/show_bug.cgi?id=365851.
+ */
+#define PROPERTY_CACHE_LOG2 12
+#define PROPERTY_CACHE_SIZE JS_BIT(PROPERTY_CACHE_LOG2)
+#define PROPERTY_CACHE_MASK JS_BITMASK(PROPERTY_CACHE_LOG2)
+
+/*
+ * Add kshape rather than xor it to avoid collisions between nearby bytecode
+ * that are evolving an object by setting successive properties, incrementing
+ * the object's scope->shape on each set.
+ */
+#define PROPERTY_CACHE_HASH(pc,kshape) \
+ (((((jsuword)(pc) >> PROPERTY_CACHE_LOG2) ^ (jsuword)(pc)) + (kshape)) & \
+ PROPERTY_CACHE_MASK)
+
+#define PROPERTY_CACHE_HASH_PC(pc,kshape) \
+ PROPERTY_CACHE_HASH(pc, kshape)
+
+#define PROPERTY_CACHE_HASH_ATOM(atom,obj,pobj) \
+ PROPERTY_CACHE_HASH((jsuword)(atom) >> 2, OBJ_SHAPE(obj))
+
+/*
+ * Property cache value capability macros.
+ */
+#define PCVCAP_PROTOBITS 4
+#define PCVCAP_PROTOSIZE JS_BIT(PCVCAP_PROTOBITS)
+#define PCVCAP_PROTOMASK JS_BITMASK(PCVCAP_PROTOBITS)
+
+#define PCVCAP_SCOPEBITS 4
+#define PCVCAP_SCOPESIZE JS_BIT(PCVCAP_SCOPEBITS)
+#define PCVCAP_SCOPEMASK JS_BITMASK(PCVCAP_SCOPEBITS)
+
+#define PCVCAP_TAGBITS (PCVCAP_PROTOBITS + PCVCAP_SCOPEBITS)
+#define PCVCAP_TAGMASK JS_BITMASK(PCVCAP_TAGBITS)
+#define PCVCAP_TAG(t) ((t) & PCVCAP_TAGMASK)
+
+#define PCVCAP_MAKE(t,s,p) (((t) << PCVCAP_TAGBITS) | \
+ ((s) << PCVCAP_PROTOBITS) | \
+ (p))
+#define PCVCAP_SHAPE(t) ((t) >> PCVCAP_TAGBITS)
+
+#define SHAPE_OVERFLOW_BIT JS_BIT(32 - PCVCAP_TAGBITS)
+
+/*
+ * When sprop is not null and the shape generation triggers the GC due to a
+ * shape overflow, the functions roots sprop.
+ */
+extern uint32
+js_GenerateShape(JSContext *cx, JSBool gcLocked, JSScopeProperty *sprop);
+
+struct JSPropCacheEntry {
+ jsbytecode *kpc; /* pc if vcap tag is <= 1, else atom */
+ jsuword kshape; /* key shape if pc, else obj for atom */
+ jsuword vcap; /* value capability, see above */
+ jsuword vword; /* value word, see PCVAL_* below */
+};
+
+#if defined DEBUG_brendan || defined DEBUG_brendaneich
+#define JS_PROPERTY_CACHE_METERING 1
+#endif
+
+typedef struct JSPropertyCache {
+ JSPropCacheEntry table[PROPERTY_CACHE_SIZE];
+ JSBool empty;
+ jsrefcount disabled; /* signed for anti-underflow asserts */
+#ifdef JS_PROPERTY_CACHE_METERING
+ uint32 fills; /* number of cache entry fills */
+ uint32 nofills; /* couldn't fill (e.g. default get) */
+ uint32 rofills; /* set on read-only prop can't fill */
+ uint32 disfills; /* fill attempts on disabled cache */
+ uint32 oddfills; /* fill attempt after setter deleted */
+ uint32 modfills; /* fill that rehashed to a new entry */
+ uint32 brandfills; /* scope brandings to type structural
+ method fills */
+ uint32 noprotos; /* resolve-returned non-proto pobj */
+ uint32 longchains; /* overlong scope and/or proto chain */
+ uint32 recycles; /* cache entries recycled by fills */
+ uint32 pcrecycles; /* pc-keyed entries recycled by atom-
+ keyed fills */
+ uint32 tests; /* cache probes */
+ uint32 pchits; /* fast-path polymorphic op hits */
+ uint32 protopchits; /* pchits hitting immediate prototype */
+ uint32 initests; /* cache probes from JSOP_INITPROP */
+ uint32 inipchits; /* init'ing next property pchit case */
+ uint32 inipcmisses; /* init'ing next property pc misses */
+ uint32 settests; /* cache probes from JOF_SET opcodes */
+ uint32 addpchits; /* adding next property pchit case */
+ uint32 setpchits; /* setting existing property pchit */
+ uint32 setpcmisses; /* setting/adding property pc misses */
+ uint32 slotchanges; /* clasp->reserveSlots result variance-
+ induced slot changes */
+ uint32 setmisses; /* JSOP_SET{NAME,PROP} total misses */
+ uint32 idmisses; /* slow-path key id == atom misses */
+ uint32 komisses; /* slow-path key object misses */
+ uint32 vcmisses; /* value capability misses */
+ uint32 misses; /* cache misses */
+ uint32 flushes; /* cache flushes */
+ uint32 pcpurges; /* shadowing purges on proto chain */
+# define PCMETER(x) x
+#else
+# define PCMETER(x) ((void)0)
+#endif
+} JSPropertyCache;
+
+/*
+ * Property cache value tagging/untagging macros.
+ */
+#define PCVAL_OBJECT 0
+#define PCVAL_SLOT 1
+#define PCVAL_SPROP 2
+
+#define PCVAL_TAGBITS 2
+#define PCVAL_TAGMASK JS_BITMASK(PCVAL_TAGBITS)
+#define PCVAL_TAG(v) ((v) & PCVAL_TAGMASK)
+#define PCVAL_CLRTAG(v) ((v) & ~(jsuword)PCVAL_TAGMASK)
+#define PCVAL_SETTAG(v,t) ((jsuword)(v) | (t))
+
+#define PCVAL_NULL 0
+#define PCVAL_IS_NULL(v) ((v) == PCVAL_NULL)
+
+#define PCVAL_IS_OBJECT(v) (PCVAL_TAG(v) == PCVAL_OBJECT)
+#define PCVAL_TO_OBJECT(v) ((JSObject *) (v))
+#define OBJECT_TO_PCVAL(obj) ((jsuword) (obj))
+
+#define PCVAL_OBJECT_TO_JSVAL(v) OBJECT_TO_JSVAL(PCVAL_TO_OBJECT(v))
+#define JSVAL_OBJECT_TO_PCVAL(v) OBJECT_TO_PCVAL(JSVAL_TO_OBJECT(v))
+
+#define PCVAL_IS_SLOT(v) ((v) & PCVAL_SLOT)
+#define PCVAL_TO_SLOT(v) ((jsuint)(v) >> 1)
+#define SLOT_TO_PCVAL(i) (((jsuword)(i) << 1) | PCVAL_SLOT)
+
+#define PCVAL_IS_SPROP(v) (PCVAL_TAG(v) == PCVAL_SPROP)
+#define PCVAL_TO_SPROP(v) ((JSScopeProperty *) PCVAL_CLRTAG(v))
+#define SPROP_TO_PCVAL(sprop) PCVAL_SETTAG(sprop, PCVAL_SPROP)
+
+/*
+ * Fill property cache entry for key cx->fp->pc, optimized value word computed
+ * from obj and sprop, and entry capability forged from 24-bit OBJ_SHAPE(obj),
+ * 4-bit scopeIndex, and 4-bit protoIndex.
+ */
+extern void
+js_FillPropertyCache(JSContext *cx, JSObject *obj, jsuword kshape,
+ uintN scopeIndex, uintN protoIndex,
+ JSObject *pobj, JSScopeProperty *sprop,
+ JSPropCacheEntry **entryp);
+
+/*
+ * Property cache lookup macros. PROPERTY_CACHE_TEST is designed to inline the
+ * fast path in js_Interpret, so it makes "just-so" restrictions on parameters,
+ * e.g. pobj and obj should not be the same variable, since for JOF_PROP-mode
+ * opcodes, obj must not be changed because of a cache miss.
+ *
+ * On return from PROPERTY_CACHE_TEST, if atom is null then obj points to the
+ * scope chain element in which the property was found, pobj is locked, and
+ * entry is valid. If atom is non-null then no object is locked but entry is
+ * still set correctly for use, e.g., by js_FillPropertyCache and atom should
+ * be used as the id to find.
+ *
+ * We must lock pobj on a hit in order to close races with threads that might
+ * be deleting a property from its scope, or otherwise invalidating property
+ * caches (on all threads) by re-generating scope->shape.
+ */
+#define PROPERTY_CACHE_TEST(cx, pc, obj, pobj, entry, atom) \
+ do { \
+ JSPropertyCache *cache_ = &JS_PROPERTY_CACHE(cx); \
+ uint32 kshape_ = (JS_ASSERT(OBJ_IS_NATIVE(obj)), OBJ_SHAPE(obj)); \
+ entry = &cache_->table[PROPERTY_CACHE_HASH_PC(pc, kshape_)]; \
+ PCMETER(cache_->tests++); \
+ JS_ASSERT(&obj != &pobj); \
+ if (entry->kpc == pc && entry->kshape == kshape_) { \
+ JSObject *tmp_; \
+ pobj = obj; \
+ JS_LOCK_OBJ(cx, pobj); \
+ JS_ASSERT(PCVCAP_TAG(entry->vcap) <= 1); \
+ if (PCVCAP_TAG(entry->vcap) == 1 && \
+ (tmp_ = LOCKED_OBJ_GET_PROTO(pobj)) != NULL && \
+ OBJ_IS_NATIVE(tmp_)) { \
+ JS_UNLOCK_OBJ(cx, pobj); \
+ pobj = tmp_; \
+ JS_LOCK_OBJ(cx, pobj); \
+ } \
+ if (PCVCAP_SHAPE(entry->vcap) == OBJ_SHAPE(pobj)) { \
+ PCMETER(cache_->pchits++); \
+ PCMETER(!PCVCAP_TAG(entry->vcap) || cache_->protopchits++); \
+ pobj = OBJ_SCOPE(pobj)->object; \
+ atom = NULL; \
+ break; \
+ } \
+ JS_UNLOCK_OBJ(cx, pobj); \
+ } \
+ atom = js_FullTestPropertyCache(cx, pc, &obj, &pobj, &entry); \
+ if (atom) \
+ PCMETER(cache_->misses++); \
+ } while (0)
+
+extern JSAtom *
+js_FullTestPropertyCache(JSContext *cx, jsbytecode *pc,
+ JSObject **objp, JSObject **pobjp,
+ JSPropCacheEntry **entryp);
+
+extern void
+js_FlushPropertyCache(JSContext *cx);
+
+extern void
+js_FlushPropertyCacheForScript(JSContext *cx, JSScript *script);
+
+extern void
+js_DisablePropertyCache(JSContext *cx);
+
+extern void
+js_EnablePropertyCache(JSContext *cx);
+
+/*
+ * Interpreter stack arena-pool alloc and free functions.
+ */
+extern JS_FRIEND_API(jsval *)
+js_AllocStack(JSContext *cx, uintN nslots, void **markp);
+
+extern JS_FRIEND_API(void)
+js_FreeStack(JSContext *cx, void *mark);
+
+/*
+ * Refresh and return fp->scopeChain. It may be stale if block scopes are
+ * active but not yet reflected by objects in the scope chain. If a block
+ * scope contains a with, eval, XML filtering predicate, or similar such
+ * dynamically scoped construct, then compile-time block scope at fp->blocks
+ * must reflect at runtime.
+ */
+extern JSObject *
+js_GetScopeChain(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * Given a context and a vector of [callee, this, args...] for a function that
+ * was specified with a JSFUN_THISP_PRIMITIVE flag, get the primitive value of
+ * |this| into *thisvp. In doing so, if |this| is an object, insist it is an
+ * instance of clasp and extract its private slot value to return via *thisvp.
+ *
+ * NB: this function loads and uses *vp before storing *thisvp, so the two may
+ * alias the same jsval.
+ */
+extern JSBool
+js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp);
+
+/*
+ * For a call with arguments argv including argv[-1] (nominal |this|) and
+ * argv[-2] (callee) replace null |this| with callee's parent, replace
+ * primitive values with the equivalent wrapper objects and censor activation
+ * objects as, per ECMA-262, they may not be referred to by |this|. argv[-1]
+ * must not be a JSVAL_VOID.
+ */
+extern JSObject *
+js_ComputeThis(JSContext *cx, JSBool lazy, jsval *argv);
+
+extern const uint16 js_PrimitiveTestFlags[];
+
+#define PRIMITIVE_THIS_TEST(fun,thisv) \
+ (JS_ASSERT(!JSVAL_IS_VOID(thisv)), \
+ JSFUN_THISP_TEST(JSFUN_THISP_FLAGS((fun)->flags), \
+ js_PrimitiveTestFlags[JSVAL_TAG(thisv) - 1]))
+
+/*
+ * NB: js_Invoke requires that cx is currently running JS (i.e., that cx->fp
+ * is non-null), and that vp points to the callee, |this| parameter, and
+ * actual arguments of the call. [vp .. vp + 2 + argc) must belong to the last
+ * JS stack segment that js_AllocStack allocated. The function may use the
+ * space available after vp + 2 + argc in the stack segment for temporaries,
+ * so the caller should not use that space for values that must be preserved
+ * across the call.
+ */
+extern JS_FRIEND_API(JSBool)
+js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags);
+
+/*
+ * Consolidated js_Invoke flags simply rename certain JSFRAME_* flags, so that
+ * we can share bits stored in JSStackFrame.flags and passed to:
+ *
+ * js_Invoke
+ * js_InternalInvoke
+ * js_ValueToFunction
+ * js_ValueToFunctionObject
+ * js_ValueToCallableObject
+ * js_ReportIsNotFunction
+ *
+ * See jsfun.h for the latter four and flag renaming macros.
+ */
+#define JSINVOKE_CONSTRUCT JSFRAME_CONSTRUCTING
+#define JSINVOKE_ITERATOR JSFRAME_ITERATOR
+
+/*
+ * Mask to isolate construct and iterator flags for use with jsfun.h functions.
+ */
+#define JSINVOKE_FUNFLAGS (JSINVOKE_CONSTRUCT | JSINVOKE_ITERATOR)
+
+/*
+ * "Internal" calls may come from C or C++ code using a JSContext on which no
+ * JS is running (!cx->fp), so they may need to push a dummy JSStackFrame.
+ */
+#define js_InternalCall(cx,obj,fval,argc,argv,rval) \
+ js_InternalInvoke(cx, obj, fval, 0, argc, argv, rval)
+
+#define js_InternalConstruct(cx,obj,fval,argc,argv,rval) \
+ js_InternalInvoke(cx, obj, fval, JSINVOKE_CONSTRUCT, argc, argv, rval)
+
+extern JSBool
+js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags,
+ uintN argc, jsval *argv, jsval *rval);
+
+extern JSBool
+js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
+ JSAccessMode mode, uintN argc, jsval *argv, jsval *rval);
+
+extern JSBool
+js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
+ JSStackFrame *down, uintN flags, jsval *result);
+
+extern JSBool
+js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp);
+
+extern JSBool
+js_Interpret(JSContext *cx);
+
+#define JSPROP_INITIALIZER 0x100 /* NB: Not a valid property attribute. */
+
+extern JSBool
+js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
+ JSObject **objp, JSProperty **propp);
+
+extern JSBool
+js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval);
+
+/*
+ * JS_LONE_INTERPRET indicates that the compiler should see just the code for
+ * the js_Interpret function when compiling jsinterp.cpp. The rest of the code
+ * from the file should be visible only when compiling jsinvoke.cpp. It allows
+ * platform builds to optimize selectively js_Interpret when the granularity
+ * of the optimizations with the given compiler is a compilation unit.
+ *
+ * JS_STATIC_INTERPRET is the modifier for functions defined in jsinterp.cpp
+ * that only js_Interpret calls. When JS_LONE_INTERPRET is true all such
+ * functions are declared below.
+ */
+#ifndef JS_LONE_INTERPRET
+# ifdef _MSC_VER
+# define JS_LONE_INTERPRET 0
+# else
+# define JS_LONE_INTERPRET 1
+# endif
+#endif
+
+#if !JS_LONE_INTERPRET
+# define JS_STATIC_INTERPRET static
+#else
+# define JS_STATIC_INTERPRET
+
+extern jsval *
+js_AllocRawStack(JSContext *cx, uintN nslots, void **markp);
+
+extern void
+js_FreeRawStack(JSContext *cx, void *mark);
+
+/*
+ * ECMA requires "the global object", but in embeddings such as the browser,
+ * which have multiple top-level objects (windows, frames, etc. in the DOM),
+ * we prefer fun's parent. An example that causes this code to run:
+ *
+ * // in window w1
+ * function f() { return this }
+ * function g() { return f }
+ *
+ * // in window w2
+ * var h = w1.g()
+ * alert(h() == w1)
+ *
+ * The alert should display "true".
+ */
+extern JSObject *
+js_ComputeGlobalThis(JSContext *cx, JSBool lazy, jsval *argv);
+
+extern JSBool
+js_EnterWith(JSContext *cx, jsint stackIndex);
+
+extern void
+js_LeaveWith(JSContext *cx);
+
+extern JSClass *
+js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth);
+
+extern jsint
+js_CountWithBlocks(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * Unwind block and scope chains to match the given depth. The function sets
+ * fp->sp on return to stackDepth.
+ */
+extern JSBool
+js_UnwindScope(JSContext *cx, JSStackFrame *fp, jsint stackDepth,
+ JSBool normalUnwind);
+
+extern JSBool
+js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp);
+
+extern JSBool
+js_OnUnknownMethod(JSContext *cx, jsval *vp);
+
+/*
+ * Find the results of incrementing or decrementing *vp. For pre-increments,
+ * both *vp and *vp2 will contain the result on return. For post-increments,
+ * vp will contain the original value converted to a number and vp2 will get
+ * the result. Both vp and vp2 must be roots.
+ */
+extern JSBool
+js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2);
+
+/*
+ * Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the
+ * previous opcode.
+ */
+extern void
+js_TraceOpcode(JSContext *cx, jsint len);
+
+/*
+ * JS_OPMETER helper functions.
+ */
+extern void
+js_MeterOpcodePair(JSOp op1, JSOp op2);
+
+extern void
+js_MeterSlotOpcode(JSOp op, uint32 slot);
+
+#endif /* JS_LONE_INTERPRET */
+
+JS_END_EXTERN_C
+
+#endif /* jsinterp_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsinvoke.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsinvoke.cpp
new file mode 100644
index 0000000..893813e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsinvoke.cpp
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.8 code, released
+ * March 4, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Igor Bukanov <igor@mir2.org>
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#define jsinvoke_cpp___
+
+#include "jsinterp.cpp"
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsiter.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsiter.cpp
new file mode 100644
index 0000000..c662045
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsiter.cpp
@@ -0,0 +1,1050 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JavaScript iterators.
+ */
+#include "jsstddef.h"
+#include <string.h> /* for memcpy */
+#include "jstypes.h"
+#include "jsutil.h"
+#include "jsarena.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsexn.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#if JSSLOT_ITER_FLAGS >= JS_INITIAL_NSLOTS
+#error JS_INITIAL_NSLOTS must be greater than JSSLOT_ITER_FLAGS.
+#endif
+
+#if JS_HAS_GENERATORS
+
+static JSBool
+CloseGenerator(JSContext *cx, JSObject *genobj);
+
+#endif
+
+/*
+ * Shared code to close iterator's state either through an explicit call or
+ * when GC detects that the iterator is no longer reachable.
+ */
+void
+js_CloseNativeIterator(JSContext *cx, JSObject *iterobj)
+{
+ jsval state;
+ JSObject *iterable;
+
+ JS_ASSERT(STOBJ_GET_CLASS(iterobj) == &js_IteratorClass);
+
+ /* Avoid double work if js_CloseNativeIterator was called on obj. */
+ state = STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_STATE);
+ if (JSVAL_IS_NULL(state))
+ return;
+
+ /* Protect against failure to fully initialize obj. */
+ iterable = STOBJ_GET_PARENT(iterobj);
+ if (iterable) {
+#if JS_HAS_XML_SUPPORT
+ uintN flags = JSVAL_TO_INT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_FLAGS));
+ if ((flags & JSITER_FOREACH) && OBJECT_IS_XML(cx, iterable)) {
+ ((JSXMLObjectOps *) iterable->map->ops)->
+ enumerateValues(cx, iterable, JSENUMERATE_DESTROY, &state,
+ NULL, NULL);
+ } else
+#endif
+ OBJ_ENUMERATE(cx, iterable, JSENUMERATE_DESTROY, &state, NULL);
+ }
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, JSVAL_NULL);
+}
+
+JSClass js_IteratorClass = {
+ "Iterator",
+ JSCLASS_HAS_RESERVED_SLOTS(2) | /* slots for state and flags */
+ JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+InitNativeIterator(JSContext *cx, JSObject *iterobj, JSObject *obj, uintN flags)
+{
+ jsval state;
+ JSBool ok;
+
+ JS_ASSERT(STOBJ_GET_CLASS(iterobj) == &js_IteratorClass);
+
+ /* Initialize iterobj in case of enumerate hook failure. */
+ STOBJ_SET_PARENT(iterobj, obj);
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, JSVAL_NULL);
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_FLAGS, INT_TO_JSVAL(flags));
+ if (!js_RegisterCloseableIterator(cx, iterobj))
+ return JS_FALSE;
+ if (!obj)
+ return JS_TRUE;
+
+ ok =
+#if JS_HAS_XML_SUPPORT
+ ((flags & JSITER_FOREACH) && OBJECT_IS_XML(cx, obj))
+ ? ((JSXMLObjectOps *) obj->map->ops)->
+ enumerateValues(cx, obj, JSENUMERATE_INIT, &state, NULL, NULL)
+ :
+#endif
+ OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &state, NULL);
+ if (!ok)
+ return JS_FALSE;
+
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state);
+ if (flags & JSITER_ENUMERATE) {
+ /*
+ * The enumerating iterator needs the original object to suppress
+ * enumeration of deleted or shadowed prototype properties. Since the
+ * enumerator never escapes to scripts, we use the prototype slot to
+ * store the original object.
+ */
+ JS_ASSERT(obj != iterobj);
+ STOBJ_SET_PROTO(iterobj, obj);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+Iterator(JSContext *cx, JSObject *iterobj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSBool keyonly;
+ uintN flags;
+ JSObject *obj;
+
+ keyonly = js_ValueToBoolean(argv[1]);
+ flags = keyonly ? 0 : JSITER_FOREACH;
+
+ if (cx->fp->flags & JSFRAME_CONSTRUCTING) {
+ /* XXX work around old valueOf call hidden beneath js_ValueToObject */
+ if (!JSVAL_IS_PRIMITIVE(argv[0])) {
+ obj = JSVAL_TO_OBJECT(argv[0]);
+ } else {
+ obj = js_ValueToNonNullObject(cx, argv[0]);
+ if (!obj)
+ return JS_FALSE;
+ argv[0] = OBJECT_TO_JSVAL(obj);
+ }
+ return InitNativeIterator(cx, iterobj, obj, flags);
+ }
+
+ *rval = argv[0];
+ return js_ValueToIterator(cx, flags, rval);
+}
+
+static JSBool
+NewKeyValuePair(JSContext *cx, jsid key, jsval val, jsval *rval)
+{
+ jsval vec[2];
+ JSTempValueRooter tvr;
+ JSObject *aobj;
+
+ vec[0] = ID_TO_VALUE(key);
+ vec[1] = val;
+
+ JS_PUSH_TEMP_ROOT(cx, 2, vec, &tvr);
+ aobj = js_NewArrayObject(cx, 2, vec);
+ *rval = OBJECT_TO_JSVAL(aobj);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+
+ return aobj != NULL;
+}
+
+static JSBool
+IteratorNextImpl(JSContext *cx, JSObject *obj, jsval *rval)
+{
+ JSObject *iterable;
+ jsval state;
+ uintN flags;
+ JSBool foreach, ok;
+ jsid id;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_IteratorClass);
+
+ iterable = OBJ_GET_PARENT(cx, obj);
+ JS_ASSERT(iterable);
+ state = STOBJ_GET_SLOT(obj, JSSLOT_ITER_STATE);
+ if (JSVAL_IS_NULL(state))
+ goto stop;
+
+ flags = JSVAL_TO_INT(STOBJ_GET_SLOT(obj, JSSLOT_ITER_FLAGS));
+ JS_ASSERT(!(flags & JSITER_ENUMERATE));
+ foreach = (flags & JSITER_FOREACH) != 0;
+ ok =
+#if JS_HAS_XML_SUPPORT
+ (foreach && OBJECT_IS_XML(cx, iterable))
+ ? ((JSXMLObjectOps *) iterable->map->ops)->
+ enumerateValues(cx, iterable, JSENUMERATE_NEXT, &state,
+ &id, rval)
+ :
+#endif
+ OBJ_ENUMERATE(cx, iterable, JSENUMERATE_NEXT, &state, &id);
+ if (!ok)
+ return JS_FALSE;
+
+ STOBJ_SET_SLOT(obj, JSSLOT_ITER_STATE, state);
+ if (JSVAL_IS_NULL(state))
+ goto stop;
+
+ if (foreach) {
+#if JS_HAS_XML_SUPPORT
+ if (!OBJECT_IS_XML(cx, iterable) &&
+ !OBJ_GET_PROPERTY(cx, iterable, id, rval)) {
+ return JS_FALSE;
+ }
+#endif
+ if (!NewKeyValuePair(cx, id, *rval, rval))
+ return JS_FALSE;
+ } else {
+ *rval = ID_TO_VALUE(id);
+ }
+ return JS_TRUE;
+
+ stop:
+ JS_ASSERT(STOBJ_GET_SLOT(obj, JSSLOT_ITER_STATE) == JSVAL_NULL);
+ *rval = JSVAL_HOLE;
+ return JS_TRUE;
+}
+
+JSBool
+js_ThrowStopIteration(JSContext *cx)
+{
+ jsval v;
+
+ JS_ASSERT(!JS_IsExceptionPending(cx));
+ if (js_FindClassObject(cx, NULL, INT_TO_JSID(JSProto_StopIteration), &v))
+ JS_SetPendingException(cx, v);
+ return JS_FALSE;
+}
+
+static JSBool
+iterator_next(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_IteratorClass, vp + 2))
+ return JS_FALSE;
+
+ if (!IteratorNextImpl(cx, obj, vp))
+ return JS_FALSE;
+
+ if (*vp == JSVAL_HOLE) {
+ *vp = JSVAL_NULL;
+ js_ThrowStopIteration(cx);
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+iterator_self(JSContext *cx, uintN argc, jsval *vp)
+{
+ *vp = JS_THIS(cx, vp);
+ return !JSVAL_IS_NULL(*vp);
+}
+
+#define JSPROP_ROPERM (JSPROP_READONLY | JSPROP_PERMANENT)
+
+static JSFunctionSpec iterator_methods[] = {
+ JS_FN(js_iterator_str, iterator_self, 0,JSPROP_ROPERM),
+ JS_FN(js_next_str, iterator_next, 0,JSPROP_ROPERM),
+ JS_FS_END
+};
+
+uintN
+js_GetNativeIteratorFlags(JSContext *cx, JSObject *iterobj)
+{
+ if (OBJ_GET_CLASS(cx, iterobj) != &js_IteratorClass)
+ return 0;
+ return JSVAL_TO_INT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_FLAGS));
+}
+
+/*
+ * Call ToObject(v).__iterator__(keyonly) if ToObject(v).__iterator__ exists.
+ * Otherwise construct the default iterator.
+ */
+JS_FRIEND_API(JSBool)
+js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
+{
+ JSObject *obj;
+ JSTempValueRooter tvr;
+ JSAtom *atom;
+ JSClass *clasp;
+ JSExtendedClass *xclasp;
+ JSBool ok;
+ JSObject *iterobj;
+ jsval arg;
+
+ JS_ASSERT(!(flags & ~(JSITER_ENUMERATE |
+ JSITER_FOREACH |
+ JSITER_KEYVALUE)));
+
+ /* JSITER_KEYVALUE must always come with JSITER_FOREACH */
+ JS_ASSERT(!(flags & JSITER_KEYVALUE) || (flags & JSITER_FOREACH));
+
+ /* XXX work around old valueOf call hidden beneath js_ValueToObject */
+ if (!JSVAL_IS_PRIMITIVE(*vp)) {
+ obj = JSVAL_TO_OBJECT(*vp);
+ } else {
+ /*
+ * Enumerating over null and undefined gives an empty enumerator.
+ * This is contrary to ECMA-262 9.9 ToObject, invoked from step 3 of
+ * the first production in 12.6.4 and step 4 of the second production,
+ * but it's "web JS" compatible.
+ */
+ if ((flags & JSITER_ENUMERATE)) {
+ if (!js_ValueToObject(cx, *vp, &obj))
+ return JS_FALSE;
+ if (!obj)
+ goto default_iter;
+ } else {
+ obj = js_ValueToNonNullObject(cx, *vp);
+ if (!obj)
+ return JS_FALSE;
+ }
+ }
+
+ JS_ASSERT(obj);
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if ((clasp->flags & JSCLASS_IS_EXTENDED) &&
+ (xclasp = (JSExtendedClass *) clasp)->iteratorObject) {
+ iterobj = xclasp->iteratorObject(cx, obj, !(flags & JSITER_FOREACH));
+ if (!iterobj)
+ goto bad;
+ *vp = OBJECT_TO_JSVAL(iterobj);
+ } else {
+ atom = cx->runtime->atomState.iteratorAtom;
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ if (!js_GetXMLFunction(cx, obj, ATOM_TO_JSID(atom), vp))
+ goto bad;
+ } else
+#endif
+ {
+ if (!OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp))
+ goto bad;
+ }
+
+ if (JSVAL_IS_VOID(*vp)) {
+ default_iter:
+ /*
+ * Fail over to the default enumerating native iterator.
+ *
+ * Create iterobj with a NULL parent to ensure that we use the
+ * correct scope chain to lookup the iterator's constructor. Since
+ * we use the parent slot to keep track of the iterable, we must
+ * fix it up after.
+ */
+ iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL, 0);
+ if (!iterobj)
+ goto bad;
+
+ /* Store in *vp to protect it from GC (callers must root vp). */
+ *vp = OBJECT_TO_JSVAL(iterobj);
+
+ if (!InitNativeIterator(cx, iterobj, obj, flags))
+ goto bad;
+ } else {
+ arg = BOOLEAN_TO_JSVAL((flags & JSITER_FOREACH) == 0);
+ if (!js_InternalInvoke(cx, obj, *vp, JSINVOKE_ITERATOR, 1, &arg,
+ vp)) {
+ goto bad;
+ }
+ if (JSVAL_IS_PRIMITIVE(*vp)) {
+ const char *printable = js_AtomToPrintableString(cx, atom);
+ if (printable) {
+ js_ReportValueError2(cx, JSMSG_BAD_ITERATOR_RETURN,
+ JSDVG_SEARCH_STACK, *vp, NULL,
+ printable);
+ }
+ goto bad;
+ }
+ }
+ }
+
+ ok = JS_TRUE;
+ out:
+ if (obj)
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+ bad:
+ ok = JS_FALSE;
+ goto out;
+}
+
+JS_FRIEND_API(JSBool) JS_FASTCALL
+js_CloseIterator(JSContext *cx, jsval v)
+{
+ JSObject *obj;
+ JSClass *clasp;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ obj = JSVAL_TO_OBJECT(v);
+ clasp = OBJ_GET_CLASS(cx, obj);
+
+ if (clasp == &js_IteratorClass) {
+ js_CloseNativeIterator(cx, obj);
+ }
+#if JS_HAS_GENERATORS
+ else if (clasp == &js_GeneratorClass) {
+ if (!CloseGenerator(cx, obj))
+ return JS_FALSE;
+ }
+#endif
+ return JS_TRUE;
+}
+
+static JSBool
+CallEnumeratorNext(JSContext *cx, JSObject *iterobj, uintN flags, jsval *rval)
+{
+ JSObject *obj, *origobj;
+ jsval state;
+ JSBool foreach;
+ jsid id;
+ JSObject *obj2;
+ JSBool cond;
+ JSClass *clasp;
+ JSExtendedClass *xclasp;
+ JSProperty *prop;
+ JSString *str;
+
+ JS_ASSERT(flags & JSITER_ENUMERATE);
+ JS_ASSERT(STOBJ_GET_CLASS(iterobj) == &js_IteratorClass);
+
+ obj = STOBJ_GET_PARENT(iterobj);
+ origobj = STOBJ_GET_PROTO(iterobj);
+ state = STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_STATE);
+ if (JSVAL_IS_NULL(state))
+ goto stop;
+
+ foreach = (flags & JSITER_FOREACH) != 0;
+#if JS_HAS_XML_SUPPORT
+ /*
+ * Treat an XML object specially only when it starts the prototype chain.
+ * Otherwise we need to do the usual deleted and shadowed property checks.
+ */
+ if (obj == origobj && OBJECT_IS_XML(cx, obj)) {
+ if (foreach) {
+ JSXMLObjectOps *xmlops = (JSXMLObjectOps *) obj->map->ops;
+
+ if (!xmlops->enumerateValues(cx, obj, JSENUMERATE_NEXT, &state,
+ &id, rval)) {
+ return JS_FALSE;
+ }
+ } else {
+ if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &state, &id))
+ return JS_FALSE;
+ }
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state);
+ if (JSVAL_IS_NULL(state))
+ goto stop;
+ } else
+#endif
+ {
+ restart:
+ if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &state, &id))
+ return JS_FALSE;
+
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state);
+ if (JSVAL_IS_NULL(state)) {
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ /*
+ * We just finished enumerating an XML obj that is present on
+ * the prototype chain of a non-XML origobj. Stop further
+ * prototype chain searches because XML objects don't
+ * enumerate prototypes.
+ */
+ JS_ASSERT(origobj != obj);
+ JS_ASSERT(!OBJECT_IS_XML(cx, origobj));
+ } else
+#endif
+ {
+ obj = OBJ_GET_PROTO(cx, obj);
+ if (obj) {
+ STOBJ_SET_PARENT(iterobj, obj);
+ if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &state, NULL))
+ return JS_FALSE;
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state);
+ if (!JSVAL_IS_NULL(state))
+ goto restart;
+ }
+ }
+ goto stop;
+ }
+
+ /* Skip properties not in obj when looking from origobj. */
+ if (!OBJ_LOOKUP_PROPERTY(cx, origobj, id, &obj2, &prop))
+ return JS_FALSE;
+ if (!prop)
+ goto restart;
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+
+ /*
+ * If the id was found in a prototype object or an unrelated object
+ * (specifically, not in an inner object for obj), skip it. This step
+ * means that all OBJ_LOOKUP_PROPERTY implementations must return an
+ * object further along on the prototype chain, or else possibly an
+ * object returned by the JSExtendedClass.outerObject optional hook.
+ */
+ if (obj != obj2) {
+ cond = JS_FALSE;
+ clasp = OBJ_GET_CLASS(cx, obj2);
+ if (clasp->flags & JSCLASS_IS_EXTENDED) {
+ xclasp = (JSExtendedClass *) clasp;
+ cond = xclasp->outerObject &&
+ xclasp->outerObject(cx, obj2) == obj;
+ }
+ if (!cond)
+ goto restart;
+ }
+
+ if (foreach) {
+ /* Get property querying the original object. */
+ if (!OBJ_GET_PROPERTY(cx, origobj, id, rval))
+ return JS_FALSE;
+ }
+ }
+
+ if (foreach) {
+ if (flags & JSITER_KEYVALUE) {
+ if (!NewKeyValuePair(cx, id, *rval, rval))
+ return JS_FALSE;
+ }
+ } else {
+ /* Make rval a string for uniformity and compatibility. */
+ str = js_ValueToString(cx, ID_TO_VALUE(id));
+ if (!str)
+ return JS_FALSE;
+ *rval = STRING_TO_JSVAL(str);
+ }
+ return JS_TRUE;
+
+ stop:
+ JS_ASSERT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_STATE) == JSVAL_NULL);
+ *rval = JSVAL_HOLE;
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_CallIteratorNext(JSContext *cx, JSObject *iterobj, jsval *rval)
+{
+ uintN flags;
+
+ /* Fast path for native iterators */
+ if (OBJ_GET_CLASS(cx, iterobj) == &js_IteratorClass) {
+ flags = JSVAL_TO_INT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_FLAGS));
+ if (flags & JSITER_ENUMERATE)
+ return CallEnumeratorNext(cx, iterobj, flags, rval);
+
+ /*
+ * Call next directly as all the methods of the native iterator are
+ * read-only and permanent.
+ */
+ if (!IteratorNextImpl(cx, iterobj, rval))
+ return JS_FALSE;
+ } else {
+ jsid id = ATOM_TO_JSID(cx->runtime->atomState.nextAtom);
+
+ if (!JS_GetMethodById(cx, iterobj, id, &iterobj, rval))
+ return JS_FALSE;
+ if (!js_InternalCall(cx, iterobj, *rval, 0, NULL, rval)) {
+ /* Check for StopIteration. */
+ if (!cx->throwing || !js_ValueIsStopIteration(cx->exception))
+ return JS_FALSE;
+
+ /* Inline JS_ClearPendingException(cx). */
+ cx->throwing = JS_FALSE;
+ cx->exception = JSVAL_VOID;
+ *rval = JSVAL_HOLE;
+ return JS_TRUE;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+stopiter_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ *bp = js_ValueIsStopIteration(v);
+ return JS_TRUE;
+}
+
+JSClass js_StopIterationClass = {
+ js_StopIteration_str,
+ JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration),
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub,
+ JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, stopiter_hasInstance,
+ NULL, NULL
+};
+
+#if JS_HAS_GENERATORS
+
+static void
+generator_finalize(JSContext *cx, JSObject *obj)
+{
+ JSGenerator *gen;
+
+ gen = (JSGenerator *) JS_GetPrivate(cx, obj);
+ if (gen) {
+ /*
+ * gen can be open on shutdown when close hooks are ignored or when
+ * the embedding cancels scheduled close hooks.
+ */
+ JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_CLOSED ||
+ gen->state == JSGEN_OPEN);
+ JS_free(cx, gen);
+ }
+}
+
+static void
+generator_trace(JSTracer *trc, JSObject *obj)
+{
+ JSGenerator *gen;
+
+ gen = (JSGenerator *) JS_GetPrivate(trc->context, obj);
+ if (!gen)
+ return;
+
+ /*
+ * js_TraceStackFrame does not recursively trace the down-linked frame
+ * chain, so we insist that gen->frame has no parent to trace when the
+ * generator is not running.
+ */
+ JS_ASSERT_IF(gen->state != JSGEN_RUNNING && gen->state != JSGEN_CLOSING,
+ !gen->frame.down);
+
+ /*
+ * FIXME be 390950. Generator's frame is a part of the JS stack when the
+ * generator is running or closing. Thus tracing the frame in this case
+ * here duplicates the work done in js_TraceContext.
+ */
+ js_TraceStackFrame(trc, &gen->frame);
+}
+
+JSClass js_GeneratorClass = {
+ js_Generator_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_IS_ANONYMOUS |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Generator),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, generator_finalize,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, JS_CLASS_TRACE(generator_trace), NULL
+};
+
+/*
+ * Called from the JSOP_GENERATOR case in the interpreter, with fp referring
+ * to the frame by which the generator function was activated. Create a new
+ * JSGenerator object, which contains its own JSStackFrame that we populate
+ * from *fp. We know that upon return, the JSOP_GENERATOR opcode will return
+ * from the activation in fp, so we can steal away fp->callobj and fp->argsobj
+ * if they are non-null.
+ */
+JSObject *
+js_NewGenerator(JSContext *cx, JSStackFrame *fp)
+{
+ JSObject *obj;
+ uintN argc, nargs, nslots;
+ JSGenerator *gen;
+ jsval *slots;
+
+ /* After the following return, failing control flow must goto bad. */
+ obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL, 0);
+ if (!obj)
+ return NULL;
+
+ /* Load and compute stack slot counts. */
+ argc = fp->argc;
+ nargs = JS_MAX(argc, fp->fun->nargs);
+ nslots = 2 + nargs + fp->script->nslots;
+
+ /* Allocate obj's private data struct. */
+ gen = (JSGenerator *)
+ JS_malloc(cx, sizeof(JSGenerator) + (nslots - 1) * sizeof(jsval));
+ if (!gen)
+ goto bad;
+
+ gen->obj = obj;
+
+ /* Steal away objects reflecting fp and point them at gen->frame. */
+ gen->frame.callobj = fp->callobj;
+ if (fp->callobj) {
+ JS_SetPrivate(cx, fp->callobj, &gen->frame);
+ fp->callobj = NULL;
+ }
+ gen->frame.argsobj = fp->argsobj;
+ if (fp->argsobj) {
+ JS_SetPrivate(cx, fp->argsobj, &gen->frame);
+ fp->argsobj = NULL;
+ }
+
+ /* These two references can be shared with fp until it goes away. */
+ gen->frame.varobj = fp->varobj;
+ gen->frame.thisp = fp->thisp;
+
+ /* Copy call-invariant script and function references. */
+ gen->frame.script = fp->script;
+ gen->frame.callee = fp->callee;
+ gen->frame.fun = fp->fun;
+
+ /* Use slots to carve space out of gen->slots. */
+ slots = gen->slots;
+ gen->arena.next = NULL;
+ gen->arena.base = (jsuword) slots;
+ gen->arena.limit = gen->arena.avail = (jsuword) (slots + nslots);
+
+ /* Copy rval, argv and vars. */
+ gen->frame.rval = fp->rval;
+ memcpy(slots, fp->argv - 2, (2 + nargs) * sizeof(jsval));
+ gen->frame.argc = nargs;
+ gen->frame.argv = slots + 2;
+ slots += 2 + nargs;
+ memcpy(slots, fp->slots, fp->script->nfixed * sizeof(jsval));
+
+ /* Initialize or copy virtual machine state. */
+ gen->frame.down = NULL;
+ gen->frame.annotation = NULL;
+ gen->frame.scopeChain = fp->scopeChain;
+
+ gen->frame.imacpc = NULL;
+ gen->frame.slots = slots;
+ JS_ASSERT(StackBase(fp) == fp->regs->sp);
+ gen->savedRegs.sp = slots + fp->script->nfixed;
+ gen->savedRegs.pc = fp->regs->pc;
+ gen->frame.regs = &gen->savedRegs;
+
+ /* Copy remaining state (XXX sharp* and xml* should be local vars). */
+ gen->frame.sharpDepth = 0;
+ gen->frame.sharpArray = NULL;
+ gen->frame.flags = (fp->flags & ~JSFRAME_ROOTED_ARGV) | JSFRAME_GENERATOR;
+ gen->frame.dormantNext = NULL;
+ gen->frame.xmlNamespace = NULL;
+ gen->frame.blockChain = NULL;
+
+ /* Note that gen is newborn. */
+ gen->state = JSGEN_NEWBORN;
+
+ if (!JS_SetPrivate(cx, obj, gen)) {
+ JS_free(cx, gen);
+ goto bad;
+ }
+ return obj;
+
+ bad:
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+}
+
+typedef enum JSGeneratorOp {
+ JSGENOP_NEXT,
+ JSGENOP_SEND,
+ JSGENOP_THROW,
+ JSGENOP_CLOSE
+} JSGeneratorOp;
+
+/*
+ * Start newborn or restart yielding generator and perform the requested
+ * operation inside its frame.
+ */
+static JSBool
+SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
+ JSGenerator *gen, jsval arg)
+{
+ JSStackFrame *fp;
+ JSArena *arena;
+ JSBool ok;
+
+ if (gen->state == JSGEN_RUNNING || gen->state == JSGEN_CLOSING) {
+ js_ReportValueError(cx, JSMSG_NESTING_GENERATOR,
+ JSDVG_SEARCH_STACK, OBJECT_TO_JSVAL(obj),
+ JS_GetFunctionId(gen->frame.fun));
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_OPEN);
+ switch (op) {
+ case JSGENOP_NEXT:
+ case JSGENOP_SEND:
+ if (gen->state == JSGEN_OPEN) {
+ /*
+ * Store the argument to send as the result of the yield
+ * expression.
+ */
+ gen->savedRegs.sp[-1] = arg;
+ }
+ gen->state = JSGEN_RUNNING;
+ break;
+
+ case JSGENOP_THROW:
+ JS_SetPendingException(cx, arg);
+ gen->state = JSGEN_RUNNING;
+ break;
+
+ default:
+ JS_ASSERT(op == JSGENOP_CLOSE);
+ JS_SetPendingException(cx, JSVAL_ARETURN);
+ gen->state = JSGEN_CLOSING;
+ break;
+ }
+
+ /* Extend the current stack pool with gen->arena. */
+ arena = cx->stackPool.current;
+ JS_ASSERT(!arena->next);
+ JS_ASSERT(!gen->arena.next);
+ JS_ASSERT(cx->stackPool.current != &gen->arena);
+ cx->stackPool.current = arena->next = &gen->arena;
+
+ /* Push gen->frame around the interpreter activation. */
+ fp = cx->fp;
+ cx->fp = &gen->frame;
+ gen->frame.down = fp;
+ ok = js_Interpret(cx);
+ cx->fp = fp;
+ gen->frame.down = NULL;
+
+ /* Retract the stack pool and sanitize gen->arena. */
+ JS_ASSERT(!gen->arena.next);
+ JS_ASSERT(arena->next == &gen->arena);
+ JS_ASSERT(cx->stackPool.current == &gen->arena);
+ cx->stackPool.current = arena;
+ arena->next = NULL;
+
+ if (gen->frame.flags & JSFRAME_YIELDING) {
+ /* Yield cannot fail, throw or be called on closing. */
+ JS_ASSERT(ok);
+ JS_ASSERT(!cx->throwing);
+ JS_ASSERT(gen->state == JSGEN_RUNNING);
+ JS_ASSERT(op != JSGENOP_CLOSE);
+ gen->frame.flags &= ~JSFRAME_YIELDING;
+ gen->state = JSGEN_OPEN;
+ return JS_TRUE;
+ }
+
+ gen->frame.rval = JSVAL_VOID;
+ gen->state = JSGEN_CLOSED;
+ if (ok) {
+ /* Returned, explicitly or by falling off the end. */
+ if (op == JSGENOP_CLOSE)
+ return JS_TRUE;
+ return js_ThrowStopIteration(cx);
+ }
+
+ /*
+ * An error, silent termination by operation callback or an exception.
+ * Propagate the condition to the caller.
+ */
+ return JS_FALSE;
+}
+
+static JSBool
+CloseGenerator(JSContext *cx, JSObject *obj)
+{
+ JSGenerator *gen;
+
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_GeneratorClass);
+ gen = (JSGenerator *) JS_GetPrivate(cx, obj);
+ if (!gen) {
+ /* Generator prototype object. */
+ return JS_TRUE;
+ }
+
+ if (gen->state == JSGEN_CLOSED)
+ return JS_TRUE;
+
+ return SendToGenerator(cx, JSGENOP_CLOSE, obj, gen, JSVAL_VOID);
+}
+
+/*
+ * Common subroutine of generator_(next|send|throw|close) methods.
+ */
+static JSBool
+generator_op(JSContext *cx, JSGeneratorOp op, jsval *vp, uintN argc)
+{
+ JSObject *obj;
+ JSGenerator *gen;
+ jsval arg;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_GeneratorClass, vp + 2))
+ return JS_FALSE;
+
+ gen = (JSGenerator *) JS_GetPrivate(cx, obj);
+ if (gen == NULL) {
+ /* This happens when obj is the generator prototype. See bug 352885. */
+ goto closed_generator;
+ }
+
+ if (gen->state == JSGEN_NEWBORN) {
+ switch (op) {
+ case JSGENOP_NEXT:
+ case JSGENOP_THROW:
+ break;
+
+ case JSGENOP_SEND:
+ if (argc >= 1 && !JSVAL_IS_VOID(vp[2])) {
+ js_ReportValueError(cx, JSMSG_BAD_GENERATOR_SEND,
+ JSDVG_SEARCH_STACK, vp[2], NULL);
+ return JS_FALSE;
+ }
+ break;
+
+ default:
+ JS_ASSERT(op == JSGENOP_CLOSE);
+ gen->state = JSGEN_CLOSED;
+ return JS_TRUE;
+ }
+ } else if (gen->state == JSGEN_CLOSED) {
+ closed_generator:
+ switch (op) {
+ case JSGENOP_NEXT:
+ case JSGENOP_SEND:
+ return js_ThrowStopIteration(cx);
+ case JSGENOP_THROW:
+ JS_SetPendingException(cx, argc >= 1 ? vp[2] : JSVAL_VOID);
+ return JS_FALSE;
+ default:
+ JS_ASSERT(op == JSGENOP_CLOSE);
+ return JS_TRUE;
+ }
+ }
+
+ arg = ((op == JSGENOP_SEND || op == JSGENOP_THROW) && argc != 0)
+ ? vp[2]
+ : JSVAL_VOID;
+ if (!SendToGenerator(cx, op, obj, gen, arg))
+ return JS_FALSE;
+ *vp = gen->frame.rval;
+ return JS_TRUE;
+}
+
+static JSBool
+generator_send(JSContext *cx, uintN argc, jsval *vp)
+{
+ return generator_op(cx, JSGENOP_SEND, vp, argc);
+}
+
+static JSBool
+generator_next(JSContext *cx, uintN argc, jsval *vp)
+{
+ return generator_op(cx, JSGENOP_NEXT, vp, argc);
+}
+
+static JSBool
+generator_throw(JSContext *cx, uintN argc, jsval *vp)
+{
+ return generator_op(cx, JSGENOP_THROW, vp, argc);
+}
+
+static JSBool
+generator_close(JSContext *cx, uintN argc, jsval *vp)
+{
+ return generator_op(cx, JSGENOP_CLOSE, vp, argc);
+}
+
+static JSFunctionSpec generator_methods[] = {
+ JS_FN(js_iterator_str, iterator_self, 0,JSPROP_ROPERM),
+ JS_FN(js_next_str, generator_next, 0,JSPROP_ROPERM),
+ JS_FN(js_send_str, generator_send, 1,JSPROP_ROPERM),
+ JS_FN(js_throw_str, generator_throw, 1,JSPROP_ROPERM),
+ JS_FN(js_close_str, generator_close, 0,JSPROP_ROPERM),
+ JS_FS_END
+};
+
+#endif /* JS_HAS_GENERATORS */
+
+JSObject *
+js_InitIteratorClasses(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto, *stop;
+
+ /* Idempotency required: we initialize several things, possibly lazily. */
+ if (!js_GetClassObject(cx, obj, JSProto_StopIteration, &stop))
+ return NULL;
+ if (stop)
+ return stop;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_IteratorClass, Iterator, 2,
+ NULL, iterator_methods, NULL, NULL);
+ if (!proto)
+ return NULL;
+ STOBJ_SET_SLOT(proto, JSSLOT_ITER_STATE, JSVAL_NULL);
+
+#if JS_HAS_GENERATORS
+ /* Initialize the generator internals if configured. */
+ if (!JS_InitClass(cx, obj, NULL, &js_GeneratorClass, NULL, 0,
+ NULL, generator_methods, NULL, NULL)) {
+ return NULL;
+ }
+#endif
+
+ return JS_InitClass(cx, obj, NULL, &js_StopIterationClass, NULL, 0,
+ NULL, NULL, NULL, NULL);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsiter.h b/tools/node_modules/expresso/deps/jscoverage/js/jsiter.h
new file mode 100644
index 0000000..2a7bb16
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsiter.h
@@ -0,0 +1,140 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsiter_h___
+#define jsiter_h___
+
+/*
+ * JavaScript iterators.
+ */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * NB: these flag bits are encoded into the bytecode stream in the immediate
+ * operand of JSOP_ITER, so don't change them without advancing jsxdrapi.h's
+ * JSXDR_BYTECODE_VERSION.
+ */
+#define JSITER_ENUMERATE 0x1 /* for-in compatible hidden default iterator */
+#define JSITER_FOREACH 0x2 /* return [key, value] pair rather than key */
+#define JSITER_KEYVALUE 0x4 /* destructuring for-in wants [key, value] */
+
+/*
+ * Native iterator object slots, shared between jsiter.cpp and jstracer.cpp.
+ */
+#define JSSLOT_ITER_STATE (JSSLOT_PRIVATE)
+#define JSSLOT_ITER_FLAGS (JSSLOT_PRIVATE + 1)
+
+/*
+ * Convert the value stored in *vp to its iteration object. The flags should
+ * contain JSITER_ENUMERATE if js_ValueToIterator is called when enumerating
+ * for-in semantics are required, and when the caller can guarantee that the
+ * iterator will never be exposed to scripts.
+ */
+extern JS_FRIEND_API(JSBool)
+js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp);
+
+extern JS_FRIEND_API(JSBool) JS_FASTCALL
+js_CloseIterator(JSContext *cx, jsval v);
+
+/*
+ * Given iterobj, call iterobj.next(). If the iterator stopped, set *rval to
+ * JSVAL_HOLE. Otherwise set it to the result of the next call.
+ */
+extern JS_FRIEND_API(JSBool)
+js_CallIteratorNext(JSContext *cx, JSObject *iterobj, jsval *rval);
+
+/*
+ * Close iterobj, whose class must be js_IteratorClass.
+ */
+extern void
+js_CloseNativeIterator(JSContext *cx, JSObject *iterobj);
+
+extern JSBool
+js_ThrowStopIteration(JSContext *cx);
+
+#if JS_HAS_GENERATORS
+
+/*
+ * Generator state codes.
+ */
+typedef enum JSGeneratorState {
+ JSGEN_NEWBORN, /* not yet started */
+ JSGEN_OPEN, /* started by a .next() or .send(undefined) call */
+ JSGEN_RUNNING, /* currently executing via .next(), etc., call */
+ JSGEN_CLOSING, /* close method is doing asynchronous return */
+ JSGEN_CLOSED /* closed, cannot be started or closed again */
+} JSGeneratorState;
+
+struct JSGenerator {
+ JSObject *obj;
+ JSGeneratorState state;
+ JSStackFrame frame;
+ JSFrameRegs savedRegs;
+ JSArena arena;
+ jsval slots[1];
+};
+
+#define FRAME_TO_GENERATOR(fp) \
+ ((JSGenerator *) ((uint8 *)(fp) - offsetof(JSGenerator, frame)))
+
+extern JSObject *
+js_NewGenerator(JSContext *cx, JSStackFrame *fp);
+
+#endif
+
+extern JSClass js_GeneratorClass;
+extern JSClass js_IteratorClass;
+extern JSClass js_StopIterationClass;
+
+static inline bool
+js_ValueIsStopIteration(jsval v)
+{
+ return !JSVAL_IS_PRIMITIVE(v) &&
+ STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v)) == &js_StopIterationClass;
+}
+
+extern JSObject *
+js_InitIteratorClasses(JSContext *cx, JSObject *obj);
+
+JS_END_EXTERN_C
+
+#endif /* jsiter_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jskeyword.tbl b/tools/node_modules/expresso/deps/jscoverage/js/jskeyword.tbl
new file mode 100644
index 0000000..adcbf0e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jskeyword.tbl
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+JS_KEYWORD(break, TOK_BREAK, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(case, TOK_CASE, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(continue, TOK_CONTINUE, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(default, TOK_DEFAULT, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(delete, TOK_DELETE, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(do, TOK_DO, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(else, TOK_ELSE, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(export, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(false, TOK_PRIMARY, JSOP_FALSE, JSVERSION_DEFAULT)
+JS_KEYWORD(for, TOK_FOR, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(function, TOK_FUNCTION, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(if, TOK_IF, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(in, TOK_IN, JSOP_IN, JSVERSION_DEFAULT)
+JS_KEYWORD(new, TOK_NEW, JSOP_NEW, JSVERSION_DEFAULT)
+JS_KEYWORD(null, TOK_PRIMARY, JSOP_NULL, JSVERSION_DEFAULT)
+JS_KEYWORD(return, TOK_RETURN, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(switch, TOK_SWITCH, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(this, TOK_PRIMARY, JSOP_THIS, JSVERSION_DEFAULT)
+JS_KEYWORD(true, TOK_PRIMARY, JSOP_TRUE, JSVERSION_DEFAULT)
+JS_KEYWORD(typeof, TOK_UNARYOP, JSOP_TYPEOF, JSVERSION_DEFAULT)
+JS_KEYWORD(var, TOK_VAR, JSOP_DEFVAR, JSVERSION_DEFAULT)
+JS_KEYWORD(void, TOK_UNARYOP, JSOP_VOID, JSVERSION_DEFAULT)
+JS_KEYWORD(while, TOK_WHILE, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(with, TOK_WITH, JSOP_NOP, JSVERSION_DEFAULT)
+#if JS_HAS_CONST
+JS_KEYWORD(const, TOK_VAR, JSOP_DEFCONST, JSVERSION_DEFAULT)
+#else
+JS_KEYWORD(const, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+#endif
+
+JS_KEYWORD(try, TOK_TRY, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(catch, TOK_CATCH, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(finally, TOK_FINALLY, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(throw, TOK_THROW, JSOP_NOP, JSVERSION_DEFAULT)
+
+JS_KEYWORD(instanceof, TOK_INSTANCEOF, JSOP_INSTANCEOF,JSVERSION_DEFAULT)
+
+#if JS_HAS_RESERVED_JAVA_KEYWORDS
+JS_KEYWORD(abstract, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(boolean, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(byte, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(char, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(class, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(double, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(extends, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(final, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(float, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(goto, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(implements, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(import, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(int, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(interface, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(long, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(native, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(package, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(private, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(protected, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(public, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(short, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(static, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(super, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(synchronized,TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(throws, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(transient, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(volatile, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+#endif
+
+#if JS_HAS_RESERVED_ECMA_KEYWORDS
+JS_KEYWORD(enum, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+#endif
+
+#if JS_HAS_DEBUGGER_KEYWORD
+JS_KEYWORD(debugger, TOK_DEBUGGER, JSOP_NOP, JSVERSION_DEFAULT)
+#elif JS_HAS_RESERVED_ECMA_KEYWORDS
+JS_KEYWORD(debugger, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+#endif
+
+#if JS_HAS_GENERATORS
+JS_KEYWORD(yield, TOK_YIELD, JSOP_NOP, JSVERSION_1_7)
+#endif
+
+#if JS_HAS_BLOCK_SCOPE
+JS_KEYWORD(let, TOK_LET, JSOP_NOP, JSVERSION_1_7)
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jskwgen.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jskwgen.cpp
new file mode 100644
index 0000000..1d26c3d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jskwgen.cpp
@@ -0,0 +1,460 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is String Switch Generator for JavaScript Keywords,
+ * released 2005-12-09.
+ *
+ * The Initial Developer of the Original Code is
+ * Igor Bukanov.
+ * Portions created by the Initial Developer are Copyright (C) 2005-2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include "jsversion.h"
+
+const char * const keyword_list[] = {
+#define JS_KEYWORD(keyword, type, op, version) #keyword,
+#include "jskeyword.tbl"
+#undef JS_KEYWORD
+};
+
+struct gen_opt {
+ FILE *output; /* output file for generated source */
+ unsigned use_if_threshold; /* max number of choices to generate
+ "if" selector instead of "switch" */
+ unsigned char_tail_test_threshold; /* max number of unprocessed columns
+ to use inlined char compare
+ for remaining chars and not generic
+ string compare code */
+ unsigned indent_level; /* current source identation level */
+};
+
+static unsigned column_to_compare;
+
+static int
+length_comparator(const void *a, const void *b)
+{
+ const char *str1 = keyword_list[*(unsigned *)a];
+ const char *str2 = keyword_list[*(unsigned *)b];
+ return (int)strlen(str1) - (int)strlen(str2);
+}
+
+static int
+column_comparator(const void *a, const void *b)
+{
+ const char *str1 = keyword_list[*(unsigned *)a];
+ const char *str2 = keyword_list[*(unsigned *)b];
+ return (int)str1[column_to_compare] - (int)str2[column_to_compare];
+}
+
+static unsigned
+count_different_lengths(unsigned indexes[], unsigned nelem)
+{
+ unsigned nlength, current_length, i, l;
+
+ current_length = 0;
+ nlength = 0;
+ for (i = 0; i != nelem; ++i) {
+ l = (unsigned)strlen(keyword_list[indexes[i]]);
+ assert(l != 0);
+ if (current_length != l) {
+ ++nlength;
+ current_length = l;
+ }
+ }
+ return nlength;
+}
+
+static void
+find_char_span_and_count(unsigned indexes[], unsigned nelem, unsigned column,
+ unsigned *span_result, unsigned *count_result)
+{
+ unsigned i, count;
+ unsigned char c, prev, minc, maxc;
+
+ assert(nelem != 0);
+ minc = maxc = prev = (unsigned char)keyword_list[indexes[0]][column];
+ count = 1;
+ for (i = 1; i != nelem; ++i) {
+ c = (unsigned char)keyword_list[indexes[i]][column];
+ if (prev != c) {
+ prev = c;
+ ++count;
+ if (minc > c) {
+ minc = c;
+ } else if (maxc < c) {
+ maxc = c;
+ }
+ }
+ }
+
+ *span_result = maxc - minc + 1;
+ *count_result = count;
+}
+
+static unsigned
+find_optimal_switch_column(struct gen_opt *opt,
+ unsigned indexes[], unsigned nelem,
+ unsigned columns[], unsigned unprocessed_columns,
+ int *use_if_result)
+{
+ unsigned i;
+ unsigned span, min_span, min_span_index;
+ unsigned nchar, min_nchar, min_nchar_index;
+
+ assert(unprocessed_columns != 0);
+ i = 0;
+ min_nchar = min_span = (unsigned)-1;
+ min_nchar_index = min_span_index = 0;
+ do {
+ column_to_compare = columns[i];
+ qsort(indexes, nelem, sizeof(indexes[0]), column_comparator);
+ find_char_span_and_count(indexes, nelem, column_to_compare,
+ &span, &nchar);
+ assert(span != 0);
+ if (span == 1) {
+ assert(nchar == 1);
+ *use_if_result = 1;
+ return 1;
+ }
+ assert(nchar != 1);
+ if (min_span > span) {
+ min_span = span;
+ min_span_index = i;
+ }
+ if (min_nchar > nchar) {
+ min_nchar = nchar;
+ min_nchar_index = i;
+ }
+ } while (++i != unprocessed_columns);
+
+ if (min_nchar <= opt->use_if_threshold) {
+ *use_if_result = 1;
+ i = min_nchar_index;
+ } else {
+ *use_if_result = 0;
+ i = min_span_index;
+ }
+
+ /*
+ * Restore order corresponding to i if it was destroyed by
+ * subsequent sort.
+ */
+ if (i != unprocessed_columns - 1) {
+ column_to_compare = columns[i];
+ qsort(indexes, nelem, sizeof(indexes[0]), column_comparator);
+ }
+
+ return i;
+}
+
+
+static void
+p(struct gen_opt *opt, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vfprintf(opt->output, format, ap);
+ va_end(ap);
+}
+
+/* Size for '\xxx' where xxx is octal escape */
+#define MIN_QUOTED_CHAR_BUFFER 7
+
+static char *
+qchar(char c, char *quoted_buffer)
+{
+ char *s;
+
+ s = quoted_buffer;
+ *s++ = '\'';
+ switch (c) {
+ case '\n': c = 'n'; goto one_char_escape;
+ case '\r': c = 'r'; goto one_char_escape;
+ case '\t': c = 't'; goto one_char_escape;
+ case '\f': c = 't'; goto one_char_escape;
+ case '\0': c = '0'; goto one_char_escape;
+ case '\'': goto one_char_escape;
+ one_char_escape:
+ *s++ = '\\';
+ break;
+ default:
+ if (!isprint(c)) {
+ *s++ = '\\';
+ *s++ = (char)('0' + (0x3 & (((unsigned char)c) >> 6)));
+ *s++ = (char)('0' + (0x7 & (((unsigned char)c) >> 3)));
+ c = (char)('0' + (0x7 & ((unsigned char)c)));
+ }
+ }
+ *s++ = c;
+ *s++ = '\'';
+ *s = '\0';
+ assert(s + 1 <= quoted_buffer + MIN_QUOTED_CHAR_BUFFER);
+ return quoted_buffer;
+}
+
+static void
+nl(struct gen_opt *opt)
+{
+ putc('\n', opt->output);
+}
+
+static void
+indent(struct gen_opt *opt)
+{
+ unsigned n = opt->indent_level;
+ while (n != 0) {
+ --n;
+ fputs(" ", opt->output);
+ }
+}
+
+static void
+line(struct gen_opt *opt, const char *format, ...)
+{
+ va_list ap;
+
+ indent(opt);
+ va_start(ap, format);
+ vfprintf(opt->output, format, ap);
+ va_end(ap);
+ nl(opt);
+}
+
+static void
+generate_letter_switch_r(struct gen_opt *opt,
+ unsigned indexes[], unsigned nelem,
+ unsigned columns[], unsigned unprocessed_columns)
+{
+ char qbuf[MIN_QUOTED_CHAR_BUFFER];
+
+ assert(nelem != 0);
+ if (nelem == 1) {
+ unsigned kw_index = indexes[0];
+ const char *keyword = keyword_list[kw_index];
+
+ if (unprocessed_columns == 0) {
+ line(opt, "JSKW_GOT_MATCH(%u) /* %s */", kw_index, keyword);
+ } else if (unprocessed_columns > opt->char_tail_test_threshold) {
+ line(opt, "JSKW_TEST_GUESS(%u) /* %s */", kw_index, keyword);
+ } else {
+ unsigned i, column;
+
+ indent(opt); p(opt, "if (");
+ for (i = 0; i != unprocessed_columns; ++i) {
+ column = columns[i];
+ qchar(keyword[column], qbuf);
+ p(opt, "%sJSKW_AT(%u)==%s", (i == 0) ? "" : " && ",
+ column, qbuf);
+ }
+ p(opt, ") {"); nl(opt);
+ ++opt->indent_level;
+ line(opt, "JSKW_GOT_MATCH(%u) /* %s */", kw_index, keyword);
+ --opt->indent_level;
+ line(opt, "}");
+ line(opt, "JSKW_NO_MATCH()");
+ }
+ } else {
+ unsigned optimal_column_index, optimal_column;
+ unsigned i;
+ int use_if;
+ char current;
+
+ assert(unprocessed_columns != 0);
+ optimal_column_index = find_optimal_switch_column(opt, indexes, nelem,
+ columns,
+ unprocessed_columns,
+ &use_if);
+ optimal_column = columns[optimal_column_index];
+ columns[optimal_column_index] = columns[unprocessed_columns - 1];
+
+ if (!use_if)
+ line(opt, "switch (JSKW_AT(%u)) {", optimal_column);
+
+ current = keyword_list[indexes[0]][optimal_column];
+ for (i = 0; i != nelem;) {
+ unsigned same_char_begin = i;
+ char next = current;
+
+ for (++i; i != nelem; ++i) {
+ next = keyword_list[indexes[i]][optimal_column];
+ if (next != current)
+ break;
+ }
+ qchar(current, qbuf);
+ if (use_if) {
+ line(opt, "if (JSKW_AT(%u) == %s) {", optimal_column, qbuf);
+ } else {
+ line(opt, " case %s:", qbuf);
+ }
+ ++opt->indent_level;
+ generate_letter_switch_r(opt, indexes + same_char_begin,
+ i - same_char_begin,
+ columns, unprocessed_columns - 1);
+ --opt->indent_level;
+ if (use_if) {
+ line(opt, "}");
+ }
+ current = next;
+ }
+
+ if (!use_if) {
+ line(opt, "}");
+ }
+
+ columns[optimal_column_index] = optimal_column;
+
+ line(opt, "JSKW_NO_MATCH()");
+ }
+}
+
+static void
+generate_letter_switch(struct gen_opt *opt,
+ unsigned indexes[], unsigned nelem,
+ unsigned current_length)
+{
+ unsigned *columns;
+ unsigned i;
+
+ columns = (unsigned *) malloc(sizeof(columns[0]) * current_length);
+ if (!columns) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+ for (i = 0; i != current_length; ++i) {
+ columns[i] = i;
+ }
+ generate_letter_switch_r(opt, indexes, nelem, columns, current_length);
+ free(columns);
+}
+
+
+static void
+generate_switch(struct gen_opt *opt)
+{
+ unsigned *indexes;
+ unsigned nlength;
+ unsigned i, current;
+ int use_if;
+ unsigned nelem;
+
+ nelem = sizeof(keyword_list)/sizeof(keyword_list[0]);
+
+ line(opt, "/*");
+ line(opt, " * Generating switch for the list of %u entries:", nelem);
+ for (i = 0; i != nelem; ++i) {
+ line(opt, " * %s", keyword_list[i]);
+ }
+ line(opt, " */");
+
+ indexes = (unsigned *) malloc(sizeof(indexes[0]) * nelem);
+ if (!indexes) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+ for (i = 0; i != nelem; ++i)
+ indexes[i] = i;
+ qsort(indexes, nelem, sizeof(indexes[i]), length_comparator);
+ nlength = count_different_lengths(indexes, nelem);
+
+ use_if = (nlength <= opt->use_if_threshold);
+
+ if (!use_if)
+ line(opt, "switch (JSKW_LENGTH()) {");
+
+ current = (unsigned)strlen(keyword_list[indexes[0]]);
+ for (i = 0; i != nelem;) {
+ unsigned same_length_begin = i;
+ unsigned next = current;
+
+ for (++i; i != nelem; ++i) {
+ next = (unsigned)strlen(keyword_list[indexes[i]]);
+ if (next != current)
+ break;
+ }
+ if (use_if) {
+ line(opt, "if (JSKW_LENGTH() == %u) {", current);
+ } else {
+ line(opt, " case %u:", current);
+ }
+ ++opt->indent_level;
+ generate_letter_switch(opt, indexes + same_length_begin,
+ i - same_length_begin,
+ current);
+ --opt->indent_level;
+ if (use_if) {
+ line(opt, "}");
+ }
+ current = next;
+ }
+ if (!use_if)
+ line(opt, "}");
+ line(opt, "JSKW_NO_MATCH()");
+ free(indexes);
+}
+
+int main(int argc, char **argv)
+{
+ struct gen_opt opt;
+
+ if (argc < 2) {
+ opt.output = stdout;
+ } else {
+ opt.output = fopen(argv[1], "w");
+ if (!opt.output) {
+ perror("fopen");
+ exit(EXIT_FAILURE);
+ }
+ }
+ opt.indent_level = 1;
+ opt.use_if_threshold = 3;
+ opt.char_tail_test_threshold = 4;
+
+ generate_switch(&opt);
+
+ if (opt.output != stdout) {
+ if (fclose(opt.output)) {
+ perror("fclose");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslibmath.h b/tools/node_modules/expresso/deps/jscoverage/js/jslibmath.h
new file mode 100644
index 0000000..d90a04c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslibmath.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _LIBMATH_H
+#define _LIBMATH_H
+
+#include <math.h>
+#include "jsversion.h"
+
+/*
+ * Use system provided math routines.
+ */
+
+/* The right copysign function is not always named the same thing. */
+#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#define js_copysign __builtin_copysign
+#elif defined WINCE
+#define js_copysign _copysign
+#elif defined _WIN32
+#if _MSC_VER < 1400
+/* Try to work around apparent _copysign bustage in VC6 and VC7. */
+#define js_copysign js_copysign
+extern double js_copysign(double, double);
+#else
+#define js_copysign _copysign
+#endif
+#else
+#define js_copysign copysign
+#endif
+
+#endif /* _LIBMATH_H */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslock.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jslock.cpp
new file mode 100644
index 0000000..f91f0ed
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslock.cpp
@@ -0,0 +1,1417 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef JS_THREADSAFE
+
+/*
+ * JS locking stubs.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jspubtd.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jscntxt.h"
+#include "jsdtoa.h"
+#include "jsgc.h"
+#include "jsfun.h" /* for VALUE_IS_FUNCTION used by *_WRITE_BARRIER */
+#include "jslock.h"
+#include "jsscope.h"
+#include "jsstr.h"
+
+#define ReadWord(W) (W)
+
+/* Implement NativeCompareAndSwap. */
+
+#if defined(_WIN32) && defined(_M_IX86)
+#pragma warning( disable : 4035 )
+JS_BEGIN_EXTERN_C
+extern long __cdecl
+_InterlockedCompareExchange(long *volatile dest, long exchange, long comp);
+JS_END_EXTERN_C
+#pragma intrinsic(_InterlockedCompareExchange)
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwapHelper(jsword *w, jsword ov, jsword nv)
+{
+ _InterlockedCompareExchange(w, nv, ov);
+ __asm {
+ sete al
+ }
+}
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ return (NativeCompareAndSwapHelper(w, ov, nv) & 1);
+}
+
+#elif defined(XP_MACOSX) || defined(DARWIN)
+
+#include <libkern/OSAtomic.h>
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ /* Details on these functions available in the manpage for atomic */
+#if JS_BYTES_PER_WORD == 8 && JS_BYTES_PER_LONG != 8
+ return OSAtomicCompareAndSwap64Barrier(ov, nv, (int64_t*) w);
+#else
+ return OSAtomicCompareAndSwap32Barrier(ov, nv, (int32_t*) w);
+#endif
+}
+
+#elif defined(__GNUC__) && defined(__i386__)
+
+/* Note: This fails on 386 cpus, cmpxchgl is a >= 486 instruction */
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ unsigned int res;
+
+ __asm__ __volatile__ (
+ "lock\n"
+ "cmpxchgl %2, (%1)\n"
+ "sete %%al\n"
+ "andl $1, %%eax\n"
+ : "=a" (res)
+ : "r" (w), "r" (nv), "a" (ov)
+ : "cc", "memory");
+ return (int)res;
+}
+
+#elif defined(__GNUC__) && defined(__x86_64__)
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ unsigned int res;
+
+ __asm__ __volatile__ (
+ "lock\n"
+ "cmpxchgq %2, (%1)\n"
+ "sete %%al\n"
+ "movzbl %%al, %%eax\n"
+ : "=a" (res)
+ : "r" (w), "r" (nv), "a" (ov)
+ : "cc", "memory");
+ return (int)res;
+}
+
+#elif defined(SOLARIS) && defined(sparc) && defined(ULTRA_SPARC)
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+#if defined(__GNUC__)
+ unsigned int res;
+ JS_ASSERT(ov != nv);
+ asm volatile ("\
+stbar\n\
+cas [%1],%2,%3\n\
+cmp %2,%3\n\
+be,a 1f\n\
+mov 1,%0\n\
+mov 0,%0\n\
+1:"
+ : "=r" (res)
+ : "r" (w), "r" (ov), "r" (nv));
+ return (int)res;
+#else /* !__GNUC__ */
+ extern int compare_and_swap(jsword*, jsword, jsword);
+ JS_ASSERT(ov != nv);
+ return compare_and_swap(w, ov, nv);
+#endif
+}
+
+#elif defined(AIX)
+
+#include <sys/atomic_op.h>
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ return !_check_lock((atomic_p)w, ov, nv);
+}
+
+#elif defined(USE_ARM_KUSER)
+
+/* See https://bugzilla.mozilla.org/show_bug.cgi?id=429387 for a
+ * description of this ABI; this is a function provided at a fixed
+ * location by the kernel in the memory space of each process.
+ */
+typedef int (__kernel_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
+#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
+
+JS_STATIC_ASSERT(sizeof(jsword) == sizeof(int));
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ volatile int *vp = (volatile int *) w;
+ PRInt32 failed = 1;
+
+ /* Loop until a __kernel_cmpxchg succeeds. See bug 446169 */
+ do {
+ failed = __kernel_cmpxchg(ov, nv, vp);
+ } while (failed && *vp == ov);
+ return !failed;
+}
+
+#elif JS_HAS_NATIVE_COMPARE_AND_SWAP
+
+#error "JS_HAS_NATIVE_COMPARE_AND_SWAP should be 0 if your platform lacks a compare-and-swap instruction."
+
+#endif /* arch-tests */
+
+#if JS_HAS_NATIVE_COMPARE_AND_SWAP
+
+JSBool
+js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ return !!NativeCompareAndSwap(w, ov, nv);
+}
+
+#elif defined(NSPR_LOCK)
+
+# ifdef __GNUC__
+# warning "js_CompareAndSwap is implemented using NSSP lock"
+# endif
+
+JSBool
+js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ int result;
+ static PRLock *CompareAndSwapLock = JS_NEW_LOCK();
+
+ JS_ACQUIRE_LOCK(CompareAndSwapLock);
+ result = (*w == ov);
+ if (result)
+ *w = nv;
+ JS_RELEASE_LOCK(CompareAndSwapLock);
+ return result;
+}
+
+#else /* !defined(NSPR_LOCK) */
+
+#error "NSPR_LOCK should be on when the platform lacks native compare-and-swap."
+
+#endif
+
+#ifndef NSPR_LOCK
+
+struct JSFatLock {
+ int susp;
+ PRLock *slock;
+ PRCondVar *svar;
+ JSFatLock *next;
+ JSFatLock **prevp;
+};
+
+typedef struct JSFatLockTable {
+ JSFatLock *free;
+ JSFatLock *taken;
+} JSFatLockTable;
+
+#define GLOBAL_LOCK_INDEX(id) (((uint32)(jsuword)(id)>>2) & global_locks_mask)
+
+static void
+js_Dequeue(JSThinLock *);
+
+static PRLock **global_locks;
+static uint32 global_lock_count = 1;
+static uint32 global_locks_log2 = 0;
+static uint32 global_locks_mask = 0;
+
+static void
+js_LockGlobal(void *id)
+{
+ uint32 i = GLOBAL_LOCK_INDEX(id);
+ PR_Lock(global_locks[i]);
+}
+
+static void
+js_UnlockGlobal(void *id)
+{
+ uint32 i = GLOBAL_LOCK_INDEX(id);
+ PR_Unlock(global_locks[i]);
+}
+
+#endif /* !NSPR_LOCK */
+
+void
+js_InitLock(JSThinLock *tl)
+{
+#ifdef NSPR_LOCK
+ tl->owner = 0;
+ tl->fat = (JSFatLock*)JS_NEW_LOCK();
+#else
+ memset(tl, 0, sizeof(JSThinLock));
+#endif
+}
+
+void
+js_FinishLock(JSThinLock *tl)
+{
+#ifdef NSPR_LOCK
+ tl->owner = 0xdeadbeef;
+ if (tl->fat)
+ JS_DESTROY_LOCK(((JSLock*)tl->fat));
+#else
+ JS_ASSERT(tl->owner == 0);
+ JS_ASSERT(tl->fat == NULL);
+#endif
+}
+
+#ifdef DEBUG_SCOPE_COUNT
+
+#include <stdio.h>
+#include "jsdhash.h"
+
+static FILE *logfp;
+static JSDHashTable logtbl;
+
+typedef struct logentry {
+ JSDHashEntryStub stub;
+ char op;
+ const char *file;
+ int line;
+} logentry;
+
+static void
+logit(JSScope *scope, char op, const char *file, int line)
+{
+ logentry *entry;
+
+ if (!logfp) {
+ logfp = fopen("/tmp/scope.log", "w");
+ if (!logfp)
+ return;
+ setvbuf(logfp, NULL, _IONBF, 0);
+ }
+ fprintf(logfp, "%p %c %s %d\n", scope, op, file, line);
+
+ if (!logtbl.entryStore &&
+ !JS_DHashTableInit(&logtbl, JS_DHashGetStubOps(), NULL,
+ sizeof(logentry), 100)) {
+ return;
+ }
+ entry = (logentry *) JS_DHashTableOperate(&logtbl, scope, JS_DHASH_ADD);
+ if (!entry)
+ return;
+ entry->stub.key = scope;
+ entry->op = op;
+ entry->file = file;
+ entry->line = line;
+}
+
+void
+js_unlog_scope(JSScope *scope)
+{
+ if (!logtbl.entryStore)
+ return;
+ (void) JS_DHashTableOperate(&logtbl, scope, JS_DHASH_REMOVE);
+}
+
+# define LOGIT(scope,op) logit(scope, op, __FILE__, __LINE__)
+
+#else
+
+# define LOGIT(scope,op) /* nothing */
+
+#endif /* DEBUG_SCOPE_COUNT */
+
+/*
+ * Return true if scope's ownercx, or the ownercx of a single-threaded scope
+ * for which ownercx is waiting to become multi-threaded and shared, is cx.
+ * That condition implies deadlock in ClaimScope if cx's thread were to wait
+ * to share scope.
+ *
+ * (i) rt->gcLock held
+ */
+static JSBool
+WillDeadlock(JSTitle *title, JSContext *cx)
+{
+ JSContext *ownercx;
+
+ do {
+ ownercx = title->ownercx;
+ if (ownercx == cx) {
+ JS_RUNTIME_METER(cx->runtime, deadlocksAvoided);
+ return JS_TRUE;
+ }
+ } while (ownercx && (title = ownercx->titleToShare) != NULL);
+ return JS_FALSE;
+}
+
+/*
+ * Make title multi-threaded, i.e. share its ownership among contexts in rt
+ * using a "thin" or (if necessary due to contention) "fat" lock. Called only
+ * from ClaimTitle, immediately below, when we detect deadlock were we to wait
+ * for title's lock, because its ownercx is waiting on a title owned by the
+ * calling cx.
+ *
+ * (i) rt->gcLock held
+ */
+static void
+ShareTitle(JSContext *cx, JSTitle *title)
+{
+ JSRuntime *rt;
+ JSTitle **todop;
+
+ rt = cx->runtime;
+ if (title->u.link) {
+ for (todop = &rt->titleSharingTodo; *todop != title;
+ todop = &(*todop)->u.link) {
+ JS_ASSERT(*todop != NO_TITLE_SHARING_TODO);
+ }
+ *todop = title->u.link;
+ title->u.link = NULL; /* null u.link for sanity ASAP */
+ JS_NOTIFY_ALL_CONDVAR(rt->titleSharingDone);
+ }
+ js_InitLock(&title->lock);
+ title->u.count = 0;
+ js_FinishSharingTitle(cx, title);
+}
+
+/*
+ * js_FinishSharingTitle is the tail part of ShareTitle, split out to become a
+ * subroutine of JS_EndRequest too. The bulk of the work here involves making
+ * mutable strings in the title's object's slots be immutable. We have to do
+ * this because such strings will soon be available to multiple threads, so
+ * their buffers can't be realloc'd any longer in js_ConcatStrings, and their
+ * members can't be modified by js_ConcatStrings, js_MinimizeDependentStrings,
+ * or js_UndependString.
+ *
+ * The last bit of work done by js_FinishSharingTitle nulls title->ownercx and
+ * updates rt->sharedTitles.
+ */
+
+void
+js_FinishSharingTitle(JSContext *cx, JSTitle *title)
+{
+ JSObjectMap *map;
+ JSScope *scope;
+ JSObject *obj;
+ uint32 nslots, i;
+ jsval v;
+
+ map = TITLE_TO_MAP(title);
+ if (!MAP_IS_NATIVE(map))
+ return;
+ scope = (JSScope *)map;
+
+ obj = scope->object;
+ if (obj) {
+ nslots = scope->map.freeslot;
+ for (i = 0; i != nslots; ++i) {
+ v = STOBJ_GET_SLOT(obj, i);
+ if (JSVAL_IS_STRING(v) &&
+ !js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) {
+ /*
+ * FIXME bug 363059: The following error recovery changes
+ * runtime execution semantics, arbitrarily and silently
+ * ignoring errors except out-of-memory, which should have been
+ * reported through JS_ReportOutOfMemory at this point.
+ */
+ STOBJ_SET_SLOT(obj, i, JSVAL_VOID);
+ }
+ }
+ }
+
+ title->ownercx = NULL; /* NB: set last, after lock init */
+ JS_RUNTIME_METER(cx->runtime, sharedTitles);
+}
+
+/*
+ * Given a title with apparently non-null ownercx different from cx, try to
+ * set ownercx to cx, claiming exclusive (single-threaded) ownership of title.
+ * If we claim ownership, return true. Otherwise, we wait for ownercx to be
+ * set to null (indicating that title is multi-threaded); or if waiting would
+ * deadlock, we set ownercx to null ourselves via ShareTitle. In any case,
+ * once ownercx is null we return false.
+ */
+static JSBool
+ClaimTitle(JSTitle *title, JSContext *cx)
+{
+ JSRuntime *rt;
+ JSContext *ownercx;
+ jsrefcount saveDepth;
+ PRStatus stat;
+
+ rt = cx->runtime;
+ JS_RUNTIME_METER(rt, claimAttempts);
+ JS_LOCK_GC(rt);
+
+ /* Reload in case ownercx went away while we blocked on the lock. */
+ while ((ownercx = title->ownercx) != NULL) {
+ /*
+ * Avoid selflock if ownercx is dead, or is not running a request, or
+ * has the same thread as cx. Set title->ownercx to cx so that the
+ * matching JS_UNLOCK_SCOPE or JS_UNLOCK_OBJ macro call will take the
+ * fast path around the corresponding js_UnlockTitle or js_UnlockObj
+ * function call.
+ *
+ * If title->u.link is non-null, title has already been inserted on
+ * the rt->titleSharingTodo list, because another thread's context
+ * already wanted to lock title while ownercx was running a request.
+ * We can't claim any title whose u.link is non-null at this point,
+ * even if ownercx->requestDepth is 0 (see below where we suspend our
+ * request before waiting on rt->titleSharingDone).
+ */
+ if (!title->u.link &&
+ (!js_ValidContextPointer(rt, ownercx) ||
+ !ownercx->requestDepth ||
+ ownercx->thread == cx->thread)) {
+ JS_ASSERT(title->u.count == 0);
+ title->ownercx = cx;
+ JS_UNLOCK_GC(rt);
+ JS_RUNTIME_METER(rt, claimedTitles);
+ return JS_TRUE;
+ }
+
+ /*
+ * Avoid deadlock if title's owner context is waiting on a title that
+ * we own, by revoking title's ownership. This approach to deadlock
+ * avoidance works because the engine never nests title locks.
+ *
+ * If cx could hold locks on ownercx->titleToShare, or if ownercx could
+ * hold locks on title, we would need to keep reentrancy counts for all
+ * such "flyweight" (ownercx != NULL) locks, so that control would
+ * unwind properly once these locks became "thin" or "fat". The engine
+ * promotes a title from exclusive to shared access only when locking,
+ * never when holding or unlocking.
+ *
+ * Avoid deadlock before any of this title/context cycle detection if
+ * cx is on the active GC's thread, because in that case, no requests
+ * will run until the GC completes. Any title wanted by the GC (from
+ * a finalizer) that can't be claimed must become shared.
+ */
+ if (rt->gcThread == cx->thread ||
+ (ownercx->titleToShare &&
+ WillDeadlock(ownercx->titleToShare, cx))) {
+ ShareTitle(cx, title);
+ break;
+ }
+
+ /*
+ * Thanks to the non-zero NO_TITLE_SHARING_TODO link terminator, we
+ * can decide whether title is on rt->titleSharingTodo with a single
+ * non-null test, and avoid double-insertion bugs.
+ */
+ if (!title->u.link) {
+ title->u.link = rt->titleSharingTodo;
+ rt->titleSharingTodo = title;
+ js_HoldObjectMap(cx, TITLE_TO_MAP(title));
+ }
+
+ /*
+ * Inline JS_SuspendRequest before we wait on rt->titleSharingDone,
+ * saving and clearing cx->requestDepth so we don't deadlock if the
+ * GC needs to run on ownercx.
+ *
+ * Unlike JS_SuspendRequest and JS_EndRequest, we must take care not
+ * to decrement rt->requestCount if cx is active on the GC's thread,
+ * because the GC has already reduced rt->requestCount to exclude all
+ * such such contexts.
+ */
+ saveDepth = cx->requestDepth;
+ if (saveDepth) {
+ cx->requestDepth = 0;
+ if (rt->gcThread != cx->thread) {
+ JS_ASSERT(rt->requestCount > 0);
+ rt->requestCount--;
+ if (rt->requestCount == 0)
+ JS_NOTIFY_REQUEST_DONE(rt);
+ }
+ }
+
+ /*
+ * We know that some other thread's context owns title, which is now
+ * linked onto rt->titleSharingTodo, awaiting the end of that other
+ * thread's request. So it is safe to wait on rt->titleSharingDone.
+ */
+ cx->titleToShare = title;
+ stat = PR_WaitCondVar(rt->titleSharingDone, PR_INTERVAL_NO_TIMEOUT);
+ JS_ASSERT(stat != PR_FAILURE);
+
+ /*
+ * Inline JS_ResumeRequest after waiting on rt->titleSharingDone,
+ * restoring cx->requestDepth. Same note as above for the inlined,
+ * specialized JS_SuspendRequest code: beware rt->gcThread.
+ */
+ if (saveDepth) {
+ if (rt->gcThread != cx->thread) {
+ while (rt->gcLevel > 0)
+ JS_AWAIT_GC_DONE(rt);
+ rt->requestCount++;
+ }
+ cx->requestDepth = saveDepth;
+ }
+
+ /*
+ * Don't clear cx->titleToShare until after we're through waiting on
+ * all condition variables protected by rt->gcLock -- that includes
+ * rt->titleSharingDone *and* rt->gcDone (hidden in JS_AWAIT_GC_DONE,
+ * in the inlined JS_ResumeRequest code immediately above).
+ *
+ * Otherwise, the GC could easily deadlock with another thread that
+ * owns a title wanted by a finalizer. By keeping cx->titleToShare
+ * set till here, we ensure that such deadlocks are detected, which
+ * results in the finalized object's title being shared (it must, of
+ * course, have other, live objects sharing it).
+ */
+ cx->titleToShare = NULL;
+ }
+
+ JS_UNLOCK_GC(rt);
+ return JS_FALSE;
+}
+
+/* Exported to js.c, which calls it via OBJ_GET_* and JSVAL_IS_* macros. */
+JS_FRIEND_API(jsval)
+js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
+{
+ jsval v;
+ JSScope *scope;
+ JSTitle *title;
+#ifndef NSPR_LOCK
+ JSThinLock *tl;
+ jsword me;
+#endif
+
+ /*
+ * We handle non-native objects via JSObjectOps.getRequiredSlot, treating
+ * all slots starting from 0 as required slots. A property definition or
+ * some prior arrangement must have allocated slot.
+ *
+ * Note once again (see jspubtd.h, before JSGetRequiredSlotOp's typedef)
+ * the crucial distinction between a |required slot number| that's passed
+ * to the get/setRequiredSlot JSObjectOps, and a |reserved slot index|
+ * passed to the JS_Get/SetReservedSlot APIs.
+ */
+ if (!OBJ_IS_NATIVE(obj))
+ return OBJ_GET_REQUIRED_SLOT(cx, obj, slot);
+
+ /*
+ * Native object locking is inlined here to optimize the single-threaded
+ * and contention-free multi-threaded cases.
+ */
+ scope = OBJ_SCOPE(obj);
+ title = &scope->title;
+ JS_ASSERT(title->ownercx != cx);
+ JS_ASSERT(slot < obj->map->freeslot);
+
+ /*
+ * Avoid locking if called from the GC. Also avoid locking an object
+ * owning a sealed scope. If neither of those special cases applies, try
+ * to claim scope's flyweight lock from whatever context may have had it in
+ * an earlier request.
+ */
+ if (CX_THREAD_IS_RUNNING_GC(cx) ||
+ (SCOPE_IS_SEALED(scope) && scope->object == obj) ||
+ (title->ownercx && ClaimTitle(title, cx))) {
+ return STOBJ_GET_SLOT(obj, slot);
+ }
+
+#ifndef NSPR_LOCK
+ tl = &title->lock;
+ me = CX_THINLOCK_ID(cx);
+ JS_ASSERT(CURRENT_THREAD_IS_ME(me));
+ if (NativeCompareAndSwap(&tl->owner, 0, me)) {
+ /*
+ * Got the lock with one compare-and-swap. Even so, someone else may
+ * have mutated obj so it now has its own scope and lock, which would
+ * require either a restart from the top of this routine, or a thin
+ * lock release followed by fat lock acquisition.
+ */
+ if (scope == OBJ_SCOPE(obj)) {
+ v = STOBJ_GET_SLOT(obj, slot);
+ if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
+ /* Assert that scope locks never revert to flyweight. */
+ JS_ASSERT(title->ownercx != cx);
+ LOGIT(scope, '1');
+ title->u.count = 1;
+ js_UnlockObj(cx, obj);
+ }
+ return v;
+ }
+ if (!NativeCompareAndSwap(&tl->owner, me, 0))
+ js_Dequeue(tl);
+ }
+ else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
+ return STOBJ_GET_SLOT(obj, slot);
+ }
+#endif
+
+ js_LockObj(cx, obj);
+ v = STOBJ_GET_SLOT(obj, slot);
+
+ /*
+ * Test whether cx took ownership of obj's scope during js_LockObj.
+ *
+ * This does not mean that a given scope reverted to flyweight from "thin"
+ * or "fat" -- it does mean that obj's map pointer changed due to another
+ * thread setting a property, requiring obj to cease sharing a prototype
+ * object's scope (whose lock was not flyweight, else we wouldn't be here
+ * in the first place!).
+ */
+ title = &OBJ_SCOPE(obj)->title;
+ if (title->ownercx != cx)
+ js_UnlockTitle(cx, title);
+ return v;
+}
+
+void
+js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
+{
+ JSTitle *title;
+ JSScope *scope;
+#ifndef NSPR_LOCK
+ JSThinLock *tl;
+ jsword me;
+#endif
+
+ /* Any string stored in a thread-safe object must be immutable. */
+ if (JSVAL_IS_STRING(v) &&
+ !js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) {
+ /* FIXME bug 363059: See comments in js_FinishSharingScope. */
+ v = JSVAL_NULL;
+ }
+
+ /*
+ * We handle non-native objects via JSObjectOps.setRequiredSlot, as above
+ * for the Get case.
+ */
+ if (!OBJ_IS_NATIVE(obj)) {
+ OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v);
+ return;
+ }
+
+ /*
+ * Native object locking is inlined here to optimize the single-threaded
+ * and contention-free multi-threaded cases.
+ */
+ scope = OBJ_SCOPE(obj);
+ title = &scope->title;
+ JS_ASSERT(title->ownercx != cx);
+ JS_ASSERT(slot < obj->map->freeslot);
+
+ /*
+ * Avoid locking if called from the GC. Also avoid locking an object
+ * owning a sealed scope. If neither of those special cases applies, try
+ * to claim scope's flyweight lock from whatever context may have had it in
+ * an earlier request.
+ */
+ if (CX_THREAD_IS_RUNNING_GC(cx) ||
+ (SCOPE_IS_SEALED(scope) && scope->object == obj) ||
+ (title->ownercx && ClaimTitle(title, cx))) {
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);
+ return;
+ }
+
+#ifndef NSPR_LOCK
+ tl = &title->lock;
+ me = CX_THINLOCK_ID(cx);
+ JS_ASSERT(CURRENT_THREAD_IS_ME(me));
+ if (NativeCompareAndSwap(&tl->owner, 0, me)) {
+ if (scope == OBJ_SCOPE(obj)) {
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);
+ if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
+ /* Assert that scope locks never revert to flyweight. */
+ JS_ASSERT(title->ownercx != cx);
+ LOGIT(scope, '1');
+ title->u.count = 1;
+ js_UnlockObj(cx, obj);
+ }
+ return;
+ }
+ if (!NativeCompareAndSwap(&tl->owner, me, 0))
+ js_Dequeue(tl);
+ }
+ else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);
+ return;
+ }
+#endif
+
+ js_LockObj(cx, obj);
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);
+
+ /*
+ * Same drill as above, in js_GetSlotThreadSafe.
+ */
+ title = &OBJ_SCOPE(obj)->title;
+ if (title->ownercx != cx)
+ js_UnlockTitle(cx, title);
+}
+
+#ifndef NSPR_LOCK
+
+static JSFatLock *
+NewFatlock()
+{
+ JSFatLock *fl = (JSFatLock *)malloc(sizeof(JSFatLock)); /* for now */
+ if (!fl) return NULL;
+ fl->susp = 0;
+ fl->next = NULL;
+ fl->prevp = NULL;
+ fl->slock = PR_NewLock();
+ fl->svar = PR_NewCondVar(fl->slock);
+ return fl;
+}
+
+static void
+DestroyFatlock(JSFatLock *fl)
+{
+ PR_DestroyLock(fl->slock);
+ PR_DestroyCondVar(fl->svar);
+ free(fl);
+}
+
+static JSFatLock *
+ListOfFatlocks(int listc)
+{
+ JSFatLock *m;
+ JSFatLock *m0;
+ int i;
+
+ JS_ASSERT(listc>0);
+ m0 = m = NewFatlock();
+ for (i=1; i<listc; i++) {
+ m->next = NewFatlock();
+ m = m->next;
+ }
+ return m0;
+}
+
+static void
+DeleteListOfFatlocks(JSFatLock *m)
+{
+ JSFatLock *m0;
+ for (; m; m=m0) {
+ m0 = m->next;
+ DestroyFatlock(m);
+ }
+}
+
+static JSFatLockTable *fl_list_table = NULL;
+static uint32 fl_list_table_len = 0;
+static uint32 fl_list_chunk_len = 0;
+
+static JSFatLock *
+GetFatlock(void *id)
+{
+ JSFatLock *m;
+
+ uint32 i = GLOBAL_LOCK_INDEX(id);
+ if (fl_list_table[i].free == NULL) {
+#ifdef DEBUG
+ if (fl_list_table[i].taken)
+ printf("Ran out of fat locks!\n");
+#endif
+ fl_list_table[i].free = ListOfFatlocks(fl_list_chunk_len);
+ }
+ m = fl_list_table[i].free;
+ fl_list_table[i].free = m->next;
+ m->susp = 0;
+ m->next = fl_list_table[i].taken;
+ m->prevp = &fl_list_table[i].taken;
+ if (fl_list_table[i].taken)
+ fl_list_table[i].taken->prevp = &m->next;
+ fl_list_table[i].taken = m;
+ return m;
+}
+
+static void
+PutFatlock(JSFatLock *m, void *id)
+{
+ uint32 i;
+ if (m == NULL)
+ return;
+
+ /* Unlink m from fl_list_table[i].taken. */
+ *m->prevp = m->next;
+ if (m->next)
+ m->next->prevp = m->prevp;
+
+ /* Insert m in fl_list_table[i].free. */
+ i = GLOBAL_LOCK_INDEX(id);
+ m->next = fl_list_table[i].free;
+ fl_list_table[i].free = m;
+}
+
+#endif /* !NSPR_LOCK */
+
+JSBool
+js_SetupLocks(int listc, int globc)
+{
+#ifndef NSPR_LOCK
+ uint32 i;
+
+ if (global_locks)
+ return JS_TRUE;
+#ifdef DEBUG
+ if (listc > 10000 || listc < 0) /* listc == fat lock list chunk length */
+ printf("Bad number %d in js_SetupLocks()!\n", listc);
+ if (globc > 100 || globc < 0) /* globc == number of global locks */
+ printf("Bad number %d in js_SetupLocks()!\n", listc);
+#endif
+ global_locks_log2 = JS_CeilingLog2(globc);
+ global_locks_mask = JS_BITMASK(global_locks_log2);
+ global_lock_count = JS_BIT(global_locks_log2);
+ global_locks = (PRLock **) malloc(global_lock_count * sizeof(PRLock*));
+ if (!global_locks)
+ return JS_FALSE;
+ for (i = 0; i < global_lock_count; i++) {
+ global_locks[i] = PR_NewLock();
+ if (!global_locks[i]) {
+ global_lock_count = i;
+ js_CleanupLocks();
+ return JS_FALSE;
+ }
+ }
+ fl_list_table = (JSFatLockTable *) malloc(i * sizeof(JSFatLockTable));
+ if (!fl_list_table) {
+ js_CleanupLocks();
+ return JS_FALSE;
+ }
+ fl_list_table_len = global_lock_count;
+ for (i = 0; i < global_lock_count; i++)
+ fl_list_table[i].free = fl_list_table[i].taken = NULL;
+ fl_list_chunk_len = listc;
+#endif /* !NSPR_LOCK */
+ return JS_TRUE;
+}
+
+void
+js_CleanupLocks()
+{
+#ifndef NSPR_LOCK
+ uint32 i;
+
+ if (global_locks) {
+ for (i = 0; i < global_lock_count; i++)
+ PR_DestroyLock(global_locks[i]);
+ free(global_locks);
+ global_locks = NULL;
+ global_lock_count = 1;
+ global_locks_log2 = 0;
+ global_locks_mask = 0;
+ }
+ if (fl_list_table) {
+ for (i = 0; i < fl_list_table_len; i++) {
+ DeleteListOfFatlocks(fl_list_table[i].free);
+ fl_list_table[i].free = NULL;
+ DeleteListOfFatlocks(fl_list_table[i].taken);
+ fl_list_table[i].taken = NULL;
+ }
+ free(fl_list_table);
+ fl_list_table = NULL;
+ fl_list_table_len = 0;
+ }
+#endif /* !NSPR_LOCK */
+}
+
+#ifdef NSPR_LOCK
+
+static JS_ALWAYS_INLINE void
+ThinLock(JSThinLock *tl, jsword me)
+{
+ JS_ACQUIRE_LOCK((JSLock *) tl->fat);
+ tl->owner = me;
+}
+
+static JS_ALWAYS_INLINE void
+ThinUnlock(JSThinLock *tl, jsword /*me*/)
+{
+ tl->owner = 0;
+ JS_RELEASE_LOCK((JSLock *) tl->fat);
+}
+
+#else
+
+/*
+ * Fast locking and unlocking is implemented by delaying the allocation of a
+ * system lock (fat lock) until contention. As long as a locking thread A
+ * runs uncontended, the lock is represented solely by storing A's identity in
+ * the object being locked.
+ *
+ * If another thread B tries to lock the object currently locked by A, B is
+ * enqueued into a fat lock structure (which might have to be allocated and
+ * pointed to by the object), and suspended using NSPR conditional variables
+ * (wait). A wait bit (Bacon bit) is set in the lock word of the object,
+ * signalling to A that when releasing the lock, B must be dequeued and
+ * notified.
+ *
+ * The basic operation of the locking primitives (js_Lock, js_Unlock,
+ * js_Enqueue, and js_Dequeue) is compare-and-swap. Hence, when locking into
+ * the word pointed at by p, compare-and-swap(p, 0, A) success implies that p
+ * is unlocked. Similarly, when unlocking p, if compare-and-swap(p, A, 0)
+ * succeeds this implies that p is uncontended (no one is waiting because the
+ * wait bit is not set).
+ *
+ * When dequeueing, the lock is released, and one of the threads suspended on
+ * the lock is notified. If other threads still are waiting, the wait bit is
+ * kept (in js_Enqueue), and if not, the fat lock is deallocated.
+ *
+ * The functions js_Enqueue, js_Dequeue, js_SuspendThread, and js_ResumeThread
+ * are serialized using a global lock. For scalability, a hashtable of global
+ * locks is used, which is indexed modulo the thin lock pointer.
+ */
+
+/*
+ * Invariants:
+ * (i) global lock is held
+ * (ii) fl->susp >= 0
+ */
+static int
+js_SuspendThread(JSThinLock *tl)
+{
+ JSFatLock *fl;
+ PRStatus stat;
+
+ if (tl->fat == NULL)
+ fl = tl->fat = GetFatlock(tl);
+ else
+ fl = tl->fat;
+ JS_ASSERT(fl->susp >= 0);
+ fl->susp++;
+ PR_Lock(fl->slock);
+ js_UnlockGlobal(tl);
+ stat = PR_WaitCondVar(fl->svar, PR_INTERVAL_NO_TIMEOUT);
+ JS_ASSERT(stat != PR_FAILURE);
+ PR_Unlock(fl->slock);
+ js_LockGlobal(tl);
+ fl->susp--;
+ if (fl->susp == 0) {
+ PutFatlock(fl, tl);
+ tl->fat = NULL;
+ }
+ return tl->fat == NULL;
+}
+
+/*
+ * (i) global lock is held
+ * (ii) fl->susp > 0
+ */
+static void
+js_ResumeThread(JSThinLock *tl)
+{
+ JSFatLock *fl = tl->fat;
+ PRStatus stat;
+
+ JS_ASSERT(fl != NULL);
+ JS_ASSERT(fl->susp > 0);
+ PR_Lock(fl->slock);
+ js_UnlockGlobal(tl);
+ stat = PR_NotifyCondVar(fl->svar);
+ JS_ASSERT(stat != PR_FAILURE);
+ PR_Unlock(fl->slock);
+}
+
+static void
+js_Enqueue(JSThinLock *tl, jsword me)
+{
+ jsword o, n;
+
+ js_LockGlobal(tl);
+ for (;;) {
+ o = ReadWord(tl->owner);
+ n = Thin_SetWait(o);
+ if (o != 0 && NativeCompareAndSwap(&tl->owner, o, n)) {
+ if (js_SuspendThread(tl))
+ me = Thin_RemoveWait(me);
+ else
+ me = Thin_SetWait(me);
+ }
+ else if (NativeCompareAndSwap(&tl->owner, 0, me)) {
+ js_UnlockGlobal(tl);
+ return;
+ }
+ }
+}
+
+static void
+js_Dequeue(JSThinLock *tl)
+{
+ jsword o;
+
+ js_LockGlobal(tl);
+ o = ReadWord(tl->owner);
+ JS_ASSERT(Thin_GetWait(o) != 0);
+ JS_ASSERT(tl->fat != NULL);
+ if (!NativeCompareAndSwap(&tl->owner, o, 0)) /* release it */
+ JS_ASSERT(0);
+ js_ResumeThread(tl);
+}
+
+static JS_ALWAYS_INLINE void
+ThinLock(JSThinLock *tl, jsword me)
+{
+ JS_ASSERT(CURRENT_THREAD_IS_ME(me));
+ if (NativeCompareAndSwap(&tl->owner, 0, me))
+ return;
+ if (Thin_RemoveWait(ReadWord(tl->owner)) != me)
+ js_Enqueue(tl, me);
+#ifdef DEBUG
+ else
+ JS_ASSERT(0);
+#endif
+}
+
+static JS_ALWAYS_INLINE void
+ThinUnlock(JSThinLock *tl, jsword me)
+{
+ JS_ASSERT(CURRENT_THREAD_IS_ME(me));
+
+ /*
+ * Since we can race with the NativeCompareAndSwap in js_Enqueue, we need
+ * to use a C_A_S here as well -- Arjan van de Ven 30/1/08
+ */
+ if (NativeCompareAndSwap(&tl->owner, me, 0))
+ return;
+
+ JS_ASSERT(Thin_GetWait(tl->owner));
+ if (Thin_RemoveWait(ReadWord(tl->owner)) == me)
+ js_Dequeue(tl);
+#ifdef DEBUG
+ else
+ JS_ASSERT(0); /* unbalanced unlock */
+#endif
+}
+
+#endif /* !NSPR_LOCK */
+
+void
+js_Lock(JSContext *cx, JSThinLock *tl)
+{
+ ThinLock(tl, CX_THINLOCK_ID(cx));
+}
+
+void
+js_Unlock(JSContext *cx, JSThinLock *tl)
+{
+ ThinUnlock(tl, CX_THINLOCK_ID(cx));
+}
+
+void
+js_LockRuntime(JSRuntime *rt)
+{
+ PR_Lock(rt->rtLock);
+#ifdef DEBUG
+ rt->rtLockOwner = js_CurrentThreadId();
+#endif
+}
+
+void
+js_UnlockRuntime(JSRuntime *rt)
+{
+#ifdef DEBUG
+ rt->rtLockOwner = 0;
+#endif
+ PR_Unlock(rt->rtLock);
+}
+
+void
+js_LockTitle(JSContext *cx, JSTitle *title)
+{
+ jsword me = CX_THINLOCK_ID(cx);
+
+ JS_ASSERT(CURRENT_THREAD_IS_ME(me));
+ JS_ASSERT(title->ownercx != cx);
+ if (CX_THREAD_IS_RUNNING_GC(cx))
+ return;
+ if (title->ownercx && ClaimTitle(title, cx))
+ return;
+
+ if (Thin_RemoveWait(ReadWord(title->lock.owner)) == me) {
+ JS_ASSERT(title->u.count > 0);
+ LOGIT(scope, '+');
+ title->u.count++;
+ } else {
+ ThinLock(&title->lock, me);
+ JS_ASSERT(title->u.count == 0);
+ LOGIT(scope, '1');
+ title->u.count = 1;
+ }
+}
+
+void
+js_UnlockTitle(JSContext *cx, JSTitle *title)
+{
+ jsword me = CX_THINLOCK_ID(cx);
+
+ /* We hope compilers use me instead of reloading cx->thread in the macro. */
+ if (CX_THREAD_IS_RUNNING_GC(cx))
+ return;
+ if (cx->lockedSealedTitle == title) {
+ cx->lockedSealedTitle = NULL;
+ return;
+ }
+
+ /*
+ * If title->ownercx is not null, it's likely that two contexts not using
+ * requests nested locks for title. The first context, cx here, claimed
+ * title; the second, title->ownercx here, re-claimed it because the first
+ * was not in a request, or was on the same thread. We don't want to keep
+ * track of such nesting, because it penalizes the common non-nested case.
+ * Instead of asserting here and silently coping, we simply re-claim title
+ * for cx and return.
+ *
+ * See http://bugzilla.mozilla.org/show_bug.cgi?id=229200 for a real world
+ * case where an asymmetric thread model (Mozilla's main thread is known
+ * to be the only thread that runs the GC) combined with multiple contexts
+ * per thread has led to such request-less nesting.
+ */
+ if (title->ownercx) {
+ JS_ASSERT(title->u.count == 0);
+ JS_ASSERT(title->lock.owner == 0);
+ title->ownercx = cx;
+ return;
+ }
+
+ JS_ASSERT(title->u.count > 0);
+ if (Thin_RemoveWait(ReadWord(title->lock.owner)) != me) {
+ JS_ASSERT(0); /* unbalanced unlock */
+ return;
+ }
+ LOGIT(scope, '-');
+ if (--title->u.count == 0)
+ ThinUnlock(&title->lock, me);
+}
+
+/*
+ * NB: oldtitle may be null if our caller is js_GetMutableScope and it just
+ * dropped the last reference to oldtitle.
+ */
+void
+js_TransferTitle(JSContext *cx, JSTitle *oldtitle, JSTitle *newtitle)
+{
+ JS_ASSERT(JS_IS_TITLE_LOCKED(cx, newtitle));
+
+ /*
+ * If the last reference to oldtitle went away, newtitle needs no lock
+ * state update.
+ */
+ if (!oldtitle)
+ return;
+ JS_ASSERT(JS_IS_TITLE_LOCKED(cx, oldtitle));
+
+ /*
+ * Special case in js_LockTitle and js_UnlockTitle for the GC calling
+ * code that locks, unlocks, or mutates. Nothing to do in these cases,
+ * because title and newtitle were "locked" by the GC thread, so neither
+ * was actually locked.
+ */
+ if (CX_THREAD_IS_RUNNING_GC(cx))
+ return;
+
+ /*
+ * Special case in js_LockObj and js_UnlockTitle for locking the sealed
+ * scope of an object that owns that scope (the prototype or mutated obj
+ * for which OBJ_SCOPE(obj)->object == obj), and unlocking it.
+ */
+ JS_ASSERT(cx->lockedSealedTitle != newtitle);
+ if (cx->lockedSealedTitle == oldtitle) {
+ JS_ASSERT(newtitle->ownercx == cx ||
+ (!newtitle->ownercx && newtitle->u.count == 1));
+ cx->lockedSealedTitle = NULL;
+ return;
+ }
+
+ /*
+ * If oldtitle is single-threaded, there's nothing to do.
+ */
+ if (oldtitle->ownercx) {
+ JS_ASSERT(oldtitle->ownercx == cx);
+ JS_ASSERT(newtitle->ownercx == cx ||
+ (!newtitle->ownercx && newtitle->u.count == 1));
+ return;
+ }
+
+ /*
+ * We transfer oldtitle->u.count only if newtitle is not single-threaded.
+ * Flow unwinds from here through some number of JS_UNLOCK_TITLE and/or
+ * JS_UNLOCK_OBJ macro calls, which will decrement newtitle->u.count only
+ * if they find newtitle->ownercx != cx.
+ */
+ if (newtitle->ownercx != cx) {
+ JS_ASSERT(!newtitle->ownercx);
+ newtitle->u.count = oldtitle->u.count;
+ }
+
+ /*
+ * Reset oldtitle's lock state so that it is completely unlocked.
+ */
+ LOGIT(oldscope, '0');
+ oldtitle->u.count = 0;
+ ThinUnlock(&oldtitle->lock, CX_THINLOCK_ID(cx));
+}
+
+void
+js_LockObj(JSContext *cx, JSObject *obj)
+{
+ JSScope *scope;
+ JSTitle *title;
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+
+ /*
+ * We must test whether the GC is calling and return without mutating any
+ * state, especially cx->lockedSealedScope. Note asymmetry with respect to
+ * js_UnlockObj, which is a thin-layer on top of js_UnlockTitle.
+ */
+ if (CX_THREAD_IS_RUNNING_GC(cx))
+ return;
+
+ for (;;) {
+ scope = OBJ_SCOPE(obj);
+ title = &scope->title;
+ if (SCOPE_IS_SEALED(scope) && scope->object == obj &&
+ !cx->lockedSealedTitle) {
+ cx->lockedSealedTitle = title;
+ return;
+ }
+
+ js_LockTitle(cx, title);
+
+ /* If obj still has this scope, we're done. */
+ if (scope == OBJ_SCOPE(obj))
+ return;
+
+ /* Lost a race with a mutator; retry with obj's new scope. */
+ js_UnlockTitle(cx, title);
+ }
+}
+
+void
+js_UnlockObj(JSContext *cx, JSObject *obj)
+{
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ js_UnlockTitle(cx, &OBJ_SCOPE(obj)->title);
+}
+
+void
+js_InitTitle(JSContext *cx, JSTitle *title)
+{
+#ifdef JS_THREADSAFE
+ title->ownercx = cx;
+ memset(&title->lock, 0, sizeof title->lock);
+
+ /*
+ * Set u.link = NULL, not u.count = 0, in case the target architecture's
+ * null pointer has a non-zero integer representation.
+ */
+ title->u.link = NULL;
+
+#ifdef JS_DEBUG_TITLE_LOCKS
+ title->file[0] = title->file[1] = title->file[2] = title->file[3] = NULL;
+ title->line[0] = title->line[1] = title->line[2] = title->line[3] = 0;
+#endif
+#endif
+}
+
+void
+js_FinishTitle(JSContext *cx, JSTitle *title)
+{
+#ifdef JS_THREADSAFE
+ /* Title must be single-threaded at this point, so set ownercx. */
+ JS_ASSERT(title->u.count == 0);
+ title->ownercx = cx;
+ js_FinishLock(&title->lock);
+#endif
+}
+
+#ifdef DEBUG
+
+JSBool
+js_IsRuntimeLocked(JSRuntime *rt)
+{
+ return js_CurrentThreadId() == rt->rtLockOwner;
+}
+
+JSBool
+js_IsObjLocked(JSContext *cx, JSObject *obj)
+{
+ JSScope *scope = OBJ_SCOPE(obj);
+
+ return MAP_IS_NATIVE(&scope->map) && js_IsTitleLocked(cx, &scope->title);
+}
+
+JSBool
+js_IsTitleLocked(JSContext *cx, JSTitle *title)
+{
+ /* Special case: the GC locking any object's title, see js_LockTitle. */
+ if (CX_THREAD_IS_RUNNING_GC(cx))
+ return JS_TRUE;
+
+ /* Special case: locked object owning a sealed scope, see js_LockObj. */
+ if (cx->lockedSealedTitle == title)
+ return JS_TRUE;
+
+ /*
+ * General case: the title is either exclusively owned (by cx), or it has
+ * a thin or fat lock to cope with shared (concurrent) ownership.
+ */
+ if (title->ownercx) {
+ JS_ASSERT(title->ownercx == cx || title->ownercx->thread == cx->thread);
+ return JS_TRUE;
+ }
+ return js_CurrentThreadId() ==
+ ((JSThread *)Thin_RemoveWait(ReadWord(title->lock.owner)))->id;
+}
+
+#ifdef JS_DEBUG_TITLE_LOCKS
+void
+js_SetScopeInfo(JSScope *scope, const char *file, int line)
+{
+ JSTitle *title = &scope->title;
+ if (!title->ownercx) {
+ jsrefcount count = title->u.count;
+ JS_ASSERT_IF(!SCOPE_IS_SEALED(scope), count > 0);
+ JS_ASSERT(count <= 4);
+ title->file[count - 1] = file;
+ title->line[count - 1] = line;
+ }
+}
+#endif /* JS_DEBUG_TITLE_LOCKS */
+#endif /* DEBUG */
+#endif /* JS_THREADSAFE */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslock.h b/tools/node_modules/expresso/deps/jscoverage/js/jslock.h
new file mode 100644
index 0000000..548e082
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslock.h
@@ -0,0 +1,311 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef jslock_h__
+#define jslock_h__
+
+#include "jstypes.h"
+#include "jsprvtd.h" /* for JSScope, etc. */
+#include "jspubtd.h" /* for JSRuntime, etc. */
+
+#ifdef JS_THREADSAFE
+# include "pratom.h"
+# include "prlock.h"
+# include "prcvar.h"
+# include "prthread.h"
+#endif
+
+JS_BEGIN_EXTERN_C
+
+#ifdef JS_THREADSAFE
+
+#if (defined(_WIN32) && defined(_M_IX86)) || \
+ (defined(__GNUC__) && defined(__i386__)) || \
+ (defined(__GNUC__) && defined(__x86_64__)) || \
+ (defined(SOLARIS) && defined(sparc) && defined(ULTRA_SPARC)) || \
+ defined(AIX) || \
+ defined(USE_ARM_KUSER)
+# define JS_HAS_NATIVE_COMPARE_AND_SWAP 1
+#else
+# define JS_HAS_NATIVE_COMPARE_AND_SWAP 0
+#endif
+
+#if defined(JS_USE_ONLY_NSPR_LOCKS) || !JS_HAS_NATIVE_COMPARE_AND_SWAP
+# define NSPR_LOCK 1
+#else
+# undef NSPR_LOCK
+#endif
+
+#define Thin_GetWait(W) ((jsword)(W) & 0x1)
+#define Thin_SetWait(W) ((jsword)(W) | 0x1)
+#define Thin_RemoveWait(W) ((jsword)(W) & ~0x1)
+
+typedef struct JSFatLock JSFatLock;
+
+typedef struct JSThinLock {
+ jsword owner;
+ JSFatLock *fat;
+} JSThinLock;
+
+#define CX_THINLOCK_ID(cx) ((jsword)(cx)->thread)
+#define CURRENT_THREAD_IS_ME(me) (((JSThread *)me)->id == js_CurrentThreadId())
+
+typedef PRLock JSLock;
+
+typedef struct JSTitle JSTitle;
+
+struct JSTitle {
+ JSContext *ownercx; /* creating context, NULL if shared */
+ JSThinLock lock; /* binary semaphore protecting title */
+ union { /* union lockful and lock-free state: */
+ jsrefcount count; /* lock entry count for reentrancy */
+ JSTitle *link; /* next link in rt->titleSharingTodo */
+ } u;
+#ifdef JS_DEBUG_TITLE_LOCKS
+ const char *file[4]; /* file where lock was (re-)taken */
+ unsigned int line[4]; /* line where lock was (re-)taken */
+#endif
+};
+
+/*
+ * Title structures must be immediately preceded by JSObjectMap structures for
+ * maps that use titles for threadsafety. This is enforced by assertion in
+ * jsscope.h; see bug 408416 for future remedies to this somewhat fragile
+ * architecture.
+ */
+
+#define TITLE_TO_MAP(title) \
+ ((JSObjectMap *)((char *)(title) - sizeof(JSObjectMap)))
+
+/*
+ * Atomic increment and decrement for a reference counter, given jsrefcount *p.
+ * NB: jsrefcount is int32, aka PRInt32, so that pratom.h functions work.
+ */
+#define JS_ATOMIC_INCREMENT(p) PR_AtomicIncrement((PRInt32 *)(p))
+#define JS_ATOMIC_DECREMENT(p) PR_AtomicDecrement((PRInt32 *)(p))
+#define JS_ATOMIC_ADD(p,v) PR_AtomicAdd((PRInt32 *)(p), (PRInt32)(v))
+
+#define js_CurrentThreadId() (jsword)PR_GetCurrentThread()
+#define JS_NEW_LOCK() PR_NewLock()
+#define JS_DESTROY_LOCK(l) PR_DestroyLock(l)
+#define JS_ACQUIRE_LOCK(l) PR_Lock(l)
+#define JS_RELEASE_LOCK(l) PR_Unlock(l)
+
+#define JS_NEW_CONDVAR(l) PR_NewCondVar(l)
+#define JS_DESTROY_CONDVAR(cv) PR_DestroyCondVar(cv)
+#define JS_WAIT_CONDVAR(cv,to) PR_WaitCondVar(cv,to)
+#define JS_NO_TIMEOUT PR_INTERVAL_NO_TIMEOUT
+#define JS_NOTIFY_CONDVAR(cv) PR_NotifyCondVar(cv)
+#define JS_NOTIFY_ALL_CONDVAR(cv) PR_NotifyAllCondVar(cv)
+
+#ifdef JS_DEBUG_TITLE_LOCKS
+
+#define SET_OBJ_INFO(obj_, file_, line_) \
+ SET_SCOPE_INFO(OBJ_SCOPE(obj_), file_, line_)
+
+#define SET_SCOPE_INFO(scope_, file_, line_) \
+ js_SetScopeInfo(scope_, file_, line_)
+
+#endif
+
+#define JS_LOCK(cx, tl) js_Lock(cx, tl)
+#define JS_UNLOCK(cx, tl) js_Unlock(cx, tl)
+
+#define JS_LOCK_RUNTIME(rt) js_LockRuntime(rt)
+#define JS_UNLOCK_RUNTIME(rt) js_UnlockRuntime(rt)
+
+/*
+ * NB: The JS_LOCK_OBJ and JS_UNLOCK_OBJ macros work *only* on native objects
+ * (objects for which OBJ_IS_NATIVE returns true). All uses of these macros in
+ * the engine are predicated on OBJ_IS_NATIVE or equivalent checks. These uses
+ * are for optimizations above the JSObjectOps layer, under which object locks
+ * normally hide.
+ */
+#define JS_LOCK_OBJ(cx,obj) ((OBJ_SCOPE(obj)->title.ownercx == (cx)) \
+ ? (void)0 \
+ : (js_LockObj(cx, obj), \
+ SET_OBJ_INFO(obj,__FILE__,__LINE__)))
+#define JS_UNLOCK_OBJ(cx,obj) ((OBJ_SCOPE(obj)->title.ownercx == (cx)) \
+ ? (void)0 : js_UnlockObj(cx, obj))
+
+#define JS_LOCK_TITLE(cx,title) \
+ ((title)->ownercx == (cx) ? (void)0 \
+ : (js_LockTitle(cx, (title)), \
+ SET_TITLE_INFO(title,__FILE__,__LINE__)))
+
+#define JS_UNLOCK_TITLE(cx,title) ((title)->ownercx == (cx) ? (void)0 \
+ : js_UnlockTitle(cx, title))
+
+#define JS_LOCK_SCOPE(cx,scope) JS_LOCK_TITLE(cx,&(scope)->title)
+#define JS_UNLOCK_SCOPE(cx,scope) JS_UNLOCK_TITLE(cx,&(scope)->title)
+
+#define JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope) \
+ js_TransferTitle(cx, &scope->title, &newscope->title)
+
+
+extern void js_Lock(JSContext *cx, JSThinLock *tl);
+extern void js_Unlock(JSContext *cx, JSThinLock *tl);
+extern void js_LockRuntime(JSRuntime *rt);
+extern void js_UnlockRuntime(JSRuntime *rt);
+extern void js_LockObj(JSContext *cx, JSObject *obj);
+extern void js_UnlockObj(JSContext *cx, JSObject *obj);
+extern void js_InitTitle(JSContext *cx, JSTitle *title);
+extern void js_FinishTitle(JSContext *cx, JSTitle *title);
+extern void js_LockTitle(JSContext *cx, JSTitle *title);
+extern void js_UnlockTitle(JSContext *cx, JSTitle *title);
+extern int js_SetupLocks(int,int);
+extern void js_CleanupLocks();
+extern void js_TransferTitle(JSContext *, JSTitle *, JSTitle *);
+extern JS_FRIEND_API(jsval)
+js_GetSlotThreadSafe(JSContext *, JSObject *, uint32);
+extern void js_SetSlotThreadSafe(JSContext *, JSObject *, uint32, jsval);
+extern void js_InitLock(JSThinLock *);
+extern void js_FinishLock(JSThinLock *);
+extern void js_FinishSharingTitle(JSContext *cx, JSTitle *title);
+
+#ifdef DEBUG
+
+#define JS_IS_RUNTIME_LOCKED(rt) js_IsRuntimeLocked(rt)
+#define JS_IS_OBJ_LOCKED(cx,obj) js_IsObjLocked(cx,obj)
+#define JS_IS_TITLE_LOCKED(cx,title) js_IsTitleLocked(cx,title)
+
+extern JSBool js_IsRuntimeLocked(JSRuntime *rt);
+extern JSBool js_IsObjLocked(JSContext *cx, JSObject *obj);
+extern JSBool js_IsTitleLocked(JSContext *cx, JSTitle *title);
+#ifdef JS_DEBUG_TITLE_LOCKS
+extern void js_SetScopeInfo(JSScope *scope, const char *file, int line);
+#endif
+
+#else
+
+#define JS_IS_RUNTIME_LOCKED(rt) 0
+#define JS_IS_OBJ_LOCKED(cx,obj) 1
+#define JS_IS_TITLE_LOCKED(cx,title) 1
+
+#endif /* DEBUG */
+
+#define JS_LOCK_OBJ_VOID(cx, obj, e) \
+ JS_BEGIN_MACRO \
+ JS_LOCK_OBJ(cx, obj); \
+ e; \
+ JS_UNLOCK_OBJ(cx, obj); \
+ JS_END_MACRO
+
+#define JS_LOCK_VOID(cx, e) \
+ JS_BEGIN_MACRO \
+ JSRuntime *_rt = (cx)->runtime; \
+ JS_LOCK_RUNTIME_VOID(_rt, e); \
+ JS_END_MACRO
+
+#else /* !JS_THREADSAFE */
+
+#define JS_ATOMIC_INCREMENT(p) (++*(p))
+#define JS_ATOMIC_DECREMENT(p) (--*(p))
+#define JS_ATOMIC_ADD(p,v) (*(p) += (v))
+
+#define JS_CurrentThreadId() 0
+#define JS_NEW_LOCK() NULL
+#define JS_DESTROY_LOCK(l) ((void)0)
+#define JS_ACQUIRE_LOCK(l) ((void)0)
+#define JS_RELEASE_LOCK(l) ((void)0)
+#define JS_LOCK(cx, tl) ((void)0)
+#define JS_UNLOCK(cx, tl) ((void)0)
+
+#define JS_NEW_CONDVAR(l) NULL
+#define JS_DESTROY_CONDVAR(cv) ((void)0)
+#define JS_WAIT_CONDVAR(cv,to) ((void)0)
+#define JS_NOTIFY_CONDVAR(cv) ((void)0)
+#define JS_NOTIFY_ALL_CONDVAR(cv) ((void)0)
+
+#define JS_LOCK_RUNTIME(rt) ((void)0)
+#define JS_UNLOCK_RUNTIME(rt) ((void)0)
+#define JS_LOCK_OBJ(cx,obj) ((void)0)
+#define JS_UNLOCK_OBJ(cx,obj) ((void)0)
+#define JS_LOCK_OBJ_VOID(cx,obj,e) (e)
+#define JS_LOCK_SCOPE(cx,scope) ((void)0)
+#define JS_UNLOCK_SCOPE(cx,scope) ((void)0)
+#define JS_TRANSFER_SCOPE_LOCK(c,o,n) ((void)0)
+
+#define JS_IS_RUNTIME_LOCKED(rt) 1
+#define JS_IS_OBJ_LOCKED(cx,obj) 1
+#define JS_IS_TITLE_LOCKED(cx,title) 1
+#define JS_LOCK_VOID(cx, e) JS_LOCK_RUNTIME_VOID((cx)->runtime, e)
+
+#endif /* !JS_THREADSAFE */
+
+#define JS_LOCK_RUNTIME_VOID(rt,e) \
+ JS_BEGIN_MACRO \
+ JS_LOCK_RUNTIME(rt); \
+ e; \
+ JS_UNLOCK_RUNTIME(rt); \
+ JS_END_MACRO
+
+#define JS_LOCK_GC(rt) JS_ACQUIRE_LOCK((rt)->gcLock)
+#define JS_UNLOCK_GC(rt) JS_RELEASE_LOCK((rt)->gcLock)
+#define JS_LOCK_GC_VOID(rt,e) (JS_LOCK_GC(rt), (e), JS_UNLOCK_GC(rt))
+#define JS_AWAIT_GC_DONE(rt) JS_WAIT_CONDVAR((rt)->gcDone, JS_NO_TIMEOUT)
+#define JS_NOTIFY_GC_DONE(rt) JS_NOTIFY_ALL_CONDVAR((rt)->gcDone)
+#define JS_AWAIT_REQUEST_DONE(rt) JS_WAIT_CONDVAR((rt)->requestDone, \
+ JS_NO_TIMEOUT)
+#define JS_NOTIFY_REQUEST_DONE(rt) JS_NOTIFY_CONDVAR((rt)->requestDone)
+
+#ifndef SET_OBJ_INFO
+#define SET_OBJ_INFO(obj,f,l) ((void)0)
+#endif
+#ifndef SET_TITLE_INFO
+#define SET_TITLE_INFO(title,f,l) ((void)0)
+#endif
+
+#ifdef JS_THREADSAFE
+
+extern JSBool
+js_CompareAndSwap(jsword *w, jsword ov, jsword nv);
+
+#else
+
+static inline JSBool
+js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ return (*w == ov) ? *w = nv, JS_TRUE : JS_FALSE;
+}
+
+#endif
+
+JS_END_EXTERN_C
+
+#endif /* jslock_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslocko.asm b/tools/node_modules/expresso/deps/jscoverage/js/jslocko.asm
new file mode 100644
index 0000000..95353ba
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslocko.asm
@@ -0,0 +1,60 @@
+; -*- Mode: asm; tab-width: 8; c-basic-offset: 4 -*-
+
+; ***** BEGIN LICENSE BLOCK *****
+; Version: MPL 1.1/GPL 2.0/LGPL 2.1
+;
+; The contents of this file are subject to the Mozilla Public License Version
+; 1.1 (the "License"); you may not use this file except in compliance with
+; the License. You may obtain a copy of the License at
+; http://www.mozilla.org/MPL/
+;
+; Software distributed under the License is distributed on an "AS IS" basis,
+; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+; for the specific language governing rights and limitations under the
+; License.
+;
+; The Original Code is an OS/2 implementation of js_CompareAndSwap in assembly.
+;
+; The Initial Developer of the Original Code is
+; IBM Corporation.
+; Portions created by the Initial Developer are Copyright (C) 2001
+; the Initial Developer. All Rights Reserved.
+;
+; Contributor(s):
+;
+; Alternatively, the contents of this file may be used under the terms of
+; either the GNU General Public License Version 2 or later (the "GPL"), or
+; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+; in which case the provisions of the GPL or the LGPL are applicable instead
+; of those above. If you wish to allow use of your version of this file only
+; under the terms of either the GPL or the LGPL, and not to allow others to
+; use your version of this file under the terms of the MPL, indicate your
+; decision by deleting the provisions above and replace them with the notice
+; and other provisions required by the GPL or the LGPL. If you do not delete
+; the provisions above, a recipient may use your version of this file under
+; the terms of any one of the MPL, the GPL or the LGPL.
+;
+; ***** END LICENSE BLOCK *****
+
+ .486P
+ .MODEL FLAT, OPTLINK
+ .STACK
+
+ .CODE
+
+;;;---------------------------------------------------------------------
+;;; int _Optlink js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
+;;;---------------------------------------------------------------------
+js_CompareAndSwap PROC OPTLINK EXPORT
+ push ebx
+ mov ebx, eax
+ mov eax, edx
+ mov edx, ebx
+ lock cmpxchg [ebx], ecx
+ sete al
+ and eax, 1h
+ pop ebx
+ ret
+js_CompareAndSwap endp
+
+ END
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslog2.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jslog2.cpp
new file mode 100644
index 0000000..84f4f51
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslog2.cpp
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h"
+#include "jsbit.h"
+#include "jsutil.h"
+
+/*
+** Compute the log of the least power of 2 greater than or equal to n
+*/
+JS_PUBLIC_API(JSIntn) JS_CeilingLog2(JSUint32 n)
+{
+ JSIntn log2;
+
+ JS_CEILING_LOG2(log2, n);
+ return log2;
+}
+
+/*
+** Compute the log of the greatest power of 2 less than or equal to n.
+** This really just finds the highest set bit in the word.
+*/
+JS_PUBLIC_API(JSIntn) JS_FloorLog2(JSUint32 n)
+{
+ JSIntn log2;
+
+ JS_FLOOR_LOG2(log2, n);
+ return log2;
+}
+
+/*
+ * js_FloorLog2wImpl has to be defined only for 64-bit non-GCC case.
+ */
+#if !defined(JS_HAS_BUILTIN_BITSCAN64) && JS_BYTES_PER_WORD == 8
+
+JSUword
+js_FloorLog2wImpl(JSUword n)
+{
+ JSUword log2, m;
+
+ JS_ASSERT(n != 0);
+
+ log2 = 0;
+ m = n >> 32;
+ if (m != 0) { n = m; log2 = 32; }
+ m = n >> 16;
+ if (m != 0) { n = m; log2 |= 16; }
+ m = n >> 8;
+ if (m != 0) { n = m; log2 |= 8; }
+ m = n >> 4;
+ if (m != 0) { n = m; log2 |= 4; }
+ m = n >> 2;
+ if (m != 0) { n = m; log2 |= 2; }
+ log2 |= (n >> 1);
+
+ return log2;
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslong.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jslong.cpp
new file mode 100644
index 0000000..71dd06d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslong.cpp
@@ -0,0 +1,264 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h"
+#include "jstypes.h"
+#include "jslong.h"
+
+#ifndef JS_HAVE_LONG_LONG
+/*
+** Divide 64-bit a by 32-bit b, which must be normalized so its high bit is 1.
+*/
+static void norm_udivmod32(JSUint32 *qp, JSUint32 *rp, JSUint64 a, JSUint32 b)
+{
+ JSUint32 d1, d0, q1, q0;
+ JSUint32 r1, r0, m;
+
+ d1 = jshi16(b);
+ d0 = jslo16(b);
+ r1 = a.hi % d1;
+ q1 = a.hi / d1;
+ m = q1 * d0;
+ r1 = (r1 << 16) | jshi16(a.lo);
+ if (r1 < m) {
+ q1--, r1 += b;
+ if (r1 >= b /* i.e., we didn't get a carry when adding to r1 */
+ && r1 < m) {
+ q1--, r1 += b;
+ }
+ }
+ r1 -= m;
+ r0 = r1 % d1;
+ q0 = r1 / d1;
+ m = q0 * d0;
+ r0 = (r0 << 16) | jslo16(a.lo);
+ if (r0 < m) {
+ q0--, r0 += b;
+ if (r0 >= b
+ && r0 < m) {
+ q0--, r0 += b;
+ }
+ }
+ *qp = (q1 << 16) | q0;
+ *rp = r0 - m;
+}
+
+static JSUint32 CountLeadingZeros(JSUint32 a)
+{
+ JSUint32 t;
+ JSUint32 r = 32;
+
+ if ((t = a >> 16) != 0)
+ r -= 16, a = t;
+ if ((t = a >> 8) != 0)
+ r -= 8, a = t;
+ if ((t = a >> 4) != 0)
+ r -= 4, a = t;
+ if ((t = a >> 2) != 0)
+ r -= 2, a = t;
+ if ((t = a >> 1) != 0)
+ r -= 1, a = t;
+ if (a & 1)
+ r--;
+ return r;
+}
+
+JS_PUBLIC_API(void) jsll_udivmod(JSUint64 *qp, JSUint64 *rp, JSUint64 a, JSUint64 b)
+{
+ JSUint32 n0, n1, n2;
+ JSUint32 q0, q1;
+ JSUint32 rsh, lsh;
+
+ n0 = a.lo;
+ n1 = a.hi;
+
+ if (b.hi == 0) {
+ if (b.lo > n1) {
+ /* (0 q0) = (n1 n0) / (0 D0) */
+
+ lsh = CountLeadingZeros(b.lo);
+
+ if (lsh) {
+ /*
+ * Normalize, i.e. make the most significant bit of the
+ * denominator be set.
+ */
+ b.lo = b.lo << lsh;
+ n1 = (n1 << lsh) | (n0 >> (32 - lsh));
+ n0 = n0 << lsh;
+ }
+
+ a.lo = n0, a.hi = n1;
+ norm_udivmod32(&q0, &n0, a, b.lo);
+ q1 = 0;
+
+ /* remainder is in n0 >> lsh */
+ } else {
+ /* (q1 q0) = (n1 n0) / (0 d0) */
+
+ if (b.lo == 0) /* user wants to divide by zero! */
+ b.lo = 1 / b.lo; /* so go ahead and crash */
+
+ lsh = CountLeadingZeros(b.lo);
+
+ if (lsh == 0) {
+ /*
+ * From (n1 >= b.lo)
+ * && (the most significant bit of b.lo is set),
+ * conclude that
+ * (the most significant bit of n1 is set)
+ * && (the leading quotient digit q1 = 1).
+ *
+ * This special case is necessary, not an optimization
+ * (Shifts counts of 32 are undefined).
+ */
+ n1 -= b.lo;
+ q1 = 1;
+ } else {
+ /*
+ * Normalize.
+ */
+ rsh = 32 - lsh;
+
+ b.lo = b.lo << lsh;
+ n2 = n1 >> rsh;
+ n1 = (n1 << lsh) | (n0 >> rsh);
+ n0 = n0 << lsh;
+
+ a.lo = n1, a.hi = n2;
+ norm_udivmod32(&q1, &n1, a, b.lo);
+ }
+
+ /* n1 != b.lo... */
+
+ a.lo = n0, a.hi = n1;
+ norm_udivmod32(&q0, &n0, a, b.lo);
+
+ /* remainder in n0 >> lsh */
+ }
+
+ if (rp) {
+ rp->lo = n0 >> lsh;
+ rp->hi = 0;
+ }
+ } else {
+ if (b.hi > n1) {
+ /* (0 0) = (n1 n0) / (D1 d0) */
+
+ q0 = 0;
+ q1 = 0;
+
+ /* remainder in (n1 n0) */
+ if (rp) {
+ rp->lo = n0;
+ rp->hi = n1;
+ }
+ } else {
+ /* (0 q0) = (n1 n0) / (d1 d0) */
+
+ lsh = CountLeadingZeros(b.hi);
+ if (lsh == 0) {
+ /*
+ * From (n1 >= b.hi)
+ * && (the most significant bit of b.hi is set),
+ * conclude that
+ * (the most significant bit of n1 is set)
+ * && (the quotient digit q0 = 0 or 1).
+ *
+ * This special case is necessary, not an optimization.
+ */
+
+ /*
+ * The condition on the next line takes advantage of that
+ * n1 >= b.hi (true due to control flow).
+ */
+ if (n1 > b.hi || n0 >= b.lo) {
+ q0 = 1;
+ a.lo = n0, a.hi = n1;
+ JSLL_SUB(a, a, b);
+ } else {
+ q0 = 0;
+ }
+ q1 = 0;
+
+ if (rp) {
+ rp->lo = n0;
+ rp->hi = n1;
+ }
+ } else {
+ JSInt64 m;
+
+ /*
+ * Normalize.
+ */
+ rsh = 32 - lsh;
+
+ b.hi = (b.hi << lsh) | (b.lo >> rsh);
+ b.lo = b.lo << lsh;
+ n2 = n1 >> rsh;
+ n1 = (n1 << lsh) | (n0 >> rsh);
+ n0 = n0 << lsh;
+
+ a.lo = n1, a.hi = n2;
+ norm_udivmod32(&q0, &n1, a, b.hi);
+ JSLL_MUL32(m, q0, b.lo);
+
+ if ((m.hi > n1) || ((m.hi == n1) && (m.lo > n0))) {
+ q0--;
+ JSLL_SUB(m, m, b);
+ }
+
+ q1 = 0;
+
+ /* Remainder is ((n1 n0) - (m1 m0)) >> lsh */
+ if (rp) {
+ a.lo = n0, a.hi = n1;
+ JSLL_SUB(a, a, m);
+ rp->lo = (a.hi << rsh) | (a.lo >> lsh);
+ rp->hi = a.hi >> lsh;
+ }
+ }
+ }
+ }
+
+ if (qp) {
+ qp->lo = q0;
+ qp->hi = q1;
+ }
+}
+#endif /* !JS_HAVE_LONG_LONG */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslong.h b/tools/node_modules/expresso/deps/jscoverage/js/jslong.h
new file mode 100644
index 0000000..e5bd4d0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslong.h
@@ -0,0 +1,412 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+** File: jslong.h
+** Description: Portable access to 64 bit numerics
+**
+** Long-long (64-bit signed integer type) support. Some C compilers
+** don't support 64 bit integers yet, so we use these macros to
+** support both machines that do and don't.
+**/
+#ifndef jslong_h___
+#define jslong_h___
+
+#include "jstypes.h"
+
+JS_BEGIN_EXTERN_C
+
+#ifdef JS_HAVE_LONG_LONG
+
+#if JS_BYTES_PER_LONG == 8
+#define JSLL_INIT(hi, lo) ((hi ## L << 32) + lo ## L)
+#elif (defined(WIN32) || defined(WIN16)) && !defined(__GNUC__)
+#define JSLL_INIT(hi, lo) ((hi ## i64 << 32) + lo ## i64)
+#else
+#define JSLL_INIT(hi, lo) ((hi ## LL << 32) + lo ## LL)
+#endif
+
+/***********************************************************************
+** MACROS: JSLL_*
+** DESCRIPTION:
+** The following macros define portable access to the 64 bit
+** math facilities.
+**
+***********************************************************************/
+
+/***********************************************************************
+** MACROS: JSLL_<relational operators>
+**
+** JSLL_IS_ZERO Test for zero
+** JSLL_EQ Test for equality
+** JSLL_NE Test for inequality
+** JSLL_GE_ZERO Test for zero or positive
+** JSLL_CMP Compare two values
+***********************************************************************/
+#define JSLL_IS_ZERO(a) ((a) == 0)
+#define JSLL_EQ(a, b) ((a) == (b))
+#define JSLL_NE(a, b) ((a) != (b))
+#define JSLL_GE_ZERO(a) ((a) >= 0)
+#define JSLL_CMP(a, op, b) ((JSInt64)(a) op (JSInt64)(b))
+#define JSLL_UCMP(a, op, b) ((JSUint64)(a) op (JSUint64)(b))
+
+/***********************************************************************
+** MACROS: JSLL_<logical operators>
+**
+** JSLL_AND Logical and
+** JSLL_OR Logical or
+** JSLL_XOR Logical exclusion
+** JSLL_OR2 A disgusting deviation
+** JSLL_NOT Negation (one's compliment)
+***********************************************************************/
+#define JSLL_AND(r, a, b) ((r) = (a) & (b))
+#define JSLL_OR(r, a, b) ((r) = (a) | (b))
+#define JSLL_XOR(r, a, b) ((r) = (a) ^ (b))
+#define JSLL_OR2(r, a) ((r) = (r) | (a))
+#define JSLL_NOT(r, a) ((r) = ~(a))
+
+/***********************************************************************
+** MACROS: JSLL_<mathematical operators>
+**
+** JSLL_NEG Negation (two's compliment)
+** JSLL_ADD Summation (two's compliment)
+** JSLL_SUB Difference (two's compliment)
+***********************************************************************/
+#define JSLL_NEG(r, a) ((r) = -(a))
+#define JSLL_ADD(r, a, b) ((r) = (a) + (b))
+#define JSLL_SUB(r, a, b) ((r) = (a) - (b))
+
+/***********************************************************************
+** MACROS: JSLL_<mathematical operators>
+**
+** JSLL_MUL Product (two's compliment)
+** JSLL_DIV Quotient (two's compliment)
+** JSLL_MOD Modulus (two's compliment)
+***********************************************************************/
+#define JSLL_MUL(r, a, b) ((r) = (a) * (b))
+#define JSLL_DIV(r, a, b) ((r) = (a) / (b))
+#define JSLL_MOD(r, a, b) ((r) = (a) % (b))
+
+/***********************************************************************
+** MACROS: JSLL_<shifting operators>
+**
+** JSLL_SHL Shift left [0..64] bits
+** JSLL_SHR Shift right [0..64] bits with sign extension
+** JSLL_USHR Unsigned shift right [0..64] bits
+** JSLL_ISHL Signed shift left [0..64] bits
+***********************************************************************/
+#define JSLL_SHL(r, a, b) ((r) = (JSInt64)(a) << (b))
+#define JSLL_SHR(r, a, b) ((r) = (JSInt64)(a) >> (b))
+#define JSLL_USHR(r, a, b) ((r) = (JSUint64)(a) >> (b))
+#define JSLL_ISHL(r, a, b) ((r) = (JSInt64)(a) << (b))
+
+/***********************************************************************
+** MACROS: JSLL_<conversion operators>
+**
+** JSLL_L2I Convert to signed 32 bit
+** JSLL_L2UI Convert to unsigned 32 bit
+** JSLL_L2F Convert to floating point
+** JSLL_L2D Convert to floating point
+** JSLL_I2L Convert signed to 64 bit
+** JSLL_UI2L Convert unsigned to 64 bit
+** JSLL_F2L Convert float to 64 bit
+** JSLL_D2L Convert float to 64 bit
+***********************************************************************/
+#define JSLL_L2I(i, l) ((i) = (JSInt32)(l))
+#define JSLL_L2UI(ui, l) ((ui) = (JSUint32)(l))
+#define JSLL_L2F(f, l) ((f) = (JSFloat64)(l))
+#define JSLL_L2D(d, l) ((d) = (JSFloat64)(l))
+
+#define JSLL_I2L(l, i) ((l) = (JSInt64)(i))
+#define JSLL_UI2L(l, ui) ((l) = (JSInt64)(ui))
+#define JSLL_F2L(l, f) ((l) = (JSInt64)(f))
+#define JSLL_D2L(l, d) ((l) = (JSInt64)(d))
+
+/***********************************************************************
+** MACROS: JSLL_UDIVMOD
+** DESCRIPTION:
+** Produce both a quotient and a remainder given an unsigned
+** INPUTS: JSUint64 a: The dividend of the operation
+** JSUint64 b: The quotient of the operation
+** OUTPUTS: JSUint64 *qp: pointer to quotient
+** JSUint64 *rp: pointer to remainder
+***********************************************************************/
+#define JSLL_UDIVMOD(qp, rp, a, b) \
+ (*(qp) = ((JSUint64)(a) / (b)), \
+ *(rp) = ((JSUint64)(a) % (b)))
+
+#else /* !JS_HAVE_LONG_LONG */
+
+#ifdef IS_LITTLE_ENDIAN
+#define JSLL_INIT(hi, lo) {JS_INT32(lo), JS_INT32(hi)}
+#else
+#define JSLL_INIT(hi, lo) {JS_INT32(hi), JS_INT32(lo)}
+#endif
+
+#define JSLL_IS_ZERO(a) (((a).hi == 0) && ((a).lo == 0))
+#define JSLL_EQ(a, b) (((a).hi == (b).hi) && ((a).lo == (b).lo))
+#define JSLL_NE(a, b) (((a).hi != (b).hi) || ((a).lo != (b).lo))
+#define JSLL_GE_ZERO(a) (((a).hi >> 31) == 0)
+
+#ifdef DEBUG
+#define JSLL_CMP(a, op, b) (JS_ASSERT((#op)[1] != '='), JSLL_REAL_CMP(a, op, b))
+#define JSLL_UCMP(a, op, b) (JS_ASSERT((#op)[1] != '='), JSLL_REAL_UCMP(a, op, b))
+#else
+#define JSLL_CMP(a, op, b) JSLL_REAL_CMP(a, op, b)
+#define JSLL_UCMP(a, op, b) JSLL_REAL_UCMP(a, op, b)
+#endif
+
+#define JSLL_REAL_CMP(a,op,b) (((JSInt32)(a).hi op (JSInt32)(b).hi) || \
+ (((a).hi == (b).hi) && ((a).lo op (b).lo)))
+#define JSLL_REAL_UCMP(a,op,b) (((a).hi op (b).hi) || \
+ (((a).hi == (b).hi) && ((a).lo op (b).lo)))
+
+#define JSLL_AND(r, a, b) ((r).lo = (a).lo & (b).lo, \
+ (r).hi = (a).hi & (b).hi)
+#define JSLL_OR(r, a, b) ((r).lo = (a).lo | (b).lo, \
+ (r).hi = (a).hi | (b).hi)
+#define JSLL_XOR(r, a, b) ((r).lo = (a).lo ^ (b).lo, \
+ (r).hi = (a).hi ^ (b).hi)
+#define JSLL_OR2(r, a) ((r).lo = (r).lo | (a).lo, \
+ (r).hi = (r).hi | (a).hi)
+#define JSLL_NOT(r, a) ((r).lo = ~(a).lo, \
+ (r).hi = ~(a).hi)
+
+#define JSLL_NEG(r, a) ((r).lo = -(JSInt32)(a).lo, \
+ (r).hi = -(JSInt32)(a).hi - ((r).lo != 0))
+#define JSLL_ADD(r, a, b) { \
+ JSInt64 _a, _b; \
+ _a = a; _b = b; \
+ (r).lo = _a.lo + _b.lo; \
+ (r).hi = _a.hi + _b.hi + ((r).lo < _b.lo); \
+}
+
+#define JSLL_SUB(r, a, b) { \
+ JSInt64 _a, _b; \
+ _a = a; _b = b; \
+ (r).lo = _a.lo - _b.lo; \
+ (r).hi = _a.hi - _b.hi - (_a.lo < _b.lo); \
+}
+
+#define JSLL_MUL(r, a, b) { \
+ JSInt64 _a, _b; \
+ _a = a; _b = b; \
+ JSLL_MUL32(r, _a.lo, _b.lo); \
+ (r).hi += _a.hi * _b.lo + _a.lo * _b.hi; \
+}
+
+#define jslo16(a) ((a) & JS_BITMASK(16))
+#define jshi16(a) ((a) >> 16)
+
+#define JSLL_MUL32(r, a, b) { \
+ JSUint32 _a1, _a0, _b1, _b0, _y0, _y1, _y2, _y3; \
+ _a1 = jshi16(a), _a0 = jslo16(a); \
+ _b1 = jshi16(b), _b0 = jslo16(b); \
+ _y0 = _a0 * _b0; \
+ _y1 = _a0 * _b1; \
+ _y2 = _a1 * _b0; \
+ _y3 = _a1 * _b1; \
+ _y1 += jshi16(_y0); /* can't carry */ \
+ _y1 += _y2; /* might carry */ \
+ if (_y1 < _y2) \
+ _y3 += (JSUint32)(JS_BIT(16)); /* propagate */ \
+ (r).lo = (jslo16(_y1) << 16) + jslo16(_y0); \
+ (r).hi = _y3 + jshi16(_y1); \
+}
+
+#define JSLL_UDIVMOD(qp, rp, a, b) jsll_udivmod(qp, rp, a, b)
+
+extern JS_PUBLIC_API(void) jsll_udivmod(JSUint64 *qp, JSUint64 *rp, JSUint64 a, JSUint64 b);
+
+#define JSLL_DIV(r, a, b) { \
+ JSInt64 _a, _b; \
+ JSUint32 _negative = (JSInt32)(a).hi < 0; \
+ if (_negative) { \
+ JSLL_NEG(_a, a); \
+ } else { \
+ _a = a; \
+ } \
+ if ((JSInt32)(b).hi < 0) { \
+ _negative ^= 1; \
+ JSLL_NEG(_b, b); \
+ } else { \
+ _b = b; \
+ } \
+ JSLL_UDIVMOD(&(r), 0, _a, _b); \
+ if (_negative) \
+ JSLL_NEG(r, r); \
+}
+
+#define JSLL_MOD(r, a, b) { \
+ JSInt64 _a, _b; \
+ JSUint32 _negative = (JSInt32)(a).hi < 0; \
+ if (_negative) { \
+ JSLL_NEG(_a, a); \
+ } else { \
+ _a = a; \
+ } \
+ if ((JSInt32)(b).hi < 0) { \
+ JSLL_NEG(_b, b); \
+ } else { \
+ _b = b; \
+ } \
+ JSLL_UDIVMOD(0, &(r), _a, _b); \
+ if (_negative) \
+ JSLL_NEG(r, r); \
+}
+
+#define JSLL_SHL(r, a, b) { \
+ if (b) { \
+ JSInt64 _a; \
+ _a = a; \
+ if ((b) < 32) { \
+ (r).lo = _a.lo << ((b) & 31); \
+ (r).hi = (_a.hi << ((b) & 31)) | (_a.lo >> (32 - (b))); \
+ } else { \
+ (r).lo = 0; \
+ (r).hi = _a.lo << ((b) & 31); \
+ } \
+ } else { \
+ (r) = (a); \
+ } \
+}
+
+/* a is an JSInt32, b is JSInt32, r is JSInt64 */
+#define JSLL_ISHL(r, a, b) { \
+ if (b) { \
+ JSInt64 _a; \
+ _a.lo = (a); \
+ _a.hi = 0; \
+ if ((b) < 32) { \
+ (r).lo = (a) << ((b) & 31); \
+ (r).hi = ((a) >> (32 - (b))); \
+ } else { \
+ (r).lo = 0; \
+ (r).hi = (a) << ((b) & 31); \
+ } \
+ } else { \
+ (r).lo = (a); \
+ (r).hi = 0; \
+ } \
+}
+
+#define JSLL_SHR(r, a, b) { \
+ if (b) { \
+ JSInt64 _a; \
+ _a = a; \
+ if ((b) < 32) { \
+ (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \
+ (r).hi = (JSInt32)_a.hi >> ((b) & 31); \
+ } else { \
+ (r).lo = (JSInt32)_a.hi >> ((b) & 31); \
+ (r).hi = (JSInt32)_a.hi >> 31; \
+ } \
+ } else { \
+ (r) = (a); \
+ } \
+}
+
+#define JSLL_USHR(r, a, b) { \
+ if (b) { \
+ JSInt64 _a; \
+ _a = a; \
+ if ((b) < 32) { \
+ (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \
+ (r).hi = _a.hi >> ((b) & 31); \
+ } else { \
+ (r).lo = _a.hi >> ((b) & 31); \
+ (r).hi = 0; \
+ } \
+ } else { \
+ (r) = (a); \
+ } \
+}
+
+#define JSLL_L2I(i, l) ((i) = (l).lo)
+#define JSLL_L2UI(ui, l) ((ui) = (l).lo)
+#define JSLL_L2F(f, l) { double _d; JSLL_L2D(_d, l); (f) = (JSFloat64)_d; }
+
+#define JSLL_L2D(d, l) { \
+ int _negative; \
+ JSInt64 _absval; \
+ \
+ _negative = (l).hi >> 31; \
+ if (_negative) { \
+ JSLL_NEG(_absval, l); \
+ } else { \
+ _absval = l; \
+ } \
+ (d) = (double)_absval.hi * 4.294967296e9 + _absval.lo; \
+ if (_negative) \
+ (d) = -(d); \
+}
+
+#define JSLL_I2L(l, i) { JSInt32 _i = (i) >> 31; (l).lo = (i); (l).hi = _i; }
+#define JSLL_UI2L(l, ui) ((l).lo = (ui), (l).hi = 0)
+#define JSLL_F2L(l, f) { double _d = (double)f; JSLL_D2L(l, _d); }
+
+#define JSLL_D2L(l, d) { \
+ int _negative; \
+ double _absval, _d_hi; \
+ JSInt64 _lo_d; \
+ \
+ _negative = ((d) < 0); \
+ _absval = _negative ? -(d) : (d); \
+ \
+ (l).hi = _absval / 4.294967296e9; \
+ (l).lo = 0; \
+ JSLL_L2D(_d_hi, l); \
+ _absval -= _d_hi; \
+ _lo_d.hi = 0; \
+ if (_absval < 0) { \
+ _lo_d.lo = -_absval; \
+ JSLL_SUB(l, l, _lo_d); \
+ } else { \
+ _lo_d.lo = _absval; \
+ JSLL_ADD(l, l, _lo_d); \
+ } \
+ \
+ if (_negative) \
+ JSLL_NEG(l, l); \
+}
+
+#endif /* !JS_HAVE_LONG_LONG */
+
+JS_END_EXTERN_C
+
+#endif /* jslong_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsmath.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsmath.cpp
new file mode 100644
index 0000000..75fa900
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsmath.cpp
@@ -0,0 +1,721 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS math package.
+ */
+#include "jsstddef.h"
+#include "jslibmath.h"
+#include <stdlib.h>
+#include "jstypes.h"
+#include "jslong.h"
+#include "prmjtime.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jslock.h"
+#include "jsmath.h"
+#include "jsnum.h"
+#include "jsobj.h"
+
+extern jsdouble js_NaN;
+
+#ifndef M_E
+#define M_E 2.7182818284590452354
+#endif
+#ifndef M_LOG2E
+#define M_LOG2E 1.4426950408889634074
+#endif
+#ifndef M_LOG10E
+#define M_LOG10E 0.43429448190325182765
+#endif
+#ifndef M_LN2
+#define M_LN2 0.69314718055994530942
+#endif
+#ifndef M_LN10
+#define M_LN10 2.30258509299404568402
+#endif
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237309504880
+#endif
+#ifndef M_SQRT1_2
+#define M_SQRT1_2 0.70710678118654752440
+#endif
+
+static JSConstDoubleSpec math_constants[] = {
+ {M_E, "E", 0, {0,0,0}},
+ {M_LOG2E, "LOG2E", 0, {0,0,0}},
+ {M_LOG10E, "LOG10E", 0, {0,0,0}},
+ {M_LN2, "LN2", 0, {0,0,0}},
+ {M_LN10, "LN10", 0, {0,0,0}},
+ {M_PI, "PI", 0, {0,0,0}},
+ {M_SQRT2, "SQRT2", 0, {0,0,0}},
+ {M_SQRT1_2, "SQRT1_2", 0, {0,0,0}},
+ {0,0,0,{0,0,0}}
+};
+
+JSClass js_MathClass = {
+ js_Math_str,
+ JSCLASS_HAS_CACHED_PROTO(JSProto_Math),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+math_abs(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = fabs(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_acos(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+#if defined(SOLARIS) && defined(__GNUC__)
+ if (x < -1 || 1 < x) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+#endif
+ z = acos(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_asin(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+#if defined(SOLARIS) && defined(__GNUC__)
+ if (x < -1 || 1 < x) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+#endif
+ z = asin(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_atan(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = atan(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_atan2(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, y, z;
+
+ if (argc <= 1) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ y = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+#if defined(_MSC_VER)
+ /*
+ * MSVC's atan2 does not yield the result demanded by ECMA when both x
+ * and y are infinite.
+ * - The result is a multiple of pi/4.
+ * - The sign of x determines the sign of the result.
+ * - The sign of y determines the multiplicator, 1 or 3.
+ */
+ if (JSDOUBLE_IS_INFINITE(x) && JSDOUBLE_IS_INFINITE(y)) {
+ z = js_copysign(M_PI / 4, x);
+ if (y < 0)
+ z *= 3;
+ return js_NewDoubleInRootedValue(cx, z, vp);
+ }
+#endif
+
+#if defined(SOLARIS) && defined(__GNUC__)
+ if (x == 0) {
+ if (JSDOUBLE_IS_NEGZERO(y)) {
+ z = js_copysign(M_PI, x);
+ return js_NewDoubleInRootedValue(cx, z, vp);
+ }
+ if (y == 0) {
+ z = x;
+ return js_NewDoubleInRootedValue(cx, z, vp);
+ }
+ }
+#endif
+ z = atan2(x, y);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_ceil(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = ceil(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_cos(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = cos(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_exp(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+#ifdef _WIN32
+ if (!JSDOUBLE_IS_NaN(x)) {
+ if (x == *cx->runtime->jsPositiveInfinity) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
+ return JS_TRUE;
+ }
+ if (x == *cx->runtime->jsNegativeInfinity) {
+ *vp = JSVAL_ZERO;
+ return JS_TRUE;
+ }
+ }
+#endif
+ z = exp(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_floor(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = floor(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_log(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+#if defined(SOLARIS) && defined(__GNUC__)
+ if (x < 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+#endif
+ z = log(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_max(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z = *cx->runtime->jsNegativeInfinity;
+ jsval *argv;
+ uintN i;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
+ return JS_TRUE;
+ }
+ argv = vp + 2;
+ for (i = 0; i < argc; i++) {
+ x = js_ValueToNumber(cx, &argv[i]);
+ if (JSVAL_IS_NULL(argv[i]))
+ return JS_FALSE;
+ if (JSDOUBLE_IS_NaN(x)) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ if (x == 0 && x == z) {
+ if (js_copysign(1.0, z) == -1)
+ z = x;
+ } else {
+ z = (x > z) ? x : z;
+ }
+ }
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_min(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z = *cx->runtime->jsPositiveInfinity;
+ jsval *argv;
+ uintN i;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
+ return JS_TRUE;
+ }
+ argv = vp + 2;
+ for (i = 0; i < argc; i++) {
+ x = js_ValueToNumber(cx, &argv[i]);
+ if (JSVAL_IS_NULL(argv[i]))
+ return JS_FALSE;
+ if (JSDOUBLE_IS_NaN(x)) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ if (x == 0 && x == z) {
+ if (js_copysign(1.0, x) == -1)
+ z = x;
+ } else {
+ z = (x < z) ? x : z;
+ }
+ }
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_pow(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, y, z;
+
+ if (argc <= 1) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ y = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ /*
+ * Because C99 and ECMA specify different behavior for pow(),
+ * we need to wrap the libm call to make it ECMA compliant.
+ */
+ if (!JSDOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ /* pow(x, +-0) is always 1, even for x = NaN. */
+ if (y == 0) {
+ *vp = JSVAL_ONE;
+ return JS_TRUE;
+ }
+ z = pow(x, y);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+/*
+ * Math.random() support, lifted from java.util.Random.java.
+ */
+static void
+random_setSeed(JSRuntime *rt, int64 seed)
+{
+ int64 tmp;
+
+ JSLL_I2L(tmp, 1000);
+ JSLL_DIV(seed, seed, tmp);
+ JSLL_XOR(tmp, seed, rt->rngMultiplier);
+ JSLL_AND(rt->rngSeed, tmp, rt->rngMask);
+}
+
+void
+js_random_init(JSRuntime *rt)
+{
+ int64 tmp, tmp2;
+
+ /* Do at most once. */
+ if (rt->rngInitialized)
+ return;
+ rt->rngInitialized = JS_TRUE;
+
+ /* rt->rngMultiplier = 0x5DEECE66DL */
+ JSLL_ISHL(tmp, 0x5, 32);
+ JSLL_UI2L(tmp2, 0xDEECE66DL);
+ JSLL_OR(rt->rngMultiplier, tmp, tmp2);
+
+ /* rt->rngAddend = 0xBL */
+ JSLL_I2L(rt->rngAddend, 0xBL);
+
+ /* rt->rngMask = (1L << 48) - 1 */
+ JSLL_I2L(tmp, 1);
+ JSLL_SHL(tmp2, tmp, 48);
+ JSLL_SUB(rt->rngMask, tmp2, tmp);
+
+ /* rt->rngDscale = (jsdouble)(1L << 53) */
+ JSLL_SHL(tmp2, tmp, 53);
+ JSLL_L2D(rt->rngDscale, tmp2);
+
+ /* Finally, set the seed from current time. */
+ random_setSeed(rt, PRMJ_Now());
+}
+
+static uint32
+random_next(JSRuntime *rt, int bits)
+{
+ int64 nextseed, tmp;
+ uint32 retval;
+
+ JSLL_MUL(nextseed, rt->rngSeed, rt->rngMultiplier);
+ JSLL_ADD(nextseed, nextseed, rt->rngAddend);
+ JSLL_AND(nextseed, nextseed, rt->rngMask);
+ rt->rngSeed = nextseed;
+ JSLL_USHR(tmp, nextseed, 48 - bits);
+ JSLL_L2I(retval, tmp);
+ return retval;
+}
+
+jsdouble
+js_random_nextDouble(JSRuntime *rt)
+{
+ int64 tmp, tmp2;
+ jsdouble d;
+
+ JSLL_ISHL(tmp, random_next(rt, 26), 27);
+ JSLL_UI2L(tmp2, random_next(rt, 27));
+ JSLL_ADD(tmp, tmp, tmp2);
+ JSLL_L2D(d, tmp);
+ return d / rt->rngDscale;
+}
+
+static JSBool
+math_random(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSRuntime *rt;
+ jsdouble z;
+
+ rt = cx->runtime;
+ JS_LOCK_RUNTIME(rt);
+ js_random_init(rt);
+ z = js_random_nextDouble(rt);
+ JS_UNLOCK_RUNTIME(rt);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+#if defined _WIN32 && !defined WINCE && _MSC_VER < 1400
+/* Try to work around apparent _copysign bustage in VC6 and VC7. */
+double
+js_copysign(double x, double y)
+{
+ jsdpun xu, yu;
+
+ xu.d = x;
+ yu.d = y;
+ xu.s.hi &= ~JSDOUBLE_HI32_SIGNBIT;
+ xu.s.hi |= yu.s.hi & JSDOUBLE_HI32_SIGNBIT;
+ return xu.d;
+}
+#endif
+
+static JSBool
+math_round(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = js_copysign(floor(x + 0.5), x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_sin(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = sin(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_sqrt(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = sqrt(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_tan(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = tan(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+math_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ *vp = ATOM_KEY(CLASS_ATOM(cx, Math));
+ return JS_TRUE;
+}
+#endif
+
+#ifdef JS_TRACER
+
+#define MATH_BUILTIN_1(name) \
+ static jsdouble FASTCALL math_##name##_tn(jsdouble d) { return name(d); } \
+ JS_DEFINE_TRCINFO_1(math_##name, \
+ (1, (static, DOUBLE, math_##name##_tn, DOUBLE, 1, 1)))
+
+MATH_BUILTIN_1(sin)
+MATH_BUILTIN_1(cos)
+MATH_BUILTIN_1(sqrt)
+MATH_BUILTIN_1(floor)
+MATH_BUILTIN_1(ceil)
+
+static jsdouble FASTCALL
+math_abs_tn(jsdouble d)
+{
+ return fabs(d);
+}
+
+static jsdouble FASTCALL
+math_log_tn(jsdouble d)
+{
+#if defined(SOLARIS) && defined(__GNUC__)
+ if (d < 0)
+ return js_NaN;
+#endif
+ return log(d);
+}
+
+static jsdouble FASTCALL
+math_max_tn(jsdouble d, jsdouble p)
+{
+ if (JSDOUBLE_IS_NaN(d) || JSDOUBLE_IS_NaN(p))
+ return js_NaN;
+
+ if (p == 0 && p == d) {
+ if (js_copysign(1.0, d) == -1)
+ return p;
+ return d;
+ }
+ return (p > d) ? p : d;
+}
+
+static jsdouble FASTCALL
+math_pow_tn(jsdouble d, jsdouble p)
+{
+ if (!JSDOUBLE_IS_FINITE(p) && (d == 1.0 || d == -1.0))
+ return js_NaN;
+ if (p == 0)
+ return 1.0;
+ return pow(d, p);
+}
+
+static jsdouble FASTCALL
+math_random_tn(JSRuntime* rt)
+{
+ JS_LOCK_RUNTIME(rt);
+ js_random_init(rt);
+ jsdouble z = js_random_nextDouble(rt);
+ JS_UNLOCK_RUNTIME(rt);
+ return z;
+}
+
+static jsdouble FASTCALL
+math_round_tn(jsdouble x)
+{
+ return js_copysign(floor(x + 0.5), x);
+}
+
+JS_DEFINE_TRCINFO_1(math_abs,
+ (1, (static, DOUBLE, math_abs_tn, DOUBLE, 1, 1)))
+JS_DEFINE_TRCINFO_1(math_log,
+ (1, (static, DOUBLE, math_log_tn, DOUBLE, 1, 1)))
+JS_DEFINE_TRCINFO_1(math_max,
+ (2, (static, DOUBLE, math_max_tn, DOUBLE, DOUBLE, 1, 1)))
+JS_DEFINE_TRCINFO_1(math_pow,
+ (2, (static, DOUBLE, math_pow_tn, DOUBLE, DOUBLE, 1, 1)))
+JS_DEFINE_TRCINFO_1(math_random,
+ (1, (static, DOUBLE, math_random_tn, RUNTIME, 0, 0)))
+JS_DEFINE_TRCINFO_1(math_round,
+ (1, (static, DOUBLE, math_round_tn, DOUBLE, 1, 1)))
+
+#endif /* JS_TRACER */
+
+static JSFunctionSpec math_static_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, math_toSource, 0, 0),
+#endif
+ JS_TN("abs", math_abs, 1, 0, math_abs_trcinfo),
+ JS_FN("acos", math_acos, 1, 0),
+ JS_FN("asin", math_asin, 1, 0),
+ JS_FN("atan", math_atan, 1, 0),
+ JS_FN("atan2", math_atan2, 2, 0),
+ JS_TN("ceil", math_ceil, 1, 0, math_ceil_trcinfo),
+ JS_TN("cos", math_cos, 1, 0, math_cos_trcinfo),
+ JS_FN("exp", math_exp, 1, 0),
+ JS_TN("floor", math_floor, 1, 0, math_floor_trcinfo),
+ JS_TN("log", math_log, 1, 0, math_log_trcinfo),
+ JS_TN("max", math_max, 2, 0, math_max_trcinfo),
+ JS_FN("min", math_min, 2, 0),
+ JS_TN("pow", math_pow, 2, 0, math_pow_trcinfo),
+ JS_TN("random", math_random, 0, 0, math_random_trcinfo),
+ JS_TN("round", math_round, 1, 0, math_round_trcinfo),
+ JS_TN("sin", math_sin, 1, 0, math_sin_trcinfo),
+ JS_TN("sqrt", math_sqrt, 1, 0, math_sqrt_trcinfo),
+ JS_FN("tan", math_tan, 1, 0),
+ JS_FS_END
+};
+
+JSObject *
+js_InitMathClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *Math;
+
+ Math = JS_NewObject(cx, &js_MathClass, NULL, obj);
+ if (!Math)
+ return NULL;
+ if (!JS_DefineProperty(cx, obj, js_Math_str, OBJECT_TO_JSVAL(Math),
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_READONLY | JSPROP_PERMANENT))
+ return NULL;
+
+ if (!JS_DefineFunctions(cx, Math, math_static_methods))
+ return NULL;
+ if (!JS_DefineConstDoubles(cx, Math, math_constants))
+ return NULL;
+ return Math;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsmath.h b/tools/node_modules/expresso/deps/jscoverage/js/jsmath.h
new file mode 100644
index 0000000..96e1c7f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsmath.h
@@ -0,0 +1,63 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* -*- Mode: C; tab-width: 8 -*-
+ * Copyright (C) 1998-1999 Netscape Communications Corporation, All Rights Reserved.
+ */
+
+#ifndef jsmath_h___
+#define jsmath_h___
+/*
+ * JS math functions.
+ */
+
+JS_BEGIN_EXTERN_C
+
+extern JSClass js_MathClass;
+
+extern JSObject *
+js_InitMathClass(JSContext *cx, JSObject *obj);
+
+extern void
+js_random_init(JSRuntime *rt);
+
+extern jsdouble
+js_random_nextDouble(JSRuntime *rt);
+
+JS_END_EXTERN_C
+
+#endif /* jsmath_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsnum.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsnum.cpp
new file mode 100644
index 0000000..f6c1b5f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsnum.cpp
@@ -0,0 +1,1338 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS number type and wrapper class.
+ */
+#include "jsstddef.h"
+#if defined(XP_WIN) || defined(XP_OS2)
+#include <float.h>
+#endif
+#include <locale.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdtoa.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsprf.h"
+#include "jsscope.h"
+#include "jsstr.h"
+
+static JSBool
+num_isNaN(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x;
+
+ if (argc == 0) {
+ *vp = JSVAL_TRUE;
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ *vp = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_NaN(x));
+ return JS_TRUE;
+}
+
+static JSBool
+num_isFinite(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x;
+
+ if (argc == 0) {
+ *vp = JSVAL_FALSE;
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ *vp = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_FINITE(x));
+ return JS_TRUE;
+}
+
+static JSBool
+num_parseFloat(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ jsdouble d;
+ const jschar *bp, *end, *ep;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if (!js_strtod(cx, bp, end, &ep, &d))
+ return JS_FALSE;
+ if (ep == bp) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ return js_NewNumberInRootedValue(cx, d, vp);
+}
+
+#ifdef JS_TRACER
+static jsdouble FASTCALL
+ParseFloat(JSContext* cx, JSString* str)
+{
+ const jschar* bp;
+ const jschar* end;
+ const jschar* ep;
+ jsdouble d;
+
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if (!js_strtod(cx, bp, end, &ep, &d) || ep == bp)
+ return js_NaN;
+ return d;
+}
+#endif
+
+/* See ECMA 15.1.2.2. */
+static JSBool
+num_parseInt(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsint radix;
+ JSString *str;
+ jsdouble d;
+ const jschar *bp, *end, *ep;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ if (argc > 1) {
+ radix = js_ValueToECMAInt32(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ } else {
+ radix = 0;
+ }
+ if (radix != 0 && (radix < 2 || radix > 36)) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+
+ if (JSVAL_IS_INT(vp[2]) && (radix == 0 || radix == 10)) {
+ *vp = vp[2];
+ return JS_TRUE;
+ }
+
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if (!js_strtointeger(cx, bp, end, &ep, radix, &d))
+ return JS_FALSE;
+ if (ep == bp) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ return js_NewNumberInRootedValue(cx, d, vp);
+}
+
+#ifdef JS_TRACER
+static jsdouble FASTCALL
+ParseInt(JSContext* cx, JSString* str)
+{
+ const jschar* bp;
+ const jschar* end;
+ const jschar* ep;
+ jsdouble d;
+
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if (!js_strtointeger(cx, bp, end, &ep, 0, &d) || ep == bp)
+ return js_NaN;
+ return d;
+}
+
+static jsdouble FASTCALL
+ParseIntDouble(jsdouble d)
+{
+ if (!JSDOUBLE_IS_FINITE(d))
+ return js_NaN;
+ return floor(d);
+}
+#endif
+
+const char js_Infinity_str[] = "Infinity";
+const char js_NaN_str[] = "NaN";
+const char js_isNaN_str[] = "isNaN";
+const char js_isFinite_str[] = "isFinite";
+const char js_parseFloat_str[] = "parseFloat";
+const char js_parseInt_str[] = "parseInt";
+
+#ifdef JS_TRACER
+
+JS_DEFINE_TRCINFO_2(num_parseInt,
+ (2, (static, DOUBLE, ParseInt, CONTEXT, STRING, 1, 1)),
+ (1, (static, DOUBLE, ParseIntDouble, DOUBLE, 1, 1)))
+
+JS_DEFINE_TRCINFO_1(num_parseFloat,
+ (2, (static, DOUBLE, ParseFloat, CONTEXT, STRING, 1, 1)))
+
+#endif /* JS_TRACER */
+
+static JSFunctionSpec number_functions[] = {
+ JS_FN(js_isNaN_str, num_isNaN, 1,0),
+ JS_FN(js_isFinite_str, num_isFinite, 1,0),
+ JS_TN(js_parseFloat_str, num_parseFloat, 1,0, num_parseFloat_trcinfo),
+ JS_TN(js_parseInt_str, num_parseInt, 2,0, num_parseInt_trcinfo),
+ JS_FS_END
+};
+
+JSClass js_NumberClass = {
+ js_Number_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Number),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+Number(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsval v;
+ jsdouble d;
+
+ if (argc != 0) {
+ d = js_ValueToNumber(cx, &argv[0]);
+ v = argv[0];
+ if (JSVAL_IS_NULL(v))
+ return JS_FALSE;
+ if (v != JSVAL_TRUE) {
+ JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v));
+ } else {
+ if (!js_NewNumberInRootedValue(cx, d, &argv[0]))
+ return JS_FALSE;
+ v = argv[0];
+ }
+ } else {
+ v = JSVAL_ZERO;
+ }
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ *rval = v;
+ return JS_TRUE;
+ }
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, v);
+ return JS_TRUE;
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+num_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ jsdouble d;
+ char numBuf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr;
+ char buf[64];
+ JSString *str;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_NUMBER(v));
+ d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
+ numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d);
+ if (!numStr) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ JS_snprintf(buf, sizeof buf, "(new %s(%s))", js_NumberClass.name, numStr);
+ str = JS_NewStringCopyZ(cx, buf);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif
+
+/* The buf must be big enough for MIN_INT to fit including '-' and '\0'. */
+char *
+js_IntToCString(jsint i, jsint base, char *buf, size_t bufSize)
+{
+ char *cp;
+ jsuint u;
+
+ u = (i < 0) ? -i : i;
+
+ cp = buf + bufSize; /* one past last buffer cell */
+ *--cp = '\0'; /* null terminate the string to be */
+
+ /*
+ * Build the string from behind. We use multiply and subtraction
+ * instead of modulus because that's much faster.
+ */
+ switch (base) {
+ case 10:
+ do {
+ jsuint newu = u / 10;
+ *--cp = (char)(u - newu * 10) + '0';
+ u = newu;
+ } while (u != 0);
+ break;
+ case 16:
+ do {
+ jsuint newu = u / 16;
+ *--cp = "0123456789abcdef"[u - newu * 16];
+ u = newu;
+ } while (u != 0);
+ break;
+ default:
+ JS_ASSERT(base >= 2 && base <= 36);
+ do {
+ jsuint newu = u / base;
+ *--cp = "0123456789abcdefghijklmnopqrstuvwxyz"[u - newu * base];
+ u = newu;
+ } while (u != 0);
+ break;
+ }
+ if (i < 0)
+ *--cp = '-';
+
+ JS_ASSERT(cp >= buf);
+ return cp;
+}
+
+static JSBool
+num_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ jsdouble d;
+ jsint base;
+ JSString *str;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_NUMBER(v));
+ d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
+ base = 10;
+ if (argc != 0 && !JSVAL_IS_VOID(vp[2])) {
+ base = js_ValueToECMAInt32(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ if (base < 2 || base > 36) {
+ char numBuf[12];
+ char *numStr = js_IntToCString(base, 10, numBuf, sizeof numBuf);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_RADIX,
+ numStr);
+ return JS_FALSE;
+ }
+ }
+ if (base == 10) {
+ str = js_NumberToString(cx, d);
+ } else {
+ char *dStr = JS_dtobasestr(base, d);
+ if (!dStr) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ str = JS_NewStringCopyZ(cx, dStr);
+ free(dStr);
+ }
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+num_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
+{
+ char thousandsLength, decimalLength;
+ const char *numGrouping, *tmpGroup;
+ JSRuntime *rt;
+ JSString *numStr, *str;
+ const char *num, *end, *tmpSrc;
+ char *buf, *tmpDest;
+ const char *nint;
+ int digits, size, remainder, nrepeat;
+
+ /*
+ * Create the string, move back to bytes to make string twiddling
+ * a bit easier and so we can insert platform charset seperators.
+ */
+ if (!num_toString(cx, 0, vp))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_STRING(*vp));
+ numStr = JSVAL_TO_STRING(*vp);
+ num = js_GetStringBytes(cx, numStr);
+ if (!num)
+ return JS_FALSE;
+
+ /*
+ * Find the first non-integer value, whether it be a letter as in
+ * 'Infinity', a decimal point, or an 'e' from exponential notation.
+ */
+ nint = num;
+ if (*nint == '-')
+ nint++;
+ while (*nint >= '0' && *nint <= '9')
+ nint++;
+ digits = nint - num;
+ end = num + digits;
+ if (!digits)
+ return JS_TRUE;
+
+ rt = cx->runtime;
+ thousandsLength = strlen(rt->thousandsSeparator);
+ decimalLength = strlen(rt->decimalSeparator);
+
+ /* Figure out how long resulting string will be. */
+ size = digits + (*nint ? strlen(nint + 1) + 1 : 0);
+ if (*nint == '.')
+ size += decimalLength;
+
+ numGrouping = tmpGroup = rt->numGrouping;
+ remainder = digits;
+ if (*num == '-')
+ remainder--;
+
+ while (*tmpGroup != CHAR_MAX && *tmpGroup != '\0') {
+ if (*tmpGroup >= remainder)
+ break;
+ size += thousandsLength;
+ remainder -= *tmpGroup;
+ tmpGroup++;
+ }
+ if (*tmpGroup == '\0' && *numGrouping != '\0') {
+ nrepeat = (remainder - 1) / tmpGroup[-1];
+ size += thousandsLength * nrepeat;
+ remainder -= nrepeat * tmpGroup[-1];
+ } else {
+ nrepeat = 0;
+ }
+ tmpGroup--;
+
+ buf = (char *)JS_malloc(cx, size + 1);
+ if (!buf)
+ return JS_FALSE;
+
+ tmpDest = buf;
+ tmpSrc = num;
+
+ while (*tmpSrc == '-' || remainder--)
+ *tmpDest++ = *tmpSrc++;
+ while (tmpSrc < end) {
+ strcpy(tmpDest, rt->thousandsSeparator);
+ tmpDest += thousandsLength;
+ memcpy(tmpDest, tmpSrc, *tmpGroup);
+ tmpDest += *tmpGroup;
+ tmpSrc += *tmpGroup;
+ if (--nrepeat < 0)
+ tmpGroup--;
+ }
+
+ if (*nint == '.') {
+ strcpy(tmpDest, rt->decimalSeparator);
+ tmpDest += decimalLength;
+ strcpy(tmpDest, nint + 1);
+ } else {
+ strcpy(tmpDest, nint);
+ }
+
+ if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
+ return cx->localeCallbacks->localeToUnicode(cx, buf, vp);
+
+ str = JS_NewString(cx, buf, size);
+ if (!str) {
+ JS_free(cx, buf);
+ return JS_FALSE;
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+num_valueOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ JSObject *obj;
+
+ v = vp[1];
+ if (JSVAL_IS_NUMBER(v)) {
+ *vp = v;
+ return JS_TRUE;
+ }
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_NumberClass, vp + 2))
+ return JS_FALSE;
+ *vp = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ return JS_TRUE;
+}
+
+
+#define MAX_PRECISION 100
+
+static JSBool
+num_to(JSContext *cx, JSDToStrMode zeroArgMode, JSDToStrMode oneArgMode,
+ jsint precisionMin, jsint precisionMax, jsint precisionOffset,
+ uintN argc, jsval *vp)
+{
+ jsval v;
+ jsdouble d, precision;
+ JSString *str;
+
+ /* Use MAX_PRECISION+1 because precisionOffset can be 1. */
+ char buf[DTOSTR_VARIABLE_BUFFER_SIZE(MAX_PRECISION+1)];
+ char *numStr;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_NUMBER(v));
+ d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
+
+ if (argc == 0) {
+ precision = 0.0;
+ oneArgMode = zeroArgMode;
+ } else {
+ precision = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ precision = js_DoubleToInteger(precision);
+ if (precision < precisionMin || precision > precisionMax) {
+ numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, precision);
+ if (!numStr)
+ JS_ReportOutOfMemory(cx);
+ else
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PRECISION_RANGE, numStr);
+ return JS_FALSE;
+ }
+ }
+
+ numStr = JS_dtostr(buf, sizeof buf, oneArgMode, (jsint)precision + precisionOffset, d);
+ if (!numStr) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ str = JS_NewStringCopyZ(cx, numStr);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+/*
+ * In the following three implementations, we allow a larger range of precision
+ * than ECMA requires; this is permitted by ECMA-262.
+ */
+static JSBool
+num_toFixed(JSContext *cx, uintN argc, jsval *vp)
+{
+ return num_to(cx, DTOSTR_FIXED, DTOSTR_FIXED, -20, MAX_PRECISION, 0,
+ argc, vp);
+}
+
+static JSBool
+num_toExponential(JSContext *cx, uintN argc, jsval *vp)
+{
+ return num_to(cx, DTOSTR_STANDARD_EXPONENTIAL, DTOSTR_EXPONENTIAL, 0,
+ MAX_PRECISION, 1, argc, vp);
+}
+
+static JSBool
+num_toPrecision(JSContext *cx, uintN argc, jsval *vp)
+{
+ if (argc == 0 || JSVAL_IS_VOID(vp[2]))
+ return num_toString(cx, 0, vp);
+ return num_to(cx, DTOSTR_STANDARD, DTOSTR_PRECISION, 1, MAX_PRECISION, 0,
+ argc, vp);
+}
+
+#ifdef JS_TRACER
+
+JS_DEFINE_TRCINFO_2(num_toString,
+ (3, (static, STRING, NumberToStringWithBase, CONTEXT, THIS_DOUBLE, INT32, 1, 1)),
+ (2, (extern, STRING, js_NumberToString, CONTEXT, THIS_DOUBLE, 1, 1)))
+
+#endif /* JS_TRACER */
+
+static JSFunctionSpec number_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, num_toSource, 0,JSFUN_THISP_NUMBER),
+#endif
+ JS_TN(js_toString_str, num_toString, 1,JSFUN_THISP_NUMBER,
+ num_toString_trcinfo),
+ JS_FN(js_toLocaleString_str, num_toLocaleString, 0,JSFUN_THISP_NUMBER),
+ JS_FN(js_valueOf_str, num_valueOf, 0,JSFUN_THISP_NUMBER),
+ JS_FN(js_toJSON_str, num_valueOf, 0,JSFUN_THISP_NUMBER),
+ JS_FN("toFixed", num_toFixed, 1,JSFUN_THISP_NUMBER),
+ JS_FN("toExponential", num_toExponential, 1,JSFUN_THISP_NUMBER),
+ JS_FN("toPrecision", num_toPrecision, 1,JSFUN_THISP_NUMBER),
+ JS_FS_END
+};
+
+/* NB: Keep this in synch with number_constants[]. */
+enum nc_slot {
+ NC_NaN,
+ NC_POSITIVE_INFINITY,
+ NC_NEGATIVE_INFINITY,
+ NC_MAX_VALUE,
+ NC_MIN_VALUE,
+ NC_LIMIT
+};
+
+/*
+ * Some to most C compilers forbid spelling these at compile time, or barf
+ * if you try, so all but MAX_VALUE are set up by js_InitRuntimeNumberState
+ * using union jsdpun.
+ */
+static JSConstDoubleSpec number_constants[] = {
+ {0, js_NaN_str, 0,{0,0,0}},
+ {0, "POSITIVE_INFINITY", 0,{0,0,0}},
+ {0, "NEGATIVE_INFINITY", 0,{0,0,0}},
+ {1.7976931348623157E+308, "MAX_VALUE", 0,{0,0,0}},
+ {0, "MIN_VALUE", 0,{0,0,0}},
+ {0,0,0,{0,0,0}}
+};
+
+jsdouble js_NaN;
+
+#if (defined XP_WIN || defined XP_OS2) && \
+ !defined WINCE && \
+ !defined __MWERKS__ && \
+ (defined _M_IX86 || \
+ (defined __GNUC__ && !defined __MINGW32__))
+
+/*
+ * Set the exception mask to mask all exceptions and set the FPU precision
+ * to 53 bit mantissa.
+ * On Alpha platform this is handled via Compiler option.
+ */
+#define FIX_FPU() _control87(MCW_EM | PC_53, MCW_EM | MCW_PC)
+
+#else
+
+#define FIX_FPU() ((void)0)
+
+#endif
+
+JSBool
+js_InitRuntimeNumberState(JSContext *cx)
+{
+ JSRuntime *rt;
+ jsdpun u;
+ struct lconv *locale;
+
+ rt = cx->runtime;
+ JS_ASSERT(!rt->jsNaN);
+
+ FIX_FPU();
+
+ u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
+ u.s.lo = 0xffffffff;
+ number_constants[NC_NaN].dval = js_NaN = u.d;
+ rt->jsNaN = js_NewWeaklyRootedDouble(cx, js_NaN);
+ if (!rt->jsNaN)
+ return JS_FALSE;
+
+ u.s.hi = JSDOUBLE_HI32_EXPMASK;
+ u.s.lo = 0x00000000;
+ number_constants[NC_POSITIVE_INFINITY].dval = u.d;
+ rt->jsPositiveInfinity = js_NewWeaklyRootedDouble(cx, u.d);
+ if (!rt->jsPositiveInfinity)
+ return JS_FALSE;
+
+ u.s.hi = JSDOUBLE_HI32_SIGNBIT | JSDOUBLE_HI32_EXPMASK;
+ u.s.lo = 0x00000000;
+ number_constants[NC_NEGATIVE_INFINITY].dval = u.d;
+ rt->jsNegativeInfinity = js_NewWeaklyRootedDouble(cx, u.d);
+ if (!rt->jsNegativeInfinity)
+ return JS_FALSE;
+
+ u.s.hi = 0;
+ u.s.lo = 1;
+ number_constants[NC_MIN_VALUE].dval = u.d;
+
+ locale = localeconv();
+ rt->thousandsSeparator =
+ JS_strdup(cx, locale->thousands_sep ? locale->thousands_sep : "'");
+ rt->decimalSeparator =
+ JS_strdup(cx, locale->decimal_point ? locale->decimal_point : ".");
+ rt->numGrouping =
+ JS_strdup(cx, locale->grouping ? locale->grouping : "\3\0");
+
+ return rt->thousandsSeparator && rt->decimalSeparator && rt->numGrouping;
+}
+
+void
+js_TraceRuntimeNumberState(JSTracer *trc)
+{
+ JSRuntime *rt;
+
+ rt = trc->context->runtime;
+ if (rt->jsNaN)
+ JS_CALL_DOUBLE_TRACER(trc, rt->jsNaN, "NaN");
+ if (rt->jsPositiveInfinity)
+ JS_CALL_DOUBLE_TRACER(trc, rt->jsPositiveInfinity, "+Infinity");
+ if (rt->jsNegativeInfinity)
+ JS_CALL_DOUBLE_TRACER(trc, rt->jsNegativeInfinity, "-Infinity");
+}
+
+void
+js_FinishRuntimeNumberState(JSContext *cx)
+{
+ JSRuntime *rt = cx->runtime;
+
+ js_UnlockGCThingRT(rt, rt->jsNaN);
+ js_UnlockGCThingRT(rt, rt->jsNegativeInfinity);
+ js_UnlockGCThingRT(rt, rt->jsPositiveInfinity);
+
+ rt->jsNaN = NULL;
+ rt->jsNegativeInfinity = NULL;
+ rt->jsPositiveInfinity = NULL;
+
+ JS_free(cx, (void *)rt->thousandsSeparator);
+ JS_free(cx, (void *)rt->decimalSeparator);
+ JS_free(cx, (void *)rt->numGrouping);
+ rt->thousandsSeparator = rt->decimalSeparator = rt->numGrouping = NULL;
+}
+
+JSObject *
+js_InitNumberClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto, *ctor;
+ JSRuntime *rt;
+
+ /* XXX must do at least once per new thread, so do it per JSContext... */
+ FIX_FPU();
+
+ if (!JS_DefineFunctions(cx, obj, number_functions))
+ return NULL;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_NumberClass, Number, 1,
+ NULL, number_methods, NULL, NULL);
+ if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
+ return NULL;
+ STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE, JSVAL_ZERO);
+ if (!JS_DefineConstDoubles(cx, ctor, number_constants))
+ return NULL;
+
+ /* ECMA 15.1.1.1 */
+ rt = cx->runtime;
+ if (!JS_DefineProperty(cx, obj, js_NaN_str, DOUBLE_TO_JSVAL(rt->jsNaN),
+ NULL, NULL, JSPROP_PERMANENT)) {
+ return NULL;
+ }
+
+ /* ECMA 15.1.1.2 */
+ if (!JS_DefineProperty(cx, obj, js_Infinity_str,
+ DOUBLE_TO_JSVAL(rt->jsPositiveInfinity),
+ NULL, NULL, JSPROP_PERMANENT)) {
+ return NULL;
+ }
+ return proto;
+}
+
+JSBool
+js_NewNumberInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
+{
+ jsint i;
+
+ if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
+ *vp = INT_TO_JSVAL(i);
+ return JS_TRUE;
+ }
+ return js_NewDoubleInRootedValue(cx, d, vp);
+}
+
+char *
+js_NumberToCString(JSContext *cx, jsdouble d, jsint base, char *buf, size_t bufSize)
+{
+ jsint i;
+ char *numStr;
+
+ JS_ASSERT(bufSize >= DTOSTR_STANDARD_BUFFER_SIZE);
+ if (JSDOUBLE_IS_INT(d, i)) {
+ numStr = js_IntToCString(i, base, buf, bufSize);
+ } else {
+ if (base == 10)
+ numStr = JS_dtostr(buf, bufSize, DTOSTR_STANDARD, 0, d);
+ else
+ numStr = JS_dtobasestr(base, d);
+ if (!numStr) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ }
+ return numStr;
+}
+
+static JSString * JS_FASTCALL
+NumberToStringWithBase(JSContext *cx, jsdouble d, jsint base)
+{
+ char buf[DTOSTR_STANDARD_BUFFER_SIZE];
+ char *numStr;
+
+ if (base < 2 || base > 36)
+ return NULL;
+ numStr = js_NumberToCString(cx, d, base, buf, sizeof buf);
+ if (!numStr)
+ return NULL;
+ return JS_NewStringCopyZ(cx, numStr);
+}
+
+JSString * JS_FASTCALL
+js_NumberToString(JSContext *cx, jsdouble d)
+{
+ return NumberToStringWithBase(cx, d, 10);
+}
+
+jsdouble
+js_ValueToNumber(JSContext *cx, jsval *vp)
+{
+ jsval v;
+ JSString *str;
+ const jschar *bp, *end, *ep;
+ jsdouble d, *dp;
+ JSObject *obj;
+ JSTempValueRooter tvr;
+
+ v = *vp;
+ for (;;) {
+ if (JSVAL_IS_INT(v))
+ return (jsdouble) JSVAL_TO_INT(v);
+ if (JSVAL_IS_DOUBLE(v))
+ return *JSVAL_TO_DOUBLE(v);
+ if (JSVAL_IS_STRING(v)) {
+ str = JSVAL_TO_STRING(v);
+
+ /*
+ * Note that ECMA doesn't treat a string beginning with a '0' as
+ * an octal number here. This works because all such numbers will
+ * be interpreted as decimal by js_strtod and will never get
+ * passed to js_strtointeger (which would interpret them as
+ * octal).
+ */
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if ((!js_strtod(cx, bp, end, &ep, &d) ||
+ js_SkipWhiteSpace(ep, end) != end) &&
+ (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
+ js_SkipWhiteSpace(ep, end) != end)) {
+ break;
+ }
+
+ /*
+ * JSVAL_TRUE indicates that double jsval was never constructed
+ * for the result.
+ */
+ *vp = JSVAL_TRUE;
+ return d;
+ }
+ if (JSVAL_IS_BOOLEAN(v)) {
+ if (JSVAL_TO_BOOLEAN(v)) {
+ *vp = JSVAL_ONE;
+ return 1.0;
+ } else {
+ *vp = JSVAL_ZERO;
+ return 0.0;
+ }
+ }
+ if (JSVAL_IS_NULL(v)) {
+ *vp = JSVAL_ZERO;
+ return 0.0;
+ }
+ if (JSVAL_IS_VOID(v))
+ break;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ obj = JSVAL_TO_OBJECT(v);
+
+ /*
+ * vp roots obj so we cannot use it as an extra root for
+ * OBJ_DEFAULT_VALUE result when calling the hook.
+ */
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_NUMBER, &tvr.u.value))
+ obj = NULL;
+ else
+ v = *vp = tvr.u.value;
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!obj) {
+ *vp = JSVAL_NULL;
+ return 0.0;
+ }
+ if (!JSVAL_IS_PRIMITIVE(v))
+ break;
+ }
+
+ dp = cx->runtime->jsNaN;
+ *vp = DOUBLE_TO_JSVAL(dp);
+ return *dp;
+}
+
+int32
+js_ValueToECMAInt32(JSContext *cx, jsval *vp)
+{
+ jsval v;
+ jsdouble d;
+
+ v = *vp;
+ if (JSVAL_IS_INT(v))
+ return JSVAL_TO_INT(v);
+ if (JSVAL_IS_DOUBLE(v)) {
+ d = *JSVAL_TO_DOUBLE(v);
+ *vp = JSVAL_TRUE;
+ } else {
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return 0;
+ *vp = JSVAL_TRUE;
+ }
+ return js_DoubleToECMAInt32(d);
+}
+
+int32
+js_DoubleToECMAInt32(jsdouble d)
+{
+ int32 i;
+ jsdouble two32, two31;
+
+ if (!JSDOUBLE_IS_FINITE(d))
+ return 0;
+
+ i = (int32) d;
+ if ((jsdouble) i == d)
+ return i;
+
+ two32 = 4294967296.0;
+ two31 = 2147483648.0;
+ d = fmod(d, two32);
+ d = (d >= 0) ? floor(d) : ceil(d) + two32;
+ return (int32) (d >= two31 ? d - two32 : d);
+}
+
+uint32
+js_ValueToECMAUint32(JSContext *cx, jsval *vp)
+{
+ jsval v;
+ jsint i;
+ jsdouble d;
+
+ v = *vp;
+ if (JSVAL_IS_INT(v)) {
+ i = JSVAL_TO_INT(v);
+ if (i < 0)
+ *vp = JSVAL_TRUE;
+ return (uint32) i;
+ }
+ if (JSVAL_IS_DOUBLE(v)) {
+ d = *JSVAL_TO_DOUBLE(v);
+ *vp = JSVAL_TRUE;
+ } else {
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return 0;
+ *vp = JSVAL_TRUE;
+ }
+ return js_DoubleToECMAUint32(d);
+}
+
+uint32
+js_DoubleToECMAUint32(jsdouble d)
+{
+ int32 i;
+ JSBool neg;
+ jsdouble two32;
+
+ if (!JSDOUBLE_IS_FINITE(d))
+ return 0;
+
+ /*
+ * We check whether d fits int32, not uint32, as all but the ">>>" bit
+ * manipulation bytecode stores the result as int, not uint. When the
+ * result does not fit int jsval, it will be stored as a negative double.
+ */
+ i = (int32) d;
+ if ((jsdouble) i == d)
+ return (int32)i;
+
+ neg = (d < 0);
+ d = floor(neg ? -d : d);
+ d = neg ? -d : d;
+
+ two32 = 4294967296.0;
+ d = fmod(d, two32);
+
+ return (uint32) (d >= 0 ? d : d + two32);
+}
+
+int32
+js_ValueToInt32(JSContext *cx, jsval *vp)
+{
+ jsval v;
+ jsdouble d;
+
+ v = *vp;
+ if (JSVAL_IS_INT(v))
+ return JSVAL_TO_INT(v);
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return 0;
+ if (JSVAL_IS_INT(*vp))
+ return JSVAL_TO_INT(*vp);
+
+ *vp = JSVAL_TRUE;
+ if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) {
+ js_ReportValueError(cx, JSMSG_CANT_CONVERT,
+ JSDVG_SEARCH_STACK, v, NULL);
+ *vp = JSVAL_NULL;
+ return 0;
+ }
+ return (int32) floor(d + 0.5); /* Round to nearest */
+}
+
+uint16
+js_ValueToUint16(JSContext *cx, jsval *vp)
+{
+ jsdouble d;
+ uint16 u;
+ jsuint m;
+ JSBool neg;
+
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return 0;
+
+ if (JSVAL_IS_INT(*vp)) {
+ u = (uint16) JSVAL_TO_INT(*vp);
+ } else if (d == 0 || !JSDOUBLE_IS_FINITE(d)) {
+ u = (uint16) 0;
+ } else {
+ u = (uint16) d;
+ if ((jsdouble) u != d) {
+ neg = (d < 0);
+ d = floor(neg ? -d : d);
+ d = neg ? -d : d;
+ m = JS_BIT(16);
+ d = fmod(d, (double) m);
+ if (d < 0)
+ d += m;
+ u = (uint16) d;
+ }
+ }
+ *vp = INT_TO_JSVAL(u);
+ return u;
+}
+
+jsdouble
+js_DoubleToInteger(jsdouble d)
+{
+ JSBool neg;
+
+ if (d == 0)
+ return d;
+ if (!JSDOUBLE_IS_FINITE(d)) {
+ if (JSDOUBLE_IS_NaN(d))
+ return 0;
+ return d;
+ }
+ neg = (d < 0);
+ d = floor(neg ? -d : d);
+ return neg ? -d : d;
+}
+
+JSBool
+js_strtod(JSContext *cx, const jschar *s, const jschar *send,
+ const jschar **ep, jsdouble *dp)
+{
+ const jschar *s1;
+ size_t length, i;
+ char cbuf[32];
+ char *cstr, *istr, *estr;
+ JSBool negative;
+ jsdouble d;
+
+ s1 = js_SkipWhiteSpace(s, send);
+ length = send - s1;
+
+ /* Use cbuf to avoid malloc */
+ if (length >= sizeof cbuf) {
+ cstr = (char *) JS_malloc(cx, length + 1);
+ if (!cstr)
+ return JS_FALSE;
+ } else {
+ cstr = cbuf;
+ }
+
+ for (i = 0; i != length; i++) {
+ if (s1[i] >> 8)
+ break;
+ cstr[i] = (char)s1[i];
+ }
+ cstr[i] = 0;
+
+ istr = cstr;
+ if ((negative = (*istr == '-')) != 0 || *istr == '+')
+ istr++;
+ if (!strncmp(istr, js_Infinity_str, sizeof js_Infinity_str - 1)) {
+ d = *(negative ? cx->runtime->jsNegativeInfinity : cx->runtime->jsPositiveInfinity);
+ estr = istr + 8;
+ } else {
+ int err;
+ d = JS_strtod(cstr, &estr, &err);
+ if (d == HUGE_VAL)
+ d = *cx->runtime->jsPositiveInfinity;
+ else if (d == -HUGE_VAL)
+ d = *cx->runtime->jsNegativeInfinity;
+#ifdef HPUX
+ if (d == 0.0 && negative) {
+ /*
+ * "-0", "-1e-2000" come out as positive zero
+ * here on HPUX. Force a negative zero instead.
+ */
+ JSDOUBLE_HI32(d) = JSDOUBLE_HI32_SIGNBIT;
+ JSDOUBLE_LO32(d) = 0;
+ }
+#endif
+ }
+
+ i = estr - cstr;
+ if (cstr != cbuf)
+ JS_free(cx, cstr);
+ *ep = i ? s1 + i : s;
+ *dp = d;
+ return JS_TRUE;
+}
+
+struct BinaryDigitReader
+{
+ uintN base; /* Base of number; must be a power of 2 */
+ uintN digit; /* Current digit value in radix given by base */
+ uintN digitMask; /* Mask to extract the next bit from digit */
+ const jschar *digits; /* Pointer to the remaining digits */
+ const jschar *end; /* Pointer to first non-digit */
+};
+
+/* Return the next binary digit from the number or -1 if done */
+static intN GetNextBinaryDigit(struct BinaryDigitReader *bdr)
+{
+ intN bit;
+
+ if (bdr->digitMask == 0) {
+ uintN c;
+
+ if (bdr->digits == bdr->end)
+ return -1;
+
+ c = *bdr->digits++;
+ if ('0' <= c && c <= '9')
+ bdr->digit = c - '0';
+ else if ('a' <= c && c <= 'z')
+ bdr->digit = c - 'a' + 10;
+ else bdr->digit = c - 'A' + 10;
+ bdr->digitMask = bdr->base >> 1;
+ }
+ bit = (bdr->digit & bdr->digitMask) != 0;
+ bdr->digitMask >>= 1;
+ return bit;
+}
+
+JSBool
+js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
+ const jschar **ep, jsint base, jsdouble *dp)
+{
+ const jschar *s1, *start;
+ JSBool negative;
+ jsdouble value;
+
+ s1 = js_SkipWhiteSpace(s, send);
+ if (s1 == send)
+ goto no_digits;
+ if ((negative = (*s1 == '-')) != 0 || *s1 == '+') {
+ s1++;
+ if (s1 == send)
+ goto no_digits;
+ }
+
+ if (base == 0) {
+ /* No base supplied, or some base that evaluated to 0. */
+ if (*s1 == '0') {
+ /* It's either hex or octal; only increment char if str isn't '0' */
+ if (s1 + 1 != send && (s1[1] == 'X' || s1[1] == 'x')) {
+ base = 16;
+ s1 += 2;
+ if (s1 == send)
+ goto no_digits;
+ } else {
+ base = 8;
+ }
+ } else {
+ base = 10; /* Default to decimal. */
+ }
+ } else if (base == 16) {
+ /* If base is 16, ignore hex prefix. */
+ if (*s1 == '0' && s1 + 1 != send && (s1[1] == 'X' || s1[1] == 'x')) {
+ s1 += 2;
+ if (s1 == send)
+ goto no_digits;
+ }
+ }
+
+ /*
+ * Done with the preliminaries; find some prefix of the string that's
+ * a number in the given base.
+ */
+ JS_ASSERT(s1 < send);
+ start = s1;
+ value = 0.0;
+ do {
+ uintN digit;
+ jschar c = *s1;
+ if ('0' <= c && c <= '9')
+ digit = c - '0';
+ else if ('a' <= c && c <= 'z')
+ digit = c - 'a' + 10;
+ else if ('A' <= c && c <= 'Z')
+ digit = c - 'A' + 10;
+ else
+ break;
+ if (digit >= (uintN)base)
+ break;
+ value = value * base + digit;
+ } while (++s1 != send);
+
+ if (value >= 9007199254740992.0) {
+ if (base == 10) {
+ /*
+ * If we're accumulating a decimal number and the number is >=
+ * 2^53, then the result from the repeated multiply-add above may
+ * be inaccurate. Call JS_strtod to get the correct answer.
+ */
+ size_t i;
+ size_t length = s1 - start;
+ char *cstr = (char *) JS_malloc(cx, length + 1);
+ char *estr;
+ int err=0;
+
+ if (!cstr)
+ return JS_FALSE;
+ for (i = 0; i != length; i++)
+ cstr[i] = (char)start[i];
+ cstr[length] = 0;
+
+ value = JS_strtod(cstr, &estr, &err);
+ if (err == JS_DTOA_ENOMEM) {
+ JS_ReportOutOfMemory(cx);
+ JS_free(cx, cstr);
+ return JS_FALSE;
+ }
+ if (err == JS_DTOA_ERANGE && value == HUGE_VAL)
+ value = *cx->runtime->jsPositiveInfinity;
+ JS_free(cx, cstr);
+ } else if ((base & (base - 1)) == 0) {
+ /*
+ * The number may also be inaccurate for power-of-two bases. This
+ * happens if the addition in value * base + digit causes a round-
+ * down to an even least significant mantissa bit when the first
+ * dropped bit is a one. If any of the following digits in the
+ * number (which haven't been added in yet) are nonzero, then the
+ * correct action would have been to round up instead of down. An
+ * example occurs when reading the number 0x1000000000000081, which
+ * rounds to 0x1000000000000000 instead of 0x1000000000000100.
+ */
+ struct BinaryDigitReader bdr;
+ intN bit, bit2;
+ intN j;
+
+ bdr.base = base;
+ bdr.digitMask = 0;
+ bdr.digits = start;
+ bdr.end = s1;
+ value = 0.0;
+
+ /* Skip leading zeros. */
+ do {
+ bit = GetNextBinaryDigit(&bdr);
+ } while (bit == 0);
+
+ if (bit == 1) {
+ /* Gather the 53 significant bits (including the leading 1) */
+ value = 1.0;
+ for (j = 52; j; j--) {
+ bit = GetNextBinaryDigit(&bdr);
+ if (bit < 0)
+ goto done;
+ value = value*2 + bit;
+ }
+ /* bit2 is the 54th bit (the first dropped from the mantissa) */
+ bit2 = GetNextBinaryDigit(&bdr);
+ if (bit2 >= 0) {
+ jsdouble factor = 2.0;
+ intN sticky = 0; /* sticky is 1 if any bit beyond the 54th is 1 */
+ intN bit3;
+
+ while ((bit3 = GetNextBinaryDigit(&bdr)) >= 0) {
+ sticky |= bit3;
+ factor *= 2;
+ }
+ value += bit2 & (bit | sticky);
+ value *= factor;
+ }
+ done:;
+ }
+ }
+ }
+ /* We don't worry about inaccurate numbers for any other base. */
+
+ if (s1 == start) {
+ no_digits:
+ *dp = 0.0;
+ *ep = s;
+ } else {
+ *dp = negative ? -value : value;
+ *ep = s1;
+ }
+ return JS_TRUE;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsnum.h b/tools/node_modules/expresso/deps/jscoverage/js/jsnum.h
new file mode 100644
index 0000000..285e29c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsnum.h
@@ -0,0 +1,287 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsnum_h___
+#define jsnum_h___
+
+/*
+ * JS number (IEEE double) interface.
+ *
+ * JS numbers are optimistically stored in the top 31 bits of 32-bit integers,
+ * but floating point literals, results that overflow 31 bits, and division and
+ * modulus operands and results require a 64-bit IEEE double. These are GC'ed
+ * and pointed to by 32-bit jsvals on the stack and in object properties.
+ */
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * The ARM architecture supports two floating point models: VFP and FPA. When
+ * targetting FPA, doubles are mixed-endian on little endian ARMs (meaning that
+ * the high and low words are in big endian order).
+ */
+#if defined(__arm) || defined(__arm32__) || defined(__arm26__) || defined(__arm__)
+#if !defined(__VFP_FP__)
+#define FPU_IS_ARM_FPA
+#endif
+#endif
+
+typedef union jsdpun {
+ struct {
+#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
+ uint32 lo, hi;
+#else
+ uint32 hi, lo;
+#endif
+ } s;
+ uint64 u64;
+ jsdouble d;
+} jsdpun;
+
+#if (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || __GNUC__ > 2
+/*
+ * This version of the macros is safe for the alias optimizations that gcc
+ * does, but uses gcc-specific extensions.
+ */
+
+#define JSDOUBLE_HI32(x) (__extension__ ({ jsdpun u; u.d = (x); u.s.hi; }))
+#define JSDOUBLE_LO32(x) (__extension__ ({ jsdpun u; u.d = (x); u.s.lo; }))
+#define JSDOUBLE_SET_HI32(x, y) \
+ (__extension__ ({ jsdpun u; u.d = (x); u.s.hi = (y); (x) = u.d; }))
+#define JSDOUBLE_SET_LO32(x, y) \
+ (__extension__ ({ jsdpun u; u.d = (x); u.s.lo = (y); (x) = u.d; }))
+
+#else /* not or old GNUC */
+
+/*
+ * We don't know of any non-gcc compilers that perform alias optimization,
+ * so this code should work.
+ */
+
+#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
+#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1])
+#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0])
+#else
+#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0])
+#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1])
+#endif
+
+#define JSDOUBLE_SET_HI32(x, y) (JSDOUBLE_HI32(x)=(y))
+#define JSDOUBLE_SET_LO32(x, y) (JSDOUBLE_LO32(x)=(y))
+
+#endif /* not or old GNUC */
+
+#define JSDOUBLE_HI32_SIGNBIT 0x80000000
+#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
+#define JSDOUBLE_HI32_MANTMASK 0x000fffff
+
+#define JSDOUBLE_IS_NaN(x) \
+ ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \
+ (JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK)))
+
+#define JSDOUBLE_IS_INFINITE(x) \
+ ((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \
+ !JSDOUBLE_LO32(x))
+
+#define JSDOUBLE_IS_FINITE(x) \
+ ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) != JSDOUBLE_HI32_EXPMASK)
+
+#define JSDOUBLE_IS_NEGZERO(d) (JSDOUBLE_HI32(d) == JSDOUBLE_HI32_SIGNBIT && \
+ JSDOUBLE_LO32(d) == 0)
+
+/*
+ * JSDOUBLE_IS_INT first checks that d is neither NaN nor infinite, to avoid
+ * raising SIGFPE on platforms such as Alpha Linux, then (only if the cast is
+ * safe) leaves i as (jsint)d. This also avoid anomalous NaN floating point
+ * comparisons under MSVC.
+ */
+#define JSDOUBLE_IS_INT(d, i) (JSDOUBLE_IS_FINITE(d) \
+ && !JSDOUBLE_IS_NEGZERO(d) \
+ && ((d) == (i = (jsint)(d))))
+
+#if defined(XP_WIN)
+#define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN) \
+ ((JSDOUBLE_IS_NaN(LVAL) || JSDOUBLE_IS_NaN(RVAL)) \
+ ? (IFNAN) \
+ : (LVAL) OP (RVAL))
+#else
+#define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN) ((LVAL) OP (RVAL))
+#endif
+
+extern jsdouble js_NaN;
+
+/* Initialize number constants and runtime state for the first context. */
+extern JSBool
+js_InitRuntimeNumberState(JSContext *cx);
+
+extern void
+js_TraceRuntimeNumberState(JSTracer *trc);
+
+extern void
+js_FinishRuntimeNumberState(JSContext *cx);
+
+/* Initialize the Number class, returning its prototype object. */
+extern JSClass js_NumberClass;
+
+extern JSObject *
+js_InitNumberClass(JSContext *cx, JSObject *obj);
+
+/*
+ * String constants for global function names, used in jsapi.c and jsnum.c.
+ */
+extern const char js_Infinity_str[];
+extern const char js_NaN_str[];
+extern const char js_isNaN_str[];
+extern const char js_isFinite_str[];
+extern const char js_parseFloat_str[];
+extern const char js_parseInt_str[];
+
+/*
+ * vp must be a root.
+ */
+extern JSBool
+js_NewNumberInRootedValue(JSContext *cx, jsdouble d, jsval *vp);
+
+/* Convert a number to a GC'ed string. */
+extern JSString * JS_FASTCALL
+js_NumberToString(JSContext *cx, jsdouble d);
+
+/*
+ * Convert int to C string. The buf must be big enough for MIN_INT to fit
+ * including '-' and '\0'.
+ */
+char *
+js_IntToCString(jsint i, jsint base, char *buf, size_t bufSize);
+
+/*
+ * Convert a number to C string. The buf must be at least
+ * DTOSTR_STANDARD_BUFFER_SIZE.
+ */
+char *
+js_NumberToCString(JSContext *cx, jsdouble d, jsint base, char *buf, size_t bufSize);
+
+/*
+ * Convert a value to a number. On exit JSVAL_IS_NULL(*vp) iff there was an
+ * error. If on exit JSVAL_IS_NUMBER(*vp), then *vp holds the jsval that
+ * matches the result. Otherwise *vp is JSVAL_TRUE indicating that the jsval
+ * for result has to be created explicitly using, for example, the
+ * js_NewNumberInRootedValue function.
+ */
+extern jsdouble
+js_ValueToNumber(JSContext *cx, jsval* vp);
+
+/*
+ * Convert a value to an int32 or uint32, according to the ECMA rules for
+ * ToInt32 and ToUint32. On exit JSVAL_IS_NULL(*vp) iff there was an error. If
+ * on exit JSVAL_IS_INT(*vp), then *vp holds the jsval matching the result.
+ * Otherwise *vp is JSVAL_TRUE indicating that the jsval for result has to be
+ * created explicitly using, for example, the js_NewNumberInRootedValue
+ * function.
+ */
+extern int32
+js_ValueToECMAInt32(JSContext *cx, jsval *vp);
+
+extern uint32
+js_ValueToECMAUint32(JSContext *cx, jsval *vp);
+
+/*
+ * Specialized ToInt32 and ToUint32 converters for doubles.
+ */
+extern int32
+js_DoubleToECMAInt32(jsdouble d);
+
+extern uint32
+js_DoubleToECMAUint32(jsdouble d);
+
+/*
+ * Convert a value to a number, then to an int32 if it fits by rounding to
+ * nearest; but failing with an error report if the double is out of range
+ * or unordered. On exit JSVAL_IS_NULL(*vp) iff there was an error. If on exit
+ * JSVAL_IS_INT(*vp), then *vp holds the jsval matching the result. Otherwise
+ * *vp is JSVAL_TRUE indicating that the jsval for result has to be created
+ * explicitly using, for example, the js_NewNumberInRootedValue function.
+ */
+extern int32
+js_ValueToInt32(JSContext *cx, jsval *vp);
+
+/*
+ * Convert a value to a number, then to a uint16 according to the ECMA rules
+ * for ToUint16. On exit JSVAL_IS_NULL(*vp) iff there was an error, otherwise
+ * vp is jsval matching the result.
+ */
+extern uint16
+js_ValueToUint16(JSContext *cx, jsval *vp);
+
+/*
+ * Convert a jsdouble to an integral number, stored in a jsdouble.
+ * If d is NaN, return 0. If d is an infinity, return it without conversion.
+ */
+extern jsdouble
+js_DoubleToInteger(jsdouble d);
+
+/*
+ * Similar to strtod except that it replaces overflows with infinities of the
+ * correct sign, and underflows with zeros of the correct sign. Guaranteed to
+ * return the closest double number to the given input in dp.
+ *
+ * Also allows inputs of the form [+|-]Infinity, which produce an infinity of
+ * the appropriate sign. The case of the "Infinity" string must match exactly.
+ * If the string does not contain a number, set *ep to s and return 0.0 in dp.
+ * Return false if out of memory.
+ */
+extern JSBool
+js_strtod(JSContext *cx, const jschar *s, const jschar *send,
+ const jschar **ep, jsdouble *dp);
+
+/*
+ * Similar to strtol except that it handles integers of arbitrary size.
+ * Guaranteed to return the closest double number to the given input when radix
+ * is 10 or a power of 2. Callers may see round-off errors for very large
+ * numbers of a different radix than 10 or a power of 2.
+ *
+ * If the string does not contain a number, set *ep to s and return 0.0 in dp.
+ * Return false if out of memory.
+ */
+extern JSBool
+js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
+ const jschar **ep, jsint radix, jsdouble *dp);
+
+JS_END_EXTERN_C
+
+#endif /* jsnum_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsobj.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsobj.cpp
new file mode 100644
index 0000000..4e7f80a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsobj.cpp
@@ -0,0 +1,5563 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS object implementation.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsbit.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jshash.h" /* Added by JSIFY */
+#include "jsdhash.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsdbgapi.h" /* whether or not JS_HAS_OBJ_WATCHPOINT */
+#include "jsstaticcheck.h"
+
+#if JS_HAS_GENERATORS
+#include "jsiter.h"
+#endif
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#if JS_HAS_XDR
+#include "jsxdrapi.h"
+#endif
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+#include "jsdtracef.h"
+#endif
+
+#include "jsautooplen.h"
+
+#ifdef JS_THREADSAFE
+#define NATIVE_DROP_PROPERTY js_DropProperty
+
+extern void
+js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop);
+#else
+#define NATIVE_DROP_PROPERTY NULL
+#endif
+
+JS_FRIEND_DATA(JSObjectOps) js_ObjectOps = {
+ js_NewObjectMap, js_DestroyObjectMap,
+ js_LookupProperty, js_DefineProperty,
+ js_GetProperty, js_SetProperty,
+ js_GetAttributes, js_SetAttributes,
+ js_DeleteProperty, js_DefaultValue,
+ js_Enumerate, js_CheckAccess,
+ NULL, NATIVE_DROP_PROPERTY,
+ js_Call, js_Construct,
+ NULL, js_HasInstance,
+ js_SetProtoOrParent, js_SetProtoOrParent,
+ js_TraceObject, js_Clear,
+ js_GetRequiredSlot, js_SetRequiredSlot
+};
+
+JSClass js_ObjectClass = {
+ js_Object_str,
+ JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+#if JS_HAS_OBJ_PROTO_PROP
+
+static JSBool
+obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+static JSBool
+obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+static JSBool
+obj_getCount(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+static JSPropertySpec object_props[] = {
+ /* These two must come first; see object_props[slot].name usage below. */
+ {js_proto_str, JSSLOT_PROTO, JSPROP_PERMANENT|JSPROP_SHARED,
+ obj_getSlot, obj_setSlot},
+ {js_parent_str,JSSLOT_PARENT,JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED,
+ obj_getSlot, obj_setSlot},
+ {js_count_str, 0, JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED,
+ obj_getCount, NULL},
+ {0,0,0,0,0}
+};
+
+/* NB: JSSLOT_PROTO and JSSLOT_PARENT are already indexes into object_props. */
+#define JSSLOT_COUNT 2
+
+static JSBool
+ReportStrictSlot(JSContext *cx, uint32 slot)
+{
+ if (slot == JSSLOT_PROTO)
+ return JS_TRUE;
+ return JS_ReportErrorFlagsAndNumber(cx,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ js_GetErrorMessage, NULL,
+ JSMSG_DEPRECATED_USAGE,
+ object_props[slot].name);
+}
+
+static JSBool
+obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ uint32 slot;
+ jsid propid;
+ JSAccessMode mode;
+ uintN attrs;
+ JSObject *pobj;
+ JSClass *clasp;
+ JSExtendedClass *xclasp;
+
+ slot = (uint32) JSVAL_TO_INT(id);
+ if (id == INT_TO_JSVAL(JSSLOT_PROTO)) {
+ propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
+ mode = JSACC_PROTO;
+ } else {
+ propid = ATOM_TO_JSID(cx->runtime->atomState.parentAtom);
+ mode = JSACC_PARENT;
+ }
+
+ /* Let OBJ_CHECK_ACCESS get the slot's value, based on the access mode. */
+ if (!OBJ_CHECK_ACCESS(cx, obj, propid, mode, vp, &attrs))
+ return JS_FALSE;
+
+ pobj = JSVAL_TO_OBJECT(*vp);
+ if (pobj) {
+ clasp = OBJ_GET_CLASS(cx, pobj);
+ if (clasp == &js_CallClass || clasp == &js_BlockClass) {
+ /* Censor activations and lexical scopes per ECMA-262. */
+ *vp = JSVAL_NULL;
+ } else if (clasp->flags & JSCLASS_IS_EXTENDED) {
+ xclasp = (JSExtendedClass *) clasp;
+ if (xclasp->outerObject) {
+ pobj = xclasp->outerObject(cx, pobj);
+ if (!pobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(pobj);
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSObject *pobj;
+ uint32 slot;
+ jsid propid;
+ uintN attrs;
+
+ if (!JSVAL_IS_OBJECT(*vp))
+ return JS_TRUE;
+ pobj = JSVAL_TO_OBJECT(*vp);
+
+ if (pobj) {
+ /*
+ * Innerize pobj here to avoid sticking unwanted properties on the
+ * outer object. This ensures that any with statements only grant
+ * access to the inner object.
+ */
+ OBJ_TO_INNER_OBJECT(cx, pobj);
+ if (!pobj)
+ return JS_FALSE;
+ }
+ slot = (uint32) JSVAL_TO_INT(id);
+ if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, slot))
+ return JS_FALSE;
+
+ /* __parent__ is readonly and permanent, only __proto__ may be set. */
+ propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
+ if (!OBJ_CHECK_ACCESS(cx, obj, propid,
+ (JSAccessMode)(JSACC_PROTO|JSACC_WRITE), vp,
+ &attrs)) {
+ return JS_FALSE;
+ }
+
+ return js_SetProtoOrParent(cx, obj, slot, pobj);
+}
+
+static JSBool
+obj_getCount(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsval iter_state;
+ jsid num_properties;
+ JSBool ok;
+
+ if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, JSSLOT_COUNT))
+ return JS_FALSE;
+
+ /* Get the number of properties to enumerate. */
+ iter_state = JSVAL_NULL;
+ ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties);
+ if (!ok)
+ goto out;
+
+ if (!JSVAL_IS_INT(num_properties)) {
+ JS_ASSERT(0);
+ *vp = JSVAL_ZERO;
+ goto out;
+ }
+ *vp = num_properties;
+
+out:
+ if (iter_state != JSVAL_NULL)
+ ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0);
+ return ok;
+}
+
+#else /* !JS_HAS_OBJ_PROTO_PROP */
+
+#define object_props NULL
+
+#endif /* !JS_HAS_OBJ_PROTO_PROP */
+
+JSBool
+js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj)
+{
+ JSSetSlotRequest ssr;
+ JSRuntime *rt;
+
+ /* Optimize the null case to avoid the unnecessary overhead of js_GC. */
+ if (!pobj) {
+ JS_LOCK_OBJ(cx, obj);
+ if (slot == JSSLOT_PROTO && !js_GetMutableScope(cx, obj)) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+ }
+ LOCKED_OBJ_SET_SLOT(obj, slot, JSVAL_NULL);
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_TRUE;
+ }
+
+ ssr.obj = obj;
+ ssr.pobj = pobj;
+ ssr.slot = (uint16) slot;
+ ssr.errnum = (uint16) JSMSG_NOT_AN_ERROR;
+
+ rt = cx->runtime;
+ JS_LOCK_GC(rt);
+ ssr.next = rt->setSlotRequests;
+ rt->setSlotRequests = &ssr;
+ for (;;) {
+ js_GC(cx, GC_SET_SLOT_REQUEST);
+ JS_UNLOCK_GC(rt);
+ if (!rt->setSlotRequests)
+ break;
+ JS_LOCK_GC(rt);
+ }
+
+ if (ssr.errnum != JSMSG_NOT_AN_ERROR) {
+ if (ssr.errnum == JSMSG_OUT_OF_MEMORY) {
+ JS_ReportOutOfMemory(cx);
+ } else {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, ssr.errnum,
+#if JS_HAS_OBJ_PROTO_PROP
+ object_props[slot].name
+#else
+ (slot == JSSLOT_PROTO) ? js_proto_str
+ : js_parent_str
+#endif
+ );
+ }
+ return JS_FALSE;
+ }
+
+ // Maintain the "any Array prototype has indexed properties hazard" flag.
+ if (slot == JSSLOT_PROTO &&
+ OBJ_IS_ARRAY(cx, pobj) &&
+ pobj->fslots[JSSLOT_ARRAY_LENGTH] != 0) {
+ rt->anyArrayProtoHasElement = JS_TRUE;
+ }
+ return JS_TRUE;
+}
+
+static JSHashNumber
+js_hash_object(const void *key)
+{
+ return (JSHashNumber)JS_PTR_TO_UINT32(key) >> JSVAL_TAGBITS;
+}
+
+static JSHashEntry *
+MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap)
+{
+ JSSharpObjectMap *map;
+ JSHashTable *table;
+ JSHashNumber hash;
+ JSHashEntry **hep, *he;
+ jsatomid sharpid;
+ JSIdArray *ida;
+ JSBool ok;
+ jsint i, length;
+ jsid id;
+#if JS_HAS_GETTER_SETTER
+ JSObject *obj2;
+ JSProperty *prop;
+ uintN attrs;
+#endif
+ jsval val;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ map = &cx->sharpObjectMap;
+ table = map->table;
+ hash = js_hash_object(obj);
+ hep = JS_HashTableRawLookup(table, hash, obj);
+ he = *hep;
+ if (!he) {
+ sharpid = 0;
+ he = JS_HashTableRawAdd(table, hep, hash, obj,
+ JS_UINT32_TO_PTR(sharpid));
+ if (!he) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+
+ /*
+ * Increment map->depth to protect js_EnterSharpObject from reentering
+ * itself badly. Without this fix, if we reenter the basis case where
+ * map->depth == 0, when unwinding the inner call we will destroy the
+ * newly-created hash table and crash.
+ */
+ ++map->depth;
+ ida = JS_Enumerate(cx, obj);
+ --map->depth;
+ if (!ida)
+ return NULL;
+
+ ok = JS_TRUE;
+ for (i = 0, length = ida->length; i < length; i++) {
+ id = ida->vector[i];
+#if JS_HAS_GETTER_SETTER
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
+ if (!ok)
+ break;
+ if (!prop)
+ continue;
+ ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
+ if (ok) {
+ if (OBJ_IS_NATIVE(obj2) &&
+ (attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
+ val = JSVAL_NULL;
+ if (attrs & JSPROP_GETTER)
+ val = (jsval) ((JSScopeProperty*)prop)->getter;
+ if (attrs & JSPROP_SETTER) {
+ if (val != JSVAL_NULL) {
+ /* Mark the getter, then set val to setter. */
+ ok = (MarkSharpObjects(cx, JSVAL_TO_OBJECT(val),
+ NULL)
+ != NULL);
+ }
+ val = (jsval) ((JSScopeProperty*)prop)->setter;
+ }
+ } else {
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val);
+ }
+ }
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+#else
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val);
+#endif
+ if (!ok)
+ break;
+ if (!JSVAL_IS_PRIMITIVE(val) &&
+ !MarkSharpObjects(cx, JSVAL_TO_OBJECT(val), NULL)) {
+ ok = JS_FALSE;
+ break;
+ }
+ }
+ if (!ok || !idap)
+ JS_DestroyIdArray(cx, ida);
+ if (!ok)
+ return NULL;
+ } else {
+ sharpid = JS_PTR_TO_UINT32(he->value);
+ if (sharpid == 0) {
+ sharpid = ++map->sharpgen << SHARP_ID_SHIFT;
+ he->value = JS_UINT32_TO_PTR(sharpid);
+ }
+ ida = NULL;
+ }
+ if (idap)
+ *idap = ida;
+ return he;
+}
+
+JSHashEntry *
+js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap,
+ jschar **sp)
+{
+ JSSharpObjectMap *map;
+ JSHashTable *table;
+ JSIdArray *ida;
+ JSHashNumber hash;
+ JSHashEntry *he, **hep;
+ jsatomid sharpid;
+ char buf[20];
+ size_t len;
+
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_ENTER_SHARP))
+ return NULL;
+
+ /* Set to null in case we return an early error. */
+ *sp = NULL;
+ map = &cx->sharpObjectMap;
+ table = map->table;
+ if (!table) {
+ table = JS_NewHashTable(8, js_hash_object, JS_CompareValues,
+ JS_CompareValues, NULL, NULL);
+ if (!table) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ map->table = table;
+ JS_KEEP_ATOMS(cx->runtime);
+ }
+
+ /* From this point the control must flow either through out: or bad:. */
+ ida = NULL;
+ if (map->depth == 0) {
+ he = MarkSharpObjects(cx, obj, &ida);
+ if (!he)
+ goto bad;
+ JS_ASSERT((JS_PTR_TO_UINT32(he->value) & SHARP_BIT) == 0);
+ if (!idap) {
+ JS_DestroyIdArray(cx, ida);
+ ida = NULL;
+ }
+ } else {
+ hash = js_hash_object(obj);
+ hep = JS_HashTableRawLookup(table, hash, obj);
+ he = *hep;
+
+ /*
+ * It's possible that the value of a property has changed from the
+ * first time the object's properties are traversed (when the property
+ * ids are entered into the hash table) to the second (when they are
+ * converted to strings), i.e., the OBJ_GET_PROPERTY() call is not
+ * idempotent.
+ */
+ if (!he) {
+ he = JS_HashTableRawAdd(table, hep, hash, obj, NULL);
+ if (!he) {
+ JS_ReportOutOfMemory(cx);
+ goto bad;
+ }
+ sharpid = 0;
+ goto out;
+ }
+ }
+
+ sharpid = JS_PTR_TO_UINT32(he->value);
+ if (sharpid != 0) {
+ len = JS_snprintf(buf, sizeof buf, "#%u%c",
+ sharpid >> SHARP_ID_SHIFT,
+ (sharpid & SHARP_BIT) ? '#' : '=');
+ *sp = js_InflateString(cx, buf, &len);
+ if (!*sp) {
+ if (ida)
+ JS_DestroyIdArray(cx, ida);
+ goto bad;
+ }
+ }
+
+out:
+ JS_ASSERT(he);
+ if ((sharpid & SHARP_BIT) == 0) {
+ if (idap && !ida) {
+ ida = JS_Enumerate(cx, obj);
+ if (!ida) {
+ if (*sp) {
+ JS_free(cx, *sp);
+ *sp = NULL;
+ }
+ goto bad;
+ }
+ }
+ map->depth++;
+ }
+
+ if (idap)
+ *idap = ida;
+ return he;
+
+bad:
+ /* Clean up the sharpObjectMap table on outermost error. */
+ if (map->depth == 0) {
+ JS_UNKEEP_ATOMS(cx->runtime);
+ map->sharpgen = 0;
+ JS_HashTableDestroy(map->table);
+ map->table = NULL;
+ }
+ return NULL;
+}
+
+void
+js_LeaveSharpObject(JSContext *cx, JSIdArray **idap)
+{
+ JSSharpObjectMap *map;
+ JSIdArray *ida;
+
+ map = &cx->sharpObjectMap;
+ JS_ASSERT(map->depth > 0);
+ if (--map->depth == 0) {
+ JS_UNKEEP_ATOMS(cx->runtime);
+ map->sharpgen = 0;
+ JS_HashTableDestroy(map->table);
+ map->table = NULL;
+ }
+ if (idap) {
+ ida = *idap;
+ if (ida) {
+ JS_DestroyIdArray(cx, ida);
+ *idap = NULL;
+ }
+ }
+}
+
+static intN
+gc_sharp_table_entry_marker(JSHashEntry *he, intN i, void *arg)
+{
+ JS_CALL_OBJECT_TRACER((JSTracer *)arg, (JSObject *)he->key,
+ "sharp table entry");
+ return JS_DHASH_NEXT;
+}
+
+void
+js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map)
+{
+ JS_ASSERT(map->depth > 0);
+ JS_ASSERT(map->table);
+
+ /*
+ * During recursive calls to MarkSharpObjects a non-native object or
+ * object with a custom getProperty method can potentially return an
+ * unrooted value or even cut from the object graph an argument of one of
+ * MarkSharpObjects recursive invocations. So we must protect map->table
+ * entries against GC.
+ *
+ * We can not simply use JSTempValueRooter to mark the obj argument of
+ * MarkSharpObjects during recursion as we have to protect *all* entries
+ * in JSSharpObjectMap including those that contains otherwise unreachable
+ * objects just allocated through custom getProperty. Otherwise newer
+ * allocations can re-use the address of an object stored in the hashtable
+ * confusing js_EnterSharpObject. So to address the problem we simply
+ * mark all objects from map->table.
+ *
+ * An alternative "proper" solution is to use JSTempValueRooter in
+ * MarkSharpObjects with code to remove during finalization entries
+ * with otherwise unreachable objects. But this is way too complex
+ * to justify spending efforts.
+ */
+ JS_HashTableEnumerateEntries(map->table, gc_sharp_table_entry_marker, trc);
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+obj_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSBool ok, outermost;
+ JSObject *obj;
+ JSHashEntry *he;
+ JSIdArray *ida;
+ jschar *chars, *ochars, *vsharp;
+ const jschar *idstrchars, *vchars;
+ size_t nchars, idstrlength, gsoplength, vlength, vsharplength, curlen;
+ const char *comma;
+ jsint i, j, length, valcnt;
+ jsid id;
+#if JS_HAS_GETTER_SETTER
+ JSObject *obj2;
+ JSProperty *prop;
+ uintN attrs;
+#endif
+ jsval *val;
+ jsval localroot[4] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
+ JSTempValueRooter tvr;
+ JSString *gsopold[2];
+ JSString *gsop[2];
+ JSString *idstr, *valstr, *str;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_TEMP_ROOT(cx, 4, localroot, &tvr);
+
+ /* If outermost, we need parentheses to be an expression, not a block. */
+ outermost = (cx->sharpObjectMap.depth == 0);
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !(he = js_EnterSharpObject(cx, obj, &ida, &chars))) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ if (IS_SHARP(he)) {
+ /*
+ * We didn't enter -- obj is already "sharp", meaning we've visited it
+ * already in our depth first search, and therefore chars contains a
+ * string of the form "#n#".
+ */
+ JS_ASSERT(!ida);
+#if JS_HAS_SHARP_VARS
+ nchars = js_strlen(chars);
+#else
+ chars[0] = '{';
+ chars[1] = '}';
+ chars[2] = 0;
+ nchars = 2;
+#endif
+ goto make_string;
+ }
+ JS_ASSERT(ida);
+ ok = JS_TRUE;
+
+ if (!chars) {
+ /* If outermost, allocate 4 + 1 for "({})" and the terminator. */
+ chars = (jschar *) malloc(((outermost ? 4 : 2) + 1) * sizeof(jschar));
+ nchars = 0;
+ if (!chars)
+ goto error;
+ if (outermost)
+ chars[nchars++] = '(';
+ } else {
+ /* js_EnterSharpObject returned a string of the form "#n=" in chars. */
+ MAKE_SHARP(he);
+ nchars = js_strlen(chars);
+ chars = (jschar *)
+ realloc((ochars = chars), (nchars + 2 + 1) * sizeof(jschar));
+ if (!chars) {
+ free(ochars);
+ goto error;
+ }
+ if (outermost) {
+ /*
+ * No need for parentheses around the whole shebang, because #n=
+ * unambiguously begins an object initializer, and never a block
+ * statement.
+ */
+ outermost = JS_FALSE;
+ }
+ }
+
+ chars[nchars++] = '{';
+
+ comma = NULL;
+
+ /*
+ * We have four local roots for cooked and raw value GC safety. Hoist the
+ * "localroot + 2" out of the loop using the val local, which refers to
+ * the raw (unconverted, "uncooked") values.
+ */
+ val = localroot + 2;
+
+ for (i = 0, length = ida->length; i < length; i++) {
+ JSBool idIsLexicalIdentifier, needOldStyleGetterSetter;
+
+ /* Get strings for id and value and GC-root them via vp. */
+ id = ida->vector[i];
+
+#if JS_HAS_GETTER_SETTER
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
+ if (!ok)
+ goto error;
+#endif
+
+ /*
+ * Convert id to a jsval and then to a string. Decide early whether we
+ * prefer get/set or old getter/setter syntax.
+ */
+ idstr = js_ValueToString(cx, ID_TO_VALUE(id));
+ if (!idstr) {
+ ok = JS_FALSE;
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ goto error;
+ }
+ *vp = STRING_TO_JSVAL(idstr); /* local root */
+ idIsLexicalIdentifier = js_IsIdentifier(idstr);
+ needOldStyleGetterSetter =
+ !idIsLexicalIdentifier ||
+ js_CheckKeyword(JSSTRING_CHARS(idstr),
+ JSSTRING_LENGTH(idstr)) != TOK_EOF;
+
+#if JS_HAS_GETTER_SETTER
+
+ valcnt = 0;
+ if (prop) {
+ ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
+ if (!ok) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ goto error;
+ }
+ if (OBJ_IS_NATIVE(obj2) &&
+ (attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
+ if (attrs & JSPROP_GETTER) {
+ val[valcnt] = (jsval) ((JSScopeProperty *)prop)->getter;
+ gsopold[valcnt] =
+ ATOM_TO_STRING(cx->runtime->atomState.getterAtom);
+ gsop[valcnt] =
+ ATOM_TO_STRING(cx->runtime->atomState.getAtom);
+
+ valcnt++;
+ }
+ if (attrs & JSPROP_SETTER) {
+ val[valcnt] = (jsval) ((JSScopeProperty *)prop)->setter;
+ gsopold[valcnt] =
+ ATOM_TO_STRING(cx->runtime->atomState.setterAtom);
+ gsop[valcnt] =
+ ATOM_TO_STRING(cx->runtime->atomState.setAtom);
+
+ valcnt++;
+ }
+ } else {
+ valcnt = 1;
+ gsop[0] = NULL;
+ gsopold[0] = NULL;
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
+ }
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+
+#else /* !JS_HAS_GETTER_SETTER */
+
+ /*
+ * We simplify the source code at the price of minor dead code bloat in
+ * the ECMA version (for testing only, see jsversion.h). The null
+ * default values in gsop[j] suffice to disable non-ECMA getter and
+ * setter code.
+ */
+ valcnt = 1;
+ gsop[0] = NULL;
+ gsopold[0] = NULL;
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
+
+#endif /* !JS_HAS_GETTER_SETTER */
+
+ if (!ok)
+ goto error;
+
+ /*
+ * If id is a string that's not an identifier, then it needs to be
+ * quoted. Also, negative integer ids must be quoted.
+ */
+ if (JSID_IS_ATOM(id)
+ ? !idIsLexicalIdentifier
+ : (!JSID_IS_INT(id) || JSID_TO_INT(id) < 0)) {
+ idstr = js_QuoteString(cx, idstr, (jschar)'\'');
+ if (!idstr) {
+ ok = JS_FALSE;
+ goto error;
+ }
+ *vp = STRING_TO_JSVAL(idstr); /* local root */
+ }
+ JSSTRING_CHARS_AND_LENGTH(idstr, idstrchars, idstrlength);
+
+ for (j = 0; j < valcnt; j++) {
+ /* Convert val[j] to its canonical source form. */
+ valstr = js_ValueToSource(cx, val[j]);
+ if (!valstr) {
+ ok = JS_FALSE;
+ goto error;
+ }
+ localroot[j] = STRING_TO_JSVAL(valstr); /* local root */
+ JSSTRING_CHARS_AND_LENGTH(valstr, vchars, vlength);
+
+ if (vchars[0] == '#')
+ needOldStyleGetterSetter = JS_TRUE;
+
+ if (needOldStyleGetterSetter)
+ gsop[j] = gsopold[j];
+
+ /* If val[j] is a non-sharp object, consider sharpening it. */
+ vsharp = NULL;
+ vsharplength = 0;
+#if JS_HAS_SHARP_VARS
+ if (!JSVAL_IS_PRIMITIVE(val[j]) && vchars[0] != '#') {
+ he = js_EnterSharpObject(cx, JSVAL_TO_OBJECT(val[j]), NULL,
+ &vsharp);
+ if (!he) {
+ ok = JS_FALSE;
+ goto error;
+ }
+ if (IS_SHARP(he)) {
+ vchars = vsharp;
+ vlength = js_strlen(vchars);
+ needOldStyleGetterSetter = JS_TRUE;
+ gsop[j] = gsopold[j];
+ } else {
+ if (vsharp) {
+ vsharplength = js_strlen(vsharp);
+ MAKE_SHARP(he);
+ needOldStyleGetterSetter = JS_TRUE;
+ gsop[j] = gsopold[j];
+ }
+ js_LeaveSharpObject(cx, NULL);
+ }
+ }
+#endif
+
+#ifndef OLD_GETTER_SETTER
+ /*
+ * Remove '(function ' from the beginning of valstr and ')' from the
+ * end so that we can put "get" in front of the function definition.
+ */
+ if (gsop[j] && VALUE_IS_FUNCTION(cx, val[j]) &&
+ !needOldStyleGetterSetter) {
+ JSFunction *fun = JS_ValueToFunction(cx, val[j]);
+ const jschar *start = vchars;
+ const jschar *end = vchars + vlength;
+
+ uint8 parenChomp = 0;
+ if (vchars[0] == '(') {
+ vchars++;
+ parenChomp = 1;
+ }
+
+ /*
+ * Try to jump "getter" or "setter" keywords, if we suspect
+ * they might appear here. This code can be confused by people
+ * defining Function.prototype.toString, so let's be cautious.
+ */
+ if (JSFUN_GETTER_TEST(fun->flags) ||
+ JSFUN_SETTER_TEST(fun->flags)) { /* skip "getter/setter" */
+ const jschar *tmp = js_strchr_limit(vchars, ' ', end);
+ if (tmp)
+ vchars = tmp + 1;
+ }
+
+ /* Try to jump "function" keyword. */
+ if (vchars)
+ vchars = js_strchr_limit(vchars, ' ', end);
+
+ if (vchars) {
+ if (*vchars == ' ')
+ vchars++;
+ vlength = end - vchars - parenChomp;
+ } else {
+ gsop[j] = NULL;
+ vchars = start;
+ }
+ }
+#else
+ needOldStyleGetterSetter = JS_TRUE;
+ gsop[j] = gsopold[j];
+#endif
+
+#define SAFE_ADD(n) \
+ JS_BEGIN_MACRO \
+ size_t n_ = (n); \
+ curlen += n_; \
+ if (curlen < n_) \
+ goto overflow; \
+ JS_END_MACRO
+
+ curlen = nchars;
+ if (comma)
+ SAFE_ADD(2);
+ SAFE_ADD(idstrlength + 1);
+ if (gsop[j])
+ SAFE_ADD(JSSTRING_LENGTH(gsop[j]) + 1);
+ SAFE_ADD(vsharplength);
+ SAFE_ADD(vlength);
+ /* Account for the trailing null. */
+ SAFE_ADD((outermost ? 2 : 1) + 1);
+#undef SAFE_ADD
+
+ if (curlen > (size_t)-1 / sizeof(jschar))
+ goto overflow;
+
+ /* Allocate 1 + 1 at end for closing brace and terminating 0. */
+ chars = (jschar *)
+ realloc((ochars = chars), curlen * sizeof(jschar));
+ if (!chars) {
+ /* Save code space on error: let JS_free ignore null vsharp. */
+ JS_free(cx, vsharp);
+ free(ochars);
+ goto error;
+ }
+
+ if (comma) {
+ chars[nchars++] = comma[0];
+ chars[nchars++] = comma[1];
+ }
+ comma = ", ";
+
+ if (needOldStyleGetterSetter) {
+ js_strncpy(&chars[nchars], idstrchars, idstrlength);
+ nchars += idstrlength;
+ if (gsop[j]) {
+ chars[nchars++] = ' ';
+ gsoplength = JSSTRING_LENGTH(gsop[j]);
+ js_strncpy(&chars[nchars], JSSTRING_CHARS(gsop[j]),
+ gsoplength);
+ nchars += gsoplength;
+ }
+ chars[nchars++] = ':';
+ } else { /* New style "decompilation" */
+ if (gsop[j]) {
+ gsoplength = JSSTRING_LENGTH(gsop[j]);
+ js_strncpy(&chars[nchars], JSSTRING_CHARS(gsop[j]),
+ gsoplength);
+ nchars += gsoplength;
+ chars[nchars++] = ' ';
+ }
+ js_strncpy(&chars[nchars], idstrchars, idstrlength);
+ nchars += idstrlength;
+ /* Extraneous space after id here will be extracted later */
+ chars[nchars++] = gsop[j] ? ' ' : ':';
+ }
+
+ if (vsharplength) {
+ js_strncpy(&chars[nchars], vsharp, vsharplength);
+ nchars += vsharplength;
+ }
+ js_strncpy(&chars[nchars], vchars, vlength);
+ nchars += vlength;
+
+ if (vsharp)
+ JS_free(cx, vsharp);
+ }
+ }
+
+ chars[nchars++] = '}';
+ if (outermost)
+ chars[nchars++] = ')';
+ chars[nchars] = 0;
+
+ error:
+ js_LeaveSharpObject(cx, &ida);
+
+ if (!ok) {
+ if (chars)
+ free(chars);
+ goto out;
+ }
+
+ if (!chars) {
+ JS_ReportOutOfMemory(cx);
+ ok = JS_FALSE;
+ goto out;
+ }
+ make_string:
+ str = js_NewString(cx, chars, nchars);
+ if (!str) {
+ free(chars);
+ ok = JS_FALSE;
+ goto out;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ ok = JS_TRUE;
+ out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+
+ overflow:
+ JS_free(cx, vsharp);
+ free(chars);
+ chars = NULL;
+ goto error;
+}
+#endif /* JS_HAS_TOSOURCE */
+
+static JSBool
+obj_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jschar *chars;
+ size_t nchars;
+ const char *clazz, *prefix;
+ JSString *str;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ obj = js_GetWrappedObject(cx, obj);
+ clazz = OBJ_GET_CLASS(cx, obj)->name;
+ nchars = 9 + strlen(clazz); /* 9 for "[object ]" */
+ chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+
+ prefix = "[object ";
+ nchars = 0;
+ while ((chars[nchars] = (jschar)*prefix) != 0)
+ nchars++, prefix++;
+ while ((chars[nchars] = (jschar)*clazz) != 0)
+ nchars++, clazz++;
+ chars[nchars++] = ']';
+ chars[nchars] = 0;
+
+ str = js_NewString(cx, chars, nchars);
+ if (!str) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+obj_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval thisv;
+ JSString *str;
+
+ thisv = JS_THIS(cx, vp);
+ if (JSVAL_IS_NULL(thisv))
+ return JS_FALSE;
+
+ str = js_ValueToString(cx, thisv);
+ if (!str)
+ return JS_FALSE;
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+obj_valueOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ *vp = JS_THIS(cx, vp);
+ return !JSVAL_IS_NULL(*vp);
+}
+
+/*
+ * Check whether principals subsumes scopeobj's principals, and return true
+ * if so (or if scopeobj has no principals, for backward compatibility with
+ * the JS API, which does not require principals), and false otherwise.
+ */
+JSBool
+js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj,
+ JSPrincipals *principals, JSAtom *caller)
+{
+ JSSecurityCallbacks *callbacks;
+ JSPrincipals *scopePrincipals;
+ const char *callerstr;
+
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks && callbacks->findObjectPrincipals) {
+ scopePrincipals = callbacks->findObjectPrincipals(cx, scopeobj);
+ if (!principals || !scopePrincipals ||
+ !principals->subsume(principals, scopePrincipals)) {
+ callerstr = js_AtomToPrintableString(cx, caller);
+ if (!callerstr)
+ return JS_FALSE;
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_INDIRECT_CALL, callerstr);
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+JSObject *
+js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller)
+{
+ JSClass *clasp;
+ JSExtendedClass *xclasp;
+ JSObject *inner;
+
+ if (!scopeobj)
+ goto bad;
+
+ OBJ_TO_INNER_OBJECT(cx, scopeobj);
+ if (!scopeobj)
+ return NULL;
+
+ inner = scopeobj;
+
+ /* XXX This is an awful gross hack. */
+ while (scopeobj) {
+ clasp = OBJ_GET_CLASS(cx, scopeobj);
+ if (clasp->flags & JSCLASS_IS_EXTENDED) {
+ xclasp = (JSExtendedClass*)clasp;
+ if (xclasp->innerObject &&
+ xclasp->innerObject(cx, scopeobj) != scopeobj) {
+ goto bad;
+ }
+ }
+
+ scopeobj = OBJ_GET_PARENT(cx, scopeobj);
+ }
+
+ return inner;
+
+bad:
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_INDIRECT_CALL, caller);
+ return NULL;
+}
+
+const char *
+js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
+ JSPrincipals *principals, uintN *linenop)
+{
+ uint32 flags;
+#ifdef DEBUG
+ JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
+#endif
+
+ JS_ASSERT(principals || !(callbacks && callbacks->findObjectPrincipals));
+ flags = JS_GetScriptFilenameFlags(caller->script);
+ if ((flags & JSFILENAME_PROTECTED) &&
+ principals &&
+ strcmp(principals->codebase, "[System Principal]")) {
+ *linenop = 0;
+ return principals->codebase;
+ }
+
+ if (caller->regs && *caller->regs->pc == JSOP_EVAL) {
+ JS_ASSERT(caller->regs->pc[JSOP_EVAL_LENGTH] == JSOP_LINENO);
+ *linenop = GET_UINT16(caller->regs->pc + JSOP_EVAL_LENGTH);
+ } else {
+ *linenop = js_FramePCToLineNumber(cx, caller);
+ }
+ return caller->script->filename;
+}
+
+static JSBool
+obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSStackFrame *fp, *caller;
+ JSBool indirectCall;
+ JSObject *scopeobj;
+ JSString *str;
+ const char *file;
+ uintN line;
+ JSPrincipals *principals;
+ uint32 tcflags;
+ JSScript *script;
+ JSBool ok;
+#if JS_HAS_EVAL_THIS_SCOPE
+ JSObject *callerScopeChain = NULL, *callerVarObj = NULL;
+ JSObject *setCallerScopeChain = NULL;
+ JSBool setCallerVarObj = JS_FALSE;
+#endif
+
+ fp = cx->fp;
+ caller = JS_GetScriptedCaller(cx, fp);
+ indirectCall = (caller && caller->regs && *caller->regs->pc != JSOP_EVAL);
+
+ /*
+ * Ban all indirect uses of eval (global.foo = eval; global.foo(...)) and
+ * calls that attempt to use a non-global object as the "with" object in
+ * the former indirect case.
+ */
+ scopeobj = OBJ_GET_PARENT(cx, obj);
+ if (scopeobj) {
+ scopeobj = js_GetWrappedObject(cx, obj);
+ scopeobj = OBJ_GET_PARENT(cx, scopeobj);
+ }
+ if (indirectCall || scopeobj) {
+ uintN flags = scopeobj
+ ? JSREPORT_ERROR
+ : JSREPORT_STRICT | JSREPORT_WARNING;
+ if (!JS_ReportErrorFlagsAndNumber(cx, flags, js_GetErrorMessage, NULL,
+ JSMSG_BAD_INDIRECT_CALL,
+ js_eval_str)) {
+ return JS_FALSE;
+ }
+ }
+
+ if (!JSVAL_IS_STRING(argv[0])) {
+ *rval = argv[0];
+ return JS_TRUE;
+ }
+
+ /*
+ * If the caller is a lightweight function and doesn't have a variables
+ * object, then we need to provide one for the compiler to stick any
+ * declared (var) variables into.
+ */
+ if (caller && !caller->varobj && !js_GetCallObject(cx, caller, NULL))
+ return JS_FALSE;
+
+ /* eval no longer takes an optional trailing argument. */
+ if (argc >= 2 &&
+ !JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING | JSREPORT_STRICT,
+ js_GetErrorMessage, NULL,
+ JSMSG_EVAL_ARITY)) {
+ return JS_FALSE;
+ }
+
+ /* From here on, control must exit through label out with ok set. */
+ MUST_FLOW_THROUGH("out");
+ if (!scopeobj) {
+#if JS_HAS_EVAL_THIS_SCOPE
+ /* If obj.eval(str), emulate 'with (obj) eval(str)' in the caller. */
+ if (indirectCall) {
+ callerScopeChain = js_GetScopeChain(cx, caller);
+ if (!callerScopeChain) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ OBJ_TO_INNER_OBJECT(cx, obj);
+ if (!obj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ if (obj != callerScopeChain) {
+ ok = js_CheckPrincipalsAccess(cx, obj,
+ caller->script->principals,
+ cx->runtime->atomState.evalAtom);
+ if (!ok)
+ goto out;
+
+ scopeobj = js_NewWithObject(cx, obj, callerScopeChain, -1);
+ if (!scopeobj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ /* Set fp->scopeChain too, for the compiler. */
+ caller->scopeChain = fp->scopeChain = scopeobj;
+
+ /* Remember scopeobj so we can null its private when done. */
+ setCallerScopeChain = scopeobj;
+ }
+
+ callerVarObj = caller->varobj;
+ if (obj != callerVarObj) {
+ /* Set fp->varobj too, for the compiler. */
+ caller->varobj = fp->varobj = obj;
+ setCallerVarObj = JS_TRUE;
+ }
+ }
+#endif
+
+ /*
+ * Compile using caller's current scope object.
+ *
+ * NB: This means that native callers (who reach this point through
+ * the C API) must use the two parameter form.
+ */
+ if (caller) {
+ scopeobj = js_GetScopeChain(cx, caller);
+ if (!scopeobj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+ }
+
+ /* Ensure we compile this eval with the right object in the scope chain. */
+ scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_eval_str);
+ if (!scopeobj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ str = JSVAL_TO_STRING(argv[0]);
+ if (caller) {
+ principals = JS_EvalFramePrincipals(cx, fp, caller);
+ file = js_ComputeFilename(cx, caller, principals, &line);
+ } else {
+ file = NULL;
+ line = 0;
+ principals = NULL;
+ }
+
+ tcflags = TCF_COMPILE_N_GO;
+ if (caller)
+ tcflags |= TCF_PUT_STATIC_DEPTH(caller->script->staticDepth + 1);
+ script = js_CompileScript(cx, scopeobj, caller, principals, tcflags,
+ JSSTRING_CHARS(str), JSSTRING_LENGTH(str),
+ NULL, file, line);
+ if (!script) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ if (argc < 2) {
+ /* Execute using caller's new scope object (might be a Call object). */
+ if (caller)
+ scopeobj = caller->scopeChain;
+ }
+
+ /*
+ * Belt-and-braces: check that the lesser of eval's principals and the
+ * caller's principals has access to scopeobj.
+ */
+ ok = js_CheckPrincipalsAccess(cx, scopeobj, principals,
+ cx->runtime->atomState.evalAtom);
+ if (ok)
+ ok = js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval);
+
+ script->u.nextToGC = JS_SCRIPTS_TO_GC(cx);
+ JS_SCRIPTS_TO_GC(cx) = script;
+#ifdef CHECK_SCRIPT_OWNER
+ script->owner = NULL;
+#endif
+
+out:
+#if JS_HAS_EVAL_THIS_SCOPE
+ /* Restore OBJ_GET_PARENT(scopeobj) not callerScopeChain in case of Call. */
+ if (setCallerScopeChain) {
+ caller->scopeChain = callerScopeChain;
+ JS_ASSERT(OBJ_GET_CLASS(cx, setCallerScopeChain) == &js_WithClass);
+ JS_SetPrivate(cx, setCallerScopeChain, NULL);
+ }
+ if (setCallerVarObj)
+ caller->varobj = callerVarObj;
+#endif
+ return ok;
+}
+
+#if JS_HAS_OBJ_WATCHPOINT
+
+static JSBool
+obj_watch_handler(JSContext *cx, JSObject *obj, jsval id, jsval old, jsval *nvp,
+ void *closure)
+{
+ JSObject *callable;
+ JSSecurityCallbacks *callbacks;
+ JSStackFrame *caller;
+ JSPrincipals *subject, *watcher;
+ JSResolvingKey key;
+ JSResolvingEntry *entry;
+ uint32 generation;
+ jsval argv[3];
+ JSBool ok;
+
+ callable = (JSObject *) closure;
+
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks && callbacks->findObjectPrincipals) {
+ /* Skip over any obj_watch_* frames between us and the real subject. */
+ caller = JS_GetScriptedCaller(cx, cx->fp);
+ if (caller) {
+ /*
+ * Only call the watch handler if the watcher is allowed to watch
+ * the currently executing script.
+ */
+ watcher = callbacks->findObjectPrincipals(cx, callable);
+ subject = JS_StackFramePrincipals(cx, caller);
+
+ if (watcher && subject && !watcher->subsume(watcher, subject)) {
+ /* Silently don't call the watch handler. */
+ return JS_TRUE;
+ }
+ }
+ }
+
+ /* Avoid recursion on (obj, id) already being watched on cx. */
+ key.obj = obj;
+ key.id = id;
+ if (!js_StartResolving(cx, &key, JSRESFLAG_WATCH, &entry))
+ return JS_FALSE;
+ if (!entry)
+ return JS_TRUE;
+ generation = cx->resolvingTable->generation;
+
+ argv[0] = id;
+ argv[1] = old;
+ argv[2] = *nvp;
+ ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(callable), 3, argv, nvp);
+ js_StopResolving(cx, &key, JSRESFLAG_WATCH, entry, generation);
+ return ok;
+}
+
+static JSBool
+obj_watch(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *callable;
+ jsval userid, value;
+ jsid propid;
+ JSObject *obj;
+ uintN attrs;
+
+ if (argc <= 1) {
+ js_ReportMissingArg(cx, vp, 1);
+ return JS_FALSE;
+ }
+
+ callable = js_ValueToCallableObject(cx, &vp[3], 0);
+ if (!callable)
+ return JS_FALSE;
+
+ /* Compute the unique int/atom symbol id needed by js_LookupProperty. */
+ userid = vp[2];
+ if (!JS_ValueToId(cx, userid, &propid))
+ return JS_FALSE;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !OBJ_CHECK_ACCESS(cx, obj, propid, JSACC_WATCH, &value, &attrs))
+ return JS_FALSE;
+ if (attrs & JSPROP_READONLY)
+ return JS_TRUE;
+ *vp = JSVAL_VOID;
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_MakeArraySlow(cx, obj))
+ return JS_FALSE;
+ return JS_SetWatchPoint(cx, obj, userid, obj_watch_handler, callable);
+}
+
+static JSBool
+obj_unwatch(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ *vp = JSVAL_VOID;
+ return JS_ClearWatchPoint(cx, obj, argc != 0 ? vp[2] : JSVAL_VOID,
+ NULL, NULL);
+}
+
+#endif /* JS_HAS_OBJ_WATCHPOINT */
+
+/*
+ * Prototype and property query methods, to complement the 'in' and
+ * 'instanceof' operators.
+ */
+
+/* Proposed ECMA 15.2.4.5. */
+static JSBool
+obj_hasOwnProperty(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj &&
+ js_HasOwnPropertyHelper(cx, obj->map->ops->lookupProperty, argc, vp);
+}
+
+JSBool
+js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, uintN argc,
+ jsval *vp)
+{
+ jsid id;
+ JSObject *obj;
+
+ if (!JS_ValueToId(cx, argc != 0 ? vp[2] : JSVAL_VOID, &id))
+ return JS_FALSE;
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && js_HasOwnProperty(cx, lookup, obj, id, vp);
+}
+
+JSBool
+js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id,
+ jsval *vp)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ if (!lookup(cx, obj, id, &obj2, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ *vp = JSVAL_FALSE;
+ } else if (obj2 == obj) {
+ *vp = JSVAL_TRUE;
+ } else {
+ JSClass *clasp;
+ JSExtendedClass *xclasp;
+ JSObject *outer;
+
+ clasp = OBJ_GET_CLASS(cx, obj2);
+ if (!(clasp->flags & JSCLASS_IS_EXTENDED) ||
+ !(xclasp = (JSExtendedClass *) clasp)->outerObject) {
+ outer = NULL;
+ } else {
+ outer = xclasp->outerObject(cx, obj2);
+ if (!outer)
+ return JS_FALSE;
+ }
+ if (outer == obj) {
+ *vp = JSVAL_TRUE;
+ } else if (OBJ_IS_NATIVE(obj2) && OBJ_GET_CLASS(cx, obj) == clasp) {
+ /*
+ * The combination of JSPROP_SHARED and JSPROP_PERMANENT in a
+ * delegated property makes that property appear to be direct in
+ * all delegating instances of the same native class. This hack
+ * avoids bloating every function instance with its own 'length'
+ * (AKA 'arity') property. But it must not extend across class
+ * boundaries, to avoid making hasOwnProperty lie (bug 320854).
+ *
+ * It's not really a hack, of course: a permanent property can't
+ * be deleted, and JSPROP_SHARED means "don't allocate a slot in
+ * any instance, prototype or delegating". Without a slot, and
+ * without the ability to remove and recreate (with differences)
+ * the property, there is no way to tell whether it is directly
+ * owned, or indirectly delegated.
+ */
+ sprop = (JSScopeProperty *)prop;
+ *vp = BOOLEAN_TO_JSVAL(SPROP_IS_SHARED_PERMANENT(sprop));
+ } else {
+ *vp = JSVAL_FALSE;
+ }
+ }
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static int32 FASTCALL
+Object_p_hasOwnProperty(JSContext* cx, JSObject* obj, JSString *str)
+{
+ jsid id;
+ jsval v;
+
+ if (!js_ValueToStringId(cx, STRING_TO_JSVAL(str), &id))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ if (!js_HasOwnProperty(cx, obj->map->ops->lookupProperty, obj, id, &v))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
+ return JSVAL_TO_BOOLEAN(v);
+}
+#endif
+
+/* Proposed ECMA 15.2.4.6. */
+static JSBool
+obj_isPrototypeOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSBool b;
+
+ if (!js_IsDelegate(cx, JS_THIS_OBJECT(cx, vp),
+ argc != 0 ? vp[2] : JSVAL_VOID, &b)) {
+ return JS_FALSE;
+ }
+ *vp = BOOLEAN_TO_JSVAL(b);
+ return JS_TRUE;
+}
+
+/* Proposed ECMA 15.2.4.7. */
+static JSBool
+obj_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsid id;
+ JSObject *obj;
+
+ if (!JS_ValueToId(cx, argc != 0 ? vp[2] : JSVAL_VOID, &id))
+ return JS_FALSE;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && js_PropertyIsEnumerable(cx, obj, id, vp);
+}
+
+#ifdef JS_TRACER
+static int32 FASTCALL
+Object_p_propertyIsEnumerable(JSContext* cx, JSObject* obj, JSString *str)
+{
+ jsid id = ATOM_TO_JSID(STRING_TO_JSVAL(str));
+ jsval v;
+ if (!js_PropertyIsEnumerable(cx, obj, id, &v))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
+ return JSVAL_TO_BOOLEAN(v);
+}
+#endif
+
+JSBool
+js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSObject *pobj;
+ uintN attrs;
+ JSProperty *prop;
+ JSBool ok;
+
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
+ return JS_FALSE;
+
+ if (!prop) {
+ *vp = JSVAL_FALSE;
+ return JS_TRUE;
+ }
+
+ /*
+ * XXX ECMA spec error compatible: return false unless hasOwnProperty.
+ * The ECMA spec really should be fixed so propertyIsEnumerable and the
+ * for..in loop agree on whether prototype properties are enumerable,
+ * obviously by fixing this method (not by breaking the for..in loop!).
+ *
+ * We check here for shared permanent prototype properties, which should
+ * be treated as if they are local to obj. They are an implementation
+ * technique used to satisfy ECMA requirements; users should not be able
+ * to distinguish a shared permanent proto-property from a local one.
+ */
+ if (pobj != obj &&
+ !(OBJ_IS_NATIVE(pobj) &&
+ SPROP_IS_SHARED_PERMANENT((JSScopeProperty *)prop))) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ *vp = JSVAL_FALSE;
+ return JS_TRUE;
+ }
+
+ ok = OBJ_GET_ATTRIBUTES(cx, pobj, id, prop, &attrs);
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ if (ok)
+ *vp = BOOLEAN_TO_JSVAL((attrs & JSPROP_ENUMERATE) != 0);
+ return ok;
+}
+
+#if JS_HAS_GETTER_SETTER
+static JSBool
+obj_defineGetter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval fval, junk;
+ jsid id;
+ JSObject *obj;
+ uintN attrs;
+
+ if (argc <= 1 || JS_TypeOfValue(cx, vp[3]) != JSTYPE_FUNCTION) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_GETTER_OR_SETTER,
+ js_getter_str);
+ return JS_FALSE;
+ }
+ fval = vp[3];
+
+ if (!JS_ValueToId(cx, vp[2], &id))
+ return JS_FALSE;
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_CheckRedeclaration(cx, obj, id, JSPROP_GETTER, NULL, NULL))
+ return JS_FALSE;
+ /*
+ * Getters and setters are just like watchpoints from an access
+ * control point of view.
+ */
+ if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &junk, &attrs))
+ return JS_FALSE;
+ *vp = JSVAL_VOID;
+ return OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
+ (JSPropertyOp) JSVAL_TO_OBJECT(fval),
+ JS_PropertyStub,
+ JSPROP_ENUMERATE | JSPROP_GETTER | JSPROP_SHARED,
+ NULL);
+}
+
+static JSBool
+obj_defineSetter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval fval, junk;
+ jsid id;
+ JSObject *obj;
+ uintN attrs;
+
+ if (argc <= 1 || JS_TypeOfValue(cx, vp[3]) != JSTYPE_FUNCTION) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_GETTER_OR_SETTER,
+ js_setter_str);
+ return JS_FALSE;
+ }
+ fval = vp[3];
+
+ if (!JS_ValueToId(cx, vp[2], &id))
+ return JS_FALSE;
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_CheckRedeclaration(cx, obj, id, JSPROP_SETTER, NULL, NULL))
+ return JS_FALSE;
+ /*
+ * Getters and setters are just like watchpoints from an access
+ * control point of view.
+ */
+ if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &junk, &attrs))
+ return JS_FALSE;
+ *vp = JSVAL_VOID;
+ return OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
+ JS_PropertyStub,
+ (JSPropertyOp) JSVAL_TO_OBJECT(fval),
+ JSPROP_ENUMERATE | JSPROP_SETTER | JSPROP_SHARED,
+ NULL);
+}
+
+static JSBool
+obj_lookupGetter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsid id;
+ JSObject *obj, *pobj;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ if (!JS_ValueToId(cx, argc != 0 ? vp[2] : JSVAL_VOID, &id))
+ return JS_FALSE;
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
+ return JS_FALSE;
+ *vp = JSVAL_VOID;
+ if (prop) {
+ if (OBJ_IS_NATIVE(pobj)) {
+ sprop = (JSScopeProperty *) prop;
+ if (sprop->attrs & JSPROP_GETTER)
+ *vp = OBJECT_TO_JSVAL(sprop->getter);
+ }
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+obj_lookupSetter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsid id;
+ JSObject *obj, *pobj;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ if (!JS_ValueToId(cx, argc != 0 ? vp[2] : JSVAL_VOID, &id))
+ return JS_FALSE;
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
+ return JS_FALSE;
+ *vp = JSVAL_VOID;
+ if (prop) {
+ if (OBJ_IS_NATIVE(pobj)) {
+ sprop = (JSScopeProperty *) prop;
+ if (sprop->attrs & JSPROP_SETTER)
+ *vp = OBJECT_TO_JSVAL(sprop->setter);
+ }
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ return JS_TRUE;
+}
+#endif /* JS_HAS_GETTER_SETTER */
+
+JSBool
+obj_getPrototypeOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ uintN attrs;
+
+ if (argc == 0) {
+ js_ReportMissingArg(cx, vp, 0);
+ return JS_FALSE;
+ }
+
+ obj = js_ValueToNonNullObject(cx, vp[2]);
+ if (!obj)
+ return JS_FALSE;
+ vp[2] = OBJECT_TO_JSVAL(obj);
+
+ return OBJ_CHECK_ACCESS(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState.protoAtom),
+ JSACC_PROTO, vp, &attrs);
+}
+
+#if JS_HAS_OBJ_WATCHPOINT
+const char js_watch_str[] = "watch";
+const char js_unwatch_str[] = "unwatch";
+#endif
+const char js_hasOwnProperty_str[] = "hasOwnProperty";
+const char js_isPrototypeOf_str[] = "isPrototypeOf";
+const char js_propertyIsEnumerable_str[] = "propertyIsEnumerable";
+#if JS_HAS_GETTER_SETTER
+const char js_defineGetter_str[] = "__defineGetter__";
+const char js_defineSetter_str[] = "__defineSetter__";
+const char js_lookupGetter_str[] = "__lookupGetter__";
+const char js_lookupSetter_str[] = "__lookupSetter__";
+#endif
+
+JS_DEFINE_TRCINFO_1(obj_hasOwnProperty,
+ (3, (static, BOOL_FAIL, Object_p_hasOwnProperty, CONTEXT, THIS, STRING, 0, 0)))
+JS_DEFINE_TRCINFO_1(obj_propertyIsEnumerable,
+ (3, (static, BOOL_FAIL, Object_p_propertyIsEnumerable, CONTEXT, THIS, STRING, 0, 0)))
+
+static JSFunctionSpec object_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, obj_toSource, 0,0),
+#endif
+ JS_FN(js_toString_str, obj_toString, 0,0),
+ JS_FN(js_toLocaleString_str, obj_toLocaleString, 0,0),
+ JS_FN(js_valueOf_str, obj_valueOf, 0,0),
+#if JS_HAS_OBJ_WATCHPOINT
+ JS_FN(js_watch_str, obj_watch, 2,0),
+ JS_FN(js_unwatch_str, obj_unwatch, 1,0),
+#endif
+ JS_TN(js_hasOwnProperty_str, obj_hasOwnProperty, 1,0,
+ obj_hasOwnProperty_trcinfo),
+ JS_FN(js_isPrototypeOf_str, obj_isPrototypeOf, 1,0),
+ JS_TN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0,
+ obj_propertyIsEnumerable_trcinfo),
+#if JS_HAS_GETTER_SETTER
+ JS_FN(js_defineGetter_str, obj_defineGetter, 2,0),
+ JS_FN(js_defineSetter_str, obj_defineSetter, 2,0),
+ JS_FN(js_lookupGetter_str, obj_lookupGetter, 1,0),
+ JS_FN(js_lookupSetter_str, obj_lookupSetter, 1,0),
+#endif
+ JS_FS_END
+};
+
+static JSFunctionSpec object_static_methods[] = {
+ JS_FN("getPrototypeOf", obj_getPrototypeOf, 1,0),
+ JS_FS_END
+};
+
+JSBool
+js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if (argc == 0) {
+ /* Trigger logic below to construct a blank object. */
+ obj = NULL;
+ } else {
+ /* If argv[0] is null or undefined, obj comes back null. */
+ if (!js_ValueToObject(cx, argv[0], &obj))
+ return JS_FALSE;
+ }
+ if (!obj) {
+ JS_ASSERT(!argc || JSVAL_IS_NULL(argv[0]) || JSVAL_IS_VOID(argv[0]));
+ if (cx->fp->flags & JSFRAME_CONSTRUCTING)
+ return JS_TRUE;
+ obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ }
+ *rval = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+/*
+ * ObjectOps and Class for with-statement stack objects.
+ */
+static JSBool
+with_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_LookupProperty(cx, obj, id, objp, propp);
+ return OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp);
+}
+
+static JSBool
+with_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_GetProperty(cx, obj, id, vp);
+ return OBJ_GET_PROPERTY(cx, proto, id, vp);
+}
+
+static JSBool
+with_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_SetProperty(cx, obj, id, vp);
+ return OBJ_SET_PROPERTY(cx, proto, id, vp);
+}
+
+static JSBool
+with_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_GetAttributes(cx, obj, id, prop, attrsp);
+ return OBJ_GET_ATTRIBUTES(cx, proto, id, prop, attrsp);
+}
+
+static JSBool
+with_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_SetAttributes(cx, obj, id, prop, attrsp);
+ return OBJ_SET_ATTRIBUTES(cx, proto, id, prop, attrsp);
+}
+
+static JSBool
+with_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_DeleteProperty(cx, obj, id, rval);
+ return OBJ_DELETE_PROPERTY(cx, proto, id, rval);
+}
+
+static JSBool
+with_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_DefaultValue(cx, obj, hint, vp);
+ return OBJ_DEFAULT_VALUE(cx, proto, hint, vp);
+}
+
+static JSBool
+with_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_Enumerate(cx, obj, enum_op, statep, idp);
+ return OBJ_ENUMERATE(cx, proto, enum_op, statep, idp);
+}
+
+static JSBool
+with_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_CheckAccess(cx, obj, id, mode, vp, attrsp);
+ return OBJ_CHECK_ACCESS(cx, proto, id, mode, vp, attrsp);
+}
+
+static JSObject *
+with_ThisObject(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return obj;
+ return OBJ_THIS_OBJECT(cx, proto);
+}
+
+JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = {
+ js_NewObjectMap, js_DestroyObjectMap,
+ with_LookupProperty, js_DefineProperty,
+ with_GetProperty, with_SetProperty,
+ with_GetAttributes, with_SetAttributes,
+ with_DeleteProperty, with_DefaultValue,
+ with_Enumerate, with_CheckAccess,
+ with_ThisObject, NATIVE_DROP_PROPERTY,
+ NULL, NULL,
+ NULL, NULL,
+ js_SetProtoOrParent, js_SetProtoOrParent,
+ js_TraceObject, js_Clear,
+ NULL, NULL
+};
+
+static JSObjectOps *
+with_getObjectOps(JSContext *cx, JSClass *clasp)
+{
+ return &js_WithObjectOps;
+}
+
+JSClass js_WithClass = {
+ "With",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_IS_ANONYMOUS,
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ with_getObjectOps,
+ 0,0,0,0,0,0,0
+};
+
+JSObject *
+js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
+{
+ JSObject *obj;
+
+ obj = js_NewObject(cx, &js_WithClass, proto, parent, 0);
+ if (!obj)
+ return NULL;
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(cx->fp));
+ OBJ_SET_BLOCK_DEPTH(cx, obj, depth);
+ return obj;
+}
+
+JSObject *
+js_NewBlockObject(JSContext *cx)
+{
+ JSObject *obj;
+ JSBool ok;
+
+ /*
+ * Null obj's proto slot so that Object.prototype.* does not pollute block
+ * scopes. Make sure obj has its own scope too, since clearing proto does
+ * not affect OBJ_SCOPE(obj).
+ */
+ obj = js_NewObject(cx, &js_BlockClass, NULL, NULL, 0);
+ if (!obj)
+ return NULL;
+ JS_LOCK_OBJ(cx, obj);
+ ok = js_GetMutableScope(cx, obj) != NULL;
+ JS_UNLOCK_OBJ(cx, obj);
+ if (!ok)
+ return NULL;
+ OBJ_CLEAR_PROTO(cx, obj);
+ return obj;
+}
+
+JSObject *
+js_CloneBlockObject(JSContext *cx, JSObject *proto, JSObject *parent,
+ JSStackFrame *fp)
+{
+ JSObject *clone;
+
+ JS_ASSERT(STOBJ_GET_CLASS(proto) == &js_BlockClass);
+ JS_ASSERT(!OBJ_IS_CLONED_BLOCK(proto));
+ clone = js_NewObject(cx, &js_BlockClass, proto, parent, 0);
+ if (!clone)
+ return NULL;
+ STOBJ_SET_SLOT(clone, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(fp));
+ STOBJ_SET_SLOT(clone, JSSLOT_BLOCK_DEPTH,
+ OBJ_GET_SLOT(cx, proto, JSSLOT_BLOCK_DEPTH));
+ JS_ASSERT(OBJ_IS_CLONED_BLOCK(clone));
+ return clone;
+}
+
+JSBool
+js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
+{
+ JSStackFrame *fp;
+ JSObject *obj;
+ uintN depth, count;
+
+ /* Blocks have one fixed slot available for the first local.*/
+ JS_STATIC_ASSERT(JS_INITIAL_NSLOTS == JSSLOT_BLOCK_DEPTH + 2);
+
+ fp = cx->fp;
+ obj = fp->scopeChain;
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_BlockClass);
+ JS_ASSERT(OBJ_GET_PRIVATE(cx, obj) == cx->fp);
+ JS_ASSERT(OBJ_IS_CLONED_BLOCK(obj));
+
+ /*
+ * Block objects should never be exposed to scripts. Thus the clone should
+ * not own the property map and rather always share it with the prototype
+ * object. This allows to skip updating OBJ_SCOPE(obj)->map.freeslot after
+ * we copy the stack slots into reserved slots.
+ */
+ JS_ASSERT(OBJ_SCOPE(obj)->object != obj);
+
+ /* Block objects should not have reserved slots before they are put. */
+ JS_ASSERT(STOBJ_NSLOTS(obj) == JS_INITIAL_NSLOTS);
+
+ /* The block and its locals must be on the current stack for GC safety. */
+ depth = OBJ_BLOCK_DEPTH(cx, obj);
+ count = OBJ_BLOCK_COUNT(cx, obj);
+ JS_ASSERT(depth <= (size_t) (fp->regs->sp - StackBase(fp)));
+ JS_ASSERT(count <= (size_t) (fp->regs->sp - StackBase(fp) - depth));
+
+ /* See comments in CheckDestructuring from jsparse.c. */
+ JS_ASSERT(count >= 1);
+
+ depth += fp->script->nfixed;
+ obj->fslots[JSSLOT_BLOCK_DEPTH + 1] = fp->slots[depth];
+ if (normalUnwind && count > 1) {
+ --count;
+ JS_LOCK_OBJ(cx, obj);
+ if (!js_ReallocSlots(cx, obj, JS_INITIAL_NSLOTS + count, JS_TRUE))
+ normalUnwind = JS_FALSE;
+ else
+ memcpy(obj->dslots, fp->slots + depth + 1, count * sizeof(jsval));
+ JS_UNLOCK_OBJ(cx, obj);
+ }
+
+ /* We must clear the private slot even with errors. */
+ JS_SetPrivate(cx, obj, NULL);
+ fp->scopeChain = OBJ_GET_PARENT(cx, obj);
+ return normalUnwind;
+}
+
+static JSBool
+block_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ uintN index;
+ JSStackFrame *fp;
+
+ JS_ASSERT(JS_InstanceOf(cx, obj, &js_BlockClass, NULL));
+ JS_ASSERT(OBJ_IS_CLONED_BLOCK(obj));
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+
+ index = (uint16) JSVAL_TO_INT(id);
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+ if (fp) {
+ index += fp->script->nfixed + OBJ_BLOCK_DEPTH(cx, obj);
+ JS_ASSERT(index < fp->script->nslots);
+ *vp = fp->slots[index];
+ return JS_TRUE;
+ }
+
+ /* Reserve slots start with the first slot after the private. */
+ index += JSSLOT_BLOCK_DEPTH - JSSLOT_PRIVATE;
+ return JS_GetReservedSlot(cx, obj, index, vp);
+}
+
+static JSBool
+block_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ uintN index;
+ JSStackFrame *fp;
+
+ JS_ASSERT(JS_InstanceOf(cx, obj, &js_BlockClass, NULL));
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+
+ index = (uint16) JSVAL_TO_INT(id);
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+ if (fp) {
+ index += fp->script->nfixed + OBJ_BLOCK_DEPTH(cx, obj);
+ JS_ASSERT(index < fp->script->nslots);
+ fp->slots[index] = *vp;
+ return JS_TRUE;
+ }
+
+ /* Reserve slots start with the first slot after the private. */
+ index += JSSLOT_BLOCK_DEPTH - JSSLOT_PRIVATE;
+ return JS_SetReservedSlot(cx, obj, index, *vp);
+}
+
+#if JS_HAS_XDR
+
+#define NO_PARENT_INDEX ((uint32)-1)
+
+uint32
+FindObjectIndex(JSObjectArray *array, JSObject *obj)
+{
+ size_t i;
+
+ if (array) {
+ i = array->length;
+ do {
+
+ if (array->vector[--i] == obj)
+ return i;
+ } while (i != 0);
+ }
+
+ return NO_PARENT_INDEX;
+}
+
+static JSBool
+block_xdrObject(JSXDRState *xdr, JSObject **objp)
+{
+ JSContext *cx;
+ uint32 parentId;
+ JSObject *obj, *parent;
+ uint16 depth, count, i;
+ uint32 tmp;
+ JSTempValueRooter tvr;
+ JSScopeProperty *sprop;
+ jsid propid;
+ JSAtom *atom;
+ int16 shortid;
+ JSBool ok;
+
+ cx = xdr->cx;
+#ifdef __GNUC__
+ obj = NULL; /* quell GCC overwarning */
+#endif
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ obj = *objp;
+ parent = OBJ_GET_PARENT(cx, obj);
+ parentId = (xdr->script->objectsOffset == 0)
+ ? NO_PARENT_INDEX
+ : FindObjectIndex(JS_SCRIPT_OBJECTS(xdr->script), parent);
+ depth = (uint16)OBJ_BLOCK_DEPTH(cx, obj);
+ count = (uint16)OBJ_BLOCK_COUNT(cx, obj);
+ tmp = (uint32)(depth << 16) | count;
+ }
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ else count = 0;
+#endif
+
+ /* First, XDR the parent atomid. */
+ if (!JS_XDRUint32(xdr, &parentId))
+ return JS_FALSE;
+
+ if (xdr->mode == JSXDR_DECODE) {
+ obj = js_NewBlockObject(cx);
+ if (!obj)
+ return JS_FALSE;
+ *objp = obj;
+
+ /*
+ * If there's a parent id, then get the parent out of our script's
+ * object array. We know that we XDR block object in outer-to-inner
+ * order, which means that getting the parent now will work.
+ */
+ if (parentId == NO_PARENT_INDEX)
+ parent = NULL;
+ else
+ JS_GET_SCRIPT_OBJECT(xdr->script, parentId, parent);
+ STOBJ_SET_PARENT(obj, parent);
+ }
+
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(obj), &tvr);
+
+ if (!JS_XDRUint32(xdr, &tmp)) {
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return JS_FALSE;
+ }
+
+ if (xdr->mode == JSXDR_DECODE) {
+ depth = (uint16)(tmp >> 16);
+ count = (uint16)tmp;
+ STOBJ_SET_SLOT(obj, JSSLOT_BLOCK_DEPTH, INT_TO_JSVAL(depth));
+ }
+
+ /*
+ * XDR the block object's properties. We know that there are 'count'
+ * properties to XDR, stored as id/shortid pairs. We do not XDR any
+ * non-native properties, only those that the compiler created.
+ */
+ sprop = NULL;
+ ok = JS_TRUE;
+ for (i = 0; i < count; i++) {
+ if (xdr->mode == JSXDR_ENCODE) {
+ /* Find a property to XDR. */
+ do {
+ /* If sprop is NULL, this is the first property. */
+ sprop = sprop ? sprop->parent : OBJ_SCOPE(obj)->lastProp;
+ } while (!(sprop->flags & SPROP_HAS_SHORTID));
+
+ JS_ASSERT(sprop->getter == js_BlockClass.getProperty);
+ propid = sprop->id;
+ JS_ASSERT(JSID_IS_ATOM(propid));
+ atom = JSID_TO_ATOM(propid);
+ shortid = sprop->shortid;
+ JS_ASSERT(shortid >= 0);
+ }
+
+ /* XDR the real id, then the shortid. */
+ if (!js_XDRStringAtom(xdr, &atom) ||
+ !JS_XDRUint16(xdr, (uint16 *)&shortid)) {
+ ok = JS_FALSE;
+ break;
+ }
+
+ if (xdr->mode == JSXDR_DECODE) {
+ if (!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom),
+ JSVAL_VOID, NULL, NULL,
+ JSPROP_ENUMERATE | JSPROP_PERMANENT,
+ SPROP_HAS_SHORTID, shortid, NULL)) {
+ ok = JS_FALSE;
+ break;
+ }
+ }
+ }
+
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+#else
+# define block_xdrObject NULL
+#endif
+
+static uint32
+block_reserveSlots(JSContext *cx, JSObject *obj)
+{
+ return OBJ_IS_CLONED_BLOCK(obj) ? OBJ_BLOCK_COUNT(cx, obj) : 0;
+}
+
+JSClass js_BlockClass = {
+ "Block",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
+ JSCLASS_IS_ANONYMOUS | JSCLASS_HAS_CACHED_PROTO(JSProto_Block),
+ JS_PropertyStub, JS_PropertyStub, block_getProperty, block_setProperty,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL, NULL, NULL, block_xdrObject, NULL, NULL, block_reserveSlots
+};
+
+JSObject*
+js_InitBlockClass(JSContext *cx, JSObject* obj)
+{
+ JSObject *proto;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_BlockClass, NULL, 0, NULL,
+ NULL, NULL, NULL);
+ if (!proto)
+ return NULL;
+
+ OBJ_CLEAR_PROTO(cx, proto);
+ return proto;
+}
+
+JSObject *
+js_InitEval(JSContext *cx, JSObject *obj)
+{
+ /* ECMA (15.1.2.1) says 'eval' is a property of the global object. */
+ if (!js_DefineFunction(cx, obj, cx->runtime->atomState.evalAtom,
+ obj_eval, 1, 0)) {
+ return NULL;
+ }
+
+ return obj;
+}
+
+JSObject *
+js_InitObjectClass(JSContext *cx, JSObject *obj)
+{
+ return JS_InitClass(cx, obj, NULL, &js_ObjectClass, js_Object, 1,
+ object_props, object_methods, NULL,
+ object_static_methods);
+}
+
+void
+js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp)
+{
+ map->nrefs = nrefs;
+ map->ops = ops;
+ map->freeslot = JSSLOT_FREE(clasp);
+}
+
+JSObjectMap *
+js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp, JSObject *obj)
+{
+ return (JSObjectMap *) js_NewScope(cx, nrefs, ops, clasp, obj);
+}
+
+void
+js_DestroyObjectMap(JSContext *cx, JSObjectMap *map)
+{
+ js_DestroyScope(cx, (JSScope *)map);
+}
+
+JSObjectMap *
+js_HoldObjectMap(JSContext *cx, JSObjectMap *map)
+{
+ JS_ASSERT(map->nrefs >= 0);
+ JS_ATOMIC_INCREMENT(&map->nrefs);
+ return map;
+}
+
+JSObjectMap *
+js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj)
+{
+ JS_ASSERT(map->nrefs > 0);
+ JS_ATOMIC_DECREMENT(&map->nrefs);
+ if (map->nrefs == 0) {
+ map->ops->destroyObjectMap(cx, map);
+ return NULL;
+ }
+ if (MAP_IS_NATIVE(map) && ((JSScope *)map)->object == obj)
+ ((JSScope *)map)->object = NULL;
+ return map;
+}
+
+static void
+FreeSlots(JSContext *cx, JSObject *obj)
+{
+ if (obj->dslots) {
+ JS_ASSERT((uint32)obj->dslots[-1] > JS_INITIAL_NSLOTS);
+ JS_free(cx, obj->dslots - 1);
+ obj->dslots = NULL;
+ }
+}
+
+#define SLOTS_TO_DYNAMIC_WORDS(nslots) \
+ (JS_ASSERT((nslots) > JS_INITIAL_NSLOTS), (nslots) + 1 - JS_INITIAL_NSLOTS)
+
+#define DYNAMIC_WORDS_TO_SLOTS(words) \
+ (JS_ASSERT((words) > 1), (words) - 1 + JS_INITIAL_NSLOTS)
+
+JSBool
+js_ReallocSlots(JSContext *cx, JSObject *obj, uint32 nslots,
+ JSBool exactAllocation)
+{
+ jsval *old, *slots;
+ uint32 oslots, nwords, owords, log, i;
+
+ /*
+ * Minimal number of dynamic slots to allocate.
+ */
+#define MIN_DYNAMIC_WORDS 4
+
+ /*
+ * The limit to switch to linear allocation strategy from the power of 2
+ * growth no to waste too much memory.
+ */
+#define LINEAR_GROWTH_STEP JS_BIT(16)
+
+ old = obj->dslots;
+ if (nslots <= JS_INITIAL_NSLOTS) {
+ if (old &&
+ (exactAllocation ||
+ SLOTS_TO_DYNAMIC_WORDS((uint32)old[-1]) != MIN_DYNAMIC_WORDS ||
+ nslots <= (JS_INITIAL_NSLOTS +
+ JSSLOT_FREE(STOBJ_GET_CLASS(obj))) / 2)) {
+ /*
+ * We do not want to free dynamic slots when allocation is a hint,
+ * we reached minimal allocation and almost all fixed slots are
+ * used. It avoids allocating dynamic slots again when properties
+ * are added to the object.
+ *
+ * If there were no private or reserved slots, the condition to
+ * free the slots would be
+ *
+ * nslots <= JS_INITIAL_NSLOTS / 2
+ *
+ * but to account for never removed slots before JSSLOT_FREE(class)
+ * we need to subtract it from the slot counts which gives
+ *
+ * nslots - JSSLOT_FREE <= (JS_INITIAL_NSLOTS - JSSLOT_FREE) / 2
+ *
+ * or
+ *
+ * nslots <= (JS_INITIAL_NSLOTS + JSSLOT_FREE) / 2
+ */
+ FreeSlots(cx, obj);
+ }
+ return JS_TRUE;
+ }
+
+ oslots = (old) ? (uint32)*--old : JS_INITIAL_NSLOTS;
+ nwords = SLOTS_TO_DYNAMIC_WORDS(nslots);
+
+ if (nslots > oslots) {
+ if (!exactAllocation) {
+ /*
+ * Round up nslots so the number of bytes in dslots array is power
+ * of 2 to ensure exponential grouth.
+ */
+ if (nwords <= MIN_DYNAMIC_WORDS) {
+ nwords = MIN_DYNAMIC_WORDS;
+ } else if (nwords < LINEAR_GROWTH_STEP) {
+ JS_CEILING_LOG2(log, nwords);
+ nwords = JS_BIT(log);
+ } else {
+ nwords = JS_ROUNDUP(nwords, LINEAR_GROWTH_STEP);
+ }
+ }
+ slots = (jsval *)JS_realloc(cx, old, nwords * sizeof(jsval));
+ if (!slots)
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(nslots < oslots);
+ if (!exactAllocation) {
+ owords = DYNAMIC_WORDS_TO_SLOTS(oslots);
+ if (owords <= MIN_DYNAMIC_WORDS)
+ return JS_TRUE;
+ if (owords < LINEAR_GROWTH_STEP * 2) {
+ /*
+ * Shrink only if 1/4 of slots are left and we need to grow
+ * the array at least twice to reach the current capacity. It
+ * prevents frequent capacity growth/shrinking when slots are
+ * often removed and added.
+ */
+ if (nwords > owords / 4)
+ return JS_TRUE;
+ JS_CEILING_LOG2(log, nwords);
+ nwords = JS_BIT(log);
+ if (nwords < MIN_DYNAMIC_WORDS)
+ nwords = MIN_DYNAMIC_WORDS;
+ } else {
+ /*
+ * Shrink only if we free at least 2 linear allocation
+ * segments, to prevent growth/shrinking resonance.
+ */
+ if (nwords > owords - LINEAR_GROWTH_STEP * 2)
+ return JS_TRUE;
+ nwords = JS_ROUNDUP(nwords, LINEAR_GROWTH_STEP);
+ }
+ }
+
+ /* We avoid JS_realloc not to report a failed shrink attempt. */
+ slots = (jsval *)realloc(old, nwords * sizeof(jsval));
+ if (!slots)
+ slots = old;
+ }
+
+ nslots = DYNAMIC_WORDS_TO_SLOTS(nwords);
+ *slots++ = (jsval)nslots;
+ obj->dslots = slots;
+
+ /* If we're extending an allocation, initialize free slots. */
+ for (i = oslots; i < nslots; i++)
+ slots[i - JS_INITIAL_NSLOTS] = JSVAL_VOID;
+
+ return JS_TRUE;
+
+#undef LINEAR_GROWTH_STEP
+#undef MIN_DYNAMIC_WORDS
+}
+
+extern JSBool
+js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp)
+{
+ JSProtoKey key;
+ JSAtom *atom;
+
+ key = JSCLASS_CACHED_PROTO_KEY(clasp);
+ if (key != JSProto_Null) {
+ *idp = INT_TO_JSID(key);
+ } else if (clasp->flags & JSCLASS_IS_ANONYMOUS) {
+ *idp = INT_TO_JSID(JSProto_Object);
+ } else {
+ atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
+ if (!atom)
+ return JS_FALSE;
+ *idp = ATOM_TO_JSID(atom);
+ }
+ return JS_TRUE;
+}
+
+JSObject *
+js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
+ uintN objectSize)
+{
+ jsid id;
+
+ /* Bootstrap the ur-object, and make it the default prototype object. */
+ if (!proto) {
+ if (!js_GetClassId(cx, clasp, &id))
+ return NULL;
+ if (!js_GetClassPrototype(cx, parent, id, &proto))
+ return NULL;
+ if (!proto &&
+ !js_GetClassPrototype(cx, parent, INT_TO_JSID(JSProto_Object),
+ &proto)) {
+ return NULL;
+ }
+ }
+
+ return js_NewObjectWithGivenProto(cx, clasp, proto, parent, objectSize);
+}
+
+JSObject *
+js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN objectSize)
+{
+ JSObject *obj;
+ JSObjectOps *ops;
+ JSObjectMap *map;
+ JSClass *protoclasp;
+ uint32 nslots, i;
+ JSTempValueRooter tvr;
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_OBJECT_CREATE_START_ENABLED())
+ jsdtrace_object_create_start(cx->fp, clasp);
+#endif
+
+ /* Currently only functions can have non-standard allocation size. */
+ if (clasp == &js_FunctionClass) {
+ if (objectSize == 0)
+ objectSize = sizeof(JSFunction);
+ else
+ JS_ASSERT(objectSize == sizeof(JSObject));
+ } else {
+ JS_ASSERT(objectSize == 0);
+ objectSize = sizeof(JSObject);
+ }
+
+ /*
+ * Allocate an object from the GC heap and initialize all its fields before
+ * doing any operation that can potentially trigger GC.
+ */
+ obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, objectSize);
+ if (!obj)
+ goto earlybad;
+
+ obj->map = NULL;
+ obj->dslots = NULL;
+
+ /*
+ * Set the class slot with the initial value of the system and delegate
+ * flags set to false.
+ */
+ JS_ASSERT(((jsuword) clasp & 3) == 0);
+ obj->classword = jsuword(clasp);
+ JS_ASSERT(!STOBJ_IS_DELEGATE(obj));
+ JS_ASSERT(!STOBJ_IS_SYSTEM(obj));
+
+ /* Set the proto and parent properties. */
+ STOBJ_SET_PROTO(obj, proto);
+ STOBJ_SET_PARENT(obj, parent);
+
+ /* Initialize the remaining fixed slots. */
+ for (i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i)
+ obj->fslots[i] = JSVAL_VOID;
+
+#ifdef DEBUG
+ memset((uint8 *) obj + sizeof(JSObject), JS_FREE_PATTERN,
+ objectSize - sizeof(JSObject));
+#endif
+
+ /*
+ * Root obj to prevent it from being collected out from under this call to
+ * js_NewObject. There's a possibilty of GC under the objectHook call-out
+ * further below.
+ */
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);
+
+ /* Always call the class's getObjectOps hook if it has one. */
+ ops = clasp->getObjectOps
+ ? clasp->getObjectOps(cx, clasp)
+ : &js_ObjectOps;
+
+ /*
+ * Default parent to the parent of the prototype, which was set from
+ * the parent of the prototype's constructor.
+ */
+ if (proto && !parent)
+ STOBJ_SET_PARENT(obj, OBJ_GET_PARENT(cx, proto));
+
+ /*
+ * Share proto's map only if it has the same JSObjectOps, and only if
+ * proto's class has the same private and reserved slots as obj's map
+ * and class have. We assume that if prototype and object are of the
+ * same class, they always have the same number of computed reserved
+ * slots (returned via clasp->reserveSlots); otherwise, prototype and
+ * object classes must have the same (null or not) reserveSlots hook.
+ */
+ if (proto &&
+ (map = proto->map)->ops == ops &&
+ ((protoclasp = OBJ_GET_CLASS(cx, proto)) == clasp ||
+ (!((protoclasp->flags ^ clasp->flags) &
+ (JSCLASS_HAS_PRIVATE |
+ (JSCLASS_RESERVED_SLOTS_MASK << JSCLASS_RESERVED_SLOTS_SHIFT))) &&
+ protoclasp->reserveSlots == clasp->reserveSlots)))
+ {
+ /* Share the given prototype's map. */
+ obj->map = js_HoldObjectMap(cx, map);
+ } else {
+ map = ops->newObjectMap(cx, 1, ops, clasp, obj);
+ if (!map)
+ goto bad;
+ obj->map = map;
+
+ /* Let ops->newObjectMap set freeslot so as to reserve slots. */
+ nslots = map->freeslot;
+ JS_ASSERT(nslots >= JSSLOT_PRIVATE);
+ if (nslots > JS_INITIAL_NSLOTS &&
+ !js_ReallocSlots(cx, obj, nslots, JS_TRUE)) {
+ js_DropObjectMap(cx, map, obj);
+ obj->map = NULL;
+ goto bad;
+ }
+ }
+
+ if (cx->debugHooks->objectHook) {
+ JS_KEEP_ATOMS(cx->runtime);
+ cx->debugHooks->objectHook(cx, obj, JS_TRUE,
+ cx->debugHooks->objectHookData);
+ JS_UNKEEP_ATOMS(cx->runtime);
+ }
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ cx->weakRoots.newborn[GCX_OBJECT] = obj;
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
+ jsdtrace_object_create(cx, clasp, obj);
+ if (JAVASCRIPT_OBJECT_CREATE_DONE_ENABLED())
+ jsdtrace_object_create_done(cx->fp, clasp);
+#endif
+ return obj;
+
+bad:
+ obj = NULL;
+ goto out;
+
+earlybad:
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
+ jsdtrace_object_create(cx, clasp, NULL);
+ if (JAVASCRIPT_OBJECT_CREATE_DONE_ENABLED())
+ jsdtrace_object_create_done(cx->fp, clasp);
+#endif
+ return NULL;
+}
+
+JS_BEGIN_EXTERN_C
+
+static JSObject *
+js_InitNullClass(JSContext *cx, JSObject *obj)
+{
+ JS_ASSERT(0);
+ return NULL;
+}
+
+#define JS_PROTO(name,code,init) extern JSObject *init(JSContext *, JSObject *);
+#include "jsproto.tbl"
+#undef JS_PROTO
+
+static JSObjectOp lazy_prototype_init[JSProto_LIMIT] = {
+#define JS_PROTO(name,code,init) init,
+#include "jsproto.tbl"
+#undef JS_PROTO
+};
+
+JS_END_EXTERN_C
+
+JSBool
+js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
+ JSObject **objp)
+{
+ JSBool ok;
+ JSObject *tmp, *cobj;
+ JSResolvingKey rkey;
+ JSResolvingEntry *rentry;
+ uint32 generation;
+ JSObjectOp init;
+ jsval v;
+
+ while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL)
+ obj = tmp;
+ if (!(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL)) {
+ *objp = NULL;
+ return JS_TRUE;
+ }
+
+ ok = JS_GetReservedSlot(cx, obj, key, &v);
+ if (!ok)
+ return JS_FALSE;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ *objp = JSVAL_TO_OBJECT(v);
+ return JS_TRUE;
+ }
+
+ rkey.obj = obj;
+ rkey.id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[key]);
+ if (!js_StartResolving(cx, &rkey, JSRESFLAG_LOOKUP, &rentry))
+ return JS_FALSE;
+ if (!rentry) {
+ /* Already caching key in obj -- suppress recursion. */
+ *objp = NULL;
+ return JS_TRUE;
+ }
+ generation = cx->resolvingTable->generation;
+
+ cobj = NULL;
+ init = lazy_prototype_init[key];
+ if (init) {
+ if (!init(cx, obj)) {
+ ok = JS_FALSE;
+ } else {
+ ok = JS_GetReservedSlot(cx, obj, key, &v);
+ if (ok && !JSVAL_IS_PRIMITIVE(v))
+ cobj = JSVAL_TO_OBJECT(v);
+ }
+ }
+
+ js_StopResolving(cx, &rkey, JSRESFLAG_LOOKUP, rentry, generation);
+ *objp = cobj;
+ return ok;
+}
+
+JSBool
+js_SetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject *cobj)
+{
+ JS_ASSERT(!OBJ_GET_PARENT(cx, obj));
+ if (!(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL))
+ return JS_TRUE;
+
+ return JS_SetReservedSlot(cx, obj, key, OBJECT_TO_JSVAL(cobj));
+}
+
+JSBool
+js_FindClassObject(JSContext *cx, JSObject *start, jsid id, jsval *vp)
+{
+ JSObject *obj, *cobj, *pobj;
+ JSProtoKey key;
+ JSProperty *prop;
+ jsval v;
+ JSScopeProperty *sprop;
+
+ if (start || (cx->fp && (start = cx->fp->scopeChain) != NULL)) {
+ /* Find the topmost object in the scope chain. */
+ do {
+ obj = start;
+ start = OBJ_GET_PARENT(cx, obj);
+ } while (start);
+ } else {
+ obj = cx->globalObject;
+ if (!obj) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ }
+
+ OBJ_TO_INNER_OBJECT(cx, obj);
+ if (!obj)
+ return JS_FALSE;
+
+ if (JSID_IS_INT(id)) {
+ key = (JSProtoKey) JSID_TO_INT(id);
+ JS_ASSERT(key != JSProto_Null);
+ if (!js_GetClassObject(cx, obj, key, &cobj))
+ return JS_FALSE;
+ if (cobj) {
+ *vp = OBJECT_TO_JSVAL(cobj);
+ return JS_TRUE;
+ }
+ id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[key]);
+ }
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ if (js_LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_CLASSNAME,
+ &pobj, &prop) < 0) {
+ return JS_FALSE;
+ }
+ v = JSVAL_VOID;
+ if (prop) {
+ if (OBJ_IS_NATIVE(pobj)) {
+ sprop = (JSScopeProperty *) prop;
+ if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))) {
+ v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
+ if (JSVAL_IS_PRIMITIVE(v))
+ v = JSVAL_VOID;
+ }
+ }
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ *vp = v;
+ return JS_TRUE;
+}
+
+JSObject *
+js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN argc, jsval *argv)
+{
+ jsid id;
+ jsval cval, rval;
+ JSTempValueRooter argtvr, tvr;
+ JSObject *obj, *ctor;
+
+ JS_PUSH_TEMP_ROOT(cx, argc, argv, &argtvr);
+
+ if (!js_GetClassId(cx, clasp, &id) ||
+ !js_FindClassObject(cx, parent, id, &cval)) {
+ JS_POP_TEMP_ROOT(cx, &argtvr);
+ return NULL;
+ }
+
+ if (JSVAL_IS_PRIMITIVE(cval)) {
+ js_ReportIsNotFunction(cx, &cval, JSV2F_CONSTRUCT | JSV2F_SEARCH_STACK);
+ JS_POP_TEMP_ROOT(cx, &argtvr);
+ return NULL;
+ }
+
+ /*
+ * Protect cval in case a crazy getter for .prototype uproots it. After
+ * this point, all control flow must exit through label out with obj set.
+ */
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, cval, &tvr);
+ MUST_FLOW_THROUGH("out");
+
+ /*
+ * If proto or parent are NULL, set them to Constructor.prototype and/or
+ * Constructor.__parent__, just like JSOP_NEW does.
+ */
+ ctor = JSVAL_TO_OBJECT(cval);
+ if (!parent)
+ parent = OBJ_GET_PARENT(cx, ctor);
+ if (!proto) {
+ if (!OBJ_GET_PROPERTY(cx, ctor,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &rval)) {
+ obj = NULL;
+ goto out;
+ }
+ if (JSVAL_IS_OBJECT(rval))
+ proto = JSVAL_TO_OBJECT(rval);
+ }
+
+ obj = js_NewObject(cx, clasp, proto, parent, 0);
+ if (!obj)
+ goto out;
+
+ if (!js_InternalConstruct(cx, obj, cval, argc, argv, &rval))
+ goto bad;
+
+ if (JSVAL_IS_PRIMITIVE(rval))
+ goto out;
+ obj = JSVAL_TO_OBJECT(rval);
+
+ /*
+ * If the instance's class differs from what was requested, throw a type
+ * error. If the given class has both the JSCLASS_HAS_PRIVATE and the
+ * JSCLASS_CONSTRUCT_PROTOTYPE flags, and the instance does not have its
+ * private data set at this point, then the constructor was replaced and
+ * we should throw a type error.
+ */
+ if (OBJ_GET_CLASS(cx, obj) != clasp ||
+ (!(~clasp->flags & (JSCLASS_HAS_PRIVATE |
+ JSCLASS_CONSTRUCT_PROTOTYPE)) &&
+ !JS_GetPrivate(cx, obj))) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_WRONG_CONSTRUCTOR, clasp->name);
+ goto bad;
+ }
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ JS_POP_TEMP_ROOT(cx, &argtvr);
+ return obj;
+
+bad:
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ obj = NULL;
+ goto out;
+}
+
+void
+js_FinalizeObject(JSContext *cx, JSObject *obj)
+{
+ JSObjectMap *map;
+
+ /* Cope with stillborn objects that have no map. */
+ map = obj->map;
+ if (!map)
+ return;
+
+ if (cx->debugHooks->objectHook) {
+ cx->debugHooks->objectHook(cx, obj, JS_FALSE,
+ cx->debugHooks->objectHookData);
+ }
+
+ /* Finalize obj first, in case it needs map and slots. */
+ STOBJ_GET_CLASS(obj)->finalize(cx, obj);
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_OBJECT_FINALIZE_ENABLED())
+ jsdtrace_object_finalize(obj);
+#endif
+
+ /* Drop map and free slots. */
+ js_DropObjectMap(cx, map, obj);
+ FreeSlots(cx, obj);
+}
+
+/* XXXbe if one adds props, deletes earlier props, adds more, the last added
+ won't recycle the deleted props' slots. */
+JSBool
+js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp)
+{
+ JSObjectMap *map;
+ JSClass *clasp;
+
+ map = obj->map;
+ JS_ASSERT(!MAP_IS_NATIVE(map) || ((JSScope *)map)->object == obj);
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ if (map->freeslot == JSSLOT_FREE(clasp) && clasp->reserveSlots) {
+ /* Adjust map->freeslot to include computed reserved slots, if any. */
+ map->freeslot += clasp->reserveSlots(cx, obj);
+ }
+
+ if (map->freeslot >= STOBJ_NSLOTS(obj) &&
+ !js_ReallocSlots(cx, obj, map->freeslot + 1, JS_FALSE)) {
+ return JS_FALSE;
+ }
+
+ /* js_ReallocSlots or js_FreeSlot should set the free slots to void. */
+ JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, map->freeslot)));
+ *slotp = map->freeslot++;
+ return JS_TRUE;
+}
+
+void
+js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot)
+{
+ JSObjectMap *map;
+
+ map = obj->map;
+ JS_ASSERT(!MAP_IS_NATIVE(map) || ((JSScope *)map)->object == obj);
+ LOCKED_OBJ_SET_SLOT(obj, slot, JSVAL_VOID);
+ if (map->freeslot == slot + 1) {
+ map->freeslot = slot;
+
+ /* When shrinking, js_ReallocSlots always returns true. */
+ js_ReallocSlots(cx, obj, slot, JS_FALSE);
+ }
+}
+
+jsid
+js_CheckForStringIndex(jsid id, const jschar *cp, const jschar *end,
+ JSBool negative)
+{
+ jsuint index = JS7_UNDEC(*cp++);
+ jsuint oldIndex = 0;
+ jsuint c = 0;
+
+ if (index != 0) {
+ while (JS7_ISDEC(*cp)) {
+ oldIndex = index;
+ c = JS7_UNDEC(*cp);
+ index = 10 * index + c;
+ cp++;
+ }
+ }
+ if (cp == end &&
+ (oldIndex < (JSVAL_INT_MAX / 10) ||
+ (oldIndex == (JSVAL_INT_MAX / 10) &&
+ c <= (JSVAL_INT_MAX % 10)))) {
+ if (negative)
+ index = 0 - index;
+ id = INT_TO_JSID((jsint)index);
+ }
+ return id;
+}
+
+static JSBool
+PurgeProtoChain(JSContext *cx, JSObject *obj, jsid id)
+{
+ JSScope *scope;
+ JSScopeProperty *sprop;
+
+ while (obj) {
+ if (!OBJ_IS_NATIVE(obj)) {
+ obj = OBJ_GET_PROTO(cx, obj);
+ continue;
+ }
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ sprop = SCOPE_GET_PROPERTY(scope, id);
+ if (sprop) {
+ PCMETER(JS_PROPERTY_CACHE(cx).pcpurges++);
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+ }
+ obj = LOCKED_OBJ_GET_PROTO(scope->object);
+ JS_UNLOCK_SCOPE(cx, scope);
+ }
+ return JS_FALSE;
+}
+
+static void
+PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id)
+{
+ if (!OBJ_IS_DELEGATE(cx, obj))
+ return;
+
+ PurgeProtoChain(cx, OBJ_GET_PROTO(cx, obj), id);
+ while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL) {
+ if (PurgeProtoChain(cx, obj, id))
+ return;
+ }
+}
+
+JSScopeProperty *
+js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
+ JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
+ uintN attrs, uintN flags, intN shortid)
+{
+ JSScope *scope;
+ JSScopeProperty *sprop;
+
+ /*
+ * Purge the property cache of now-shadowed id in obj's scope chain. Do
+ * this optimistically (assuming no failure below) before locking obj, so
+ * we can lock the shadowed scope.
+ */
+ PurgeScopeChain(cx, obj, id);
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ sprop = NULL;
+ } else {
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+ sprop = js_AddScopeProperty(cx, scope, id, getter, setter, slot, attrs,
+ flags, shortid);
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ return sprop;
+}
+
+JSScopeProperty *
+js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
+ JSScopeProperty *sprop, uintN attrs, uintN mask,
+ JSPropertyOp getter, JSPropertyOp setter)
+{
+ JSScope *scope;
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ sprop = NULL;
+ } else {
+ sprop = js_ChangeScopePropertyAttrs(cx, scope, sprop, attrs, mask,
+ getter, setter);
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ return sprop;
+}
+
+JSBool
+js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ JSProperty **propp)
+{
+ return js_DefineNativeProperty(cx, obj, id, value, getter, setter, attrs,
+ 0, 0, propp);
+}
+
+/*
+ * Backward compatibility requires allowing addProperty hooks to mutate the
+ * nominal initial value of a slot-full property, while GC safety wants that
+ * value to be stored before the call-out through the hook. Optimize to do
+ * both while saving cycles for classes that stub their addProperty hook.
+ */
+#define ADD_PROPERTY_HELPER(cx,clasp,obj,scope,sprop,vp,cleanup) \
+ JS_BEGIN_MACRO \
+ if ((clasp)->addProperty != JS_PropertyStub) { \
+ jsval nominal_ = *(vp); \
+ if (!(clasp)->addProperty(cx, obj, SPROP_USERID(sprop), vp)) { \
+ cleanup; \
+ } \
+ if (*(vp) != nominal_) { \
+ if (SPROP_HAS_VALID_SLOT(sprop, scope)) \
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, (sprop)->slot, *(vp)); \
+ } \
+ } \
+ JS_END_MACRO
+
+JSBool
+js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ uintN flags, intN shortid, JSProperty **propp)
+{
+ JSClass *clasp;
+ JSScope *scope;
+ JSScopeProperty *sprop;
+
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+
+#if JS_HAS_GETTER_SETTER
+ /*
+ * If defining a getter or setter, we must check for its counterpart and
+ * update the attributes and property ops. A getter or setter is really
+ * only half of a property.
+ */
+ sprop = NULL;
+ if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
+ JSObject *pobj;
+ JSProperty *prop;
+
+ /*
+ * If JS_THREADSAFE and id is found, js_LookupProperty returns with
+ * sprop non-null and pobj locked. If pobj == obj, the property is
+ * already in obj and obj has its own (mutable) scope. So if we are
+ * defining a getter whose setter was already defined, or vice versa,
+ * finish the job via js_ChangeScopePropertyAttributes, and refresh
+ * the property cache line for (obj, id) to map sprop.
+ */
+ if (!js_LookupProperty(cx, obj, id, &pobj, &prop))
+ return JS_FALSE;
+ sprop = (JSScopeProperty *) prop;
+ if (sprop &&
+ pobj == obj &&
+ (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
+ sprop = js_ChangeScopePropertyAttrs(cx, OBJ_SCOPE(obj), sprop,
+ attrs, sprop->attrs,
+ (attrs & JSPROP_GETTER)
+ ? getter
+ : sprop->getter,
+ (attrs & JSPROP_SETTER)
+ ? setter
+ : sprop->setter);
+
+ /* NB: obj == pobj, so we can share unlock code at the bottom. */
+ if (!sprop)
+ goto bad;
+ } else if (prop) {
+ /* NB: call OBJ_DROP_PROPERTY, as pobj might not be native. */
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ prop = NULL;
+ sprop = NULL;
+ }
+ }
+#endif /* JS_HAS_GETTER_SETTER */
+
+ /*
+ * Purge the property cache of now-shadowed id in obj's scope chain.
+ * Do this early, before locking obj to avoid nesting locks.
+ */
+ PurgeScopeChain(cx, obj, id);
+
+ /* Lock if object locking is required by this implementation. */
+ JS_LOCK_OBJ(cx, obj);
+
+ /* Use the object's class getter and setter by default. */
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ if (!getter)
+ getter = clasp->getProperty;
+ if (!setter)
+ setter = clasp->setProperty;
+
+ /* Get obj's own scope if it has one, or create a new one for obj. */
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope)
+ goto bad;
+
+ if (!sprop) {
+ /* Add a new property, or replace an existing one of the same id. */
+ if (clasp->flags & JSCLASS_SHARE_ALL_PROPERTIES)
+ attrs |= JSPROP_SHARED;
+ sprop = js_AddScopeProperty(cx, scope, id, getter, setter,
+ SPROP_INVALID_SLOT, attrs, flags,
+ shortid);
+ if (!sprop)
+ goto bad;
+ }
+
+ /* Store value before calling addProperty, in case the latter GC's. */
+ if (SPROP_HAS_VALID_SLOT(sprop, scope))
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, sprop->slot, value);
+
+ /* XXXbe called with lock held */
+ ADD_PROPERTY_HELPER(cx, clasp, obj, scope, sprop, &value,
+ js_RemoveScopeProperty(cx, scope, id);
+ goto bad);
+
+ if (propp)
+ *propp = (JSProperty *) sprop;
+ else
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_TRUE;
+
+bad:
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+}
+
+/*
+ * Given pc pointing after a property accessing bytecode, return true if the
+ * access is "object-detecting" in the sense used by web scripts, e.g., when
+ * checking whether document.all is defined.
+ */
+static JSBool
+Detecting(JSContext *cx, jsbytecode *pc)
+{
+ JSScript *script;
+ jsbytecode *endpc;
+ JSOp op;
+ JSAtom *atom;
+
+ if (!cx->fp)
+ return JS_FALSE;
+ script = cx->fp->script;
+ for (endpc = script->code + script->length;
+ pc < endpc;
+ pc += js_CodeSpec[op].length) {
+ /* General case: a branch or equality op follows the access. */
+ op = (JSOp) *pc;
+ if (js_CodeSpec[op].format & JOF_DETECTING)
+ return JS_TRUE;
+
+ switch (op) {
+ case JSOP_NULL:
+ /*
+ * Special case #1: handle (document.all == null). Don't sweat
+ * about JS1.2's revision of the equality operators here.
+ */
+ if (++pc < endpc)
+ return *pc == JSOP_EQ || *pc == JSOP_NE;
+ return JS_FALSE;
+
+ case JSOP_NAME:
+ /*
+ * Special case #2: handle (document.all == undefined). Don't
+ * worry about someone redefining undefined, which was added by
+ * Edition 3, so is read/write for backward compatibility.
+ */
+ GET_ATOM_FROM_BYTECODE(script, pc, 0, atom);
+ if (atom == cx->runtime->atomState.typeAtoms[JSTYPE_VOID] &&
+ (pc += js_CodeSpec[op].length) < endpc) {
+ op = (JSOp) *pc;
+ return op == JSOP_EQ || op == JSOP_NE ||
+ op == JSOP_STRICTEQ || op == JSOP_STRICTNE;
+ }
+ return JS_FALSE;
+
+ default:
+ /*
+ * At this point, anything but an extended atom index prefix means
+ * we're not detecting.
+ */
+ if (!(js_CodeSpec[op].format & JOF_INDEXBASE))
+ return JS_FALSE;
+ break;
+ }
+ }
+ return JS_FALSE;
+}
+
+JS_FRIEND_API(JSBool)
+js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp)
+{
+ return js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
+ objp, propp) >= 0;
+}
+
+#define SCOPE_DEPTH_ACCUM(bs,val) \
+ JS_SCOPE_DEPTH_METERING(JS_BASIC_STATS_ACCUM(bs, val))
+
+int
+js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
+ JSObject **objp, JSProperty **propp)
+{
+ JSObject *start, *obj2, *proto;
+ int protoIndex;
+ JSScope *scope;
+ JSScopeProperty *sprop;
+ JSClass *clasp;
+ JSResolveOp resolve;
+ JSResolvingKey key;
+ JSResolvingEntry *entry;
+ uint32 generation;
+ JSNewResolveOp newresolve;
+ jsbytecode *pc;
+ const JSCodeSpec *cs;
+ uint32 format;
+ JSBool ok;
+
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+ JS_COUNT_OPERATION(cx, JSOW_LOOKUP_PROPERTY);
+
+ /* Search scopes starting with obj and following the prototype link. */
+ start = obj;
+ for (protoIndex = 0; ; protoIndex++) {
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ if (scope->object == obj) {
+ sprop = SCOPE_GET_PROPERTY(scope, id);
+ } else {
+ /* Shared prototype scope: try resolve before lookup. */
+ sprop = NULL;
+ }
+
+ /* Try obj's class resolve hook if id was not found in obj's scope. */
+ if (!sprop) {
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ resolve = clasp->resolve;
+ if (resolve != JS_ResolveStub) {
+ /* Avoid recursion on (obj, id) already being resolved on cx. */
+ key.obj = obj;
+ key.id = id;
+
+ /*
+ * Once we have successfully added an entry for (obj, key) to
+ * cx->resolvingTable, control must go through cleanup: before
+ * returning. But note that JS_DHASH_ADD may find an existing
+ * entry, in which case we bail to suppress runaway recursion.
+ */
+ if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry)) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return -1;
+ }
+ if (!entry) {
+ /* Already resolving id in obj -- suppress recursion. */
+ JS_UNLOCK_OBJ(cx, obj);
+ goto out;
+ }
+ generation = cx->resolvingTable->generation;
+
+ /* Null *propp here so we can test it at cleanup: safely. */
+ *propp = NULL;
+
+ if (clasp->flags & JSCLASS_NEW_RESOLVE) {
+ newresolve = (JSNewResolveOp)resolve;
+ if (flags == JSRESOLVE_INFER && cx->fp && cx->fp->regs) {
+ flags = 0;
+ pc = cx->fp->regs->pc;
+ cs = &js_CodeSpec[*pc];
+ format = cs->format;
+ if (JOF_MODE(format) != JOF_NAME)
+ flags |= JSRESOLVE_QUALIFIED;
+ if ((format & (JOF_SET | JOF_FOR)) ||
+ (cx->fp->flags & JSFRAME_ASSIGNING)) {
+ flags |= JSRESOLVE_ASSIGNING;
+ } else {
+ pc += cs->length;
+ if (Detecting(cx, pc))
+ flags |= JSRESOLVE_DETECTING;
+ }
+ if (format & JOF_DECLARING)
+ flags |= JSRESOLVE_DECLARING;
+ }
+ obj2 = (clasp->flags & JSCLASS_NEW_RESOLVE_GETS_START)
+ ? start
+ : NULL;
+ JS_UNLOCK_OBJ(cx, obj);
+
+ /* Protect id and all atoms from a GC nested in resolve. */
+ JS_KEEP_ATOMS(cx->runtime);
+ ok = newresolve(cx, obj, ID_TO_VALUE(id), flags, &obj2);
+ JS_UNKEEP_ATOMS(cx->runtime);
+ if (!ok)
+ goto cleanup;
+
+ JS_LOCK_OBJ(cx, obj);
+ if (obj2) {
+ /* Resolved: juggle locks and lookup id again. */
+ if (obj2 != obj) {
+ JS_UNLOCK_OBJ(cx, obj);
+ if (OBJ_IS_NATIVE(obj2))
+ JS_LOCK_OBJ(cx, obj2);
+ }
+ protoIndex = 0;
+ for (proto = start; proto && proto != obj2;
+ proto = OBJ_GET_PROTO(cx, proto)) {
+ protoIndex++;
+ }
+ scope = OBJ_SCOPE(obj2);
+ if (!MAP_IS_NATIVE(&scope->map)) {
+ /* Whoops, newresolve handed back a foreign obj2. */
+ JS_ASSERT(obj2 != obj);
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj2, id, objp, propp);
+ if (!ok || *propp)
+ goto cleanup;
+ JS_LOCK_OBJ(cx, obj2);
+ } else {
+ /*
+ * Require that obj2 have its own scope now, as we
+ * do for old-style resolve. If it doesn't, then
+ * id was not truly resolved, and we'll find it in
+ * the proto chain, or miss it if obj2's proto is
+ * not on obj's proto chain. That last case is a
+ * "too bad!" case.
+ */
+ if (scope->object == obj2)
+ sprop = SCOPE_GET_PROPERTY(scope, id);
+ }
+ if (sprop) {
+ JS_ASSERT(obj2 == scope->object);
+ obj = obj2;
+ } else if (obj2 != obj) {
+ if (OBJ_IS_NATIVE(obj2))
+ JS_UNLOCK_OBJ(cx, obj2);
+ JS_LOCK_OBJ(cx, obj);
+ }
+ }
+ } else {
+ /*
+ * Old resolve always requires id re-lookup if obj owns
+ * its scope after resolve returns.
+ */
+ JS_UNLOCK_OBJ(cx, obj);
+ ok = resolve(cx, obj, ID_TO_VALUE(id));
+ if (!ok)
+ goto cleanup;
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ JS_ASSERT(MAP_IS_NATIVE(&scope->map));
+ if (scope->object == obj)
+ sprop = SCOPE_GET_PROPERTY(scope, id);
+ }
+
+ cleanup:
+ js_StopResolving(cx, &key, JSRESFLAG_LOOKUP, entry, generation);
+ if (!ok)
+ return -1;
+ if (*propp)
+ return protoIndex;
+ }
+ }
+
+ if (sprop) {
+ SCOPE_DEPTH_ACCUM(&cx->runtime->protoLookupDepthStats, protoIndex);
+ JS_ASSERT(OBJ_SCOPE(obj) == scope);
+ *objp = scope->object; /* XXXbe hide in jsscope.[ch] */
+
+ *propp = (JSProperty *) sprop;
+ return protoIndex;
+ }
+
+ proto = LOCKED_OBJ_GET_PROTO(obj);
+ JS_UNLOCK_OBJ(cx, obj);
+ if (!proto)
+ break;
+ if (!OBJ_IS_NATIVE(proto)) {
+ if (!OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp))
+ return -1;
+ return protoIndex + 1;
+ }
+ obj = proto;
+ }
+
+out:
+ *objp = NULL;
+ *propp = NULL;
+ return protoIndex;
+}
+
+int
+js_FindPropertyHelper(JSContext *cx, jsid id, JSObject **objp,
+ JSObject **pobjp, JSProperty **propp,
+ JSPropCacheEntry **entryp)
+{
+ JSObject *obj, *pobj, *lastobj;
+ uint32 shape;
+ int scopeIndex, protoIndex;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ obj = cx->fp->scopeChain;
+ shape = OBJ_SHAPE(obj);
+ for (scopeIndex = 0; ; scopeIndex++) {
+ if (obj->map->ops->lookupProperty == js_LookupProperty) {
+ protoIndex =
+ js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
+ &pobj, &prop);
+ } else {
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
+ return -1;
+ protoIndex = -1;
+ }
+
+ if (prop) {
+ if (entryp) {
+ if (protoIndex >= 0 && OBJ_IS_NATIVE(pobj)) {
+ sprop = (JSScopeProperty *) prop;
+ js_FillPropertyCache(cx, cx->fp->scopeChain, shape,
+ scopeIndex, protoIndex, pobj, sprop,
+ entryp);
+ } else {
+ PCMETER(JS_PROPERTY_CACHE(cx).nofills++);
+ *entryp = NULL;
+ }
+ }
+ SCOPE_DEPTH_ACCUM(&rt->scopeSearchDepthStats, scopeIndex);
+ *objp = obj;
+ *pobjp = pobj;
+ *propp = prop;
+ return scopeIndex;
+ }
+
+ lastobj = obj;
+ obj = OBJ_GET_PARENT(cx, obj);
+ if (!obj)
+ break;
+ }
+
+ *objp = lastobj;
+ *pobjp = NULL;
+ *propp = NULL;
+ return scopeIndex;
+}
+
+JS_FRIEND_API(JSBool)
+js_FindProperty(JSContext *cx, jsid id, JSObject **objp, JSObject **pobjp,
+ JSProperty **propp)
+{
+ return js_FindPropertyHelper(cx, id, objp, pobjp, propp, NULL) >= 0;
+}
+
+JSObject *
+js_FindIdentifierBase(JSContext *cx, jsid id, JSPropCacheEntry *entry)
+{
+ JSObject *obj, *pobj;
+ JSProperty *prop;
+
+ /*
+ * Look for id's property along the "with" statement chain and the
+ * statically-linked scope chain.
+ */
+ if (js_FindPropertyHelper(cx, id, &obj, &pobj, &prop, &entry) < 0)
+ return NULL;
+ if (prop) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ return obj;
+ }
+
+ /*
+ * Use the top-level scope from the scope chain, which won't end in the
+ * same scope as cx->globalObject for cross-context function calls.
+ */
+ JS_ASSERT(obj);
+
+ /*
+ * Property not found. Give a strict warning if binding an undeclared
+ * top-level variable.
+ */
+ if (JS_HAS_STRICT_OPTION(cx)) {
+ JSString *str = JSVAL_TO_STRING(ID_TO_VALUE(id));
+ const char *bytes = js_GetStringBytes(cx, str);
+
+ if (!bytes ||
+ !JS_ReportErrorFlagsAndNumber(cx,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ js_GetErrorMessage, NULL,
+ JSMSG_UNDECLARED_VAR, bytes)) {
+ return NULL;
+ }
+ }
+
+ return obj;
+}
+
+JSBool
+js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
+ JSScopeProperty *sprop, jsval *vp)
+{
+ JSScope *scope;
+ uint32 slot;
+ int32 sample;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ JS_ASSERT(OBJ_IS_NATIVE(pobj));
+ JS_ASSERT(JS_IS_OBJ_LOCKED(cx, pobj));
+ scope = OBJ_SCOPE(pobj);
+ JS_ASSERT(scope->object == pobj);
+
+ slot = sprop->slot;
+ *vp = (slot != SPROP_INVALID_SLOT)
+ ? LOCKED_OBJ_GET_SLOT(pobj, slot)
+ : JSVAL_VOID;
+ if (SPROP_HAS_STUB_GETTER(sprop))
+ return JS_TRUE;
+
+ sample = cx->runtime->propertyRemovals;
+ JS_UNLOCK_SCOPE(cx, scope);
+ JS_PUSH_TEMP_ROOT_SPROP(cx, sprop, &tvr);
+ ok = SPROP_GET(cx, sprop, obj, pobj, vp);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+
+ JS_LOCK_SCOPE(cx, scope);
+ JS_ASSERT(scope->object == pobj);
+ if (SLOT_IN_SCOPE(slot, scope) &&
+ (JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
+ SCOPE_GET_PROPERTY(scope, sprop->id) == sprop)) {
+ LOCKED_OBJ_SET_SLOT(pobj, slot, *vp);
+ }
+
+ return JS_TRUE;
+}
+
+JSBool
+js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, jsval *vp)
+{
+ JSScope *scope;
+ uint32 slot;
+ int32 sample;
+ JSTempValueRooter tvr;
+ bool ok;
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ JS_ASSERT(JS_IS_OBJ_LOCKED(cx, obj));
+ scope = OBJ_SCOPE(obj);
+ JS_ASSERT(scope->object == obj);
+
+ slot = sprop->slot;
+ if (slot != SPROP_INVALID_SLOT) {
+ OBJ_CHECK_SLOT(obj, slot);
+
+ /* If sprop has a stub setter, keep scope locked and just store *vp. */
+ if (SPROP_HAS_STUB_SETTER(sprop))
+ goto set_slot;
+ } else {
+ /*
+ * Allow API consumers to create shared properties with stub setters.
+ * Such properties lack value storage, so setting them is like writing
+ * to /dev/null.
+ */
+ if (SPROP_HAS_STUB_SETTER(sprop))
+ return JS_TRUE;
+ }
+
+ sample = cx->runtime->propertyRemovals;
+ JS_UNLOCK_SCOPE(cx, scope);
+ JS_PUSH_TEMP_ROOT_SPROP(cx, sprop, &tvr);
+ ok = SPROP_SET(cx, sprop, obj, obj, vp);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+
+ JS_LOCK_SCOPE(cx, scope);
+ JS_ASSERT(scope->object == obj);
+ if (SLOT_IN_SCOPE(slot, scope) &&
+ (JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
+ SCOPE_GET_PROPERTY(scope, sprop->id) == sprop)) {
+ set_slot:
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, *vp);
+ }
+
+ return JS_TRUE;
+}
+
+JSBool
+js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+ JSPropCacheEntry **entryp)
+{
+ uint32 shape;
+ int protoIndex;
+ JSObject *obj2;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+ JS_COUNT_OPERATION(cx, JSOW_GET_PROPERTY);
+
+ shape = OBJ_SHAPE(obj);
+ protoIndex = js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
+ &obj2, &prop);
+ if (protoIndex < 0)
+ return JS_FALSE;
+ if (!prop) {
+ jsbytecode *pc;
+
+ *vp = JSVAL_VOID;
+
+ if (!OBJ_GET_CLASS(cx, obj)->getProperty(cx, obj, ID_TO_VALUE(id), vp))
+ return JS_FALSE;
+
+ if (entryp) {
+ PCMETER(JS_PROPERTY_CACHE(cx).nofills++);
+ *entryp = NULL;
+ }
+
+ /*
+ * Give a strict warning if foo.bar is evaluated by a script for an
+ * object foo with no property named 'bar'.
+ */
+ if (JSVAL_IS_VOID(*vp) && cx->fp && cx->fp->regs) {
+ JSOp op;
+ uintN flags;
+
+ pc = cx->fp->regs->pc;
+ op = (JSOp) *pc;
+ if (op == JSOP_GETXPROP) {
+ flags = JSREPORT_ERROR;
+ } else {
+ if (!JS_HAS_STRICT_OPTION(cx) ||
+ (op != JSOP_GETPROP && op != JSOP_GETELEM)) {
+ return JS_TRUE;
+ }
+
+ /*
+ * XXX do not warn about missing __iterator__ as the function
+ * may be called from JS_GetMethodById. See bug 355145.
+ */
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.iteratorAtom))
+ return JS_TRUE;
+
+ /* Kludge to allow (typeof foo == "undefined") tests. */
+ JS_ASSERT(cx->fp->script);
+ pc += js_CodeSpec[op].length;
+ if (Detecting(cx, pc))
+ return JS_TRUE;
+
+ flags = JSREPORT_WARNING | JSREPORT_STRICT;
+ }
+
+ /* Ok, bad undefined property reference: whine about it. */
+ if (!js_ReportValueErrorFlags(cx, flags, JSMSG_UNDEFINED_PROP,
+ JSDVG_IGNORE_STACK, ID_TO_VALUE(id),
+ NULL, NULL, NULL)) {
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+ }
+
+ if (!OBJ_IS_NATIVE(obj2)) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return OBJ_GET_PROPERTY(cx, obj2, id, vp);
+ }
+
+ sprop = (JSScopeProperty *) prop;
+ if (!js_NativeGet(cx, obj, obj2, sprop, vp))
+ return JS_FALSE;
+
+ if (entryp)
+ js_FillPropertyCache(cx, obj, shape, 0, protoIndex, obj2, sprop, entryp);
+ JS_UNLOCK_OBJ(cx, obj2);
+ return JS_TRUE;
+}
+
+JSBool
+js_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return js_GetPropertyHelper(cx, obj, id, vp, NULL);
+}
+
+JSBool
+js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+ JSPropCacheEntry **entryp)
+{
+ uint32 shape;
+ int protoIndex;
+ JSObject *pobj;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ JSScope *scope;
+ uintN attrs, flags;
+ intN shortid;
+ JSClass *clasp;
+ JSPropertyOp getter, setter;
+
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+ JS_COUNT_OPERATION(cx, JSOW_SET_PROPERTY);
+
+ shape = OBJ_SHAPE(obj);
+ protoIndex = js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
+ &pobj, &prop);
+ if (protoIndex < 0)
+ return JS_FALSE;
+
+ if (prop && !OBJ_IS_NATIVE(pobj)) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ prop = NULL;
+ }
+ sprop = (JSScopeProperty *) prop;
+
+ /*
+ * Now either sprop is null, meaning id was not found in obj or one of its
+ * prototypes; or sprop is non-null, meaning id was found in pobj's scope.
+ * If JS_THREADSAFE and sprop is non-null, then scope is locked, and sprop
+ * is held: we must OBJ_DROP_PROPERTY or JS_UNLOCK_SCOPE before we return
+ * (the two are equivalent for native objects, but we use JS_UNLOCK_SCOPE
+ * because it is cheaper).
+ */
+ attrs = JSPROP_ENUMERATE;
+ flags = 0;
+ shortid = 0;
+ clasp = OBJ_GET_CLASS(cx, obj);
+ getter = clasp->getProperty;
+ setter = clasp->setProperty;
+
+ if (sprop) {
+ /*
+ * Set scope for use below. It was locked by js_LookupProperty, and
+ * we know pobj owns it (i.e., scope->object == pobj). Therefore we
+ * optimize JS_UNLOCK_OBJ(cx, pobj) into JS_UNLOCK_SCOPE(cx, scope).
+ */
+ scope = OBJ_SCOPE(pobj);
+
+ attrs = sprop->attrs;
+ if ((attrs & JSPROP_READONLY) ||
+ (SCOPE_IS_SEALED(scope) && pobj == obj)) {
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ /*
+ * Here, we'll either return true or goto read_only_error, which
+ * reports a strict warning or throws an error. So we redefine
+ * the |flags| local variable to be JSREPORT_* flags to pass to
+ * JS_ReportErrorFlagsAndNumberUC at label read_only_error. We
+ * must likewise re-task flags further below for the other 'goto
+ * read_only_error;' case.
+ */
+ flags = JSREPORT_ERROR;
+ if (attrs & JSPROP_READONLY) {
+ if (!JS_HAS_STRICT_OPTION(cx)) {
+ /* Just return true per ECMA if not in strict mode. */
+ PCMETER(!entryp || JS_PROPERTY_CACHE(cx).rofills++);
+ return JS_TRUE;
+ }
+
+ /* Strict mode: report a read-only strict warning. */
+ flags = JSREPORT_STRICT | JSREPORT_WARNING;
+ }
+ goto read_only_error;
+ }
+
+ if (pobj != obj) {
+ /*
+ * We found id in a prototype object: prepare to share or shadow.
+ *
+ * NB: Thanks to the immutable, garbage-collected property tree
+ * maintained by jsscope.c in cx->runtime, we needn't worry about
+ * sprop going away behind our back after we've unlocked scope.
+ */
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ /*
+ * Don't clone a shared prototype property. Don't fill it in the
+ * property cache either, since the JSOP_SETPROP/JSOP_SETNAME code
+ * in js_Interpret does not handle shared or prototype properties.
+ * Shared prototype properties require more hit qualification than
+ * the fast-path code for those ops, which is targeted on direct,
+ * slot-based properties.
+ */
+ if (attrs & JSPROP_SHARED) {
+ if (entryp) {
+ PCMETER(JS_PROPERTY_CACHE(cx).nofills++);
+ *entryp = NULL;
+ }
+
+ if (SPROP_HAS_STUB_SETTER(sprop) &&
+ !(sprop->attrs & JSPROP_GETTER)) {
+ return JS_TRUE;
+ }
+
+ return !!SPROP_SET(cx, sprop, obj, pobj, vp);
+ }
+
+ /* Restore attrs to the ECMA default for new properties. */
+ attrs = JSPROP_ENUMERATE;
+
+ /*
+ * Preserve the shortid, getter, and setter when shadowing any
+ * property that has a shortid. An old API convention requires
+ * that the property's getter and setter functions receive the
+ * shortid, not id, when they are called on the shadow we are
+ * about to create in obj's scope.
+ */
+ if (sprop->flags & SPROP_HAS_SHORTID) {
+ flags = SPROP_HAS_SHORTID;
+ shortid = sprop->shortid;
+ getter = sprop->getter;
+ setter = sprop->setter;
+ }
+
+ /*
+ * Forget we found the proto-property now that we've copied any
+ * needed member values.
+ */
+ sprop = NULL;
+ }
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ } else {
+ scope = NULL;
+#endif
+ }
+
+ if (!sprop) {
+ if (SCOPE_IS_SEALED(OBJ_SCOPE(obj)) && OBJ_SCOPE(obj)->object == obj) {
+ flags = JSREPORT_ERROR;
+ goto read_only_error;
+ }
+
+ /*
+ * Purge the property cache of now-shadowed id in obj's scope chain.
+ * Do this early, before locking obj to avoid nesting locks.
+ */
+ PurgeScopeChain(cx, obj, id);
+
+ /* Find or make a property descriptor with the right heritage. */
+ JS_LOCK_OBJ(cx, obj);
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+ }
+ if (clasp->flags & JSCLASS_SHARE_ALL_PROPERTIES)
+ attrs |= JSPROP_SHARED;
+ sprop = js_AddScopeProperty(cx, scope, id, getter, setter,
+ SPROP_INVALID_SLOT, attrs, flags, shortid);
+ if (!sprop) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE;
+ }
+
+ /*
+ * Initialize the new property value (passed to setter) to undefined.
+ * Note that we store before calling addProperty, to match the order
+ * in js_DefineNativeProperty.
+ */
+ if (SPROP_HAS_VALID_SLOT(sprop, scope))
+ LOCKED_OBJ_SET_SLOT(obj, sprop->slot, JSVAL_VOID);
+
+ /* XXXbe called with obj locked */
+ ADD_PROPERTY_HELPER(cx, clasp, obj, scope, sprop, vp,
+ js_RemoveScopeProperty(cx, scope, id);
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE);
+ }
+
+ if (!js_NativeSet(cx, obj, sprop, vp))
+ return JS_FALSE;
+
+ if (entryp) {
+ if (!(attrs & JSPROP_SHARED))
+ js_FillPropertyCache(cx, obj, shape, 0, 0, obj, sprop, entryp);
+ else
+ PCMETER(JS_PROPERTY_CACHE(cx).nofills++);
+ }
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+
+ read_only_error:
+ return js_ReportValueErrorFlags(cx, flags, JSMSG_READ_ONLY,
+ JSDVG_IGNORE_STACK, ID_TO_VALUE(id), NULL,
+ NULL, NULL);
+}
+
+JSBool
+js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return js_SetPropertyHelper(cx, obj, id, vp, NULL);
+}
+
+JSBool
+js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSBool noprop, ok;
+ JSScopeProperty *sprop;
+
+ noprop = !prop;
+ if (noprop) {
+ if (!js_LookupProperty(cx, obj, id, &obj, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ *attrsp = 0;
+ return JS_TRUE;
+ }
+ if (!OBJ_IS_NATIVE(obj)) {
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, attrsp);
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+ }
+ }
+ sprop = (JSScopeProperty *)prop;
+ *attrsp = sprop->attrs;
+ if (noprop)
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return JS_TRUE;
+}
+
+JSBool
+js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSBool noprop, ok;
+ JSScopeProperty *sprop;
+
+ noprop = !prop;
+ if (noprop) {
+ if (!js_LookupProperty(cx, obj, id, &obj, &prop))
+ return JS_FALSE;
+ if (!prop)
+ return JS_TRUE;
+ if (!OBJ_IS_NATIVE(obj)) {
+ ok = OBJ_SET_ATTRIBUTES(cx, obj, id, prop, attrsp);
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+ }
+ }
+ sprop = (JSScopeProperty *)prop;
+ sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, *attrsp, 0,
+ sprop->getter, sprop->setter);
+ if (noprop)
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return (sprop != NULL);
+}
+
+JSBool
+js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
+{
+ JSObject *proto;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ JSScope *scope;
+ JSBool ok;
+
+ *rval = JSVAL_TRUE;
+
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+ JS_COUNT_OPERATION(cx, JSOW_DELETE_PROPERTY);
+
+ if (!js_LookupProperty(cx, obj, id, &proto, &prop))
+ return JS_FALSE;
+ if (!prop || proto != obj) {
+ /*
+ * If the property was found in a native prototype, check whether it's
+ * shared and permanent. Such a property stands for direct properties
+ * in all delegating objects, matching ECMA semantics without bloating
+ * each delegating object.
+ */
+ if (prop) {
+ if (OBJ_IS_NATIVE(proto)) {
+ sprop = (JSScopeProperty *)prop;
+ if (SPROP_IS_SHARED_PERMANENT(sprop))
+ *rval = JSVAL_FALSE;
+ }
+ OBJ_DROP_PROPERTY(cx, proto, prop);
+ if (*rval == JSVAL_FALSE)
+ return JS_TRUE;
+ }
+
+ /*
+ * If no property, or the property comes unshared or impermanent from
+ * a prototype, call the class's delProperty hook, passing rval as the
+ * result parameter.
+ */
+ return OBJ_GET_CLASS(cx, obj)->delProperty(cx, obj, ID_TO_VALUE(id),
+ rval);
+ }
+
+ sprop = (JSScopeProperty *)prop;
+ if (sprop->attrs & JSPROP_PERMANENT) {
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ *rval = JSVAL_FALSE;
+ return JS_TRUE;
+ }
+
+ /* XXXbe called with obj locked */
+ if (!LOCKED_OBJ_GET_CLASS(obj)->delProperty(cx, obj, SPROP_USERID(sprop),
+ rval)) {
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return JS_FALSE;
+ }
+
+ scope = OBJ_SCOPE(obj);
+ if (SPROP_HAS_VALID_SLOT(sprop, scope))
+ GC_POKE(cx, LOCKED_OBJ_GET_SLOT(obj, sprop->slot));
+
+ ok = js_RemoveScopeProperty(cx, scope, id);
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+JSBool
+js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
+{
+ jsval v, save;
+ JSString *str;
+
+ v = save = OBJECT_TO_JSVAL(obj);
+ switch (hint) {
+ case JSTYPE_STRING:
+ /*
+ * Propagate the exception if js_TryMethod finds an appropriate
+ * method, and calling that method returned failure.
+ */
+ if (!js_TryMethod(cx, obj, cx->runtime->atomState.toStringAtom, 0, NULL,
+ &v)) {
+ return JS_FALSE;
+ }
+
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, hint, &v))
+ return JS_FALSE;
+ }
+ break;
+
+ default:
+ if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, hint, &v))
+ return JS_FALSE;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ JSType type = JS_TypeOfValue(cx, v);
+ if (type == hint ||
+ (type == JSTYPE_FUNCTION && hint == JSTYPE_OBJECT)) {
+ goto out;
+ }
+ if (!js_TryMethod(cx, obj, cx->runtime->atomState.toStringAtom, 0,
+ NULL, &v)) {
+ return JS_FALSE;
+ }
+ }
+ break;
+ }
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ /* Avoid recursive death when decompiling in js_ReportValueError. */
+ if (hint == JSTYPE_STRING) {
+ str = JS_InternString(cx, OBJ_GET_CLASS(cx, obj)->name);
+ if (!str)
+ return JS_FALSE;
+ } else {
+ str = NULL;
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ js_ReportValueError2(cx, JSMSG_CANT_CONVERT_TO,
+ JSDVG_SEARCH_STACK, save, str,
+ (hint == JSTYPE_VOID)
+ ? "primitive type"
+ : JS_TYPE_STR(hint));
+ return JS_FALSE;
+ }
+out:
+ *vp = v;
+ return JS_TRUE;
+}
+
+/*
+ * Private type used to enumerate properties of a native JS object. It is
+ * allocated as necessary from JSENUMERATE_INIT and is freed when running the
+ * GC. The structure is not allocated when there are no enumerable properties
+ * in the object. Instead for the empty enumerator the code uses JSVAL_ZERO as
+ * the enumeration state.
+ *
+ * JSRuntime.nativeEnumCache caches the enumerators using scope's shape to
+ * avoid repeated scanning of scopes for enumerable properties. The cache
+ * entry is either JSNativeEnumerator* or, for the empty enumerator, the shape
+ * value itself. The latter is stored as (shape << 1) | 1 to ensure that it is
+ * always different from JSNativeEnumerator* values.
+ */
+struct JSNativeEnumerator {
+ /*
+ * The index into the ids array. It runs from the length down to 1 when
+ * the enumerator is running. It is 0 when the enumerator is finished and
+ * can be reused on a cache hit. Its type is jsword, not uint32, for
+ * compatibility with js_CompareAndSwap.
+ */
+ jsword cursor;
+
+ uint32 length; /* length of ids array */
+ uint32 shape; /* "shape" number -- see jsscope.h */
+ JSNativeEnumerator *next; /* list linking */
+ jsid ids[1]; /* enumeration id array */
+};
+
+/* The tagging of shape values requires one bit. */
+JS_STATIC_ASSERT((jsuword) SHAPE_OVERFLOW_BIT <=
+ ((jsuword) 1 << (JS_BITS_PER_WORD - 1)));
+
+static inline size_t
+NativeEnumeratorSize(uint32 length)
+{
+ JS_ASSERT(length != 0);
+ return offsetof(JSNativeEnumerator, ids) + (size_t) length * sizeof(jsid);
+}
+
+/*
+ * This function is used to enumerate the properties of native JSObjects
+ * and those host objects that do not define a JSNewEnumerateOp-style iterator
+ * function.
+ */
+JSBool
+js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ JSClass *clasp;
+ JSEnumerateOp enumerate;
+ JSNativeEnumerator *ne;
+ uint32 length, shape;
+ size_t allocated;
+ JSScope *scope;
+ jsuword *cachep, oldcache;
+ JSScopeProperty *sprop;
+ jsid *ids;
+ jsword newcursor;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ enumerate = clasp->enumerate;
+ if (clasp->flags & JSCLASS_NEW_ENUMERATE) {
+ JS_ASSERT(enumerate != JS_EnumerateStub);
+ return ((JSNewEnumerateOp) enumerate)(cx, obj, enum_op, statep, idp);
+ }
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ if (!enumerate(cx, obj))
+ return JS_FALSE;
+
+ /*
+ * The set of all property ids is pre-computed when the iterator is
+ * initialized to avoid problems caused by properties being deleted
+ * during the iteration.
+ *
+ * Use a do-while(0) loop to avoid too many nested ifs. If ne is null
+ * after the loop, it indicates an empty enumerator. If allocated is
+ * not zero after the loop, we add the newly allocated ne to the cache
+ * and runtime->nativeEnumerators list.
+ */
+ ne = NULL;
+ length = 0;
+ allocated = (size_t) 0;
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ do {
+ /*
+ * If this object shares a scope with its prototype, don't
+ * enumerate its properties. Otherwise they will be enumerated
+ * a second time when the prototype object is enumerated.
+ */
+ if (scope->object != obj) {
+#ifdef __GNUC__
+ cachep = NULL; /* suppress bogus gcc warnings */
+#endif
+ break;
+ }
+
+ ENUM_CACHE_METER(nativeEnumProbes);
+ shape = scope->shape;
+ JS_ASSERT(shape < SHAPE_OVERFLOW_BIT);
+ cachep = &cx->runtime->
+ nativeEnumCache[NATIVE_ENUM_CACHE_HASH(shape)];
+ oldcache = *cachep;
+ if (oldcache & (jsuword) 1) {
+ if ((uint32) (oldcache >> 1) == shape) {
+ /* scope has a shape with no enumerable properties. */
+ break;
+ }
+ } else if (oldcache != (jsuword) 0) {
+ /*
+ * We can safely read ne->shape without taking the GC lock as
+ * ne is deleted only when running the GC and ne->shape is
+ * read-only after initialization.
+ */
+ ne = (JSNativeEnumerator *) *cachep;
+ JS_ASSERT(ne->length >= 1);
+ if (ne->shape == shape) {
+ /*
+ * Check that ne is not running with another enumerator
+ * and, if so, reuse and mark it as running from now.
+ */
+ length = ne->length;
+ if (js_CompareAndSwap(&ne->cursor, 0, length))
+ break;
+ length = 0;
+ }
+ ne = NULL;
+ }
+ ENUM_CACHE_METER(nativeEnumMisses);
+
+ /* Count all enumerable properties in object's scope. */
+ JS_ASSERT(length == 0);
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
+ if ((sprop->attrs & JSPROP_ENUMERATE) &&
+ !(sprop->flags & SPROP_IS_ALIAS) &&
+ (!SCOPE_HAD_MIDDLE_DELETE(scope) ||
+ SCOPE_HAS_PROPERTY(scope, sprop))) {
+ length++;
+ }
+ }
+ if (length == 0) {
+ /* cache the scope without enumerable properties. */
+ *cachep = ((jsuword) shape << 1) | (jsuword) 1;
+ break;
+ }
+
+ allocated = NativeEnumeratorSize(length);
+ ne = (JSNativeEnumerator *) JS_malloc(cx, allocated);
+ if (!ne) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE;
+ }
+ ne->cursor = length;
+ ne->length = length;
+ ne->shape = shape;
+ ids = ne->ids;
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
+ if ((sprop->attrs & JSPROP_ENUMERATE) &&
+ !(sprop->flags & SPROP_IS_ALIAS) &&
+ (!SCOPE_HAD_MIDDLE_DELETE(scope) ||
+ SCOPE_HAS_PROPERTY(scope, sprop))) {
+ JS_ASSERT(ids < ne->ids + length);
+ *ids++ = sprop->id;
+ }
+ }
+ JS_ASSERT(ids == ne->ids + length);
+ } while (0);
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ if (!ne) {
+ JS_ASSERT(length == 0);
+ JS_ASSERT(allocated == 0);
+ *statep = JSVAL_ZERO;
+ } else {
+ JS_ASSERT(length != 0);
+ JS_ASSERT(ne->cursor == (jsword) length);
+ if (allocated != 0) {
+ JS_LOCK_GC(cx->runtime);
+ if (!js_AddAsGCBytes(cx, allocated)) {
+ /* js_AddAsGCBytes releases the GC lock on failures. */
+ JS_free(cx, ne);
+ return JS_FALSE;
+ }
+ ne->next = cx->runtime->nativeEnumerators;
+ cx->runtime->nativeEnumerators = ne;
+ JS_ASSERT(((jsuword) ne & (jsuword) 1) == (jsuword) 0);
+ *cachep = (jsuword) ne;
+ JS_UNLOCK_GC(cx->runtime);
+ }
+ *statep = PRIVATE_TO_JSVAL(ne);
+ }
+ if (idp)
+ *idp = INT_TO_JSVAL(length);
+ break;
+
+ case JSENUMERATE_NEXT:
+ case JSENUMERATE_DESTROY:
+ if (*statep == JSVAL_ZERO) {
+ *statep = JSVAL_NULL;
+ break;
+ }
+ ne = (JSNativeEnumerator *) JSVAL_TO_PRIVATE(*statep);
+ JS_ASSERT(ne->length >= 1);
+ JS_ASSERT(ne->cursor >= 1);
+
+ /*
+ * We must not access ne->cursor when we set it to zero as it means
+ * that ne is free and another thread can grab it from the cache. So
+ * we set the state to JSVAL_ZERO in the NEXT case to avoid touching
+ * ne->length again in the DESTROY case.
+ */
+ if (enum_op == JSENUMERATE_NEXT) {
+ newcursor = ne->cursor - 1;
+ *idp = ne->ids[newcursor];
+ ne->cursor = newcursor;
+ if (newcursor == 0)
+ *statep = JSVAL_ZERO;
+ } else {
+ /* The enumerator has not iterated over all ids. */
+ ne->cursor = 0;
+ }
+ break;
+ }
+ return JS_TRUE;
+}
+
+void
+js_TraceNativeEnumerators(JSTracer *trc)
+{
+ JSRuntime *rt;
+ JSNativeEnumerator **nep, *ne;
+ jsid *cursor, *end;
+
+ /*
+ * Purge native enumerators cached by shape id, which we are about to
+ * re-number completely when tracing is done for the GC.
+ */
+ rt = trc->context->runtime;
+ if (IS_GC_MARKING_TRACER(trc)) {
+ memset(&rt->nativeEnumCache, 0, sizeof rt->nativeEnumCache);
+#ifdef JS_DUMP_ENUM_CACHE_STATS
+ printf("nativeEnumCache hit rate %g%%\n",
+ 100.0 * (rt->nativeEnumProbes - rt->nativeEnumMisses) /
+ rt->nativeEnumProbes);
+#endif
+ }
+
+ nep = &rt->nativeEnumerators;
+ while ((ne = *nep) != NULL) {
+ JS_ASSERT(ne->length != 0);
+ if (ne->cursor != 0) {
+ /* Trace ids of the running enumerator. */
+ cursor = ne->ids;
+ end = cursor + ne->length;
+ do {
+ TRACE_ID(trc, *cursor);
+ } while (++cursor != end);
+ } else if (IS_GC_MARKING_TRACER(trc)) {
+ js_RemoveAsGCBytes(rt, NativeEnumeratorSize(ne->length));
+ *nep = ne->next;
+ JS_free(trc->context, ne);
+ continue;
+ }
+ nep = &ne->next;
+ }
+}
+
+JSBool
+js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp)
+{
+ JSBool writing;
+ JSObject *pobj;
+ JSProperty *prop;
+ JSClass *clasp;
+ JSScopeProperty *sprop;
+ JSSecurityCallbacks *callbacks;
+ JSCheckAccessOp check;
+
+ writing = (mode & JSACC_WRITE) != 0;
+ switch (mode & JSACC_TYPEMASK) {
+ case JSACC_PROTO:
+ pobj = obj;
+ if (!writing)
+ *vp = OBJECT_TO_JSVAL(OBJ_GET_PROTO(cx, obj));
+ *attrsp = JSPROP_PERMANENT;
+ break;
+
+ case JSACC_PARENT:
+ JS_ASSERT(!writing);
+ pobj = obj;
+ *vp = OBJECT_TO_JSVAL(OBJ_GET_PARENT(cx, obj));
+ *attrsp = JSPROP_READONLY | JSPROP_PERMANENT;
+ break;
+
+ default:
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ if (!writing)
+ *vp = JSVAL_VOID;
+ *attrsp = 0;
+ pobj = obj;
+ break;
+ }
+
+ if (!OBJ_IS_NATIVE(pobj)) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+
+ /* Avoid diverging for non-natives that reuse js_CheckAccess. */
+ if (pobj->map->ops->checkAccess == js_CheckAccess) {
+ if (!writing) {
+ *vp = JSVAL_VOID;
+ *attrsp = 0;
+ }
+ break;
+ }
+ return OBJ_CHECK_ACCESS(cx, pobj, id, mode, vp, attrsp);
+ }
+
+ sprop = (JSScopeProperty *)prop;
+ *attrsp = sprop->attrs;
+ if (!writing) {
+ *vp = (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)))
+ ? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot)
+ : JSVAL_VOID;
+ }
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+
+ /*
+ * If obj's class has a stub (null) checkAccess hook, use the per-runtime
+ * checkObjectAccess callback, if configured.
+ *
+ * We don't want to require all classes to supply a checkAccess hook; we
+ * need that hook only for certain classes used when precompiling scripts
+ * and functions ("brutal sharing"). But for general safety of built-in
+ * magic properties such as __proto__ and __parent__, we route all access
+ * checks, even for classes that stub out checkAccess, through the global
+ * checkObjectAccess hook. This covers precompilation-based sharing and
+ * (possibly unintended) runtime sharing across trust boundaries.
+ */
+ clasp = OBJ_GET_CLASS(cx, pobj);
+ check = clasp->checkAccess;
+ if (!check) {
+ callbacks = JS_GetSecurityCallbacks(cx);
+ check = callbacks ? callbacks->checkObjectAccess : NULL;
+ }
+ return !check || check(cx, pobj, ID_TO_VALUE(id), mode, vp);
+}
+
+#ifdef JS_THREADSAFE
+void
+js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop)
+{
+ JS_UNLOCK_OBJ(cx, obj);
+}
+#endif
+
+#ifdef NARCISSUS
+static JSBool
+GetCurrentExecutionContext(JSContext *cx, JSObject *obj, jsval *rval)
+{
+ JSObject *tmp;
+ jsval xcval;
+
+ while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL)
+ obj = tmp;
+ if (!OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .ExecutionContextAtom),
+ &xcval)) {
+ return JS_FALSE;
+ }
+ if (JSVAL_IS_PRIMITIVE(xcval)) {
+ JS_ReportError(cx, "invalid ExecutionContext in global object");
+ return JS_FALSE;
+ }
+ if (!OBJ_GET_PROPERTY(cx, JSVAL_TO_OBJECT(xcval),
+ ATOM_TO_JSID(cx->runtime->atomState.currentAtom),
+ rval)) {
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+#endif
+
+JSBool
+js_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[-2]));
+ if (!clasp->call) {
+#ifdef NARCISSUS
+ JSObject *callee, *args;
+ jsval fval, nargv[3];
+ JSBool ok;
+
+ callee = JSVAL_TO_OBJECT(argv[-2]);
+ if (!OBJ_GET_PROPERTY(cx, callee,
+ ATOM_TO_JSID(cx->runtime->atomState.__call__Atom),
+ &fval)) {
+ return JS_FALSE;
+ }
+ if (VALUE_IS_FUNCTION(cx, fval)) {
+ if (!GetCurrentExecutionContext(cx, obj, &nargv[2]))
+ return JS_FALSE;
+ args = js_GetArgsObject(cx, cx->fp);
+ if (!args)
+ return JS_FALSE;
+ nargv[0] = OBJECT_TO_JSVAL(obj);
+ nargv[1] = OBJECT_TO_JSVAL(args);
+ return js_InternalCall(cx, callee, fval, 3, nargv, rval);
+ }
+ if (JSVAL_IS_OBJECT(fval) && JSVAL_TO_OBJECT(fval) != callee) {
+ argv[-2] = fval;
+ ok = js_Call(cx, obj, argc, argv, rval);
+ argv[-2] = OBJECT_TO_JSVAL(callee);
+ return ok;
+ }
+#endif
+ js_ReportIsNotFunction(cx, &argv[-2], cx->fp->flags & JSFRAME_ITERATOR);
+ return JS_FALSE;
+ }
+ return clasp->call(cx, obj, argc, argv, rval);
+}
+
+JSBool
+js_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[-2]));
+ if (!clasp->construct) {
+#ifdef NARCISSUS
+ JSObject *callee, *args;
+ jsval cval, nargv[2];
+ JSBool ok;
+
+ callee = JSVAL_TO_OBJECT(argv[-2]);
+ if (!OBJ_GET_PROPERTY(cx, callee,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .__construct__Atom),
+ &cval)) {
+ return JS_FALSE;
+ }
+ if (VALUE_IS_FUNCTION(cx, cval)) {
+ if (!GetCurrentExecutionContext(cx, obj, &nargv[1]))
+ return JS_FALSE;
+ args = js_GetArgsObject(cx, cx->fp);
+ if (!args)
+ return JS_FALSE;
+ nargv[0] = OBJECT_TO_JSVAL(args);
+ return js_InternalCall(cx, callee, cval, 2, nargv, rval);
+ }
+ if (JSVAL_IS_OBJECT(cval) && JSVAL_TO_OBJECT(cval) != callee) {
+ argv[-2] = cval;
+ ok = js_Call(cx, obj, argc, argv, rval);
+ argv[-2] = OBJECT_TO_JSVAL(callee);
+ return ok;
+ }
+#endif
+ js_ReportIsNotFunction(cx, &argv[-2], JSV2F_CONSTRUCT);
+ return JS_FALSE;
+ }
+ return clasp->construct(cx, obj, argc, argv, rval);
+}
+
+JSBool
+js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp->hasInstance)
+ return clasp->hasInstance(cx, obj, v, bp);
+#ifdef NARCISSUS
+ {
+ jsval fval, rval;
+
+ if (!OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .__hasInstance__Atom),
+ &fval)) {
+ return JS_FALSE;
+ }
+ if (VALUE_IS_FUNCTION(cx, fval)) {
+ if (!js_InternalCall(cx, obj, fval, 1, &v, &rval))
+ return JS_FALSE;
+ *bp = js_ValueToBoolean(rval);
+ return JS_TRUE;
+ }
+ }
+#endif
+ js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
+ JSDVG_SEARCH_STACK, OBJECT_TO_JSVAL(obj), NULL);
+ return JS_FALSE;
+}
+
+JSBool
+js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ JSObject *obj2;
+
+ *bp = JS_FALSE;
+ if (JSVAL_IS_PRIMITIVE(v))
+ return JS_TRUE;
+ obj2 = JSVAL_TO_OBJECT(v);
+ while ((obj2 = OBJ_GET_PROTO(cx, obj2)) != NULL) {
+ if (obj2 == obj) {
+ *bp = JS_TRUE;
+ break;
+ }
+ }
+ return JS_TRUE;
+}
+
+JSBool
+js_GetClassPrototype(JSContext *cx, JSObject *scope, jsid id,
+ JSObject **protop)
+{
+ jsval v;
+ JSObject *ctor;
+
+ if (!js_FindClassObject(cx, scope, id, &v))
+ return JS_FALSE;
+ if (VALUE_IS_FUNCTION(cx, v)) {
+ ctor = JSVAL_TO_OBJECT(v);
+ if (!OBJ_GET_PROPERTY(cx, ctor,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &v)) {
+ return JS_FALSE;
+ }
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ /*
+ * Set the newborn root in case v is otherwise unreferenced.
+ * It's ok to overwrite newborn roots here, since the getter
+ * called just above could have. Unlike the common GC rooting
+ * model, our callers do not have to protect protop thanks to
+ * this newborn root, since they all immediately create a new
+ * instance that delegates to this object, or just query the
+ * prototype for its class.
+ */
+ cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(v);
+ }
+ }
+ *protop = JSVAL_IS_OBJECT(v) ? JSVAL_TO_OBJECT(v) : NULL;
+ return JS_TRUE;
+}
+
+/*
+ * For shared precompilation of function objects, we support cloning on entry
+ * to an execution context in which the function declaration or expression
+ * should be processed as if it were not precompiled, where the precompiled
+ * function's scope chain does not match the execution context's. The cloned
+ * function object carries its execution-context scope in its parent slot; it
+ * links to the precompiled function (the "clone-parent") via its proto slot.
+ *
+ * Note that this prototype-based delegation leaves an unchecked access path
+ * from the clone to the clone-parent's 'constructor' property. If the clone
+ * lives in a less privileged or shared scope than the clone-parent, this is
+ * a security hole, a sharing hazard, or both. Therefore we check all such
+ * accesses with the following getter/setter pair, which we use when defining
+ * 'constructor' in f.prototype for all function objects f.
+ */
+static JSBool
+CheckCtorGetAccess(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSAtom *atom;
+ uintN attrs;
+
+ atom = cx->runtime->atomState.constructorAtom;
+ JS_ASSERT(id == ATOM_TO_JSID(atom));
+ return OBJ_CHECK_ACCESS(cx, obj, ATOM_TO_JSID(atom), JSACC_READ,
+ vp, &attrs);
+}
+
+static JSBool
+CheckCtorSetAccess(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSAtom *atom;
+ uintN attrs;
+
+ atom = cx->runtime->atomState.constructorAtom;
+ JS_ASSERT(id == ATOM_TO_JSID(atom));
+ return OBJ_CHECK_ACCESS(cx, obj, ATOM_TO_JSID(atom), JSACC_WRITE,
+ vp, &attrs);
+}
+
+JSBool
+js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto,
+ uintN attrs)
+{
+ /*
+ * Use the given attributes for the prototype property of the constructor,
+ * as user-defined constructors have a DontDelete prototype (which may be
+ * reset), while native or "system" constructors have DontEnum | ReadOnly |
+ * DontDelete.
+ */
+ if (!OBJ_DEFINE_PROPERTY(cx, ctor,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ OBJECT_TO_JSVAL(proto),
+ JS_PropertyStub, JS_PropertyStub,
+ attrs, NULL)) {
+ return JS_FALSE;
+ }
+
+ /*
+ * ECMA says that Object.prototype.constructor, or f.prototype.constructor
+ * for a user-defined function f, is DontEnum.
+ */
+ return OBJ_DEFINE_PROPERTY(cx, proto,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .constructorAtom),
+ OBJECT_TO_JSVAL(ctor),
+ CheckCtorGetAccess, CheckCtorSetAccess,
+ 0, NULL);
+}
+
+JSBool
+js_PrimitiveToObject(JSContext *cx, jsval *vp)
+{
+ JSClass *clasp;
+ JSObject *obj;
+
+ /* Table to map primitive value's tag into the corresponding class. */
+ JS_STATIC_ASSERT(JSVAL_INT == 1);
+ JS_STATIC_ASSERT(JSVAL_DOUBLE == 2);
+ JS_STATIC_ASSERT(JSVAL_STRING == 4);
+ JS_STATIC_ASSERT(JSVAL_BOOLEAN == 6);
+ static JSClass *const PrimitiveClasses[] = {
+ &js_NumberClass, /* INT */
+ &js_NumberClass, /* DOUBLE */
+ &js_NumberClass, /* INT */
+ &js_StringClass, /* STRING */
+ &js_NumberClass, /* INT */
+ &js_BooleanClass, /* BOOLEAN */
+ &js_NumberClass /* INT */
+ };
+
+ JS_ASSERT(!JSVAL_IS_OBJECT(*vp));
+ JS_ASSERT(!JSVAL_IS_VOID(*vp));
+ clasp = PrimitiveClasses[JSVAL_TAG(*vp) - 1];
+ obj = js_NewObject(cx, clasp, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, *vp);
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+JSBool
+js_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
+{
+ JSObject *obj;
+
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) {
+ obj = NULL;
+ } else if (JSVAL_IS_OBJECT(v)) {
+ obj = JSVAL_TO_OBJECT(v);
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_OBJECT, &v))
+ return JS_FALSE;
+ if (JSVAL_IS_OBJECT(v))
+ obj = JSVAL_TO_OBJECT(v);
+ } else {
+ if (!js_PrimitiveToObject(cx, &v))
+ return JS_FALSE;
+ obj = JSVAL_TO_OBJECT(v);
+ }
+ *objp = obj;
+ return JS_TRUE;
+}
+
+JSObject *
+js_ValueToNonNullObject(JSContext *cx, jsval v)
+{
+ JSObject *obj;
+
+ if (!js_ValueToObject(cx, v, &obj))
+ return NULL;
+ if (!obj)
+ js_ReportIsNullOrUndefined(cx, JSDVG_SEARCH_STACK, v, NULL);
+ return obj;
+}
+
+JSBool
+js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval)
+{
+ jsval argv[1];
+
+ argv[0] = ATOM_KEY(cx->runtime->atomState.typeAtoms[type]);
+ return js_TryMethod(cx, obj, cx->runtime->atomState.valueOfAtom, 1, argv,
+ rval);
+}
+
+JSBool
+js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ JSErrorReporter older;
+ jsid id;
+ jsval fval;
+ JSBool ok;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ /*
+ * Report failure only if an appropriate method was found, and calling it
+ * returned failure. We propagate failure in this case to make exceptions
+ * behave properly.
+ */
+ older = JS_SetErrorReporter(cx, NULL);
+ id = ATOM_TO_JSID(atom);
+ fval = JSVAL_VOID;
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ JSXMLObjectOps *ops;
+
+ ops = (JSXMLObjectOps *) obj->map->ops;
+ obj = ops->getMethod(cx, obj, id, &fval);
+ ok = (obj != NULL);
+ } else
+#endif
+ {
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &fval);
+ }
+ if (!ok)
+ JS_ClearPendingException(cx);
+ JS_SetErrorReporter(cx, older);
+
+ return JSVAL_IS_PRIMITIVE(fval) ||
+ js_InternalCall(cx, obj, fval, argc, argv, rval);
+}
+
+#if JS_HAS_XDR
+
+JSBool
+js_XDRObject(JSXDRState *xdr, JSObject **objp)
+{
+ JSContext *cx;
+ JSAtom *atom;
+ JSClass *clasp;
+ uint32 classId, classDef;
+ JSProtoKey protoKey;
+ jsid classKey;
+ JSObject *proto;
+
+ cx = xdr->cx;
+ atom = NULL;
+ if (xdr->mode == JSXDR_ENCODE) {
+ clasp = OBJ_GET_CLASS(cx, *objp);
+ classId = JS_XDRFindClassIdByName(xdr, clasp->name);
+ classDef = !classId;
+ if (classDef) {
+ if (!JS_XDRRegisterClass(xdr, clasp, &classId))
+ return JS_FALSE;
+ protoKey = JSCLASS_CACHED_PROTO_KEY(clasp);
+ if (protoKey != JSProto_Null) {
+ classDef |= (protoKey << 1);
+ } else {
+ atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
+ if (!atom)
+ return JS_FALSE;
+ }
+ }
+ } else {
+ clasp = NULL; /* quell GCC overwarning */
+ classDef = 0;
+ }
+
+ /*
+ * XDR a flag word, which could be 0 for a class use, in which case no
+ * name follows, only the id in xdr's class registry; 1 for a class def,
+ * in which case the flag word is followed by the class name transferred
+ * from or to atom; or a value greater than 1, an odd number that when
+ * divided by two yields the JSProtoKey for class. In the last case, as
+ * in the 0 classDef case, no name is transferred via atom.
+ */
+ if (!JS_XDRUint32(xdr, &classDef))
+ return JS_FALSE;
+ if (classDef == 1 && !js_XDRStringAtom(xdr, &atom))
+ return JS_FALSE;
+
+ if (!JS_XDRUint32(xdr, &classId))
+ return JS_FALSE;
+
+ if (xdr->mode == JSXDR_DECODE) {
+ if (classDef) {
+ /* NB: we know that JSProto_Null is 0 here, for backward compat. */
+ protoKey = (JSProtoKey) (classDef >> 1);
+ classKey = (protoKey != JSProto_Null)
+ ? INT_TO_JSID(protoKey)
+ : ATOM_TO_JSID(atom);
+ if (!js_GetClassPrototype(cx, NULL, classKey, &proto))
+ return JS_FALSE;
+ clasp = OBJ_GET_CLASS(cx, proto);
+ if (!JS_XDRRegisterClass(xdr, clasp, &classId))
+ return JS_FALSE;
+ } else {
+ clasp = JS_XDRFindClassById(xdr, classId);
+ if (!clasp) {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)classId);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_FIND_CLASS, numBuf);
+ return JS_FALSE;
+ }
+ }
+ }
+
+ if (!clasp->xdrObject) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_XDR_CLASS, clasp->name);
+ return JS_FALSE;
+ }
+ return clasp->xdrObject(xdr, objp);
+}
+
+#endif /* JS_HAS_XDR */
+
+#ifdef JS_DUMP_SCOPE_METERS
+
+#include <stdio.h>
+
+JSBasicStats js_entry_count_bs = JS_INIT_STATIC_BASIC_STATS;
+
+static void
+MeterEntryCount(uintN count)
+{
+ JS_BASIC_STATS_ACCUM(&js_entry_count_bs, count);
+}
+
+void
+js_DumpScopeMeters(JSRuntime *rt)
+{
+ static FILE *logfp;
+ if (!logfp)
+ logfp = fopen("/tmp/scope.stats", "a");
+
+ {
+ double mean, sigma;
+
+ mean = JS_MeanAndStdDevBS(&js_entry_count_bs, &sigma);
+
+ fprintf(logfp, "scopes %u entries %g mean %g sigma %g max %u",
+ js_entry_count_bs.num, js_entry_count_bs.sum, mean, sigma,
+ js_entry_count_bs.max);
+ }
+
+ JS_DumpHistogram(&js_entry_count_bs, logfp);
+ JS_BASIC_STATS_INIT(&js_entry_count_bs);
+ fflush(logfp);
+}
+#endif
+
+#ifdef DEBUG
+void
+js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize)
+{
+ JSObject *obj;
+ uint32 slot;
+ JSScope *scope;
+ jsval nval;
+ JSScopeProperty *sprop;
+ JSClass *clasp;
+ uint32 key;
+ const char *slotname;
+
+ JS_ASSERT(trc->debugPrinter == js_PrintObjectSlotName);
+ obj = (JSObject *)trc->debugPrintArg;
+ slot = (uint32)trc->debugPrintIndex;
+
+ if (OBJ_IS_NATIVE(obj)) {
+ scope = OBJ_SCOPE(obj);
+ sprop = SCOPE_LAST_PROP(scope);
+ while (sprop && sprop->slot != slot)
+ sprop = sprop->parent;
+ } else {
+ sprop = NULL;
+ }
+
+ if (!sprop) {
+ switch (slot) {
+ case JSSLOT_PROTO:
+ JS_snprintf(buf, bufsize, "__proto__");
+ break;
+ case JSSLOT_PARENT:
+ JS_snprintf(buf, bufsize, "__parent__");
+ break;
+ default:
+ slotname = NULL;
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ if (clasp->flags & JSCLASS_IS_GLOBAL) {
+ key = slot - JSSLOT_START(clasp);
+#define JS_PROTO(name,code,init) \
+ if ((code) == key) { slotname = js_##name##_str; goto found; }
+#include "jsproto.tbl"
+#undef JS_PROTO
+ }
+ found:
+ if (slotname)
+ JS_snprintf(buf, bufsize, "CLASS_OBJECT(%s)", slotname);
+ else
+ JS_snprintf(buf, bufsize, "**UNKNOWN SLOT %ld**", (long)slot);
+ break;
+ }
+ } else {
+ nval = ID_TO_VALUE(sprop->id);
+ if (JSVAL_IS_INT(nval)) {
+ JS_snprintf(buf, bufsize, "%ld", (long)JSVAL_TO_INT(nval));
+ } else if (JSVAL_IS_STRING(nval)) {
+ js_PutEscapedString(buf, bufsize, JSVAL_TO_STRING(nval), 0);
+ } else {
+ JS_snprintf(buf, bufsize, "**FINALIZED ATOM KEY**");
+ }
+ }
+}
+#endif
+
+void
+js_TraceObject(JSTracer *trc, JSObject *obj)
+{
+ JSContext *cx;
+ JSScope *scope;
+ JSBool traceScope;
+ JSScopeProperty *sprop;
+ JSClass *clasp;
+ size_t nslots, i;
+ jsval v;
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ cx = trc->context;
+ scope = OBJ_SCOPE(obj);
+
+ traceScope = (scope->object == obj);
+ if (!traceScope) {
+ JSObject *pobj = obj;
+
+ /*
+ * Because obj does not own scope, we should be able to assert that an
+ * object on obj's prototype chain does -- or scope's properties might
+ * go untraced. It indeed turns out that you can disconnect an object
+ * from the prototype object whose scope it shares, so we may have to
+ * mark scope even though scope->object != obj.
+ */
+ while ((pobj = LOCKED_OBJ_GET_PROTO(pobj)) != NULL) {
+ if (pobj == scope->object)
+ break;
+ }
+ JS_ASSERT_IF(pobj, OBJ_SCOPE(pobj) == scope);
+ traceScope = !pobj;
+ }
+
+ if (traceScope) {
+#ifdef JS_DUMP_SCOPE_METERS
+ MeterEntryCount(scope->entryCount);
+#endif
+
+ sprop = SCOPE_LAST_PROP(scope);
+ if (sprop) {
+ JS_ASSERT(SCOPE_HAS_PROPERTY(scope, sprop));
+
+ /* Regenerate property cache shape ids if GC'ing. */
+ if (IS_GC_MARKING_TRACER(trc)) {
+ uint32 shape, oldshape;
+
+ shape = ++cx->runtime->shapeGen;
+ JS_ASSERT(shape != 0);
+
+ if (!(sprop->flags & SPROP_MARK)) {
+ oldshape = sprop->shape;
+ sprop->shape = shape;
+ sprop->flags |= SPROP_FLAG_SHAPE_REGEN;
+ if (scope->shape != oldshape) {
+ shape = ++cx->runtime->shapeGen;
+ JS_ASSERT(shape != 0);
+ }
+ }
+
+ scope->shape = shape;
+ }
+
+ /* Trace scope's property tree ancestor line. */
+ do {
+ if (SCOPE_HAD_MIDDLE_DELETE(scope) &&
+ !SCOPE_HAS_PROPERTY(scope, sprop)) {
+ continue;
+ }
+ TRACE_SCOPE_PROPERTY(trc, sprop);
+ } while ((sprop = sprop->parent) != NULL);
+ }
+ }
+
+ if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList))
+ js_TraceWatchPoints(trc, obj);
+
+ /* No one runs while the GC is running, so we can use LOCKED_... here. */
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ if (clasp->mark) {
+ if (clasp->flags & JSCLASS_MARK_IS_TRACE)
+ ((JSTraceOp) clasp->mark)(trc, obj);
+ else if (IS_GC_MARKING_TRACER(trc))
+ (void) clasp->mark(cx, obj, trc);
+ }
+
+ /*
+ * An unmutated object that shares a prototype object's scope. We can't
+ * tell how many slots are in use in obj by looking at its scope, so we
+ * use STOBJ_NSLOTS(obj).
+ *
+ * NB: In case clasp->mark mutates something, leave this code here --
+ * don't move it up and unify it with the |if (!traceScope)| section
+ * above.
+ */
+ nslots = STOBJ_NSLOTS(obj);
+ if (scope->object == obj && scope->map.freeslot < nslots)
+ nslots = scope->map.freeslot;
+
+ for (i = 0; i != nslots; ++i) {
+ v = STOBJ_GET_SLOT(obj, i);
+ if (JSVAL_IS_TRACEABLE(v)) {
+ JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
+ }
+ }
+}
+
+void
+js_Clear(JSContext *cx, JSObject *obj)
+{
+ JSScope *scope;
+ uint32 i, n;
+
+ /*
+ * Clear our scope and the property cache of all obj's properties only if
+ * obj owns the scope (i.e., not if obj is unmutated and therefore sharing
+ * its prototype's scope). NB: we do not clear any reserved slots lying
+ * below JSSLOT_FREE(clasp).
+ */
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ if (scope->object == obj) {
+ /* Now that we're done using scope->lastProp/table, clear scope. */
+ js_ClearScope(cx, scope);
+
+ /* Clear slot values and reset freeslot so we're consistent. */
+ i = STOBJ_NSLOTS(obj);
+ n = JSSLOT_FREE(LOCKED_OBJ_GET_CLASS(obj));
+ while (--i >= n)
+ STOBJ_SET_SLOT(obj, i, JSVAL_VOID);
+ scope->map.freeslot = n;
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+}
+
+jsval
+js_GetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot)
+{
+ jsval v;
+
+ JS_LOCK_OBJ(cx, obj);
+ v = (slot < STOBJ_NSLOTS(obj)) ? STOBJ_GET_SLOT(obj, slot) : JSVAL_VOID;
+ JS_UNLOCK_OBJ(cx, obj);
+ return v;
+}
+
+JSBool
+js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
+{
+ JSScope *scope;
+ uint32 nslots;
+ JSClass *clasp;
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ if (slot >= JS_INITIAL_NSLOTS && !obj->dslots) {
+ /*
+ * At this point, obj may or may not own scope. If some path calls
+ * js_GetMutableScope but does not add a slot-owning property, then
+ * scope->object == obj but obj->dslots will be null. If obj shares a
+ * prototype's scope, then we cannot update scope->map here. Instead
+ * we rely on STOBJ_NSLOTS(obj) to get the number of available slots
+ * in obj after we allocate dynamic slots.
+ *
+ * See js_TraceObject, before the slot tracing, where we make a special
+ * case for unmutated (scope->object != obj) objects.
+ */
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ nslots = JSSLOT_FREE(clasp);
+ if (clasp->reserveSlots)
+ nslots += clasp->reserveSlots(cx, obj);
+ JS_ASSERT(slot < nslots);
+ if (!js_ReallocSlots(cx, obj, nslots, JS_TRUE)) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE;
+ }
+ }
+
+ /* Whether or not we grew nslots, we may need to advance freeslot. */
+ if (scope->object == obj && slot >= scope->map.freeslot)
+ scope->map.freeslot = slot + 1;
+
+ STOBJ_SET_SLOT(obj, slot, v);
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+}
+
+JSObject *
+js_GetWrappedObject(JSContext *cx, JSObject *obj)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp->flags & JSCLASS_IS_EXTENDED) {
+ JSExtendedClass *xclasp;
+ JSObject *obj2;
+
+ xclasp = (JSExtendedClass *)clasp;
+ if (xclasp->wrappedObject && (obj2 = xclasp->wrappedObject(cx, obj)))
+ return obj2;
+ }
+ return obj;
+}
+
+#if DEBUG
+
+/*
+ * Routines to print out values during debugging. These are FRIEND_API to help
+ * the debugger find them and to support temporarily hacking js_Dump* calls
+ * into other code.
+ */
+
+void
+dumpChars(const jschar *s, size_t n)
+{
+ size_t i;
+
+ if (n == (size_t) -1) {
+ while (s[++n]) ;
+ }
+
+ fputc('"', stderr);
+ for (i = 0; i < n; i++) {
+ if (s[i] == '\n')
+ fprintf(stderr, "\\n");
+ else if (s[i] == '\t')
+ fprintf(stderr, "\\t");
+ else if (s[i] >= 32 && s[i] < 127)
+ fputc(s[i], stderr);
+ else if (s[i] <= 255)
+ fprintf(stderr, "\\x%02x", (unsigned int) s[i]);
+ else
+ fprintf(stderr, "\\u%04x", (unsigned int) s[i]);
+ }
+ fputc('"', stderr);
+}
+
+JS_FRIEND_API(void)
+js_DumpChars(const jschar *s, size_t n)
+{
+ fprintf(stderr, "jschar * (%p) = ", (void *) s);
+ dumpChars(s, n);
+ fputc('\n', stderr);
+}
+
+void
+dumpString(JSString *str)
+{
+ dumpChars(JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
+}
+
+JS_FRIEND_API(void)
+js_DumpString(JSString *str)
+{
+ fprintf(stderr, "JSString* (%p) = jschar * (%p) = ",
+ (void *) str, (void *) JSSTRING_CHARS(str));
+ dumpString(str);
+ fputc('\n', stderr);
+}
+
+JS_FRIEND_API(void)
+js_DumpAtom(JSAtom *atom)
+{
+ fprintf(stderr, "JSAtom* (%p) = ", (void *) atom);
+ js_DumpValue(ATOM_KEY(atom));
+}
+
+void
+dumpValue(jsval val)
+{
+ if (JSVAL_IS_NULL(val)) {
+ fprintf(stderr, "null");
+ } else if (JSVAL_IS_VOID(val)) {
+ fprintf(stderr, "undefined");
+ } else if (JSVAL_IS_OBJECT(val)) {
+ JSObject *obj = JSVAL_TO_OBJECT(val);
+ JSClass *cls = STOBJ_GET_CLASS(obj);
+ fprintf(stderr, "<%s%s at %p>",
+ cls->name,
+ cls == &js_ObjectClass ? "" : " object",
+ obj);
+ } else if (JSVAL_IS_INT(val)) {
+ fprintf(stderr, "%d", JSVAL_TO_INT(val));
+ } else if (JSVAL_IS_STRING(val)) {
+ dumpString(JSVAL_TO_STRING(val));
+ } else if (JSVAL_IS_DOUBLE(val)) {
+ fprintf(stderr, "%g", *JSVAL_TO_DOUBLE(val));
+ } else if (val == JSVAL_TRUE) {
+ fprintf(stderr, "true");
+ } else if (val == JSVAL_FALSE) {
+ fprintf(stderr, "false");
+ } else if (val == JSVAL_HOLE) {
+ fprintf(stderr, "hole");
+ } else {
+ /* jsvals are pointer-sized, and %p is portable */
+ fprintf(stderr, "unrecognized jsval %p", (void *) val);
+ }
+}
+
+JS_FRIEND_API(void)
+js_DumpValue(jsval val)
+{
+ fprintf(stderr, "jsval %d (%p) = ", (int) val, (void *) val);
+ dumpValue(val);
+ fputc('\n', stderr);
+}
+
+JS_FRIEND_API(void)
+js_DumpId(jsid id)
+{
+ fprintf(stderr, "id %d (%p) = ", (int) id, (void *) id);
+ dumpValue(ID_TO_VALUE(id));
+ fputc('\n', stderr);
+}
+
+static void
+dumpScopeProp(JSScopeProperty *sprop)
+{
+ jsid id = sprop->id;
+ uint8 attrs = sprop->attrs;
+
+ fprintf(stderr, " ");
+ if (attrs & JSPROP_ENUMERATE) fprintf(stderr, "enumerate ");
+ if (attrs & JSPROP_READONLY) fprintf(stderr, "readonly ");
+ if (attrs & JSPROP_PERMANENT) fprintf(stderr, "permanent ");
+ if (attrs & JSPROP_GETTER) fprintf(stderr, "getter ");
+ if (attrs & JSPROP_SETTER) fprintf(stderr, "setter ");
+ if (attrs & JSPROP_SHARED) fprintf(stderr, "shared ");
+ if (sprop->flags & SPROP_IS_ALIAS) fprintf(stderr, "alias ");
+ if (JSID_IS_ATOM(id))
+ dumpString(JSVAL_TO_STRING(ID_TO_VALUE(id)));
+ else if (JSID_IS_INT(id))
+ fprintf(stderr, "%d", (int) JSID_TO_INT(id));
+ else
+ fprintf(stderr, "unknown jsid %p", (void *) id);
+ fprintf(stderr, ": slot %d", sprop->slot);
+ fprintf(stderr, "\n");
+}
+
+JS_FRIEND_API(void)
+js_DumpObject(JSObject *obj)
+{
+ uint32 i, slots;
+ JSClass *clasp;
+ jsuint reservedEnd;
+ JSBool sharesScope = JS_FALSE;
+
+ fprintf(stderr, "object %p\n", (void *) obj);
+ clasp = STOBJ_GET_CLASS(obj);
+ fprintf(stderr, "class %p %s\n", (void *)clasp, clasp->name);
+
+ /* OBJ_IS_DENSE_ARRAY ignores the cx argument. */
+ if (OBJ_IS_DENSE_ARRAY(BOGUS_CX, obj)) {
+ slots = JS_MIN((jsuint) obj->fslots[JSSLOT_ARRAY_LENGTH],
+ ARRAY_DENSE_LENGTH(obj));
+ fprintf(stderr, "elements\n");
+ for (i = 0; i < slots; i++) {
+ fprintf(stderr, " %3d: ", i);
+ dumpValue(obj->dslots[i]);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+ return;
+ }
+
+ if (OBJ_IS_NATIVE(obj)) {
+ JSScope *scope = OBJ_SCOPE(obj);
+ JSObject *proto = STOBJ_GET_PROTO(obj);
+
+ if (SCOPE_IS_SEALED(scope))
+ fprintf(stderr, "sealed\n");
+
+ sharesScope = (scope->object != obj);
+ if (sharesScope) {
+ fprintf(stderr, "no own properties - see proto (%s at %p)\n",
+ STOBJ_GET_CLASS(proto)->name, proto);
+ } else {
+ fprintf(stderr, "properties:\n");
+ for (JSScopeProperty *sprop = SCOPE_LAST_PROP(scope); sprop;
+ sprop = sprop->parent) {
+ if (!SCOPE_HAD_MIDDLE_DELETE(scope) ||
+ SCOPE_HAS_PROPERTY(scope, sprop)) {
+ dumpScopeProp(sprop);
+ }
+ }
+ }
+ } else {
+ if (!OBJ_IS_NATIVE(obj))
+ fprintf(stderr, "not native\n");
+ }
+
+ fprintf(stderr, "slots:\n");
+ reservedEnd = JSSLOT_PRIVATE;
+ if (clasp->flags & JSCLASS_HAS_PRIVATE)
+ reservedEnd++;
+ reservedEnd += JSCLASS_RESERVED_SLOTS(clasp);
+ slots = sharesScope ? reservedEnd : obj->map->freeslot;
+ for (i = 0; i < slots; i++) {
+ fprintf(stderr, " %3d ", i);
+ if (i == JSSLOT_PRIVATE && (clasp->flags & JSCLASS_HAS_PRIVATE)) {
+ fprintf(stderr, "(private) = %p\n",
+ JSVAL_TO_PRIVATE(STOBJ_GET_SLOT(obj, i)));
+ continue;
+ }
+ if (i == JSSLOT_PROTO)
+ fprintf(stderr, "(proto) ");
+ else if (i == JSSLOT_PARENT)
+ fprintf(stderr, "(parent) ");
+ else if (i < reservedEnd)
+ fprintf(stderr, "(reserved) ");
+ fprintf(stderr, "= ");
+ dumpValue(STOBJ_GET_SLOT(obj, i));
+ fputc('\n', stderr);
+ }
+ fputc('\n', stderr);
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsobj.h b/tools/node_modules/expresso/deps/jscoverage/js/jsobj.h
new file mode 100644
index 0000000..59a354f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsobj.h
@@ -0,0 +1,735 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsobj_h___
+#define jsobj_h___
+/*
+ * JS object definitions.
+ *
+ * A JS object consists of a possibly-shared object descriptor containing
+ * ordered property names, called the map; and a dense vector of property
+ * values, called slots. The map/slot pointer pair is GC'ed, while the map
+ * is reference counted and the slot vector is malloc'ed.
+ */
+#include "jshash.h" /* Added by JSIFY */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+struct JSObjectMap {
+ jsrefcount nrefs; /* count of all referencing objects */
+ JSObjectOps *ops; /* high level object operation vtable */
+ uint32 freeslot; /* index of next free slot in object */
+};
+
+/* Shorthand macros for frequently-made calls. */
+#define OBJ_LOOKUP_PROPERTY(cx,obj,id,objp,propp) \
+ (obj)->map->ops->lookupProperty(cx,obj,id,objp,propp)
+#define OBJ_DEFINE_PROPERTY(cx,obj,id,value,getter,setter,attrs,propp) \
+ (obj)->map->ops->defineProperty(cx,obj,id,value,getter,setter,attrs,propp)
+#define OBJ_GET_PROPERTY(cx,obj,id,vp) \
+ (obj)->map->ops->getProperty(cx,obj,id,vp)
+#define OBJ_SET_PROPERTY(cx,obj,id,vp) \
+ (obj)->map->ops->setProperty(cx,obj,id,vp)
+#define OBJ_GET_ATTRIBUTES(cx,obj,id,prop,attrsp) \
+ (obj)->map->ops->getAttributes(cx,obj,id,prop,attrsp)
+#define OBJ_SET_ATTRIBUTES(cx,obj,id,prop,attrsp) \
+ (obj)->map->ops->setAttributes(cx,obj,id,prop,attrsp)
+#define OBJ_DELETE_PROPERTY(cx,obj,id,rval) \
+ (obj)->map->ops->deleteProperty(cx,obj,id,rval)
+#define OBJ_DEFAULT_VALUE(cx,obj,hint,vp) \
+ (obj)->map->ops->defaultValue(cx,obj,hint,vp)
+#define OBJ_ENUMERATE(cx,obj,enum_op,statep,idp) \
+ (obj)->map->ops->enumerate(cx,obj,enum_op,statep,idp)
+#define OBJ_CHECK_ACCESS(cx,obj,id,mode,vp,attrsp) \
+ (obj)->map->ops->checkAccess(cx,obj,id,mode,vp,attrsp)
+
+/* These four are time-optimized to avoid stub calls. */
+#define OBJ_THIS_OBJECT(cx,obj) \
+ ((obj)->map->ops->thisObject \
+ ? (obj)->map->ops->thisObject(cx,obj) \
+ : (obj))
+#define OBJ_DROP_PROPERTY(cx,obj,prop) \
+ ((obj)->map->ops->dropProperty \
+ ? (obj)->map->ops->dropProperty(cx,obj,prop) \
+ : (void)0)
+#define OBJ_GET_REQUIRED_SLOT(cx,obj,slot) \
+ ((obj)->map->ops->getRequiredSlot \
+ ? (obj)->map->ops->getRequiredSlot(cx, obj, slot) \
+ : JSVAL_VOID)
+#define OBJ_SET_REQUIRED_SLOT(cx,obj,slot,v) \
+ ((obj)->map->ops->setRequiredSlot \
+ ? (obj)->map->ops->setRequiredSlot(cx, obj, slot, v) \
+ : JS_TRUE)
+
+#define OBJ_TO_INNER_OBJECT(cx,obj) \
+ JS_BEGIN_MACRO \
+ JSClass *clasp_ = OBJ_GET_CLASS(cx, obj); \
+ if (clasp_->flags & JSCLASS_IS_EXTENDED) { \
+ JSExtendedClass *xclasp_ = (JSExtendedClass*)clasp_; \
+ if (xclasp_->innerObject) \
+ obj = xclasp_->innerObject(cx, obj); \
+ } \
+ JS_END_MACRO
+
+#define OBJ_TO_OUTER_OBJECT(cx,obj) \
+ JS_BEGIN_MACRO \
+ JSClass *clasp_ = OBJ_GET_CLASS(cx, obj); \
+ if (clasp_->flags & JSCLASS_IS_EXTENDED) { \
+ JSExtendedClass *xclasp_ = (JSExtendedClass*)clasp_; \
+ if (xclasp_->outerObject) \
+ obj = xclasp_->outerObject(cx, obj); \
+ } \
+ JS_END_MACRO
+
+#define JS_INITIAL_NSLOTS 5
+
+/*
+ * When JSObject.dslots is not null, JSObject.dslots[-1] records the number of
+ * available slots.
+ */
+struct JSObject {
+ JSObjectMap *map;
+ jsuword classword;
+ jsval fslots[JS_INITIAL_NSLOTS];
+ jsval *dslots; /* dynamically allocated slots */
+};
+
+#define JSSLOT_PROTO 0
+#define JSSLOT_PARENT 1
+#define JSSLOT_PRIVATE 2
+#define JSSLOT_START(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE) \
+ ? JSSLOT_PRIVATE + 1 \
+ : JSSLOT_PARENT + 1)
+
+#define JSSLOT_FREE(clasp) (JSSLOT_START(clasp) \
+ + JSCLASS_RESERVED_SLOTS(clasp))
+
+/*
+ * STOBJ prefix means Single Threaded Object. Use the following fast macros to
+ * directly manipulate slots in obj when only one thread can access obj and
+ * when obj->map->freeslot can be inconsistent with slots.
+ */
+
+#define STOBJ_NSLOTS(obj) \
+ ((obj)->dslots ? (uint32)(obj)->dslots[-1] : (uint32)JS_INITIAL_NSLOTS)
+
+#define STOBJ_GET_SLOT(obj,slot) \
+ ((slot) < JS_INITIAL_NSLOTS \
+ ? (obj)->fslots[(slot)] \
+ : (JS_ASSERT((slot) < (uint32)(obj)->dslots[-1]), \
+ (obj)->dslots[(slot) - JS_INITIAL_NSLOTS]))
+
+#define STOBJ_SET_SLOT(obj,slot,value) \
+ ((slot) < JS_INITIAL_NSLOTS \
+ ? (obj)->fslots[(slot)] = (value) \
+ : (JS_ASSERT((slot) < (uint32)(obj)->dslots[-1]), \
+ (obj)->dslots[(slot) - JS_INITIAL_NSLOTS] = (value)))
+
+#define STOBJ_GET_PROTO(obj) \
+ JSVAL_TO_OBJECT((obj)->fslots[JSSLOT_PROTO])
+#define STOBJ_SET_PROTO(obj,proto) \
+ (void)(STOBJ_NULLSAFE_SET_DELEGATE(proto), \
+ (obj)->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto))
+#define STOBJ_CLEAR_PROTO(obj) \
+ ((obj)->fslots[JSSLOT_PROTO] = JSVAL_NULL)
+
+#define STOBJ_GET_PARENT(obj) \
+ JSVAL_TO_OBJECT((obj)->fslots[JSSLOT_PARENT])
+#define STOBJ_SET_PARENT(obj,parent) \
+ (void)(STOBJ_NULLSAFE_SET_DELEGATE(parent), \
+ (obj)->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent))
+#define STOBJ_CLEAR_PARENT(obj) \
+ ((obj)->fslots[JSSLOT_PARENT] = JSVAL_NULL)
+
+/*
+ * We use JSObject.classword to store both JSClass* and the delegate and system
+ * flags in the two least significant bits. We do *not* synchronize updates of
+ * obj->classword -- API clients must take care.
+ */
+#define STOBJ_GET_CLASS(obj) ((JSClass *)((obj)->classword & ~3))
+#define STOBJ_IS_DELEGATE(obj) (((obj)->classword & 1) != 0)
+#define STOBJ_SET_DELEGATE(obj) ((obj)->classword |= 1)
+#define STOBJ_NULLSAFE_SET_DELEGATE(obj) \
+ (!(obj) || STOBJ_SET_DELEGATE((JSObject*)obj))
+#define STOBJ_IS_SYSTEM(obj) (((obj)->classword & 2) != 0)
+#define STOBJ_SET_SYSTEM(obj) ((obj)->classword |= 2)
+
+#define STOBJ_GET_PRIVATE(obj) \
+ (JS_ASSERT(JSVAL_IS_INT(STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE))), \
+ JSVAL_TO_PRIVATE(STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE)))
+
+#define OBJ_CHECK_SLOT(obj,slot) \
+ JS_ASSERT(slot < (obj)->map->freeslot)
+
+#define LOCKED_OBJ_GET_SLOT(obj,slot) \
+ (OBJ_CHECK_SLOT(obj, slot), STOBJ_GET_SLOT(obj, slot))
+#define LOCKED_OBJ_SET_SLOT(obj,slot,value) \
+ (OBJ_CHECK_SLOT(obj, slot), STOBJ_SET_SLOT(obj, slot, value))
+
+/*
+ * NB: Don't call LOCKED_OBJ_SET_SLOT or STOBJ_SET_SLOT for a write to a slot
+ * that may contain a function reference already, or where the new value is a
+ * function ref, and the object's scope may be branded with a property cache
+ * structural type capability that distinguishes versions of the object with
+ * and without the function property. Instead use LOCKED_OBJ_WRITE_BARRIER or
+ * a fast inline equivalent (JSOP_SETNAME/JSOP_SETPROP cases in jsinterp.c).
+ */
+#define LOCKED_OBJ_WRITE_BARRIER(cx,obj,slot,newval) \
+ JS_BEGIN_MACRO \
+ JSScope *scope_ = OBJ_SCOPE(obj); \
+ JS_ASSERT(scope_->object == (obj)); \
+ GC_WRITE_BARRIER(cx, scope_, LOCKED_OBJ_GET_SLOT(obj, slot), newval); \
+ LOCKED_OBJ_SET_SLOT(obj, slot, newval); \
+ JS_END_MACRO
+
+#define LOCKED_OBJ_GET_PROTO(obj) \
+ (OBJ_CHECK_SLOT(obj, JSSLOT_PROTO), STOBJ_GET_PROTO(obj))
+#define LOCKED_OBJ_SET_PROTO(obj,proto) \
+ (OBJ_CHECK_SLOT(obj, JSSLOT_PROTO), STOBJ_SET_PROTO(obj, proto))
+
+#define LOCKED_OBJ_GET_PARENT(obj) \
+ (OBJ_CHECK_SLOT(obj, JSSLOT_PARENT), STOBJ_GET_PARENT(obj))
+#define LOCKED_OBJ_SET_PARENT(obj,parent) \
+ (OBJ_CHECK_SLOT(obj, JSSLOT_PARENT), STOBJ_SET_PARENT(obj, parent))
+
+#define LOCKED_OBJ_GET_CLASS(obj) \
+ STOBJ_GET_CLASS(obj)
+
+#define LOCKED_OBJ_GET_PRIVATE(obj) \
+ (OBJ_CHECK_SLOT(obj, JSSLOT_PRIVATE), STOBJ_GET_PRIVATE(obj))
+
+#ifdef JS_THREADSAFE
+
+/* Thread-safe functions and wrapper macros for accessing slots in obj. */
+#define OBJ_GET_SLOT(cx,obj,slot) \
+ (OBJ_CHECK_SLOT(obj, slot), \
+ (OBJ_IS_NATIVE(obj) && OBJ_SCOPE(obj)->title.ownercx == cx) \
+ ? LOCKED_OBJ_GET_SLOT(obj, slot) \
+ : js_GetSlotThreadSafe(cx, obj, slot))
+
+#define OBJ_SET_SLOT(cx,obj,slot,value) \
+ JS_BEGIN_MACRO \
+ OBJ_CHECK_SLOT(obj, slot); \
+ if (OBJ_IS_NATIVE(obj) && OBJ_SCOPE(obj)->title.ownercx == cx) \
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, value); \
+ else \
+ js_SetSlotThreadSafe(cx, obj, slot, value); \
+ JS_END_MACRO
+
+/*
+ * If thread-safe, define an OBJ_GET_SLOT wrapper that bypasses, for a native
+ * object, the lock-free "fast path" test of (OBJ_SCOPE(obj)->ownercx == cx),
+ * to avoid needlessly switching from lock-free to lock-full scope when doing
+ * GC on a different context from the last one to own the scope. The caller
+ * in this case is probably a JSClass.mark function, e.g., fun_mark, or maybe
+ * a finalizer.
+ *
+ * The GC runs only when all threads except the one on which the GC is active
+ * are suspended at GC-safe points, so calling STOBJ_GET_SLOT from the GC's
+ * thread is safe when rt->gcRunning is set. See jsgc.c for details.
+ */
+#define THREAD_IS_RUNNING_GC(rt, thread) \
+ ((rt)->gcRunning && (rt)->gcThread == (thread))
+
+#define CX_THREAD_IS_RUNNING_GC(cx) \
+ THREAD_IS_RUNNING_GC((cx)->runtime, (cx)->thread)
+
+#else /* !JS_THREADSAFE */
+
+#define OBJ_GET_SLOT(cx,obj,slot) LOCKED_OBJ_GET_SLOT(obj,slot)
+#define OBJ_SET_SLOT(cx,obj,slot,value) LOCKED_OBJ_WRITE_BARRIER(cx,obj,slot, \
+ value)
+
+#endif /* !JS_THREADSAFE */
+
+/* Thread-safe delegate, proto, parent, and class access macros. */
+#define OBJ_IS_DELEGATE(cx,obj) STOBJ_IS_DELEGATE(obj)
+#define OBJ_SET_DELEGATE(cx,obj) STOBJ_SET_DELEGATE(obj)
+
+#define OBJ_GET_PROTO(cx,obj) STOBJ_GET_PROTO(obj)
+#define OBJ_SET_PROTO(cx,obj,proto) STOBJ_SET_PROTO(obj, proto)
+#define OBJ_CLEAR_PROTO(cx,obj) STOBJ_CLEAR_PROTO(obj)
+
+#define OBJ_GET_PARENT(cx,obj) STOBJ_GET_PARENT(obj)
+#define OBJ_SET_PARENT(cx,obj,parent) STOBJ_SET_PARENT(obj, parent)
+#define OBJ_CLEAR_PARENT(cx,obj) STOBJ_CLEAR_PARENT(obj)
+
+/*
+ * Class is invariant and comes from the fixed clasp member. Thus no locking
+ * is necessary to read it. Same for the private slot.
+ */
+#define OBJ_GET_CLASS(cx,obj) STOBJ_GET_CLASS(obj)
+#define OBJ_GET_PRIVATE(cx,obj) STOBJ_GET_PRIVATE(obj)
+
+/* Test whether a map or object is native. */
+#define MAP_IS_NATIVE(map) \
+ JS_LIKELY((map)->ops == &js_ObjectOps || \
+ (map)->ops->newObjectMap == js_ObjectOps.newObjectMap)
+
+#define OBJ_IS_NATIVE(obj) MAP_IS_NATIVE((obj)->map)
+
+extern JS_FRIEND_DATA(JSObjectOps) js_ObjectOps;
+extern JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps;
+extern JSClass js_ObjectClass;
+extern JSClass js_WithClass;
+extern JSClass js_BlockClass;
+
+/*
+ * Block scope object macros. The slots reserved by js_BlockClass are:
+ *
+ * JSSLOT_PRIVATE JSStackFrame * active frame pointer or null
+ * JSSLOT_BLOCK_DEPTH int depth of block slots in frame
+ *
+ * After JSSLOT_BLOCK_DEPTH come one or more slots for the block locals.
+ *
+ * A With object is like a Block object, in that both have one reserved slot
+ * telling the stack depth of the relevant slots (the slot whose value is the
+ * object named in the with statement, the slots containing the block's local
+ * variables); and both have a private slot referring to the JSStackFrame in
+ * whose activation they were created (or null if the with or block object
+ * outlives the frame).
+ */
+#define JSSLOT_BLOCK_DEPTH (JSSLOT_PRIVATE + 1)
+
+#define OBJ_IS_CLONED_BLOCK(obj) \
+ (OBJ_SCOPE(obj)->object != (obj))
+#define OBJ_BLOCK_COUNT(cx,obj) \
+ (OBJ_SCOPE(obj)->entryCount)
+#define OBJ_BLOCK_DEPTH(cx,obj) \
+ JSVAL_TO_INT(STOBJ_GET_SLOT(obj, JSSLOT_BLOCK_DEPTH))
+#define OBJ_SET_BLOCK_DEPTH(cx,obj,depth) \
+ STOBJ_SET_SLOT(obj, JSSLOT_BLOCK_DEPTH, INT_TO_JSVAL(depth))
+
+/*
+ * To make sure this slot is well-defined, always call js_NewWithObject to
+ * create a With object, don't call js_NewObject directly. When creating a
+ * With object that does not correspond to a stack slot, pass -1 for depth.
+ *
+ * When popping the stack across this object's "with" statement, client code
+ * must call JS_SetPrivate(cx, withobj, NULL).
+ */
+extern JSObject *
+js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth);
+
+/*
+ * Create a new block scope object not linked to any proto or parent object.
+ * Blocks are created by the compiler to reify let blocks and comprehensions.
+ * Only when dynamic scope is captured do they need to be cloned and spliced
+ * into an active scope chain.
+ */
+extern JSObject *
+js_NewBlockObject(JSContext *cx);
+
+extern JSObject *
+js_CloneBlockObject(JSContext *cx, JSObject *proto, JSObject *parent,
+ JSStackFrame *fp);
+
+extern JSBool
+js_PutBlockObject(JSContext *cx, JSBool normalUnwind);
+
+struct JSSharpObjectMap {
+ jsrefcount depth;
+ jsatomid sharpgen;
+ JSHashTable *table;
+};
+
+#define SHARP_BIT ((jsatomid) 1)
+#define BUSY_BIT ((jsatomid) 2)
+#define SHARP_ID_SHIFT 2
+#define IS_SHARP(he) (JS_PTR_TO_UINT32((he)->value) & SHARP_BIT)
+#define MAKE_SHARP(he) ((he)->value = JS_UINT32_TO_PTR(JS_PTR_TO_UINT32((he)->value)|SHARP_BIT))
+#define IS_BUSY(he) (JS_PTR_TO_UINT32((he)->value) & BUSY_BIT)
+#define MAKE_BUSY(he) ((he)->value = JS_UINT32_TO_PTR(JS_PTR_TO_UINT32((he)->value)|BUSY_BIT))
+#define CLEAR_BUSY(he) ((he)->value = JS_UINT32_TO_PTR(JS_PTR_TO_UINT32((he)->value)&~BUSY_BIT))
+
+extern JSHashEntry *
+js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap,
+ jschar **sp);
+
+extern void
+js_LeaveSharpObject(JSContext *cx, JSIdArray **idap);
+
+/*
+ * Mark objects stored in map if GC happens between js_EnterSharpObject
+ * and js_LeaveSharpObject. GC calls this when map->depth > 0.
+ */
+extern void
+js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map);
+
+extern JSBool
+js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, uintN argc,
+ jsval *vp);
+
+extern JSBool
+js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id,
+ jsval *vp);
+
+extern JSBool
+js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSObject *
+js_InitBlockClass(JSContext *cx, JSObject* obj);
+
+extern JSObject *
+js_InitEval(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitObjectClass(JSContext *cx, JSObject *obj);
+
+/* Select Object.prototype method names shared between jsapi.c and jsobj.c. */
+extern const char js_watch_str[];
+extern const char js_unwatch_str[];
+extern const char js_hasOwnProperty_str[];
+extern const char js_isPrototypeOf_str[];
+extern const char js_propertyIsEnumerable_str[];
+extern const char js_defineGetter_str[];
+extern const char js_defineSetter_str[];
+extern const char js_lookupGetter_str[];
+extern const char js_lookupSetter_str[];
+
+extern void
+js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp);
+
+extern JSObjectMap *
+js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp, JSObject *obj);
+
+extern void
+js_DestroyObjectMap(JSContext *cx, JSObjectMap *map);
+
+extern JSObjectMap *
+js_HoldObjectMap(JSContext *cx, JSObjectMap *map);
+
+extern JSObjectMap *
+js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj);
+
+extern JSBool
+js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp);
+
+extern JSObject *
+js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
+ uintN objectSize);
+
+/*
+ * See jsapi.h, JS_NewObjectWithGivenProto.
+ *
+ * objectSize is either the explicit size for the allocated object or 0
+ * indicating to use the default size based on object's class.
+ */
+extern JSObject *
+js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN objectSize);
+
+/*
+ * Fast access to immutable standard objects (constructors and prototypes).
+ */
+extern JSBool
+js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
+ JSObject **objp);
+
+extern JSBool
+js_SetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject *cobj);
+
+extern JSBool
+js_FindClassObject(JSContext *cx, JSObject *start, jsid id, jsval *vp);
+
+extern JSObject *
+js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN argc, jsval *argv);
+
+extern void
+js_FinalizeObject(JSContext *cx, JSObject *obj);
+
+extern JSBool
+js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp);
+
+extern void
+js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot);
+
+/* JSVAL_INT_MAX as a string */
+#define JSVAL_INT_MAX_STRING "1073741823"
+
+#define CHECK_FOR_STRING_INDEX(id) \
+ JS_BEGIN_MACRO \
+ if (JSID_IS_ATOM(id)) { \
+ JSAtom *atom_ = JSID_TO_ATOM(id); \
+ JSString *str_ = ATOM_TO_STRING(atom_); \
+ const jschar *s_ = JSFLATSTR_CHARS(str_); \
+ JSBool negative_ = (*s_ == '-'); \
+ if (negative_) s_++; \
+ if (JS7_ISDEC(*s_)) { \
+ size_t n_ = JSFLATSTR_LENGTH(str_) - negative_; \
+ if (n_ <= sizeof(JSVAL_INT_MAX_STRING) - 1) \
+ id = js_CheckForStringIndex(id, s_, s_ + n_, negative_); \
+ } \
+ } \
+ JS_END_MACRO
+
+extern jsid
+js_CheckForStringIndex(jsid id, const jschar *cp, const jschar *end,
+ JSBool negative);
+
+/*
+ * Find or create a property named by id in obj's scope, with the given getter
+ * and setter, slot, attributes, and other members.
+ */
+extern JSScopeProperty *
+js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
+ JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
+ uintN attrs, uintN flags, intN shortid);
+
+/*
+ * Change sprop to have the given attrs, getter, and setter in scope, morphing
+ * it into a potentially new JSScopeProperty. Return a pointer to the changed
+ * or identical property.
+ */
+extern JSScopeProperty *
+js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
+ JSScopeProperty *sprop, uintN attrs, uintN mask,
+ JSPropertyOp getter, JSPropertyOp setter);
+
+/*
+ * On error, return false. On success, if propp is non-null, return true with
+ * obj locked and with a held property in *propp; if propp is null, return true
+ * but release obj's lock first. Therefore all callers who pass non-null propp
+ * result parameters must later call OBJ_DROP_PROPERTY(cx, obj, *propp) both to
+ * drop the held property, and to release the lock on obj.
+ */
+extern JSBool
+js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ JSProperty **propp);
+
+extern JSBool
+js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ uintN flags, intN shortid, JSProperty **propp);
+
+/*
+ * Unlike js_DefineProperty, propp must be non-null. On success, and if id was
+ * found, return true with *objp non-null and locked, and with a held property
+ * stored in *propp. If successful but id was not found, return true with both
+ * *objp and *propp null. Therefore all callers who receive a non-null *propp
+ * must later call OBJ_DROP_PROPERTY(cx, *objp, *propp).
+ */
+extern JS_FRIEND_API(JSBool)
+js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp);
+
+/*
+ * Specialized subroutine that allows caller to preset JSRESOLVE_* flags and
+ * returns the index along the prototype chain in which *propp was found, or
+ * the last index if not found, or -1 on error.
+ */
+extern int
+js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
+ JSObject **objp, JSProperty **propp);
+
+extern int
+js_FindPropertyHelper(JSContext *cx, jsid id, JSObject **objp,
+ JSObject **pobjp, JSProperty **propp,
+ JSPropCacheEntry **entryp);
+
+/*
+ * Return the index along the scope chain in which id was found, or the last
+ * index if not found, or -1 on error.
+ */
+extern JS_FRIEND_API(JSBool)
+js_FindProperty(JSContext *cx, jsid id, JSObject **objp, JSObject **pobjp,
+ JSProperty **propp);
+
+extern JSObject *
+js_FindIdentifierBase(JSContext *cx, jsid id, JSPropCacheEntry *entry);
+
+extern JSObject *
+js_FindVariableScope(JSContext *cx, JSFunction **funp);
+
+/*
+ * NB: js_NativeGet and js_NativeSet are called with the scope containing sprop
+ * (pobj's scope for Get, obj's for Set) locked, and on successful return, that
+ * scope is again locked. But on failure, both functions return false with the
+ * scope containing sprop unlocked.
+ */
+extern JSBool
+js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
+ JSScopeProperty *sprop, jsval *vp);
+
+extern JSBool
+js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, jsval *vp);
+
+extern JSBool
+js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+ JSPropCacheEntry **entryp);
+
+extern JSBool
+js_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSBool
+js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+ JSPropCacheEntry **entryp);
+
+extern JSBool
+js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSBool
+js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp);
+
+extern JSBool
+js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp);
+
+extern JSBool
+js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval);
+
+extern JSBool
+js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp);
+
+extern JSBool
+js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp);
+
+extern void
+js_TraceNativeEnumerators(JSTracer *trc);
+
+extern JSBool
+js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp);
+
+extern JSBool
+js_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+extern JSBool
+js_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JSBool
+js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+extern JSBool
+js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj);
+
+extern JSBool
+js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+extern JSBool
+js_GetClassPrototype(JSContext *cx, JSObject *scope, jsid id,
+ JSObject **protop);
+
+extern JSBool
+js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto,
+ uintN attrs);
+
+/*
+ * Wrap boolean, number or string as Boolean, Number or String object.
+ * *vp must not be an object, null or undefined.
+ */
+extern JSBool
+js_PrimitiveToObject(JSContext *cx, jsval *vp);
+
+extern JSBool
+js_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
+
+extern JSObject *
+js_ValueToNonNullObject(JSContext *cx, jsval v);
+
+extern JSBool
+js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval);
+
+extern JSBool
+js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
+ uintN argc, jsval *argv, jsval *rval);
+
+extern JSBool
+js_XDRObject(JSXDRState *xdr, JSObject **objp);
+
+extern void
+js_TraceObject(JSTracer *trc, JSObject *obj);
+
+extern void
+js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize);
+
+extern void
+js_Clear(JSContext *cx, JSObject *obj);
+
+extern jsval
+js_GetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot);
+
+extern JSBool
+js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v);
+
+/*
+ * Precondition: obj must be locked.
+ */
+extern JSBool
+js_ReallocSlots(JSContext *cx, JSObject *obj, uint32 nslots,
+ JSBool exactAllocation);
+
+extern JSObject *
+js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller);
+
+extern JSBool
+js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj,
+ JSPrincipals *principals, JSAtom *caller);
+
+/* Infallible -- returns its argument if there is no wrapped object. */
+extern JSObject *
+js_GetWrappedObject(JSContext *cx, JSObject *obj);
+
+/* NB: Infallible. */
+extern const char *
+js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
+ JSPrincipals *principals, uintN *linenop);
+
+#ifdef DEBUG
+JS_FRIEND_API(void) js_DumpChars(const jschar *s, size_t n);
+JS_FRIEND_API(void) js_DumpString(JSString *str);
+JS_FRIEND_API(void) js_DumpAtom(JSAtom *atom);
+JS_FRIEND_API(void) js_DumpValue(jsval val);
+JS_FRIEND_API(void) js_DumpId(jsid id);
+JS_FRIEND_API(void) js_DumpObject(JSObject *obj);
+#endif
+
+JS_END_EXTERN_C
+
+#endif /* jsobj_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/json.cpp b/tools/node_modules/expresso/deps/jscoverage/js/json.cpp
new file mode 100644
index 0000000..e6cd28a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/json.cpp
@@ -0,0 +1,954 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey JSON.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Robert Sayre <sayrer@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "jsapi.h"
+#include "jsarena.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsdtoa.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsprf.h"
+#include "jsscan.h"
+#include "jsstr.h"
+#include "jstypes.h"
+#include "jsutil.h"
+
+#include "json.h"
+
+JSClass js_JSONClass = {
+ js_JSON_str,
+ JSCLASS_HAS_CACHED_PROTO(JSProto_JSON),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+JSBool
+js_json_parse(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *s = NULL;
+ jsval *argv = vp + 2;
+
+ // Must throw an Error if there isn't a first arg
+ if (!JS_ConvertArguments(cx, argc, argv, "S", &s))
+ return JS_FALSE;
+
+
+ JSONParser *jp = js_BeginJSONParse(cx, vp);
+ JSBool ok = jp != NULL;
+
+ if (ok) {
+ ok = js_ConsumeJSONText(cx, jp, JS_GetStringChars(s), JS_GetStringLength(s));
+ ok &= js_FinishJSONParse(cx, jp);
+ }
+
+ if (!ok)
+ JS_ReportError(cx, "Error parsing JSON");
+
+ return ok;
+}
+
+class StringifyClosure : JSAutoTempValueRooter
+{
+public:
+ StringifyClosure(JSContext *cx, size_t len, jsval *vec)
+ : JSAutoTempValueRooter(cx, len, vec), cx(cx), s(vec)
+ {
+ }
+
+ JSContext *cx;
+ jsval *s;
+};
+
+static JSBool
+WriteCallback(const jschar *buf, uint32 len, void *data)
+{
+ StringifyClosure *sc = static_cast<StringifyClosure*>(data);
+ JSString *s1 = JSVAL_TO_STRING(sc->s[0]);
+ JSString *s2 = js_NewStringCopyN(sc->cx, buf, len);
+ if (!s2)
+ return JS_FALSE;
+
+ sc->s[1] = STRING_TO_JSVAL(s2);
+
+ s1 = js_ConcatStrings(sc->cx, s1, s2);
+ if (!s1)
+ return JS_FALSE;
+
+ sc->s[0] = STRING_TO_JSVAL(s1);
+ sc->s[1] = JSVAL_VOID;
+
+ return JS_TRUE;
+}
+
+JSBool
+js_json_stringify(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval *argv = vp + 2;
+
+ // Must throw an Error if there isn't a first arg
+ if (!JS_ConvertArguments(cx, argc, argv, "o", &obj))
+ return JS_FALSE;
+
+ // Only use objects and arrays as the root for now
+ *vp = OBJECT_TO_JSVAL(obj);
+
+ JSBool ok = js_TryJSON(cx, vp);
+ JSType type;
+ if (!ok ||
+ JSVAL_IS_PRIMITIVE(*vp) ||
+ ((type = JS_TypeOfValue(cx, *vp)) == JSTYPE_FUNCTION ||
+ type == JSTYPE_XML)) {
+ JS_ReportError(cx, "Invalid argument");
+ return JS_FALSE;
+ }
+
+ JSString *s = JS_NewStringCopyN(cx, "", 0);
+ if (!s)
+ ok = JS_FALSE;
+
+ if (ok) {
+ jsval vec[2] = {STRING_TO_JSVAL(s), JSVAL_VOID};
+ StringifyClosure sc(cx, 2, vec);
+ JSAutoTempValueRooter resultTvr(cx, 1, sc.s);
+ ok = js_Stringify(cx, vp, NULL, &WriteCallback, &sc, 0);
+ *vp = *sc.s;
+ }
+
+ return ok;
+}
+
+JSBool
+js_TryJSON(JSContext *cx, jsval *vp)
+{
+ // Checks whether the return value implements toJSON()
+ JSBool ok = JS_TRUE;
+
+ if (!JSVAL_IS_PRIMITIVE(*vp)) {
+ JSObject *obj = JSVAL_TO_OBJECT(*vp);
+ ok = js_TryMethod(cx, obj, cx->runtime->atomState.toJSONAtom, 0, NULL, vp);
+ }
+
+ return ok;
+}
+
+
+static const jschar quote = jschar('"');
+static const jschar backslash = jschar('\\');
+static const jschar unicodeEscape[] = {'\\', 'u', '0', '0'};
+
+static JSBool
+write_string(JSContext *cx, JSONWriteCallback callback, void *data, const jschar *buf, uint32 len)
+{
+ if (!callback(&quote, 1, data))
+ return JS_FALSE;
+
+ uint32 mark = 0;
+ uint32 i;
+ for (i = 0; i < len; ++i) {
+ if (buf[i] == quote || buf[i] == backslash) {
+ if (!callback(&buf[mark], i - mark, data) || !callback(&backslash, 1, data) ||
+ !callback(&buf[i], 1, data)) {
+ return JS_FALSE;
+ }
+ mark = i + 1;
+ } else if (buf[i] <= 31 || buf[i] == 127) {
+ if (!callback(&buf[mark], i - mark, data) || !callback(unicodeEscape, 4, data))
+ return JS_FALSE;
+ char ubuf[3];
+ size_t len = JS_snprintf(ubuf, sizeof(ubuf), "%.2x", buf[i]);
+ JS_ASSERT(len == 2);
+ jschar wbuf[3];
+ size_t wbufSize = JS_ARRAY_LENGTH(wbuf);
+ if (!js_InflateStringToBuffer(cx, ubuf, len, wbuf, &wbufSize) ||
+ !callback(wbuf, wbufSize, data)) {
+ return JS_FALSE;
+ }
+ mark = i + 1;
+ }
+ }
+
+ if (mark < len && !callback(&buf[mark], len - mark, data))
+ return JS_FALSE;
+
+ if (!callback(&quote, 1, data))
+ return JS_FALSE;
+
+ return JS_TRUE;
+}
+
+JSBool
+js_Stringify(JSContext *cx, jsval *vp, JSObject *replacer,
+ JSONWriteCallback callback, void *data, uint32 depth)
+{
+ if (depth > JSON_MAX_DEPTH)
+ return JS_FALSE; /* encoding error */
+
+ JSBool ok = JS_TRUE;
+ JSObject *obj = JSVAL_TO_OBJECT(*vp);
+ JSBool isArray = JS_IsArrayObject(cx, obj);
+ jschar output = jschar(isArray ? '[' : '{');
+ if (!callback(&output, 1, data))
+ return JS_FALSE;
+
+ JSObject *iterObj = NULL;
+ jsint i = 0;
+ jsuint length = 0;
+
+ if (isArray) {
+ if (!js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ } else {
+ if (!js_ValueToIterator(cx, JSITER_ENUMERATE, vp))
+ return JS_FALSE;
+ iterObj = JSVAL_TO_OBJECT(*vp);
+ }
+
+ jsval outputValue = JSVAL_VOID;
+ JSAutoTempValueRooter tvr(cx, 1, &outputValue);
+
+ jsval key;
+ JSBool memberWritten = JS_FALSE;
+ do {
+ outputValue = JSVAL_VOID;
+
+ if (isArray) {
+ if ((jsuint)i >= length)
+ break;
+ ok = OBJ_GET_PROPERTY(cx, obj, INT_TO_JSID(i), &outputValue);
+ i++;
+ } else {
+ ok = js_CallIteratorNext(cx, iterObj, &key);
+ if (!ok)
+ break;
+ if (key == JSVAL_HOLE)
+ break;
+
+ JSString *ks;
+ if (JSVAL_IS_STRING(key)) {
+ ks = JSVAL_TO_STRING(key);
+ } else {
+ ks = js_ValueToString(cx, key);
+ if (!ks) {
+ ok = JS_FALSE;
+ break;
+ }
+ }
+
+ ok = JS_GetUCProperty(cx, obj, JS_GetStringChars(ks),
+ JS_GetStringLength(ks), &outputValue);
+ }
+
+ if (!ok)
+ break;
+
+ // if this is an array, holes are transmitted as null
+ if (isArray && outputValue == JSVAL_VOID) {
+ outputValue = JSVAL_NULL;
+ } else if (JSVAL_IS_OBJECT(outputValue)) {
+ ok = js_TryJSON(cx, &outputValue);
+ if (!ok)
+ break;
+ }
+
+ // elide undefined values
+ if (outputValue == JSVAL_VOID)
+ continue;
+
+ // output a comma unless this is the first member to write
+ if (memberWritten) {
+ output = jschar(',');
+ ok = callback(&output, 1, data);
+ if (!ok)
+ break;
+ }
+ memberWritten = JS_TRUE;
+
+ JSType type = JS_TypeOfValue(cx, outputValue);
+
+ // Can't encode these types, so drop them
+ if (type == JSTYPE_FUNCTION || type == JSTYPE_XML)
+ break;
+
+ // Be careful below, this string is weakly rooted.
+ JSString *s;
+
+ // If this isn't an array, we need to output a key
+ if (!isArray) {
+ s = js_ValueToString(cx, key);
+ if (!s) {
+ ok = JS_FALSE;
+ break;
+ }
+
+ ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s));
+ if (!ok)
+ break;
+
+ output = jschar(':');
+ ok = callback(&output, 1, data);
+ if (!ok)
+ break;
+ }
+
+ if (!JSVAL_IS_PRIMITIVE(outputValue)) {
+ // recurse
+ ok = js_Stringify(cx, &outputValue, replacer, callback, data, depth + 1);
+ } else {
+ JSString *outputString;
+ s = js_ValueToString(cx, outputValue);
+ if (!s) {
+ ok = JS_FALSE;
+ break;
+ }
+
+ if (type == JSTYPE_STRING) {
+ ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s));
+ if (!ok)
+ break;
+
+ continue;
+ }
+
+ if (type == JSTYPE_NUMBER) {
+ if (JSVAL_IS_DOUBLE(outputValue)) {
+ jsdouble d = *JSVAL_TO_DOUBLE(outputValue);
+ if (!JSDOUBLE_IS_FINITE(d))
+ outputString = JS_NewStringCopyN(cx, "null", 4);
+ else
+ outputString = s;
+ } else {
+ outputString = s;
+ }
+ } else if (type == JSTYPE_BOOLEAN) {
+ outputString = s;
+ } else if (JSVAL_IS_NULL(outputValue)) {
+ outputString = JS_NewStringCopyN(cx, "null", 4);
+ } else {
+ ok = JS_FALSE; // encoding error
+ break;
+ }
+
+ if (!outputString) {
+ ok = JS_FALSE;
+ break;
+ }
+
+ ok = callback(JS_GetStringChars(outputString), JS_GetStringLength(outputString), data);
+ }
+ } while (ok);
+
+ if (iterObj) {
+ // Always close the iterator, but make sure not to stomp on OK
+ ok &= js_CloseIterator(cx, *vp);
+ // encoding error or propagate? FIXME: Bug 408838.
+ }
+
+ if (!ok) {
+ JS_ReportError(cx, "Error during JSON encoding");
+ return JS_FALSE;
+ }
+
+ output = jschar(isArray ? ']' : '}');
+ ok = callback(&output, 1, data);
+
+ return ok;
+}
+
+// helper to determine whether a character could be part of a number
+static JSBool IsNumChar(jschar c)
+{
+ return ((c <= '9' && c >= '0') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E');
+}
+
+JSONParser *
+js_BeginJSONParse(JSContext *cx, jsval *rootVal)
+{
+ if (!cx)
+ return NULL;
+
+ JSObject *arr = js_NewArrayObject(cx, 0, NULL);
+ if (!arr)
+ return NULL;
+
+ JSONParser *jp = (JSONParser*) JS_malloc(cx, sizeof(JSONParser));
+ if (!jp)
+ return NULL;
+ jp->buffer = NULL;
+
+ jp->objectStack = arr;
+ if (!js_AddRoot(cx, &jp->objectStack, "JSON parse stack"))
+ goto bad;
+
+ jp->hexChar = 0;
+ jp->numHex = 0;
+ jp->statep = jp->stateStack;
+ *jp->statep = JSON_PARSE_STATE_INIT;
+ jp->rootVal = rootVal;
+
+ jp->objectKey = (JSStringBuffer*) JS_malloc(cx, sizeof(JSStringBuffer));
+ if (!jp->objectKey)
+ goto bad;
+ js_InitStringBuffer(jp->objectKey);
+
+ jp->buffer = (JSStringBuffer*) JS_malloc(cx, sizeof(JSStringBuffer));
+ if (!jp->buffer)
+ goto bad;
+ js_InitStringBuffer(jp->buffer);
+
+ return jp;
+bad:
+ JS_free(cx, jp->buffer);
+ JS_free(cx, jp);
+ return NULL;
+}
+
+JSBool
+js_FinishJSONParse(JSContext *cx, JSONParser *jp)
+{
+ if (!jp)
+ return JS_TRUE;
+
+ if (jp->objectKey)
+ js_FinishStringBuffer(jp->objectKey);
+ JS_free(cx, jp->objectKey);
+
+ if (jp->buffer)
+ js_FinishStringBuffer(jp->buffer);
+ JS_free(cx, jp->buffer);
+
+ if (!js_RemoveRoot(cx->runtime, &jp->objectStack))
+ return JS_FALSE;
+ JSBool ok = *jp->statep == JSON_PARSE_STATE_FINISHED;
+ JS_free(cx, jp);
+
+ return ok;
+}
+
+static JSBool
+PushState(JSONParser *jp, JSONParserState state)
+{
+ if (*jp->statep == JSON_PARSE_STATE_FINISHED)
+ return JS_FALSE; // extra input
+
+ jp->statep++;
+ if ((uint32)(jp->statep - jp->stateStack) >= JS_ARRAY_LENGTH(jp->stateStack))
+ return JS_FALSE; // too deep
+
+ *jp->statep = state;
+
+ return JS_TRUE;
+}
+
+static JSBool
+PopState(JSONParser *jp)
+{
+ jp->statep--;
+ if (jp->statep < jp->stateStack) {
+ jp->statep = jp->stateStack;
+ return JS_FALSE;
+ }
+
+ if (*jp->statep == JSON_PARSE_STATE_INIT)
+ *jp->statep = JSON_PARSE_STATE_FINISHED;
+
+ return JS_TRUE;
+}
+
+static JSBool
+PushValue(JSContext *cx, JSONParser *jp, JSObject *parent, jsval value)
+{
+ JSAutoTempValueRooter tvr(cx, 1, &value);
+
+ JSBool ok;
+ if (OBJ_IS_ARRAY(cx, parent)) {
+ jsuint len;
+ ok = js_GetLengthProperty(cx, parent, &len);
+ if (ok) {
+ ok = OBJ_DEFINE_PROPERTY(cx, parent, INT_TO_JSID(len), value,
+ NULL, NULL, JSPROP_ENUMERATE, NULL);
+ }
+ } else {
+ ok = JS_DefineUCProperty(cx, parent, jp->objectKey->base,
+ STRING_BUFFER_OFFSET(jp->objectKey), value,
+ NULL, NULL, JSPROP_ENUMERATE);
+ js_FinishStringBuffer(jp->objectKey);
+ js_InitStringBuffer(jp->objectKey);
+ }
+
+ return ok;
+}
+
+static JSBool
+PushObject(JSContext *cx, JSONParser *jp, JSObject *obj)
+{
+ jsuint len;
+ if (!js_GetLengthProperty(cx, jp->objectStack, &len))
+ return JS_FALSE;
+ if (len >= JSON_MAX_DEPTH)
+ return JS_FALSE; // decoding error
+
+ jsval v = OBJECT_TO_JSVAL(obj);
+ JSAutoTempValueRooter tvr(cx, v);
+
+ // Check if this is the root object
+ if (len == 0) {
+ *jp->rootVal = v;
+ // This property must be enumerable to keep the array dense
+ if (!OBJ_DEFINE_PROPERTY(cx, jp->objectStack, INT_TO_JSID(0), *jp->rootVal,
+ NULL, NULL, JSPROP_ENUMERATE, NULL)) {
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+ }
+
+ jsval p;
+ if (!OBJ_GET_PROPERTY(cx, jp->objectStack, INT_TO_JSID(len - 1), &p))
+ return JS_FALSE;
+
+ JS_ASSERT(JSVAL_IS_OBJECT(p));
+ JSObject *parent = JSVAL_TO_OBJECT(p);
+ if (!PushValue(cx, jp, parent, OBJECT_TO_JSVAL(obj)))
+ return JS_FALSE;
+
+ // This property must be enumerable to keep the array dense
+ if (!OBJ_DEFINE_PROPERTY(cx, jp->objectStack, INT_TO_JSID(len), v,
+ NULL, NULL, JSPROP_ENUMERATE, NULL)) {
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+static JSObject *
+GetTopOfObjectStack(JSContext *cx, JSONParser *jp)
+{
+ jsuint length;
+ if (!js_GetLengthProperty(cx, jp->objectStack, &length))
+ return NULL;
+
+ jsval o;
+ if (!OBJ_GET_PROPERTY(cx, jp->objectStack, INT_TO_JSID(length - 1), &o))
+ return NULL;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(o));
+ return JSVAL_TO_OBJECT(o);
+}
+
+static JSBool
+OpenObject(JSContext *cx, JSONParser *jp)
+{
+ JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+
+ return PushObject(cx, jp, obj);
+}
+
+static JSBool
+OpenArray(JSContext *cx, JSONParser *jp)
+{
+ // Add an array to an existing array or object
+ JSObject *arr = js_NewArrayObject(cx, 0, NULL);
+ if (!arr)
+ return JS_FALSE;
+
+ return PushObject(cx, jp, arr);
+}
+
+static JSBool
+CloseObject(JSContext *cx, JSONParser *jp)
+{
+ jsuint len;
+ if (!js_GetLengthProperty(cx, jp->objectStack, &len))
+ return JS_FALSE;
+ if (!js_SetLengthProperty(cx, jp->objectStack, len - 1))
+ return JS_FALSE;
+
+ return JS_TRUE;
+}
+
+static JSBool
+CloseArray(JSContext *cx, JSONParser *jp)
+{
+ return CloseObject(cx, jp);
+}
+
+static JSBool
+HandleNumber(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
+{
+ const jschar *ep;
+ double val;
+ if (!js_strtod(cx, buf, buf + len, &ep, &val) || ep != buf + len)
+ return JS_FALSE;
+
+ JSBool ok;
+ jsval numVal;
+ JSObject *obj = GetTopOfObjectStack(cx, jp);
+ if (obj && JS_NewNumberValue(cx, val, &numVal))
+ ok = PushValue(cx, jp, obj, numVal);
+ else
+ ok = JS_FALSE; // decode error
+
+ return ok;
+}
+
+static JSBool
+HandleString(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
+{
+ JSObject *obj = GetTopOfObjectStack(cx, jp);
+ JSString *str = js_NewStringCopyN(cx, buf, len);
+ if (!obj || !str)
+ return JS_FALSE;
+
+ return PushValue(cx, jp, obj, STRING_TO_JSVAL(str));
+}
+
+static JSBool
+HandleKeyword(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
+{
+ jsval keyword;
+ JSTokenType tt = js_CheckKeyword(buf, len);
+ if (tt != TOK_PRIMARY)
+ return JS_FALSE;
+
+ if (buf[0] == 'n')
+ keyword = JSVAL_NULL;
+ else if (buf[0] == 't')
+ keyword = JSVAL_TRUE;
+ else if (buf[0] == 'f')
+ keyword = JSVAL_FALSE;
+ else
+ return JS_FALSE;
+
+ JSObject *obj = GetTopOfObjectStack(cx, jp);
+ if (!obj)
+ return JS_FALSE;
+
+ return PushValue(cx, jp, obj, keyword);
+}
+
+static JSBool
+HandleData(JSContext *cx, JSONParser *jp, JSONDataType type)
+{
+ JSBool ok = JS_FALSE;
+
+ if (!STRING_BUFFER_OK(jp->buffer))
+ return JS_FALSE;
+
+ switch (type) {
+ case JSON_DATA_STRING:
+ ok = HandleString(cx, jp, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
+ break;
+
+ case JSON_DATA_KEYSTRING:
+ js_AppendUCString(jp->objectKey, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
+ ok = STRING_BUFFER_OK(jp->objectKey);
+ break;
+
+ case JSON_DATA_NUMBER:
+ ok = HandleNumber(cx, jp, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
+ break;
+
+ case JSON_DATA_KEYWORD:
+ ok = HandleKeyword(cx, jp, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
+ break;
+
+ default:
+ JS_NOT_REACHED("Should have a JSON data type");
+ }
+
+ js_FinishStringBuffer(jp->buffer);
+ js_InitStringBuffer(jp->buffer);
+
+ return ok;
+}
+
+JSBool
+js_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len)
+{
+ uint32 i;
+
+ if (*jp->statep == JSON_PARSE_STATE_INIT) {
+ PushState(jp, JSON_PARSE_STATE_OBJECT_VALUE);
+ }
+
+ for (i = 0; i < len; i++) {
+ jschar c = data[i];
+ switch (*jp->statep) {
+ case JSON_PARSE_STATE_VALUE :
+ if (c == ']') {
+ // empty array
+ if (!PopState(jp))
+ return JS_FALSE;
+ if (*jp->statep != JSON_PARSE_STATE_ARRAY)
+ return JS_FALSE; // unexpected char
+ if (!CloseArray(cx, jp) || !PopState(jp))
+ return JS_FALSE;
+ break;
+ }
+
+ if (c == '}') {
+ // we should only find these in OBJECT_KEY state
+ return JS_FALSE; // unexpected failure
+ }
+
+ if (c == '"') {
+ *jp->statep = JSON_PARSE_STATE_STRING;
+ break;
+ }
+
+ if (IsNumChar(c)) {
+ *jp->statep = JSON_PARSE_STATE_NUMBER;
+ js_AppendChar(jp->buffer, c);
+ break;
+ }
+
+ if (JS7_ISLET(c)) {
+ *jp->statep = JSON_PARSE_STATE_KEYWORD;
+ js_AppendChar(jp->buffer, c);
+ break;
+ }
+
+ // fall through in case the value is an object or array
+ case JSON_PARSE_STATE_OBJECT_VALUE :
+ if (c == '{') {
+ *jp->statep = JSON_PARSE_STATE_OBJECT;
+ if (!OpenObject(cx, jp) || !PushState(jp, JSON_PARSE_STATE_OBJECT_PAIR))
+ return JS_FALSE;
+ } else if (c == '[') {
+ *jp->statep = JSON_PARSE_STATE_ARRAY;
+ if (!OpenArray(cx, jp) || !PushState(jp, JSON_PARSE_STATE_VALUE))
+ return JS_FALSE;
+ } else if (!JS_ISXMLSPACE(c)) {
+ return JS_FALSE; // unexpected
+ }
+ break;
+
+ case JSON_PARSE_STATE_OBJECT :
+ if (c == '}') {
+ if (!CloseObject(cx, jp) || !PopState(jp))
+ return JS_FALSE;
+ } else if (c == ',') {
+ if (!PushState(jp, JSON_PARSE_STATE_OBJECT_PAIR))
+ return JS_FALSE;
+ } else if (c == ']' || !JS_ISXMLSPACE(c)) {
+ return JS_FALSE; // unexpected
+ }
+ break;
+
+ case JSON_PARSE_STATE_ARRAY :
+ if (c == ']') {
+ if (!CloseArray(cx, jp) || !PopState(jp))
+ return JS_FALSE;
+ } else if (c == ',') {
+ if (!PushState(jp, JSON_PARSE_STATE_VALUE))
+ return JS_FALSE;
+ } else if (!JS_ISXMLSPACE(c)) {
+ return JS_FALSE; // unexpected
+ }
+ break;
+
+ case JSON_PARSE_STATE_OBJECT_PAIR :
+ if (c == '"') {
+ // we want to be waiting for a : when the string has been read
+ *jp->statep = JSON_PARSE_STATE_OBJECT_IN_PAIR;
+ if (!PushState(jp, JSON_PARSE_STATE_STRING))
+ return JS_FALSE;
+ } else if (c == '}') {
+ // pop off the object pair state and the object state
+ if (!CloseObject(cx, jp) || !PopState(jp) || !PopState(jp))
+ return JS_FALSE;
+ } else if (c == ']' || !JS_ISXMLSPACE(c)) {
+ return JS_FALSE; // unexpected
+ }
+ break;
+
+ case JSON_PARSE_STATE_OBJECT_IN_PAIR:
+ if (c == ':') {
+ *jp->statep = JSON_PARSE_STATE_VALUE;
+ } else if (!JS_ISXMLSPACE(c)) {
+ return JS_FALSE; // unexpected
+ }
+ break;
+
+ case JSON_PARSE_STATE_STRING:
+ if (c == '"') {
+ if (!PopState(jp))
+ return JS_FALSE;
+ JSONDataType jdt;
+ if (*jp->statep == JSON_PARSE_STATE_OBJECT_IN_PAIR) {
+ jdt = JSON_DATA_KEYSTRING;
+ } else {
+ jdt = JSON_DATA_STRING;
+ }
+ if (!HandleData(cx, jp, jdt))
+ return JS_FALSE;
+ } else if (c == '\\') {
+ *jp->statep = JSON_PARSE_STATE_STRING_ESCAPE;
+ } else {
+ js_AppendChar(jp->buffer, c);
+ }
+ break;
+
+ case JSON_PARSE_STATE_STRING_ESCAPE:
+ switch (c) {
+ case '"':
+ case '\\':
+ case '/':
+ break;
+ case 'b' : c = '\b'; break;
+ case 'f' : c = '\f'; break;
+ case 'n' : c = '\n'; break;
+ case 'r' : c = '\r'; break;
+ case 't' : c = '\t'; break;
+ default :
+ if (c == 'u') {
+ jp->numHex = 0;
+ jp->hexChar = 0;
+ *jp->statep = JSON_PARSE_STATE_STRING_HEX;
+ continue;
+ } else {
+ return JS_FALSE; // unexpected
+ }
+ }
+
+ js_AppendChar(jp->buffer, c);
+ *jp->statep = JSON_PARSE_STATE_STRING;
+ break;
+
+ case JSON_PARSE_STATE_STRING_HEX:
+ if (('0' <= c) && (c <= '9'))
+ jp->hexChar = (jp->hexChar << 4) | (c - '0');
+ else if (('a' <= c) && (c <= 'f'))
+ jp->hexChar = (jp->hexChar << 4) | (c - 'a' + 0x0a);
+ else if (('A' <= c) && (c <= 'F'))
+ jp->hexChar = (jp->hexChar << 4) | (c - 'A' + 0x0a);
+ else
+ return JS_FALSE; // unexpected
+
+ if (++(jp->numHex) == 4) {
+ js_AppendChar(jp->buffer, jp->hexChar);
+ jp->hexChar = 0;
+ jp->numHex = 0;
+ *jp->statep = JSON_PARSE_STATE_STRING;
+ }
+ break;
+
+ case JSON_PARSE_STATE_KEYWORD:
+ if (JS7_ISLET(c)) {
+ js_AppendChar(jp->buffer, c);
+ } else {
+ // this character isn't part of the keyword, process it again
+ i--;
+ if (!PopState(jp))
+ return JS_FALSE;
+
+ if (!HandleData(cx, jp, JSON_DATA_KEYWORD))
+ return JS_FALSE;
+ }
+ break;
+
+ case JSON_PARSE_STATE_NUMBER:
+ if (IsNumChar(c)) {
+ js_AppendChar(jp->buffer, c);
+ } else {
+ // this character isn't part of the number, process it again
+ i--;
+ if (!PopState(jp))
+ return JS_FALSE;
+ if (!HandleData(cx, jp, JSON_DATA_NUMBER))
+ return JS_FALSE;
+ }
+ break;
+
+ case JSON_PARSE_STATE_FINISHED:
+ if (!JS_ISXMLSPACE(c))
+ return JS_FALSE; // extra input
+
+ break;
+
+ default:
+ JS_NOT_REACHED("Invalid JSON parser state");
+ }
+ }
+
+ return JS_TRUE;
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+json_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ *vp = ATOM_KEY(CLASS_ATOM(cx, JSON));
+ return JS_TRUE;
+}
+#endif
+
+static JSFunctionSpec json_static_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, json_toSource, 0, 0),
+#endif
+ JS_FN("parse", js_json_parse, 0, 0),
+ JS_FN("stringify", js_json_stringify, 0, 0),
+ JS_FS_END
+};
+
+JSObject *
+js_InitJSONClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *JSON;
+
+ JSON = JS_NewObject(cx, &js_JSONClass, NULL, obj);
+ if (!JSON)
+ return NULL;
+ if (!JS_DefineProperty(cx, obj, js_JSON_str, OBJECT_TO_JSVAL(JSON),
+ JS_PropertyStub, JS_PropertyStub, 0))
+ return NULL;
+
+ if (!JS_DefineFunctions(cx, JSON, json_static_methods))
+ return NULL;
+
+ return JSON;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/json.h b/tools/node_modules/expresso/deps/jscoverage/js/json.h
new file mode 100644
index 0000000..b2fc729
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/json.h
@@ -0,0 +1,107 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey JSON.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Robert Sayre <sayrer@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef json_h___
+#define json_h___
+/*
+ * JS JSON functions.
+ */
+
+#define JSON_MAX_DEPTH 2048
+#define JSON_PARSER_BUFSIZE 1024
+
+JS_BEGIN_EXTERN_C
+
+extern JSClass js_JSONClass;
+
+extern JSObject *
+js_InitJSONClass(JSContext *cx, JSObject *obj);
+
+extern JSBool
+js_Stringify(JSContext *cx, jsval *vp, JSObject *replacer,
+ JSONWriteCallback callback, void *data, uint32 depth);
+
+extern JSBool js_TryJSON(JSContext *cx, jsval *vp);
+
+enum JSONParserState {
+ JSON_PARSE_STATE_INIT,
+ JSON_PARSE_STATE_OBJECT_VALUE,
+ JSON_PARSE_STATE_VALUE,
+ JSON_PARSE_STATE_OBJECT,
+ JSON_PARSE_STATE_OBJECT_PAIR,
+ JSON_PARSE_STATE_OBJECT_IN_PAIR,
+ JSON_PARSE_STATE_ARRAY,
+ JSON_PARSE_STATE_STRING,
+ JSON_PARSE_STATE_STRING_ESCAPE,
+ JSON_PARSE_STATE_STRING_HEX,
+ JSON_PARSE_STATE_NUMBER,
+ JSON_PARSE_STATE_KEYWORD,
+ JSON_PARSE_STATE_FINISHED
+};
+
+enum JSONDataType {
+ JSON_DATA_STRING,
+ JSON_DATA_KEYSTRING,
+ JSON_DATA_NUMBER,
+ JSON_DATA_KEYWORD
+};
+
+struct JSONParser {
+ /* Used while handling \uNNNN in strings */
+ jschar hexChar;
+ uint8 numHex;
+
+ JSONParserState *statep;
+ JSONParserState stateStack[JSON_MAX_DEPTH];
+ jsval *rootVal;
+ JSStringBuffer *objectKey;
+ JSStringBuffer *buffer;
+ JSObject *objectStack;
+};
+
+extern JSONParser *
+js_BeginJSONParse(JSContext *cx, jsval *rootVal);
+
+extern JSBool
+js_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len);
+
+extern JSBool
+js_FinishJSONParse(JSContext *cx, JSONParser *jp);
+
+JS_END_EXTERN_C
+
+#endif /* json_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.cpp
new file mode 100644
index 0000000..a3227dc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.cpp
@@ -0,0 +1,5304 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS bytecode descriptors, disassemblers, and decompilers.
+ */
+#include "jsstddef.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsdtoa.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsiter.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsregexp.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsstaticcheck.h"
+#include "jstracer.h"
+
+#include "jsautooplen.h"
+
+/* Verify JSOP_XXX_LENGTH constant definitions. */
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ JS_STATIC_ASSERT(op##_LENGTH == length);
+#include "jsopcode.tbl"
+#undef OPDEF
+
+static const char js_incop_strs[][3] = {"++", "--"};
+static const char js_for_each_str[] = "for each";
+
+const JSCodeSpec js_CodeSpec[] = {
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ {length,nuses,ndefs,prec,format},
+#include "jsopcode.tbl"
+#undef OPDEF
+};
+
+uintN js_NumCodeSpecs = JS_ARRAY_LENGTH(js_CodeSpec);
+
+/*
+ * Each element of the array is either a source literal associated with JS
+ * bytecode or null.
+ */
+static const char *CodeToken[] = {
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ token,
+#include "jsopcode.tbl"
+#undef OPDEF
+};
+
+#if defined(DEBUG) || defined(JS_JIT_SPEW)
+/*
+ * Array of JS bytecode names used by DEBUG-only js_Disassemble and by
+ * JIT debug spew.
+ */
+const char *js_CodeName[] = {
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ name,
+#include "jsopcode.tbl"
+#undef OPDEF
+};
+#endif
+
+/************************************************************************/
+
+static ptrdiff_t
+GetJumpOffset(jsbytecode *pc, jsbytecode *pc2)
+{
+ uint32 type;
+
+ type = JOF_OPTYPE(*pc);
+ if (JOF_TYPE_IS_EXTENDED_JUMP(type))
+ return GET_JUMPX_OFFSET(pc2);
+ return GET_JUMP_OFFSET(pc2);
+}
+
+uintN
+js_GetIndexFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc,
+ ptrdiff_t pcoff)
+{
+ JSOp op;
+ uintN span, base;
+
+ op = (JSOp)*pc;
+ if (op == JSOP_TRAP)
+ op = JS_GetTrapOpcode(cx, script, pc);
+ JS_ASSERT(js_CodeSpec[op].length >= 1 + pcoff + UINT16_LEN);
+
+ /*
+ * We need to detect index base prefix. It presents when resetbase
+ * follows the bytecode.
+ */
+ span = js_CodeSpec[op].length;
+ base = 0;
+ if (pc - script->code + span < script->length) {
+ if (pc[span] == JSOP_RESETBASE) {
+ base = GET_INDEXBASE(pc - JSOP_INDEXBASE_LENGTH);
+ } else if (pc[span] == JSOP_RESETBASE0) {
+ JS_ASSERT(JSOP_INDEXBASE1 <= pc[-1] || pc[-1] <= JSOP_INDEXBASE3);
+ base = (pc[-1] - JSOP_INDEXBASE1 + 1) << 16;
+ }
+ }
+ return base + GET_UINT16(pc + pcoff);
+}
+
+uintN
+js_GetVariableBytecodeLength(jsbytecode *pc)
+{
+ JSOp op;
+ uintN jmplen, ncases;
+ jsint low, high;
+
+ op = (JSOp) *pc;
+ JS_ASSERT(js_CodeSpec[op].length == -1);
+ switch (op) {
+ case JSOP_TABLESWITCHX:
+ jmplen = JUMPX_OFFSET_LEN;
+ goto do_table;
+ case JSOP_TABLESWITCH:
+ jmplen = JUMP_OFFSET_LEN;
+ do_table:
+ /* Structure: default-jump case-low case-high case1-jump ... */
+ pc += jmplen;
+ low = GET_JUMP_OFFSET(pc);
+ pc += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc);
+ ncases = (uintN)(high - low + 1);
+ return 1 + jmplen + INDEX_LEN + INDEX_LEN + ncases * jmplen;
+
+ case JSOP_LOOKUPSWITCHX:
+ jmplen = JUMPX_OFFSET_LEN;
+ goto do_lookup;
+ default:
+ JS_ASSERT(op == JSOP_LOOKUPSWITCH);
+ jmplen = JUMP_OFFSET_LEN;
+ do_lookup:
+ /* Structure: default-jump case-count (case1-value case1-jump) ... */
+ pc += jmplen;
+ ncases = GET_UINT16(pc);
+ return 1 + jmplen + INDEX_LEN + ncases * (INDEX_LEN + jmplen);
+ }
+}
+
+uintN
+js_GetVariableStackUseLength(JSOp op, jsbytecode *pc)
+{
+ JS_ASSERT(*pc == op || *pc == JSOP_TRAP);
+ JS_ASSERT(js_CodeSpec[op].nuses == -1);
+ switch (op) {
+ case JSOP_POPN:
+ return GET_UINT16(pc);
+ case JSOP_LEAVEBLOCK:
+ return GET_UINT16(pc);
+ case JSOP_LEAVEBLOCKEXPR:
+ return GET_UINT16(pc) + 1;
+ case JSOP_NEWARRAY:
+ return GET_UINT24(pc);
+ default:
+ /* stack: fun, this, [argc arguments] */
+ JS_ASSERT(op == JSOP_NEW || op == JSOP_CALL ||
+ op == JSOP_EVAL || op == JSOP_SETCALL ||
+ op == JSOP_APPLY);
+ return 2 + GET_ARGC(pc);
+ }
+}
+
+#ifdef DEBUG
+
+JS_FRIEND_API(JSBool)
+js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp)
+{
+ jsbytecode *pc, *end;
+ uintN len;
+
+ pc = script->code;
+ end = pc + script->length;
+ while (pc < end) {
+ if (pc == script->main)
+ fputs("main:\n", fp);
+ len = js_Disassemble1(cx, script, pc,
+ PTRDIFF(pc, script->code, jsbytecode),
+ lines, fp);
+ if (!len)
+ return JS_FALSE;
+ pc += len;
+ }
+ return JS_TRUE;
+}
+
+const char *
+ToDisassemblySource(JSContext *cx, jsval v)
+{
+ JSObject *obj;
+ JSScopeProperty *sprop;
+ char *source;
+ const char *bytes;
+ JSString *str;
+
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ obj = JSVAL_TO_OBJECT(v);
+ if (OBJ_GET_CLASS(cx, obj) == &js_BlockClass) {
+ source = JS_sprintf_append(NULL, "depth %d {",
+ OBJ_BLOCK_DEPTH(cx, obj));
+ for (sprop = OBJ_SCOPE(obj)->lastProp; sprop;
+ sprop = sprop->parent) {
+ bytes = js_AtomToPrintableString(cx, JSID_TO_ATOM(sprop->id));
+ if (!bytes)
+ return NULL;
+ source = JS_sprintf_append(source, "%s: %d%s",
+ bytes, sprop->shortid,
+ sprop->parent ? ", " : "");
+ }
+ source = JS_sprintf_append(source, "}");
+ if (!source)
+ return NULL;
+ str = JS_NewString(cx, source, strlen(source));
+ if (!str)
+ return NULL;
+ return js_GetStringBytes(cx, str);
+ }
+ }
+ return js_ValueToPrintableSource(cx, v);
+}
+
+JS_FRIEND_API(uintN)
+js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
+ uintN loc, JSBool lines, FILE *fp)
+{
+ JSOp op;
+ const JSCodeSpec *cs;
+ ptrdiff_t len, off, jmplen;
+ uint32 type;
+ JSAtom *atom;
+ uintN index;
+ JSObject *obj;
+ jsval v;
+ const char *bytes;
+ jsint i;
+
+ op = (JSOp)*pc;
+ if (op >= JSOP_LIMIT) {
+ char numBuf1[12], numBuf2[12];
+ JS_snprintf(numBuf1, sizeof numBuf1, "%d", op);
+ JS_snprintf(numBuf2, sizeof numBuf2, "%d", JSOP_LIMIT);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BYTECODE_TOO_BIG, numBuf1, numBuf2);
+ return 0;
+ }
+ cs = &js_CodeSpec[op];
+ len = (ptrdiff_t) cs->length;
+ fprintf(fp, "%05u:", loc);
+ if (lines)
+ fprintf(fp, "%4u", JS_PCToLineNumber(cx, script, pc));
+ fprintf(fp, " %s", js_CodeName[op]);
+ type = JOF_TYPE(cs->format);
+ switch (type) {
+ case JOF_BYTE:
+ if (op == JSOP_TRAP) {
+ op = JS_GetTrapOpcode(cx, script, pc);
+ len = (ptrdiff_t) js_CodeSpec[op].length;
+ }
+ break;
+
+ case JOF_JUMP:
+ case JOF_JUMPX:
+ off = GetJumpOffset(pc, pc);
+ fprintf(fp, " %u (%d)", loc + (intN) off, (intN) off);
+ break;
+
+ case JOF_ATOM:
+ case JOF_OBJECT:
+ case JOF_REGEXP:
+ index = js_GetIndexFromBytecode(cx, script, pc, 0);
+ if (type == JOF_ATOM) {
+ JS_GET_SCRIPT_ATOM(script, index, atom);
+ v = ATOM_KEY(atom);
+ } else {
+ if (type == JOF_OBJECT)
+ JS_GET_SCRIPT_OBJECT(script, index, obj);
+ else
+ JS_GET_SCRIPT_REGEXP(script, index, obj);
+ v = OBJECT_TO_JSVAL(obj);
+ }
+ bytes = ToDisassemblySource(cx, v);
+ if (!bytes)
+ return 0;
+ fprintf(fp, " %s", bytes);
+ break;
+
+ case JOF_UINT16:
+ i = (jsint)GET_UINT16(pc);
+ goto print_int;
+
+ case JOF_TABLESWITCH:
+ case JOF_TABLESWITCHX:
+ {
+ jsbytecode *pc2;
+ jsint i, low, high;
+
+ jmplen = (type == JOF_TABLESWITCH) ? JUMP_OFFSET_LEN
+ : JUMPX_OFFSET_LEN;
+ pc2 = pc;
+ off = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+ low = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ fprintf(fp, " defaultOffset %d low %d high %d", (intN) off, low, high);
+ for (i = low; i <= high; i++) {
+ off = GetJumpOffset(pc, pc2);
+ fprintf(fp, "\n\t%d: %d", i, (intN) off);
+ pc2 += jmplen;
+ }
+ len = 1 + pc2 - pc;
+ break;
+ }
+
+ case JOF_LOOKUPSWITCH:
+ case JOF_LOOKUPSWITCHX:
+ {
+ jsbytecode *pc2;
+ jsatomid npairs;
+
+ jmplen = (type == JOF_LOOKUPSWITCH) ? JUMP_OFFSET_LEN
+ : JUMPX_OFFSET_LEN;
+ pc2 = pc;
+ off = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+ npairs = GET_UINT16(pc2);
+ pc2 += UINT16_LEN;
+ fprintf(fp, " offset %d npairs %u", (intN) off, (uintN) npairs);
+ while (npairs) {
+ JS_GET_SCRIPT_ATOM(script, GET_INDEX(pc2), atom);
+ pc2 += INDEX_LEN;
+ off = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+
+ bytes = ToDisassemblySource(cx, ATOM_KEY(atom));
+ if (!bytes)
+ return 0;
+ fprintf(fp, "\n\t%s: %d", bytes, (intN) off);
+ npairs--;
+ }
+ len = 1 + pc2 - pc;
+ break;
+ }
+
+ case JOF_QARG:
+ fprintf(fp, " %u", GET_ARGNO(pc));
+ break;
+
+ case JOF_LOCAL:
+ fprintf(fp, " %u", GET_SLOTNO(pc));
+ break;
+
+ case JOF_SLOTATOM:
+ case JOF_SLOTOBJECT:
+ fprintf(fp, " %u", GET_SLOTNO(pc));
+ index = js_GetIndexFromBytecode(cx, script, pc, SLOTNO_LEN);
+ if (type == JOF_SLOTATOM) {
+ JS_GET_SCRIPT_ATOM(script, index, atom);
+ v = ATOM_KEY(atom);
+ } else {
+ JS_GET_SCRIPT_OBJECT(script, index, obj);
+ v = OBJECT_TO_JSVAL(obj);
+ }
+ bytes = ToDisassemblySource(cx, v);
+ if (!bytes)
+ return 0;
+ fprintf(fp, " %s", bytes);
+ break;
+
+ case JOF_UINT24:
+ JS_ASSERT(op == JSOP_UINT24 || op == JSOP_NEWARRAY);
+ i = (jsint)GET_UINT24(pc);
+ goto print_int;
+
+ case JOF_UINT8:
+ i = pc[1];
+ goto print_int;
+
+ case JOF_INT8:
+ i = GET_INT8(pc);
+ goto print_int;
+
+ case JOF_INT32:
+ JS_ASSERT(op == JSOP_INT32);
+ i = GET_INT32(pc);
+ print_int:
+ fprintf(fp, " %d", i);
+ break;
+
+ default: {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) cs->format);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_UNKNOWN_FORMAT, numBuf);
+ return 0;
+ }
+ }
+ fputs("\n", fp);
+ return len;
+}
+
+#endif /* DEBUG */
+
+/************************************************************************/
+
+/*
+ * Sprintf, but with unlimited and automatically allocated buffering.
+ */
+typedef struct Sprinter {
+ JSContext *context; /* context executing the decompiler */
+ JSArenaPool *pool; /* string allocation pool */
+ char *base; /* base address of buffer in pool */
+ size_t size; /* size of buffer allocated at base */
+ ptrdiff_t offset; /* offset of next free char in buffer */
+} Sprinter;
+
+#define INIT_SPRINTER(cx, sp, ap, off) \
+ ((sp)->context = cx, (sp)->pool = ap, (sp)->base = NULL, (sp)->size = 0, \
+ (sp)->offset = off)
+
+#define OFF2STR(sp,off) ((sp)->base + (off))
+#define STR2OFF(sp,str) ((str) - (sp)->base)
+#define RETRACT(sp,str) ((sp)->offset = STR2OFF(sp, str))
+
+static JSBool
+SprintEnsureBuffer(Sprinter *sp, size_t len)
+{
+ ptrdiff_t nb;
+ char *base;
+
+ nb = (sp->offset + len + 1) - sp->size;
+ if (nb < 0)
+ return JS_TRUE;
+ base = sp->base;
+ if (!base) {
+ JS_ARENA_ALLOCATE_CAST(base, char *, sp->pool, nb);
+ } else {
+ JS_ARENA_GROW_CAST(base, char *, sp->pool, sp->size, nb);
+ }
+ if (!base) {
+ js_ReportOutOfScriptQuota(sp->context);
+ return JS_FALSE;
+ }
+ sp->base = base;
+ sp->size += nb;
+ return JS_TRUE;
+}
+
+static ptrdiff_t
+SprintPut(Sprinter *sp, const char *s, size_t len)
+{
+ ptrdiff_t offset;
+ char *bp;
+
+ /* Allocate space for s, including the '\0' at the end. */
+ if (!SprintEnsureBuffer(sp, len))
+ return -1;
+
+ /* Advance offset and copy s into sp's buffer. */
+ offset = sp->offset;
+ sp->offset += len;
+ bp = sp->base + offset;
+ memmove(bp, s, len);
+ bp[len] = 0;
+ return offset;
+}
+
+static ptrdiff_t
+SprintCString(Sprinter *sp, const char *s)
+{
+ return SprintPut(sp, s, strlen(s));
+}
+
+static ptrdiff_t
+SprintString(Sprinter *sp, JSString *str)
+{
+ jschar *chars;
+ size_t length, size;
+ ptrdiff_t offset;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ if (length == 0)
+ return sp->offset;
+
+ size = js_GetDeflatedStringLength(sp->context, chars, length);
+ if (size == (size_t)-1 || !SprintEnsureBuffer(sp, size))
+ return -1;
+
+ offset = sp->offset;
+ sp->offset += size;
+ js_DeflateStringToBuffer(sp->context, chars, length, sp->base + offset,
+ &size);
+ sp->base[sp->offset] = 0;
+ return offset;
+}
+
+
+static ptrdiff_t
+Sprint(Sprinter *sp, const char *format, ...)
+{
+ va_list ap;
+ char *bp;
+ ptrdiff_t offset;
+
+ va_start(ap, format);
+ bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */
+ va_end(ap);
+ if (!bp) {
+ JS_ReportOutOfMemory(sp->context);
+ return -1;
+ }
+ offset = SprintCString(sp, bp);
+ free(bp);
+ return offset;
+}
+
+const char js_EscapeMap[] = {
+ '\b', 'b',
+ '\f', 'f',
+ '\n', 'n',
+ '\r', 'r',
+ '\t', 't',
+ '\v', 'v',
+ '"', '"',
+ '\'', '\'',
+ '\\', '\\',
+ '\0', '0'
+};
+
+#define DONT_ESCAPE 0x10000
+
+static char *
+QuoteString(Sprinter *sp, JSString *str, uint32 quote)
+{
+ JSBool dontEscape, ok;
+ jschar qc, c;
+ ptrdiff_t off, len;
+ const jschar *s, *t, *z;
+ const char *e;
+ char *bp;
+
+ /* Sample off first for later return value pointer computation. */
+ dontEscape = (quote & DONT_ESCAPE) != 0;
+ qc = (jschar) quote;
+ off = sp->offset;
+ if (qc && Sprint(sp, "%c", (char)qc) < 0)
+ return NULL;
+
+ /* Loop control variables: z points at end of string sentinel. */
+ JSSTRING_CHARS_AND_END(str, s, z);
+ for (t = s; t < z; s = ++t) {
+ /* Move t forward from s past un-quote-worthy characters. */
+ c = *t;
+ while (JS_ISPRINT(c) && c != qc && c != '\\' && c != '\t' &&
+ !(c >> 8)) {
+ c = *++t;
+ if (t == z)
+ break;
+ }
+ len = PTRDIFF(t, s, jschar);
+
+ /* Allocate space for s, including the '\0' at the end. */
+ if (!SprintEnsureBuffer(sp, len))
+ return NULL;
+
+ /* Advance sp->offset and copy s into sp's buffer. */
+ bp = sp->base + sp->offset;
+ sp->offset += len;
+ while (--len >= 0)
+ *bp++ = (char) *s++;
+ *bp = '\0';
+
+ if (t == z)
+ break;
+
+ /* Use js_EscapeMap, \u, or \x only if necessary. */
+ if (!(c >> 8) && (e = strchr(js_EscapeMap, (int)c)) != NULL) {
+ ok = dontEscape
+ ? Sprint(sp, "%c", (char)c) >= 0
+ : Sprint(sp, "\\%c", e[1]) >= 0;
+ } else {
+ ok = Sprint(sp, (c >> 8) ? "\\u%04X" : "\\x%02X", c) >= 0;
+ }
+ if (!ok)
+ return NULL;
+ }
+
+ /* Sprint the closing quote and return the quoted string. */
+ if (qc && Sprint(sp, "%c", (char)qc) < 0)
+ return NULL;
+
+ /*
+ * If we haven't Sprint'd anything yet, Sprint an empty string so that
+ * the OFF2STR below gives a valid result.
+ */
+ if (off == sp->offset && Sprint(sp, "") < 0)
+ return NULL;
+ return OFF2STR(sp, off);
+}
+
+JSString *
+js_QuoteString(JSContext *cx, JSString *str, jschar quote)
+{
+ void *mark;
+ Sprinter sprinter;
+ char *bytes;
+ JSString *escstr;
+
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
+ bytes = QuoteString(&sprinter, str, quote);
+ escstr = bytes ? JS_NewStringCopyZ(cx, bytes) : NULL;
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return escstr;
+}
+
+/************************************************************************/
+
+struct JSPrinter {
+ Sprinter sprinter; /* base class state */
+ JSArenaPool pool; /* string allocation pool */
+ uintN indent; /* indentation in spaces */
+ JSPackedBool pretty; /* pretty-print: indent, use newlines */
+ JSPackedBool grouped; /* in parenthesized expression context */
+ JSScript *script; /* script being printed */
+ jsbytecode *dvgfence; /* DecompileExpression fencepost */
+ jsbytecode **pcstack; /* DecompileExpression modeled stack */
+ JSFunction *fun; /* interpreted function */
+ jsuword *localNames; /* argument and variable names */
+};
+
+/*
+ * Hack another flag, a la JS_DONT_PRETTY_PRINT, into uintN indent parameters
+ * to functions such as js_DecompileFunction and js_NewPrinter. This time, as
+ * opposed to JS_DONT_PRETTY_PRINT back in the dark ages, we can assume that a
+ * uintN is at least 32 bits.
+ */
+#define JS_IN_GROUP_CONTEXT 0x10000
+
+JSPrinter *
+JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
+ uintN indent, JSBool pretty)
+{
+ JSPrinter *jp;
+
+ jp = (JSPrinter *) JS_malloc(cx, sizeof(JSPrinter));
+ if (!jp)
+ return NULL;
+ INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);
+ JS_INIT_ARENA_POOL(&jp->pool, name, 256, 1, &cx->scriptStackQuota);
+ jp->indent = indent & ~JS_IN_GROUP_CONTEXT;
+ jp->pretty = pretty;
+ jp->grouped = (indent & JS_IN_GROUP_CONTEXT) != 0;
+ jp->script = NULL;
+ jp->dvgfence = NULL;
+ jp->pcstack = NULL;
+ jp->fun = fun;
+ jp->localNames = NULL;
+ if (fun && FUN_INTERPRETED(fun) && JS_GET_LOCAL_NAME_COUNT(fun)) {
+ jp->localNames = js_GetLocalNameArray(cx, fun, &jp->pool);
+ if (!jp->localNames) {
+ js_DestroyPrinter(jp);
+ return NULL;
+ }
+ }
+ return jp;
+}
+
+void
+js_DestroyPrinter(JSPrinter *jp)
+{
+ JS_FinishArenaPool(&jp->pool);
+ JS_free(jp->sprinter.context, jp);
+}
+
+JSString *
+js_GetPrinterOutput(JSPrinter *jp)
+{
+ JSContext *cx;
+ JSString *str;
+
+ cx = jp->sprinter.context;
+ if (!jp->sprinter.base)
+ return cx->runtime->emptyString;
+ str = JS_NewStringCopyZ(cx, jp->sprinter.base);
+ if (!str)
+ return NULL;
+ JS_FreeArenaPool(&jp->pool);
+ INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);
+ return str;
+}
+
+/*
+ * NB: Indexed by SRC_DECL_* defines from jsemit.h.
+ */
+static const char * const var_prefix[] = {"var ", "const ", "let "};
+
+static const char *
+VarPrefix(jssrcnote *sn)
+{
+ if (sn && (SN_TYPE(sn) == SRC_DECL || SN_TYPE(sn) == SRC_GROUPASSIGN)) {
+ ptrdiff_t type = js_GetSrcNoteOffset(sn, 0);
+ if ((uintN)type <= SRC_DECL_LET)
+ return var_prefix[type];
+ }
+ return "";
+}
+
+int
+js_printf(JSPrinter *jp, const char *format, ...)
+{
+ va_list ap;
+ char *bp, *fp;
+ int cc;
+
+ if (*format == '\0')
+ return 0;
+
+ va_start(ap, format);
+
+ /* If pretty-printing, expand magic tab into a run of jp->indent spaces. */
+ if (*format == '\t') {
+ format++;
+ if (jp->pretty && Sprint(&jp->sprinter, "%*s", jp->indent, "") < 0)
+ return -1;
+ }
+
+ /* Suppress newlines (must be once per format, at the end) if not pretty. */
+ fp = NULL;
+ if (!jp->pretty && format[cc = strlen(format) - 1] == '\n') {
+ fp = JS_strdup(jp->sprinter.context, format);
+ if (!fp)
+ return -1;
+ fp[cc] = '\0';
+ format = fp;
+ }
+
+ /* Allocate temp space, convert format, and put. */
+ bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */
+ if (fp) {
+ JS_free(jp->sprinter.context, fp);
+ format = NULL;
+ }
+ if (!bp) {
+ JS_ReportOutOfMemory(jp->sprinter.context);
+ return -1;
+ }
+
+ cc = strlen(bp);
+ if (SprintPut(&jp->sprinter, bp, (size_t)cc) < 0)
+ cc = -1;
+ free(bp);
+
+ va_end(ap);
+ return cc;
+}
+
+JSBool
+js_puts(JSPrinter *jp, const char *s)
+{
+ return SprintCString(&jp->sprinter, s) >= 0;
+}
+
+/************************************************************************/
+
+typedef struct SprintStack {
+ Sprinter sprinter; /* sprinter for postfix to infix buffering */
+ ptrdiff_t *offsets; /* stack of postfix string offsets */
+ jsbytecode *opcodes; /* parallel stack of JS opcodes */
+ uintN top; /* top of stack index */
+ uintN inArrayInit; /* array initialiser/comprehension level */
+ JSBool inGenExp; /* in generator expression */
+ JSPrinter *printer; /* permanent output goes here */
+} SprintStack;
+
+/*
+ * Find the depth of the operand stack when the interpreter reaches the given
+ * pc in script. pcstack must have space for least script->depth elements. On
+ * return it will contain pointers to opcodes that populated the interpreter's
+ * current operand stack.
+ *
+ * This function cannot raise an exception or error. However, due to a risk of
+ * potential bugs when modeling the stack, the function returns -1 if it
+ * detects an inconsistency in the model. Such an inconsistency triggers an
+ * assert in a debug build.
+ */
+static intN
+ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *pc,
+ jsbytecode **pcstack);
+
+#define FAILED_EXPRESSION_DECOMPILER ((char *) 1)
+
+/*
+ * Decompile a part of expression up to the given pc. The function returns
+ * NULL on out-of-memory, or the FAILED_EXPRESSION_DECOMPILER sentinel when
+ * the decompiler fails due to a bug and/or unimplemented feature, or the
+ * decompiled string on success.
+ */
+static char *
+DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
+ jsbytecode *pc);
+
+/*
+ * Get a stacked offset from ss->sprinter.base, or if the stacked value |off|
+ * is negative, fetch the generating pc from printer->pcstack[-2 - off] and
+ * decompile the code that generated the missing value. This is used when
+ * reporting errors, where the model stack will lack |pcdepth| non-negative
+ * offsets (see DecompileExpression and DecompileCode).
+ *
+ * If the stacked offset is -1, return 0 to index the NUL padding at the start
+ * of ss->sprinter.base. If this happens, it means there is a decompiler bug
+ * to fix, but it won't violate memory safety.
+ */
+static ptrdiff_t
+GetOff(SprintStack *ss, uintN i)
+{
+ ptrdiff_t off;
+ jsbytecode *pc;
+ char *bytes;
+
+ off = ss->offsets[i];
+ if (off >= 0)
+ return off;
+
+ JS_ASSERT(off <= -2);
+ JS_ASSERT(ss->printer->pcstack);
+ if (off < -2 && ss->printer->pcstack) {
+ pc = ss->printer->pcstack[-2 - off];
+ bytes = DecompileExpression(ss->sprinter.context, ss->printer->script,
+ ss->printer->fun, pc);
+ if (!bytes)
+ return 0;
+ if (bytes != FAILED_EXPRESSION_DECOMPILER) {
+ off = SprintCString(&ss->sprinter, bytes);
+ if (off < 0)
+ off = 0;
+ ss->offsets[i] = off;
+ JS_free(ss->sprinter.context, bytes);
+ return off;
+ }
+ if (!ss->sprinter.base && SprintPut(&ss->sprinter, "", 0) >= 0) {
+ memset(ss->sprinter.base, 0, ss->sprinter.offset);
+ ss->offsets[i] = -1;
+ }
+ }
+ return 0;
+}
+
+static const char *
+GetStr(SprintStack *ss, uintN i)
+{
+ ptrdiff_t off;
+
+ /*
+ * Must call GetOff before using ss->sprinter.base, since it may be null
+ * until bootstrapped by GetOff.
+ */
+ off = GetOff(ss, i);
+ return OFF2STR(&ss->sprinter, off);
+}
+
+/*
+ * Gap between stacked strings to allow for insertion of parens and commas
+ * when auto-parenthesizing expressions and decompiling array initialisers
+ * (see the JSOP_NEWARRAY case in Decompile).
+ */
+#define PAREN_SLOP (2 + 1)
+
+/*
+ * These pseudo-ops help js_DecompileValueGenerator decompile JSOP_SETNAME,
+ * JSOP_SETPROP, and JSOP_SETELEM, respectively. They are never stored in
+ * bytecode, so they don't preempt valid opcodes.
+ */
+#define JSOP_GETPROP2 256
+#define JSOP_GETELEM2 257
+
+static void
+AddParenSlop(SprintStack *ss)
+{
+ memset(OFF2STR(&ss->sprinter, ss->sprinter.offset), 0, PAREN_SLOP);
+ ss->sprinter.offset += PAREN_SLOP;
+}
+
+static JSBool
+PushOff(SprintStack *ss, ptrdiff_t off, JSOp op)
+{
+ uintN top;
+
+ if (!SprintEnsureBuffer(&ss->sprinter, PAREN_SLOP))
+ return JS_FALSE;
+
+ /* ss->top points to the next free slot; be paranoid about overflow. */
+ top = ss->top;
+ JS_ASSERT(top < StackDepth(ss->printer->script));
+ if (top >= StackDepth(ss->printer->script)) {
+ JS_ReportOutOfMemory(ss->sprinter.context);
+ return JS_FALSE;
+ }
+
+ /* The opcodes stack must contain real bytecodes that index js_CodeSpec. */
+ ss->offsets[top] = off;
+ ss->opcodes[top] = (op == JSOP_GETPROP2) ? JSOP_GETPROP
+ : (op == JSOP_GETELEM2) ? JSOP_GETELEM
+ : (jsbytecode) op;
+ ss->top = ++top;
+ AddParenSlop(ss);
+ return JS_TRUE;
+}
+
+static ptrdiff_t
+PopOffPrec(SprintStack *ss, uint8 prec)
+{
+ uintN top;
+ const JSCodeSpec *topcs;
+ ptrdiff_t off;
+
+ /* ss->top points to the next free slot; be paranoid about underflow. */
+ top = ss->top;
+ JS_ASSERT(top != 0);
+ if (top == 0)
+ return 0;
+
+ ss->top = --top;
+ off = GetOff(ss, top);
+ topcs = &js_CodeSpec[ss->opcodes[top]];
+ if (topcs->prec != 0 && topcs->prec < prec) {
+ ss->sprinter.offset = ss->offsets[top] = off - 2;
+ off = Sprint(&ss->sprinter, "(%s)", OFF2STR(&ss->sprinter, off));
+ } else {
+ ss->sprinter.offset = off;
+ }
+ return off;
+}
+
+static const char *
+PopStrPrec(SprintStack *ss, uint8 prec)
+{
+ ptrdiff_t off;
+
+ off = PopOffPrec(ss, prec);
+ return OFF2STR(&ss->sprinter, off);
+}
+
+static ptrdiff_t
+PopOff(SprintStack *ss, JSOp op)
+{
+ return PopOffPrec(ss, js_CodeSpec[op].prec);
+}
+
+static const char *
+PopStr(SprintStack *ss, JSOp op)
+{
+ return PopStrPrec(ss, js_CodeSpec[op].prec);
+}
+
+typedef struct TableEntry {
+ jsval key;
+ ptrdiff_t offset;
+ JSAtom *label;
+ jsint order; /* source order for stable tableswitch sort */
+} TableEntry;
+
+static JSBool
+CompareOffsets(void *arg, const void *v1, const void *v2, int *result)
+{
+ ptrdiff_t offset_diff;
+ const TableEntry *te1 = (const TableEntry *) v1,
+ *te2 = (const TableEntry *) v2;
+
+ offset_diff = te1->offset - te2->offset;
+ *result = (offset_diff == 0 ? te1->order - te2->order
+ : offset_diff < 0 ? -1
+ : 1);
+ return JS_TRUE;
+}
+
+static ptrdiff_t
+SprintDoubleValue(Sprinter *sp, jsval v, JSOp *opp)
+{
+ jsdouble d;
+ ptrdiff_t todo;
+ char *s, buf[DTOSTR_STANDARD_BUFFER_SIZE];
+
+ JS_ASSERT(JSVAL_IS_DOUBLE(v));
+ d = *JSVAL_TO_DOUBLE(v);
+ if (JSDOUBLE_IS_NEGZERO(d)) {
+ todo = SprintCString(sp, "-0");
+ *opp = JSOP_NEG;
+ } else if (!JSDOUBLE_IS_FINITE(d)) {
+ /* Don't use Infinity and NaN, they're mutable. */
+ todo = SprintCString(sp,
+ JSDOUBLE_IS_NaN(d)
+ ? "0 / 0"
+ : (d < 0)
+ ? "1 / -0"
+ : "1 / 0");
+ *opp = JSOP_DIV;
+ } else {
+ s = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, d);
+ if (!s) {
+ JS_ReportOutOfMemory(sp->context);
+ return -1;
+ }
+ JS_ASSERT(strcmp(s, js_Infinity_str) &&
+ (*s != '-' ||
+ strcmp(s + 1, js_Infinity_str)) &&
+ strcmp(s, js_NaN_str));
+ todo = Sprint(sp, s);
+ }
+ return todo;
+}
+
+static jsbytecode *
+Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop);
+
+static JSBool
+DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
+ jsbytecode *pc, ptrdiff_t switchLength,
+ ptrdiff_t defaultOffset, JSBool isCondSwitch)
+{
+ JSContext *cx;
+ JSPrinter *jp;
+ ptrdiff_t off, off2, diff, caseExprOff, todo;
+ char *lval, *rval;
+ uintN i;
+ jsval key;
+ JSString *str;
+
+ cx = ss->sprinter.context;
+ jp = ss->printer;
+
+ /* JSOP_CONDSWITCH doesn't pop, unlike JSOP_{LOOKUP,TABLE}SWITCH. */
+ off = isCondSwitch ? GetOff(ss, ss->top-1) : PopOff(ss, JSOP_NOP);
+ lval = OFF2STR(&ss->sprinter, off);
+
+ js_printf(jp, "\tswitch (%s) {\n", lval);
+
+ if (tableLength) {
+ diff = table[0].offset - defaultOffset;
+ if (diff > 0) {
+ jp->indent += 2;
+ js_printf(jp, "\t%s:\n", js_default_str);
+ jp->indent += 2;
+ if (!Decompile(ss, pc + defaultOffset, diff, JSOP_NOP))
+ return JS_FALSE;
+ jp->indent -= 4;
+ }
+
+ caseExprOff = isCondSwitch ? JSOP_CONDSWITCH_LENGTH : 0;
+
+ for (i = 0; i < tableLength; i++) {
+ off = table[i].offset;
+ off2 = (i + 1 < tableLength) ? table[i + 1].offset : switchLength;
+
+ key = table[i].key;
+ if (isCondSwitch) {
+ ptrdiff_t nextCaseExprOff;
+
+ /*
+ * key encodes the JSOP_CASE bytecode's offset from switchtop.
+ * The next case expression follows immediately, unless we are
+ * at the last case.
+ */
+ nextCaseExprOff = (ptrdiff_t)JSVAL_TO_INT(key);
+ nextCaseExprOff += js_CodeSpec[pc[nextCaseExprOff]].length;
+ jp->indent += 2;
+ if (!Decompile(ss, pc + caseExprOff,
+ nextCaseExprOff - caseExprOff, JSOP_NOP)) {
+ return JS_FALSE;
+ }
+ caseExprOff = nextCaseExprOff;
+
+ /* Balance the stack as if this JSOP_CASE matched. */
+ --ss->top;
+ } else {
+ /*
+ * key comes from an atom, not the decompiler, so we need to
+ * quote it if it's a string literal. But if table[i].label
+ * is non-null, key was constant-propagated and label is the
+ * name of the const we should show as the case label. We set
+ * key to undefined so this identifier is escaped, if required
+ * by non-ASCII characters, but not quoted, by QuoteString.
+ */
+ todo = -1;
+ if (table[i].label) {
+ str = ATOM_TO_STRING(table[i].label);
+ key = JSVAL_VOID;
+ } else if (JSVAL_IS_DOUBLE(key)) {
+ JSOp junk;
+
+ todo = SprintDoubleValue(&ss->sprinter, key, &junk);
+ str = NULL;
+ } else {
+ str = js_ValueToString(cx, key);
+ if (!str)
+ return JS_FALSE;
+ }
+ if (todo >= 0) {
+ rval = OFF2STR(&ss->sprinter, todo);
+ } else {
+ rval = QuoteString(&ss->sprinter, str, (jschar)
+ (JSVAL_IS_STRING(key) ? '"' : 0));
+ if (!rval)
+ return JS_FALSE;
+ }
+ RETRACT(&ss->sprinter, rval);
+ jp->indent += 2;
+ js_printf(jp, "\tcase %s:\n", rval);
+ }
+
+ jp->indent += 2;
+ if (off <= defaultOffset && defaultOffset < off2) {
+ diff = defaultOffset - off;
+ if (diff != 0) {
+ if (!Decompile(ss, pc + off, diff, JSOP_NOP))
+ return JS_FALSE;
+ off = defaultOffset;
+ }
+ jp->indent -= 2;
+ js_printf(jp, "\t%s:\n", js_default_str);
+ jp->indent += 2;
+ }
+ if (!Decompile(ss, pc + off, off2 - off, JSOP_NOP))
+ return JS_FALSE;
+ jp->indent -= 4;
+
+ /* Re-balance as if last JSOP_CASE or JSOP_DEFAULT mismatched. */
+ if (isCondSwitch)
+ ++ss->top;
+ }
+ }
+
+ if (defaultOffset == switchLength) {
+ jp->indent += 2;
+ js_printf(jp, "\t%s:;\n", js_default_str);
+ jp->indent -= 2;
+ }
+ js_printf(jp, "\t}\n");
+
+ /* By the end of a JSOP_CONDSWITCH, the discriminant has been popped. */
+ if (isCondSwitch)
+ --ss->top;
+ return JS_TRUE;
+}
+
+#define LOCAL_ASSERT_CUSTOM(expr, BAD_EXIT) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT(expr); \
+ if (!(expr)) { BAD_EXIT; } \
+ JS_END_MACRO
+
+#define LOCAL_ASSERT_RV(expr, rv) \
+ LOCAL_ASSERT_CUSTOM(expr, return (rv))
+
+static JSAtom *
+GetArgOrVarAtom(JSPrinter *jp, uintN slot)
+{
+ JSAtom *name;
+
+ LOCAL_ASSERT_RV(jp->fun, NULL);
+ LOCAL_ASSERT_RV(slot < (uintN) JS_GET_LOCAL_NAME_COUNT(jp->fun), NULL);
+ name = JS_LOCAL_NAME_TO_ATOM(jp->localNames[slot]);
+#if !JS_HAS_DESTRUCTURING
+ LOCAL_ASSERT_RV(name, NULL);
+#endif
+ return name;
+}
+
+const char *
+GetLocal(SprintStack *ss, jsint i)
+{
+ ptrdiff_t off;
+ JSContext *cx;
+ JSScript *script;
+ jsatomid j, n;
+ JSAtom *atom;
+ JSObject *obj;
+ jsint depth, count;
+ JSScopeProperty *sprop;
+ const char *rval;
+
+#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, "")
+
+ off = ss->offsets[i];
+ if (off >= 0)
+ return OFF2STR(&ss->sprinter, off);
+
+ /*
+ * We must be called from js_DecompileValueGenerator (via Decompile) when
+ * dereferencing a local that's undefined or null. Search script->objects
+ * for the block containing this local by its stack index, i.
+ */
+ cx = ss->sprinter.context;
+ script = ss->printer->script;
+ LOCAL_ASSERT(script->objectsOffset != 0);
+ for (j = 0, n = JS_SCRIPT_OBJECTS(script)->length; ; j++) {
+ LOCAL_ASSERT(j < n);
+ JS_GET_SCRIPT_OBJECT(script, j, obj);
+ if (OBJ_GET_CLASS(cx, obj) == &js_BlockClass) {
+ depth = OBJ_BLOCK_DEPTH(cx, obj);
+ count = OBJ_BLOCK_COUNT(cx, obj);
+ if ((jsuint)(i - depth) < (jsuint)count)
+ break;
+ }
+ }
+
+ i -= depth;
+ for (sprop = OBJ_SCOPE(obj)->lastProp; sprop; sprop = sprop->parent) {
+ if (sprop->shortid == i)
+ break;
+ }
+
+ LOCAL_ASSERT(sprop && JSID_IS_ATOM(sprop->id));
+ atom = JSID_TO_ATOM(sprop->id);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ return rval;
+
+#undef LOCAL_ASSERT
+}
+
+static JSBool
+IsVarSlot(JSPrinter *jp, jsbytecode *pc, jsint *indexp)
+{
+ uintN slot;
+
+ slot = GET_SLOTNO(pc);
+ if (slot < jp->script->nfixed) {
+ /* The slot refers to a variable with name stored in jp->localNames. */
+ *indexp = jp->fun->nargs + slot;
+ return JS_TRUE;
+ }
+
+ /* We have a local which index is relative to the stack base. */
+ slot -= jp->script->nfixed;
+ JS_ASSERT(slot < StackDepth(jp->script));
+ *indexp = slot;
+ return JS_FALSE;
+}
+
+#if JS_HAS_DESTRUCTURING
+
+#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, NULL)
+#define LOAD_OP_DATA(pc) (oplen = (cs = &js_CodeSpec[op=(JSOp)*pc])->length)
+
+static jsbytecode *
+DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc);
+
+static jsbytecode *
+DecompileDestructuringLHS(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
+ JSBool *hole)
+{
+ JSContext *cx;
+ JSPrinter *jp;
+ JSOp op;
+ const JSCodeSpec *cs;
+ uintN oplen;
+ jsint i;
+ const char *lval, *xval;
+ ptrdiff_t todo;
+ JSAtom *atom;
+
+ *hole = JS_FALSE;
+ cx = ss->sprinter.context;
+ jp = ss->printer;
+ LOAD_OP_DATA(pc);
+
+ switch (op) {
+ case JSOP_POP:
+ *hole = JS_TRUE;
+ todo = SprintPut(&ss->sprinter, ", ", 2);
+ break;
+
+ case JSOP_DUP:
+ pc = DecompileDestructuring(ss, pc, endpc);
+ if (!pc)
+ return NULL;
+ if (pc == endpc)
+ return pc;
+ LOAD_OP_DATA(pc);
+ lval = PopStr(ss, JSOP_NOP);
+ todo = SprintCString(&ss->sprinter, lval);
+ if (op == JSOP_POPN)
+ return pc;
+ LOCAL_ASSERT(*pc == JSOP_POP);
+ break;
+
+ case JSOP_SETARG:
+ case JSOP_SETGVAR:
+ case JSOP_SETLOCAL:
+ LOCAL_ASSERT(pc[oplen] == JSOP_POP || pc[oplen] == JSOP_POPN);
+ /* FALL THROUGH */
+
+ case JSOP_SETLOCALPOP:
+ atom = NULL;
+ lval = NULL;
+ if (op == JSOP_SETARG) {
+ atom = GetArgOrVarAtom(jp, GET_SLOTNO(pc));
+ LOCAL_ASSERT(atom);
+ } else if (op == JSOP_SETGVAR) {
+ GET_ATOM_FROM_BYTECODE(jp->script, pc, 0, atom);
+ } else if (IsVarSlot(jp, pc, &i)) {
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ } else {
+ lval = GetLocal(ss, i);
+ }
+ if (atom)
+ lval = js_AtomToPrintableString(cx, atom);
+ LOCAL_ASSERT(lval);
+ todo = SprintCString(&ss->sprinter, lval);
+ if (op != JSOP_SETLOCALPOP) {
+ pc += oplen;
+ if (pc == endpc)
+ return pc;
+ LOAD_OP_DATA(pc);
+ if (op == JSOP_POPN)
+ return pc;
+ LOCAL_ASSERT(op == JSOP_POP);
+ }
+ break;
+
+ default:
+ /*
+ * We may need to auto-parenthesize the left-most value decompiled
+ * here, so add back PAREN_SLOP temporarily. Then decompile until the
+ * opcode that would reduce the stack depth to (ss->top-1), which we
+ * pass to Decompile encoded as -(ss->top-1) - 1 or just -ss->top for
+ * the nb parameter.
+ */
+ todo = ss->sprinter.offset;
+ ss->sprinter.offset = todo + PAREN_SLOP;
+ pc = Decompile(ss, pc, -((intN)ss->top), JSOP_NOP);
+ if (!pc)
+ return NULL;
+ if (pc == endpc)
+ return pc;
+ LOAD_OP_DATA(pc);
+ LOCAL_ASSERT(op == JSOP_ENUMELEM || op == JSOP_ENUMCONSTELEM);
+ xval = PopStr(ss, JSOP_NOP);
+ lval = PopStr(ss, JSOP_GETPROP);
+ ss->sprinter.offset = todo;
+ if (*lval == '\0') {
+ /* lval is from JSOP_BINDNAME, so just print xval. */
+ todo = SprintCString(&ss->sprinter, xval);
+ } else if (*xval == '\0') {
+ /* xval is from JSOP_SETCALL or JSOP_BINDXMLNAME, print lval. */
+ todo = SprintCString(&ss->sprinter, lval);
+ } else {
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(ss->opcodes[ss->top+1]) == JOF_XMLNAME)
+ ? "%s.%s"
+ : "%s[%s]",
+ lval, xval);
+ }
+ break;
+ }
+
+ if (todo < 0)
+ return NULL;
+
+ LOCAL_ASSERT(pc < endpc);
+ pc += oplen;
+ return pc;
+}
+
+/*
+ * Starting with a SRC_DESTRUCT-annotated JSOP_DUP, decompile a destructuring
+ * left-hand side object or array initialiser, including nested destructuring
+ * initialisers. On successful return, the decompilation will be pushed on ss
+ * and the return value will point to the POP or GROUP bytecode following the
+ * destructuring expression.
+ *
+ * At any point, if pc is equal to endpc and would otherwise advance, we stop
+ * immediately and return endpc.
+ */
+static jsbytecode *
+DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
+{
+ ptrdiff_t head;
+ JSContext *cx;
+ JSPrinter *jp;
+ JSOp op, saveop;
+ const JSCodeSpec *cs;
+ uintN oplen;
+ jsint i, lasti;
+ jsdouble d;
+ const char *lval;
+ JSAtom *atom;
+ jssrcnote *sn;
+ JSString *str;
+ JSBool hole;
+
+ LOCAL_ASSERT(*pc == JSOP_DUP);
+ pc += JSOP_DUP_LENGTH;
+
+ /*
+ * Set head so we can rewrite '[' to '{' as needed. Back up PAREN_SLOP
+ * chars so the destructuring decompilation accumulates contiguously in
+ * ss->sprinter starting with "[".
+ */
+ head = SprintPut(&ss->sprinter, "[", 1);
+ if (head < 0 || !PushOff(ss, head, JSOP_NOP))
+ return NULL;
+ ss->sprinter.offset -= PAREN_SLOP;
+ LOCAL_ASSERT(head == ss->sprinter.offset - 1);
+ LOCAL_ASSERT(*OFF2STR(&ss->sprinter, head) == '[');
+
+ cx = ss->sprinter.context;
+ jp = ss->printer;
+ lasti = -1;
+
+ while (pc < endpc) {
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ ptrdiff_t nameoff = -1;
+#endif
+
+ LOAD_OP_DATA(pc);
+ saveop = op;
+
+ switch (op) {
+ case JSOP_POP:
+ pc += oplen;
+ goto out;
+
+ /* Handle the optimized number-pushing opcodes. */
+ case JSOP_ZERO: d = i = 0; goto do_getelem;
+ case JSOP_ONE: d = i = 1; goto do_getelem;
+ case JSOP_UINT16: d = i = GET_UINT16(pc); goto do_getelem;
+ case JSOP_UINT24: d = i = GET_UINT24(pc); goto do_getelem;
+ case JSOP_INT8: d = i = GET_INT8(pc); goto do_getelem;
+ case JSOP_INT32: d = i = GET_INT32(pc); goto do_getelem;
+
+ case JSOP_DOUBLE:
+ GET_ATOM_FROM_BYTECODE(jp->script, pc, 0, atom);
+ d = *ATOM_TO_DOUBLE(atom);
+ LOCAL_ASSERT(JSDOUBLE_IS_FINITE(d) && !JSDOUBLE_IS_NEGZERO(d));
+ i = (jsint)d;
+
+ do_getelem:
+ sn = js_GetSrcNote(jp->script, pc);
+ pc += oplen;
+ if (pc == endpc)
+ return pc;
+ LOAD_OP_DATA(pc);
+ LOCAL_ASSERT(op == JSOP_GETELEM);
+
+ /* Distinguish object from array by opcode or source note. */
+ if (sn && SN_TYPE(sn) == SRC_INITPROP) {
+ *OFF2STR(&ss->sprinter, head) = '{';
+ if (Sprint(&ss->sprinter, "%g: ", d) < 0)
+ return NULL;
+ } else {
+ /* Sanity check for the gnarly control flow above. */
+ LOCAL_ASSERT(i == d);
+
+ /* Fill in any holes (holes at the end don't matter). */
+ while (++lasti < i) {
+ if (SprintPut(&ss->sprinter, ", ", 2) < 0)
+ return NULL;
+ }
+ }
+ break;
+
+ case JSOP_LENGTH:
+ atom = cx->runtime->atomState.lengthAtom;
+ goto do_destructure_atom;
+
+ case JSOP_CALLPROP:
+ case JSOP_GETPROP:
+ GET_ATOM_FROM_BYTECODE(jp->script, pc, 0, atom);
+ do_destructure_atom:
+ *OFF2STR(&ss->sprinter, head) = '{';
+ str = ATOM_TO_STRING(atom);
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ nameoff = ss->sprinter.offset;
+#endif
+ if (!QuoteString(&ss->sprinter, str,
+ js_IsIdentifier(str) ? 0 : (jschar)'\'')) {
+ return NULL;
+ }
+ if (SprintPut(&ss->sprinter, ": ", 2) < 0)
+ return NULL;
+ break;
+
+ default:
+ LOCAL_ASSERT(0);
+ }
+
+ pc += oplen;
+ if (pc == endpc)
+ return pc;
+
+ /*
+ * Decompile the left-hand side expression whose bytecode starts at pc
+ * and continues for a bounded number of bytecodes or stack operations
+ * (and which in any event stops before endpc).
+ */
+ pc = DecompileDestructuringLHS(ss, pc, endpc, &hole);
+ if (!pc)
+ return NULL;
+
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ if (nameoff >= 0) {
+ ptrdiff_t offset, initlen;
+
+ offset = ss->sprinter.offset;
+ LOCAL_ASSERT(*OFF2STR(&ss->sprinter, offset) == '\0');
+ initlen = offset - nameoff;
+ LOCAL_ASSERT(initlen >= 4);
+
+ /* Early check to rule out odd "name: lval" length. */
+ if (((size_t)initlen & 1) == 0) {
+ size_t namelen;
+ const char *name;
+
+ /*
+ * Even "name: lval" string length: check for "x: x" and the
+ * like, and apply the shorthand if we can.
+ */
+ namelen = (size_t)(initlen - 2) >> 1;
+ name = OFF2STR(&ss->sprinter, nameoff);
+ if (!strncmp(name + namelen, ": ", 2) &&
+ !strncmp(name, name + namelen + 2, namelen)) {
+ offset -= namelen + 2;
+ *OFF2STR(&ss->sprinter, offset) = '\0';
+ ss->sprinter.offset = offset;
+ }
+ }
+ }
+#endif
+
+ if (pc == endpc || *pc != JSOP_DUP)
+ break;
+
+ /*
+ * Check for SRC_DESTRUCT on this JSOP_DUP, which would mean another
+ * destructuring initialiser abuts this one, and we should stop. This
+ * happens with source of the form '[a] = [b] = c'.
+ */
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_DESTRUCT)
+ break;
+
+ if (!hole && SprintPut(&ss->sprinter, ", ", 2) < 0)
+ return NULL;
+
+ pc += JSOP_DUP_LENGTH;
+ }
+
+out:
+ lval = OFF2STR(&ss->sprinter, head);
+ if (SprintPut(&ss->sprinter, (*lval == '[') ? "]" : "}", 1) < 0)
+ return NULL;
+ return pc;
+}
+
+static jsbytecode *
+DecompileGroupAssignment(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
+ jssrcnote *sn, ptrdiff_t *todop)
+{
+ JSOp op;
+ const JSCodeSpec *cs;
+ uintN oplen, start, end, i;
+ ptrdiff_t todo;
+ JSBool hole;
+ const char *rval;
+
+ LOAD_OP_DATA(pc);
+ LOCAL_ASSERT(op == JSOP_PUSH || op == JSOP_GETLOCAL);
+
+ todo = Sprint(&ss->sprinter, "%s[", VarPrefix(sn));
+ if (todo < 0 || !PushOff(ss, todo, JSOP_NOP))
+ return NULL;
+ ss->sprinter.offset -= PAREN_SLOP;
+
+ for (;;) {
+ pc += oplen;
+ if (pc == endpc)
+ return pc;
+ pc = DecompileDestructuringLHS(ss, pc, endpc, &hole);
+ if (!pc)
+ return NULL;
+ if (pc == endpc)
+ return pc;
+ LOAD_OP_DATA(pc);
+ if (op != JSOP_PUSH && op != JSOP_GETLOCAL)
+ break;
+ if (!hole && SprintPut(&ss->sprinter, ", ", 2) < 0)
+ return NULL;
+ }
+
+ LOCAL_ASSERT(op == JSOP_POPN);
+ if (SprintPut(&ss->sprinter, "] = [", 5) < 0)
+ return NULL;
+
+ end = ss->top - 1;
+ start = end - GET_UINT16(pc);
+ for (i = start; i < end; i++) {
+ rval = GetStr(ss, i);
+ if (Sprint(&ss->sprinter,
+ (i == start) ? "%s" : ", %s",
+ (i == end - 1 && *rval == '\0') ? ", " : rval) < 0) {
+ return NULL;
+ }
+ }
+
+ if (SprintPut(&ss->sprinter, "]", 1) < 0)
+ return NULL;
+ ss->sprinter.offset = ss->offsets[i];
+ ss->top = start;
+ *todop = todo;
+ return pc;
+}
+
+#undef LOCAL_ASSERT
+#undef LOAD_OP_DATA
+
+#endif /* JS_HAS_DESTRUCTURING */
+
+static JSBool
+InitSprintStack(JSContext *cx, SprintStack *ss, JSPrinter *jp, uintN depth)
+{
+ size_t offsetsz, opcodesz;
+ void *space;
+
+ INIT_SPRINTER(cx, &ss->sprinter, &cx->tempPool, PAREN_SLOP);
+
+ /* Allocate the parallel (to avoid padding) offset and opcode stacks. */
+ offsetsz = depth * sizeof(ptrdiff_t);
+ opcodesz = depth * sizeof(jsbytecode);
+ JS_ARENA_ALLOCATE(space, &cx->tempPool, offsetsz + opcodesz);
+ if (!space) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ ss->offsets = (ptrdiff_t *) space;
+ ss->opcodes = (jsbytecode *) ((char *)space + offsetsz);
+
+ ss->top = ss->inArrayInit = 0;
+ ss->inGenExp = JS_FALSE;
+ ss->printer = jp;
+ return JS_TRUE;
+}
+
+/*
+ * If nb is non-negative, decompile nb bytecodes starting at pc. Otherwise
+ * the decompiler starts at pc and continues until it reaches an opcode for
+ * which decompiling would result in the stack depth equaling -(nb + 1).
+ *
+ * The nextop parameter is either JSOP_NOP or the "next" opcode in order of
+ * abstract interpretation (not necessarily physically next in a bytecode
+ * vector). So nextop is JSOP_POP for the last operand in a comma expression,
+ * or JSOP_AND for the right operand of &&.
+ */
+static jsbytecode *
+Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
+{
+ JSContext *cx;
+ JSPrinter *jp, *jp2;
+ jsbytecode *startpc, *endpc, *pc2, *done;
+ ptrdiff_t tail, todo, len, oplen, cond, next;
+ JSOp op, lastop, saveop;
+ const JSCodeSpec *cs;
+ jssrcnote *sn, *sn2;
+ const char *lval, *rval, *xval, *fmt, *token;
+ jsint i, argc;
+ char **argv;
+ JSAtom *atom;
+ JSObject *obj;
+ JSFunction *fun;
+ JSString *str;
+ JSBool ok;
+#if JS_HAS_XML_SUPPORT
+ JSBool foreach, inXML, quoteAttr;
+#else
+#define inXML JS_FALSE
+#endif
+ jsval val;
+
+ static const char exception_cookie[] = "/*EXCEPTION*/";
+ static const char retsub_pc_cookie[] = "/*RETSUB_PC*/";
+ static const char iter_cookie[] = "/*ITER*/";
+ static const char forelem_cookie[] = "/*FORELEM*/";
+ static const char with_cookie[] = "/*WITH*/";
+ static const char dot_format[] = "%s.%s";
+ static const char index_format[] = "%s[%s]";
+ static const char predot_format[] = "%s%s.%s";
+ static const char postdot_format[] = "%s.%s%s";
+ static const char preindex_format[] = "%s%s[%s]";
+ static const char postindex_format[] = "%s[%s]%s";
+ static const char ss_format[] = "%s%s";
+ static const char sss_format[] = "%s%s%s";
+
+ /* Argument and variables decompilation uses the following to share code. */
+ JS_STATIC_ASSERT(ARGNO_LEN == SLOTNO_LEN);
+
+/*
+ * Local macros
+ */
+#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, NULL)
+#define DECOMPILE_CODE(pc,nb) if (!Decompile(ss, pc, nb, JSOP_NOP)) return NULL
+#define NEXT_OP(pc) (((pc) + (len) == endpc) ? nextop : pc[len])
+#define TOP_STR() GetStr(ss, ss->top - 1)
+#define POP_STR() PopStr(ss, op)
+#define POP_STR_PREC(prec) PopStrPrec(ss, prec)
+
+/*
+ * Pop a condition expression for if/for/while. JSOP_IFEQ's precedence forces
+ * extra parens around assignment, which avoids a strict-mode warning.
+ */
+#define POP_COND_STR() \
+ PopStr(ss, (js_CodeSpec[ss->opcodes[ss->top - 1]].format & JOF_SET) \
+ ? JSOP_IFEQ \
+ : JSOP_NOP)
+
+/*
+ * Callers know that ATOM_IS_STRING(atom), and we leave it to the optimizer to
+ * common ATOM_TO_STRING(atom) here and near the call sites.
+ */
+#define ATOM_IS_IDENTIFIER(atom) js_IsIdentifier(ATOM_TO_STRING(atom))
+#define ATOM_IS_KEYWORD(atom) \
+ (js_CheckKeyword(JSSTRING_CHARS(ATOM_TO_STRING(atom)), \
+ JSSTRING_LENGTH(ATOM_TO_STRING(atom))) != TOK_EOF)
+
+/*
+ * Given an atom already fetched from jp->script's atom map, quote/escape its
+ * string appropriately into rval, and select fmt from the quoted and unquoted
+ * alternatives.
+ */
+#define GET_QUOTE_AND_FMT(qfmt, ufmt, rval) \
+ JS_BEGIN_MACRO \
+ jschar quote_; \
+ if (!ATOM_IS_IDENTIFIER(atom)) { \
+ quote_ = '\''; \
+ fmt = qfmt; \
+ } else { \
+ quote_ = 0; \
+ fmt = ufmt; \
+ } \
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), quote_); \
+ if (!rval) \
+ return NULL; \
+ JS_END_MACRO
+
+#define LOAD_ATOM(PCOFF) \
+ GET_ATOM_FROM_BYTECODE(jp->script, pc, PCOFF, atom)
+
+#define LOAD_OBJECT(PCOFF) \
+ GET_OBJECT_FROM_BYTECODE(jp->script, pc, PCOFF, obj)
+
+#define LOAD_FUNCTION(PCOFF) \
+ GET_FUNCTION_FROM_BYTECODE(jp->script, pc, PCOFF, fun)
+
+#define LOAD_REGEXP(PCOFF) \
+ GET_REGEXP_FROM_BYTECODE(jp->script, pc, PCOFF, obj)
+
+#define GET_SOURCE_NOTE_ATOM(sn, atom) \
+ JS_BEGIN_MACRO \
+ jsatomid atomIndex_ = (jsatomid) js_GetSrcNoteOffset((sn), 0); \
+ \
+ LOCAL_ASSERT(atomIndex_ < jp->script->atomMap.length); \
+ (atom) = jp->script->atomMap.vector[atomIndex_]; \
+ JS_END_MACRO
+
+/*
+ * Get atom from jp->script's atom map, quote/escape its string appropriately
+ * into rval, and select fmt from the quoted and unquoted alternatives.
+ */
+#define GET_ATOM_QUOTE_AND_FMT(qfmt, ufmt, rval) \
+ JS_BEGIN_MACRO \
+ LOAD_ATOM(0); \
+ GET_QUOTE_AND_FMT(qfmt, ufmt, rval); \
+ JS_END_MACRO
+
+/*
+ * Per spec, new x(y).z means (new x(y))).z. For example new (x(y).z) must
+ * decompile with the constructor parenthesized, but new x.z should not. The
+ * normal rules give x(y).z and x.z identical precedence: both are produced by
+ * JSOP_GETPROP.
+ *
+ * Therefore, we need to know in case JSOP_NEW whether the constructor
+ * expression contains any unparenthesized function calls. So when building a
+ * MemberExpression or CallExpression, we set ss->opcodes[n] to JSOP_CALL if
+ * this is true. x(y).z gets JSOP_CALL, not JSOP_GETPROP.
+ */
+#define PROPAGATE_CALLNESS() \
+ JS_BEGIN_MACRO \
+ if (ss->opcodes[ss->top - 1] == JSOP_CALL) \
+ saveop = JSOP_CALL; \
+ JS_END_MACRO
+
+ cx = ss->sprinter.context;
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ jp = ss->printer;
+ startpc = pc;
+ endpc = (nb < 0) ? jp->script->code + jp->script->length : pc + nb;
+ tail = -1;
+ todo = -2; /* NB: different from Sprint() error return. */
+ saveop = JSOP_NOP;
+ sn = NULL;
+ rval = NULL;
+#if JS_HAS_XML_SUPPORT
+ foreach = inXML = quoteAttr = JS_FALSE;
+#endif
+
+ while (nb < 0 || pc < endpc) {
+ /*
+ * Move saveop to lastop so prefixed bytecodes can take special action
+ * while sharing maximal code. Set op and saveop to the new bytecode,
+ * use op in POP_STR to trigger automatic parenthesization, but push
+ * saveop at the bottom of the loop if this op pushes. Thus op may be
+ * set to nop or otherwise mutated to suppress auto-parens.
+ */
+ lastop = saveop;
+ op = (JSOp) *pc;
+ cs = &js_CodeSpec[op];
+ if (cs->format & JOF_INDEXBASE) {
+ /*
+ * The decompiler uses js_GetIndexFromBytecode to get atoms and
+ * objects and ignores these suffix/prefix bytecodes, thus
+ * simplifying code that must process JSOP_GETTER/JSOP_SETTER
+ * prefixes.
+ */
+ pc += cs->length;
+ if (pc >= endpc)
+ break;
+ op = (JSOp) *pc;
+ cs = &js_CodeSpec[op];
+ }
+ saveop = op;
+ len = oplen = cs->length;
+
+ if (nb < 0 && -(nb + 1) == (intN)ss->top - cs->nuses + cs->ndefs)
+ return pc;
+
+ /*
+ * Save source literal associated with JS now before the following
+ * rewrite changes op. See bug 380197.
+ */
+ token = CodeToken[op];
+
+ if (pc + oplen == jp->dvgfence) {
+ JSStackFrame *fp;
+ uint32 format, mode, type;
+
+ /*
+ * Rewrite non-get ops to their "get" format if the error is in
+ * the bytecode at pc, so we don't decompile more than the error
+ * expression.
+ */
+ for (fp = cx->fp; fp && !fp->script; fp = fp->down)
+ continue;
+ format = cs->format;
+ if (((fp && fp->regs && pc == fp->regs->pc) ||
+ (pc == startpc && cs->nuses != 0)) &&
+ format & (JOF_SET|JOF_DEL|JOF_INCDEC|JOF_FOR|JOF_VARPROP)) {
+ mode = JOF_MODE(format);
+ if (mode == JOF_NAME) {
+ /*
+ * JOF_NAME does not imply JOF_ATOM, so we must check for
+ * the QARG and QVAR format types, and translate those to
+ * JSOP_GETARG or JSOP_GETLOCAL appropriately, instead of
+ * to JSOP_NAME.
+ */
+ type = JOF_TYPE(format);
+ op = (type == JOF_QARG)
+ ? JSOP_GETARG
+ : (type == JOF_LOCAL)
+ ? JSOP_GETLOCAL
+ : JSOP_NAME;
+
+ i = cs->nuses - js_CodeSpec[op].nuses;
+ while (--i >= 0)
+ PopOff(ss, JSOP_NOP);
+ } else {
+ /*
+ * We must replace the faulting pc's bytecode with a
+ * corresponding JSOP_GET* code. For JSOP_SET{PROP,ELEM},
+ * we must use the "2nd" form of JSOP_GET{PROP,ELEM}, to
+ * throw away the assignment op's right-hand operand and
+ * decompile it as if it were a GET of its left-hand
+ * operand.
+ */
+ if (mode == JOF_PROP) {
+ op = (JSOp) ((format & JOF_SET)
+ ? JSOP_GETPROP2
+ : JSOP_GETPROP);
+ } else if (mode == JOF_ELEM) {
+ op = (JSOp) ((format & JOF_SET)
+ ? JSOP_GETELEM2
+ : JSOP_GETELEM);
+ } else {
+ /*
+ * Unknown mode (including mode 0) means that op is
+ * uncategorized for our purposes, so we must write
+ * per-op special case code here.
+ */
+ switch (op) {
+ case JSOP_ENUMELEM:
+ case JSOP_ENUMCONSTELEM:
+ op = JSOP_GETELEM;
+ break;
+#if JS_HAS_LVALUE_RETURN
+ case JSOP_SETCALL:
+ op = JSOP_CALL;
+ break;
+#endif
+ case JSOP_GETTHISPROP:
+ /*
+ * NB: JSOP_GETTHISPROP can't fail due to |this|
+ * being null or undefined at runtime (beware that
+ * this may change for ES4). Therefore any error
+ * resulting from this op must be due to the value
+ * of the property accessed via |this|, so do not
+ * rewrite op to JSOP_THIS.
+ *
+ * The next two cases should not change op if
+ * js_DecompileValueGenerator was called from the
+ * the property getter. They should rewrite only
+ * if the base object in the arg/var/local is null
+ * or undefined. FIXME: bug 431569.
+ */
+ break;
+ case JSOP_GETARGPROP:
+ op = JSOP_GETARG;
+ break;
+ case JSOP_GETLOCALPROP:
+ op = JSOP_GETLOCAL;
+ break;
+ default:
+ LOCAL_ASSERT(0);
+ }
+ }
+ }
+ }
+
+ saveop = op;
+ if (op >= JSOP_LIMIT) {
+ switch (op) {
+ case JSOP_GETPROP2:
+ saveop = JSOP_GETPROP;
+ break;
+ case JSOP_GETELEM2:
+ saveop = JSOP_GETELEM;
+ break;
+ default:;
+ }
+ }
+ LOCAL_ASSERT(js_CodeSpec[saveop].length == oplen ||
+ JOF_TYPE(format) == JOF_SLOTATOM);
+
+ jp->dvgfence = NULL;
+ }
+
+ if (token) {
+ switch (cs->nuses) {
+ case 2:
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
+ /*
+ * Avoid over-parenthesizing y in x op= y based on its
+ * expansion: x = x op y (replace y by z = w to see the
+ * problem).
+ */
+ op = (JSOp) pc[oplen];
+ rval = POP_STR();
+ lval = POP_STR();
+ /* Print only the right operand of the assignment-op. */
+ todo = SprintCString(&ss->sprinter, rval);
+ op = saveop;
+ } else if (!inXML) {
+ rval = POP_STR_PREC(cs->prec + !!(cs->format & JOF_LEFTASSOC));
+ lval = POP_STR_PREC(cs->prec + !(cs->format & JOF_LEFTASSOC));
+ todo = Sprint(&ss->sprinter, "%s %s %s",
+ lval, token, rval);
+ } else {
+ /* In XML, just concatenate the two operands. */
+ LOCAL_ASSERT(op == JSOP_ADD);
+ rval = POP_STR();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, ss_format, lval, rval);
+ }
+ break;
+
+ case 1:
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, ss_format, token, rval);
+ break;
+
+ case 0:
+ todo = SprintCString(&ss->sprinter, token);
+ break;
+
+ default:
+ todo = -2;
+ break;
+ }
+ } else {
+ switch (op) {
+ case JSOP_NOP:
+ /*
+ * Check for a do-while loop, a for-loop with an empty
+ * initializer part, a labeled statement, a function
+ * definition, or try/finally.
+ */
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = -2;
+ switch (sn ? SN_TYPE(sn) : SRC_NULL) {
+ case SRC_WHILE:
+ ++pc;
+ tail = js_GetSrcNoteOffset(sn, 0) - 1;
+ LOCAL_ASSERT(pc[tail] == JSOP_IFNE ||
+ pc[tail] == JSOP_IFNEX);
+ js_printf(jp, "\tdo {\n");
+ jp->indent += 4;
+ DECOMPILE_CODE(pc, tail);
+ jp->indent -= 4;
+ js_printf(jp, "\t} while (%s);\n", POP_COND_STR());
+ pc += tail;
+ len = js_CodeSpec[*pc].length;
+ todo = -2;
+ break;
+
+ case SRC_FOR:
+ rval = "";
+
+ do_forloop:
+ JS_ASSERT(SN_TYPE(sn) == SRC_FOR);
+
+ /* Skip the JSOP_NOP or JSOP_POP bytecode. */
+ pc += JSOP_NOP_LENGTH;
+
+ /* Get the cond, next, and loop-closing tail offsets. */
+ cond = js_GetSrcNoteOffset(sn, 0);
+ next = js_GetSrcNoteOffset(sn, 1);
+ tail = js_GetSrcNoteOffset(sn, 2);
+
+ /*
+ * If this loop has a condition, then pc points at a goto
+ * targeting the condition.
+ */
+ pc2 = pc;
+ if (cond != tail) {
+ LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
+ pc2 += (*pc == JSOP_GOTO) ? JSOP_GOTO_LENGTH : JSOP_GOTOX_LENGTH;
+ }
+ LOCAL_ASSERT(tail + GetJumpOffset(pc+tail, pc+tail) == pc2 - pc);
+
+ /* Print the keyword and the possibly empty init-part. */
+ js_printf(jp, "\tfor (%s;", rval);
+
+ if (cond != tail) {
+ /* Decompile the loop condition. */
+ DECOMPILE_CODE(pc + cond, tail - cond);
+ js_printf(jp, " %s", POP_STR());
+ }
+
+ /* Need a semicolon whether or not there was a cond. */
+ js_puts(jp, ";");
+
+ if (next != cond) {
+ /*
+ * Decompile the loop updater. It may end in a JSOP_POP
+ * that we skip; or in a JSOP_POPN that we do not skip,
+ * followed by a JSOP_NOP (skipped as if it's a POP).
+ * We cope with the difference between these two cases
+ * by checking for stack imbalance and popping if there
+ * is an rval.
+ */
+ uintN saveTop = ss->top;
+
+ DECOMPILE_CODE(pc + next, cond - next - JSOP_POP_LENGTH);
+ LOCAL_ASSERT(ss->top - saveTop <= 1U);
+ rval = (ss->top == saveTop)
+ ? ss->sprinter.base + ss->sprinter.offset
+ : POP_STR();
+ js_printf(jp, " %s", rval);
+ }
+
+ /* Do the loop body. */
+ js_printf(jp, ") {\n");
+ jp->indent += 4;
+ next -= pc2 - pc;
+ DECOMPILE_CODE(pc2, next);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+
+ /* Set len so pc skips over the entire loop. */
+ len = tail + js_CodeSpec[pc[tail]].length;
+ break;
+
+ case SRC_LABEL:
+ GET_SOURCE_NOTE_ATOM(sn, atom);
+ jp->indent -= 4;
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ js_printf(jp, "\t%s:\n", rval);
+ jp->indent += 4;
+ break;
+
+ case SRC_LABELBRACE:
+ GET_SOURCE_NOTE_ATOM(sn, atom);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ js_printf(jp, "\t%s: {\n", rval);
+ jp->indent += 4;
+ break;
+
+ case SRC_ENDBRACE:
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ break;
+
+ case SRC_FUNCDEF:
+ JS_GET_SCRIPT_FUNCTION(jp->script,
+ js_GetSrcNoteOffset(sn, 0),
+ fun);
+ do_function:
+ js_puts(jp, "\n");
+ jp2 = JS_NEW_PRINTER(cx, "nested_function", fun,
+ jp->indent, jp->pretty);
+ if (!jp2)
+ return NULL;
+ ok = js_DecompileFunction(jp2);
+ if (ok && jp2->sprinter.base)
+ js_puts(jp, jp2->sprinter.base);
+ js_DestroyPrinter(jp2);
+ if (!ok)
+ return NULL;
+ js_puts(jp, "\n\n");
+ break;
+
+ case SRC_BRACE:
+ js_printf(jp, "\t{\n");
+ jp->indent += 4;
+ len = js_GetSrcNoteOffset(sn, 0);
+ DECOMPILE_CODE(pc + oplen, len - oplen);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ break;
+
+ default:;
+ }
+ break;
+
+ case JSOP_PUSH:
+#if JS_HAS_DESTRUCTURING
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_GROUPASSIGN) {
+ pc = DecompileGroupAssignment(ss, pc, endpc, sn, &todo);
+ if (!pc)
+ return NULL;
+ LOCAL_ASSERT(*pc == JSOP_POPN);
+ len = oplen = JSOP_POPN_LENGTH;
+ goto end_groupassignment;
+ }
+#endif
+ /* FALL THROUGH */
+
+ case JSOP_BINDNAME:
+ todo = Sprint(&ss->sprinter, "");
+ break;
+
+ case JSOP_TRY:
+ js_printf(jp, "\ttry {\n");
+ jp->indent += 4;
+ todo = -2;
+ break;
+
+ case JSOP_FINALLY:
+ jp->indent -= 4;
+ js_printf(jp, "\t} finally {\n");
+ jp->indent += 4;
+
+ /*
+ * We push push the pair of exception/restsub cookies to
+ * simulate the effects [gosub] or control transfer during
+ * exception capturing on the stack.
+ */
+ todo = Sprint(&ss->sprinter, exception_cookie);
+ if (todo < 0 || !PushOff(ss, todo, op))
+ return NULL;
+ todo = Sprint(&ss->sprinter, retsub_pc_cookie);
+ break;
+
+ case JSOP_RETSUB:
+ rval = POP_STR();
+ LOCAL_ASSERT(strcmp(rval, retsub_pc_cookie) == 0);
+ lval = POP_STR();
+ LOCAL_ASSERT(strcmp(lval, exception_cookie) == 0);
+ todo = -2;
+ break;
+
+ case JSOP_GOSUB:
+ case JSOP_GOSUBX:
+ /*
+ * JSOP_GOSUB and GOSUBX have no effect on the decompiler's
+ * string stack because the next op in bytecode order finds
+ * the stack balanced by a JSOP_RETSUB executed elsewhere.
+ */
+ todo = -2;
+ break;
+
+ case JSOP_POPN:
+ {
+ uintN newtop, oldtop;
+
+ /*
+ * The compiler models operand stack depth and fixes the stack
+ * pointer on entry to a catch clause based on its depth model.
+ * The decompiler must match the code generator's model, which
+ * is why JSOP_FINALLY pushes a cookie that JSOP_RETSUB pops.
+ */
+ oldtop = ss->top;
+ newtop = oldtop - GET_UINT16(pc);
+ LOCAL_ASSERT(newtop <= oldtop);
+ todo = -2;
+
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_HIDDEN)
+ break;
+#if JS_HAS_DESTRUCTURING
+ if (sn && SN_TYPE(sn) == SRC_GROUPASSIGN) {
+ todo = Sprint(&ss->sprinter, "%s[] = [",
+ VarPrefix(sn));
+ if (todo < 0)
+ return NULL;
+ for (uintN i = newtop; i < oldtop; i++) {
+ rval = OFF2STR(&ss->sprinter, ss->offsets[i]);
+ if (Sprint(&ss->sprinter, ss_format,
+ (i == newtop) ? "" : ", ",
+ (i == oldtop - 1 && *rval == '\0')
+ ? ", " : rval) < 0) {
+ return NULL;
+ }
+ }
+ if (SprintPut(&ss->sprinter, "]", 1) < 0)
+ return NULL;
+
+ /*
+ * If this is an empty group assignment, we have no stack
+ * budget into which we can push our result string. Adjust
+ * ss->sprinter.offset so that our consumer can find the
+ * empty group assignment decompilation.
+ */
+ if (newtop == oldtop) {
+ ss->sprinter.offset = todo;
+ } else {
+ /*
+ * Kill newtop before the end_groupassignment: label by
+ * retracting/popping early. Control will either jump
+ * to do_forloop: or do_letheadbody: or else break from
+ * our case JSOP_POPN: after the switch (*pc2) below.
+ */
+ LOCAL_ASSERT(newtop < oldtop);
+ ss->sprinter.offset = GetOff(ss, newtop);
+ ss->top = newtop;
+ }
+
+ end_groupassignment:
+ LOCAL_ASSERT(*pc == JSOP_POPN);
+
+ /*
+ * Thread directly to the next opcode if we can, to handle
+ * the special cases of a group assignment in the first or
+ * last part of a for(;;) loop head, or in a let block or
+ * expression head.
+ *
+ * NB: todo at this point indexes space in ss->sprinter
+ * that is liable to be overwritten. The code below knows
+ * exactly how long rval lives, or else copies it down via
+ * SprintCString.
+ */
+ rval = OFF2STR(&ss->sprinter, todo);
+ todo = -2;
+ pc2 = pc + oplen;
+ if (*pc2 == JSOP_NOP) {
+ sn = js_GetSrcNote(jp->script, pc2);
+ if (sn) {
+ if (SN_TYPE(sn) == SRC_FOR) {
+ op = JSOP_NOP;
+ pc = pc2;
+ goto do_forloop;
+ }
+
+ if (SN_TYPE(sn) == SRC_DECL) {
+ if (ss->top == StackDepth(jp->script)) {
+ /*
+ * This must be an empty destructuring
+ * in the head of a let whose body block
+ * is also empty.
+ */
+ pc = pc2 + JSOP_NOP_LENGTH;
+ len = js_GetSrcNoteOffset(sn, 0);
+ LOCAL_ASSERT(pc[len] == JSOP_LEAVEBLOCK);
+ js_printf(jp, "\tlet (%s) {\n", rval);
+ js_printf(jp, "\t}\n");
+ break;
+ }
+ todo = SprintCString(&ss->sprinter, rval);
+ if (todo < 0 || !PushOff(ss, todo, JSOP_NOP))
+ return NULL;
+ op = JSOP_POP;
+ pc = pc2 + JSOP_NOP_LENGTH;
+ goto do_letheadbody;
+ }
+ } else {
+ /*
+ * An unnannotated NOP following a POPN must be the
+ * third part of for(;;) loop head. If the POPN's
+ * immediate operand is 0, then we may have no slot
+ * on the sprint-stack in which to push our result
+ * string. In this case the result can be recovered
+ * at ss->sprinter.base + ss->sprinter.offset.
+ */
+ if (GET_UINT16(pc) == 0)
+ break;
+ todo = SprintCString(&ss->sprinter, rval);
+ saveop = JSOP_NOP;
+ }
+ }
+
+ /*
+ * If control flow reaches this point with todo still -2,
+ * just print rval as an expression statement.
+ */
+ if (todo == -2)
+ js_printf(jp, "\t%s;\n", rval);
+ break;
+ }
+#endif
+ if (newtop < oldtop) {
+ ss->sprinter.offset = GetOff(ss, newtop);
+ ss->top = newtop;
+ }
+ break;
+ }
+
+ case JSOP_EXCEPTION:
+ /* The catch decompiler handles this op itself. */
+ LOCAL_ASSERT(JS_FALSE);
+ break;
+
+ case JSOP_POP:
+ /*
+ * By default, do not automatically parenthesize when popping
+ * a stacked expression decompilation. We auto-parenthesize
+ * only when JSOP_POP is annotated with SRC_PCDELTA, meaning
+ * comma operator.
+ */
+ op = JSOP_POPV;
+ /* FALL THROUGH */
+
+ case JSOP_POPV:
+ sn = js_GetSrcNote(jp->script, pc);
+ switch (sn ? SN_TYPE(sn) : SRC_NULL) {
+ case SRC_FOR:
+ /* Force parens around 'in' expression at 'for' front. */
+ if (ss->opcodes[ss->top-1] == JSOP_IN)
+ op = JSOP_LSH;
+ rval = POP_STR();
+ todo = -2;
+ goto do_forloop;
+
+ case SRC_PCDELTA:
+ /* Comma operator: use JSOP_POP for correct precedence. */
+ op = JSOP_POP;
+
+ /* Pop and save to avoid blowing stack depth budget. */
+ lval = JS_strdup(cx, POP_STR());
+ if (!lval)
+ return NULL;
+
+ /*
+ * The offset tells distance to the end of the right-hand
+ * operand of the comma operator.
+ */
+ done = pc + len;
+ pc += js_GetSrcNoteOffset(sn, 0);
+ len = 0;
+
+ if (!Decompile(ss, done, pc - done, JSOP_POP)) {
+ JS_free(cx, (char *)lval);
+ return NULL;
+ }
+
+ /* Pop Decompile result and print comma expression. */
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s, %s", lval, rval);
+ JS_free(cx, (char *)lval);
+ break;
+
+ case SRC_HIDDEN:
+ /* Hide this pop, it's from a goto in a with or for/in. */
+ todo = -2;
+ break;
+
+ case SRC_DECL:
+ /* This pop is at the end of the let block/expr head. */
+ pc += JSOP_POP_LENGTH;
+#if JS_HAS_DESTRUCTURING
+ do_letheadbody:
+#endif
+ len = js_GetSrcNoteOffset(sn, 0);
+ if (pc[len] == JSOP_LEAVEBLOCK) {
+ js_printf(jp, "\tlet (%s) {\n", POP_STR());
+ jp->indent += 4;
+ DECOMPILE_CODE(pc, len);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ todo = -2;
+ } else {
+ LOCAL_ASSERT(pc[len] == JSOP_LEAVEBLOCKEXPR);
+
+ lval = JS_strdup(cx, PopStr(ss, JSOP_NOP));
+ if (!lval)
+ return NULL;
+
+ /* Set saveop to reflect what we will push. */
+ saveop = JSOP_LEAVEBLOCKEXPR;
+ if (!Decompile(ss, pc, len, saveop)) {
+ JS_free(cx, (char *)lval);
+ return NULL;
+ }
+ rval = PopStr(ss, JSOP_SETNAME);
+ todo = Sprint(&ss->sprinter,
+ (*rval == '{')
+ ? "let (%s) (%s)"
+ : "let (%s) %s",
+ lval, rval);
+ JS_free(cx, (char *)lval);
+ }
+ break;
+
+ default:
+ /* Turn off parens around a yield statement. */
+ if (ss->opcodes[ss->top-1] == JSOP_YIELD)
+ op = JSOP_NOP;
+
+ rval = POP_STR();
+
+ /*
+ * Don't emit decompiler-pushed strings that are not
+ * handled by other opcodes. They are pushed onto the
+ * stack to help model the interpreter stack and should
+ * not appear in the decompiler's output.
+ */
+ if (*rval != '\0' && (rval[0] != '/' || rval[1] != '*')) {
+ js_printf(jp,
+ (*rval == '{' ||
+ (strncmp(rval, js_function_str, 8) == 0 &&
+ rval[8] == ' '))
+ ? "\t(%s);\n"
+ : "\t%s;\n",
+ rval);
+ } else {
+ LOCAL_ASSERT(*rval == '\0' ||
+ strcmp(rval, exception_cookie) == 0);
+ }
+ todo = -2;
+ break;
+ }
+ sn = NULL;
+ break;
+
+ case JSOP_ENTERWITH:
+ LOCAL_ASSERT(!js_GetSrcNote(jp->script, pc));
+ rval = POP_STR();
+ js_printf(jp, "\twith (%s) {\n", rval);
+ jp->indent += 4;
+ todo = Sprint(&ss->sprinter, with_cookie);
+ break;
+
+ case JSOP_LEAVEWITH:
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = -2;
+ if (sn && SN_TYPE(sn) == SRC_HIDDEN)
+ break;
+ rval = POP_STR();
+ LOCAL_ASSERT(strcmp(rval, with_cookie) == 0);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ break;
+
+ case JSOP_ENTERBLOCK:
+ {
+ JSAtom **atomv, *smallv[5];
+ JSScopeProperty *sprop;
+
+ LOAD_OBJECT(0);
+ argc = OBJ_BLOCK_COUNT(cx, obj);
+ if ((size_t)argc <= JS_ARRAY_LENGTH(smallv)) {
+ atomv = smallv;
+ } else {
+ atomv = (JSAtom **) JS_malloc(cx, argc * sizeof(JSAtom *));
+ if (!atomv)
+ return NULL;
+ }
+
+ MUST_FLOW_THROUGH("enterblock_out");
+#define LOCAL_ASSERT_OUT(expr) LOCAL_ASSERT_CUSTOM(expr, ok = JS_FALSE; \
+ goto enterblock_out)
+ for (sprop = OBJ_SCOPE(obj)->lastProp; sprop;
+ sprop = sprop->parent) {
+ if (!(sprop->flags & SPROP_HAS_SHORTID))
+ continue;
+ LOCAL_ASSERT_OUT(sprop->shortid < argc);
+ atomv[sprop->shortid] = JSID_TO_ATOM(sprop->id);
+ }
+ ok = JS_TRUE;
+ for (i = 0; i < argc; i++) {
+ atom = atomv[i];
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval ||
+ !PushOff(ss, STR2OFF(&ss->sprinter, rval), op)) {
+ ok = JS_FALSE;
+ goto enterblock_out;
+ }
+ }
+
+ sn = js_GetSrcNote(jp->script, pc);
+ switch (sn ? SN_TYPE(sn) : SRC_NULL) {
+#if JS_HAS_BLOCK_SCOPE
+ case SRC_BRACE:
+ js_printf(jp, "\t{\n");
+ jp->indent += 4;
+ len = js_GetSrcNoteOffset(sn, 0);
+ ok = Decompile(ss, pc + oplen, len - oplen, JSOP_NOP)
+ != NULL;
+ if (!ok)
+ goto enterblock_out;
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ break;
+#endif
+
+ case SRC_CATCH:
+ jp->indent -= 4;
+ js_printf(jp, "\t} catch (");
+
+ pc2 = pc;
+ pc += oplen;
+ LOCAL_ASSERT_OUT(*pc == JSOP_EXCEPTION);
+ pc += JSOP_EXCEPTION_LENGTH;
+ todo = Sprint(&ss->sprinter, exception_cookie);
+ if (todo < 0 || !PushOff(ss, todo, JSOP_EXCEPTION)) {
+ ok = JS_FALSE;
+ goto enterblock_out;
+ }
+
+ if (*pc == JSOP_DUP) {
+ sn2 = js_GetSrcNote(jp->script, pc);
+ if (!sn2 || SN_TYPE(sn2) != SRC_DESTRUCT) {
+ /*
+ * This is a dup to save the exception for later.
+ * It is emitted only when the catch head contains
+ * an exception guard.
+ */
+ LOCAL_ASSERT_OUT(js_GetSrcNoteOffset(sn, 0) != 0);
+ pc += JSOP_DUP_LENGTH;
+ todo = Sprint(&ss->sprinter, exception_cookie);
+ if (todo < 0 ||
+ !PushOff(ss, todo, JSOP_EXCEPTION)) {
+ ok = JS_FALSE;
+ goto enterblock_out;
+ }
+ }
+ }
+
+#if JS_HAS_DESTRUCTURING
+ if (*pc == JSOP_DUP) {
+ pc = DecompileDestructuring(ss, pc, endpc);
+ if (!pc) {
+ ok = JS_FALSE;
+ goto enterblock_out;
+ }
+ LOCAL_ASSERT_OUT(*pc == JSOP_POP);
+ pc += JSOP_POP_LENGTH;
+ lval = PopStr(ss, JSOP_NOP);
+ js_puts(jp, lval);
+ } else {
+#endif
+ LOCAL_ASSERT_OUT(*pc == JSOP_SETLOCALPOP);
+ i = GET_SLOTNO(pc) - jp->script->nfixed;
+ pc += JSOP_SETLOCALPOP_LENGTH;
+ atom = atomv[i - OBJ_BLOCK_DEPTH(cx, obj)];
+ str = ATOM_TO_STRING(atom);
+ if (!QuoteString(&jp->sprinter, str, 0)) {
+ ok = JS_FALSE;
+ goto enterblock_out;
+ }
+#if JS_HAS_DESTRUCTURING
+ }
+#endif
+
+ /*
+ * Pop the exception_cookie (or its dup in the case of a
+ * guarded catch head) off the stack now.
+ */
+ rval = PopStr(ss, JSOP_NOP);
+ LOCAL_ASSERT_OUT(strcmp(rval, exception_cookie) == 0);
+
+ len = js_GetSrcNoteOffset(sn, 0);
+ if (len) {
+ len -= PTRDIFF(pc, pc2, jsbytecode);
+ LOCAL_ASSERT_OUT(len > 0);
+ js_printf(jp, " if ");
+ ok = Decompile(ss, pc, len, JSOP_NOP) != NULL;
+ if (!ok)
+ goto enterblock_out;
+ js_printf(jp, "%s", POP_STR());
+ pc += len;
+ LOCAL_ASSERT_OUT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
+ pc += js_CodeSpec[*pc].length;
+ }
+
+ js_printf(jp, ") {\n");
+ jp->indent += 4;
+ len = 0;
+ break;
+ default:
+ break;
+ }
+
+ todo = -2;
+
+#undef LOCAL_ASSERT_OUT
+ enterblock_out:
+ if (atomv != smallv)
+ JS_free(cx, atomv);
+ if (!ok)
+ return NULL;
+ }
+ break;
+
+ case JSOP_LEAVEBLOCK:
+ case JSOP_LEAVEBLOCKEXPR:
+ {
+ uintN top, depth;
+
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = -2;
+ if (op == JSOP_LEAVEBLOCKEXPR) {
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_PCBASE);
+ rval = POP_STR();
+ } else if (sn) {
+ LOCAL_ASSERT(op == JSOP_LEAVEBLOCK);
+ if (SN_TYPE(sn) == SRC_HIDDEN)
+ break;
+
+ /*
+ * This JSOP_LEAVEBLOCK must be for a catch block. If sn's
+ * offset does not equal the model stack depth, there must
+ * be a copy of the exception value on the stack due to a
+ * catch guard (see above, the JSOP_ENTERBLOCK + SRC_CATCH
+ * case code).
+ */
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_CATCH);
+ if ((uintN)js_GetSrcNoteOffset(sn, 0) != ss->top) {
+ LOCAL_ASSERT((uintN)js_GetSrcNoteOffset(sn, 0)
+ == ss->top - 1);
+ rval = POP_STR();
+ LOCAL_ASSERT(strcmp(rval, exception_cookie) == 0);
+ }
+ }
+ top = ss->top;
+ depth = GET_UINT16(pc);
+ LOCAL_ASSERT(top >= depth);
+ top -= depth;
+ ss->top = top;
+ ss->sprinter.offset = GetOff(ss, top);
+ if (op == JSOP_LEAVEBLOCKEXPR)
+ todo = SprintCString(&ss->sprinter, rval);
+ break;
+ }
+
+ case JSOP_CALLUPVAR:
+ case JSOP_GETUPVAR:
+
+ if (!jp->fun)
+ JS_GET_SCRIPT_FUNCTION(jp->script, 0, jp->fun);
+
+ if (!jp->localNames)
+ jp->localNames = js_GetLocalNameArray(cx, jp->fun, &jp->pool);
+
+ i = JS_UPVAR_LOCAL_NAME_START(jp->fun) + GET_UINT16(pc);
+ if (i >= JS_GET_LOCAL_NAME_COUNT(jp->fun)) {
+ JSUpvarArray *uva;
+#ifdef DEBUG
+ /*
+ * We must be in an eval called from jp->fun, where
+ * jp->script is the eval-compiled script.
+ *
+ * However, it's possible that a js_Invoke already
+ * pushed a frame trying to call js_Construct on an
+ * object that's not a constructor, causing us to be
+ * called with an intervening frame on the stack.
+ */
+ JSStackFrame *fp = cx->fp;
+ if (fp) {
+ while (!(fp->flags & JSFRAME_EVAL))
+ fp = fp->down;
+ JS_ASSERT(fp->script == jp->script);
+ JS_ASSERT(fp->down->fun == jp->fun);
+ JS_ASSERT(FUN_INTERPRETED(jp->fun));
+ JS_ASSERT(jp->script != jp->fun->u.i.script);
+ JS_ASSERT(jp->script->upvarsOffset != 0);
+ }
+#endif
+ uva = JS_SCRIPT_UPVARS(jp->script);
+ i = GET_UINT16(pc);
+ i = UPVAR_FRAME_SLOT(uva->vector[i]);
+ }
+ atom = GetArgOrVarAtom(jp, i);
+ goto do_name;
+
+ case JSOP_CALLLOCAL:
+ case JSOP_GETLOCAL:
+ if (IsVarSlot(jp, pc, &i)) {
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ goto do_name;
+ }
+ LOCAL_ASSERT((uintN)i < ss->top);
+ sn = js_GetSrcNote(jp->script, pc);
+
+#if JS_HAS_DESTRUCTURING
+ if (sn && SN_TYPE(sn) == SRC_GROUPASSIGN) {
+ pc = DecompileGroupAssignment(ss, pc, endpc, sn, &todo);
+ if (!pc)
+ return NULL;
+ LOCAL_ASSERT(*pc == JSOP_POPN);
+ len = oplen = JSOP_POPN_LENGTH;
+ goto end_groupassignment;
+ }
+#endif
+
+ rval = GetLocal(ss, i);
+ todo = Sprint(&ss->sprinter, ss_format, VarPrefix(sn), rval);
+ break;
+
+ case JSOP_SETLOCAL:
+ case JSOP_SETLOCALPOP:
+ if (IsVarSlot(jp, pc, &i)) {
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ goto do_setname;
+ }
+ lval = GetLocal(ss, i);
+ rval = POP_STR();
+ goto do_setlval;
+
+ case JSOP_INCLOCAL:
+ case JSOP_DECLOCAL:
+ if (IsVarSlot(jp, pc, &i)) {
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ goto do_incatom;
+ }
+ lval = GetLocal(ss, i);
+ goto do_inclval;
+
+ case JSOP_LOCALINC:
+ case JSOP_LOCALDEC:
+ if (IsVarSlot(jp, pc, &i)) {
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ goto do_atominc;
+ }
+ lval = GetLocal(ss, i);
+ goto do_lvalinc;
+
+ case JSOP_RETRVAL:
+ todo = -2;
+ break;
+
+ case JSOP_RETURN:
+ LOCAL_ASSERT(jp->fun);
+ fun = jp->fun;
+ if (fun->flags & JSFUN_EXPR_CLOSURE) {
+ /* Turn on parens around comma-expression here. */
+ op = JSOP_SETNAME;
+ rval = POP_STR();
+ js_printf(jp, (*rval == '{') ? "(%s)%s" : ss_format,
+ rval,
+ ((fun->flags & JSFUN_LAMBDA) || !fun->atom)
+ ? ""
+ : ";");
+ todo = -2;
+ break;
+ }
+ /* FALL THROUGH */
+
+ case JSOP_SETRVAL:
+ rval = POP_STR();
+ if (*rval != '\0')
+ js_printf(jp, "\t%s %s;\n", js_return_str, rval);
+ else
+ js_printf(jp, "\t%s;\n", js_return_str);
+ todo = -2;
+ break;
+
+#if JS_HAS_GENERATORS
+ case JSOP_YIELD:
+#if JS_HAS_GENERATOR_EXPRS
+ if (!ss->inGenExp || !(sn = js_GetSrcNote(jp->script, pc)))
+#endif
+ {
+ /* Turn off most parens. */
+ op = JSOP_SETNAME;
+ rval = POP_STR();
+ todo = (*rval != '\0')
+ ? Sprint(&ss->sprinter,
+ (strncmp(rval, js_yield_str, 5) == 0 &&
+ (rval[5] == ' ' || rval[5] == '\0'))
+ ? "%s (%s)"
+ : "%s %s",
+ js_yield_str, rval)
+ : SprintCString(&ss->sprinter, js_yield_str);
+ break;
+ }
+#if JS_HAS_GENERATOR_EXPRS
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_HIDDEN);
+ /* FALL THROUGH */
+#endif
+
+ case JSOP_ARRAYPUSH:
+ {
+ uintN pos, forpos;
+ ptrdiff_t start;
+
+ /* Turn off most parens. */
+ op = JSOP_SETNAME;
+
+ /* Pop the expression being pushed or yielded. */
+ rval = POP_STR();
+
+ /*
+ * Skip the for loop head stacked by JSOP_FORLOCAL until we hit
+ * a block local slot (note empty destructuring patterns result
+ * in unit-count blocks).
+ */
+ pos = ss->top;
+ while (pos != 0) {
+ op = (JSOp) ss->opcodes[--pos];
+ if (op == JSOP_ENTERBLOCK)
+ break;
+ }
+ JS_ASSERT(op == JSOP_ENTERBLOCK);
+
+ /*
+ * Here, forpos must index the space before the left-most |for|
+ * in the single string of accumulated |for| heads and optional
+ * final |if (condition)|.
+ */
+ forpos = pos + 2;
+ LOCAL_ASSERT(forpos < ss->top);
+
+ /*
+ * Now move pos downward over the block's local slots. Even an
+ * empty destructuring pattern has one (dummy) local.
+ */
+ while (ss->opcodes[pos] == JSOP_ENTERBLOCK) {
+ if (pos == 0)
+ break;
+ --pos;
+ }
+ JS_ASSERT_IF(saveop == JSOP_ARRAYPUSH,
+ jp->script->nfixed + pos == GET_UINT16(pc));
+
+#if JS_HAS_GENERATOR_EXPRS
+ if (saveop == JSOP_YIELD) {
+ /*
+ * Generator expression: decompile just rval followed by
+ * the string starting at forpos. Leave the result string
+ * in ss->offsets[0] so it can be recovered by our caller
+ * (the JSOP_ANONFUNOBJ with SRC_GENEXP case). Bump the
+ * top of stack to balance yield, which is an expression
+ * (so has neutral stack balance).
+ */
+ LOCAL_ASSERT(pos == 0);
+ xval = OFF2STR(&ss->sprinter, ss->offsets[forpos]);
+ ss->sprinter.offset = PAREN_SLOP;
+ todo = Sprint(&ss->sprinter, ss_format, rval, xval);
+ if (todo < 0)
+ return NULL;
+ ss->offsets[0] = todo;
+ ++ss->top;
+ return pc;
+ }
+#endif /* JS_HAS_GENERATOR_EXPRS */
+
+ /*
+ * Array comprehension: retract the sprinter to the beginning
+ * of the array initialiser and decompile "[<rval> for ...]".
+ */
+ LOCAL_ASSERT(ss->opcodes[pos] == JSOP_NEWINIT);
+ start = ss->offsets[pos];
+ LOCAL_ASSERT(ss->sprinter.base[start] == '[' ||
+ ss->sprinter.base[start] == '#');
+ LOCAL_ASSERT(forpos < ss->top);
+ xval = OFF2STR(&ss->sprinter, ss->offsets[forpos]);
+ lval = OFF2STR(&ss->sprinter, start);
+ RETRACT(&ss->sprinter, lval);
+
+ todo = Sprint(&ss->sprinter, sss_format, lval, rval, xval);
+ if (todo < 0)
+ return NULL;
+ ss->offsets[pos] = todo;
+ todo = -2;
+ break;
+ }
+#endif
+
+ case JSOP_THROWING:
+ todo = -2;
+ break;
+
+ case JSOP_THROW:
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = -2;
+ if (sn && SN_TYPE(sn) == SRC_HIDDEN)
+ break;
+ rval = POP_STR();
+ js_printf(jp, "\t%s %s;\n", js_throw_str, rval);
+ break;
+
+ case JSOP_ITER:
+ foreach = (pc[1] & (JSITER_FOREACH | JSITER_KEYVALUE)) ==
+ JSITER_FOREACH;
+ todo = SprintCString(&ss->sprinter, iter_cookie);
+ break;
+
+ case JSOP_NEXTITER:
+ JS_NOT_REACHED("JSOP_NEXTITER");
+ break;
+
+ case JSOP_ENDITER:
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = -2;
+ if (sn && SN_TYPE(sn) == SRC_HIDDEN)
+ break;
+ (void) PopOff(ss, op);
+ (void) PopOff(ss, op);
+ break;
+
+ case JSOP_GOTO:
+ case JSOP_GOTOX:
+ sn = js_GetSrcNote(jp->script, pc);
+ switch (sn ? SN_TYPE(sn) : SRC_NULL) {
+ case SRC_FOR_IN:
+ /*
+ * The loop back-edge carries +1 stack balance, for the
+ * flag processed by JSOP_IFNE. We do not decompile the
+ * JSOP_IFNE, and instead push the left-hand side of 'in'
+ * after the loop edge in this stack slot (the JSOP_FOR*
+ * opcodes' decompilers do this pushing).
+ */
+ cond = GetJumpOffset(pc, pc);
+ next = js_GetSrcNoteOffset(sn, 0);
+ tail = js_GetSrcNoteOffset(sn, 1);
+ JS_ASSERT(pc[cond] == JSOP_NEXTITER);
+ DECOMPILE_CODE(pc + oplen, next - oplen);
+ lval = POP_STR();
+ if (ss->inArrayInit || ss->inGenExp) {
+ (void) PopOff(ss, JSOP_NOP);
+ rval = TOP_STR();
+ LOCAL_ASSERT(ss->top >= 2);
+ if (ss->opcodes[ss->top - 2] == JSOP_FORLOCAL) {
+ ss->sprinter.offset = ss->offsets[ss->top - 1] - PAREN_SLOP;
+ if (Sprint(&ss->sprinter, " %s (%s in %s)",
+ foreach ? js_for_each_str : js_for_str,
+ lval, rval) < 0) {
+ return NULL;
+ }
+
+ /*
+ * Do not AddParentSlop here, as we will push the
+ * top-most offset again, which will add paren slop
+ * for us. We must push to balance the stack budget
+ * when nesting for heads in a comprehension.
+ */
+ todo = ss->offsets[ss->top - 1];
+ } else {
+ LOCAL_ASSERT(ss->opcodes[ss->top - 2] == JSOP_ENTERBLOCK);
+ todo = Sprint(&ss->sprinter, " %s (%s in %s)",
+ foreach ? js_for_each_str : js_for_str,
+ lval, rval);
+ }
+ if (todo < 0 || !PushOff(ss, todo, JSOP_FORLOCAL))
+ return NULL;
+ DECOMPILE_CODE(pc + next, cond - next);
+ } else {
+ /*
+ * As above, rval or an extension of it must remain
+ * stacked during loop body decompilation.
+ */
+ rval = GetStr(ss, ss->top - 2);
+ js_printf(jp, "\t%s (%s in %s) {\n",
+ foreach ? js_for_each_str : js_for_str,
+ lval, rval);
+ jp->indent += 4;
+ DECOMPILE_CODE(pc + next, cond - next);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ }
+ pc += tail;
+ LOCAL_ASSERT(*pc == JSOP_IFNE || *pc == JSOP_IFNEX);
+ len = js_CodeSpec[*pc].length;
+ break;
+
+ case SRC_WHILE:
+ cond = GetJumpOffset(pc, pc);
+ tail = js_GetSrcNoteOffset(sn, 0);
+ DECOMPILE_CODE(pc + cond, tail - cond);
+ js_printf(jp, "\twhile (%s) {\n", POP_COND_STR());
+ jp->indent += 4;
+ DECOMPILE_CODE(pc + oplen, cond - oplen);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ pc += tail;
+ LOCAL_ASSERT(*pc == JSOP_IFNE || *pc == JSOP_IFNEX);
+ len = js_CodeSpec[*pc].length;
+ todo = -2;
+ break;
+
+ case SRC_CONT2LABEL:
+ GET_SOURCE_NOTE_ATOM(sn, atom);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ js_printf(jp, "\tcontinue %s;\n", rval);
+ break;
+
+ case SRC_CONTINUE:
+ js_printf(jp, "\tcontinue;\n");
+ break;
+
+ case SRC_BREAK2LABEL:
+ GET_SOURCE_NOTE_ATOM(sn, atom);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ js_printf(jp, "\tbreak %s;\n", rval);
+ break;
+
+ case SRC_HIDDEN:
+ break;
+
+ default:
+ js_printf(jp, "\tbreak;\n");
+ break;
+ }
+ todo = -2;
+ break;
+
+ case JSOP_IFEQ:
+ case JSOP_IFEQX:
+ {
+ JSBool elseif = JS_FALSE;
+
+ if_again:
+ len = GetJumpOffset(pc, pc);
+ sn = js_GetSrcNote(jp->script, pc);
+
+ switch (sn ? SN_TYPE(sn) : SRC_NULL) {
+ case SRC_IF:
+ case SRC_IF_ELSE:
+ rval = POP_COND_STR();
+ if (ss->inArrayInit || ss->inGenExp) {
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_IF);
+ ss->sprinter.offset -= PAREN_SLOP;
+ if (Sprint(&ss->sprinter, " if (%s)", rval) < 0)
+ return NULL;
+ AddParenSlop(ss);
+ } else {
+ js_printf(jp,
+ elseif ? " if (%s) {\n" : "\tif (%s) {\n",
+ rval);
+ jp->indent += 4;
+ }
+
+ if (SN_TYPE(sn) == SRC_IF) {
+ DECOMPILE_CODE(pc + oplen, len - oplen);
+ } else {
+ LOCAL_ASSERT(!ss->inArrayInit && !ss->inGenExp);
+ tail = js_GetSrcNoteOffset(sn, 0);
+ DECOMPILE_CODE(pc + oplen, tail - oplen);
+ jp->indent -= 4;
+ pc += tail;
+ LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
+ oplen = js_CodeSpec[*pc].length;
+ len = GetJumpOffset(pc, pc);
+ js_printf(jp, "\t} else");
+
+ /*
+ * If the second offset for sn is non-zero, it tells
+ * the distance from the goto around the else, to the
+ * ifeq for the if inside the else that forms an "if
+ * else if" chain. Thus cond spans the condition of
+ * the second if, so we simply decompile it and start
+ * over at label if_again.
+ */
+ cond = js_GetSrcNoteOffset(sn, 1);
+ if (cond != 0) {
+ DECOMPILE_CODE(pc + oplen, cond - oplen);
+ pc += cond;
+ elseif = JS_TRUE;
+ goto if_again;
+ }
+
+ js_printf(jp, " {\n");
+ jp->indent += 4;
+ DECOMPILE_CODE(pc + oplen, len - oplen);
+ }
+
+ if (!ss->inArrayInit && !ss->inGenExp) {
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ }
+ todo = -2;
+ break;
+
+ case SRC_COND:
+ xval = JS_strdup(cx, POP_STR());
+ if (!xval)
+ return NULL;
+ len = js_GetSrcNoteOffset(sn, 0);
+ DECOMPILE_CODE(pc + oplen, len - oplen);
+ lval = JS_strdup(cx, POP_STR());
+ if (!lval) {
+ JS_free(cx, (void *)xval);
+ return NULL;
+ }
+ pc += len;
+ LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
+ oplen = js_CodeSpec[*pc].length;
+ len = GetJumpOffset(pc, pc);
+ DECOMPILE_CODE(pc + oplen, len - oplen);
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s ? %s : %s",
+ xval, lval, rval);
+ JS_free(cx, (void *)xval);
+ JS_free(cx, (void *)lval);
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ case JSOP_IFNE:
+ case JSOP_IFNEX:
+ LOCAL_ASSERT(0);
+ break;
+
+ case JSOP_OR:
+ case JSOP_ORX:
+ xval = "||";
+
+ do_logical_connective:
+ /* Top of stack is the first clause in a disjunction (||). */
+ lval = JS_strdup(cx, POP_STR());
+ if (!lval)
+ return NULL;
+ done = pc + GetJumpOffset(pc, pc);
+ pc += len;
+ len = PTRDIFF(done, pc, jsbytecode);
+ if (!Decompile(ss, pc, len, op)) {
+ JS_free(cx, (char *)lval);
+ return NULL;
+ }
+ rval = POP_STR();
+ if (jp->pretty &&
+ jp->indent + 4 + strlen(lval) + 4 + strlen(rval) > 75) {
+ rval = JS_strdup(cx, rval);
+ if (!rval) {
+ tail = -1;
+ } else {
+ todo = Sprint(&ss->sprinter, "%s %s\n", lval, xval);
+ tail = Sprint(&ss->sprinter, "%*s%s",
+ jp->indent + 4, "", rval);
+ JS_free(cx, (char *)rval);
+ }
+ if (tail < 0)
+ todo = -1;
+ } else {
+ todo = Sprint(&ss->sprinter, "%s %s %s", lval, xval, rval);
+ }
+ JS_free(cx, (char *)lval);
+ break;
+
+ case JSOP_AND:
+ case JSOP_ANDX:
+ xval = "&&";
+ goto do_logical_connective;
+
+ case JSOP_FORARG:
+ sn = NULL;
+ i = GET_ARGNO(pc);
+ goto do_forvarslot;
+
+ case JSOP_FORLOCAL:
+ sn = js_GetSrcNote(jp->script, pc);
+ if (!IsVarSlot(jp, pc, &i)) {
+ JS_ASSERT(op == JSOP_FORLOCAL);
+ todo = Sprint(&ss->sprinter, ss_format, VarPrefix(sn), GetStr(ss, i));
+ break;
+ }
+
+ do_forvarslot:
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ todo = SprintCString(&ss->sprinter, VarPrefix(sn));
+ if (todo < 0 || !QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
+ return NULL;
+ break;
+
+ case JSOP_FORNAME:
+ LOAD_ATOM(0);
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = SprintCString(&ss->sprinter, VarPrefix(sn));
+ if (todo < 0 || !QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
+ return NULL;
+ break;
+
+ case JSOP_FORPROP:
+ xval = NULL;
+ LOAD_ATOM(0);
+ if (!ATOM_IS_IDENTIFIER(atom)) {
+ xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ (jschar)'\'');
+ if (!xval)
+ return NULL;
+ }
+ lval = POP_STR();
+ if (xval) {
+ JS_ASSERT(*lval);
+ todo = Sprint(&ss->sprinter, index_format, lval, xval);
+ } else {
+ todo = Sprint(&ss->sprinter, ss_format, lval, *lval ? "." : "");
+ if (todo < 0)
+ return NULL;
+ if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
+ return NULL;
+ }
+ break;
+
+ case JSOP_FORELEM:
+ todo = SprintCString(&ss->sprinter, forelem_cookie);
+ break;
+
+ case JSOP_ENUMELEM:
+ case JSOP_ENUMCONSTELEM:
+ /*
+ * The stack has the object under the (top) index expression.
+ * The "rval" property id is underneath those two on the stack.
+ * The for loop body net and gross lengths can now be adjusted
+ * to account for the length of the indexing expression that
+ * came after JSOP_FORELEM and before JSOP_ENUMELEM.
+ */
+ atom = NULL;
+ op = JSOP_NOP; /* turn off parens around xval */
+ xval = POP_STR();
+ op = JSOP_GETELEM; /* lval must have high precedence */
+ lval = POP_STR();
+ op = saveop;
+ rval = POP_STR();
+ LOCAL_ASSERT(strcmp(rval, forelem_cookie) == 0);
+ if (*xval == '\0') {
+ todo = SprintCString(&ss->sprinter, lval);
+ } else {
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(lastop) == JOF_XMLNAME)
+ ? dot_format
+ : index_format,
+ lval, xval);
+ }
+ break;
+
+#if JS_HAS_GETTER_SETTER
+ case JSOP_GETTER:
+ case JSOP_SETTER:
+ todo = -2;
+ break;
+#endif
+
+ case JSOP_DUP2:
+ rval = GetStr(ss, ss->top-2);
+ todo = SprintCString(&ss->sprinter, rval);
+ if (todo < 0 || !PushOff(ss, todo,
+ (JSOp) ss->opcodes[ss->top-2])) {
+ return NULL;
+ }
+ /* FALL THROUGH */
+
+ case JSOP_DUP:
+#if JS_HAS_DESTRUCTURING
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn) {
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_DESTRUCT);
+ pc = DecompileDestructuring(ss, pc, endpc);
+ if (!pc)
+ return NULL;
+ len = 0;
+ lval = POP_STR();
+ op = saveop = JSOP_ENUMELEM;
+ rval = POP_STR();
+
+ if (strcmp(rval, forelem_cookie) == 0) {
+ todo = Sprint(&ss->sprinter, ss_format,
+ VarPrefix(sn), lval);
+
+ // Skip POP so the SRC_FOR_IN code can pop for itself.
+ if (*pc == JSOP_POP)
+ len = JSOP_POP_LENGTH;
+ } else {
+ todo = Sprint(&ss->sprinter, "%s%s = %s",
+ VarPrefix(sn), lval, rval);
+ }
+ break;
+ }
+#endif
+
+ rval = GetStr(ss, ss->top-1);
+ saveop = (JSOp) ss->opcodes[ss->top-1];
+ todo = SprintCString(&ss->sprinter, rval);
+ break;
+
+ case JSOP_SETARG:
+ atom = GetArgOrVarAtom(jp, GET_ARGNO(pc));
+ LOCAL_ASSERT(atom);
+ goto do_setname;
+
+ case JSOP_SETCONST:
+ case JSOP_SETNAME:
+ case JSOP_SETGVAR:
+ LOAD_ATOM(0);
+
+ do_setname:
+ lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!lval)
+ return NULL;
+ rval = POP_STR();
+ if (op == JSOP_SETNAME)
+ (void) PopOff(ss, op);
+
+ do_setlval:
+ sn = js_GetSrcNote(jp->script, pc - 1);
+ if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
+ todo = Sprint(&ss->sprinter, "%s %s= %s",
+ lval,
+ (lastop == JSOP_GETTER)
+ ? js_getter_str
+ : (lastop == JSOP_SETTER)
+ ? js_setter_str
+ : CodeToken[lastop],
+ rval);
+ } else {
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = Sprint(&ss->sprinter, "%s%s = %s",
+ VarPrefix(sn), lval, rval);
+ }
+ if (op == JSOP_SETLOCALPOP) {
+ if (!PushOff(ss, todo, saveop))
+ return NULL;
+ rval = POP_STR();
+ LOCAL_ASSERT(*rval != '\0');
+ js_printf(jp, "\t%s;\n", rval);
+ todo = -2;
+ }
+ break;
+
+ case JSOP_NEW:
+ case JSOP_CALL:
+ case JSOP_EVAL:
+ case JSOP_APPLY:
+#if JS_HAS_LVALUE_RETURN
+ case JSOP_SETCALL:
+#endif
+ /* Turn off most parens (all if there's only one argument). */
+ argc = GET_ARGC(pc);
+ op = (argc == 1) ? JSOP_NOP : JSOP_SETNAME;
+ argv = (char **)
+ JS_malloc(cx, (size_t)(argc + 1) * sizeof *argv);
+ if (!argv)
+ return NULL;
+
+ ok = JS_TRUE;
+ for (i = argc; i > 0; i--) {
+ argv[i] = JS_strdup(cx, POP_STR());
+ if (!argv[i])
+ ok = JS_FALSE;
+ }
+
+ /* Skip the JSOP_PUSHOBJ-created empty string. */
+ LOCAL_ASSERT(ss->top >= 2);
+ (void) PopOff(ss, op);
+
+ /*
+ * Special case: new (x(y)(z)) must be parenthesized like so.
+ * Same for new (x(y).z) -- contrast with new x(y).z.
+ * See PROPAGATE_CALLNESS.
+ */
+ op = (JSOp) ss->opcodes[ss->top-1];
+ lval = PopStr(ss,
+ (saveop == JSOP_NEW &&
+ (op == JSOP_CALL ||
+ op == JSOP_EVAL ||
+ op == JSOP_APPLY ||
+ (js_CodeSpec[op].format & JOF_CALLOP)))
+ ? JSOP_NAME
+ : saveop);
+ op = saveop;
+
+ argv[0] = JS_strdup(cx, lval);
+ if (!argv[i])
+ ok = JS_FALSE;
+
+ lval = "(", rval = ")";
+ if (op == JSOP_NEW) {
+ if (argc == 0)
+ lval = rval = "";
+ todo = Sprint(&ss->sprinter, "%s %s%s",
+ js_new_str, argv[0], lval);
+ } else {
+ todo = Sprint(&ss->sprinter, ss_format,
+ argv[0], lval);
+ }
+ if (todo < 0)
+ ok = JS_FALSE;
+
+ for (i = 1; i <= argc; i++) {
+ if (!argv[i] ||
+ Sprint(&ss->sprinter, ss_format,
+ argv[i], (i < argc) ? ", " : "") < 0) {
+ ok = JS_FALSE;
+ break;
+ }
+ }
+ if (Sprint(&ss->sprinter, rval) < 0)
+ ok = JS_FALSE;
+
+ for (i = 0; i <= argc; i++) {
+ if (argv[i])
+ JS_free(cx, argv[i]);
+ }
+ JS_free(cx, argv);
+ if (!ok)
+ return NULL;
+#if JS_HAS_LVALUE_RETURN
+ if (op == JSOP_SETCALL) {
+ if (!PushOff(ss, todo, op))
+ return NULL;
+ todo = Sprint(&ss->sprinter, "");
+ }
+#endif
+ break;
+
+ case JSOP_DELNAME:
+ LOAD_ATOM(0);
+ lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!lval)
+ return NULL;
+ RETRACT(&ss->sprinter, lval);
+ do_delete_lval:
+ todo = Sprint(&ss->sprinter, "%s %s", js_delete_str, lval);
+ break;
+
+ case JSOP_DELPROP:
+ GET_ATOM_QUOTE_AND_FMT("%s %s[%s]", "%s %s.%s", rval);
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, fmt, js_delete_str, lval, rval);
+ break;
+
+ case JSOP_DELELEM:
+ op = JSOP_NOP; /* turn off parens */
+ xval = POP_STR();
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ if (*xval == '\0')
+ goto do_delete_lval;
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(lastop) == JOF_XMLNAME)
+ ? "%s %s.%s"
+ : "%s %s[%s]",
+ js_delete_str, lval, xval);
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case JSOP_DELDESC:
+ xval = POP_STR();
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s %s..%s",
+ js_delete_str, lval, xval);
+ break;
+#endif
+
+ case JSOP_TYPEOFEXPR:
+ case JSOP_TYPEOF:
+ case JSOP_VOID:
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s %s",
+ (op == JSOP_VOID) ? js_void_str : js_typeof_str,
+ rval);
+ break;
+
+ case JSOP_INCARG:
+ case JSOP_DECARG:
+ atom = GetArgOrVarAtom(jp, GET_ARGNO(pc));
+ LOCAL_ASSERT(atom);
+ goto do_incatom;
+
+ case JSOP_INCNAME:
+ case JSOP_DECNAME:
+ case JSOP_INCGVAR:
+ case JSOP_DECGVAR:
+ LOAD_ATOM(0);
+ do_incatom:
+ lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!lval)
+ return NULL;
+ RETRACT(&ss->sprinter, lval);
+ do_inclval:
+ todo = Sprint(&ss->sprinter, ss_format,
+ js_incop_strs[!(cs->format & JOF_INC)], lval);
+ break;
+
+ case JSOP_INCPROP:
+ case JSOP_DECPROP:
+ GET_ATOM_QUOTE_AND_FMT(preindex_format, predot_format, rval);
+
+ /*
+ * Force precedence below the numeric literal opcodes, so that
+ * 42..foo or 10000..toString(16), e.g., decompile with parens
+ * around the left-hand side of dot.
+ */
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, fmt,
+ js_incop_strs[!(cs->format & JOF_INC)],
+ lval, rval);
+ break;
+
+ case JSOP_INCELEM:
+ case JSOP_DECELEM:
+ op = JSOP_NOP; /* turn off parens */
+ xval = POP_STR();
+ op = JSOP_GETELEM;
+ lval = POP_STR();
+ if (*xval != '\0') {
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(lastop) == JOF_XMLNAME)
+ ? predot_format
+ : preindex_format,
+ js_incop_strs[!(cs->format & JOF_INC)],
+ lval, xval);
+ } else {
+ todo = Sprint(&ss->sprinter, ss_format,
+ js_incop_strs[!(cs->format & JOF_INC)], lval);
+ }
+ break;
+
+ case JSOP_ARGINC:
+ case JSOP_ARGDEC:
+ atom = GetArgOrVarAtom(jp, GET_ARGNO(pc));
+ LOCAL_ASSERT(atom);
+ goto do_atominc;
+
+ case JSOP_NAMEINC:
+ case JSOP_NAMEDEC:
+ case JSOP_GVARINC:
+ case JSOP_GVARDEC:
+ LOAD_ATOM(0);
+ do_atominc:
+ lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!lval)
+ return NULL;
+ RETRACT(&ss->sprinter, lval);
+ do_lvalinc:
+ todo = Sprint(&ss->sprinter, ss_format,
+ lval, js_incop_strs[!(cs->format & JOF_INC)]);
+ break;
+
+ case JSOP_PROPINC:
+ case JSOP_PROPDEC:
+ GET_ATOM_QUOTE_AND_FMT(postindex_format, postdot_format, rval);
+
+ /*
+ * Force precedence below the numeric literal opcodes, so that
+ * 42..foo or 10000..toString(16), e.g., decompile with parens
+ * around the left-hand side of dot.
+ */
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, fmt, lval, rval,
+ js_incop_strs[!(cs->format & JOF_INC)]);
+ break;
+
+ case JSOP_ELEMINC:
+ case JSOP_ELEMDEC:
+ op = JSOP_NOP; /* turn off parens */
+ xval = POP_STR();
+ op = JSOP_GETELEM;
+ lval = POP_STR();
+ if (*xval != '\0') {
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(lastop) == JOF_XMLNAME)
+ ? postdot_format
+ : postindex_format,
+ lval, xval,
+ js_incop_strs[!(cs->format & JOF_INC)]);
+ } else {
+ todo = Sprint(&ss->sprinter, ss_format,
+ lval, js_incop_strs[!(cs->format & JOF_INC)]);
+ }
+ break;
+
+ case JSOP_LENGTH:
+ fmt = dot_format;
+ rval = js_length_str;
+ goto do_getprop_lval;
+
+ case JSOP_GETPROP2:
+ op = JSOP_GETPROP;
+ (void) PopOff(ss, lastop);
+ /* FALL THROUGH */
+
+ case JSOP_CALLPROP:
+ case JSOP_GETPROP:
+ case JSOP_GETXPROP:
+ LOAD_ATOM(0);
+
+ do_getprop:
+ GET_QUOTE_AND_FMT(index_format, dot_format, rval);
+ do_getprop_lval:
+ PROPAGATE_CALLNESS();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, fmt, lval, rval);
+ break;
+
+ case JSOP_GETTHISPROP:
+ LOAD_ATOM(0);
+ GET_QUOTE_AND_FMT(index_format, dot_format, rval);
+ todo = Sprint(&ss->sprinter, fmt, js_this_str, rval);
+ break;
+
+ case JSOP_GETARGPROP:
+ /* Get the name of the argument or variable. */
+ i = GET_ARGNO(pc);
+
+ do_getarg_prop:
+ atom = GetArgOrVarAtom(ss->printer, i);
+ LOCAL_ASSERT(atom);
+ LOCAL_ASSERT(ATOM_IS_STRING(atom));
+ lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!lval || !PushOff(ss, STR2OFF(&ss->sprinter, lval), op))
+ return NULL;
+
+ /* Get the name of the property. */
+ LOAD_ATOM(ARGNO_LEN);
+ goto do_getprop;
+
+ case JSOP_GETLOCALPROP:
+ if (IsVarSlot(jp, pc, &i))
+ goto do_getarg_prop;
+ LOCAL_ASSERT((uintN)i < ss->top);
+ lval = GetLocal(ss, i);
+ if (!lval)
+ return NULL;
+ todo = SprintCString(&ss->sprinter, lval);
+ if (todo < 0 || !PushOff(ss, todo, op))
+ return NULL;
+ LOAD_ATOM(2);
+ goto do_getprop;
+
+ case JSOP_SETPROP:
+ LOAD_ATOM(0);
+ GET_QUOTE_AND_FMT("%s[%s] %s= %s", "%s.%s %s= %s", xval);
+ rval = POP_STR();
+
+ /*
+ * Force precedence below the numeric literal opcodes, so that
+ * 42..foo or 10000..toString(16), e.g., decompile with parens
+ * around the left-hand side of dot.
+ */
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ sn = js_GetSrcNote(jp->script, pc - 1);
+ todo = Sprint(&ss->sprinter, fmt, lval, xval,
+ (sn && SN_TYPE(sn) == SRC_ASSIGNOP)
+ ? (lastop == JSOP_GETTER)
+ ? js_getter_str
+ : (lastop == JSOP_SETTER)
+ ? js_setter_str
+ : CodeToken[lastop]
+ : "",
+ rval);
+ break;
+
+ case JSOP_GETELEM2:
+ op = JSOP_GETELEM;
+ (void) PopOff(ss, lastop);
+ /* FALL THROUGH */
+
+ case JSOP_CALLELEM:
+ case JSOP_GETELEM:
+ op = JSOP_NOP; /* turn off parens */
+ xval = POP_STR();
+ op = saveop;
+ PROPAGATE_CALLNESS();
+ lval = POP_STR();
+ if (*xval == '\0') {
+ todo = Sprint(&ss->sprinter, "%s", lval);
+ } else {
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(lastop) == JOF_XMLNAME)
+ ? dot_format
+ : index_format,
+ lval, xval);
+ }
+ break;
+
+ case JSOP_SETELEM:
+ rval = POP_STR();
+ op = JSOP_NOP; /* turn off parens */
+ xval = POP_STR();
+ cs = &js_CodeSpec[ss->opcodes[ss->top]];
+ op = JSOP_GETELEM; /* lval must have high precedence */
+ lval = POP_STR();
+ op = saveop;
+ if (*xval == '\0')
+ goto do_setlval;
+ sn = js_GetSrcNote(jp->script, pc - 1);
+ todo = Sprint(&ss->sprinter,
+ (JOF_MODE(cs->format) == JOF_XMLNAME)
+ ? "%s.%s %s= %s"
+ : "%s[%s] %s= %s",
+ lval, xval,
+ (sn && SN_TYPE(sn) == SRC_ASSIGNOP)
+ ? (lastop == JSOP_GETTER)
+ ? js_getter_str
+ : (lastop == JSOP_SETTER)
+ ? js_setter_str
+ : CodeToken[lastop]
+ : "",
+ rval);
+ break;
+
+ case JSOP_ARGSUB:
+ i = (jsint) GET_ARGNO(pc);
+ todo = Sprint(&ss->sprinter, "%s[%d]",
+ js_arguments_str, (int) i);
+ break;
+
+ case JSOP_ARGCNT:
+ todo = Sprint(&ss->sprinter, dot_format,
+ js_arguments_str, js_length_str);
+ break;
+
+ case JSOP_CALLARG:
+ case JSOP_GETARG:
+ i = GET_ARGNO(pc);
+ atom = GetArgOrVarAtom(jp, i);
+#if JS_HAS_DESTRUCTURING
+ if (!atom) {
+ todo = Sprint(&ss->sprinter, "%s[%d]", js_arguments_str, i);
+ break;
+ }
+#else
+ LOCAL_ASSERT(atom);
+#endif
+ goto do_name;
+
+ case JSOP_CALLNAME:
+ case JSOP_NAME:
+ case JSOP_GETGVAR:
+ case JSOP_CALLGVAR:
+ LOAD_ATOM(0);
+ do_name:
+ lval = "";
+#if JS_HAS_XML_SUPPORT
+ do_qname:
+#endif
+ sn = js_GetSrcNote(jp->script, pc);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ inXML ? DONT_ESCAPE : 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ todo = Sprint(&ss->sprinter, sss_format,
+ VarPrefix(sn), lval, rval);
+ break;
+
+ case JSOP_UINT16:
+ i = (jsint) GET_UINT16(pc);
+ goto do_sprint_int;
+
+ case JSOP_UINT24:
+ i = (jsint) GET_UINT24(pc);
+ goto do_sprint_int;
+
+ case JSOP_INT8:
+ i = GET_INT8(pc);
+ goto do_sprint_int;
+
+ case JSOP_INT32:
+ i = GET_INT32(pc);
+ do_sprint_int:
+ todo = Sprint(&ss->sprinter, "%d", i);
+ break;
+
+ case JSOP_DOUBLE:
+ LOAD_ATOM(0);
+ val = ATOM_KEY(atom);
+ LOCAL_ASSERT(JSVAL_IS_DOUBLE(val));
+ todo = SprintDoubleValue(&ss->sprinter, val, &saveop);
+ break;
+
+ case JSOP_STRING:
+ LOAD_ATOM(0);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ inXML ? DONT_ESCAPE : '"');
+ if (!rval)
+ return NULL;
+ todo = STR2OFF(&ss->sprinter, rval);
+ break;
+
+ case JSOP_ANONFUNOBJ:
+#if JS_HAS_GENERATOR_EXPRS
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_GENEXP) {
+ JSScript *inner, *outer;
+ void *mark;
+ SprintStack ss2;
+
+ LOAD_FUNCTION(0);
+ inner = fun->u.i.script;
+
+ /*
+ * All allocation when decompiling is LIFO, using malloc
+ * or, more commonly, arena-alloocating from cx->tempPool.
+ * After InitSprintStack succeeds, we must release to mark
+ * before returning.
+ */
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ if (!InitSprintStack(cx, &ss2, jp, StackDepth(inner)))
+ return NULL;
+ ss2.inGenExp = JS_TRUE;
+
+ /*
+ * Recursively decompile this generator function as an
+ * un-parenthesized generator expression. The ss->inGenExp
+ * special case of JSOP_YIELD shares array comprehension
+ * decompilation code that leaves the result as the single
+ * string pushed on ss2.
+ */
+ outer = jp->script;
+ LOCAL_ASSERT(JS_UPTRDIFF(pc, outer->code) <= outer->length);
+ jp->script = inner;
+ if (!Decompile(&ss2, inner->code, inner->length, JSOP_NOP)) {
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return NULL;
+ }
+ jp->script = outer;
+
+ /*
+ * Advance over this op and its global |this| push, and
+ * arrange to advance over the call to this lambda.
+ */
+ pc += len;
+ LOCAL_ASSERT(*pc == JSOP_NULL || *pc == JSOP_NULLTHIS);
+ pc += JSOP_NULL_LENGTH;
+ LOCAL_ASSERT(*pc == JSOP_CALL);
+ LOCAL_ASSERT(GET_ARGC(pc) == 0);
+ len = JSOP_CALL_LENGTH;
+
+ /*
+ * Arrange to parenthesize this genexp unless:
+ *
+ * 1. It is the complete expression consumed by a control
+ * flow bytecode such as JSOP_TABLESWITCH whose syntax
+ * always parenthesizes the controlling expression.
+ * 2. It is the condition of a loop other than a for (;;).
+ * 3. It is the sole argument to a function call.
+ * 4. It is the condition of an if statement and not of a
+ * ?: expression.
+ *
+ * But (first, before anything else) always parenthesize
+ * if this genexp runs up against endpc and the next op is
+ * not a loop condition (JSOP_IFNE*) opcode. In such cases,
+ * this Decompile activation has been recursively called by
+ * a comma operator, &&, or || bytecode.
+ */
+ pc2 = pc + len;
+ LOCAL_ASSERT(pc2 < endpc ||
+ endpc < outer->code + outer->length);
+ LOCAL_ASSERT(ss2.top == 1);
+ ss2.opcodes[0] = JSOP_POP;
+ if (pc2 == endpc &&
+ (JSOp) *endpc != JSOP_IFNE &&
+ (JSOp) *endpc != JSOP_IFNEX) {
+ op = JSOP_SETNAME;
+ } else {
+ op = (JSOp) *pc2;
+ op = ((js_CodeSpec[op].format & JOF_PARENHEAD) ||
+ ((js_CodeSpec[op].format & JOF_INVOKE) &&
+ GET_ARGC(pc2) == 1) ||
+ ((op == JSOP_IFEQ || op == JSOP_IFEQX) &&
+ (sn2 = js_GetSrcNote(outer, pc2)) &&
+ SN_TYPE(sn2) != SRC_COND))
+ ? JSOP_POP
+ : JSOP_SETNAME;
+
+ /*
+ * Stack this result as if it's a name and not an
+ * anonymous function, so it doesn't get decompiled as
+ * a generator function in a getter or setter context.
+ * The precedence level is the same for JSOP_NAME and
+ * JSOP_ANONFUNOBJ.
+ */
+ LOCAL_ASSERT(js_CodeSpec[JSOP_NAME].prec ==
+ js_CodeSpec[saveop].prec);
+ saveop = JSOP_NAME;
+ }
+
+ /*
+ * Alas, we have to malloc a copy of the result left on
+ * the top of ss2 because both ss and ss2 arena-allocate
+ * from cx's tempPool.
+ */
+ rval = JS_strdup(cx, PopStr(&ss2, op));
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ if (!rval)
+ return NULL;
+ todo = SprintCString(&ss->sprinter, rval);
+ JS_free(cx, (void *)rval);
+ break;
+ }
+#endif /* JS_HAS_GENERATOR_EXPRS */
+ /* FALL THROUGH */
+
+ case JSOP_NAMEDFUNOBJ:
+ LOAD_FUNCTION(0);
+ {
+ uintN indent = JS_DONT_PRETTY_PRINT;
+
+ /*
+ * Always parenthesize expression closures. We can't force
+ * saveop to a low-precedence op to arrange for auto-magic
+ * parenthesization without confusing getter/setter code
+ * that checks for JSOP_ANONFUNOBJ and JSOP_NAMEDFUNOBJ.
+ */
+ if (!(fun->flags & JSFUN_EXPR_CLOSURE))
+ indent |= JS_IN_GROUP_CONTEXT;
+ str = JS_DecompileFunction(cx, fun, indent);
+ if (!str)
+ return NULL;
+ }
+ sprint_string:
+ todo = SprintString(&ss->sprinter, str);
+ break;
+
+ case JSOP_OBJECT:
+ LOAD_OBJECT(0);
+ LOCAL_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
+ goto do_regexp;
+
+ case JSOP_REGEXP:
+ GET_REGEXP_FROM_BYTECODE(jp->script, pc, 0, obj);
+ do_regexp:
+ if (!js_regexp_toString(cx, obj, &val))
+ return NULL;
+ str = JSVAL_TO_STRING(val);
+ goto sprint_string;
+
+ case JSOP_TABLESWITCH:
+ case JSOP_TABLESWITCHX:
+ {
+ ptrdiff_t jmplen, off, off2;
+ jsint j, n, low, high;
+ TableEntry *table, *tmp;
+
+ sn = js_GetSrcNote(jp->script, pc);
+ LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
+ len = js_GetSrcNoteOffset(sn, 0);
+ jmplen = (op == JSOP_TABLESWITCH) ? JUMP_OFFSET_LEN
+ : JUMPX_OFFSET_LEN;
+ pc2 = pc;
+ off = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+ low = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+
+ n = high - low + 1;
+ if (n == 0) {
+ table = NULL;
+ j = 0;
+ ok = JS_TRUE;
+ } else {
+ table = (TableEntry *)
+ JS_malloc(cx, (size_t)n * sizeof *table);
+ if (!table)
+ return NULL;
+ for (i = j = 0; i < n; i++) {
+ table[j].label = NULL;
+ off2 = GetJumpOffset(pc, pc2);
+ if (off2) {
+ sn = js_GetSrcNote(jp->script, pc2);
+ if (sn) {
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_LABEL);
+ GET_SOURCE_NOTE_ATOM(sn, table[j].label);
+ }
+ table[j].key = INT_TO_JSVAL(low + i);
+ table[j].offset = off2;
+ table[j].order = j;
+ j++;
+ }
+ pc2 += jmplen;
+ }
+ tmp = (TableEntry *)
+ JS_malloc(cx, (size_t)j * sizeof *table);
+ if (tmp) {
+ ok = js_MergeSort(table, (size_t)j, sizeof(TableEntry),
+ CompareOffsets, NULL, tmp);
+ JS_free(cx, tmp);
+ } else {
+ ok = JS_FALSE;
+ }
+ }
+
+ if (ok) {
+ ok = DecompileSwitch(ss, table, (uintN)j, pc, len, off,
+ JS_FALSE);
+ }
+ JS_free(cx, table);
+ if (!ok)
+ return NULL;
+ todo = -2;
+ break;
+ }
+
+ case JSOP_LOOKUPSWITCH:
+ case JSOP_LOOKUPSWITCHX:
+ {
+ ptrdiff_t jmplen, off, off2;
+ jsatomid npairs, k;
+ TableEntry *table;
+
+ sn = js_GetSrcNote(jp->script, pc);
+ LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
+ len = js_GetSrcNoteOffset(sn, 0);
+ jmplen = (op == JSOP_LOOKUPSWITCH) ? JUMP_OFFSET_LEN
+ : JUMPX_OFFSET_LEN;
+ pc2 = pc;
+ off = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+ npairs = GET_UINT16(pc2);
+ pc2 += UINT16_LEN;
+
+ table = (TableEntry *)
+ JS_malloc(cx, (size_t)npairs * sizeof *table);
+ if (!table)
+ return NULL;
+ for (k = 0; k < npairs; k++) {
+ sn = js_GetSrcNote(jp->script, pc2);
+ if (sn) {
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_LABEL);
+ GET_SOURCE_NOTE_ATOM(sn, table[k].label);
+ } else {
+ table[k].label = NULL;
+ }
+ JS_GET_SCRIPT_ATOM(jp->script, GET_INDEX(pc2), atom);
+ pc2 += INDEX_LEN;
+ off2 = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+ table[k].key = ATOM_KEY(atom);
+ table[k].offset = off2;
+ }
+
+ ok = DecompileSwitch(ss, table, (uintN)npairs, pc, len, off,
+ JS_FALSE);
+ JS_free(cx, table);
+ if (!ok)
+ return NULL;
+ todo = -2;
+ break;
+ }
+
+ case JSOP_CONDSWITCH:
+ {
+ ptrdiff_t off, off2, caseOff;
+ jsint ncases;
+ TableEntry *table;
+
+ sn = js_GetSrcNote(jp->script, pc);
+ LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
+ len = js_GetSrcNoteOffset(sn, 0);
+ off = js_GetSrcNoteOffset(sn, 1);
+
+ /*
+ * Count the cases using offsets from switch to first case,
+ * and case to case, stored in srcnote immediates.
+ */
+ pc2 = pc;
+ off2 = off;
+ for (ncases = 0; off2 != 0; ncases++) {
+ pc2 += off2;
+ LOCAL_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT ||
+ *pc2 == JSOP_CASEX || *pc2 == JSOP_DEFAULTX);
+ if (*pc2 == JSOP_DEFAULT || *pc2 == JSOP_DEFAULTX) {
+ /* End of cases, but count default as a case. */
+ off2 = 0;
+ } else {
+ sn = js_GetSrcNote(jp->script, pc2);
+ LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_PCDELTA);
+ off2 = js_GetSrcNoteOffset(sn, 0);
+ }
+ }
+
+ /*
+ * Allocate table and rescan the cases using their srcnotes,
+ * stashing each case's delta from switch top in table[i].key,
+ * and the distance to its statements in table[i].offset.
+ */
+ table = (TableEntry *)
+ JS_malloc(cx, (size_t)ncases * sizeof *table);
+ if (!table)
+ return NULL;
+ pc2 = pc;
+ off2 = off;
+ for (i = 0; i < ncases; i++) {
+ pc2 += off2;
+ LOCAL_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT ||
+ *pc2 == JSOP_CASEX || *pc2 == JSOP_DEFAULTX);
+ caseOff = pc2 - pc;
+ table[i].key = INT_TO_JSVAL((jsint) caseOff);
+ table[i].offset = caseOff + GetJumpOffset(pc2, pc2);
+ if (*pc2 == JSOP_CASE || *pc2 == JSOP_CASEX) {
+ sn = js_GetSrcNote(jp->script, pc2);
+ LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_PCDELTA);
+ off2 = js_GetSrcNoteOffset(sn, 0);
+ }
+ }
+
+ /*
+ * Find offset of default code by fetching the default offset
+ * from the end of table. JSOP_CONDSWITCH always has a default
+ * case at the end.
+ */
+ off = JSVAL_TO_INT(table[ncases-1].key);
+ pc2 = pc + off;
+ off += GetJumpOffset(pc2, pc2);
+
+ ok = DecompileSwitch(ss, table, (uintN)ncases, pc, len, off,
+ JS_TRUE);
+ JS_free(cx, table);
+ if (!ok)
+ return NULL;
+ todo = -2;
+ break;
+ }
+
+ case JSOP_CASE:
+ case JSOP_CASEX:
+ {
+ lval = POP_STR();
+ if (!lval)
+ return NULL;
+ js_printf(jp, "\tcase %s:\n", lval);
+ todo = -2;
+ break;
+ }
+
+ case JSOP_DEFFUN:
+ LOAD_FUNCTION(0);
+ todo = -2;
+ goto do_function;
+ break;
+
+ case JSOP_TRAP:
+ saveop = op = JS_GetTrapOpcode(cx, jp->script, pc);
+ *pc = op;
+ cs = &js_CodeSpec[op];
+ len = cs->length;
+ DECOMPILE_CODE(pc, len);
+ *pc = JSOP_TRAP;
+ todo = -2;
+ break;
+
+ case JSOP_HOLE:
+ todo = SprintPut(&ss->sprinter, "", 0);
+ break;
+
+ case JSOP_NEWARRAY:
+ {
+ ptrdiff_t off;
+ char *base, *from, *to;
+
+ /*
+ * All operands are stacked and ready for in-place formatting.
+ * We know that PAREN_SLOP is 3 here, and take advantage of it
+ * to avoid strdup'ing.
+ */
+ argc = GET_UINT24(pc);
+ LOCAL_ASSERT(ss->top >= (uintN) argc);
+ sn = js_GetSrcNote(jp->script, pc);
+ if (argc == 0) {
+ todo = Sprint(&ss->sprinter, "[%s]",
+ (sn && SN_TYPE(sn) == SRC_CONTINUE)
+ ? ", "
+ : "");
+ } else {
+ ss->top -= argc;
+ off = GetOff(ss, ss->top);
+ LOCAL_ASSERT(off >= PAREN_SLOP);
+ base = OFF2STR(&ss->sprinter, off);
+ to = base + 1;
+ i = 0;
+ for (;;) {
+ /* Move to the next string that had been stacked. */
+ from = OFF2STR(&ss->sprinter, off);
+ todo = strlen(from);
+ memmove(to, from, todo);
+ to += todo;
+ if (++i == argc &&
+ !(sn && SN_TYPE(sn) == SRC_CONTINUE)) {
+ break;
+ }
+ *to++ = ',';
+ *to++ = ' ';
+ off = GetOff(ss, ss->top + i);
+ }
+ LOCAL_ASSERT(to - base < ss->sprinter.offset - PAREN_SLOP);
+ *base = '[';
+ *to++ = ']';
+ *to = '\0';
+ ss->sprinter.offset = STR2OFF(&ss->sprinter, to);
+ todo = STR2OFF(&ss->sprinter, base);
+ }
+ break;
+ }
+
+ case JSOP_NEWINIT:
+ {
+ i = GET_INT8(pc);
+ LOCAL_ASSERT(i == JSProto_Array || i == JSProto_Object);
+
+ todo = ss->sprinter.offset;
+#if JS_HAS_SHARP_VARS
+ op = (JSOp)pc[len];
+ if (op == JSOP_DEFSHARP) {
+ pc += len;
+ cs = &js_CodeSpec[op];
+ len = cs->length;
+ if (Sprint(&ss->sprinter, "#%u=",
+ (unsigned) (jsint) GET_UINT16(pc)) < 0)
+ return NULL;
+ }
+#endif /* JS_HAS_SHARP_VARS */
+ if (i == JSProto_Array) {
+ ++ss->inArrayInit;
+ if (SprintCString(&ss->sprinter, "[") < 0)
+ return NULL;
+ } else {
+ if (SprintCString(&ss->sprinter, "{") < 0)
+ return NULL;
+ }
+ break;
+ }
+
+ case JSOP_ENDINIT:
+ {
+ JSBool inArray;
+
+ op = JSOP_NOP; /* turn off parens */
+ rval = POP_STR();
+ sn = js_GetSrcNote(jp->script, pc);
+
+ /* Skip any #n= prefix to find the opening bracket. */
+ for (xval = rval; *xval != '[' && *xval != '{'; xval++)
+ continue;
+ inArray = (*xval == '[');
+ if (inArray)
+ --ss->inArrayInit;
+ todo = Sprint(&ss->sprinter, "%s%s%c",
+ rval,
+ (sn && SN_TYPE(sn) == SRC_CONTINUE) ? ", " : "",
+ inArray ? ']' : '}');
+ break;
+ }
+
+ {
+ JSBool isFirst;
+ const char *maybeComma;
+
+ case JSOP_INITELEM:
+ isFirst = (ss->opcodes[ss->top - 3] == JSOP_NEWINIT);
+
+ /* Turn off most parens. */
+ op = JSOP_SETNAME;
+ rval = POP_STR();
+
+ /* Turn off all parens for xval and lval, which we control. */
+ op = JSOP_NOP;
+ xval = POP_STR();
+ lval = POP_STR();
+ sn = js_GetSrcNote(jp->script, pc);
+
+ if (sn && SN_TYPE(sn) == SRC_INITPROP) {
+ atom = NULL;
+ goto do_initprop;
+ }
+ maybeComma = isFirst ? "" : ", ";
+ todo = Sprint(&ss->sprinter, sss_format,
+ lval,
+ maybeComma,
+ rval);
+ break;
+
+ case JSOP_INITPROP:
+ LOAD_ATOM(0);
+ xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ (jschar)
+ (ATOM_IS_IDENTIFIER(atom) ? 0 : '\''));
+ if (!xval)
+ return NULL;
+ isFirst = (ss->opcodes[ss->top - 2] == JSOP_NEWINIT);
+ rval = POP_STR();
+ lval = POP_STR();
+ /* fall through */
+
+ do_initprop:
+ maybeComma = isFirst ? "" : ", ";
+#ifdef OLD_GETTER_SETTER
+ todo = Sprint(&ss->sprinter, "%s%s%s%s%s%s%s:%s",
+ lval,
+ maybeComma,
+ xval,
+ (lastop == JSOP_GETTER || lastop == JSOP_SETTER)
+ ? " " : "",
+ (lastop == JSOP_GETTER) ? js_getter_str :
+ (lastop == JSOP_SETTER) ? js_setter_str :
+ "",
+ rval);
+#else
+ if (lastop == JSOP_GETTER || lastop == JSOP_SETTER) {
+ if (!atom ||
+ !ATOM_IS_STRING(atom) ||
+ !ATOM_IS_IDENTIFIER(atom) ||
+ ATOM_IS_KEYWORD(atom) ||
+ (ss->opcodes[ss->top+1] != JSOP_ANONFUNOBJ &&
+ ss->opcodes[ss->top+1] != JSOP_NAMEDFUNOBJ)) {
+ todo = Sprint(&ss->sprinter, "%s%s%s %s: %s",
+ lval,
+ maybeComma,
+ xval,
+ (lastop == JSOP_GETTER) ? js_getter_str :
+ (lastop == JSOP_SETTER) ? js_setter_str :
+ "",
+ rval);
+ } else {
+ const char *end = rval + strlen(rval);
+
+ if (*rval == '(')
+ ++rval, --end;
+ LOCAL_ASSERT(strncmp(rval, js_function_str, 8) == 0);
+ LOCAL_ASSERT(rval[8] == ' ');
+ rval += 8 + 1;
+ LOCAL_ASSERT(*end ? *end == ')' : end[-1] == '}');
+ todo = Sprint(&ss->sprinter, "%s%s%s %s%s%.*s",
+ lval,
+ maybeComma,
+ (lastop == JSOP_GETTER)
+ ? js_get_str : js_set_str,
+ xval,
+ (rval[0] != '(') ? " " : "",
+ end - rval, rval);
+ }
+ } else {
+ todo = Sprint(&ss->sprinter, "%s%s%s: %s",
+ lval, maybeComma, xval, rval);
+ }
+#endif
+ break;
+ }
+
+#if JS_HAS_SHARP_VARS
+ case JSOP_DEFSHARP:
+ i = (jsint) GET_UINT16(pc);
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, "#%u=%s", (unsigned) i, rval);
+ break;
+
+ case JSOP_USESHARP:
+ i = (jsint) GET_UINT16(pc);
+ todo = Sprint(&ss->sprinter, "#%u#", (unsigned) i);
+ break;
+#endif /* JS_HAS_SHARP_VARS */
+
+#if JS_HAS_DEBUGGER_KEYWORD
+ case JSOP_DEBUGGER:
+ js_printf(jp, "\tdebugger;\n");
+ todo = -2;
+ break;
+#endif /* JS_HAS_DEBUGGER_KEYWORD */
+
+#if JS_HAS_XML_SUPPORT
+ case JSOP_STARTXML:
+ case JSOP_STARTXMLEXPR:
+ inXML = op == JSOP_STARTXML;
+ todo = -2;
+ break;
+
+ case JSOP_DEFXMLNS:
+ rval = POP_STR();
+ js_printf(jp, "\t%s %s %s = %s;\n",
+ js_default_str, js_xml_str, js_namespace_str, rval);
+ todo = -2;
+ break;
+
+ case JSOP_ANYNAME:
+ if (pc[JSOP_ANYNAME_LENGTH] == JSOP_TOATTRNAME) {
+ len += JSOP_TOATTRNAME_LENGTH;
+ todo = SprintPut(&ss->sprinter, "@*", 2);
+ } else {
+ todo = SprintPut(&ss->sprinter, "*", 1);
+ }
+ break;
+
+ case JSOP_QNAMEPART:
+ LOAD_ATOM(0);
+ if (pc[JSOP_QNAMEPART_LENGTH] == JSOP_TOATTRNAME) {
+ saveop = JSOP_TOATTRNAME;
+ len += JSOP_TOATTRNAME_LENGTH;
+ lval = "@";
+ goto do_qname;
+ }
+ goto do_name;
+
+ case JSOP_QNAMECONST:
+ LOAD_ATOM(0);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s::%s", lval, rval);
+ break;
+
+ case JSOP_QNAME:
+ rval = POP_STR();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s::[%s]", lval, rval);
+ break;
+
+ case JSOP_TOATTRNAME:
+ op = JSOP_NOP; /* turn off parens */
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, "@[%s]", rval);
+ break;
+
+ case JSOP_TOATTRVAL:
+ todo = -2;
+ break;
+
+ case JSOP_ADDATTRNAME:
+ rval = POP_STR();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s %s", lval, rval);
+ /* This gets reset by all XML tag expressions. */
+ quoteAttr = JS_TRUE;
+ break;
+
+ case JSOP_ADDATTRVAL:
+ rval = POP_STR();
+ lval = POP_STR();
+ if (quoteAttr)
+ todo = Sprint(&ss->sprinter, "%s=\"%s\"", lval, rval);
+ else
+ todo = Sprint(&ss->sprinter, "%s=%s", lval, rval);
+ break;
+
+ case JSOP_BINDXMLNAME:
+ /* Leave the name stacked and push a dummy string. */
+ todo = Sprint(&ss->sprinter, "");
+ break;
+
+ case JSOP_SETXMLNAME:
+ /* Pop the r.h.s., the dummy string, and the name. */
+ rval = POP_STR();
+ (void) PopOff(ss, op);
+ lval = POP_STR();
+ goto do_setlval;
+
+ case JSOP_XMLELTEXPR:
+ case JSOP_XMLTAGEXPR:
+ todo = Sprint(&ss->sprinter, "{%s}", POP_STR());
+ inXML = JS_TRUE;
+ /* If we're an attribute value, we shouldn't quote this. */
+ quoteAttr = JS_FALSE;
+ break;
+
+ case JSOP_TOXMLLIST:
+ op = JSOP_NOP; /* turn off parens */
+ todo = Sprint(&ss->sprinter, "<>%s</>", POP_STR());
+ inXML = JS_FALSE;
+ break;
+
+ case JSOP_TOXML:
+ case JSOP_CALLXMLNAME:
+ case JSOP_XMLNAME:
+ case JSOP_FILTER:
+ /* These ops indicate the end of XML expressions. */
+ inXML = JS_FALSE;
+ todo = -2;
+ break;
+
+ case JSOP_ENDFILTER:
+ rval = POP_STR();
+ PROPAGATE_CALLNESS();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s.(%s)", lval, rval);
+ break;
+
+ case JSOP_DESCENDANTS:
+ rval = POP_STR();
+ PROPAGATE_CALLNESS();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s..%s", lval, rval);
+ break;
+
+ case JSOP_XMLOBJECT:
+ LOAD_OBJECT(0);
+ todo = Sprint(&ss->sprinter, "<xml address='%p'>", obj);
+ break;
+
+ case JSOP_XMLCDATA:
+ LOAD_ATOM(0);
+ todo = SprintPut(&ss->sprinter, "<![CDATA[", 9);
+ if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ DONT_ESCAPE))
+ return NULL;
+ SprintPut(&ss->sprinter, "]]>", 3);
+ break;
+
+ case JSOP_XMLCOMMENT:
+ LOAD_ATOM(0);
+ todo = SprintPut(&ss->sprinter, "<!--", 4);
+ if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ DONT_ESCAPE))
+ return NULL;
+ SprintPut(&ss->sprinter, "-->", 3);
+ break;
+
+ case JSOP_XMLPI:
+ LOAD_ATOM(0);
+ rval = JS_strdup(cx, POP_STR());
+ if (!rval)
+ return NULL;
+ todo = SprintPut(&ss->sprinter, "<?", 2);
+ ok = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0) &&
+ (*rval == '\0' ||
+ (SprintPut(&ss->sprinter, " ", 1) >= 0 &&
+ SprintCString(&ss->sprinter, rval)));
+ JS_free(cx, (char *)rval);
+ if (!ok)
+ return NULL;
+ SprintPut(&ss->sprinter, "?>", 2);
+ break;
+
+ case JSOP_GETFUNNS:
+ todo = SprintPut(&ss->sprinter, js_function_str, 8);
+ break;
+#endif /* JS_HAS_XML_SUPPORT */
+
+ default:
+ todo = -2;
+ break;
+ }
+ }
+
+ if (todo < 0) {
+ /* -2 means "don't push", -1 means reported error. */
+ if (todo == -1)
+ return NULL;
+ } else {
+ if (!PushOff(ss, todo, saveop))
+ return NULL;
+ }
+
+ if (cs->format & JOF_CALLOP) {
+ todo = Sprint(&ss->sprinter, "");
+ if (todo < 0 || !PushOff(ss, todo, saveop))
+ return NULL;
+ }
+
+ pc += len;
+ }
+
+/*
+ * Undefine local macros.
+ */
+#undef inXML
+#undef DECOMPILE_CODE
+#undef NEXT_OP
+#undef TOP_STR
+#undef POP_STR
+#undef POP_STR_PREC
+#undef LOCAL_ASSERT
+#undef ATOM_IS_IDENTIFIER
+#undef GET_QUOTE_AND_FMT
+#undef GET_ATOM_QUOTE_AND_FMT
+
+ return pc;
+}
+
+static JSBool
+DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len,
+ uintN pcdepth)
+{
+ uintN depth, i;
+ SprintStack ss;
+ JSContext *cx;
+ void *mark;
+ JSBool ok;
+ JSScript *oldscript;
+ jsbytecode *oldcode, *oldmain, *code;
+ char *last;
+
+ depth = StackDepth(script);
+ JS_ASSERT(pcdepth <= depth);
+
+ /* Initialize a sprinter for use with the offset stack. */
+ cx = jp->sprinter.context;
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ ok = InitSprintStack(cx, &ss, jp, depth);
+ if (!ok)
+ goto out;
+
+ /*
+ * If we are called from js_DecompileValueGenerator with a portion of
+ * script's bytecode that starts with a non-zero model stack depth given
+ * by pcdepth, attempt to initialize the missing string offsets in ss to
+ * |spindex| negative indexes from fp->sp for the activation fp in which
+ * the error arose.
+ *
+ * See js_DecompileValueGenerator for how its |spindex| parameter is used,
+ * and see also GetOff, which makes use of the ss.offsets[i] < -1 that are
+ * potentially stored below.
+ */
+ ss.top = pcdepth;
+ if (pcdepth != 0) {
+ for (i = 0; i < pcdepth; i++) {
+ ss.offsets[i] = -2 - (ptrdiff_t)i;
+ ss.opcodes[i] = *jp->pcstack[i];
+ }
+ }
+
+ /* Call recursive subroutine to do the hard work. */
+ oldscript = jp->script;
+ jp->script = script;
+ oldcode = jp->script->code;
+ oldmain = jp->script->main;
+ code = js_UntrapScriptCode(cx, jp->script);
+ if (code != oldcode) {
+ jp->script->code = code;
+ jp->script->main = code + (oldmain - oldcode);
+ pc = code + (pc - oldcode);
+ }
+
+ ok = Decompile(&ss, pc, len, JSOP_NOP) != NULL;
+ if (code != oldcode) {
+ JS_free(cx, jp->script->code);
+ jp->script->code = oldcode;
+ jp->script->main = oldmain;
+ }
+ jp->script = oldscript;
+
+ /* If the given code didn't empty the stack, do it now. */
+ if (ok && ss.top) {
+ do {
+ last = OFF2STR(&ss.sprinter, PopOff(&ss, JSOP_POP));
+ } while (ss.top > pcdepth);
+ js_printf(jp, "%s", last);
+ }
+
+out:
+ /* Free all temporary stuff allocated under this call. */
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return ok;
+}
+
+JSBool
+js_DecompileScript(JSPrinter *jp, JSScript *script)
+{
+ return DecompileCode(jp, script, script->code, (uintN)script->length, 0);
+}
+
+static const char native_code_str[] = "\t[native code]\n";
+
+JSBool
+js_DecompileFunctionBody(JSPrinter *jp)
+{
+ JSScript *script;
+
+ JS_ASSERT(jp->fun);
+ JS_ASSERT(!jp->script);
+ if (!FUN_INTERPRETED(jp->fun)) {
+ js_printf(jp, native_code_str);
+ return JS_TRUE;
+ }
+
+ script = jp->fun->u.i.script;
+ return DecompileCode(jp, script, script->code, (uintN)script->length, 0);
+}
+
+JSBool
+js_DecompileFunction(JSPrinter *jp)
+{
+ JSFunction *fun;
+ uintN i;
+ JSAtom *param;
+ jsbytecode *pc, *endpc;
+ ptrdiff_t len;
+ JSBool ok;
+
+ fun = jp->fun;
+ JS_ASSERT(fun);
+ JS_ASSERT(!jp->script);
+
+ /*
+ * If pretty, conform to ECMA-262 Edition 3, 15.3.4.2, by decompiling a
+ * FunctionDeclaration. Otherwise, check the JSFUN_LAMBDA flag and force
+ * an expression by parenthesizing.
+ */
+ if (jp->pretty) {
+ js_printf(jp, "\t");
+ } else {
+ if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
+ js_puts(jp, "(");
+ }
+ if (JSFUN_GETTER_TEST(fun->flags))
+ js_printf(jp, "%s ", js_getter_str);
+ else if (JSFUN_SETTER_TEST(fun->flags))
+ js_printf(jp, "%s ", js_setter_str);
+
+ js_printf(jp, "%s ", js_function_str);
+ if (fun->atom && !QuoteString(&jp->sprinter, ATOM_TO_STRING(fun->atom), 0))
+ return JS_FALSE;
+ js_puts(jp, "(");
+
+ if (!FUN_INTERPRETED(fun)) {
+ js_printf(jp, ") {\n");
+ jp->indent += 4;
+ js_printf(jp, native_code_str);
+ jp->indent -= 4;
+ js_printf(jp, "\t}");
+ } else {
+#ifdef JS_HAS_DESTRUCTURING
+ SprintStack ss;
+ void *mark;
+#endif
+
+ /* Print the parameters. */
+ pc = fun->u.i.script->main;
+ endpc = pc + fun->u.i.script->length;
+ ok = JS_TRUE;
+
+#ifdef JS_HAS_DESTRUCTURING
+ /* Skip JSOP_GENERATOR in case of destructuring parameters. */
+ if (*pc == JSOP_GENERATOR)
+ pc += JSOP_GENERATOR_LENGTH;
+
+ ss.printer = NULL;
+ jp->script = fun->u.i.script;
+ mark = JS_ARENA_MARK(&jp->sprinter.context->tempPool);
+#endif
+
+ for (i = 0; i < fun->nargs; i++) {
+ if (i > 0)
+ js_puts(jp, ", ");
+
+ param = GetArgOrVarAtom(jp, i);
+
+#if JS_HAS_DESTRUCTURING
+#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, JS_FALSE)
+
+ if (!param) {
+ ptrdiff_t todo;
+ const char *lval;
+
+ LOCAL_ASSERT(*pc == JSOP_GETARG);
+ pc += JSOP_GETARG_LENGTH;
+ LOCAL_ASSERT(*pc == JSOP_DUP);
+ if (!ss.printer) {
+ ok = InitSprintStack(jp->sprinter.context, &ss, jp,
+ StackDepth(fun->u.i.script));
+ if (!ok)
+ break;
+ }
+ pc = DecompileDestructuring(&ss, pc, endpc);
+ if (!pc) {
+ ok = JS_FALSE;
+ break;
+ }
+ LOCAL_ASSERT(*pc == JSOP_POP);
+ pc += JSOP_POP_LENGTH;
+ lval = PopStr(&ss, JSOP_NOP);
+ todo = SprintCString(&jp->sprinter, lval);
+ if (todo < 0) {
+ ok = JS_FALSE;
+ break;
+ }
+ continue;
+ }
+
+#undef LOCAL_ASSERT
+#endif
+
+ if (!QuoteString(&jp->sprinter, ATOM_TO_STRING(param), 0)) {
+ ok = JS_FALSE;
+ break;
+ }
+ }
+
+#ifdef JS_HAS_DESTRUCTURING
+ jp->script = NULL;
+ JS_ARENA_RELEASE(&jp->sprinter.context->tempPool, mark);
+#endif
+ if (!ok)
+ return JS_FALSE;
+ if (fun->flags & JSFUN_EXPR_CLOSURE) {
+ js_printf(jp, ") ");
+ } else {
+ js_printf(jp, ") {\n");
+ jp->indent += 4;
+ }
+
+ len = fun->u.i.script->code + fun->u.i.script->length - pc;
+ ok = DecompileCode(jp, fun->u.i.script, pc, (uintN)len, 0);
+ if (!ok)
+ return JS_FALSE;
+
+ if (!(fun->flags & JSFUN_EXPR_CLOSURE)) {
+ jp->indent -= 4;
+ js_printf(jp, "\t}");
+ }
+ }
+
+ if (!jp->pretty && !jp->grouped && (fun->flags & JSFUN_LAMBDA))
+ js_puts(jp, ")");
+
+ return JS_TRUE;
+}
+
+char *
+js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
+ JSString *fallback)
+{
+ JSStackFrame *fp;
+ jsbytecode *pc;
+ JSScript *script;
+ JSFrameRegs *regs;
+ intN pcdepth;
+ jsval *sp, *stackBase;
+ char *name;
+
+ JS_ASSERT(spindex < 0 ||
+ spindex == JSDVG_IGNORE_STACK ||
+ spindex == JSDVG_SEARCH_STACK);
+
+ for (fp = cx->fp; fp && !fp->script; fp = fp->down)
+ continue;
+ if (!fp || !fp->regs)
+ goto do_fallback;
+
+ script = fp->script;
+ regs = fp->regs;
+ pc = fp->imacpc ? fp->imacpc : regs->pc;
+ if (pc < script->main || script->code + script->length <= pc) {
+ JS_NOT_REACHED("bug");
+ goto do_fallback;
+ }
+
+ if (spindex != JSDVG_IGNORE_STACK) {
+ jsbytecode **pcstack;
+
+ /*
+ * Prepare computing pcstack containing pointers to opcodes that
+ * populated interpreter's stack with its current content.
+ */
+ pcstack = (jsbytecode **)
+ JS_malloc(cx, StackDepth(script) * sizeof *pcstack);
+ if (!pcstack)
+ return NULL;
+ pcdepth = ReconstructPCStack(cx, script, pc, pcstack);
+ if (pcdepth < 0)
+ goto release_pcstack;
+
+ if (spindex != JSDVG_SEARCH_STACK) {
+ JS_ASSERT(spindex < 0);
+ pcdepth += spindex;
+ if (pcdepth < 0)
+ goto release_pcstack;
+ pc = pcstack[pcdepth];
+ } else {
+ /*
+ * We search from fp->sp to base to find the most recently
+ * calculated value matching v under assumption that it is
+ * it that caused exception, see bug 328664.
+ */
+ stackBase = StackBase(fp);
+ sp = regs->sp;
+ do {
+ if (sp == stackBase) {
+ pcdepth = -1;
+ goto release_pcstack;
+ }
+ } while (*--sp != v);
+
+ if (sp >= stackBase + pcdepth) {
+ /*
+ * The value comes from a temporary slot that the interpreter
+ * uses for GC roots or when JSOP_APPLY extended the stack to
+ * fit the argument array elements. Assume that it is the
+ * current PC that caused the exception.
+ */
+ pc = fp->imacpc ? fp->imacpc : regs->pc;
+ } else {
+ pc = pcstack[sp - stackBase];
+ }
+ }
+
+ release_pcstack:
+ JS_free(cx, pcstack);
+ if (pcdepth < 0)
+ goto do_fallback;
+ }
+
+ {
+ jsbytecode* savepc = regs->pc;
+ jsbytecode* imacpc = fp->imacpc;
+ if (imacpc) {
+ regs->pc = imacpc;
+ fp->imacpc = NULL;
+ }
+ name = DecompileExpression(cx, script, fp->fun, pc);
+ if (imacpc) {
+ regs->pc = savepc;
+ fp->imacpc = imacpc;
+ }
+ }
+ if (name != FAILED_EXPRESSION_DECOMPILER)
+ return name;
+
+ do_fallback:
+ if (!fallback) {
+ fallback = js_ValueToSource(cx, v);
+ if (!fallback)
+ return NULL;
+ }
+ return js_DeflateString(cx, JSSTRING_CHARS(fallback),
+ JSSTRING_LENGTH(fallback));
+}
+
+static char *
+DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
+ jsbytecode *pc)
+{
+ jsbytecode *code, *oldcode, *oldmain;
+ JSOp op;
+ const JSCodeSpec *cs;
+ jsbytecode *begin, *end;
+ jssrcnote *sn;
+ ptrdiff_t len;
+ jsbytecode **pcstack;
+ intN pcdepth;
+ JSPrinter *jp;
+ char *name;
+
+ JS_ASSERT(script->main <= pc && pc < script->code + script->length);
+
+ pcstack = NULL;
+ oldcode = script->code;
+ oldmain = script->main;
+
+ MUST_FLOW_THROUGH("out");
+ code = js_UntrapScriptCode(cx, script);
+ if (code != oldcode) {
+ script->code = code;
+ script->main = code + (oldmain - oldcode);
+ pc = code + (pc - oldcode);
+ }
+
+ op = (JSOp) *pc;
+
+ /* None of these stack-writing ops generates novel values. */
+ JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX &&
+ op != JSOP_DUP && op != JSOP_DUP2);
+
+ /*
+ * |this| could convert to a very long object initialiser, so cite it by
+ * its keyword name instead.
+ */
+ if (op == JSOP_THIS) {
+ name = JS_strdup(cx, js_this_str);
+ goto out;
+ }
+
+ /*
+ * JSOP_BINDNAME is special: it generates a value, the base object of a
+ * reference. But if it is the generating op for a diagnostic produced by
+ * js_DecompileValueGenerator, the name being bound is irrelevant. Just
+ * fall back to the base object.
+ */
+ if (op == JSOP_BINDNAME) {
+ name = FAILED_EXPRESSION_DECOMPILER;
+ goto out;
+ }
+
+ /* NAME ops are self-contained, others require left or right context. */
+ cs = &js_CodeSpec[op];
+ begin = pc;
+ end = pc + cs->length;
+ switch (JOF_MODE(cs->format)) {
+ case JOF_PROP:
+ case JOF_ELEM:
+ case JOF_XMLNAME:
+ case 0:
+ sn = js_GetSrcNote(script, pc);
+ if (!sn) {
+ name = FAILED_EXPRESSION_DECOMPILER;
+ goto out;
+ }
+ switch (SN_TYPE(sn)) {
+ case SRC_PCBASE:
+ begin -= js_GetSrcNoteOffset(sn, 0);
+ break;
+ case SRC_PCDELTA:
+ end = begin + js_GetSrcNoteOffset(sn, 0);
+ begin += cs->length;
+ break;
+ default:
+ name = FAILED_EXPRESSION_DECOMPILER;
+ goto out;
+ }
+ break;
+ default:;
+ }
+ len = PTRDIFF(end, begin, jsbytecode);
+ if (len <= 0) {
+ name = FAILED_EXPRESSION_DECOMPILER;
+ goto out;
+ }
+
+ pcstack = (jsbytecode **)
+ JS_malloc(cx, StackDepth(script) * sizeof *pcstack);
+ if (!pcstack) {
+ name = NULL;
+ goto out;
+ }
+
+ MUST_FLOW_THROUGH("out");
+ pcdepth = ReconstructPCStack(cx, script, begin, pcstack);
+ if (pcdepth < 0) {
+ name = FAILED_EXPRESSION_DECOMPILER;
+ goto out;
+ }
+
+ name = NULL;
+ jp = JS_NEW_PRINTER(cx, "js_DecompileValueGenerator", fun, 0, JS_FALSE);
+ if (jp) {
+ jp->dvgfence = end;
+ jp->pcstack = pcstack;
+ if (DecompileCode(jp, script, begin, (uintN) len, (uintN) pcdepth)) {
+ name = (jp->sprinter.base) ? jp->sprinter.base : (char *) "";
+ name = JS_strdup(cx, name);
+ }
+ js_DestroyPrinter(jp);
+ }
+
+ out:
+ if (code != oldcode) {
+ JS_free(cx, script->code);
+ script->code = oldcode;
+ script->main = oldmain;
+ }
+
+ JS_free(cx, pcstack);
+ return name;
+}
+
+uintN
+js_ReconstructStackDepth(JSContext *cx, JSScript *script, jsbytecode *pc)
+{
+ return ReconstructPCStack(cx, script, pc, NULL);
+}
+
+static intN
+ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
+ jsbytecode **pcstack)
+{
+ intN pcdepth, nuses, ndefs;
+ jsbytecode *pc;
+ JSOp op;
+ const JSCodeSpec *cs;
+ ptrdiff_t oplen;
+ jssrcnote *sn;
+ intN i;
+
+#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, -1);
+
+ /*
+ * Walk forward from script->main and compute the stack depth and stack of
+ * operand-generating opcode PCs in pcstack.
+ *
+ * FIXME: Code to compute oplen copied from js_Disassemble1 and reduced.
+ * FIXME: Optimize to use last empty-stack sequence point.
+ */
+ LOCAL_ASSERT(script->main <= target && target < script->code + script->length);
+ pcdepth = 0;
+ for (pc = script->main; pc < target; pc += oplen) {
+ op = (JSOp) *pc;
+ if (op == JSOP_TRAP)
+ op = JS_GetTrapOpcode(cx, script, pc);
+ cs = &js_CodeSpec[op];
+ oplen = cs->length;
+ if (oplen < 0)
+ oplen = js_GetVariableBytecodeLength(pc);
+
+ /*
+ * A (C ? T : E) expression requires skipping either T (if target is in
+ * E) or both T and E (if target is after the whole expression) before
+ * adjusting pcdepth based on the JSOP_IFEQ or JSOP_IFEQX at pc that
+ * tests condition C. We know that the stack depth can't change from
+ * what it was with C on top of stack.
+ */
+ sn = js_GetSrcNote(script, pc);
+ if (sn && SN_TYPE(sn) == SRC_COND) {
+ ptrdiff_t jmpoff, jmplen;
+
+ jmpoff = js_GetSrcNoteOffset(sn, 0);
+ if (pc + jmpoff < target) {
+ pc += jmpoff;
+ op = (JSOp) *pc;
+ JS_ASSERT(op == JSOP_GOTO || op == JSOP_GOTOX);
+ cs = &js_CodeSpec[op];
+ oplen = cs->length;
+ JS_ASSERT(oplen > 0);
+ jmplen = GetJumpOffset(pc, pc);
+ if (pc + jmplen < target) {
+ oplen = (uintN) jmplen;
+ continue;
+ }
+
+ /*
+ * Ok, target lies in E. Manually pop C off the model stack,
+ * since we have moved beyond the IFEQ now.
+ */
+ --pcdepth;
+ LOCAL_ASSERT(pcdepth >= 0);
+ }
+ }
+
+ if (sn && SN_TYPE(sn) == SRC_HIDDEN)
+ continue;
+
+ nuses = cs->nuses;
+ if (nuses < 0)
+ nuses = js_GetVariableStackUseLength(op, pc);
+
+ ndefs = cs->ndefs;
+ if (ndefs < 0) {
+ JSObject *obj;
+
+ JS_ASSERT(op == JSOP_ENTERBLOCK);
+ GET_OBJECT_FROM_BYTECODE(script, pc, 0, obj);
+ JS_ASSERT(OBJ_BLOCK_DEPTH(cx, obj) == pcdepth);
+ ndefs = OBJ_BLOCK_COUNT(cx, obj);
+ }
+
+ pcdepth -= nuses;
+ LOCAL_ASSERT(pcdepth >= 0);
+ LOCAL_ASSERT((uintN)(pcdepth + ndefs) <= StackDepth(script));
+
+ /*
+ * Fill the slots that the opcode defines withs its pc unless it just
+ * reshuffle the stack. In the latter case we want to preserve the
+ * opcode that generated the original value.
+ */
+ switch (op) {
+ default:
+ if (pcstack) {
+ for (i = 0; i != ndefs; ++i)
+ pcstack[pcdepth + i] = pc;
+ }
+ break;
+
+ case JSOP_CASE:
+ case JSOP_CASEX:
+ /* Keep the switch value. */
+ JS_ASSERT(ndefs == 1);
+ break;
+
+ case JSOP_DUP:
+ JS_ASSERT(ndefs == 2);
+ if (pcstack)
+ pcstack[pcdepth + 1] = pcstack[pcdepth];
+ break;
+
+ case JSOP_DUP2:
+ JS_ASSERT(ndefs == 4);
+ if (pcstack) {
+ pcstack[pcdepth + 2] = pcstack[pcdepth];
+ pcstack[pcdepth + 3] = pcstack[pcdepth + 1];
+ }
+ break;
+ }
+ pcdepth += ndefs;
+ }
+ LOCAL_ASSERT(pc == target);
+ return pcdepth;
+
+#undef LOCAL_ASSERT
+}
+
+#undef LOCAL_ASSERT_RV
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.h b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.h
new file mode 100644
index 0000000..6ce8a40
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.h
@@ -0,0 +1,404 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsopcode_h___
+#define jsopcode_h___
+/*
+ * JS bytecode definitions.
+ */
+#include <stddef.h>
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsutil.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * JS operation bytecodes.
+ */
+typedef enum JSOp {
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ op = val,
+#include "jsopcode.tbl"
+#undef OPDEF
+ JSOP_LIMIT
+} JSOp;
+
+/*
+ * JS bytecode formats.
+ */
+#define JOF_BYTE 0 /* single bytecode, no immediates */
+#define JOF_JUMP 1 /* signed 16-bit jump offset immediate */
+#define JOF_ATOM 2 /* unsigned 16-bit constant pool index */
+#define JOF_UINT16 3 /* unsigned 16-bit immediate operand */
+#define JOF_TABLESWITCH 4 /* table switch */
+#define JOF_LOOKUPSWITCH 5 /* lookup switch */
+#define JOF_QARG 6 /* quickened get/set function argument ops */
+#define JOF_LOCAL 7 /* var or block-local variable */
+#define JOF_SLOTATOM 8 /* uint16 slot index + constant pool index */
+#define JOF_JUMPX 9 /* signed 32-bit jump offset immediate */
+#define JOF_TABLESWITCHX 10 /* extended (32-bit offset) table switch */
+#define JOF_LOOKUPSWITCHX 11 /* extended (32-bit offset) lookup switch */
+#define JOF_UINT24 12 /* extended unsigned 24-bit literal (index) */
+#define JOF_UINT8 13 /* uint8 immediate, e.g. top 8 bits of 24-bit
+ atom index */
+#define JOF_INT32 14 /* int32 immediate operand */
+#define JOF_OBJECT 15 /* unsigned 16-bit object pool index */
+#define JOF_SLOTOBJECT 16 /* uint16 slot index + object pool index */
+#define JOF_REGEXP 17 /* unsigned 16-bit regexp pool index */
+#define JOF_INT8 18 /* int8 immediate operand */
+#define JOF_TYPEMASK 0x001f /* mask for above immediate types */
+
+#define JOF_NAME (1U<<5) /* name operation */
+#define JOF_PROP (2U<<5) /* obj.prop operation */
+#define JOF_ELEM (3U<<5) /* obj[index] operation */
+#define JOF_XMLNAME (4U<<5) /* XML name: *, a::b, @a, @a::b, etc. */
+#define JOF_VARPROP (5U<<5) /* x.prop for this, arg, var, or local x */
+#define JOF_MODEMASK (7U<<5) /* mask for above addressing modes */
+#define JOF_SET (1U<<8) /* set (i.e., assignment) operation */
+#define JOF_DEL (1U<<9) /* delete operation */
+#define JOF_DEC (1U<<10) /* decrement (--, not ++) opcode */
+#define JOF_INC (2U<<10) /* increment (++, not --) opcode */
+#define JOF_INCDEC (3U<<10) /* increment or decrement opcode */
+#define JOF_POST (1U<<12) /* postorder increment or decrement */
+#define JOF_FOR (1U<<13) /* for-in property op (akin to JOF_SET) */
+#define JOF_ASSIGNING JOF_SET /* hint for JSClass.resolve, used for ops
+ that do simplex assignment */
+#define JOF_DETECTING (1U<<14) /* object detection for JSNewResolveOp */
+#define JOF_BACKPATCH (1U<<15) /* backpatch placeholder during codegen */
+#define JOF_LEFTASSOC (1U<<16) /* left-associative operator */
+#define JOF_DECLARING (1U<<17) /* var, const, or function declaration op */
+#define JOF_INDEXBASE (1U<<18) /* atom segment base setting prefix op */
+#define JOF_CALLOP (1U<<19) /* call operation that pushes function and
+ this */
+#define JOF_PARENHEAD (1U<<20) /* opcode consumes value of expression in
+ parenthesized statement head */
+#define JOF_INVOKE (1U<<21) /* JSOP_CALL, JSOP_NEW, JSOP_EVAL */
+#define JOF_TMPSLOT (1U<<22) /* interpreter uses extra temporary slot
+ to root intermediate objects besides
+ the slots opcode uses */
+#define JOF_TMPSLOT2 (2U<<22) /* interpreter uses extra 2 temporary slot
+ besides the slots opcode uses */
+#define JOF_TMPSLOT_SHIFT 22
+#define JOF_TMPSLOT_MASK (JS_BITMASK(2) << JOF_TMPSLOT_SHIFT)
+
+/* Shorthands for type from format and type from opcode. */
+#define JOF_TYPE(fmt) ((fmt) & JOF_TYPEMASK)
+#define JOF_OPTYPE(op) JOF_TYPE(js_CodeSpec[op].format)
+
+/* Shorthands for mode from format and mode from opcode. */
+#define JOF_MODE(fmt) ((fmt) & JOF_MODEMASK)
+#define JOF_OPMODE(op) JOF_MODE(js_CodeSpec[op].format)
+
+#define JOF_TYPE_IS_EXTENDED_JUMP(t) \
+ ((unsigned)((t) - JOF_JUMPX) <= (unsigned)(JOF_LOOKUPSWITCHX - JOF_JUMPX))
+
+/*
+ * Immediate operand getters, setters, and bounds.
+ */
+
+/* Common uint16 immediate format helpers. */
+#define UINT16_LEN 2
+#define UINT16_HI(i) ((jsbytecode)((i) >> 8))
+#define UINT16_LO(i) ((jsbytecode)(i))
+#define GET_UINT16(pc) ((uintN)(((pc)[1] << 8) | (pc)[2]))
+#define SET_UINT16(pc,i) ((pc)[1] = UINT16_HI(i), (pc)[2] = UINT16_LO(i))
+#define UINT16_LIMIT ((uintN)1 << 16)
+
+/* Short (2-byte signed offset) relative jump macros. */
+#define JUMP_OFFSET_LEN 2
+#define JUMP_OFFSET_HI(off) ((jsbytecode)((off) >> 8))
+#define JUMP_OFFSET_LO(off) ((jsbytecode)(off))
+#define GET_JUMP_OFFSET(pc) ((int16)GET_UINT16(pc))
+#define SET_JUMP_OFFSET(pc,off) ((pc)[1] = JUMP_OFFSET_HI(off), \
+ (pc)[2] = JUMP_OFFSET_LO(off))
+#define JUMP_OFFSET_MIN ((int16)0x8000)
+#define JUMP_OFFSET_MAX ((int16)0x7fff)
+
+/*
+ * When a short jump won't hold a relative offset, its 2-byte immediate offset
+ * operand is an unsigned index of a span-dependency record, maintained until
+ * code generation finishes -- after which some (but we hope not nearly all)
+ * span-dependent jumps must be extended (see OptimizeSpanDeps in jsemit.c).
+ *
+ * If the span-dependency record index overflows SPANDEP_INDEX_MAX, the jump
+ * offset will contain SPANDEP_INDEX_HUGE, indicating that the record must be
+ * found (via binary search) by its "before span-dependency optimization" pc
+ * offset (from script main entry point).
+ */
+#define GET_SPANDEP_INDEX(pc) ((uint16)GET_UINT16(pc))
+#define SET_SPANDEP_INDEX(pc,i) ((pc)[1] = JUMP_OFFSET_HI(i), \
+ (pc)[2] = JUMP_OFFSET_LO(i))
+#define SPANDEP_INDEX_MAX ((uint16)0xfffe)
+#define SPANDEP_INDEX_HUGE ((uint16)0xffff)
+
+/* Ultimately, if short jumps won't do, emit long (4-byte signed) offsets. */
+#define JUMPX_OFFSET_LEN 4
+#define JUMPX_OFFSET_B3(off) ((jsbytecode)((off) >> 24))
+#define JUMPX_OFFSET_B2(off) ((jsbytecode)((off) >> 16))
+#define JUMPX_OFFSET_B1(off) ((jsbytecode)((off) >> 8))
+#define JUMPX_OFFSET_B0(off) ((jsbytecode)(off))
+#define GET_JUMPX_OFFSET(pc) ((int32)(((pc)[1] << 24) | ((pc)[2] << 16) \
+ | ((pc)[3] << 8) | (pc)[4]))
+#define SET_JUMPX_OFFSET(pc,off)((pc)[1] = JUMPX_OFFSET_B3(off), \
+ (pc)[2] = JUMPX_OFFSET_B2(off), \
+ (pc)[3] = JUMPX_OFFSET_B1(off), \
+ (pc)[4] = JUMPX_OFFSET_B0(off))
+#define JUMPX_OFFSET_MIN ((int32)0x80000000)
+#define JUMPX_OFFSET_MAX ((int32)0x7fffffff)
+
+/*
+ * A literal is indexed by a per-script atom or object maps. Most scripts
+ * have relatively few literals, so the standard JOF_ATOM, JOF_OBJECT and
+ * JOF_REGEXP formats specifies a fixed 16 bits of immediate operand index.
+ * A script with more than 64K literals must wrap the bytecode into
+ * JSOP_INDEXBASE and JSOP_RESETBASE pair.
+ */
+#define INDEX_LEN 2
+#define INDEX_HI(i) ((jsbytecode)((i) >> 8))
+#define INDEX_LO(i) ((jsbytecode)(i))
+#define GET_INDEX(pc) GET_UINT16(pc)
+#define SET_INDEX(pc,i) ((pc)[1] = INDEX_HI(i), (pc)[2] = INDEX_LO(i))
+
+#define GET_INDEXBASE(pc) (JS_ASSERT(*(pc) == JSOP_INDEXBASE), \
+ ((uintN)((pc)[1])) << 16)
+#define INDEXBASE_LEN 1
+
+#define UINT24_HI(i) ((jsbytecode)((i) >> 16))
+#define UINT24_MID(i) ((jsbytecode)((i) >> 8))
+#define UINT24_LO(i) ((jsbytecode)(i))
+#define GET_UINT24(pc) ((jsatomid)(((pc)[1] << 16) | \
+ ((pc)[2] << 8) | \
+ (pc)[3]))
+#define SET_UINT24(pc,i) ((pc)[1] = UINT24_HI(i), \
+ (pc)[2] = UINT24_MID(i), \
+ (pc)[3] = UINT24_LO(i))
+
+#define GET_INT8(pc) ((jsint)(int8)(pc)[1])
+
+#define GET_INT32(pc) ((jsint)(((uint32)((pc)[1]) << 24) | \
+ ((uint32)((pc)[2]) << 16) | \
+ ((uint32)((pc)[3]) << 8) | \
+ (uint32)(pc)[4]))
+#define SET_INT32(pc,i) ((pc)[1] = (jsbytecode)((uint32)(i) >> 24), \
+ (pc)[2] = (jsbytecode)((uint32)(i) >> 16), \
+ (pc)[3] = (jsbytecode)((uint32)(i) >> 8), \
+ (pc)[4] = (jsbytecode)(uint32)(i))
+
+/* Index limit is determined by SN_3BYTE_OFFSET_FLAG, see jsemit.h. */
+#define INDEX_LIMIT_LOG2 23
+#define INDEX_LIMIT ((uint32)1 << INDEX_LIMIT_LOG2)
+
+JS_STATIC_ASSERT(sizeof(uint32) * JS_BITS_PER_BYTE >= INDEX_LIMIT_LOG2 + 1);
+
+/* Actual argument count operand format helpers. */
+#define ARGC_HI(argc) UINT16_HI(argc)
+#define ARGC_LO(argc) UINT16_LO(argc)
+#define GET_ARGC(pc) GET_UINT16(pc)
+#define ARGC_LIMIT UINT16_LIMIT
+
+/* Synonyms for quick JOF_QARG and JOF_LOCAL bytecodes. */
+#define GET_ARGNO(pc) GET_UINT16(pc)
+#define SET_ARGNO(pc,argno) SET_UINT16(pc,argno)
+#define ARGNO_LEN 2
+#define ARGNO_LIMIT UINT16_LIMIT
+
+#define GET_SLOTNO(pc) GET_UINT16(pc)
+#define SET_SLOTNO(pc,varno) SET_UINT16(pc,varno)
+#define SLOTNO_LEN 2
+#define SLOTNO_LIMIT UINT16_LIMIT
+
+struct JSCodeSpec {
+ int8 length; /* length including opcode byte */
+ int8 nuses; /* arity, -1 if variadic */
+ int8 ndefs; /* number of stack results */
+ uint8 prec; /* operator precedence */
+ uint32 format; /* immediate operand format */
+};
+
+extern const JSCodeSpec js_CodeSpec[];
+extern uintN js_NumCodeSpecs;
+extern const char *js_CodeName[];
+extern const char js_EscapeMap[];
+
+/*
+ * Return a GC'ed string containing the chars in str, with any non-printing
+ * chars or quotes (' or " as specified by the quote argument) escaped, and
+ * with the quote character at the beginning and end of the result string.
+ */
+extern JSString *
+js_QuoteString(JSContext *cx, JSString *str, jschar quote);
+
+/*
+ * JSPrinter operations, for printf style message formatting. The return
+ * value from js_GetPrinterOutput() is the printer's cumulative output, in
+ * a GC'ed string.
+ */
+
+#ifdef JS_ARENAMETER
+# define JS_NEW_PRINTER(cx, name, fun, indent, pretty) \
+ js_NewPrinter(cx, name, fun, indent, pretty)
+#else
+# define JS_NEW_PRINTER(cx, name, fun, indent, pretty) \
+ js_NewPrinter(cx, fun, indent, pretty)
+#endif
+
+extern JSPrinter *
+JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
+ uintN indent, JSBool pretty);
+
+extern void
+js_DestroyPrinter(JSPrinter *jp);
+
+extern JSString *
+js_GetPrinterOutput(JSPrinter *jp);
+
+extern int
+js_printf(JSPrinter *jp, const char *format, ...);
+
+extern JSBool
+js_puts(JSPrinter *jp, const char *s);
+
+/*
+ * Get index operand from the bytecode using a bytecode analysis to deduce the
+ * the index register. This function is infallible, in spite of taking cx as
+ * its first parameter; it uses only cx->runtime when calling JS_GetTrapOpcode.
+ * The GET_*_FROM_BYTECODE macros that call it pick up cx from their caller's
+ * lexical environments.
+ */
+uintN
+js_GetIndexFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc,
+ ptrdiff_t pcoff);
+
+/*
+ * A slower version of GET_ATOM when the caller does not want to maintain
+ * the index segment register itself.
+ */
+#define GET_ATOM_FROM_BYTECODE(script, pc, pcoff, atom) \
+ JS_BEGIN_MACRO \
+ uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \
+ JS_GET_SCRIPT_ATOM((script), index_, atom); \
+ JS_END_MACRO
+
+#define GET_OBJECT_FROM_BYTECODE(script, pc, pcoff, obj) \
+ JS_BEGIN_MACRO \
+ uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \
+ JS_GET_SCRIPT_OBJECT((script), index_, obj); \
+ JS_END_MACRO
+
+#define GET_FUNCTION_FROM_BYTECODE(script, pc, pcoff, fun) \
+ JS_BEGIN_MACRO \
+ uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \
+ JS_GET_SCRIPT_FUNCTION((script), index_, fun); \
+ JS_END_MACRO
+
+#define GET_REGEXP_FROM_BYTECODE(script, pc, pcoff, obj) \
+ JS_BEGIN_MACRO \
+ uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \
+ JS_GET_SCRIPT_REGEXP((script), index_, obj); \
+ JS_END_MACRO
+
+/*
+ * Get the length of variable-length bytecode like JSOP_TABLESWITCH.
+ */
+extern uintN
+js_GetVariableBytecodeLength(jsbytecode *pc);
+
+/*
+ * Find the number of stack slots used by a variadic opcode such as JSOP_CALL
+ * or JSOP_NEWARRAY (for such ops, JSCodeSpec.nuses is -1).
+ */
+extern uintN
+js_GetVariableStackUseLength(JSOp op, jsbytecode *pc);
+
+#ifdef DEBUG
+/*
+ * Disassemblers, for debugging only.
+ */
+#include <stdio.h>
+
+extern JS_FRIEND_API(JSBool)
+js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp);
+
+extern JS_FRIEND_API(uintN)
+js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
+ JSBool lines, FILE *fp);
+#endif /* DEBUG */
+
+/*
+ * Decompilers, for script, function, and expression pretty-printing.
+ */
+extern JSBool
+js_DecompileScript(JSPrinter *jp, JSScript *script);
+
+extern JSBool
+js_DecompileFunctionBody(JSPrinter *jp);
+
+extern JSBool
+js_DecompileFunction(JSPrinter *jp);
+
+/*
+ * Find the source expression that resulted in v, and return a newly allocated
+ * C-string containing it. Fall back on v's string conversion (fallback) if we
+ * can't find the bytecode that generated and pushed v on the operand stack.
+ *
+ * Search the current stack frame if spindex is JSDVG_SEARCH_STACK. Don't
+ * look for v on the stack if spindex is JSDVG_IGNORE_STACK. Otherwise,
+ * spindex is the negative index of v, measured from cx->fp->sp, or from a
+ * lower frame's sp if cx->fp is native.
+ *
+ * The caller must call JS_free on the result after a succsesful call.
+ */
+extern char *
+js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
+ JSString *fallback);
+
+#define JSDVG_IGNORE_STACK 0
+#define JSDVG_SEARCH_STACK 1
+
+/*
+ * Given bytecode address pc in script's main program code, return the operand
+ * stack depth just before (JSOp) *pc executes.
+ */
+extern uintN
+js_ReconstructStackDepth(JSContext *cx, JSScript *script, jsbytecode *pc);
+
+JS_END_EXTERN_C
+
+#endif /* jsopcode_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.tbl b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.tbl
new file mode 100644
index 0000000..6392209
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.tbl
@@ -0,0 +1,557 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=0 ft=C:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JavaScript operation bytecodes. If you need to allocate a bytecode, look
+ * for a name of the form JSOP_UNUSED* and claim it. Otherwise, always add at
+ * the end of the table.
+ *
+ * Includers must define an OPDEF macro of the following form:
+ *
+ * #define OPDEF(op,val,name,image,length,nuses,ndefs,prec,format) ...
+ *
+ * Selected arguments can be expanded in initializers. The op argument is
+ * expanded followed by comma in the JSOp enum (jsopcode.h), e.g. The value
+ * field must be dense for now, because jsopcode.c uses an OPDEF() expansion
+ * inside the js_CodeSpec[] initializer.
+ *
+ * Field Description
+ * op Bytecode name, which is the JSOp enumerator name
+ * value Bytecode value, which is the JSOp enumerator value
+ * name C string containing name for disassembler
+ * image C string containing "image" for pretty-printer, null if ugly
+ * length Number of bytes including any immediate operands
+ * nuses Number of stack slots consumed by bytecode, -1 if variadic
+ * ndefs Number of stack slots produced by bytecode, -1 if variadic
+ * prec Operator precedence, zero if not an operator
+ * format Bytecode plus immediate operand encoding format
+ *
+ * Precedence Operators Opcodes
+ * 1 yield w JSOP_YIELD
+ * 2 , JSOP_POP with SRC_PCDELTA, JSOP_RETURN
+ * 3 =, +=, etc. JSOP_SETNAME, etc. (all JOF_SET);
+ * let (...) ... and JSOP_LEAVEBLOCKEXPR
+ * 4 ?: JSOP_IFEQ, JSOP_IFEQX
+ * 5 || JSOP_OR, JSOP_ORX
+ * 6 && JSOP_AND, JSOP_ANDX
+ * 7 | JSOP_BITOR
+ * 8 ^ JSOP_BITXOR
+ * 9 & JSOP_BITAND
+ * 10 ==, !=, etc. JSOP_EQ, JSOP_NE, etc.
+ * 11 <, in, etc. JSOP_LT, JSOP_IN, etc.
+ * 12 <<, >>, >>> JSOP_LSH, JSOP_RSH, JSOP_URSH
+ * 13 +, -, etc. JSOP_ADD, JSOP_SUB, etc.
+ * 14 *, /, % JSOP_MUL, JSOP_DIV, JSOP_MOD
+ * 15 !, ~, delete, etc. JSOP_NOT, JSOP_BITNOT, JSOP_DEL*, etc.
+ * 16 3.14, 0, etc. JSOP_DOUBLE, JSOP_ZERO, etc.
+ * 17 new JSOP_NEW
+ * 18 x.y, f(), etc. JSOP_GETPROP, JSOP_CALL, etc.
+ * 19 x, null, JSOP_NAME, JSOP_NULL, etc.;
+ * function (...) ... and JSOP_ANONFUNOBJ, JSOP_NAMEDFUNOBJ
+ *
+ * The push-numeric-constant operators, JSOP_ZERO, JSOP_DOUBLE, etc., have
+ * lower precedence than the member operators emitted for the . operator, to
+ * cause the decompiler to parenthesize the . left operand, e.g. (0).foo.
+ * Otherwise the . could be taken as a decimal point.
+ *
+ * Let expressions are "primary" when viewed from the left, but they eat up ops
+ * to the right as if assignment expressions and therefore have precedence 3.
+ * This makes the decompiler retain the parentheses in (let (a=0) x) ? a : 0
+ * but omit the superfluous ones in (let (a=0) x), a.
+ *
+ * Yield expressions must be parenthesized even in comma-expressions and
+ * argument lists, so they have the lowest precedence.
+ *
+ * This file is best viewed with 128 columns:
+12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
+ */
+
+/* legend: op val name image len use def prec format */
+
+/* Longstanding JavaScript bytecodes. */
+OPDEF(JSOP_INTERRUPT, 0, "interrupt", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_PUSH, 1, "push", NULL, 1, 0, 1, 0, JOF_BYTE)
+OPDEF(JSOP_POPV, 2, "popv", NULL, 1, 1, 0, 2, JOF_BYTE)
+OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE|JOF_PARENHEAD)
+OPDEF(JSOP_LEAVEWITH, 4, "leavewith", NULL, 1, 1, 0, 0, JOF_BYTE)
+OPDEF(JSOP_RETURN, 5, "return", NULL, 1, 1, 0, 2, JOF_BYTE)
+OPDEF(JSOP_GOTO, 6, "goto", NULL, 3, 0, 0, 0, JOF_JUMP)
+OPDEF(JSOP_IFEQ, 7, "ifeq", NULL, 3, 1, 0, 4, JOF_JUMP|JOF_DETECTING)
+OPDEF(JSOP_IFNE, 8, "ifne", NULL, 3, 1, 0, 0, JOF_JUMP|JOF_PARENHEAD)
+
+/* Get the arguments object for the current, lightweight function activation. */
+OPDEF(JSOP_ARGUMENTS, 9, js_arguments_str, js_arguments_str, 1, 0, 1, 18, JOF_BYTE)
+
+/* ECMA-compliant for-in loop with argument or local loop control. */
+OPDEF(JSOP_FORARG, 10, "forarg", NULL, 3, 2, 2, 19, JOF_QARG|JOF_NAME|JOF_FOR)
+OPDEF(JSOP_FORLOCAL, 11, "forlocal", NULL, 3, 2, 2, 19, JOF_LOCAL|JOF_NAME|JOF_FOR)
+
+/* More longstanding bytecodes. */
+OPDEF(JSOP_DUP, 12, "dup", NULL, 1, 1, 2, 0, JOF_BYTE)
+OPDEF(JSOP_DUP2, 13, "dup2", NULL, 1, 2, 4, 0, JOF_BYTE)
+OPDEF(JSOP_SETCONST, 14, "setconst", NULL, 3, 1, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET)
+OPDEF(JSOP_BITOR, 15, "bitor", "|", 1, 2, 1, 7, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_BITXOR, 16, "bitxor", "^", 1, 2, 1, 8, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_BITAND, 17, "bitand", "&", 1, 2, 1, 9, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_EQ, 18, "eq", "==", 1, 2, 1, 10, JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING)
+OPDEF(JSOP_NE, 19, "ne", "!=", 1, 2, 1, 10, JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING)
+OPDEF(JSOP_LT, 20, "lt", "<", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_LE, 21, "le", "<=", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_GT, 22, "gt", ">", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_GE, 23, "ge", ">=", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_LSH, 24, "lsh", "<<", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_RSH, 25, "rsh", ">>", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_URSH, 26, "ursh", ">>>", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_ADD, 27, "add", "+", 1, 2, 1, 13, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_SUB, 28, "sub", "-", 1, 2, 1, 13, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_MUL, 29, "mul", "*", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_DIV, 30, "div", "/", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_MOD, 31, "mod", "%", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_NOT, 32, "not", "!", 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING)
+OPDEF(JSOP_BITNOT, 33, "bitnot", "~", 1, 1, 1, 15, JOF_BYTE)
+OPDEF(JSOP_NEG, 34, "neg", "- ", 1, 1, 1, 15, JOF_BYTE)
+OPDEF(JSOP_NEW, 35, js_new_str, NULL, 3, -1, 1, 17, JOF_UINT16|JOF_INVOKE)
+OPDEF(JSOP_DELNAME, 36, "delname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEL)
+OPDEF(JSOP_DELPROP, 37, "delprop", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_DEL)
+OPDEF(JSOP_DELELEM, 38, "delelem", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_DEL)
+OPDEF(JSOP_TYPEOF, 39, js_typeof_str,NULL, 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING)
+OPDEF(JSOP_VOID, 40, js_void_str, NULL, 1, 1, 1, 15, JOF_BYTE)
+
+OPDEF(JSOP_INCNAME, 41, "incname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT2)
+OPDEF(JSOP_INCPROP, 42, "incprop", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_INC|JOF_TMPSLOT2)
+OPDEF(JSOP_INCELEM, 43, "incelem", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_INC|JOF_TMPSLOT2)
+OPDEF(JSOP_DECNAME, 44, "decname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT2)
+OPDEF(JSOP_DECPROP, 45, "decprop", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_DEC|JOF_TMPSLOT2)
+OPDEF(JSOP_DECELEM, 46, "decelem", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_TMPSLOT2)
+OPDEF(JSOP_NAMEINC, 47, "nameinc", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_PROPINC, 48, "propinc", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_INC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_ELEMINC, 49, "eleminc", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_INC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_NAMEDEC, 50, "namedec", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_PROPDEC, 51, "propdec", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_DEC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_ELEMDEC, 52, "elemdec", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_POST|JOF_TMPSLOT2)
+
+OPDEF(JSOP_GETPROP, 53, "getprop", NULL, 3, 1, 1, 18, JOF_ATOM|JOF_PROP)
+OPDEF(JSOP_SETPROP, 54, "setprop", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_GETELEM, 55, "getelem", NULL, 1, 2, 1, 18, JOF_BYTE |JOF_ELEM|JOF_LEFTASSOC)
+OPDEF(JSOP_SETELEM, 56, "setelem", NULL, 1, 3, 1, 3, JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_CALLNAME, 57, "callname", NULL, 3, 0, 2, 19, JOF_ATOM|JOF_NAME|JOF_CALLOP)
+OPDEF(JSOP_CALL, 58, "call", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE)
+OPDEF(JSOP_NAME, 59, "name", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_NAME)
+OPDEF(JSOP_DOUBLE, 60, "double", NULL, 3, 0, 1, 16, JOF_ATOM)
+OPDEF(JSOP_STRING, 61, "string", NULL, 3, 0, 1, 19, JOF_ATOM)
+OPDEF(JSOP_ZERO, 62, "zero", "0", 1, 0, 1, 16, JOF_BYTE)
+OPDEF(JSOP_ONE, 63, "one", "1", 1, 0, 1, 16, JOF_BYTE)
+OPDEF(JSOP_NULL, 64, js_null_str, js_null_str, 1, 0, 1, 19, JOF_BYTE)
+OPDEF(JSOP_THIS, 65, js_this_str, js_this_str, 1, 0, 1, 19, JOF_BYTE)
+OPDEF(JSOP_FALSE, 66, js_false_str, js_false_str, 1, 0, 1, 19, JOF_BYTE)
+OPDEF(JSOP_TRUE, 67, js_true_str, js_true_str, 1, 0, 1, 19, JOF_BYTE)
+OPDEF(JSOP_OR, 68, "or", NULL, 3, 1, 0, 5, JOF_JUMP|JOF_DETECTING|JOF_LEFTASSOC)
+OPDEF(JSOP_AND, 69, "and", NULL, 3, 1, 0, 6, JOF_JUMP|JOF_DETECTING|JOF_LEFTASSOC)
+
+/* The switch bytecodes have variable length. */
+OPDEF(JSOP_TABLESWITCH, 70, "tableswitch", NULL, -1, 1, 0, 0, JOF_TABLESWITCH|JOF_DETECTING|JOF_PARENHEAD)
+OPDEF(JSOP_LOOKUPSWITCH, 71, "lookupswitch", NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCH|JOF_DETECTING|JOF_PARENHEAD)
+
+/* New, infallible/transitive identity ops. */
+OPDEF(JSOP_STRICTEQ, 72, "stricteq", "===", 1, 2, 1, 10, JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC)
+OPDEF(JSOP_STRICTNE, 73, "strictne", "!==", 1, 2, 1, 10, JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC)
+
+/* Variant of JSOP_NULL for default (global) |this| parameter pushing. */
+OPDEF(JSOP_NULLTHIS, 74, js_null_str, js_null_str, 1, 0, 1, 19, JOF_BYTE)
+
+/*
+ * JSOP_ITER sets up a for-in or for-each-in loop using the JSITER_* flag bits
+ * in this op's uint8 immediate operand. It replaces the top of stack object
+ * with an iterator for that object, and pushes a slot used by JSOP_NEXTITER.
+ *
+ * JSOP_NEXTITER stores the next iterated value in the top of stack slot which
+ * was allocated by JSOP_ITER and pushes true, or stores JSVAL_HOLE and pushes
+ * false. It is followed immediately by JSOP_IFNE{,X}.
+ *
+ * JSOP_ENDITER cleans up after the loop. It uses the slot above the iterator
+ * for temporary GC rooting.
+ */
+OPDEF(JSOP_ITER, 75, "iter", NULL, 2, 1, 2, 0, JOF_UINT8)
+OPDEF(JSOP_NEXTITER, 76, "nextiter", NULL, 1, 2, 3, 0, JOF_BYTE)
+OPDEF(JSOP_ENDITER, 77, "enditer", NULL, 1, 2, 0, 0, JOF_BYTE)
+
+OPDEF(JSOP_APPLY, 78, "apply", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE)
+OPDEF(JSOP_SWAP, 79, "swap", NULL, 1, 2, 2, 0, JOF_BYTE)
+
+/* Push object literal. */
+OPDEF(JSOP_OBJECT, 80, "object", NULL, 3, 0, 1, 19, JOF_OBJECT)
+
+/* Pop value and discard it. */
+OPDEF(JSOP_POP, 81, "pop", NULL, 1, 1, 0, 2, JOF_BYTE)
+
+/* Convert value to number, for unary +. */
+OPDEF(JSOP_POS, 82, "pos", "+ ", 1, 1, 1, 15, JOF_BYTE)
+
+/* Trap into debugger for breakpoint, etc. */
+OPDEF(JSOP_TRAP, 83, "trap", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/* Fast get/set ops for function arguments and local variables. */
+OPDEF(JSOP_GETARG, 84, "getarg", NULL, 3, 0, 1, 19, JOF_QARG |JOF_NAME)
+OPDEF(JSOP_SETARG, 85, "setarg", NULL, 3, 1, 1, 3, JOF_QARG |JOF_NAME|JOF_SET)
+OPDEF(JSOP_GETLOCAL, 86,"getlocal", NULL, 3, 0, 1, 19, JOF_LOCAL|JOF_NAME)
+OPDEF(JSOP_SETLOCAL, 87,"setlocal", NULL, 3, 1, 1, 3, JOF_LOCAL|JOF_NAME|JOF_SET|JOF_DETECTING)
+
+/* Push unsigned 16-bit int constant. */
+OPDEF(JSOP_UINT16, 88, "uint16", NULL, 3, 0, 1, 16, JOF_UINT16)
+
+/* Object and array literal support. */
+OPDEF(JSOP_NEWINIT, 89, "newinit", NULL, 2, 0, 1, 19, JOF_INT8)
+OPDEF(JSOP_ENDINIT, 90, "endinit", NULL, 1, 0, 0, 19, JOF_BYTE)
+OPDEF(JSOP_INITPROP, 91, "initprop", NULL, 3, 1, 0, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_INITELEM, 92, "initelem", NULL, 1, 2, 0, 3, JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_DEFSHARP, 93, "defsharp", NULL, 3, 0, 0, 0, JOF_UINT16)
+OPDEF(JSOP_USESHARP, 94, "usesharp", NULL, 3, 0, 1, 0, JOF_UINT16)
+
+/* Fast inc/dec ops for args and locals. */
+OPDEF(JSOP_INCARG, 95, "incarg", NULL, 3, 0, 1, 15, JOF_QARG |JOF_NAME|JOF_INC)
+OPDEF(JSOP_DECARG, 96, "decarg", NULL, 3, 0, 1, 15, JOF_QARG |JOF_NAME|JOF_DEC)
+OPDEF(JSOP_ARGINC, 97, "arginc", NULL, 3, 0, 1, 15, JOF_QARG |JOF_NAME|JOF_INC|JOF_POST)
+OPDEF(JSOP_ARGDEC, 98, "argdec", NULL, 3, 0, 1, 15, JOF_QARG |JOF_NAME|JOF_DEC|JOF_POST)
+
+OPDEF(JSOP_INCLOCAL, 99, "inclocal", NULL, 3, 0, 1, 15, JOF_LOCAL|JOF_NAME|JOF_INC)
+OPDEF(JSOP_DECLOCAL, 100,"declocal", NULL, 3, 0, 1, 15, JOF_LOCAL|JOF_NAME|JOF_DEC)
+OPDEF(JSOP_LOCALINC, 101,"localinc", NULL, 3, 0, 1, 15, JOF_LOCAL|JOF_NAME|JOF_INC|JOF_POST)
+OPDEF(JSOP_LOCALDEC, 102,"localdec", NULL, 3, 0, 1, 15, JOF_LOCAL|JOF_NAME|JOF_DEC|JOF_POST)
+
+OPDEF(JSOP_IMACOP, 103,"imacop", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/* ECMA-compliant for/in ops. */
+OPDEF(JSOP_FORNAME, 104,"forname", NULL, 3, 2, 2, 19, JOF_ATOM|JOF_NAME|JOF_FOR)
+OPDEF(JSOP_FORPROP, 105,"forprop", NULL, 3, 3, 2, 18, JOF_ATOM|JOF_PROP|JOF_FOR)
+OPDEF(JSOP_FORELEM, 106,"forelem", NULL, 1, 2, 3, 18, JOF_BYTE |JOF_ELEM|JOF_FOR)
+OPDEF(JSOP_POPN, 107,"popn", NULL, 3, -1, 0, 0, JOF_UINT16)
+
+/* ECMA-compliant assignment ops. */
+OPDEF(JSOP_BINDNAME, 108,"bindname", NULL, 3, 0, 1, 0, JOF_ATOM|JOF_NAME|JOF_SET)
+OPDEF(JSOP_SETNAME, 109,"setname", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING)
+
+/* Exception handling ops. */
+OPDEF(JSOP_THROW, 110,js_throw_str, NULL, 1, 1, 0, 0, JOF_BYTE)
+
+/* 'in' and 'instanceof' ops. */
+OPDEF(JSOP_IN, 111,js_in_str, js_in_str, 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC)
+OPDEF(JSOP_INSTANCEOF,112,js_instanceof_str,js_instanceof_str,1,2,1,11,JOF_BYTE|JOF_LEFTASSOC)
+
+/* debugger op */
+OPDEF(JSOP_DEBUGGER, 113,"debugger", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/* gosub/retsub for finally handling */
+OPDEF(JSOP_GOSUB, 114,"gosub", NULL, 3, 0, 0, 0, JOF_JUMP)
+OPDEF(JSOP_RETSUB, 115,"retsub", NULL, 1, 2, 0, 0, JOF_BYTE)
+
+/* More exception handling ops. */
+OPDEF(JSOP_EXCEPTION, 116,"exception", NULL, 1, 0, 1, 0, JOF_BYTE)
+
+/* Embedded lineno to speedup pc->line mapping. */
+OPDEF(JSOP_LINENO, 117,"lineno", NULL, 3, 0, 0, 0, JOF_UINT16)
+
+/*
+ * ECMA-compliant switch statement ops.
+ * CONDSWITCH is a decompilable NOP; CASE is ===, POP, jump if true, re-push
+ * lval if false; and DEFAULT is POP lval and GOTO.
+ */
+OPDEF(JSOP_CONDSWITCH,118,"condswitch", NULL, 1, 0, 0, 0, JOF_BYTE|JOF_PARENHEAD)
+OPDEF(JSOP_CASE, 119,"case", NULL, 3, 2, 1, 0, JOF_JUMP)
+OPDEF(JSOP_DEFAULT, 120,"default", NULL, 3, 1, 0, 0, JOF_JUMP)
+
+/*
+ * ECMA-compliant call to eval op
+ */
+OPDEF(JSOP_EVAL, 121,"eval", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE)
+
+/*
+ * ECMA-compliant helper for 'for (x[i] in o)' loops.
+ */
+OPDEF(JSOP_ENUMELEM, 122,"enumelem", NULL, 1, 3, 0, 3, JOF_BYTE |JOF_SET)
+
+/*
+ * Getter and setter prefix bytecodes. These modify the next bytecode, either
+ * an assignment or a property initializer code, which then defines a property
+ * getter or setter.
+ */
+OPDEF(JSOP_GETTER, 123,js_getter_str,NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_SETTER, 124,js_setter_str,NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Prolog bytecodes for defining function, var, and const names.
+ */
+OPDEF(JSOP_DEFFUN, 125,"deffun", NULL, 3, 0, 0, 0, JOF_OBJECT|JOF_DECLARING)
+OPDEF(JSOP_DEFCONST, 126,"defconst", NULL, 3, 0, 0, 0, JOF_ATOM|JOF_DECLARING)
+OPDEF(JSOP_DEFVAR, 127,"defvar", NULL, 3, 0, 0, 0, JOF_ATOM|JOF_DECLARING)
+
+/* Auto-clone (if needed due to re-parenting) and push an anonymous function. */
+OPDEF(JSOP_ANONFUNOBJ, 128, "anonfunobj", NULL, 3, 0, 1, 19, JOF_OBJECT)
+
+/* ECMA ed. 3 named function expression. */
+OPDEF(JSOP_NAMEDFUNOBJ, 129, "namedfunobj", NULL, 3, 0, 1, 19, JOF_OBJECT)
+
+/*
+ * Like JSOP_SETLOCAL, but specialized to avoid requiring JSOP_POP immediately
+ * after to throw away the exception value.
+ */
+OPDEF(JSOP_SETLOCALPOP, 130, "setlocalpop", NULL, 3, 1, 0, 3, JOF_LOCAL|JOF_NAME|JOF_SET)
+
+/* Parenthesization opcode to help the decompiler. */
+OPDEF(JSOP_UNUSED131, 131, "unused131", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Host object extension: given 'o.item(i) = j', the left-hand side compiles
+ * JSOP_SETCALL, rather than JSOP_CALL.
+ */
+OPDEF(JSOP_SETCALL, 132, "setcall", NULL, 3, -1, 2, 18, JOF_UINT16|JOF_SET)
+
+/*
+ * Exception handling no-op, for more economical byte-coding than SRC_TRYFIN
+ * srcnote-annotated JSOP_NOPs and to simply stack balance handling.
+ */
+OPDEF(JSOP_TRY, 133,"try", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_FINALLY, 134,"finally", NULL, 1, 0, 2, 0, JOF_BYTE)
+
+/*
+ * Generic nop for the decompiler.
+ */
+OPDEF(JSOP_NOP, 135,"nop", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Bytecodes that avoid making an arguments object in most cases:
+ * JSOP_ARGSUB gets arguments[i] from fp->argv, iff i is in [0, fp->argc-1].
+ * JSOP_ARGCNT returns fp->argc.
+ */
+OPDEF(JSOP_ARGSUB, 136,"argsub", NULL, 3, 0, 1, 18, JOF_QARG |JOF_NAME)
+OPDEF(JSOP_ARGCNT, 137,"argcnt", NULL, 1, 0, 1, 18, JOF_BYTE)
+
+/*
+ * Define a local function object as a local variable.
+ * The local variable's slot number is the first immediate two-byte operand.
+ * The function object's atom index is the second immediate operand.
+ */
+OPDEF(JSOP_DEFLOCALFUN, 138,"deflocalfun",NULL, 5, 0, 0, 0, JOF_SLOTOBJECT|JOF_DECLARING)
+
+/* Extended jumps. */
+OPDEF(JSOP_GOTOX, 139,"gotox", NULL, 5, 0, 0, 0, JOF_JUMPX)
+OPDEF(JSOP_IFEQX, 140,"ifeqx", NULL, 5, 1, 0, 4, JOF_JUMPX|JOF_DETECTING)
+OPDEF(JSOP_IFNEX, 141,"ifnex", NULL, 5, 1, 0, 0, JOF_JUMPX|JOF_PARENHEAD)
+OPDEF(JSOP_ORX, 142,"orx", NULL, 5, 1, 0, 5, JOF_JUMPX|JOF_DETECTING)
+OPDEF(JSOP_ANDX, 143,"andx", NULL, 5, 1, 0, 6, JOF_JUMPX|JOF_DETECTING)
+OPDEF(JSOP_GOSUBX, 144,"gosubx", NULL, 5, 0, 0, 0, JOF_JUMPX)
+OPDEF(JSOP_CASEX, 145,"casex", NULL, 5, 2, 1, 0, JOF_JUMPX)
+OPDEF(JSOP_DEFAULTX, 146,"defaultx", NULL, 5, 1, 0, 0, JOF_JUMPX)
+OPDEF(JSOP_TABLESWITCHX, 147,"tableswitchx",NULL, -1, 1, 0, 0, JOF_TABLESWITCHX|JOF_DETECTING|JOF_PARENHEAD)
+OPDEF(JSOP_LOOKUPSWITCHX, 148,"lookupswitchx",NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCHX|JOF_DETECTING|JOF_PARENHEAD)
+
+/* Placeholders for a real jump opcode set during backpatch chain fixup. */
+OPDEF(JSOP_BACKPATCH, 149,"backpatch",NULL, 3, 0, 0, 0, JOF_JUMP|JOF_BACKPATCH)
+OPDEF(JSOP_BACKPATCH_POP, 150,"backpatch_pop",NULL, 3, 1, 0, 0, JOF_JUMP|JOF_BACKPATCH)
+
+/* Set pending exception from the stack, to trigger rethrow. */
+OPDEF(JSOP_THROWING, 151,"throwing", NULL, 1, 1, 0, 0, JOF_BYTE)
+
+/* Set and get return value pseudo-register in stack frame. */
+OPDEF(JSOP_SETRVAL, 152,"setrval", NULL, 1, 1, 0, 2, JOF_BYTE)
+OPDEF(JSOP_RETRVAL, 153,"retrval", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/* Optimized global variable ops (we don't bother doing a JSOP_FORGVAR op). */
+OPDEF(JSOP_GETGVAR, 154,"getgvar", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_NAME)
+OPDEF(JSOP_SETGVAR, 155,"setgvar", NULL, 3, 1, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_INCGVAR, 156,"incgvar", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT2)
+OPDEF(JSOP_DECGVAR, 157,"decgvar", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT2)
+OPDEF(JSOP_GVARINC, 158,"gvarinc", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_GVARDEC, 159,"gvardec", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT2)
+
+/* Regular expression literal requiring special "fork on exec" handling. */
+OPDEF(JSOP_REGEXP, 160,"regexp", NULL, 3, 0, 1, 19, JOF_REGEXP)
+
+/* XML (ECMA-357, a.k.a. "E4X") support. */
+OPDEF(JSOP_DEFXMLNS, 161,"defxmlns", NULL, 1, 1, 0, 0, JOF_BYTE)
+OPDEF(JSOP_ANYNAME, 162,"anyname", NULL, 1, 0, 1, 19, JOF_BYTE|JOF_XMLNAME)
+OPDEF(JSOP_QNAMEPART, 163,"qnamepart", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_XMLNAME)
+OPDEF(JSOP_QNAMECONST, 164,"qnameconst", NULL, 3, 1, 1, 19, JOF_ATOM|JOF_XMLNAME)
+OPDEF(JSOP_QNAME, 165,"qname", NULL, 1, 2, 1, 0, JOF_BYTE|JOF_XMLNAME)
+OPDEF(JSOP_TOATTRNAME, 166,"toattrname", NULL, 1, 1, 1, 19, JOF_BYTE|JOF_XMLNAME)
+OPDEF(JSOP_TOATTRVAL, 167,"toattrval", NULL, 1, 1, 1, 19, JOF_BYTE)
+OPDEF(JSOP_ADDATTRNAME, 168,"addattrname",NULL, 1, 2, 1, 13, JOF_BYTE)
+OPDEF(JSOP_ADDATTRVAL, 169,"addattrval", NULL, 1, 2, 1, 13, JOF_BYTE)
+OPDEF(JSOP_BINDXMLNAME, 170,"bindxmlname",NULL, 1, 1, 2, 3, JOF_BYTE|JOF_SET)
+OPDEF(JSOP_SETXMLNAME, 171,"setxmlname", NULL, 1, 3, 1, 3, JOF_BYTE|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_XMLNAME, 172,"xmlname", NULL, 1, 1, 1, 19, JOF_BYTE)
+OPDEF(JSOP_DESCENDANTS, 173,"descendants",NULL, 1, 2, 1, 18, JOF_BYTE)
+OPDEF(JSOP_FILTER, 174,"filter", NULL, 3, 1, 1, 0, JOF_JUMP)
+OPDEF(JSOP_ENDFILTER, 175,"endfilter", NULL, 3, 2, 1, 18, JOF_JUMP)
+OPDEF(JSOP_TOXML, 176,"toxml", NULL, 1, 1, 1, 19, JOF_BYTE)
+OPDEF(JSOP_TOXMLLIST, 177,"toxmllist", NULL, 1, 1, 1, 19, JOF_BYTE)
+OPDEF(JSOP_XMLTAGEXPR, 178,"xmltagexpr", NULL, 1, 1, 1, 0, JOF_BYTE)
+OPDEF(JSOP_XMLELTEXPR, 179,"xmleltexpr", NULL, 1, 1, 1, 0, JOF_BYTE)
+OPDEF(JSOP_XMLOBJECT, 180,"xmlobject", NULL, 3, 0, 1, 19, JOF_OBJECT)
+OPDEF(JSOP_XMLCDATA, 181,"xmlcdata", NULL, 3, 0, 1, 19, JOF_ATOM)
+OPDEF(JSOP_XMLCOMMENT, 182,"xmlcomment", NULL, 3, 0, 1, 19, JOF_ATOM)
+OPDEF(JSOP_XMLPI, 183,"xmlpi", NULL, 3, 1, 1, 19, JOF_ATOM)
+OPDEF(JSOP_CALLPROP, 184,"callprop", NULL, 3, 1, 2, 18, JOF_ATOM|JOF_PROP|JOF_CALLOP)
+OPDEF(JSOP_GETFUNNS, 185,"getfunns", NULL, 1, 0, 1, 19, JOF_BYTE)
+
+/*
+ * Get a display (free) variable from the closure's reserved slots.
+ */
+OPDEF(JSOP_GETUPVAR, 186,"getupvar", NULL, 3, 0, 1, 19, JOF_UINT16|JOF_NAME)
+
+OPDEF(JSOP_DELDESC, 187,"deldesc", NULL, 1, 2, 1, 15, JOF_BYTE|JOF_ELEM|JOF_DEL)
+
+/*
+ * Opcode to hold 24-bit immediate integer operands.
+ */
+OPDEF(JSOP_UINT24, 188,"uint24", NULL, 4, 0, 1, 16, JOF_UINT24)
+
+/*
+ * Opcodes to allow 24-bit atom or object indexes. Whenever an index exceeds
+ * the 16-bit limit, the index-accessing bytecode must be bracketed by
+ * JSOP_INDEXBASE and JSOP_RESETBASE to provide the upper bits of the index.
+ * See jsemit.c, EmitIndexOp.
+ */
+OPDEF(JSOP_INDEXBASE, 189,"atombase", NULL, 2, 0, 0, 0, JOF_UINT8|JOF_INDEXBASE)
+OPDEF(JSOP_RESETBASE, 190,"resetbase", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_RESETBASE0, 191,"resetbase0", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Opcodes to help the decompiler deal with XML.
+ */
+OPDEF(JSOP_STARTXML, 192,"startxml", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_STARTXMLEXPR, 193,"startxmlexpr",NULL, 1, 0, 0, 0, JOF_BYTE)
+
+OPDEF(JSOP_CALLELEM, 194, "callelem", NULL, 1, 2, 2, 18, JOF_BYTE |JOF_ELEM|JOF_LEFTASSOC|JOF_CALLOP)
+
+/*
+ * Stop interpretation, emitted at end of script to save the threaded bytecode
+ * interpreter an extra branch test on every DO_NEXT_OP (see jsinterp.c).
+ */
+OPDEF(JSOP_STOP, 195,"stop", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Get an extant property value, throwing ReferenceError if the identified
+ * property does not exist.
+ */
+OPDEF(JSOP_GETXPROP, 196,"getxprop", NULL, 3, 1, 1, 18, JOF_ATOM|JOF_PROP)
+
+OPDEF(JSOP_CALLXMLNAME, 197, "callxmlname", NULL, 1, 1, 2, 19, JOF_BYTE|JOF_CALLOP)
+
+/*
+ * Specialized JSOP_TYPEOF to avoid reporting undefined for typeof(0, undef).
+ */
+OPDEF(JSOP_TYPEOFEXPR, 198,"typeofexpr", NULL, 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING)
+
+/*
+ * Block-local scope support.
+ */
+OPDEF(JSOP_ENTERBLOCK, 199,"enterblock", NULL, 3, 0, -1, 0, JOF_OBJECT)
+OPDEF(JSOP_LEAVEBLOCK, 200,"leaveblock", NULL, 3, -1, 0, 0, JOF_UINT16)
+OPDEF(JSOP_UNUSED201, 201,"unused201", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED202, 202,"unused202", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED203, 203,"unused203", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED204, 204,"unused204", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED205, 205,"unused205", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED206, 206,"unused206", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED207, 207,"unused207", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED208, 208,"unused208", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED209, 209,"unused209", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Generator and array comprehension support.
+ */
+OPDEF(JSOP_GENERATOR, 210,"generator", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_YIELD, 211,"yield", NULL, 1, 1, 1, 1, JOF_BYTE)
+OPDEF(JSOP_ARRAYPUSH, 212,"arraypush", NULL, 3, 1, 0, 3, JOF_LOCAL)
+
+/*
+ * In the forthcoming great opcode reorg, this should go next to JSOP_GETUPVAR.
+ */
+OPDEF(JSOP_CALLUPVAR, 213, "callupvar", NULL, 3, 0, 2, 19, JOF_UINT16|JOF_NAME|JOF_CALLOP)
+
+/*
+ * Variant of JSOP_ENUMELEM for destructuring const (const [a, b] = ...).
+ */
+OPDEF(JSOP_ENUMCONSTELEM, 214,"enumconstelem",NULL, 1, 3, 0, 3, JOF_BYTE|JOF_SET)
+
+/*
+ * Variant of JSOP_LEAVEBLOCK has a result on the stack above the locals,
+ * which must be moved down when the block pops.
+ */
+OPDEF(JSOP_LEAVEBLOCKEXPR,215,"leaveblockexpr",NULL, 3, -1, 1, 3, JOF_UINT16)
+
+/*
+ * Optimize common JSOP_{THIS,GET{ARG,LOCAL}} -> JSOP_GETPROP cliches.
+ */
+OPDEF(JSOP_GETTHISPROP, 216,"getthisprop", NULL, 3, 0, 1, 18, JOF_ATOM|JOF_VARPROP)
+OPDEF(JSOP_GETARGPROP, 217,"getargprop", NULL, 5, 0, 1, 18, JOF_SLOTATOM|JOF_VARPROP)
+OPDEF(JSOP_GETLOCALPROP, 218,"getlocalprop", NULL, 5, 0, 1, 18, JOF_SLOTATOM|JOF_VARPROP)
+OPDEF(JSOP_UNUSED219, 219,"unused219", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Optimize atom segments 1-3. These must be followed by JSOP_RESETBASE0 after
+ * the opcode that they prefix.
+ */
+OPDEF(JSOP_INDEXBASE1, 220,"atombase1", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
+OPDEF(JSOP_INDEXBASE2, 221,"atombase2", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
+OPDEF(JSOP_INDEXBASE3, 222,"atombase3", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
+
+OPDEF(JSOP_CALLGVAR, 223, "callgvar", NULL, 3, 0, 2, 19, JOF_ATOM|JOF_NAME|JOF_CALLOP)
+OPDEF(JSOP_CALLLOCAL, 224, "calllocal", NULL, 3, 0, 2, 19, JOF_LOCAL|JOF_NAME|JOF_CALLOP)
+OPDEF(JSOP_CALLARG, 225, "callarg", NULL, 3, 0, 2, 19, JOF_QARG |JOF_NAME|JOF_CALLOP)
+OPDEF(JSOP_UNUSED226, 226, "unused226", NULL, 1, 0, 1, 1, JOF_BYTE)
+
+/*
+ * Opcodes to hold 8-bit and 32-bit immediate integer operands.
+ */
+OPDEF(JSOP_INT8, 227, "int8", NULL, 2, 0, 1, 16, JOF_INT8)
+OPDEF(JSOP_INT32, 228, "int32", NULL, 5, 0, 1, 16, JOF_INT32)
+
+/*
+ * Get the value of the 'length' property from a stacked object.
+ */
+OPDEF(JSOP_LENGTH, 229, "length", NULL, 1, 1, 1, 18, JOF_BYTE|JOF_PROP)
+
+/*
+ * JSOP_NEWARRAY optimizes array literal evaluation using the interpreter stack.
+ * JSOP_HOLE pushes a JSVAL_HOLE (used with JSOP_NEWINIT and JSOP_NEWARRAY).
+ */
+OPDEF(JSOP_NEWARRAY, 230, "newarray", NULL, 4, -1, 1, 19, JOF_UINT24)
+OPDEF(JSOP_HOLE, 231, "hole", NULL, 1, 0, 1, 0, JOF_BYTE)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsoplengen.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsoplengen.cpp
new file mode 100644
index 0000000..ecebc06
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsoplengen.cpp
@@ -0,0 +1,121 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is String Switch Generator for JavaScript Keywords,
+ * released 2005-12-09.
+ *
+ * The Initial Developer of the Original Code is
+ * Igor Bukanov.
+ * Portions created by the Initial Developer are Copyright (C) 2005-2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static const struct {
+ const char *name;
+ int length;
+} pairs[] = {
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ { #op, length } ,
+#include "jsopcode.tbl"
+#undef OPDEF
+};
+
+int
+main(int argc, char **argv)
+{
+ FILE *fp;
+ size_t maxNameWidth, i, nameWidth, tabStop;
+ int lengthGap;
+
+ static const char prefix[] = "#define ";
+ static const char suffix[] = "_LENGTH";
+ static const size_t tabWidth = 8;
+ static const size_t prefixWidth = sizeof(prefix) - 1;
+ static const size_t suffixWidth = sizeof(suffix) - 1;
+
+ if (argc != 2) {
+ fputs("Bad usage\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ fp = fopen(argv[1], "w");
+ if (!fp) {
+ perror("fopen");
+ return EXIT_FAILURE;
+ }
+ fputs("/*\n"
+ " * Automatically generated header with JS opcode length constants.\n"
+ " *\n"
+ " * Do not edit it, alter jsopcode.tbl instead.\n"
+ " */\n",
+ fp);
+
+ /*
+ * Print
+ *
+ * #define name_LENGTH length
+ *
+ * with all length values aligned on the same column. The column is at the
+ * second character position after a tab-stop with the first position
+ * reserved for the minus sign of variable-length opcodes.
+ */
+ maxNameWidth = 0;
+ for (i = 0; i != sizeof pairs / sizeof pairs[0]; ++i) {
+ nameWidth = strlen(pairs[i].name);
+ if (maxNameWidth < nameWidth)
+ maxNameWidth = nameWidth;
+ }
+
+ tabStop = prefixWidth + maxNameWidth + suffixWidth + 1;
+ tabStop = (tabStop + tabWidth - 1) / tabWidth * tabWidth;
+ for (i = 0; i != sizeof pairs / sizeof pairs[0]; ++i) {
+ lengthGap = (int) (tabStop - prefixWidth - strlen(pairs[i].name) -
+ suffixWidth);
+ fprintf(fp, "%s%s%s%*c%2d\n",
+ prefix, pairs[i].name, suffix, lengthGap, ' ',
+ pairs[i].length);
+ if (ferror(fp)) {
+ perror("fclose");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (fclose(fp)) {
+ perror("fclose");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsotypes.h b/tools/node_modules/expresso/deps/jscoverage/js/jsotypes.h
new file mode 100644
index 0000000..ede1221
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsotypes.h
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * This section typedefs the old 'native' types to the new PR<type>s.
+ * These definitions are scheduled to be eliminated at the earliest
+ * possible time. The NSPR API is implemented and documented using
+ * the new definitions.
+ */
+
+/*
+ * Note that we test for PROTYPES_H, not JSOTYPES_H. This is to avoid
+ * double-definitions of scalar types such as uint32, if NSPR's
+ * protypes.h is also included.
+ */
+#ifndef PROTYPES_H
+#define PROTYPES_H
+
+#ifdef XP_BEOS
+/* BeOS defines most int types in SupportDefs.h (int8, uint8, int16,
+ * uint16, int32, uint32, int64, uint64), so in the interest of
+ * not conflicting with other definitions elsewhere we have to skip the
+ * #ifdef jungle below, duplicate some definitions, and do our stuff.
+ */
+#include <SupportDefs.h>
+
+typedef JSUintn uintn;
+#ifndef _XP_Core_
+typedef JSIntn intn;
+#endif
+
+#else
+
+/* SVR4 typedef of uint is commonly found on UNIX machines. */
+#ifdef XP_UNIX
+#include <sys/types.h>
+#else
+typedef JSUintn uint;
+#endif
+
+typedef JSUintn uintn;
+typedef JSUint64 uint64;
+#if !defined(_WIN32) && !defined(XP_OS2)
+typedef JSUint32 uint32;
+#else
+typedef unsigned long uint32;
+#endif
+typedef JSUint16 uint16;
+typedef JSUint8 uint8;
+
+#ifndef _XP_Core_
+typedef JSIntn intn;
+#endif
+
+/*
+ * On AIX 4.3, sys/inttypes.h (which is included by sys/types.h, a very
+ * common header file) defines the types int8, int16, int32, and int64.
+ * So we don't define these four types here to avoid conflicts in case
+ * the code also includes sys/types.h.
+ */
+#if defined(AIX) && defined(HAVE_SYS_INTTYPES_H)
+#include <sys/inttypes.h>
+#else
+typedef JSInt64 int64;
+
+/* /usr/include/model.h on HP-UX defines int8, int16, and int32 */
+#ifdef HPUX
+#include <model.h>
+#else
+#if !defined(_WIN32) && !defined(XP_OS2)
+typedef JSInt32 int32;
+#else
+typedef long int32;
+#endif
+typedef JSInt16 int16;
+typedef JSInt8 int8;
+#endif /* HPUX */
+#endif /* AIX && HAVE_SYS_INTTYPES_H */
+
+#endif /* XP_BEOS */
+
+typedef JSFloat64 float64;
+
+/* Re: jsbit.h */
+#define TEST_BIT JS_TEST_BIT
+#define SET_BIT JS_SET_BIT
+#define CLEAR_BIT JS_CLEAR_BIT
+
+/* Re: prarena.h->plarena.h */
+#define PRArena PLArena
+#define PRArenaPool PLArenaPool
+#define PRArenaStats PLArenaStats
+#define PR_ARENA_ALIGN PL_ARENA_ALIGN
+#define PR_INIT_ARENA_POOL PL_INIT_ARENA_POOL
+#define PR_ARENA_ALLOCATE PL_ARENA_ALLOCATE
+#define PR_ARENA_GROW PL_ARENA_GROW
+#define PR_ARENA_MARK PL_ARENA_MARK
+#define PR_CLEAR_UNUSED PL_CLEAR_UNUSED
+#define PR_CLEAR_ARENA PL_CLEAR_ARENA
+#define PR_ARENA_RELEASE PL_ARENA_RELEASE
+#define PR_COUNT_ARENA PL_COUNT_ARENA
+#define PR_ARENA_DESTROY PL_ARENA_DESTROY
+#define PR_InitArenaPool PL_InitArenaPool
+#define PR_FreeArenaPool PL_FreeArenaPool
+#define PR_FinishArenaPool PL_FinishArenaPool
+#define PR_CompactArenaPool PL_CompactArenaPool
+#define PR_ArenaFinish PL_ArenaFinish
+#define PR_ArenaAllocate PL_ArenaAllocate
+#define PR_ArenaGrow PL_ArenaGrow
+#define PR_ArenaRelease PL_ArenaRelease
+#define PR_ArenaCountAllocation PL_ArenaCountAllocation
+#define PR_ArenaCountInplaceGrowth PL_ArenaCountInplaceGrowth
+#define PR_ArenaCountGrowth PL_ArenaCountGrowth
+#define PR_ArenaCountRelease PL_ArenaCountRelease
+#define PR_ArenaCountRetract PL_ArenaCountRetract
+
+/* Re: prevent.h->plevent.h */
+#define PREvent PLEvent
+#define PREventQueue PLEventQueue
+#define PR_CreateEventQueue PL_CreateEventQueue
+#define PR_DestroyEventQueue PL_DestroyEventQueue
+#define PR_GetEventQueueMonitor PL_GetEventQueueMonitor
+#define PR_ENTER_EVENT_QUEUE_MONITOR PL_ENTER_EVENT_QUEUE_MONITOR
+#define PR_EXIT_EVENT_QUEUE_MONITOR PL_EXIT_EVENT_QUEUE_MONITOR
+#define PR_PostEvent PL_PostEvent
+#define PR_PostSynchronousEvent PL_PostSynchronousEvent
+#define PR_GetEvent PL_GetEvent
+#define PR_EventAvailable PL_EventAvailable
+#define PREventFunProc PLEventFunProc
+#define PR_MapEvents PL_MapEvents
+#define PR_RevokeEvents PL_RevokeEvents
+#define PR_ProcessPendingEvents PL_ProcessPendingEvents
+#define PR_WaitForEvent PL_WaitForEvent
+#define PR_EventLoop PL_EventLoop
+#define PR_GetEventQueueSelectFD PL_GetEventQueueSelectFD
+#define PRHandleEventProc PLHandleEventProc
+#define PRDestroyEventProc PLDestroyEventProc
+#define PR_InitEvent PL_InitEvent
+#define PR_GetEventOwner PL_GetEventOwner
+#define PR_HandleEvent PL_HandleEvent
+#define PR_DestroyEvent PL_DestroyEvent
+#define PR_DequeueEvent PL_DequeueEvent
+#define PR_GetMainEventQueue PL_GetMainEventQueue
+
+/* Re: prhash.h->plhash.h */
+#define PRHashEntry PLHashEntry
+#define PRHashTable PLHashTable
+#define PRHashNumber PLHashNumber
+#define PRHashFunction PLHashFunction
+#define PRHashComparator PLHashComparator
+#define PRHashEnumerator PLHashEnumerator
+#define PRHashAllocOps PLHashAllocOps
+#define PR_NewHashTable PL_NewHashTable
+#define PR_HashTableDestroy PL_HashTableDestroy
+#define PR_HashTableRawLookup PL_HashTableRawLookup
+#define PR_HashTableRawAdd PL_HashTableRawAdd
+#define PR_HashTableRawRemove PL_HashTableRawRemove
+#define PR_HashTableAdd PL_HashTableAdd
+#define PR_HashTableRemove PL_HashTableRemove
+#define PR_HashTableEnumerateEntries PL_HashTableEnumerateEntries
+#define PR_HashTableLookup PL_HashTableLookup
+#define PR_HashTableDump PL_HashTableDump
+#define PR_HashString PL_HashString
+#define PR_CompareStrings PL_CompareStrings
+#define PR_CompareValues PL_CompareValues
+
+#endif /* !defined(PROTYPES_H) */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsparse.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsparse.cpp
new file mode 100644
index 0000000..57da28a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsparse.cpp
@@ -0,0 +1,6822 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS parser.
+ *
+ * This is a recursive-descent parser for the JavaScript language specified by
+ * "The JavaScript 1.5 Language Specification". It uses lexical and semantic
+ * feedback to disambiguate non-LL(1) structures. It generates trees of nodes
+ * induced by the recursive parsing (not precise syntax trees, see jsparse.h).
+ * After tree construction, it rewrites trees to fold constants and evaluate
+ * compile-time expressions. Finally, it calls js_EmitTree (see jsemit.h) to
+ * generate bytecode.
+ *
+ * This parser attempts no error recovery.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsstaticcheck.h"
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#if JS_HAS_DESTRUCTURING
+#include "jsdhash.h"
+#endif
+
+/*
+ * Asserts to verify assumptions behind pn_ macros.
+ */
+JS_STATIC_ASSERT(offsetof(JSParseNode, pn_u.name.atom) ==
+ offsetof(JSParseNode, pn_u.apair.atom));
+JS_STATIC_ASSERT(offsetof(JSParseNode, pn_u.name.slot) ==
+ offsetof(JSParseNode, pn_u.lexical.slot));
+
+/*
+ * JS parsers, from lowest to highest precedence.
+ *
+ * Each parser takes a context, a token stream, and a tree context struct.
+ * Each returns a parse node tree or null on error.
+ */
+
+typedef JSParseNode *
+JSParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc);
+
+typedef JSParseNode *
+JSMemberParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSBool allowCallSyntax);
+
+typedef JSParseNode *
+JSPrimaryParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSTokenType tt, JSBool afterDot);
+
+typedef JSParseNode *
+JSParenParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSParseNode *pn1, JSBool *genexp);
+
+static JSParser FunctionStmt;
+static JSParser FunctionExpr;
+static JSParser Statements;
+static JSParser Statement;
+static JSParser Variables;
+static JSParser Expr;
+static JSParser AssignExpr;
+static JSParser CondExpr;
+static JSParser OrExpr;
+static JSParser AndExpr;
+static JSParser BitOrExpr;
+static JSParser BitXorExpr;
+static JSParser BitAndExpr;
+static JSParser EqExpr;
+static JSParser RelExpr;
+static JSParser ShiftExpr;
+static JSParser AddExpr;
+static JSParser MulExpr;
+static JSParser UnaryExpr;
+static JSMemberParser MemberExpr;
+static JSPrimaryParser PrimaryExpr;
+static JSParenParser ParenExpr;
+
+/*
+ * Insist that the next token be of type tt, or report errno and return null.
+ * NB: this macro uses cx and ts from its lexical environment.
+ */
+#define MUST_MATCH_TOKEN(tt, errno) \
+ JS_BEGIN_MACRO \
+ if (js_GetToken(cx, ts) != tt) { \
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, errno); \
+ return NULL; \
+ } \
+ JS_END_MACRO
+
+#ifdef METER_PARSENODES
+static uint32 parsenodes = 0;
+static uint32 maxparsenodes = 0;
+static uint32 recyclednodes = 0;
+#endif
+
+JSBool
+js_InitParseContext(JSContext *cx, JSParseContext *pc, JSPrincipals *principals,
+ JSStackFrame *callerFrame,
+ const jschar *base, size_t length,
+ FILE *fp, const char *filename, uintN lineno)
+{
+ JS_ASSERT_IF(callerFrame, callerFrame->script);
+
+ pc->tempPoolMark = JS_ARENA_MARK(&cx->tempPool);
+ if (!js_InitTokenStream(cx, TS(pc), base, length, fp, filename, lineno)) {
+ JS_ARENA_RELEASE(&cx->tempPool, pc->tempPoolMark);
+ return JS_FALSE;
+ }
+ if (principals)
+ JSPRINCIPALS_HOLD(cx, principals);
+ pc->principals = principals;
+ pc->callerFrame = callerFrame;
+ pc->nodeList = NULL;
+ pc->traceListHead = NULL;
+
+ /* Root atoms and objects allocated for the parsed tree. */
+ JS_KEEP_ATOMS(cx->runtime);
+ JS_PUSH_TEMP_ROOT_PARSE_CONTEXT(cx, pc, &pc->tempRoot);
+ return JS_TRUE;
+}
+
+void
+js_FinishParseContext(JSContext *cx, JSParseContext *pc)
+{
+ if (pc->principals)
+ JSPRINCIPALS_DROP(cx, pc->principals);
+ JS_ASSERT(pc->tempRoot.u.parseContext == pc);
+ JS_POP_TEMP_ROOT(cx, &pc->tempRoot);
+ JS_UNKEEP_ATOMS(cx->runtime);
+ js_CloseTokenStream(cx, TS(pc));
+ JS_ARENA_RELEASE(&cx->tempPool, pc->tempPoolMark);
+}
+
+void
+js_InitCompilePrincipals(JSContext *cx, JSParseContext *pc,
+ JSPrincipals *principals)
+{
+ JS_ASSERT(!pc->principals);
+ if (principals)
+ JSPRINCIPALS_HOLD(cx, principals);
+ pc->principals = principals;
+}
+
+JSParsedObjectBox *
+js_NewParsedObjectBox(JSContext *cx, JSParseContext *pc, JSObject *obj)
+{
+ JSParsedObjectBox *pob;
+
+ /*
+ * We use JSContext.tempPool to allocate parsed objects and place them on
+ * a list in JSTokenStream to ensure GC safety. Thus the tempPool arenas
+ * containing the entries must be alive until we are done with scanning,
+ * parsing and code generation for the whole script or top-level function.
+ */
+ JS_ASSERT(obj);
+ JS_ARENA_ALLOCATE_TYPE(pob, JSParsedObjectBox, &cx->tempPool);
+ if (!pob) {
+ js_ReportOutOfScriptQuota(cx);
+ return NULL;
+ }
+ pob->traceLink = pc->traceListHead;
+ pob->emitLink = NULL;
+ pob->object = obj;
+ pc->traceListHead = pob;
+ return pob;
+}
+
+
+void
+js_TraceParseContext(JSTracer *trc, JSParseContext *pc)
+{
+ JSParsedObjectBox *pob;
+
+ JS_ASSERT(pc->tempRoot.u.parseContext == pc);
+ pob = pc->traceListHead;
+ while (pob) {
+ JS_CALL_OBJECT_TRACER(trc, pob->object, "parser.object");
+ pob = pob->traceLink;
+ }
+}
+
+static JSParseNode *
+RecycleTree(JSParseNode *pn, JSTreeContext *tc)
+{
+ JSParseNode *next;
+
+ if (!pn)
+ return NULL;
+
+ /* Catch back-to-back dup recycles. */
+ JS_ASSERT(pn != tc->parseContext->nodeList);
+ next = pn->pn_next;
+ pn->pn_next = tc->parseContext->nodeList;
+ tc->parseContext->nodeList = pn;
+#ifdef METER_PARSENODES
+ recyclednodes++;
+#endif
+ return next;
+}
+
+static JSParseNode *
+NewOrRecycledNode(JSContext *cx, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = tc->parseContext->nodeList;
+ if (!pn) {
+ JS_ARENA_ALLOCATE_TYPE(pn, JSParseNode, &cx->tempPool);
+ if (!pn)
+ js_ReportOutOfScriptQuota(cx);
+ } else {
+ tc->parseContext->nodeList = pn->pn_next;
+
+ /* Recycle immediate descendents only, to save work and working set. */
+ switch (pn->pn_arity) {
+ case PN_FUNC:
+ RecycleTree(pn->pn_body, tc);
+ break;
+ case PN_LIST:
+ if (pn->pn_head) {
+ /* XXX check for dup recycles in the list */
+ *pn->pn_tail = tc->parseContext->nodeList;
+ tc->parseContext->nodeList = pn->pn_head;
+#ifdef METER_PARSENODES
+ recyclednodes += pn->pn_count;
+#endif
+ }
+ break;
+ case PN_TERNARY:
+ RecycleTree(pn->pn_kid1, tc);
+ RecycleTree(pn->pn_kid2, tc);
+ RecycleTree(pn->pn_kid3, tc);
+ break;
+ case PN_BINARY:
+ if (pn->pn_left != pn->pn_right)
+ RecycleTree(pn->pn_left, tc);
+ RecycleTree(pn->pn_right, tc);
+ break;
+ case PN_UNARY:
+ RecycleTree(pn->pn_kid, tc);
+ break;
+ case PN_NAME:
+ RecycleTree(pn->pn_expr, tc);
+ break;
+ case PN_NULLARY:
+ break;
+ }
+ }
+ if (pn) {
+#ifdef METER_PARSENODES
+ parsenodes++;
+ if (parsenodes - recyclednodes > maxparsenodes)
+ maxparsenodes = parsenodes - recyclednodes;
+#endif
+ memset(&pn->pn_u, 0, sizeof pn->pn_u);
+ pn->pn_next = NULL;
+ }
+ return pn;
+}
+
+/*
+ * Allocate a JSParseNode from cx's temporary arena.
+ */
+static JSParseNode *
+NewParseNode(JSContext *cx, JSTokenStream *ts, JSParseNodeArity arity,
+ JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSToken *tp;
+
+ pn = NewOrRecycledNode(cx, tc);
+ if (!pn)
+ return NULL;
+ tp = &CURRENT_TOKEN(ts);
+ pn->pn_type = tp->type;
+ pn->pn_pos = tp->pos;
+ pn->pn_op = JSOP_NOP;
+ pn->pn_arity = arity;
+ return pn;
+}
+
+static JSParseNode *
+NewBinary(JSContext *cx, JSTokenType tt,
+ JSOp op, JSParseNode *left, JSParseNode *right,
+ JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn1, *pn2;
+
+ if (!left || !right)
+ return NULL;
+
+ /*
+ * Flatten a left-associative (left-heavy) tree of a given operator into
+ * a list, to reduce js_FoldConstants and js_EmitTree recursion.
+ */
+ if (left->pn_type == tt &&
+ left->pn_op == op &&
+ (js_CodeSpec[op].format & JOF_LEFTASSOC)) {
+ if (left->pn_arity != PN_LIST) {
+ pn1 = left->pn_left, pn2 = left->pn_right;
+ left->pn_arity = PN_LIST;
+ PN_INIT_LIST_1(left, pn1);
+ PN_APPEND(left, pn2);
+ if (tt == TOK_PLUS) {
+ if (pn1->pn_type == TOK_STRING)
+ left->pn_extra |= PNX_STRCAT;
+ else if (pn1->pn_type != TOK_NUMBER)
+ left->pn_extra |= PNX_CANTFOLD;
+ if (pn2->pn_type == TOK_STRING)
+ left->pn_extra |= PNX_STRCAT;
+ else if (pn2->pn_type != TOK_NUMBER)
+ left->pn_extra |= PNX_CANTFOLD;
+ }
+ }
+ PN_APPEND(left, right);
+ left->pn_pos.end = right->pn_pos.end;
+ if (tt == TOK_PLUS) {
+ if (right->pn_type == TOK_STRING)
+ left->pn_extra |= PNX_STRCAT;
+ else if (right->pn_type != TOK_NUMBER)
+ left->pn_extra |= PNX_CANTFOLD;
+ }
+ return left;
+ }
+
+ /*
+ * Fold constant addition immediately, to conserve node space and, what's
+ * more, so js_FoldConstants never sees mixed addition and concatenation
+ * operations with more than one leading non-string operand in a PN_LIST
+ * generated for expressions such as 1 + 2 + "pt" (which should evaluate
+ * to "3pt", not "12pt").
+ */
+ if (tt == TOK_PLUS &&
+ left->pn_type == TOK_NUMBER &&
+ right->pn_type == TOK_NUMBER) {
+ left->pn_dval += right->pn_dval;
+ left->pn_pos.end = right->pn_pos.end;
+ RecycleTree(right, tc);
+ return left;
+ }
+
+ pn = NewOrRecycledNode(cx, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = tt;
+ pn->pn_pos.begin = left->pn_pos.begin;
+ pn->pn_pos.end = right->pn_pos.end;
+ pn->pn_op = op;
+ pn->pn_arity = PN_BINARY;
+ pn->pn_left = left;
+ pn->pn_right = right;
+ return pn;
+}
+
+#if JS_HAS_GETTER_SETTER
+static JSTokenType
+CheckGetterOrSetter(JSContext *cx, JSTokenStream *ts, JSTokenType tt)
+{
+ JSAtom *atom;
+ JSRuntime *rt;
+ JSOp op;
+ const char *name;
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_NAME);
+ atom = CURRENT_TOKEN(ts).t_atom;
+ rt = cx->runtime;
+ if (atom == rt->atomState.getterAtom)
+ op = JSOP_GETTER;
+ else if (atom == rt->atomState.setterAtom)
+ op = JSOP_SETTER;
+ else
+ return TOK_NAME;
+ if (js_PeekTokenSameLine(cx, ts) != tt)
+ return TOK_NAME;
+ (void) js_GetToken(cx, ts);
+ if (CURRENT_TOKEN(ts).t_op != JSOP_NOP) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_GETTER_OR_SETTER,
+ (op == JSOP_GETTER)
+ ? js_getter_str
+ : js_setter_str);
+ return TOK_ERROR;
+ }
+ CURRENT_TOKEN(ts).t_op = op;
+ if (JS_HAS_STRICT_OPTION(cx)) {
+ name = js_AtomToPrintableString(cx, atom);
+ if (!name ||
+ !js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_DEPRECATED_USAGE,
+ name)) {
+ return TOK_ERROR;
+ }
+ }
+ return tt;
+}
+#endif
+
+/*
+ * Parse a top-level JS script.
+ */
+JSParseNode *
+js_ParseScript(JSContext *cx, JSObject *chain, JSParseContext *pc)
+{
+ JSTreeContext tc;
+ JSParseNode *pn;
+
+ /*
+ * Protect atoms from being collected by a GC activation, which might
+ * - nest on this thread due to out of memory (the so-called "last ditch"
+ * GC attempted within js_NewGCThing), or
+ * - run for any reason on another thread if this thread is suspended on
+ * an object lock before it finishes generating bytecode into a script
+ * protected from the GC by a root or a stack frame reference.
+ */
+ TREE_CONTEXT_INIT(&tc, pc);
+ tc.u.scopeChain = chain;
+ pn = Statements(cx, TS(pc), &tc);
+ if (pn) {
+ if (!js_MatchToken(cx, TS(pc), TOK_EOF)) {
+ js_ReportCompileErrorNumber(cx, TS(pc), NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ pn = NULL;
+ } else {
+ pn->pn_type = TOK_LC;
+ if (!js_FoldConstants(cx, pn, &tc))
+ pn = NULL;
+ }
+ }
+
+ TREE_CONTEXT_FINISH(cx, &tc);
+ return pn;
+}
+
+/*
+ * Compile a top-level script.
+ */
+extern JSScript *
+js_CompileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *callerFrame,
+ JSPrincipals *principals, uint32 tcflags,
+ const jschar *chars, size_t length,
+ FILE *file, const char *filename, uintN lineno)
+{
+ JSParseContext pc;
+ JSArenaPool codePool, notePool;
+ JSCodeGenerator cg;
+ JSTokenType tt;
+ JSParseNode *pn;
+ uint32 scriptGlobals;
+ JSScript *script;
+#ifdef METER_PARSENODES
+ void *sbrk(ptrdiff_t), *before = sbrk(0);
+#endif
+
+ JS_ASSERT(!(tcflags & ~(TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL |
+ TCF_STATIC_DEPTH_MASK)));
+
+ /*
+ * The scripted callerFrame can only be given for compile-and-go scripts
+ * and non-zero static depth requires callerFrame.
+ */
+ JS_ASSERT_IF(callerFrame, tcflags & TCF_COMPILE_N_GO);
+ JS_ASSERT_IF(TCF_GET_STATIC_DEPTH(tcflags) != 0, callerFrame);
+
+ if (!js_InitParseContext(cx, &pc, principals, callerFrame, chars, length,
+ file, filename, lineno)) {
+ return NULL;
+ }
+
+ JS_INIT_ARENA_POOL(&codePool, "code", 1024, sizeof(jsbytecode),
+ &cx->scriptStackQuota);
+ JS_INIT_ARENA_POOL(&notePool, "note", 1024, sizeof(jssrcnote),
+ &cx->scriptStackQuota);
+ js_InitCodeGenerator(cx, &cg, &pc, &codePool, &notePool,
+ pc.tokenStream.lineno);
+
+ MUST_FLOW_THROUGH("out");
+ cg.treeContext.flags |= (uint16) tcflags;
+ cg.treeContext.u.scopeChain = scopeChain;
+ cg.staticDepth = TCF_GET_STATIC_DEPTH(tcflags);
+
+ if ((tcflags & TCF_COMPILE_N_GO) && callerFrame && callerFrame->fun) {
+ /*
+ * An eval script in a caller frame needs to have its enclosing function
+ * captured in case it uses an upvar reference, and someone wishes to
+ * decompile it while running.
+ */
+ JSParsedObjectBox *pob = js_NewParsedObjectBox(cx, &pc, callerFrame->callee);
+ pob->emitLink = cg.objectList.lastPob;
+ cg.objectList.lastPob = pob;
+ cg.objectList.length++;
+ }
+
+ /* Inline Statements() to emit as we go to save space. */
+ for (;;) {
+ pc.tokenStream.flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, &pc.tokenStream);
+ pc.tokenStream.flags &= ~TSF_OPERAND;
+ if (tt <= TOK_EOF) {
+ if (tt == TOK_EOF)
+ break;
+ JS_ASSERT(tt == TOK_ERROR);
+ script = NULL;
+ goto out;
+ }
+
+ pn = Statement(cx, &pc.tokenStream, &cg.treeContext);
+ if (!pn) {
+ script = NULL;
+ goto out;
+ }
+ JS_ASSERT(!cg.treeContext.blockNode);
+
+ if (!js_FoldConstants(cx, pn, &cg.treeContext) ||
+ !js_EmitTree(cx, &cg, pn)) {
+ script = NULL;
+ goto out;
+ }
+ RecycleTree(pn, &cg.treeContext);
+ }
+
+ /*
+ * Global variables and regexps shares the index space with locals. Due to
+ * incremental code generation we need to patch the bytecode to adjust the
+ * local references to skip the globals.
+ */
+ scriptGlobals = cg.treeContext.ngvars + cg.regexpList.length;
+ if (scriptGlobals != 0) {
+ jsbytecode *code, *end;
+ JSOp op;
+ const JSCodeSpec *cs;
+ uintN len, slot;
+
+ if (scriptGlobals >= SLOTNO_LIMIT)
+ goto too_many_slots;
+ code = CG_BASE(&cg);
+ for (end = code + CG_OFFSET(&cg); code != end; code += len) {
+ JS_ASSERT(code < end);
+ op = (JSOp) *code;
+ cs = &js_CodeSpec[op];
+ len = (cs->length > 0)
+ ? (uintN) cs->length
+ : js_GetVariableBytecodeLength(code);
+ if (JOF_TYPE(cs->format) == JOF_LOCAL ||
+ (JOF_TYPE(cs->format) == JOF_SLOTATOM)) {
+ /*
+ * JSOP_GETARGPROP also has JOF_SLOTATOM type, but it may be
+ * emitted only for a function.
+ */
+ JS_ASSERT((JOF_TYPE(cs->format) == JOF_SLOTATOM) ==
+ (op == JSOP_GETLOCALPROP));
+ slot = GET_SLOTNO(code);
+ slot += scriptGlobals;
+ if (slot >= SLOTNO_LIMIT)
+ goto too_many_slots;
+ SET_SLOTNO(code, slot);
+ }
+ }
+ }
+
+#ifdef METER_PARSENODES
+ printf("Parser growth: %d (%u nodes, %u max, %u unrecycled)\n",
+ (char *)sbrk(0) - (char *)before,
+ parsenodes,
+ maxparsenodes,
+ parsenodes - recyclednodes);
+ before = sbrk(0);
+#endif
+
+ /*
+ * Nowadays the threaded interpreter needs a stop instruction, so we
+ * do have to emit that here.
+ */
+ if (js_Emit1(cx, &cg, JSOP_STOP) < 0) {
+ script = NULL;
+ goto out;
+ }
+#ifdef METER_PARSENODES
+ printf("Code-gen growth: %d (%u bytecodes, %u srcnotes)\n",
+ (char *)sbrk(0) - (char *)before, CG_OFFSET(cg), cg->noteCount);
+#endif
+#ifdef JS_ARENAMETER
+ JS_DumpArenaStats(stdout);
+#endif
+ script = js_NewScriptFromCG(cx, &cg);
+
+#ifdef JS_SCOPE_DEPTH_METER
+ if (script) {
+ JSObject *obj = scopeChain;
+ uintN depth = 1;
+ while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL)
+ ++depth;
+ JS_BASIC_STATS_ACCUM(&cx->runtime->hostenvScopeDepthStats, depth);
+ }
+#endif
+
+ out:
+ js_FinishCodeGenerator(cx, &cg);
+ JS_FinishArenaPool(&codePool);
+ JS_FinishArenaPool(&notePool);
+ js_FinishParseContext(cx, &pc);
+ return script;
+
+ too_many_slots:
+ js_ReportCompileErrorNumber(cx, &pc.tokenStream, NULL,
+ JSREPORT_ERROR, JSMSG_TOO_MANY_LOCALS);
+ script = NULL;
+ goto out;
+}
+
+/*
+ * Insist on a final return before control flows out of pn. Try to be a bit
+ * smart about loops: do {...; return e2;} while(0) at the end of a function
+ * that contains an early return e1 will get a strict warning. Similarly for
+ * iloops: while (true){...} is treated as though ... returns.
+ */
+#define ENDS_IN_OTHER 0
+#define ENDS_IN_RETURN 1
+#define ENDS_IN_BREAK 2
+
+static int
+HasFinalReturn(JSParseNode *pn)
+{
+ JSParseNode *pn2, *pn3;
+ uintN rv, rv2, hasDefault;
+
+ switch (pn->pn_type) {
+ case TOK_LC:
+ if (!pn->pn_head)
+ return ENDS_IN_OTHER;
+ return HasFinalReturn(PN_LAST(pn));
+
+ case TOK_IF:
+ if (!pn->pn_kid3)
+ return ENDS_IN_OTHER;
+ return HasFinalReturn(pn->pn_kid2) & HasFinalReturn(pn->pn_kid3);
+
+ case TOK_WHILE:
+ pn2 = pn->pn_left;
+ if (pn2->pn_type == TOK_PRIMARY && pn2->pn_op == JSOP_TRUE)
+ return ENDS_IN_RETURN;
+ if (pn2->pn_type == TOK_NUMBER && pn2->pn_dval)
+ return ENDS_IN_RETURN;
+ return ENDS_IN_OTHER;
+
+ case TOK_DO:
+ pn2 = pn->pn_right;
+ if (pn2->pn_type == TOK_PRIMARY) {
+ if (pn2->pn_op == JSOP_FALSE)
+ return HasFinalReturn(pn->pn_left);
+ if (pn2->pn_op == JSOP_TRUE)
+ return ENDS_IN_RETURN;
+ }
+ if (pn2->pn_type == TOK_NUMBER) {
+ if (pn2->pn_dval == 0)
+ return HasFinalReturn(pn->pn_left);
+ return ENDS_IN_RETURN;
+ }
+ return ENDS_IN_OTHER;
+
+ case TOK_FOR:
+ pn2 = pn->pn_left;
+ if (pn2->pn_arity == PN_TERNARY && !pn2->pn_kid2)
+ return ENDS_IN_RETURN;
+ return ENDS_IN_OTHER;
+
+ case TOK_SWITCH:
+ rv = ENDS_IN_RETURN;
+ hasDefault = ENDS_IN_OTHER;
+ pn2 = pn->pn_right;
+ if (pn2->pn_type == TOK_LEXICALSCOPE)
+ pn2 = pn2->pn_expr;
+ for (pn2 = pn2->pn_head; rv && pn2; pn2 = pn2->pn_next) {
+ if (pn2->pn_type == TOK_DEFAULT)
+ hasDefault = ENDS_IN_RETURN;
+ pn3 = pn2->pn_right;
+ JS_ASSERT(pn3->pn_type == TOK_LC);
+ if (pn3->pn_head) {
+ rv2 = HasFinalReturn(PN_LAST(pn3));
+ if (rv2 == ENDS_IN_OTHER && pn2->pn_next)
+ /* Falling through to next case or default. */;
+ else
+ rv &= rv2;
+ }
+ }
+ /* If a final switch has no default case, we judge it harshly. */
+ rv &= hasDefault;
+ return rv;
+
+ case TOK_BREAK:
+ return ENDS_IN_BREAK;
+
+ case TOK_WITH:
+ return HasFinalReturn(pn->pn_right);
+
+ case TOK_RETURN:
+ return ENDS_IN_RETURN;
+
+ case TOK_COLON:
+ case TOK_LEXICALSCOPE:
+ return HasFinalReturn(pn->pn_expr);
+
+ case TOK_THROW:
+ return ENDS_IN_RETURN;
+
+ case TOK_TRY:
+ /* If we have a finally block that returns, we are done. */
+ if (pn->pn_kid3) {
+ rv = HasFinalReturn(pn->pn_kid3);
+ if (rv == ENDS_IN_RETURN)
+ return rv;
+ }
+
+ /* Else check the try block and any and all catch statements. */
+ rv = HasFinalReturn(pn->pn_kid1);
+ if (pn->pn_kid2) {
+ JS_ASSERT(pn->pn_kid2->pn_arity == PN_LIST);
+ for (pn2 = pn->pn_kid2->pn_head; pn2; pn2 = pn2->pn_next)
+ rv &= HasFinalReturn(pn2);
+ }
+ return rv;
+
+ case TOK_CATCH:
+ /* Check this catch block's body. */
+ return HasFinalReturn(pn->pn_kid3);
+
+ case TOK_LET:
+ /* Non-binary let statements are let declarations. */
+ if (pn->pn_arity != PN_BINARY)
+ return ENDS_IN_OTHER;
+ return HasFinalReturn(pn->pn_right);
+
+ default:
+ return ENDS_IN_OTHER;
+ }
+}
+
+static JSBool
+ReportBadReturn(JSContext *cx, JSTreeContext *tc, uintN flags, uintN errnum,
+ uintN anonerrnum)
+{
+ const char *name;
+
+ JS_ASSERT(tc->flags & TCF_IN_FUNCTION);
+ if (tc->u.fun->atom) {
+ name = js_AtomToPrintableString(cx, tc->u.fun->atom);
+ } else {
+ errnum = anonerrnum;
+ name = NULL;
+ }
+ return js_ReportCompileErrorNumber(cx, TS(tc->parseContext), NULL, flags,
+ errnum, name);
+}
+
+static JSBool
+CheckFinalReturn(JSContext *cx, JSTreeContext *tc, JSParseNode *pn)
+{
+ JS_ASSERT(tc->flags & TCF_IN_FUNCTION);
+ return HasFinalReturn(pn) == ENDS_IN_RETURN ||
+ ReportBadReturn(cx, tc, JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_NO_RETURN_VALUE, JSMSG_ANON_NO_RETURN_VALUE);
+}
+
+static JSParseNode *
+FunctionBody(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSStmtInfo stmtInfo;
+ uintN oldflags, firstLine;
+ JSParseNode *pn;
+
+ JS_ASSERT(tc->flags & TCF_IN_FUNCTION);
+ js_PushStatement(tc, &stmtInfo, STMT_BLOCK, -1);
+ stmtInfo.flags = SIF_BODY_BLOCK;
+
+ oldflags = tc->flags;
+ tc->flags &= ~(TCF_RETURN_EXPR | TCF_RETURN_VOID);
+
+ /*
+ * Save the body's first line, and store it in pn->pn_pos.begin.lineno
+ * later, because we may have not peeked in ts yet, so Statements won't
+ * acquire a valid pn->pn_pos.begin from the current token.
+ */
+ firstLine = ts->lineno;
+#if JS_HAS_EXPR_CLOSURES
+ if (CURRENT_TOKEN(ts).type == TOK_LC) {
+ pn = Statements(cx, ts, tc);
+ } else {
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (pn) {
+ pn->pn_kid = AssignExpr(cx, ts, tc);
+ if (!pn->pn_kid) {
+ pn = NULL;
+ } else {
+ if (tc->flags & TCF_FUN_IS_GENERATOR) {
+ ReportBadReturn(cx, tc, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_RETURN,
+ JSMSG_BAD_ANON_GENERATOR_RETURN);
+ pn = NULL;
+ } else {
+ pn->pn_type = TOK_RETURN;
+ pn->pn_op = JSOP_RETURN;
+ pn->pn_pos.end = pn->pn_kid->pn_pos.end;
+ }
+ }
+ }
+ }
+#else
+ pn = Statements(cx, ts, tc);
+#endif
+
+ if (pn) {
+ js_PopStatement(tc);
+ pn->pn_pos.begin.lineno = firstLine;
+
+ /* Check for falling off the end of a function that returns a value. */
+ if (JS_HAS_STRICT_OPTION(cx) && (tc->flags & TCF_RETURN_EXPR) &&
+ !CheckFinalReturn(cx, tc, pn)) {
+ pn = NULL;
+ }
+ }
+
+ tc->flags = oldflags | (tc->flags & (TCF_FUN_FLAGS | TCF_HAS_DEFXMLNS));
+ return pn;
+}
+
+/*
+ * Compile a JS function body, which might appear as the value of an event
+ * handler attribute in an HTML <INPUT> tag.
+ */
+JSBool
+js_CompileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *principals,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno)
+{
+ JSParseContext pc;
+ JSArenaPool codePool, notePool;
+ JSCodeGenerator funcg;
+ JSParseNode *pn;
+
+ if (!js_InitParseContext(cx, &pc, principals, NULL, chars, length, NULL,
+ filename, lineno)) {
+ return JS_FALSE;
+ }
+
+ /* No early return from this point until js_FinishParseContext call. */
+ JS_INIT_ARENA_POOL(&codePool, "code", 1024, sizeof(jsbytecode),
+ &cx->scriptStackQuota);
+ JS_INIT_ARENA_POOL(&notePool, "note", 1024, sizeof(jssrcnote),
+ &cx->scriptStackQuota);
+ js_InitCodeGenerator(cx, &funcg, &pc, &codePool, &notePool,
+ pc.tokenStream.lineno);
+ funcg.treeContext.flags |= TCF_IN_FUNCTION;
+ funcg.treeContext.u.fun = fun;
+
+ /*
+ * Farble the body so that it looks like a block statement to js_EmitTree,
+ * which is called beneath FunctionBody; see Statements, further below in
+ * this file. FunctionBody pushes a STMT_BLOCK record around its call to
+ * Statements, so Statements will not compile each statement as it loops
+ * to save JSParseNode space -- it will not compile at all, only build a
+ * JSParseNode tree.
+ *
+ * Therefore we must fold constants, allocate try notes, and generate code
+ * for this function, including a stop opcode at the end.
+ */
+ CURRENT_TOKEN(&pc.tokenStream).type = TOK_LC;
+ pn = FunctionBody(cx, &pc.tokenStream, &funcg.treeContext);
+ if (pn) {
+ if (!js_MatchToken(cx, &pc.tokenStream, TOK_EOF)) {
+ js_ReportCompileErrorNumber(cx, &pc.tokenStream, NULL,
+ JSREPORT_ERROR, JSMSG_SYNTAX_ERROR);
+ pn = NULL;
+ } else {
+ if (!js_FoldConstants(cx, pn, &funcg.treeContext) ||
+ !js_EmitFunctionScript(cx, &funcg, pn)) {
+ pn = NULL;
+ }
+ }
+ }
+
+ /* Restore saved state and release code generation arenas. */
+ js_FinishCodeGenerator(cx, &funcg);
+ JS_FinishArenaPool(&codePool);
+ JS_FinishArenaPool(&notePool);
+ js_FinishParseContext(cx, &pc);
+ return pn != NULL;
+}
+
+/*
+ * Parameter block types for the several Binder functions. We use a common
+ * helper function signature in order to share code among destructuring and
+ * simple variable declaration parsers. In the destructuring case, the binder
+ * function is called indirectly from the variable declaration parser by way
+ * of CheckDestructuring and its friends.
+ */
+typedef struct BindData BindData;
+
+typedef JSBool
+(*Binder)(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc);
+
+struct BindData {
+ JSParseNode *pn; /* error source coordinate */
+ JSOp op; /* prolog bytecode or nop */
+ Binder binder; /* binder, discriminates u */
+ union {
+ struct {
+ uintN overflow;
+ } let;
+ } u;
+};
+
+static JSBool
+BindArg(JSContext *cx, JSAtom *atom, JSTreeContext *tc)
+{
+ const char *name;
+
+ /*
+ * Check for a duplicate parameter name, a "feature" required by ECMA-262.
+ */
+ JS_ASSERT(tc->flags & TCF_IN_FUNCTION);
+ if (js_LookupLocal(cx, tc->u.fun, atom, NULL) != JSLOCAL_NONE) {
+ name = js_AtomToPrintableString(cx, atom);
+ if (!name ||
+ !js_ReportCompileErrorNumber(cx, TS(tc->parseContext), NULL,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_DUPLICATE_FORMAL,
+ name)) {
+ return JS_FALSE;
+ }
+ }
+
+ return js_AddLocal(cx, tc->u.fun, atom, JSLOCAL_ARG);
+}
+
+static JSBool
+BindLocalVariable(JSContext *cx, JSFunction *fun, JSAtom *atom,
+ JSLocalKind localKind)
+{
+ JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
+
+ /*
+ * Don't bind a variable with the hidden name 'arguments', per ECMA-262.
+ * Instead 'var arguments' always restates the predefined property of the
+ * activation objects with unhidden name 'arguments'. Assignment to such
+ * a variable must be handled specially.
+ */
+ if (atom == cx->runtime->atomState.argumentsAtom)
+ return JS_TRUE;
+
+ return js_AddLocal(cx, fun, atom, localKind);
+}
+
+#if JS_HAS_DESTRUCTURING
+/*
+ * Forward declaration to maintain top-down presentation.
+ */
+static JSParseNode *
+DestructuringExpr(JSContext *cx, BindData *data, JSTreeContext *tc,
+ JSTokenType tt);
+
+static JSBool
+BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom,
+ JSTreeContext *tc)
+{
+ JSAtomListElement *ale;
+ const char *name;
+
+ JS_ASSERT(tc->flags & TCF_IN_FUNCTION);
+ ATOM_LIST_SEARCH(ale, &tc->decls, atom);
+ if (!ale) {
+ ale = js_IndexAtom(cx, atom, &tc->decls);
+ if (!ale)
+ return JS_FALSE;
+ ALE_SET_JSOP(ale, data->op);
+ }
+
+ if (js_LookupLocal(cx, tc->u.fun, atom, NULL) != JSLOCAL_NONE) {
+ name = js_AtomToPrintableString(cx, atom);
+ if (!name ||
+ !js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_DUPLICATE_FORMAL,
+ name)) {
+ return JS_FALSE;
+ }
+ } else {
+ if (!BindLocalVariable(cx, tc->u.fun, atom, JSLOCAL_VAR))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+#endif /* JS_HAS_DESTRUCTURING */
+
+static JSFunction *
+NewCompilerFunction(JSContext *cx, JSTreeContext *tc, JSAtom *atom,
+ uintN lambda)
+{
+ JSObject *parent;
+ JSFunction *fun;
+
+ JS_ASSERT((lambda & ~JSFUN_LAMBDA) == 0);
+ parent = (tc->flags & TCF_IN_FUNCTION)
+ ? FUN_OBJECT(tc->u.fun)
+ : tc->u.scopeChain;
+ fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED | lambda,
+ parent, atom);
+ if (fun && !(tc->flags & TCF_COMPILE_N_GO)) {
+ STOBJ_CLEAR_PARENT(FUN_OBJECT(fun));
+ STOBJ_CLEAR_PROTO(FUN_OBJECT(fun));
+ }
+ return fun;
+}
+
+static JSParseNode *
+FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ uintN lambda)
+{
+ JSOp op, prevop;
+ JSParseNode *pn, *body, *result;
+ JSTokenType tt;
+ JSAtom *funAtom;
+ JSParsedObjectBox *funpob;
+ JSAtomListElement *ale;
+ JSFunction *fun;
+ JSTreeContext funtc;
+#if JS_HAS_DESTRUCTURING
+ JSParseNode *item, *list = NULL;
+#endif
+
+ /* Make a TOK_FUNCTION node. */
+#if JS_HAS_GETTER_SETTER
+ op = CURRENT_TOKEN(ts).t_op;
+#endif
+ pn = NewParseNode(cx, ts, PN_FUNC, tc);
+ if (!pn)
+ return NULL;
+#ifdef DEBUG
+ pn->pn_index = (uint32) -1;
+#endif
+
+ /* Scan the optional function name into funAtom. */
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ if (tt == TOK_NAME) {
+ funAtom = CURRENT_TOKEN(ts).t_atom;
+ } else {
+ if (lambda == 0 && (cx->options & JSOPTION_ANONFUNFIX)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+ funAtom = NULL;
+ js_UngetToken(ts);
+ }
+
+ /*
+ * Record names for function statements in tc->decls so we know when to
+ * avoid optimizing variable references that might name a function.
+ */
+ if (lambda == 0 && funAtom) {
+ ATOM_LIST_SEARCH(ale, &tc->decls, funAtom);
+ if (ale) {
+ prevop = ALE_JSOP(ale);
+ if (JS_HAS_STRICT_OPTION(cx) || prevop == JSOP_DEFCONST) {
+ const char *name = js_AtomToPrintableString(cx, funAtom);
+ if (!name ||
+ !js_ReportCompileErrorNumber(cx, ts, NULL,
+ (prevop != JSOP_DEFCONST)
+ ? JSREPORT_WARNING |
+ JSREPORT_STRICT
+ : JSREPORT_ERROR,
+ JSMSG_REDECLARED_VAR,
+ (prevop == JSOP_DEFFUN)
+ ? js_function_str
+ : (prevop == JSOP_DEFCONST)
+ ? js_const_str
+ : js_var_str,
+ name)) {
+ return NULL;
+ }
+ }
+ if (!AT_TOP_LEVEL(tc) && prevop == JSOP_DEFVAR)
+ tc->flags |= TCF_FUN_CLOSURE_VS_VAR;
+ } else {
+ ale = js_IndexAtom(cx, funAtom, &tc->decls);
+ if (!ale)
+ return NULL;
+ }
+ ALE_SET_JSOP(ale, JSOP_DEFFUN);
+
+ /*
+ * A function nested at top level inside another's body needs only a
+ * local variable to bind its name to its value, and not an activation
+ * object property (it might also need the activation property, if the
+ * outer function contains with statements, e.g., but the stack slot
+ * wins when jsemit.c's BindNameToSlot can optimize a JSOP_NAME into a
+ * JSOP_GETLOCAL bytecode).
+ */
+ if (AT_TOP_LEVEL(tc) && (tc->flags & TCF_IN_FUNCTION)) {
+ JSLocalKind localKind;
+
+ /*
+ * Define a property on the outer function so that BindNameToSlot
+ * can properly optimize accesses. Note that we need a variable,
+ * not an argument, for the function statement. Thus we add a
+ * variable even if the parameter with the given name already
+ * exists.
+ */
+ localKind = js_LookupLocal(cx, tc->u.fun, funAtom, NULL);
+ if (localKind == JSLOCAL_NONE || localKind == JSLOCAL_ARG) {
+ if (!js_AddLocal(cx, tc->u.fun, funAtom, JSLOCAL_VAR))
+ return NULL;
+ }
+ }
+ }
+
+ fun = NewCompilerFunction(cx, tc, funAtom, lambda);
+ if (!fun)
+ return NULL;
+
+#if JS_HAS_GETTER_SETTER
+ if (op != JSOP_NOP)
+ fun->flags |= (op == JSOP_GETTER) ? JSPROP_GETTER : JSPROP_SETTER;
+#endif
+
+ /*
+ * Create wrapping box for fun->object early to protect against a
+ * last-ditch GC.
+ */
+ funpob = js_NewParsedObjectBox(cx, tc->parseContext, FUN_OBJECT(fun));
+ if (!funpob)
+ return NULL;
+
+ /* Initialize early for possible flags mutation via DestructuringExpr. */
+ TREE_CONTEXT_INIT(&funtc, tc->parseContext);
+ funtc.flags |= TCF_IN_FUNCTION | (tc->flags & TCF_COMPILE_N_GO);
+ funtc.u.fun = fun;
+
+ /* Now parse formal argument list and compute fun->nargs. */
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_FORMAL);
+ if (!js_MatchToken(cx, ts, TOK_RP)) {
+ do {
+ tt = js_GetToken(cx, ts);
+ switch (tt) {
+#if JS_HAS_DESTRUCTURING
+ case TOK_LB:
+ case TOK_LC:
+ {
+ BindData data;
+ JSParseNode *lhs, *rhs;
+ jsint slot;
+
+ /*
+ * A destructuring formal parameter turns into one or more
+ * local variables initialized from properties of a single
+ * anonymous positional parameter, so here we must tweak our
+ * binder and its data.
+ */
+ data.pn = NULL;
+ data.op = JSOP_DEFVAR;
+ data.binder = BindDestructuringArg;
+ lhs = DestructuringExpr(cx, &data, &funtc, tt);
+ if (!lhs)
+ return NULL;
+
+ /*
+ * Adjust fun->nargs to count the single anonymous positional
+ * parameter that is to be destructured.
+ */
+ slot = fun->nargs;
+ if (!js_AddLocal(cx, fun, NULL, JSLOCAL_ARG))
+ return NULL;
+
+ /*
+ * Synthesize a destructuring assignment from the single
+ * anonymous positional parameter into the destructuring
+ * left-hand-side expression and accumulate it in list.
+ */
+ rhs = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!rhs)
+ return NULL;
+ rhs->pn_type = TOK_NAME;
+ rhs->pn_op = JSOP_GETARG;
+ rhs->pn_atom = cx->runtime->atomState.emptyAtom;
+ rhs->pn_slot = slot;
+
+ item = NewBinary(cx, TOK_ASSIGN, JSOP_NOP, lhs, rhs, tc);
+ if (!item)
+ return NULL;
+ if (!list) {
+ list = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!list)
+ return NULL;
+ list->pn_type = TOK_COMMA;
+ PN_INIT_LIST(list);
+ }
+ PN_APPEND(list, item);
+ break;
+ }
+#endif /* JS_HAS_DESTRUCTURING */
+
+ case TOK_NAME:
+ if (!BindArg(cx, CURRENT_TOKEN(ts).t_atom, &funtc))
+ return NULL;
+ break;
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_MISSING_FORMAL);
+ return NULL;
+ }
+ } while (js_MatchToken(cx, ts, TOK_COMMA));
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FORMAL);
+ }
+
+#if JS_HAS_EXPR_CLOSURES
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt != TOK_LC) {
+ js_UngetToken(ts);
+ fun->flags |= JSFUN_EXPR_CLOSURE;
+ }
+#else
+ MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_BODY);
+#endif
+ pn->pn_pos.begin = CURRENT_TOKEN(ts).pos.begin;
+
+ body = FunctionBody(cx, ts, &funtc);
+ if (!body)
+ return NULL;
+
+#if JS_HAS_EXPR_CLOSURES
+ if (tt == TOK_LC)
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
+ else if (lambda == 0)
+ js_MatchToken(cx, ts, TOK_SEMI);
+#else
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
+#endif
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+
+#if JS_HAS_DESTRUCTURING
+ /*
+ * If there were destructuring formal parameters, prepend the initializing
+ * comma expression that we synthesized to body. If the body is a lexical
+ * scope node, we must make a special TOK_SEQ node, to prepend the formal
+ * parameter destructuring code without bracing the decompilation of the
+ * function body's lexical scope.
+ */
+ if (list) {
+ if (body->pn_arity != PN_LIST) {
+ JSParseNode *block;
+
+ block = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!block)
+ return NULL;
+ block->pn_type = TOK_SEQ;
+ block->pn_pos = body->pn_pos;
+ PN_INIT_LIST_1(block, body);
+
+ body = block;
+ }
+
+ item = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!item)
+ return NULL;
+
+ item->pn_type = TOK_SEMI;
+ item->pn_pos.begin = item->pn_pos.end = body->pn_pos.begin;
+ item->pn_kid = list;
+ item->pn_next = body->pn_head;
+ body->pn_head = item;
+ if (body->pn_tail == &body->pn_head)
+ body->pn_tail = &item->pn_next;
+ ++body->pn_count;
+ }
+#endif
+
+ /*
+ * If we collected flags that indicate nested heavyweight functions, or
+ * this function contains heavyweight-making statements (references to
+ * __parent__ or __proto__; use of with, or eval; and assignment to
+ * arguments), flag the function as heavyweight (requiring a call object
+ * per invocation).
+ */
+ if (funtc.flags & TCF_FUN_HEAVYWEIGHT) {
+ fun->flags |= JSFUN_HEAVYWEIGHT;
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ } else {
+ /*
+ * If this function is a named statement function not at top-level
+ * (i.e. not a top-level function definiton or expression), then
+ * our enclosing function, if any, must be heavyweight.
+ *
+ * The TCF_FUN_USES_NONLOCALS flag is set only by the code generator,
+ * so it won't be set here. Assert that it's not. We have to check
+ * it later, in js_EmitTree, after js_EmitFunctionScript has traversed
+ * the function's body.
+ */
+ JS_ASSERT(!(funtc.flags & TCF_FUN_USES_NONLOCALS));
+ if (lambda == 0 && funAtom && !AT_TOP_LEVEL(tc))
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ }
+
+ result = pn;
+ if (lambda != 0) {
+ /*
+ * ECMA ed. 3 standard: function expression, possibly anonymous.
+ */
+ op = funAtom ? JSOP_NAMEDFUNOBJ : JSOP_ANONFUNOBJ;
+ } else if (!funAtom) {
+ /*
+ * If this anonymous function definition is *not* embedded within a
+ * larger expression, we treat it as an expression statement, not as
+ * a function declaration -- and not as a syntax error (as ECMA-262
+ * Edition 3 would have it). Backward compatibility must trump all,
+ * unless JSOPTION_ANONFUNFIX is set.
+ */
+ result = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!result)
+ return NULL;
+ result->pn_type = TOK_SEMI;
+ result->pn_pos = pn->pn_pos;
+ result->pn_kid = pn;
+ op = JSOP_ANONFUNOBJ;
+ } else if (!AT_TOP_LEVEL(tc)) {
+ /*
+ * ECMA ed. 3 extension: a function expression statement not at the
+ * top level, e.g., in a compound statement such as the "then" part
+ * of an "if" statement, binds a closure only if control reaches that
+ * sub-statement.
+ */
+ op = JSOP_DEFFUN;
+ } else {
+ op = JSOP_NOP;
+ }
+
+ pn->pn_funpob = funpob;
+ pn->pn_op = op;
+ pn->pn_body = body;
+ pn->pn_flags = funtc.flags & (TCF_FUN_FLAGS | TCF_HAS_DEFXMLNS | TCF_COMPILE_N_GO);
+ TREE_CONTEXT_FINISH(cx, &funtc);
+ return result;
+}
+
+static JSParseNode *
+FunctionStmt(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ return FunctionDef(cx, ts, tc, 0);
+}
+
+static JSParseNode *
+FunctionExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ return FunctionDef(cx, ts, tc, JSFUN_LAMBDA);
+}
+
+/*
+ * Parse the statements in a block, creating a TOK_LC node that lists the
+ * statements' trees. If called from block-parsing code, the caller must
+ * match { before and } after.
+ */
+static JSParseNode *
+Statements(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2, *saveBlock;
+ JSTokenType tt;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ saveBlock = tc->blockNode;
+ tc->blockNode = pn;
+ PN_INIT_LIST(pn);
+
+ for (;;) {
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt <= TOK_EOF || tt == TOK_RC) {
+ if (tt == TOK_ERROR)
+ return NULL;
+ break;
+ }
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2) {
+ if (ts->flags & TSF_EOF)
+ ts->flags |= TSF_UNEXPECTED_EOF;
+ return NULL;
+ }
+
+ if (pn2->pn_type == TOK_FUNCTION) {
+ /*
+ * PNX_FUNCDEFS notifies the emitter that the block contains top-
+ * level function definitions that should be processed before the
+ * rest of nodes.
+ *
+ * TCF_HAS_FUNCTION_STMT is for the TOK_LC case in Statement. It
+ * is relevant only for function definitions not at top-level,
+ * which we call function statements.
+ */
+ if (AT_TOP_LEVEL(tc))
+ pn->pn_extra |= PNX_FUNCDEFS;
+ else
+ tc->flags |= TCF_HAS_FUNCTION_STMT;
+ }
+ PN_APPEND(pn, pn2);
+ }
+
+ /*
+ * Handle the case where there was a let declaration under this block. If
+ * it replaced tc->blockNode with a new block node then we must refresh pn
+ * and then restore tc->blockNode.
+ */
+ if (tc->blockNode != pn)
+ pn = tc->blockNode;
+ tc->blockNode = saveBlock;
+
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ return pn;
+}
+
+static JSParseNode *
+Condition(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND);
+ pn = ParenExpr(cx, ts, tc, NULL, NULL);
+ if (!pn)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND);
+
+ /*
+ * Check for (a = b) and warn about possible (a == b) mistype iff b's
+ * operator has greater precedence than ==.
+ */
+ if (pn->pn_type == TOK_ASSIGN &&
+ pn->pn_op == JSOP_NOP &&
+ pn->pn_right->pn_type > TOK_EQOP)
+ {
+ if (!js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_EQUAL_AS_ASSIGN,
+ "")) {
+ return NULL;
+ }
+ }
+ return pn;
+}
+
+static JSBool
+MatchLabel(JSContext *cx, JSTokenStream *ts, JSParseNode *pn)
+{
+ JSAtom *label;
+ JSTokenType tt;
+
+ tt = js_PeekTokenSameLine(cx, ts);
+ if (tt == TOK_ERROR)
+ return JS_FALSE;
+ if (tt == TOK_NAME) {
+ (void) js_GetToken(cx, ts);
+ label = CURRENT_TOKEN(ts).t_atom;
+ } else {
+ label = NULL;
+ }
+ pn->pn_atom = label;
+ return JS_TRUE;
+}
+
+static JSBool
+BindLet(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
+{
+ JSObject *blockObj;
+ JSScopeProperty *sprop;
+ JSAtomListElement *ale;
+ uintN n;
+
+ blockObj = tc->blockChain;
+ sprop = SCOPE_GET_PROPERTY(OBJ_SCOPE(blockObj), ATOM_TO_JSID(atom));
+ ATOM_LIST_SEARCH(ale, &tc->decls, atom);
+ if (sprop || (ale && ALE_JSOP(ale) == JSOP_DEFCONST)) {
+ const char *name;
+
+ if (sprop) {
+ JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
+ JS_ASSERT((uint16)sprop->shortid < OBJ_BLOCK_COUNT(cx, blockObj));
+ }
+
+ name = js_AtomToPrintableString(cx, atom);
+ if (name) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ JSREPORT_ERROR, JSMSG_REDECLARED_VAR,
+ (ale && ALE_JSOP(ale) == JSOP_DEFCONST)
+ ? js_const_str
+ : "variable",
+ name);
+ }
+ return JS_FALSE;
+ }
+
+ n = OBJ_BLOCK_COUNT(cx, blockObj);
+ if (n == JS_BIT(16)) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ JSREPORT_ERROR, data->u.let.overflow);
+ return JS_FALSE;
+ }
+
+ /* Use JSPROP_ENUMERATE to aid the disassembler. */
+ return js_DefineNativeProperty(cx, blockObj, ATOM_TO_JSID(atom),
+ JSVAL_VOID, NULL, NULL,
+ JSPROP_ENUMERATE |
+ JSPROP_PERMANENT |
+ JSPROP_SHARED,
+ SPROP_HAS_SHORTID, (int16) n, NULL);
+}
+
+static JSBool
+BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
+{
+ JSStmtInfo *stmt;
+ JSAtomListElement *ale;
+ JSOp op, prevop;
+ const char *name;
+ JSLocalKind localKind;
+
+ stmt = js_LexicalLookup(tc, atom, NULL);
+ ATOM_LIST_SEARCH(ale, &tc->decls, atom);
+ op = data->op;
+ if ((stmt && stmt->type != STMT_WITH) || ale) {
+ prevop = ale ? ALE_JSOP(ale) : JSOP_DEFVAR;
+ if (JS_HAS_STRICT_OPTION(cx)
+ ? op != JSOP_DEFVAR || prevop != JSOP_DEFVAR
+ : op == JSOP_DEFCONST || prevop == JSOP_DEFCONST) {
+ name = js_AtomToPrintableString(cx, atom);
+ if (!name ||
+ !js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ (op != JSOP_DEFCONST &&
+ prevop != JSOP_DEFCONST)
+ ? JSREPORT_WARNING |
+ JSREPORT_STRICT
+ : JSREPORT_ERROR,
+ JSMSG_REDECLARED_VAR,
+ (prevop == JSOP_DEFFUN)
+ ? js_function_str
+ : (prevop == JSOP_DEFCONST)
+ ? js_const_str
+ : js_var_str,
+ name)) {
+ return JS_FALSE;
+ }
+ }
+ if (op == JSOP_DEFVAR && prevop == JSOP_DEFFUN)
+ tc->flags |= TCF_FUN_CLOSURE_VS_VAR;
+ }
+ if (!ale) {
+ ale = js_IndexAtom(cx, atom, &tc->decls);
+ if (!ale)
+ return JS_FALSE;
+ }
+ ALE_SET_JSOP(ale, op);
+
+ if (!(tc->flags & TCF_IN_FUNCTION)) {
+ /*
+ * Don't lookup global variables or variables in an active frame at
+ * compile time.
+ */
+ return JS_TRUE;
+ }
+
+ localKind = js_LookupLocal(cx, tc->u.fun, atom, NULL);
+ if (localKind == JSLOCAL_NONE) {
+ /*
+ * Property not found in current variable scope: we have not seen this
+ * variable before. Define a new local variable by adding a property
+ * to the function's scope, allocating one slot in the function's vars
+ * frame. Any locals declared in with statement bodies are handled at
+ * runtime, by script prolog JSOP_DEFVAR opcodes generated for
+ * slot-less vars.
+ */
+ localKind = (data->op == JSOP_DEFCONST) ? JSLOCAL_CONST : JSLOCAL_VAR;
+ if (!js_InWithStatement(tc) &&
+ !BindLocalVariable(cx, tc->u.fun, atom, localKind)) {
+ return JS_FALSE;
+ }
+ } else if (localKind == JSLOCAL_ARG) {
+ name = js_AtomToPrintableString(cx, atom);
+ if (!name)
+ return JS_FALSE;
+
+ if (op == JSOP_DEFCONST) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ JSREPORT_ERROR, JSMSG_REDECLARED_PARAM,
+ name);
+ return JS_FALSE;
+ }
+ if (!js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_VAR_HIDES_ARG, name)) {
+ return JS_FALSE;
+ }
+ } else {
+ /* Not an argument, must be a redeclared local var. */
+ JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+MakeSetCall(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, uintN msg)
+{
+ JSParseNode *pn2;
+
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ JS_ASSERT(pn->pn_op == JSOP_CALL || pn->pn_op == JSOP_EVAL || pn->pn_op == JSOP_APPLY);
+ pn2 = pn->pn_head;
+ if (pn2->pn_type == TOK_FUNCTION && (pn2->pn_flags & TCF_GENEXP_LAMBDA)) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), pn,
+ JSREPORT_ERROR, msg);
+ return JS_FALSE;
+ }
+ pn->pn_op = JSOP_SETCALL;
+ return JS_TRUE;
+}
+
+#if JS_HAS_DESTRUCTURING
+
+static JSBool
+BindDestructuringVar(JSContext *cx, BindData *data, JSParseNode *pn,
+ JSTreeContext *tc)
+{
+ JSAtom *atom;
+
+ /*
+ * Destructuring is a form of assignment, so just as for an initialized
+ * simple variable, we must check for assignment to 'arguments' and flag
+ * the enclosing function (if any) as heavyweight.
+ */
+ JS_ASSERT(pn->pn_type == TOK_NAME);
+ atom = pn->pn_atom;
+ if (atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+
+ data->pn = pn;
+ if (!data->binder(cx, data, atom, tc))
+ return JS_FALSE;
+ data->pn = NULL;
+
+ /*
+ * Select the appropriate name-setting opcode, which may be specialized
+ * further for local variable and argument slot optimizations. At this
+ * point, we can't select the optimal final opcode, yet we must preserve
+ * the CONST bit and convey "set", not "get".
+ */
+ if (data->op == JSOP_DEFCONST) {
+ pn->pn_op = JSOP_SETCONST;
+ pn->pn_const = JS_TRUE;
+ } else {
+ pn->pn_op = JSOP_SETNAME;
+ pn->pn_const = JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+/*
+ * Here, we are destructuring {... P: Q, ...} = R, where P is any id, Q is any
+ * LHS expression except a destructuring initialiser, and R is on the stack.
+ * Because R is already evaluated, the usual LHS-specialized bytecodes won't
+ * work. After pushing R[P] we need to evaluate Q's "reference base" QB and
+ * then push its property name QN. At this point the stack looks like
+ *
+ * [... R, R[P], QB, QN]
+ *
+ * We need to set QB[QN] = R[P]. This is a job for JSOP_ENUMELEM, which takes
+ * its operands with left-hand side above right-hand side:
+ *
+ * [rval, lval, xval]
+ *
+ * and pops all three values, setting lval[xval] = rval. But we cannot select
+ * JSOP_ENUMELEM yet, because the LHS may turn out to be an arg or local var,
+ * which can be optimized further. So we select JSOP_SETNAME.
+ */
+static JSBool
+BindDestructuringLHS(JSContext *cx, JSParseNode *pn, JSTreeContext *tc)
+{
+ while (pn->pn_type == TOK_RP)
+ pn = pn->pn_kid;
+
+ switch (pn->pn_type) {
+ case TOK_NAME:
+ if (pn->pn_atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ /* FALL THROUGH */
+ case TOK_DOT:
+ case TOK_LB:
+ pn->pn_op = JSOP_SETNAME;
+ break;
+
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ if (!MakeSetCall(cx, pn, tc, JSMSG_BAD_LEFTSIDE_OF_ASS))
+ return JS_FALSE;
+ break;
+#endif
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ if (pn->pn_op == JSOP_XMLNAME) {
+ pn->pn_op = JSOP_BINDXMLNAME;
+ break;
+ }
+ /* FALL THROUGH */
+#endif
+
+ default:
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), pn,
+ JSREPORT_ERROR, JSMSG_BAD_LEFTSIDE_OF_ASS);
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+typedef struct FindPropValData {
+ uint32 numvars; /* # of destructuring vars in left side */
+ uint32 maxstep; /* max # of steps searching right side */
+ JSDHashTable table; /* hash table for O(1) right side search */
+} FindPropValData;
+
+typedef struct FindPropValEntry {
+ JSDHashEntryHdr hdr;
+ JSParseNode *pnkey;
+ JSParseNode *pnval;
+} FindPropValEntry;
+
+#define ASSERT_VALID_PROPERTY_KEY(pnkey) \
+ JS_ASSERT((pnkey)->pn_arity == PN_NULLARY && \
+ ((pnkey)->pn_type == TOK_NUMBER || \
+ (pnkey)->pn_type == TOK_STRING || \
+ (pnkey)->pn_type == TOK_NAME))
+
+static JSDHashNumber
+HashFindPropValKey(JSDHashTable *table, const void *key)
+{
+ const JSParseNode *pnkey = (const JSParseNode *)key;
+
+ ASSERT_VALID_PROPERTY_KEY(pnkey);
+ return (pnkey->pn_type == TOK_NUMBER)
+ ? (JSDHashNumber) (JSDOUBLE_HI32(pnkey->pn_dval) ^
+ JSDOUBLE_LO32(pnkey->pn_dval))
+ : ATOM_HASH(pnkey->pn_atom);
+}
+
+static JSBool
+MatchFindPropValEntry(JSDHashTable *table,
+ const JSDHashEntryHdr *entry,
+ const void *key)
+{
+ const FindPropValEntry *fpve = (const FindPropValEntry *)entry;
+ const JSParseNode *pnkey = (const JSParseNode *)key;
+
+ ASSERT_VALID_PROPERTY_KEY(pnkey);
+ return pnkey->pn_type == fpve->pnkey->pn_type &&
+ ((pnkey->pn_type == TOK_NUMBER)
+ ? pnkey->pn_dval == fpve->pnkey->pn_dval
+ : pnkey->pn_atom == fpve->pnkey->pn_atom);
+}
+
+static const JSDHashTableOps FindPropValOps = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ HashFindPropValKey,
+ MatchFindPropValEntry,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+#define STEP_HASH_THRESHOLD 10
+#define BIG_DESTRUCTURING 5
+#define BIG_OBJECT_INIT 20
+
+static JSParseNode *
+FindPropertyValue(JSParseNode *pn, JSParseNode *pnid, FindPropValData *data)
+{
+ FindPropValEntry *entry;
+ JSParseNode *pnhit, *pnhead, *pnprop, *pnkey;
+ uint32 step;
+
+ /* If we have a hash table, use it as the sole source of truth. */
+ if (data->table.ops) {
+ entry = (FindPropValEntry *)
+ JS_DHashTableOperate(&data->table, pnid, JS_DHASH_LOOKUP);
+ return JS_DHASH_ENTRY_IS_BUSY(&entry->hdr) ? entry->pnval : NULL;
+ }
+
+ /* If pn is not an object initialiser node, we can't do anything here. */
+ if (pn->pn_type != TOK_RC)
+ return NULL;
+
+ /*
+ * We must search all the way through pn's list, to handle the case of an
+ * id duplicated for two or more property initialisers.
+ */
+ pnhit = NULL;
+ step = 0;
+ ASSERT_VALID_PROPERTY_KEY(pnid);
+ pnhead = pn->pn_head;
+ if (pnhead && pnhead->pn_type == TOK_DEFSHARP)
+ pnhead = pnhead->pn_next;
+ if (pnid->pn_type == TOK_NUMBER) {
+ for (pnprop = pnhead; pnprop; pnprop = pnprop->pn_next) {
+ JS_ASSERT(pnprop->pn_type == TOK_COLON);
+ if (pnprop->pn_op == JSOP_NOP) {
+ pnkey = pnprop->pn_left;
+ ASSERT_VALID_PROPERTY_KEY(pnkey);
+ if (pnkey->pn_type == TOK_NUMBER &&
+ pnkey->pn_dval == pnid->pn_dval) {
+ pnhit = pnprop;
+ }
+ ++step;
+ }
+ }
+ } else {
+ for (pnprop = pnhead; pnprop; pnprop = pnprop->pn_next) {
+ JS_ASSERT(pnprop->pn_type == TOK_COLON);
+ if (pnprop->pn_op == JSOP_NOP) {
+ pnkey = pnprop->pn_left;
+ ASSERT_VALID_PROPERTY_KEY(pnkey);
+ if (pnkey->pn_type == pnid->pn_type &&
+ pnkey->pn_atom == pnid->pn_atom) {
+ pnhit = pnprop;
+ }
+ ++step;
+ }
+ }
+ }
+ if (!pnhit)
+ return NULL;
+
+ /* Hit via full search -- see whether it's time to create the hash table. */
+ JS_ASSERT(!data->table.ops);
+ if (step > data->maxstep) {
+ data->maxstep = step;
+ if (step >= STEP_HASH_THRESHOLD &&
+ data->numvars >= BIG_DESTRUCTURING &&
+ pn->pn_count >= BIG_OBJECT_INIT &&
+ JS_DHashTableInit(&data->table, &FindPropValOps, pn,
+ sizeof(FindPropValEntry),
+ JS_DHASH_DEFAULT_CAPACITY(pn->pn_count)))
+ {
+ for (pn = pnhead; pn; pn = pn->pn_next) {
+ JS_ASSERT(pnprop->pn_type == TOK_COLON);
+ ASSERT_VALID_PROPERTY_KEY(pn->pn_left);
+ entry = (FindPropValEntry *)
+ JS_DHashTableOperate(&data->table, pn->pn_left,
+ JS_DHASH_ADD);
+ entry->pnval = pn->pn_right;
+ }
+ }
+ }
+ return pnhit->pn_right;
+}
+
+/*
+ * If data is null, the caller is AssignExpr and instead of binding variables,
+ * we specialize lvalues in the propery value positions of the left-hand side.
+ * If right is null, just check for well-formed lvalues.
+ */
+static JSBool
+CheckDestructuring(JSContext *cx, BindData *data,
+ JSParseNode *left, JSParseNode *right,
+ JSTreeContext *tc)
+{
+ JSBool ok;
+ FindPropValData fpvd;
+ JSParseNode *lhs, *rhs, *pn, *pn2;
+
+ if (left->pn_type == TOK_ARRAYCOMP) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), left,
+ JSREPORT_ERROR, JSMSG_ARRAY_COMP_LEFTSIDE);
+ return JS_FALSE;
+ }
+
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ if (right && right->pn_arity == PN_LIST && (right->pn_extra & PNX_SHORTHAND)) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), right,
+ JSREPORT_ERROR, JSMSG_BAD_OBJECT_INIT);
+ return JS_FALSE;
+ }
+#endif
+
+ fpvd.table.ops = NULL;
+ lhs = left->pn_head;
+ if (lhs && lhs->pn_type == TOK_DEFSHARP) {
+ pn = lhs;
+ goto no_var_name;
+ }
+
+ if (left->pn_type == TOK_RB) {
+ rhs = (right && right->pn_type == left->pn_type)
+ ? right->pn_head
+ : NULL;
+
+ while (lhs) {
+ pn = lhs, pn2 = rhs;
+ if (!data) {
+ /* Skip parenthesization if not in a variable declaration. */
+ while (pn->pn_type == TOK_RP)
+ pn = pn->pn_kid;
+ if (pn2) {
+ while (pn2->pn_type == TOK_RP)
+ pn2 = pn2->pn_kid;
+ }
+ }
+
+ /* Nullary comma is an elision; binary comma is an expression.*/
+ if (pn->pn_type != TOK_COMMA || pn->pn_arity != PN_NULLARY) {
+ if (pn->pn_type == TOK_RB || pn->pn_type == TOK_RC) {
+ ok = CheckDestructuring(cx, data, pn, pn2, tc);
+ } else {
+ if (data) {
+ if (pn->pn_type != TOK_NAME)
+ goto no_var_name;
+
+ ok = BindDestructuringVar(cx, data, pn, tc);
+ } else {
+ ok = BindDestructuringLHS(cx, pn, tc);
+ }
+ }
+ if (!ok)
+ goto out;
+ }
+
+ lhs = lhs->pn_next;
+ if (rhs)
+ rhs = rhs->pn_next;
+ }
+ } else {
+ JS_ASSERT(left->pn_type == TOK_RC);
+ fpvd.numvars = left->pn_count;
+ fpvd.maxstep = 0;
+ rhs = NULL;
+
+ while (lhs) {
+ JS_ASSERT(lhs->pn_type == TOK_COLON);
+ pn = lhs->pn_right;
+ if (!data) {
+ /* Skip parenthesization if not in a variable declaration. */
+ while (pn->pn_type == TOK_RP)
+ pn = pn->pn_kid;
+ }
+
+ if (pn->pn_type == TOK_RB || pn->pn_type == TOK_RC) {
+ if (right) {
+ rhs = FindPropertyValue(right, lhs->pn_left, &fpvd);
+ if (rhs && !data) {
+ while (rhs->pn_type == TOK_RP)
+ rhs = rhs->pn_kid;
+ }
+ }
+
+ ok = CheckDestructuring(cx, data, pn, rhs, tc);
+ } else if (data) {
+ if (pn->pn_type != TOK_NAME)
+ goto no_var_name;
+
+ ok = BindDestructuringVar(cx, data, pn, tc);
+ } else {
+ ok = BindDestructuringLHS(cx, pn, tc);
+ }
+ if (!ok)
+ goto out;
+
+ lhs = lhs->pn_next;
+ }
+ }
+
+ /*
+ * The catch/finally handler implementation in the interpreter assumes
+ * that any operation that introduces a new scope (like a "let" or "with"
+ * block) increases the stack depth. This way, it is possible to restore
+ * the scope chain based on stack depth of the handler alone. "let" with
+ * an empty destructuring pattern like in
+ *
+ * let [] = 1;
+ *
+ * would violate this assumption as the there would be no let locals to
+ * store on the stack. To satisfy it we add an empty property to such
+ * blocks so that OBJ_BLOCK_COUNT(cx, blockObj), which gives the number of
+ * slots, would be always positive.
+ *
+ * Note that we add such a property even if the block has locals due to
+ * later let declarations in it. We optimize for code simplicity here,
+ * not the fastest runtime performance with empty [] or {}.
+ */
+ if (data &&
+ data->binder == BindLet &&
+ OBJ_BLOCK_COUNT(cx, tc->blockChain) == 0) {
+ ok = js_DefineNativeProperty(cx, tc->blockChain,
+ ATOM_TO_JSID(cx->runtime->
+ atomState.emptyAtom),
+ JSVAL_VOID, NULL, NULL,
+ JSPROP_ENUMERATE |
+ JSPROP_PERMANENT |
+ JSPROP_SHARED,
+ SPROP_HAS_SHORTID, 0, NULL);
+ if (!ok)
+ goto out;
+ }
+
+ ok = JS_TRUE;
+
+ out:
+ if (fpvd.table.ops)
+ JS_DHashTableFinish(&fpvd.table);
+ return ok;
+
+ no_var_name:
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), pn, JSREPORT_ERROR,
+ JSMSG_NO_VARIABLE_NAME);
+ ok = JS_FALSE;
+ goto out;
+}
+
+static JSParseNode *
+DestructuringExpr(JSContext *cx, BindData *data, JSTreeContext *tc,
+ JSTokenType tt)
+{
+ JSParseNode *pn;
+
+ pn = PrimaryExpr(cx, TS(tc->parseContext), tc, tt, JS_FALSE);
+ if (!pn)
+ return NULL;
+ if (!CheckDestructuring(cx, data, pn, NULL, tc))
+ return NULL;
+ return pn;
+}
+
+// Currently used only #if JS_HAS_DESTRUCTURING, in Statement's TOK_FOR case.
+static JSParseNode *
+CloneParseTree(JSContext *cx, JSParseNode *opn, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2, *opn2;
+
+ pn = NewOrRecycledNode(cx, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = opn->pn_type;
+ pn->pn_pos = opn->pn_pos;
+ pn->pn_op = opn->pn_op;
+ pn->pn_arity = opn->pn_arity;
+
+ switch (pn->pn_arity) {
+#define NULLCHECK(e) JS_BEGIN_MACRO if (!(e)) return NULL; JS_END_MACRO
+
+ case PN_FUNC:
+ NULLCHECK(pn->pn_funpob =
+ js_NewParsedObjectBox(cx, tc->parseContext, opn->pn_funpob->object));
+ NULLCHECK(pn->pn_body = CloneParseTree(cx, opn->pn_body, tc));
+ pn->pn_flags = opn->pn_flags;
+ pn->pn_index = opn->pn_index;
+ break;
+
+ case PN_LIST:
+ PN_INIT_LIST(pn);
+ for (opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) {
+ NULLCHECK(pn2 = CloneParseTree(cx, opn2, tc));
+ PN_APPEND(pn, pn2);
+ }
+ pn->pn_extra = opn->pn_extra;
+ break;
+
+ case PN_TERNARY:
+ NULLCHECK(pn->pn_kid1 = CloneParseTree(cx, opn->pn_kid1, tc));
+ NULLCHECK(pn->pn_kid2 = CloneParseTree(cx, opn->pn_kid2, tc));
+ NULLCHECK(pn->pn_kid3 = CloneParseTree(cx, opn->pn_kid3, tc));
+ break;
+
+ case PN_BINARY:
+ NULLCHECK(pn->pn_left = CloneParseTree(cx, opn->pn_left, tc));
+ if (opn->pn_right != opn->pn_left)
+ NULLCHECK(pn->pn_right = CloneParseTree(cx, opn->pn_right, tc));
+ else
+ pn->pn_right = pn->pn_left;
+ pn->pn_val = opn->pn_val;
+ pn->pn_iflags = opn->pn_iflags;
+ break;
+
+ case PN_UNARY:
+ NULLCHECK(pn->pn_kid = CloneParseTree(cx, opn->pn_kid, tc));
+ pn->pn_num = opn->pn_num;
+ pn->pn_hidden = opn->pn_hidden;
+ break;
+
+ case PN_NAME:
+ // PN_NAME could mean several arms in pn_u, so copy the whole thing.
+ pn->pn_u = opn->pn_u;
+ if (opn->pn_expr)
+ NULLCHECK(pn->pn_expr = CloneParseTree(cx, opn->pn_expr, tc));
+ break;
+
+ case PN_NULLARY:
+ // Even PN_NULLARY may have data (apair for E4X -- what a botch).
+ pn->pn_u = opn->pn_u;
+ break;
+
+#undef NULLCHECK
+ }
+ return pn;
+}
+
+#endif /* JS_HAS_DESTRUCTURING */
+
+extern const char js_with_statement_str[];
+
+static JSParseNode *
+ContainsStmt(JSParseNode *pn, JSTokenType tt)
+{
+ JSParseNode *pn2, *pnt;
+
+ if (!pn)
+ return NULL;
+ if (pn->pn_type == tt)
+ return pn;
+ switch (pn->pn_arity) {
+ case PN_LIST:
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ pnt = ContainsStmt(pn2, tt);
+ if (pnt)
+ return pnt;
+ }
+ break;
+ case PN_TERNARY:
+ pnt = ContainsStmt(pn->pn_kid1, tt);
+ if (pnt)
+ return pnt;
+ pnt = ContainsStmt(pn->pn_kid2, tt);
+ if (pnt)
+ return pnt;
+ return ContainsStmt(pn->pn_kid3, tt);
+ case PN_BINARY:
+ /*
+ * Limit recursion if pn is a binary expression, which can't contain a
+ * var statement.
+ */
+ if (pn->pn_op != JSOP_NOP)
+ return NULL;
+ pnt = ContainsStmt(pn->pn_left, tt);
+ if (pnt)
+ return pnt;
+ return ContainsStmt(pn->pn_right, tt);
+ case PN_UNARY:
+ if (pn->pn_op != JSOP_NOP)
+ return NULL;
+ return ContainsStmt(pn->pn_kid, tt);
+ case PN_NAME:
+ return ContainsStmt(pn->pn_expr, tt);
+ default:;
+ }
+ return NULL;
+}
+
+static JSParseNode *
+ReturnOrYield(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSParser operandParser)
+{
+ JSTokenType tt, tt2;
+ JSParseNode *pn, *pn2;
+
+ tt = CURRENT_TOKEN(ts).type;
+ if (tt == TOK_RETURN && !(tc->flags & TCF_IN_FUNCTION)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_RETURN_OR_YIELD, js_return_str);
+ return NULL;
+ }
+
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+
+#if JS_HAS_GENERATORS
+ if (tt == TOK_YIELD)
+ tc->flags |= TCF_FUN_IS_GENERATOR;
+#endif
+
+ /* This is ugly, but we don't want to require a semicolon. */
+ ts->flags |= TSF_OPERAND;
+ tt2 = js_PeekTokenSameLine(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt2 == TOK_ERROR)
+ return NULL;
+
+ if (tt2 != TOK_EOF && tt2 != TOK_EOL && tt2 != TOK_SEMI && tt2 != TOK_RC
+#if JS_HAS_GENERATORS
+ && (tt != TOK_YIELD ||
+ (tt2 != tt && tt2 != TOK_RB && tt2 != TOK_RP &&
+ tt2 != TOK_COLON && tt2 != TOK_COMMA))
+#endif
+ ) {
+ pn2 = operandParser(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+#if JS_HAS_GENERATORS
+ if (tt == TOK_RETURN)
+#endif
+ tc->flags |= TCF_RETURN_EXPR;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_kid = pn2;
+ } else {
+#if JS_HAS_GENERATORS
+ if (tt == TOK_RETURN)
+#endif
+ tc->flags |= TCF_RETURN_VOID;
+ }
+
+ if ((~tc->flags & (TCF_RETURN_EXPR | TCF_FUN_IS_GENERATOR)) == 0) {
+ /* As in Python (see PEP-255), disallow return v; in generators. */
+ ReportBadReturn(cx, tc, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_RETURN,
+ JSMSG_BAD_ANON_GENERATOR_RETURN);
+ return NULL;
+ }
+
+ if (JS_HAS_STRICT_OPTION(cx) &&
+ (~tc->flags & (TCF_RETURN_EXPR | TCF_RETURN_VOID)) == 0 &&
+ !ReportBadReturn(cx, tc, JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_NO_RETURN_VALUE,
+ JSMSG_ANON_NO_RETURN_VALUE)) {
+ return NULL;
+ }
+
+ return pn;
+}
+
+static JSParseNode *
+PushLexicalScope(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSStmtInfo *stmtInfo)
+{
+ JSParseNode *pn;
+ JSObject *obj;
+ JSParsedObjectBox *blockpob;
+
+ pn = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn)
+ return NULL;
+
+ obj = js_NewBlockObject(cx);
+ if (!obj)
+ return NULL;
+
+ blockpob = js_NewParsedObjectBox(cx, tc->parseContext, obj);
+ if (!blockpob)
+ return NULL;
+
+ js_PushBlockScope(tc, stmtInfo, obj, -1);
+ pn->pn_type = TOK_LEXICALSCOPE;
+ pn->pn_op = JSOP_LEAVEBLOCK;
+ pn->pn_pob = blockpob;
+ pn->pn_slot = -1;
+ return pn;
+}
+
+#if JS_HAS_BLOCK_SCOPE
+
+static JSParseNode *
+LetBlock(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, JSBool statement)
+{
+ JSParseNode *pn, *pnblock, *pnlet;
+ JSStmtInfo stmtInfo;
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_LET);
+
+ /* Create the let binary node. */
+ pnlet = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pnlet)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_LET);
+
+ /* This is a let block or expression of the form: let (a, b, c) .... */
+ pnblock = PushLexicalScope(cx, ts, tc, &stmtInfo);
+ if (!pnblock)
+ return NULL;
+ pn = pnblock;
+ pn->pn_expr = pnlet;
+
+ pnlet->pn_left = Variables(cx, ts, tc);
+ if (!pnlet->pn_left)
+ return NULL;
+ pnlet->pn_left->pn_extra = PNX_POPVAR;
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_LET);
+
+ ts->flags |= TSF_OPERAND;
+ if (statement && !js_MatchToken(cx, ts, TOK_LC)) {
+ /*
+ * If this is really an expression in let statement guise, then we
+ * need to wrap the TOK_LET node in a TOK_SEMI node so that we pop
+ * the return value of the expression.
+ */
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_SEMI;
+ pn->pn_num = -1;
+ pn->pn_kid = pnblock;
+
+ statement = JS_FALSE;
+ }
+ ts->flags &= ~TSF_OPERAND;
+
+ if (statement) {
+ pnlet->pn_right = Statements(cx, ts, tc);
+ if (!pnlet->pn_right)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_LET);
+ } else {
+ /*
+ * Change pnblock's opcode to the variant that propagates the last
+ * result down after popping the block, and clear statement.
+ */
+ pnblock->pn_op = JSOP_LEAVEBLOCKEXPR;
+ pnlet->pn_right = AssignExpr(cx, ts, tc);
+ if (!pnlet->pn_right)
+ return NULL;
+ }
+
+ js_PopStatement(tc);
+ return pn;
+}
+
+#endif /* JS_HAS_BLOCK_SCOPE */
+
+static JSParseNode *
+Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSTokenType tt;
+ JSParseNode *pn, *pn1, *pn2, *pn3, *pn4;
+ JSStmtInfo stmtInfo, *stmt, *stmt2;
+ JSAtom *label;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+
+#if JS_HAS_GETTER_SETTER
+ if (tt == TOK_NAME) {
+ tt = CheckGetterOrSetter(cx, ts, TOK_FUNCTION);
+ if (tt == TOK_ERROR)
+ return NULL;
+ }
+#endif
+
+ switch (tt) {
+ case TOK_FUNCTION:
+#if JS_HAS_XML_SUPPORT
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ if (tt == TOK_DBLCOLON)
+ goto expression;
+#endif
+ return FunctionStmt(cx, ts, tc);
+
+ case TOK_IF:
+ /* An IF node has three kids: condition, then, and optional else. */
+ pn = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn)
+ return NULL;
+ pn1 = Condition(cx, ts, tc);
+ if (!pn1)
+ return NULL;
+ js_PushStatement(tc, &stmtInfo, STMT_IF, -1);
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ ts->flags |= TSF_OPERAND;
+ if (js_MatchToken(cx, ts, TOK_ELSE)) {
+ ts->flags &= ~TSF_OPERAND;
+ stmtInfo.type = STMT_ELSE;
+ pn3 = Statement(cx, ts, tc);
+ if (!pn3)
+ return NULL;
+ pn->pn_pos.end = pn3->pn_pos.end;
+ } else {
+ ts->flags &= ~TSF_OPERAND;
+ pn3 = NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ }
+ js_PopStatement(tc);
+ pn->pn_kid1 = pn1;
+ pn->pn_kid2 = pn2;
+ pn->pn_kid3 = pn3;
+ return pn;
+
+ case TOK_SWITCH:
+ {
+ JSParseNode *pn5, *saveBlock;
+ JSBool seenDefault = JS_FALSE;
+
+ pn = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_SWITCH);
+
+ /* pn1 points to the switch's discriminant. */
+ pn1 = ParenExpr(cx, ts, tc, NULL, NULL);
+ if (!pn1)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_SWITCH);
+ MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_SWITCH);
+
+ /* pn2 is a list of case nodes. The default case has pn_left == NULL */
+ pn2 = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn2)
+ return NULL;
+ saveBlock = tc->blockNode;
+ tc->blockNode = pn2;
+ PN_INIT_LIST(pn2);
+
+ js_PushStatement(tc, &stmtInfo, STMT_SWITCH, -1);
+
+ while ((tt = js_GetToken(cx, ts)) != TOK_RC) {
+ switch (tt) {
+ case TOK_DEFAULT:
+ if (seenDefault) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_TOO_MANY_DEFAULTS);
+ return NULL;
+ }
+ seenDefault = JS_TRUE;
+ /* FALL THROUGH */
+
+ case TOK_CASE:
+ pn3 = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn3)
+ return NULL;
+ if (tt == TOK_CASE) {
+ pn3->pn_left = Expr(cx, ts, tc);
+ if (!pn3->pn_left)
+ return NULL;
+ }
+ PN_APPEND(pn2, pn3);
+ if (pn2->pn_count == JS_BIT(16)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_TOO_MANY_CASES);
+ return NULL;
+ }
+ break;
+
+ case TOK_ERROR:
+ return NULL;
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_SWITCH);
+ return NULL;
+ }
+ MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
+
+ pn4 = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn4)
+ return NULL;
+ pn4->pn_type = TOK_LC;
+ PN_INIT_LIST(pn4);
+ ts->flags |= TSF_OPERAND;
+ while ((tt = js_PeekToken(cx, ts)) != TOK_RC &&
+ tt != TOK_CASE && tt != TOK_DEFAULT) {
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_ERROR)
+ return NULL;
+ pn5 = Statement(cx, ts, tc);
+ if (!pn5)
+ return NULL;
+ pn4->pn_pos.end = pn5->pn_pos.end;
+ PN_APPEND(pn4, pn5);
+ ts->flags |= TSF_OPERAND;
+ }
+ ts->flags &= ~TSF_OPERAND;
+
+ /* Fix the PN_LIST so it doesn't begin at the TOK_COLON. */
+ if (pn4->pn_head)
+ pn4->pn_pos.begin = pn4->pn_head->pn_pos.begin;
+ pn3->pn_pos.end = pn4->pn_pos.end;
+ pn3->pn_right = pn4;
+ }
+
+ /*
+ * Handle the case where there was a let declaration in any case in
+ * the switch body, but not within an inner block. If it replaced
+ * tc->blockNode with a new block node then we must refresh pn2 and
+ * then restore tc->blockNode.
+ */
+ if (tc->blockNode != pn2)
+ pn2 = tc->blockNode;
+ tc->blockNode = saveBlock;
+ js_PopStatement(tc);
+
+ pn->pn_pos.end = pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ pn->pn_left = pn1;
+ pn->pn_right = pn2;
+ return pn;
+ }
+
+ case TOK_WHILE:
+ pn = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn)
+ return NULL;
+ js_PushStatement(tc, &stmtInfo, STMT_WHILE_LOOP, -1);
+ pn2 = Condition(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_left = pn2;
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ js_PopStatement(tc);
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_right = pn2;
+ return pn;
+
+ case TOK_DO:
+ pn = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn)
+ return NULL;
+ js_PushStatement(tc, &stmtInfo, STMT_DO_LOOP, -1);
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_left = pn2;
+ MUST_MATCH_TOKEN(TOK_WHILE, JSMSG_WHILE_AFTER_DO);
+ pn2 = Condition(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ js_PopStatement(tc);
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_right = pn2;
+ if (JSVERSION_NUMBER(cx) != JSVERSION_ECMA_3) {
+ /*
+ * All legacy and extended versions must do automatic semicolon
+ * insertion after do-while. See the testcase and discussion in
+ * http://bugzilla.mozilla.org/show_bug.cgi?id=238945.
+ */
+ (void) js_MatchToken(cx, ts, TOK_SEMI);
+ return pn;
+ }
+ break;
+
+ case TOK_FOR:
+ {
+ JSParseNode *pnseq = NULL;
+#if JS_HAS_BLOCK_SCOPE
+ JSParseNode *pnlet = NULL;
+ JSStmtInfo blockInfo;
+#endif
+
+ /* A FOR node is binary, left is loop control and right is the body. */
+ pn = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn)
+ return NULL;
+ js_PushStatement(tc, &stmtInfo, STMT_FOR_LOOP, -1);
+
+ pn->pn_op = JSOP_ITER;
+ pn->pn_iflags = 0;
+ if (js_MatchToken(cx, ts, TOK_NAME)) {
+ if (CURRENT_TOKEN(ts).t_atom == cx->runtime->atomState.eachAtom)
+ pn->pn_iflags = JSITER_FOREACH;
+ else
+ js_UngetToken(ts);
+ }
+
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_SEMI) {
+ if (pn->pn_iflags & JSITER_FOREACH)
+ goto bad_for_each;
+
+ /* No initializer -- set first kid of left sub-node to null. */
+ pn1 = NULL;
+ } else {
+ /*
+ * Set pn1 to a var list or an initializing expression.
+ *
+ * Set the TCF_IN_FOR_INIT flag during parsing of the first clause
+ * of the for statement. This flag will be used by the RelExpr
+ * production; if it is set, then the 'in' keyword will not be
+ * recognized as an operator, leaving it available to be parsed as
+ * part of a for/in loop.
+ *
+ * A side effect of this restriction is that (unparenthesized)
+ * expressions involving an 'in' operator are illegal in the init
+ * clause of an ordinary for loop.
+ */
+ tc->flags |= TCF_IN_FOR_INIT;
+ if (tt == TOK_VAR) {
+ (void) js_GetToken(cx, ts);
+ pn1 = Variables(cx, ts, tc);
+#if JS_HAS_BLOCK_SCOPE
+ } else if (tt == TOK_LET) {
+ (void) js_GetToken(cx, ts);
+ if (js_PeekToken(cx, ts) == TOK_LP) {
+ pn1 = LetBlock(cx, ts, tc, JS_FALSE);
+ tt = TOK_LEXICALSCOPE;
+ } else {
+ pnlet = PushLexicalScope(cx, ts, tc, &blockInfo);
+ if (!pnlet)
+ return NULL;
+ blockInfo.flags |= SIF_FOR_BLOCK;
+ pn1 = Variables(cx, ts, tc);
+ }
+#endif
+ } else {
+ pn1 = Expr(cx, ts, tc);
+ if (pn1) {
+ while (pn1->pn_type == TOK_RP)
+ pn1 = pn1->pn_kid;
+ }
+ }
+ tc->flags &= ~TCF_IN_FOR_INIT;
+ if (!pn1)
+ return NULL;
+ }
+
+ /*
+ * We can be sure that it's a for/in loop if there's still an 'in'
+ * keyword here, even if JavaScript recognizes 'in' as an operator,
+ * as we've excluded 'in' from being parsed in RelExpr by setting
+ * the TCF_IN_FOR_INIT flag in our JSTreeContext.
+ */
+ if (pn1 && js_MatchToken(cx, ts, TOK_IN)) {
+ pn->pn_iflags |= JSITER_ENUMERATE;
+ stmtInfo.type = STMT_FOR_IN_LOOP;
+
+ /* Check that the left side of the 'in' is valid. */
+ JS_ASSERT(!TOKEN_TYPE_IS_DECL(tt) || pn1->pn_type == tt);
+ if (TOKEN_TYPE_IS_DECL(tt)
+ ? (pn1->pn_count > 1 || pn1->pn_op == JSOP_DEFCONST
+#if JS_HAS_DESTRUCTURING
+ || (JSVERSION_NUMBER(cx) == JSVERSION_1_7 &&
+ pn->pn_op == JSOP_ITER &&
+ !(pn->pn_iflags & JSITER_FOREACH) &&
+ (pn1->pn_head->pn_type == TOK_RC ||
+ (pn1->pn_head->pn_type == TOK_RB &&
+ pn1->pn_head->pn_count != 2) ||
+ (pn1->pn_head->pn_type == TOK_ASSIGN &&
+ (pn1->pn_head->pn_left->pn_type != TOK_RB ||
+ pn1->pn_head->pn_left->pn_count != 2))))
+#endif
+ )
+ : (pn1->pn_type != TOK_NAME &&
+ pn1->pn_type != TOK_DOT &&
+#if JS_HAS_DESTRUCTURING
+ ((JSVERSION_NUMBER(cx) == JSVERSION_1_7 &&
+ pn->pn_op == JSOP_ITER &&
+ !(pn->pn_iflags & JSITER_FOREACH))
+ ? (pn1->pn_type != TOK_RB || pn1->pn_count != 2)
+ : (pn1->pn_type != TOK_RB && pn1->pn_type != TOK_RC)) &&
+#endif
+#if JS_HAS_LVALUE_RETURN
+ pn1->pn_type != TOK_LP &&
+#endif
+#if JS_HAS_XML_SUPPORT
+ (pn1->pn_type != TOK_UNARYOP ||
+ pn1->pn_op != JSOP_XMLNAME) &&
+#endif
+ pn1->pn_type != TOK_LB)) {
+ js_ReportCompileErrorNumber(cx, ts, pn1, JSREPORT_ERROR,
+ JSMSG_BAD_FOR_LEFTSIDE);
+ return NULL;
+ }
+
+ /* pn2 points to the name or destructuring pattern on in's left. */
+ pn2 = NULL;
+
+ if (TOKEN_TYPE_IS_DECL(tt)) {
+ /* Tell js_EmitTree(TOK_VAR) that pn1 is part of a for/in. */
+ pn1->pn_extra |= PNX_FORINVAR;
+
+ /*
+ * Rewrite 'for (<decl> x = i in o)' where <decl> is 'let',
+ * 'var', or 'const' to hoist the initializer or the entire
+ * decl out of the loop head. TOK_VAR is the type for both
+ * 'var' and 'const'.
+ */
+ pn2 = pn1->pn_head;
+ if (pn2->pn_type == TOK_NAME && pn2->pn_expr
+#if JS_HAS_DESTRUCTURING
+ || pn2->pn_type == TOK_ASSIGN
+#endif
+ ) {
+ pnseq = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pnseq)
+ return NULL;
+ pnseq->pn_type = TOK_SEQ;
+ pnseq->pn_pos.begin = pn->pn_pos.begin;
+ if (tt == TOK_LET) {
+ /*
+ * Hoist just the 'i' from 'for (let x = i in o)' to
+ * before the loop, glued together via pnseq.
+ */
+ pn3 = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn3)
+ return NULL;
+ pn3->pn_type = TOK_SEMI;
+ pn3->pn_op = JSOP_NOP;
+#if JS_HAS_DESTRUCTURING
+ if (pn2->pn_type == TOK_ASSIGN) {
+ pn4 = pn2->pn_right;
+ pn2 = pn1->pn_head = pn2->pn_left;
+ } else
+#endif
+ {
+ pn4 = pn2->pn_expr;
+ pn2->pn_expr = NULL;
+ }
+ pn3->pn_pos = pn4->pn_pos;
+ pn3->pn_kid = pn4;
+ PN_INIT_LIST_1(pnseq, pn3);
+ } else {
+ /*
+ * All of 'var x = i' is hoisted above 'for (x in o)',
+ * so clear PNX_FORINVAR.
+ *
+ * Request JSOP_POP here since the var is for a simple
+ * name (it is not a destructuring binding's left-hand
+ * side) and it has an initializer.
+ */
+ pn1->pn_extra &= ~PNX_FORINVAR;
+ pn1->pn_extra |= PNX_POPVAR;
+ PN_INIT_LIST_1(pnseq, pn1);
+
+#if JS_HAS_DESTRUCTURING
+ if (pn2->pn_type == TOK_ASSIGN) {
+ pn1 = CloneParseTree(cx, pn2->pn_left, tc);
+ if (!pn1)
+ return NULL;
+ } else
+#endif
+ {
+ pn1 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn1)
+ return NULL;
+ pn1->pn_type = TOK_NAME;
+ pn1->pn_op = JSOP_NAME;
+ pn1->pn_pos = pn2->pn_pos;
+ pn1->pn_atom = pn2->pn_atom;
+ pn1->pn_expr = NULL;
+ pn1->pn_slot = -1;
+ pn1->pn_const = pn2->pn_const;
+ }
+ pn2 = pn1;
+ }
+ }
+ }
+
+ if (!pn2) {
+ pn2 = pn1;
+#if JS_HAS_LVALUE_RETURN
+ if (pn2->pn_type == TOK_LP &&
+ !MakeSetCall(cx, pn2, tc, JSMSG_BAD_LEFTSIDE_OF_ASS)) {
+ return NULL;
+ }
+#endif
+#if JS_HAS_XML_SUPPORT
+ if (pn2->pn_type == TOK_UNARYOP)
+ pn2->pn_op = JSOP_BINDXMLNAME;
+#endif
+ }
+
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ /* Beware 'for (arguments in ...)' with or without a 'var'. */
+ if (pn2->pn_atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ break;
+
+#if JS_HAS_DESTRUCTURING
+ case TOK_ASSIGN:
+ pn2 = pn2->pn_left;
+ JS_ASSERT(pn2->pn_type == TOK_RB || pn2->pn_type == TOK_RC);
+ /* FALL THROUGH */
+ case TOK_RB:
+ case TOK_RC:
+ /* Check for valid lvalues in var-less destructuring for-in. */
+ if (pn1 == pn2 && !CheckDestructuring(cx, NULL, pn2, NULL, tc))
+ return NULL;
+
+ if (JSVERSION_NUMBER(cx) == JSVERSION_1_7) {
+ /*
+ * Destructuring for-in requires [key, value] enumeration
+ * in JS1.7.
+ */
+ JS_ASSERT(pn->pn_op == JSOP_ITER);
+ if (!(pn->pn_iflags & JSITER_FOREACH))
+ pn->pn_iflags |= JSITER_FOREACH | JSITER_KEYVALUE;
+ }
+ break;
+#endif
+
+ default:;
+ }
+
+ /* Parse the object expression as the right operand of 'in'. */
+ pn2 = NewBinary(cx, TOK_IN, JSOP_NOP, pn1, Expr(cx, ts, tc), tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_left = pn2;
+ } else {
+ if (pn->pn_iflags & JSITER_FOREACH)
+ goto bad_for_each;
+ pn->pn_op = JSOP_NOP;
+
+ /* Parse the loop condition or null into pn2. */
+ MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_INIT);
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_SEMI) {
+ pn2 = NULL;
+ } else {
+ pn2 = Expr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ }
+
+ /* Parse the update expression or null into pn3. */
+ MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_COND);
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_RP) {
+ pn3 = NULL;
+ } else {
+ pn3 = Expr(cx, ts, tc);
+ if (!pn3)
+ return NULL;
+ }
+
+ /* Build the FORHEAD node to use as the left kid of pn. */
+ pn4 = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn4)
+ return NULL;
+ pn4->pn_type = TOK_FORHEAD;
+ pn4->pn_op = JSOP_NOP;
+ pn4->pn_kid1 = pn1;
+ pn4->pn_kid2 = pn2;
+ pn4->pn_kid3 = pn3;
+ pn->pn_left = pn4;
+ }
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_CTRL);
+
+ /* Parse the loop body into pn->pn_right. */
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_right = pn2;
+
+ /* Record the absolute line number for source note emission. */
+ pn->pn_pos.end = pn2->pn_pos.end;
+
+#if JS_HAS_BLOCK_SCOPE
+ if (pnlet) {
+ js_PopStatement(tc);
+ pnlet->pn_expr = pn;
+ pn = pnlet;
+ }
+#endif
+ if (pnseq) {
+ pnseq->pn_pos.end = pn->pn_pos.end;
+ PN_APPEND(pnseq, pn);
+ pn = pnseq;
+ }
+ js_PopStatement(tc);
+ return pn;
+
+ bad_for_each:
+ js_ReportCompileErrorNumber(cx, ts, pn, JSREPORT_ERROR,
+ JSMSG_BAD_FOR_EACH_LOOP);
+ return NULL;
+ }
+
+ case TOK_TRY: {
+ JSParseNode *catchList, *lastCatch;
+
+ /*
+ * try nodes are ternary.
+ * kid1 is the try Statement
+ * kid2 is the catch node list or null
+ * kid3 is the finally Statement
+ *
+ * catch nodes are ternary.
+ * kid1 is the lvalue (TOK_NAME, TOK_LB, or TOK_LC)
+ * kid2 is the catch guard or null if no guard
+ * kid3 is the catch block
+ *
+ * catch lvalue nodes are either:
+ * TOK_NAME for a single identifier
+ * TOK_RB or TOK_RC for a destructuring left-hand side
+ *
+ * finally nodes are TOK_LC Statement lists.
+ */
+ pn = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_op = JSOP_NOP;
+
+ MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY);
+ js_PushStatement(tc, &stmtInfo, STMT_TRY, -1);
+ pn->pn_kid1 = Statements(cx, ts, tc);
+ if (!pn->pn_kid1)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_TRY);
+ js_PopStatement(tc);
+
+ catchList = NULL;
+ tt = js_GetToken(cx, ts);
+ if (tt == TOK_CATCH) {
+ catchList = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!catchList)
+ return NULL;
+ catchList->pn_type = TOK_RESERVED;
+ PN_INIT_LIST(catchList);
+ lastCatch = NULL;
+
+ do {
+ JSParseNode *pnblock;
+ BindData data;
+
+ /* Check for another catch after unconditional catch. */
+ if (lastCatch && !lastCatch->pn_kid2) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_CATCH_AFTER_GENERAL);
+ return NULL;
+ }
+
+ /*
+ * Create a lexical scope node around the whole catch clause,
+ * including the head.
+ */
+ pnblock = PushLexicalScope(cx, ts, tc, &stmtInfo);
+ if (!pnblock)
+ return NULL;
+ stmtInfo.type = STMT_CATCH;
+
+ /*
+ * Legal catch forms are:
+ * catch (lhs)
+ * catch (lhs if <boolean_expression>)
+ * where lhs is a name or a destructuring left-hand side.
+ * (the latter is legal only #ifdef JS_HAS_CATCH_GUARD)
+ */
+ pn2 = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn2)
+ return NULL;
+ pnblock->pn_expr = pn2;
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_CATCH);
+
+ /*
+ * Contrary to ECMA Ed. 3, the catch variable is lexically
+ * scoped, not a property of a new Object instance. This is
+ * an intentional change that anticipates ECMA Ed. 4.
+ */
+ data.pn = NULL;
+ data.op = JSOP_NOP;
+ data.binder = BindLet;
+ data.u.let.overflow = JSMSG_TOO_MANY_CATCH_VARS;
+
+ tt = js_GetToken(cx, ts);
+ switch (tt) {
+#if JS_HAS_DESTRUCTURING
+ case TOK_LB:
+ case TOK_LC:
+ pn3 = DestructuringExpr(cx, &data, tc, tt);
+ if (!pn3)
+ return NULL;
+ break;
+#endif
+
+ case TOK_NAME:
+ label = CURRENT_TOKEN(ts).t_atom;
+ if (!data.binder(cx, &data, label, tc))
+ return NULL;
+
+ pn3 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn3)
+ return NULL;
+ pn3->pn_atom = label;
+ pn3->pn_slot = -1;
+ break;
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_CATCH_IDENTIFIER);
+ return NULL;
+ }
+
+ pn2->pn_kid1 = pn3;
+#if JS_HAS_CATCH_GUARD
+ /*
+ * We use 'catch (x if x === 5)' (not 'catch (x : x === 5)')
+ * to avoid conflicting with the JS2/ECMAv4 type annotation
+ * catchguard syntax.
+ */
+ if (js_MatchToken(cx, ts, TOK_IF)) {
+ pn2->pn_kid2 = Expr(cx, ts, tc);
+ if (!pn2->pn_kid2)
+ return NULL;
+ }
+#endif
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_CATCH);
+
+ MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CATCH);
+ pn2->pn_kid3 = Statements(cx, ts, tc);
+ if (!pn2->pn_kid3)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_CATCH);
+ js_PopStatement(tc);
+
+ PN_APPEND(catchList, pnblock);
+ lastCatch = pn2;
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ } while (tt == TOK_CATCH);
+ }
+ pn->pn_kid2 = catchList;
+
+ if (tt == TOK_FINALLY) {
+ MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_FINALLY);
+ js_PushStatement(tc, &stmtInfo, STMT_FINALLY, -1);
+ pn->pn_kid3 = Statements(cx, ts, tc);
+ if (!pn->pn_kid3)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_FINALLY);
+ js_PopStatement(tc);
+ } else {
+ js_UngetToken(ts);
+ }
+ if (!catchList && !pn->pn_kid3) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_CATCH_OR_FINALLY);
+ return NULL;
+ }
+ return pn;
+ }
+
+ case TOK_THROW:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+
+ /* ECMA-262 Edition 3 says 'throw [no LineTerminator here] Expr'. */
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekTokenSameLine(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_ERROR)
+ return NULL;
+ if (tt == TOK_EOF || tt == TOK_EOL || tt == TOK_SEMI || tt == TOK_RC) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+
+ pn2 = Expr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_op = JSOP_THROW;
+ pn->pn_kid = pn2;
+ break;
+
+ /* TOK_CATCH and TOK_FINALLY are both handled in the TOK_TRY case */
+ case TOK_CATCH:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_CATCH_WITHOUT_TRY);
+ return NULL;
+
+ case TOK_FINALLY:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_FINALLY_WITHOUT_TRY);
+ return NULL;
+
+ case TOK_BREAK:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ if (!MatchLabel(cx, ts, pn))
+ return NULL;
+ stmt = tc->topStmt;
+ label = pn->pn_atom;
+ if (label) {
+ for (; ; stmt = stmt->down) {
+ if (!stmt) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_LABEL_NOT_FOUND);
+ return NULL;
+ }
+ if (stmt->type == STMT_LABEL && stmt->u.label == label)
+ break;
+ }
+ } else {
+ for (; ; stmt = stmt->down) {
+ if (!stmt) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_TOUGH_BREAK);
+ return NULL;
+ }
+ if (STMT_IS_LOOP(stmt) || stmt->type == STMT_SWITCH)
+ break;
+ }
+ }
+ if (label)
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ break;
+
+ case TOK_CONTINUE:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ if (!MatchLabel(cx, ts, pn))
+ return NULL;
+ stmt = tc->topStmt;
+ label = pn->pn_atom;
+ if (label) {
+ for (stmt2 = NULL; ; stmt = stmt->down) {
+ if (!stmt) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_LABEL_NOT_FOUND);
+ return NULL;
+ }
+ if (stmt->type == STMT_LABEL) {
+ if (stmt->u.label == label) {
+ if (!stmt2 || !STMT_IS_LOOP(stmt2)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_ERROR,
+ JSMSG_BAD_CONTINUE);
+ return NULL;
+ }
+ break;
+ }
+ } else {
+ stmt2 = stmt;
+ }
+ }
+ } else {
+ for (; ; stmt = stmt->down) {
+ if (!stmt) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_CONTINUE);
+ return NULL;
+ }
+ if (STMT_IS_LOOP(stmt))
+ break;
+ }
+ }
+ if (label)
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ break;
+
+ case TOK_WITH:
+ pn = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_WITH);
+ pn2 = ParenExpr(cx, ts, tc, NULL, NULL);
+ if (!pn2)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_WITH);
+ pn->pn_left = pn2;
+
+ js_PushStatement(tc, &stmtInfo, STMT_WITH, -1);
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ js_PopStatement(tc);
+
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_right = pn2;
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ return pn;
+
+ case TOK_VAR:
+ pn = Variables(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+ /* Tell js_EmitTree to generate a final POP. */
+ pn->pn_extra |= PNX_POPVAR;
+ break;
+
+#if JS_HAS_BLOCK_SCOPE
+ case TOK_LET:
+ {
+ JSObject *obj;
+ JSParsedObjectBox *blockpob;
+
+ /* Check for a let statement or let expression. */
+ if (js_PeekToken(cx, ts) == TOK_LP) {
+ pn = LetBlock(cx, ts, tc, JS_TRUE);
+ if (!pn || pn->pn_op == JSOP_LEAVEBLOCK)
+ return pn;
+
+ /* Let expressions require automatic semicolon insertion. */
+ JS_ASSERT(pn->pn_type == TOK_SEMI ||
+ pn->pn_op == JSOP_LEAVEBLOCKEXPR);
+ break;
+ }
+
+ /*
+ * This is a let declaration. We must be directly under a block per
+ * the proposed ES4 specs, but not an implicit block created due to
+ * 'for (let ...)'. If we pass this error test, make the enclosing
+ * JSStmtInfo be our scope. Further let declarations in this block
+ * will find this scope statement and use the same block object.
+ *
+ * If we are the first let declaration in this block (i.e., when the
+ * enclosing maybe-scope JSStmtInfo isn't yet a scope statement) then
+ * we also need to set tc->blockNode to be our TOK_LEXICALSCOPE.
+ */
+ stmt = tc->topStmt;
+ if (stmt &&
+ (!STMT_MAYBE_SCOPE(stmt) || (stmt->flags & SIF_FOR_BLOCK))) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_LET_DECL_NOT_IN_BLOCK);
+ return NULL;
+ }
+
+ if (stmt && (stmt->flags & SIF_SCOPE)) {
+ JS_ASSERT(tc->blockChain == stmt->u.blockObj);
+ obj = tc->blockChain;
+ } else {
+ if (!stmt || (stmt->flags & SIF_BODY_BLOCK)) {
+ /*
+ * ES4 specifies that let at top level and at body-block scope
+ * does not shadow var, so convert back to var.
+ */
+ CURRENT_TOKEN(ts).type = TOK_VAR;
+ CURRENT_TOKEN(ts).t_op = JSOP_DEFVAR;
+
+ pn = Variables(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_extra |= PNX_POPVAR;
+ break;
+ }
+
+ /*
+ * Some obvious assertions here, but they may help clarify the
+ * situation. This stmt is not yet a scope, so it must not be a
+ * catch block (which is a lexical scope by definition).
+ */
+ JS_ASSERT(!(stmt->flags & SIF_SCOPE));
+ JS_ASSERT(stmt != tc->topScopeStmt);
+ JS_ASSERT(stmt->type == STMT_BLOCK ||
+ stmt->type == STMT_SWITCH ||
+ stmt->type == STMT_TRY ||
+ stmt->type == STMT_FINALLY);
+ JS_ASSERT(!stmt->downScope);
+
+ /* Convert the block statement into a scope statement. */
+ obj = js_NewBlockObject(cx);
+ if (!obj)
+ return NULL;
+ blockpob = js_NewParsedObjectBox(cx, tc->parseContext, obj);
+ if (!blockpob)
+ return NULL;
+
+ /*
+ * Insert stmt on the tc->topScopeStmt/stmtInfo.downScope linked
+ * list stack, if it isn't already there. If it is there, but it
+ * lacks the SIF_SCOPE flag, it must be a try, catch, or finally
+ * block.
+ */
+ stmt->flags |= SIF_SCOPE;
+ stmt->downScope = tc->topScopeStmt;
+ tc->topScopeStmt = stmt;
+ JS_SCOPE_DEPTH_METERING(++tc->scopeDepth > tc->maxScopeDepth &&
+ (tc->maxScopeDepth = tc->scopeDepth));
+
+ STOBJ_SET_PARENT(obj, tc->blockChain);
+ tc->blockChain = obj;
+ stmt->u.blockObj = obj;
+
+#ifdef DEBUG
+ pn1 = tc->blockNode;
+ JS_ASSERT(!pn1 || pn1->pn_type != TOK_LEXICALSCOPE);
+#endif
+
+ /* Create a new lexical scope node for these statements. */
+ pn1 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn1)
+ return NULL;
+
+ pn1->pn_type = TOK_LEXICALSCOPE;
+ pn1->pn_op = JSOP_LEAVEBLOCK;
+ pn1->pn_pos = tc->blockNode->pn_pos;
+ pn1->pn_pob = blockpob;
+ pn1->pn_expr = tc->blockNode;
+ pn1->pn_slot = -1;
+ tc->blockNode = pn1;
+ }
+
+ pn = Variables(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_extra = PNX_POPVAR;
+ break;
+ }
+#endif /* JS_HAS_BLOCK_SCOPE */
+
+ case TOK_RETURN:
+ pn = ReturnOrYield(cx, ts, tc, Expr);
+ if (!pn)
+ return NULL;
+ break;
+
+ case TOK_LC:
+ {
+ uintN oldflags;
+
+ oldflags = tc->flags;
+ tc->flags = oldflags & ~TCF_HAS_FUNCTION_STMT;
+ js_PushStatement(tc, &stmtInfo, STMT_BLOCK, -1);
+ pn = Statements(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_COMPOUND);
+ js_PopStatement(tc);
+
+ /*
+ * If we contain a function statement and our container is top-level
+ * or another block, flag pn to preserve braces when decompiling.
+ */
+ if ((tc->flags & TCF_HAS_FUNCTION_STMT) &&
+ (!tc->topStmt || tc->topStmt->type == STMT_BLOCK)) {
+ pn->pn_extra |= PNX_NEEDBRACES;
+ }
+ tc->flags = oldflags | (tc->flags & (TCF_FUN_FLAGS | TCF_RETURN_FLAGS));
+ return pn;
+ }
+
+ case TOK_EOL:
+ case TOK_SEMI:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_SEMI;
+ return pn;
+
+#if JS_HAS_DEBUGGER_KEYWORD
+ case TOK_DEBUGGER:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_DEBUGGER;
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ break;
+#endif /* JS_HAS_DEBUGGER_KEYWORD */
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_DEFAULT:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ if (!js_MatchToken(cx, ts, TOK_NAME) ||
+ CURRENT_TOKEN(ts).t_atom != cx->runtime->atomState.xmlAtom ||
+ !js_MatchToken(cx, ts, TOK_NAME) ||
+ CURRENT_TOKEN(ts).t_atom != cx->runtime->atomState.namespaceAtom ||
+ !js_MatchToken(cx, ts, TOK_ASSIGN) ||
+ CURRENT_TOKEN(ts).t_op != JSOP_NOP) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_DEFAULT_XML_NAMESPACE);
+ return NULL;
+ }
+ pn2 = Expr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_op = JSOP_DEFXMLNS;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_kid = pn2;
+ tc->flags |= TCF_HAS_DEFXMLNS;
+ break;
+#endif
+
+ case TOK_ERROR:
+ return NULL;
+
+ default:
+#if JS_HAS_XML_SUPPORT
+ expression:
+#endif
+ js_UngetToken(ts);
+ pn2 = Expr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+
+ if (js_PeekToken(cx, ts) == TOK_COLON) {
+ if (pn2->pn_type != TOK_NAME) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_LABEL);
+ return NULL;
+ }
+ label = pn2->pn_atom;
+ for (stmt = tc->topStmt; stmt; stmt = stmt->down) {
+ if (stmt->type == STMT_LABEL && stmt->u.label == label) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_DUPLICATE_LABEL);
+ return NULL;
+ }
+ }
+ (void) js_GetToken(cx, ts);
+
+ /* Push a label struct and parse the statement. */
+ js_PushStatement(tc, &stmtInfo, STMT_LABEL, -1);
+ stmtInfo.u.label = label;
+ pn = Statement(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+ /* Normalize empty statement to empty block for the decompiler. */
+ if (pn->pn_type == TOK_SEMI && !pn->pn_kid) {
+ pn->pn_type = TOK_LC;
+ pn->pn_arity = PN_LIST;
+ PN_INIT_LIST(pn);
+ }
+
+ /* Pop the label, set pn_expr, and return early. */
+ js_PopStatement(tc);
+ pn2->pn_type = TOK_COLON;
+ pn2->pn_pos.end = pn->pn_pos.end;
+ pn2->pn_expr = pn;
+ return pn2;
+ }
+
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_SEMI;
+ pn->pn_pos = pn2->pn_pos;
+ pn->pn_kid = pn2;
+ break;
+ }
+
+ /* Check termination of this primitive statement. */
+ if (ON_CURRENT_LINE(ts, pn->pn_pos)) {
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekTokenSameLine(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_ERROR)
+ return NULL;
+ if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SEMI_BEFORE_STMNT);
+ return NULL;
+ }
+ }
+
+ (void) js_MatchToken(cx, ts, TOK_SEMI);
+ return pn;
+}
+
+static JSParseNode *
+Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSTokenType tt;
+ JSBool let;
+ JSStmtInfo *scopeStmt;
+ BindData data;
+ JSParseNode *pn, *pn2;
+ JSAtom *atom;
+
+ /*
+ * The three options here are:
+ * - TOK_LET: We are parsing a let declaration.
+ * - TOK_LP: We are parsing the head of a let block.
+ * - Otherwise, we're parsing var declarations.
+ */
+ tt = CURRENT_TOKEN(ts).type;
+ let = (tt == TOK_LET || tt == TOK_LP);
+ JS_ASSERT(let || tt == TOK_VAR);
+
+ /* Make sure that Statement set the tree context up correctly. */
+ scopeStmt = tc->topScopeStmt;
+ if (let) {
+ while (scopeStmt && !(scopeStmt->flags & SIF_SCOPE)) {
+ JS_ASSERT(!STMT_MAYBE_SCOPE(scopeStmt));
+ scopeStmt = scopeStmt->downScope;
+ }
+ JS_ASSERT(scopeStmt);
+ }
+
+ data.pn = NULL;
+ data.op = let ? JSOP_NOP : CURRENT_TOKEN(ts).t_op;
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_op = data.op;
+ PN_INIT_LIST(pn);
+
+ /*
+ * The tricky part of this code is to create special parsenode opcodes for
+ * getting and setting variables (which will be stored as special slots in
+ * the frame). The most complicated case is an eval() inside a function.
+ * If the evaluated string references variables in the enclosing function,
+ * then we need to generate the special variable opcodes. We determine
+ * this by looking up the variable's id in the current variable object.
+ * Fortunately, we can avoid doing this for let declared variables.
+ */
+ if (let) {
+ JS_ASSERT(tc->blockChain == scopeStmt->u.blockObj);
+ data.binder = BindLet;
+ data.u.let.overflow = JSMSG_TOO_MANY_LOCALS;
+ } else {
+ data.binder = BindVarOrConst;
+ }
+
+ do {
+ tt = js_GetToken(cx, ts);
+#if JS_HAS_DESTRUCTURING
+ if (tt == TOK_LB || tt == TOK_LC) {
+ pn2 = PrimaryExpr(cx, ts, tc, tt, JS_FALSE);
+ if (!pn2)
+ return NULL;
+
+ if ((tc->flags & TCF_IN_FOR_INIT) &&
+ js_PeekToken(cx, ts) == TOK_IN) {
+ if (!CheckDestructuring(cx, &data, pn2, NULL, tc))
+ return NULL;
+ PN_APPEND(pn, pn2);
+ continue;
+ }
+
+ MUST_MATCH_TOKEN(TOK_ASSIGN, JSMSG_BAD_DESTRUCT_DECL);
+ if (CURRENT_TOKEN(ts).t_op != JSOP_NOP)
+ goto bad_var_init;
+
+ pn2 = NewBinary(cx, TOK_ASSIGN, JSOP_NOP,
+ pn2, AssignExpr(cx, ts, tc),
+ tc);
+ if (!pn2 ||
+ !CheckDestructuring(cx, &data,
+ pn2->pn_left, pn2->pn_right,
+ tc)) {
+ return NULL;
+ }
+ PN_APPEND(pn, pn2);
+ continue;
+ }
+#endif
+
+ if (tt != TOK_NAME) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_NO_VARIABLE_NAME);
+ return NULL;
+ }
+ atom = CURRENT_TOKEN(ts).t_atom;
+ if (!data.binder(cx, &data, atom, tc))
+ return NULL;
+
+ pn2 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_op = JSOP_NAME;
+ pn2->pn_atom = atom;
+ pn2->pn_slot = -1;
+ if (!let)
+ pn2->pn_const = (data.op == JSOP_DEFCONST);
+ PN_APPEND(pn, pn2);
+
+ if (js_MatchToken(cx, ts, TOK_ASSIGN)) {
+ if (CURRENT_TOKEN(ts).t_op != JSOP_NOP)
+ goto bad_var_init;
+
+ pn2->pn_expr = AssignExpr(cx, ts, tc);
+ if (!pn2->pn_expr)
+ return NULL;
+ pn2->pn_op = (!let && data.op == JSOP_DEFCONST)
+ ? JSOP_SETCONST
+ : JSOP_SETNAME;
+ if (!let && atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ }
+ } while (js_MatchToken(cx, ts, TOK_COMMA));
+
+ pn->pn_pos.end = PN_LAST(pn)->pn_pos.end;
+ return pn;
+
+bad_var_init:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_VAR_INIT);
+ return NULL;
+}
+
+static JSParseNode *
+Expr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2;
+
+ pn = AssignExpr(cx, ts, tc);
+ if (pn && js_MatchToken(cx, ts, TOK_COMMA)) {
+ pn2 = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+ PN_INIT_LIST_1(pn2, pn);
+ pn = pn2;
+ do {
+#if JS_HAS_GENERATORS
+ pn2 = PN_LAST(pn);
+ if (pn2->pn_type == TOK_YIELD) {
+ js_ReportCompileErrorNumber(cx, ts, pn2, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_yield_str);
+ return NULL;
+ }
+#endif
+ pn2 = AssignExpr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ PN_APPEND(pn, pn2);
+ } while (js_MatchToken(cx, ts, TOK_COMMA));
+ pn->pn_pos.end = PN_LAST(pn)->pn_pos.end;
+ }
+ return pn;
+}
+
+static JSParseNode *
+AssignExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2;
+ JSTokenType tt;
+ JSOp op;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+#if JS_HAS_GENERATORS
+ ts->flags |= TSF_OPERAND;
+ if (js_MatchToken(cx, ts, TOK_YIELD)) {
+ ts->flags &= ~TSF_OPERAND;
+ return ReturnOrYield(cx, ts, tc, AssignExpr);
+ }
+ ts->flags &= ~TSF_OPERAND;
+#endif
+
+ pn = CondExpr(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+ tt = js_GetToken(cx, ts);
+#if JS_HAS_GETTER_SETTER
+ if (tt == TOK_NAME) {
+ tt = CheckGetterOrSetter(cx, ts, TOK_ASSIGN);
+ if (tt == TOK_ERROR)
+ return NULL;
+ }
+#endif
+ if (tt != TOK_ASSIGN) {
+ js_UngetToken(ts);
+ return pn;
+ }
+
+ op = CURRENT_TOKEN(ts).t_op;
+ for (pn2 = pn; pn2->pn_type == TOK_RP; pn2 = pn2->pn_kid)
+ continue;
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ pn2->pn_op = JSOP_SETNAME;
+ if (pn2->pn_atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ break;
+ case TOK_DOT:
+ pn2->pn_op = JSOP_SETPROP;
+ break;
+ case TOK_LB:
+ pn2->pn_op = JSOP_SETELEM;
+ break;
+#if JS_HAS_DESTRUCTURING
+ case TOK_RB:
+ case TOK_RC:
+ if (op != JSOP_NOP) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_DESTRUCT_ASS);
+ return NULL;
+ }
+ pn = AssignExpr(cx, ts, tc);
+ if (!pn || !CheckDestructuring(cx, NULL, pn2, pn, tc))
+ return NULL;
+ return NewBinary(cx, TOK_ASSIGN, op, pn2, pn, tc);
+#endif
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ if (!MakeSetCall(cx, pn2, tc, JSMSG_BAD_LEFTSIDE_OF_ASS))
+ return NULL;
+ break;
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ if (pn2->pn_op == JSOP_XMLNAME) {
+ pn2->pn_op = JSOP_SETXMLNAME;
+ break;
+ }
+ /* FALL THROUGH */
+#endif
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_LEFTSIDE_OF_ASS);
+ return NULL;
+ }
+
+ return NewBinary(cx, TOK_ASSIGN, op, pn2, AssignExpr(cx, ts, tc), tc);
+}
+
+static JSParseNode *
+CondExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn1, *pn2, *pn3;
+ uintN oldflags;
+
+ pn = OrExpr(cx, ts, tc);
+ if (pn && js_MatchToken(cx, ts, TOK_HOOK)) {
+ pn1 = pn;
+ pn = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn)
+ return NULL;
+ /*
+ * Always accept the 'in' operator in the middle clause of a ternary,
+ * where it's unambiguous, even if we might be parsing the init of a
+ * for statement.
+ */
+ oldflags = tc->flags;
+ tc->flags &= ~TCF_IN_FOR_INIT;
+ pn2 = AssignExpr(cx, ts, tc);
+ tc->flags = oldflags | (tc->flags & TCF_FUN_FLAGS);
+
+ if (!pn2)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_IN_COND);
+ pn3 = AssignExpr(cx, ts, tc);
+ if (!pn3)
+ return NULL;
+ pn->pn_pos.begin = pn1->pn_pos.begin;
+ pn->pn_pos.end = pn3->pn_pos.end;
+ pn->pn_kid1 = pn1;
+ pn->pn_kid2 = pn2;
+ pn->pn_kid3 = pn3;
+ }
+ return pn;
+}
+
+static JSParseNode *
+OrExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = AndExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_OR))
+ pn = NewBinary(cx, TOK_OR, JSOP_OR, pn, AndExpr(cx, ts, tc), tc);
+ return pn;
+}
+
+static JSParseNode *
+AndExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = BitOrExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_AND))
+ pn = NewBinary(cx, TOK_AND, JSOP_AND, pn, BitOrExpr(cx, ts, tc), tc);
+ return pn;
+}
+
+static JSParseNode *
+BitOrExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = BitXorExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_BITOR)) {
+ pn = NewBinary(cx, TOK_BITOR, JSOP_BITOR, pn, BitXorExpr(cx, ts, tc),
+ tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+BitXorExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = BitAndExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_BITXOR)) {
+ pn = NewBinary(cx, TOK_BITXOR, JSOP_BITXOR, pn, BitAndExpr(cx, ts, tc),
+ tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+BitAndExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = EqExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_BITAND))
+ pn = NewBinary(cx, TOK_BITAND, JSOP_BITAND, pn, EqExpr(cx, ts, tc), tc);
+ return pn;
+}
+
+static JSParseNode *
+EqExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSOp op;
+
+ pn = RelExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_EQOP)) {
+ op = CURRENT_TOKEN(ts).t_op;
+ pn = NewBinary(cx, TOK_EQOP, op, pn, RelExpr(cx, ts, tc), tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+RelExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSTokenType tt;
+ JSOp op;
+ uintN inForInitFlag = tc->flags & TCF_IN_FOR_INIT;
+
+ /*
+ * Uses of the in operator in ShiftExprs are always unambiguous,
+ * so unset the flag that prohibits recognizing it.
+ */
+ tc->flags &= ~TCF_IN_FOR_INIT;
+
+ pn = ShiftExpr(cx, ts, tc);
+ while (pn &&
+ (js_MatchToken(cx, ts, TOK_RELOP) ||
+ /*
+ * Recognize the 'in' token as an operator only if we're not
+ * currently in the init expr of a for loop.
+ */
+ (inForInitFlag == 0 && js_MatchToken(cx, ts, TOK_IN)) ||
+ js_MatchToken(cx, ts, TOK_INSTANCEOF))) {
+ tt = CURRENT_TOKEN(ts).type;
+ op = CURRENT_TOKEN(ts).t_op;
+ pn = NewBinary(cx, tt, op, pn, ShiftExpr(cx, ts, tc), tc);
+ }
+ /* Restore previous state of inForInit flag. */
+ tc->flags |= inForInitFlag;
+
+ return pn;
+}
+
+static JSParseNode *
+ShiftExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSOp op;
+
+ pn = AddExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_SHOP)) {
+ op = CURRENT_TOKEN(ts).t_op;
+ pn = NewBinary(cx, TOK_SHOP, op, pn, AddExpr(cx, ts, tc), tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+AddExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSTokenType tt;
+ JSOp op;
+
+ pn = MulExpr(cx, ts, tc);
+ while (pn &&
+ (js_MatchToken(cx, ts, TOK_PLUS) ||
+ js_MatchToken(cx, ts, TOK_MINUS))) {
+ tt = CURRENT_TOKEN(ts).type;
+ op = (tt == TOK_PLUS) ? JSOP_ADD : JSOP_SUB;
+ pn = NewBinary(cx, tt, op, pn, MulExpr(cx, ts, tc), tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+MulExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSTokenType tt;
+ JSOp op;
+
+ pn = UnaryExpr(cx, ts, tc);
+ while (pn &&
+ (js_MatchToken(cx, ts, TOK_STAR) ||
+ js_MatchToken(cx, ts, TOK_DIVOP))) {
+ tt = CURRENT_TOKEN(ts).type;
+ op = CURRENT_TOKEN(ts).t_op;
+ pn = NewBinary(cx, tt, op, pn, UnaryExpr(cx, ts, tc), tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+SetLvalKid(JSContext *cx, JSTokenStream *ts, JSParseNode *pn, JSParseNode *kid,
+ const char *name)
+{
+ while (kid->pn_type == TOK_RP)
+ kid = kid->pn_kid;
+ if (kid->pn_type != TOK_NAME &&
+ kid->pn_type != TOK_DOT &&
+#if JS_HAS_LVALUE_RETURN
+ (kid->pn_type != TOK_LP ||
+ (kid->pn_op != JSOP_CALL && kid->pn_op != JSOP_EVAL && kid->pn_op != JSOP_APPLY)) &&
+#endif
+#if JS_HAS_XML_SUPPORT
+ (kid->pn_type != TOK_UNARYOP || kid->pn_op != JSOP_XMLNAME) &&
+#endif
+ kid->pn_type != TOK_LB) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_OPERAND, name);
+ return NULL;
+ }
+ pn->pn_kid = kid;
+ return kid;
+}
+
+static const char incop_name_str[][10] = {"increment", "decrement"};
+
+static JSBool
+SetIncOpKid(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSParseNode *pn, JSParseNode *kid,
+ JSTokenType tt, JSBool preorder)
+{
+ JSOp op;
+
+ kid = SetLvalKid(cx, ts, pn, kid, incop_name_str[tt == TOK_DEC]);
+ if (!kid)
+ return JS_FALSE;
+ switch (kid->pn_type) {
+ case TOK_NAME:
+ op = (tt == TOK_INC)
+ ? (preorder ? JSOP_INCNAME : JSOP_NAMEINC)
+ : (preorder ? JSOP_DECNAME : JSOP_NAMEDEC);
+ if (kid->pn_atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ break;
+
+ case TOK_DOT:
+ op = (tt == TOK_INC)
+ ? (preorder ? JSOP_INCPROP : JSOP_PROPINC)
+ : (preorder ? JSOP_DECPROP : JSOP_PROPDEC);
+ break;
+
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ if (!MakeSetCall(cx, kid, tc, JSMSG_BAD_INCOP_OPERAND))
+ return JS_FALSE;
+ /* FALL THROUGH */
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ if (kid->pn_op == JSOP_XMLNAME)
+ kid->pn_op = JSOP_SETXMLNAME;
+ /* FALL THROUGH */
+#endif
+ case TOK_LB:
+ op = (tt == TOK_INC)
+ ? (preorder ? JSOP_INCELEM : JSOP_ELEMINC)
+ : (preorder ? JSOP_DECELEM : JSOP_ELEMDEC);
+ break;
+
+ default:
+ JS_ASSERT(0);
+ op = JSOP_NOP;
+ }
+ pn->pn_op = op;
+ return JS_TRUE;
+}
+
+static JSParseNode *
+UnaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSTokenType tt;
+ JSParseNode *pn, *pn2;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+
+ switch (tt) {
+ case TOK_UNARYOP:
+ case TOK_PLUS:
+ case TOK_MINUS:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_UNARYOP; /* PLUS and MINUS are binary */
+ pn->pn_op = CURRENT_TOKEN(ts).t_op;
+ pn2 = UnaryExpr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_kid = pn2;
+ break;
+
+ case TOK_INC:
+ case TOK_DEC:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn2 = MemberExpr(cx, ts, tc, JS_TRUE);
+ if (!pn2)
+ return NULL;
+ if (!SetIncOpKid(cx, ts, tc, pn, pn2, tt, JS_TRUE))
+ return NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ break;
+
+ case TOK_DELETE:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn2 = UnaryExpr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+
+ /*
+ * Under ECMA3, deleting any unary expression is valid -- it simply
+ * returns true. Here we strip off any parentheses and fold constants
+ * before checking for a call expression, in order to rule out delete
+ * of a generator expression.
+ */
+ while (pn2->pn_type == TOK_RP)
+ pn2 = pn2->pn_kid;
+ if (!js_FoldConstants(cx, pn2, tc))
+ return NULL;
+ if (pn2->pn_type == TOK_LP &&
+ pn2->pn_op != JSOP_SETCALL &&
+ !MakeSetCall(cx, pn2, tc, JSMSG_BAD_DELETE_OPERAND)) {
+ return NULL;
+ }
+ pn->pn_kid = pn2;
+ break;
+
+ case TOK_ERROR:
+ return NULL;
+
+ default:
+ js_UngetToken(ts);
+ pn = MemberExpr(cx, ts, tc, JS_TRUE);
+ if (!pn)
+ return NULL;
+
+ /* Don't look across a newline boundary for a postfix incop. */
+ if (ON_CURRENT_LINE(ts, pn->pn_pos)) {
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekTokenSameLine(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_INC || tt == TOK_DEC) {
+ (void) js_GetToken(cx, ts);
+ pn2 = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn2)
+ return NULL;
+ if (!SetIncOpKid(cx, ts, tc, pn2, pn, tt, JS_FALSE))
+ return NULL;
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+ pn = pn2;
+ }
+ }
+ break;
+ }
+ return pn;
+}
+
+#if JS_HAS_GENERATORS
+
+/*
+ * Starting from a |for| keyword after the first array initialiser element or
+ * an expression in an open parenthesis, parse the tail of the comprehension
+ * or generator expression signified by this |for| keyword in context.
+ *
+ * Return null on failure, else return the top-most parse node for the array
+ * comprehension or generator expression, with a unary node as the body of the
+ * (possibly nested) for-loop, initialized by |type, op, kid|.
+ */
+static JSParseNode *
+ComprehensionTail(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSTokenType type, JSOp op, JSParseNode *kid)
+{
+ JSParseNode *pn, *pn2, *pn3, **pnp;
+ JSStmtInfo stmtInfo;
+ BindData data;
+ JSRuntime *rt;
+ JSTokenType tt;
+ JSAtom *atom;
+
+ JS_ASSERT(type == TOK_SEMI || type == TOK_ARRAYPUSH);
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_FOR);
+
+ /*
+ * Make a parse-node and literal object representing the block scope of
+ * this array comprehension or generator expression.
+ */
+ pn = PushLexicalScope(cx, ts, tc, &stmtInfo);
+ if (!pn)
+ return NULL;
+ pnp = &pn->pn_expr;
+
+ data.pn = NULL;
+ data.op = JSOP_NOP;
+ data.binder = BindLet;
+ data.u.let.overflow = JSMSG_ARRAY_INIT_TOO_BIG;
+
+ rt = cx->runtime;
+ do {
+ /*
+ * FOR node is binary, left is loop control and right is body. Use
+ * index to count each block-local let-variable on the left-hand side
+ * of the IN.
+ */
+ pn2 = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn2)
+ return NULL;
+
+ pn2->pn_op = JSOP_ITER;
+ pn2->pn_iflags = JSITER_ENUMERATE;
+ if (js_MatchToken(cx, ts, TOK_NAME)) {
+ if (CURRENT_TOKEN(ts).t_atom == rt->atomState.eachAtom)
+ pn2->pn_iflags |= JSITER_FOREACH;
+ else
+ js_UngetToken(ts);
+ }
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
+
+ tt = js_GetToken(cx, ts);
+ switch (tt) {
+#if JS_HAS_DESTRUCTURING
+ case TOK_LB:
+ case TOK_LC:
+ pn3 = DestructuringExpr(cx, &data, tc, tt);
+ if (!pn3)
+ return NULL;
+
+ if (pn3->pn_type != TOK_RB || pn3->pn_count != 2) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_FOR_LEFTSIDE);
+ return NULL;
+ }
+
+ if (JSVERSION_NUMBER(cx) == JSVERSION_1_7) {
+ /* Destructuring requires [key, value] enumeration in JS1.7. */
+ JS_ASSERT(pn2->pn_op == JSOP_ITER);
+ JS_ASSERT(pn2->pn_iflags & JSITER_ENUMERATE);
+ if (!(pn2->pn_iflags & JSITER_FOREACH))
+ pn2->pn_iflags |= JSITER_FOREACH | JSITER_KEYVALUE;
+ }
+ break;
+#endif
+
+ case TOK_NAME:
+ atom = CURRENT_TOKEN(ts).t_atom;
+ if (!data.binder(cx, &data, atom, tc))
+ return NULL;
+
+ /*
+ * Create a name node with pn_op JSOP_NAME. We can't set pn_op to
+ * JSOP_GETLOCAL here, because we don't yet know the block's depth
+ * in the operand stack frame. The code generator computes that,
+ * and it tries to bind all names to slots, so we must let it do
+ * the deed.
+ */
+ pn3 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn3)
+ return NULL;
+ pn3->pn_op = JSOP_NAME;
+ pn3->pn_atom = atom;
+ pn3->pn_slot = -1;
+ break;
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_NO_VARIABLE_NAME);
+
+ case TOK_ERROR:
+ return NULL;
+ }
+
+ MUST_MATCH_TOKEN(TOK_IN, JSMSG_IN_AFTER_FOR_NAME);
+ pn3 = NewBinary(cx, TOK_IN, JSOP_NOP, pn3,
+ Expr(cx, ts, tc), tc);
+ if (!pn3)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_CTRL);
+ pn2->pn_left = pn3;
+ *pnp = pn2;
+ pnp = &pn2->pn_right;
+ } while (js_MatchToken(cx, ts, TOK_FOR));
+
+ if (js_MatchToken(cx, ts, TOK_IF)) {
+ pn2 = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_kid1 = Condition(cx, ts, tc);
+ if (!pn2->pn_kid1)
+ return NULL;
+ *pnp = pn2;
+ pnp = &pn2->pn_kid2;
+ }
+
+ pn2 = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_type = type;
+ pn2->pn_op = op;
+ pn2->pn_kid = kid;
+ *pnp = pn2;
+
+ js_PopStatement(tc);
+ return pn;
+}
+
+#if JS_HAS_GENERATOR_EXPRS
+
+/*
+ * Starting from a |for| keyword after an expression, parse the comprehension
+ * tail completing this generator expression. Wrap the expression at kid in a
+ * generator function that is immediately called to evaluate to the generator
+ * iterator that is the value of this generator expression.
+ *
+ * Callers pass a blank unary node via pn, which GeneratorExpr fills in as the
+ * yield expression, which ComprehensionTail in turn wraps in a TOK_SEMI-type
+ * expression-statement node that constitutes the body of the |for| loop(s) in
+ * the generator function.
+ *
+ * Note how unlike Python, we do not evaluate the expression to the right of
+ * the first |in| in the chain of |for| heads. Instead, a generator expression
+ * is merely sugar for a generator function expression and its application.
+ */
+static JSParseNode *
+GeneratorExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ uintN oldflags, JSParseNode *pn, JSParseNode *kid)
+{
+ JSParseNode *body, *lambda;
+ JSFunction *fun;
+
+ /* Initialize pn, connecting it to kid. */
+ JS_ASSERT(pn->pn_arity == PN_UNARY);
+ pn->pn_type = TOK_YIELD;
+ pn->pn_op = JSOP_YIELD;
+ pn->pn_pos = kid->pn_pos;
+ pn->pn_kid = kid;
+ pn->pn_hidden = JS_TRUE;
+
+ /*
+ * Parse the comprehension tail at hand, making pn the kid of the loop
+ * body's expression statement.
+ */
+ body = ComprehensionTail(cx, ts, tc, TOK_SEMI, JSOP_NOP, pn);
+ if (!body)
+ return NULL;
+ body->pn_pos.begin = kid->pn_pos.begin;
+
+ /*
+ * Make the generator function and flag it as interpreted ASAP (see the
+ * comment in FunctionBody).
+ */
+ fun = NewCompilerFunction(cx, tc, NULL, JSFUN_LAMBDA);
+ if (!fun)
+ return NULL;
+
+ /*
+ * This generator function is referenced by an anonymous function object
+ * node. Here is where we must take care to propagate certain tc->flags
+ * that may have changed from oldflags to reflect crucial facts about the
+ * expression on the left of |for| and in the comprehension tail after it.
+ */
+ lambda = NewParseNode(cx, ts, PN_FUNC, tc);
+ if (!lambda)
+ return NULL;
+ lambda->pn_type = TOK_FUNCTION;
+ lambda->pn_op = JSOP_ANONFUNOBJ;
+ lambda->pn_pos.begin = body->pn_pos.begin;
+ lambda->pn_funpob = js_NewParsedObjectBox(cx, tc->parseContext,
+ FUN_OBJECT(fun));
+ if (!lambda->pn_funpob)
+ return NULL;
+ lambda->pn_body = body;
+ lambda->pn_flags = TCF_FUN_IS_GENERATOR | TCF_GENEXP_LAMBDA |
+ ((oldflags ^ tc->flags) & TCF_FUN_FLAGS);
+
+ /*
+ * Re-use pn to name the result node, a call expression invoking the
+ * anonymous generator function object.
+ */
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_LP;
+ pn->pn_op = JSOP_CALL;
+ pn->pn_pos.begin = lambda->pn_pos.begin;
+ PN_INIT_LIST_1(pn, lambda);
+
+ body->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ tc->flags = oldflags;
+ return pn;
+}
+
+static const char js_generator_str[] = "generator";
+
+#endif /* JS_HAS_GENERATOR_EXPRS */
+#endif /* JS_HAS_GENERATORS */
+
+static JSBool
+ArgumentList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSParseNode *listNode)
+{
+ JSBool matched;
+
+ ts->flags |= TSF_OPERAND;
+ matched = js_MatchToken(cx, ts, TOK_RP);
+ ts->flags &= ~TSF_OPERAND;
+ if (!matched) {
+ do {
+#if JS_HAS_GENERATOR_EXPRS
+ uintN oldflags = tc->flags;
+#endif
+ JSParseNode *argNode = AssignExpr(cx, ts, tc);
+ if (!argNode)
+ return JS_FALSE;
+#if JS_HAS_GENERATORS
+ if (argNode->pn_type == TOK_YIELD &&
+ js_PeekToken(cx, ts) == TOK_COMMA) {
+ js_ReportCompileErrorNumber(cx, ts, argNode, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_yield_str);
+ return JS_FALSE;
+ }
+#endif
+#if JS_HAS_GENERATOR_EXPRS
+ if (js_MatchToken(cx, ts, TOK_FOR)) {
+ JSParseNode *pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return JS_FALSE;
+ argNode = GeneratorExpr(cx, ts, tc, oldflags, pn, argNode);
+ if (!argNode)
+ return JS_FALSE;
+ if (listNode->pn_count > 1 ||
+ js_PeekToken(cx, ts) == TOK_COMMA) {
+ js_ReportCompileErrorNumber(cx, ts, argNode, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_generator_str);
+ return JS_FALSE;
+ }
+ }
+#endif
+ PN_APPEND(listNode, argNode);
+ } while (js_MatchToken(cx, ts, TOK_COMMA));
+
+ if (js_GetToken(cx, ts) != TOK_RP) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_PAREN_AFTER_ARGS);
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSParseNode *
+MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSBool allowCallSyntax)
+{
+ JSParseNode *pn, *pn2, *pn3;
+ JSTokenType tt;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ /* Check for new expression first. */
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_NEW) {
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ pn2 = MemberExpr(cx, ts, tc, JS_FALSE);
+ if (!pn2)
+ return NULL;
+ pn->pn_op = JSOP_NEW;
+ PN_INIT_LIST_1(pn, pn2);
+ pn->pn_pos.begin = pn2->pn_pos.begin;
+
+ if (js_MatchToken(cx, ts, TOK_LP) && !ArgumentList(cx, ts, tc, pn))
+ return NULL;
+ if (pn->pn_count > ARGC_LIMIT) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_TOO_MANY_CON_ARGS);
+ return NULL;
+ }
+ pn->pn_pos.end = PN_LAST(pn)->pn_pos.end;
+ } else {
+ pn = PrimaryExpr(cx, ts, tc, tt, JS_FALSE);
+ if (!pn)
+ return NULL;
+
+ if (pn->pn_type == TOK_ANYNAME ||
+ pn->pn_type == TOK_AT ||
+ pn->pn_type == TOK_DBLCOLON) {
+ pn2 = NewOrRecycledNode(cx, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_type = TOK_UNARYOP;
+ pn2->pn_pos = pn->pn_pos;
+ pn2->pn_op = JSOP_XMLNAME;
+ pn2->pn_arity = PN_UNARY;
+ pn2->pn_kid = pn;
+ pn = pn2;
+ }
+ }
+
+ while ((tt = js_GetToken(cx, ts)) > TOK_EOF) {
+ if (tt == TOK_DOT) {
+ pn2 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_slot = -1;
+#if JS_HAS_XML_SUPPORT
+ ts->flags |= TSF_OPERAND | TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~(TSF_OPERAND | TSF_KEYWORD_IS_NAME);
+ pn3 = PrimaryExpr(cx, ts, tc, tt, JS_TRUE);
+ if (!pn3)
+ return NULL;
+ tt = PN_TYPE(pn3);
+ if (tt == TOK_NAME) {
+ pn2->pn_op = JSOP_GETPROP;
+ pn2->pn_expr = pn;
+ pn2->pn_atom = pn3->pn_atom;
+ RecycleTree(pn3, tc);
+ } else {
+ if (TOKEN_TYPE_IS_XML(tt)) {
+ pn2->pn_type = TOK_LB;
+ pn2->pn_op = JSOP_GETELEM;
+ } else if (tt == TOK_RP) {
+ JSParseNode *group = pn3;
+
+ /* Recycle the useless TOK_RP node. */
+ pn3 = group->pn_kid;
+ group->pn_kid = NULL;
+ RecycleTree(group, tc);
+ pn2->pn_type = TOK_FILTER;
+ pn2->pn_op = JSOP_FILTER;
+
+ /* A filtering predicate is like a with statement. */
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ } else {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_NAME_AFTER_DOT);
+ return NULL;
+ }
+ pn2->pn_arity = PN_BINARY;
+ pn2->pn_left = pn;
+ pn2->pn_right = pn3;
+ }
+#else
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NAME_AFTER_DOT);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ pn2->pn_op = JSOP_GETPROP;
+ pn2->pn_expr = pn;
+ pn2->pn_atom = CURRENT_TOKEN(ts).t_atom;
+#endif
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+ pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+#if JS_HAS_XML_SUPPORT
+ } else if (tt == TOK_DBLDOT) {
+ pn2 = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn2)
+ return NULL;
+ ts->flags |= TSF_OPERAND | TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~(TSF_OPERAND | TSF_KEYWORD_IS_NAME);
+ pn3 = PrimaryExpr(cx, ts, tc, tt, JS_TRUE);
+ if (!pn3)
+ return NULL;
+ tt = PN_TYPE(pn3);
+ if (tt == TOK_NAME) {
+ pn3->pn_type = TOK_STRING;
+ pn3->pn_arity = PN_NULLARY;
+ pn3->pn_op = JSOP_QNAMEPART;
+ } else if (!TOKEN_TYPE_IS_XML(tt)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_NAME_AFTER_DOT);
+ return NULL;
+ }
+ pn2->pn_op = JSOP_DESCENDANTS;
+ pn2->pn_left = pn;
+ pn2->pn_right = pn3;
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+ pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+#endif
+ } else if (tt == TOK_LB) {
+ pn2 = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn2)
+ return NULL;
+ pn3 = Expr(cx, ts, tc);
+ if (!pn3)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX);
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+ pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+
+ /*
+ * Optimize o['p'] to o.p by rewriting pn2, but avoid rewriting
+ * o['0'] to use JSOP_GETPROP, to keep fast indexing disjoint in
+ * the interpreter from fast property access. However, if the
+ * bracketed string is a uint32, we rewrite pn3 to be a number
+ * instead of a string.
+ */
+ do {
+ if (pn3->pn_type == TOK_STRING) {
+ jsuint index;
+
+ if (!js_IdIsIndex(ATOM_TO_JSID(pn3->pn_atom), &index)) {
+ pn2->pn_type = TOK_DOT;
+ pn2->pn_op = JSOP_GETPROP;
+ pn2->pn_arity = PN_NAME;
+ pn2->pn_expr = pn;
+ pn2->pn_atom = pn3->pn_atom;
+ break;
+ }
+ pn3->pn_type = TOK_NUMBER;
+ pn3->pn_op = JSOP_DOUBLE;
+ pn3->pn_dval = index;
+ }
+ pn2->pn_op = JSOP_GETELEM;
+ pn2->pn_left = pn;
+ pn2->pn_right = pn3;
+ } while (0);
+ } else if (allowCallSyntax && tt == TOK_LP) {
+ pn2 = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn2)
+ return NULL;
+
+ pn2->pn_op = JSOP_CALL;
+ if (pn->pn_op == JSOP_NAME &&
+ pn->pn_atom == cx->runtime->atomState.evalAtom) {
+ /* Pick JSOP_EVAL and flag tc as heavyweight if eval(...). */
+ pn2->pn_op = JSOP_EVAL;
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ } else if (pn->pn_op == JSOP_GETPROP &&
+ (pn->pn_atom == cx->runtime->atomState.applyAtom ||
+ pn->pn_atom == cx->runtime->atomState.callAtom)) {
+ /* Pick JSOP_APPLY if apply(...). */
+ pn2->pn_op = JSOP_APPLY;
+ }
+
+ PN_INIT_LIST_1(pn2, pn);
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+
+ if (!ArgumentList(cx, ts, tc, pn2))
+ return NULL;
+ if (pn2->pn_count > ARGC_LIMIT) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_TOO_MANY_FUN_ARGS);
+ return NULL;
+ }
+ pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ } else {
+ js_UngetToken(ts);
+ return pn;
+ }
+
+ pn = pn2;
+ }
+ if (tt == TOK_ERROR)
+ return NULL;
+ return pn;
+}
+
+static JSParseNode *
+BracketedExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ uintN oldflags;
+ JSParseNode *pn;
+
+ /*
+ * Always accept the 'in' operator in a parenthesized expression,
+ * where it's unambiguous, even if we might be parsing the init of a
+ * for statement.
+ */
+ oldflags = tc->flags;
+ tc->flags &= ~TCF_IN_FOR_INIT;
+ pn = Expr(cx, ts, tc);
+ tc->flags = oldflags | (tc->flags & TCF_FUN_FLAGS);
+ return pn;
+}
+
+#if JS_HAS_XML_SUPPORT
+
+static JSParseNode *
+EndBracketedExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = BracketedExpr(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_ATTR_EXPR);
+ return pn;
+}
+
+/*
+ * From the ECMA-357 grammar in 11.1.1 and 11.1.2:
+ *
+ * AttributeIdentifier:
+ * @ PropertySelector
+ * @ QualifiedIdentifier
+ * @ [ Expression ]
+ *
+ * PropertySelector:
+ * Identifier
+ * *
+ *
+ * QualifiedIdentifier:
+ * PropertySelector :: PropertySelector
+ * PropertySelector :: [ Expression ]
+ *
+ * We adapt AttributeIdentifier and QualifiedIdentier to be LL(1), like so:
+ *
+ * AttributeIdentifier:
+ * @ QualifiedIdentifier
+ * @ [ Expression ]
+ *
+ * PropertySelector:
+ * Identifier
+ * *
+ *
+ * QualifiedIdentifier:
+ * PropertySelector :: PropertySelector
+ * PropertySelector :: [ Expression ]
+ * PropertySelector
+ *
+ * As PrimaryExpression: Identifier is in ECMA-262 and we want the semantics
+ * for that rule to result in a name node, but ECMA-357 extends the grammar
+ * to include PrimaryExpression: QualifiedIdentifier, we must factor further:
+ *
+ * QualifiedIdentifier:
+ * PropertySelector QualifiedSuffix
+ *
+ * QualifiedSuffix:
+ * :: PropertySelector
+ * :: [ Expression ]
+ * /nothing/
+ *
+ * And use this production instead of PrimaryExpression: QualifiedIdentifier:
+ *
+ * PrimaryExpression:
+ * Identifier QualifiedSuffix
+ *
+ * We hoist the :: match into callers of QualifiedSuffix, in order to tweak
+ * PropertySelector vs. Identifier pn_arity, pn_op, and other members.
+ */
+static JSParseNode *
+PropertySelector(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ if (pn->pn_type == TOK_STAR) {
+ pn->pn_type = TOK_ANYNAME;
+ pn->pn_op = JSOP_ANYNAME;
+ pn->pn_atom = cx->runtime->atomState.starAtom;
+ } else {
+ JS_ASSERT(pn->pn_type == TOK_NAME);
+ pn->pn_op = JSOP_QNAMEPART;
+ pn->pn_arity = PN_NAME;
+ pn->pn_atom = CURRENT_TOKEN(ts).t_atom;
+ pn->pn_slot = -1;
+ }
+ return pn;
+}
+
+static JSParseNode *
+QualifiedSuffix(JSContext *cx, JSTokenStream *ts, JSParseNode *pn,
+ JSTreeContext *tc)
+{
+ JSParseNode *pn2, *pn3;
+ JSTokenType tt;
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_DBLCOLON);
+ pn2 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn2)
+ return NULL;
+
+ /* Left operand of :: must be evaluated if it is an identifier. */
+ if (pn->pn_op == JSOP_QNAMEPART)
+ pn->pn_op = JSOP_NAME;
+
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ if (tt == TOK_STAR || tt == TOK_NAME) {
+ /* Inline and specialize PropertySelector for JSOP_QNAMECONST. */
+ pn2->pn_op = JSOP_QNAMECONST;
+ pn2->pn_atom = (tt == TOK_STAR)
+ ? cx->runtime->atomState.starAtom
+ : CURRENT_TOKEN(ts).t_atom;
+ pn2->pn_expr = pn;
+ pn2->pn_slot = -1;
+ return pn2;
+ }
+
+ if (tt != TOK_LB) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+ pn3 = EndBracketedExpr(cx, ts, tc);
+ if (!pn3)
+ return NULL;
+
+ pn2->pn_op = JSOP_QNAME;
+ pn2->pn_arity = PN_BINARY;
+ pn2->pn_left = pn;
+ pn2->pn_right = pn3;
+ return pn2;
+}
+
+static JSParseNode *
+QualifiedIdentifier(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = PropertySelector(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ if (js_MatchToken(cx, ts, TOK_DBLCOLON))
+ pn = QualifiedSuffix(cx, ts, pn, tc);
+ return pn;
+}
+
+static JSParseNode *
+AttributeIdentifier(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2;
+ JSTokenType tt;
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_AT);
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_op = JSOP_TOATTRNAME;
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ if (tt == TOK_STAR || tt == TOK_NAME) {
+ pn2 = QualifiedIdentifier(cx, ts, tc);
+ } else if (tt == TOK_LB) {
+ pn2 = EndBracketedExpr(cx, ts, tc);
+ } else {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+ if (!pn2)
+ return NULL;
+ pn->pn_kid = pn2;
+ return pn;
+}
+
+/*
+ * Make a TOK_LC unary node whose pn_kid is an expression.
+ */
+static JSParseNode *
+XMLExpr(JSContext *cx, JSTokenStream *ts, JSBool inTag, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2;
+ uintN oldflags;
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_LC);
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+
+ /*
+ * Turn off XML tag mode, but don't restore it after parsing this braced
+ * expression. Instead, simply restore ts's old flags. This is required
+ * because XMLExpr is called both from within a tag, and from within text
+ * contained in an element, but outside of any start, end, or point tag.
+ */
+ oldflags = ts->flags;
+ ts->flags = oldflags & ~TSF_XMLTAGMODE;
+ pn2 = Expr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_XML_EXPR);
+ ts->flags = oldflags;
+ pn->pn_kid = pn2;
+ pn->pn_op = inTag ? JSOP_XMLTAGEXPR : JSOP_XMLELTEXPR;
+ return pn;
+}
+
+/*
+ * Make a terminal node for one of TOK_XMLNAME, TOK_XMLATTR, TOK_XMLSPACE,
+ * TOK_XMLTEXT, TOK_XMLCDATA, TOK_XMLCOMMENT, or TOK_XMLPI. When converting
+ * parse tree to XML, we preserve a TOK_XMLSPACE node only if it's the sole
+ * child of a container tag.
+ */
+static JSParseNode *
+XMLAtomNode(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSToken *tp;
+
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ tp = &CURRENT_TOKEN(ts);
+ pn->pn_op = tp->t_op;
+ pn->pn_atom = tp->t_atom;
+ if (tp->type == TOK_XMLPI)
+ pn->pn_atom2 = tp->t_atom2;
+ return pn;
+}
+
+/*
+ * Parse the productions:
+ *
+ * XMLNameExpr:
+ * XMLName XMLNameExpr?
+ * { Expr } XMLNameExpr?
+ *
+ * Return a PN_LIST, PN_UNARY, or PN_NULLARY according as XMLNameExpr produces
+ * a list of names and/or expressions, a single expression, or a single name.
+ * If PN_LIST or PN_NULLARY, pn_type will be TOK_XMLNAME; if PN_UNARY, pn_type
+ * will be TOK_LC.
+ */
+static JSParseNode *
+XMLNameExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2, *list;
+ JSTokenType tt;
+
+ pn = list = NULL;
+ do {
+ tt = CURRENT_TOKEN(ts).type;
+ if (tt == TOK_LC) {
+ pn2 = XMLExpr(cx, ts, JS_TRUE, tc);
+ if (!pn2)
+ return NULL;
+ } else {
+ JS_ASSERT(tt == TOK_XMLNAME);
+ pn2 = XMLAtomNode(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ }
+
+ if (!pn) {
+ pn = pn2;
+ } else {
+ if (!list) {
+ list = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!list)
+ return NULL;
+ list->pn_type = TOK_XMLNAME;
+ list->pn_pos.begin = pn->pn_pos.begin;
+ PN_INIT_LIST_1(list, pn);
+ list->pn_extra = PNX_CANTFOLD;
+ pn = list;
+ }
+ pn->pn_pos.end = pn2->pn_pos.end;
+ PN_APPEND(pn, pn2);
+ }
+ } while ((tt = js_GetToken(cx, ts)) == TOK_XMLNAME || tt == TOK_LC);
+
+ js_UngetToken(ts);
+ return pn;
+}
+
+/*
+ * Macro to test whether an XMLNameExpr or XMLTagContent node can be folded
+ * at compile time into a JSXML tree.
+ */
+#define XML_FOLDABLE(pn) ((pn)->pn_arity == PN_LIST \
+ ? ((pn)->pn_extra & PNX_CANTFOLD) == 0 \
+ : (pn)->pn_type != TOK_LC)
+
+/*
+ * Parse the productions:
+ *
+ * XMLTagContent:
+ * XMLNameExpr
+ * XMLTagContent S XMLNameExpr S? = S? XMLAttr
+ * XMLTagContent S XMLNameExpr S? = S? { Expr }
+ *
+ * Return a PN_LIST, PN_UNARY, or PN_NULLARY according to how XMLTagContent
+ * produces a list of name and attribute values and/or braced expressions, a
+ * single expression, or a single name.
+ *
+ * If PN_LIST or PN_NULLARY, pn_type will be TOK_XMLNAME for the case where
+ * XMLTagContent: XMLNameExpr. If pn_type is not TOK_XMLNAME but pn_arity is
+ * PN_LIST, pn_type will be tagtype. If PN_UNARY, pn_type will be TOK_LC and
+ * we parsed exactly one expression.
+ */
+static JSParseNode *
+XMLTagContent(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSTokenType tagtype, JSAtom **namep)
+{
+ JSParseNode *pn, *pn2, *list;
+ JSTokenType tt;
+
+ pn = XMLNameExpr(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ *namep = (pn->pn_arity == PN_NULLARY) ? pn->pn_atom : NULL;
+ list = NULL;
+
+ while (js_MatchToken(cx, ts, TOK_XMLSPACE)) {
+ tt = js_GetToken(cx, ts);
+ if (tt != TOK_XMLNAME && tt != TOK_LC) {
+ js_UngetToken(ts);
+ break;
+ }
+
+ pn2 = XMLNameExpr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ if (!list) {
+ list = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!list)
+ return NULL;
+ list->pn_type = tagtype;
+ list->pn_pos.begin = pn->pn_pos.begin;
+ PN_INIT_LIST_1(list, pn);
+ pn = list;
+ }
+ PN_APPEND(pn, pn2);
+ if (!XML_FOLDABLE(pn2))
+ pn->pn_extra |= PNX_CANTFOLD;
+
+ js_MatchToken(cx, ts, TOK_XMLSPACE);
+ MUST_MATCH_TOKEN(TOK_ASSIGN, JSMSG_NO_ASSIGN_IN_XML_ATTR);
+ js_MatchToken(cx, ts, TOK_XMLSPACE);
+
+ tt = js_GetToken(cx, ts);
+ if (tt == TOK_XMLATTR) {
+ pn2 = XMLAtomNode(cx, ts, tc);
+ } else if (tt == TOK_LC) {
+ pn2 = XMLExpr(cx, ts, JS_TRUE, tc);
+ pn->pn_extra |= PNX_CANTFOLD;
+ } else {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_ATTR_VALUE);
+ return NULL;
+ }
+ if (!pn2)
+ return NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ PN_APPEND(pn, pn2);
+ }
+
+ return pn;
+}
+
+#define XML_CHECK_FOR_ERROR_AND_EOF(tt,result) \
+ JS_BEGIN_MACRO \
+ if ((tt) <= TOK_EOF) { \
+ if ((tt) == TOK_EOF) { \
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, \
+ JSMSG_END_OF_XML_SOURCE); \
+ } \
+ return result; \
+ } \
+ JS_END_MACRO
+
+static JSParseNode *
+XMLElementOrList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSBool allowList);
+
+/*
+ * Consume XML element tag content, including the TOK_XMLETAGO (</) sequence
+ * that opens the end tag for the container.
+ */
+static JSBool
+XMLElementContent(JSContext *cx, JSTokenStream *ts, JSParseNode *pn,
+ JSTreeContext *tc)
+{
+ JSTokenType tt;
+ JSParseNode *pn2;
+ JSAtom *textAtom;
+
+ ts->flags &= ~TSF_XMLTAGMODE;
+ for (;;) {
+ ts->flags |= TSF_XMLTEXTMODE;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_XMLTEXTMODE;
+ XML_CHECK_FOR_ERROR_AND_EOF(tt, JS_FALSE);
+
+ JS_ASSERT(tt == TOK_XMLSPACE || tt == TOK_XMLTEXT);
+ textAtom = CURRENT_TOKEN(ts).t_atom;
+ if (textAtom) {
+ /* Non-zero-length XML text scanned. */
+ pn2 = XMLAtomNode(cx, ts, tc);
+ if (!pn2)
+ return JS_FALSE;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ PN_APPEND(pn, pn2);
+ }
+
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ XML_CHECK_FOR_ERROR_AND_EOF(tt, JS_FALSE);
+ if (tt == TOK_XMLETAGO)
+ break;
+
+ if (tt == TOK_LC) {
+ pn2 = XMLExpr(cx, ts, JS_FALSE, tc);
+ pn->pn_extra |= PNX_CANTFOLD;
+ } else if (tt == TOK_XMLSTAGO) {
+ pn2 = XMLElementOrList(cx, ts, tc, JS_FALSE);
+ if (pn2) {
+ pn2->pn_extra &= ~PNX_XMLROOT;
+ pn->pn_extra |= pn2->pn_extra;
+ }
+ } else {
+ JS_ASSERT(tt == TOK_XMLCDATA || tt == TOK_XMLCOMMENT ||
+ tt == TOK_XMLPI);
+ pn2 = XMLAtomNode(cx, ts, tc);
+ }
+ if (!pn2)
+ return JS_FALSE;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ PN_APPEND(pn, pn2);
+ }
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_XMLETAGO);
+ ts->flags |= TSF_XMLTAGMODE;
+ return JS_TRUE;
+}
+
+/*
+ * Return a PN_LIST node containing an XML or XMLList Initialiser.
+ */
+static JSParseNode *
+XMLElementOrList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSBool allowList)
+{
+ JSParseNode *pn, *pn2, *list;
+ JSTokenType tt;
+ JSAtom *startAtom, *endAtom;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_XMLSTAGO);
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+
+ ts->flags |= TSF_XMLTAGMODE;
+ tt = js_GetToken(cx, ts);
+ if (tt == TOK_ERROR)
+ return NULL;
+
+ if (tt == TOK_XMLNAME || tt == TOK_LC) {
+ /*
+ * XMLElement. Append the tag and its contents, if any, to pn.
+ */
+ pn2 = XMLTagContent(cx, ts, tc, TOK_XMLSTAGO, &startAtom);
+ if (!pn2)
+ return NULL;
+ js_MatchToken(cx, ts, TOK_XMLSPACE);
+
+ tt = js_GetToken(cx, ts);
+ if (tt == TOK_XMLPTAGC) {
+ /* Point tag (/>): recycle pn if pn2 is a list of tag contents. */
+ if (pn2->pn_type == TOK_XMLSTAGO) {
+ PN_INIT_LIST(pn);
+ RecycleTree(pn, tc);
+ pn = pn2;
+ } else {
+ JS_ASSERT(pn2->pn_type == TOK_XMLNAME ||
+ pn2->pn_type == TOK_LC);
+ PN_INIT_LIST_1(pn, pn2);
+ if (!XML_FOLDABLE(pn2))
+ pn->pn_extra |= PNX_CANTFOLD;
+ }
+ pn->pn_type = TOK_XMLPTAGC;
+ pn->pn_extra |= PNX_XMLROOT;
+ } else {
+ /* We had better have a tag-close (>) at this point. */
+ if (tt != TOK_XMLTAGC) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_TAG_SYNTAX);
+ return NULL;
+ }
+ pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+
+ /* Make sure pn2 is a TOK_XMLSTAGO list containing tag contents. */
+ if (pn2->pn_type != TOK_XMLSTAGO) {
+ PN_INIT_LIST_1(pn, pn2);
+ if (!XML_FOLDABLE(pn2))
+ pn->pn_extra |= PNX_CANTFOLD;
+ pn2 = pn;
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ }
+
+ /* Now make pn a nominal-root TOK_XMLELEM list containing pn2. */
+ pn->pn_type = TOK_XMLELEM;
+ PN_INIT_LIST_1(pn, pn2);
+ if (!XML_FOLDABLE(pn2))
+ pn->pn_extra |= PNX_CANTFOLD;
+ pn->pn_extra |= PNX_XMLROOT;
+
+ /* Get element contents and delimiting end-tag-open sequence. */
+ if (!XMLElementContent(cx, ts, pn, tc))
+ return NULL;
+
+ tt = js_GetToken(cx, ts);
+ XML_CHECK_FOR_ERROR_AND_EOF(tt, NULL);
+ if (tt != TOK_XMLNAME && tt != TOK_LC) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_TAG_SYNTAX);
+ return NULL;
+ }
+
+ /* Parse end tag; check mismatch at compile-time if we can. */
+ pn2 = XMLTagContent(cx, ts, tc, TOK_XMLETAGO, &endAtom);
+ if (!pn2)
+ return NULL;
+ if (pn2->pn_type == TOK_XMLETAGO) {
+ /* Oops, end tag has attributes! */
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_TAG_SYNTAX);
+ return NULL;
+ }
+ if (endAtom && startAtom && endAtom != startAtom) {
+ JSString *str = ATOM_TO_STRING(startAtom);
+
+ /* End vs. start tag name mismatch: point to the tag name. */
+ js_ReportCompileErrorNumber(cx, ts, pn2,
+ JSREPORT_UC | JSREPORT_ERROR,
+ JSMSG_XML_TAG_NAME_MISMATCH,
+ JSSTRING_CHARS(str));
+ return NULL;
+ }
+
+ /* Make a TOK_XMLETAGO list with pn2 as its single child. */
+ JS_ASSERT(pn2->pn_type == TOK_XMLNAME || pn2->pn_type == TOK_LC);
+ list = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!list)
+ return NULL;
+ list->pn_type = TOK_XMLETAGO;
+ PN_INIT_LIST_1(list, pn2);
+ PN_APPEND(pn, list);
+ if (!XML_FOLDABLE(pn2)) {
+ list->pn_extra |= PNX_CANTFOLD;
+ pn->pn_extra |= PNX_CANTFOLD;
+ }
+
+ js_MatchToken(cx, ts, TOK_XMLSPACE);
+ MUST_MATCH_TOKEN(TOK_XMLTAGC, JSMSG_BAD_XML_TAG_SYNTAX);
+ }
+
+ /* Set pn_op now that pn has been updated to its final value. */
+ pn->pn_op = JSOP_TOXML;
+ } else if (allowList && tt == TOK_XMLTAGC) {
+ /* XMLList Initialiser. */
+ pn->pn_type = TOK_XMLLIST;
+ pn->pn_op = JSOP_TOXMLLIST;
+ PN_INIT_LIST(pn);
+ pn->pn_extra |= PNX_XMLROOT;
+ if (!XMLElementContent(cx, ts, pn, tc))
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_XMLTAGC, JSMSG_BAD_XML_LIST_SYNTAX);
+ } else {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_NAME_SYNTAX);
+ return NULL;
+ }
+
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ ts->flags &= ~TSF_XMLTAGMODE;
+ return pn;
+}
+
+static JSParseNode *
+XMLElementOrListRoot(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSBool allowList)
+{
+ uint32 oldopts;
+ JSParseNode *pn;
+
+ /*
+ * Force XML support to be enabled so that comments and CDATA literals
+ * are recognized, instead of <! followed by -- starting an HTML comment
+ * to end of line (used in script tags to hide content from old browsers
+ * that don't recognize <script>).
+ */
+ oldopts = JS_SetOptions(cx, cx->options | JSOPTION_XML);
+ pn = XMLElementOrList(cx, ts, tc, allowList);
+ JS_SetOptions(cx, oldopts);
+ return pn;
+}
+
+JS_FRIEND_API(JSParseNode *)
+js_ParseXMLText(JSContext *cx, JSObject *chain, JSParseContext *pc,
+ JSBool allowList)
+{
+ JSParseNode *pn;
+ JSTreeContext tc;
+ JSTokenType tt;
+
+ /*
+ * Push a compiler frame if we have no frames, or if the top frame is a
+ * lightweight function activation, or if its scope chain doesn't match
+ * the one passed to us.
+ */
+ TREE_CONTEXT_INIT(&tc, pc);
+ tc.u.scopeChain = chain;
+
+ /* Set XML-only mode to turn off special treatment of {expr} in XML. */
+ TS(pc)->flags |= TSF_OPERAND | TSF_XMLONLYMODE;
+ tt = js_GetToken(cx, TS(pc));
+ TS(pc)->flags &= ~TSF_OPERAND;
+
+ if (tt != TOK_XMLSTAGO) {
+ js_ReportCompileErrorNumber(cx, TS(pc), NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_MARKUP);
+ pn = NULL;
+ } else {
+ pn = XMLElementOrListRoot(cx, TS(pc), &tc, allowList);
+ }
+
+ TS(pc)->flags &= ~TSF_XMLONLYMODE;
+ TREE_CONTEXT_FINISH(cx, &tc);
+ return pn;
+}
+
+#endif /* JS_HAS_XMLSUPPORT */
+
+static JSParseNode *
+PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSTokenType tt, JSBool afterDot)
+{
+ JSParseNode *pn, *pn2, *pn3;
+ JSOp op;
+#if JS_HAS_SHARP_VARS
+ JSParseNode *defsharp;
+ JSBool notsharp;
+#endif
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+#if JS_HAS_SHARP_VARS
+ defsharp = NULL;
+ notsharp = JS_FALSE;
+ again:
+ /*
+ * Control flows here after #n= is scanned. If the following primary is
+ * not valid after such a "sharp variable" definition, the tt switch case
+ * should set notsharp.
+ */
+#endif
+
+#if JS_HAS_GETTER_SETTER
+ if (tt == TOK_NAME) {
+ tt = CheckGetterOrSetter(cx, ts, TOK_FUNCTION);
+ if (tt == TOK_ERROR)
+ return NULL;
+ }
+#endif
+
+ switch (tt) {
+ case TOK_FUNCTION:
+#if JS_HAS_XML_SUPPORT
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ if (js_MatchToken(cx, ts, TOK_DBLCOLON)) {
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ pn2 = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_type = TOK_FUNCTION;
+ pn = QualifiedSuffix(cx, ts, pn2, tc);
+ if (!pn)
+ return NULL;
+ break;
+ }
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+#endif
+ pn = FunctionExpr(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ break;
+
+ case TOK_LB:
+ {
+ JSBool matched;
+ jsuint index;
+
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_RB;
+ pn->pn_op = JSOP_NEWINIT;
+
+#if JS_HAS_SHARP_VARS
+ if (defsharp) {
+ PN_INIT_LIST_1(pn, defsharp);
+ defsharp = NULL;
+ } else
+#endif
+ PN_INIT_LIST(pn);
+
+ ts->flags |= TSF_OPERAND;
+ matched = js_MatchToken(cx, ts, TOK_RB);
+ ts->flags &= ~TSF_OPERAND;
+ if (!matched) {
+ for (index = 0; ; index++) {
+ if (index == ARRAY_INIT_LIMIT) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_ARRAY_INIT_TOO_BIG);
+ return NULL;
+ }
+
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_RB) {
+ pn->pn_extra |= PNX_ENDCOMMA;
+ break;
+ }
+
+ if (tt == TOK_COMMA) {
+ /* So CURRENT_TOKEN gets TOK_COMMA and not TOK_LB. */
+ js_MatchToken(cx, ts, TOK_COMMA);
+ pn2 = NewParseNode(cx, ts, PN_NULLARY, tc);
+ } else {
+ pn2 = AssignExpr(cx, ts, tc);
+ }
+ if (!pn2)
+ return NULL;
+ PN_APPEND(pn, pn2);
+
+ if (tt != TOK_COMMA) {
+ /* If we didn't already match TOK_COMMA in above case. */
+ if (!js_MatchToken(cx, ts, TOK_COMMA))
+ break;
+ }
+ }
+
+#if JS_HAS_GENERATORS
+ /*
+ * At this point, (index == 0 && pn->pn_count != 0) implies one
+ * element initialiser was parsed (possibly with a defsharp before
+ * the left bracket).
+ *
+ * An array comprehension of the form:
+ *
+ * [i * j for (i in o) for (j in p) if (i != j)]
+ *
+ * translates to roughly the following let expression:
+ *
+ * let (array = new Array, i, j) {
+ * for (i in o) let {
+ * for (j in p)
+ * if (i != j)
+ * array.push(i * j)
+ * }
+ * array
+ * }
+ *
+ * where array is a nameless block-local variable. The "roughly"
+ * means that an implementation may optimize away the array.push.
+ * An array comprehension opens exactly one block scope, no matter
+ * how many for heads it contains.
+ *
+ * Each let () {...} or for (let ...) ... compiles to:
+ *
+ * JSOP_ENTERBLOCK <o> ... JSOP_LEAVEBLOCK <n>
+ *
+ * where <o> is a literal object representing the block scope,
+ * with <n> properties, naming each var declared in the block.
+ *
+ * Each var declaration in a let-block binds a name in <o> at
+ * compile time, and allocates a slot on the operand stack at
+ * runtime via JSOP_ENTERBLOCK. A block-local var is accessed
+ * by the JSOP_GETLOCAL and JSOP_SETLOCAL ops, and iterated with
+ * JSOP_FORLOCAL. These ops all have an immediate operand, the
+ * local slot's stack index from fp->spbase.
+ *
+ * The array comprehension iteration step, array.push(i * j) in
+ * the example above, is done by <i * j>; JSOP_ARRAYCOMP <array>,
+ * where <array> is the index of array's stack slot.
+ */
+ if (index == 0 &&
+ pn->pn_count != 0 &&
+ js_MatchToken(cx, ts, TOK_FOR)) {
+ JSParseNode *pnexp, *pntop;
+
+ /* Relabel pn as an array comprehension node. */
+ pn->pn_type = TOK_ARRAYCOMP;
+
+ /*
+ * Remove the comprehension expression from pn's linked list
+ * and save it via pnexp. We'll re-install it underneath the
+ * ARRAYPUSH node after we parse the rest of the comprehension.
+ */
+ pnexp = PN_LAST(pn);
+ JS_ASSERT(pn->pn_count == 1 || pn->pn_count == 2);
+ pn->pn_tail = (--pn->pn_count == 1)
+ ? &pn->pn_head->pn_next
+ : &pn->pn_head;
+ *pn->pn_tail = NULL;
+
+ pntop = ComprehensionTail(cx, ts, tc, TOK_ARRAYPUSH,
+ JSOP_ARRAYPUSH, pnexp);
+ if (!pntop)
+ return NULL;
+ PN_APPEND(pn, pntop);
+ }
+#endif /* JS_HAS_GENERATORS */
+
+ MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_LIST);
+ }
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ return pn;
+ }
+
+ case TOK_LC:
+ {
+ JSBool afterComma;
+ JSParseNode *pnval;
+
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_RC;
+ pn->pn_op = JSOP_NEWINIT;
+
+#if JS_HAS_SHARP_VARS
+ if (defsharp) {
+ PN_INIT_LIST_1(pn, defsharp);
+ defsharp = NULL;
+ } else
+#endif
+ PN_INIT_LIST(pn);
+
+ afterComma = JS_FALSE;
+ for (;;) {
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ switch (tt) {
+ case TOK_NUMBER:
+ pn3 = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (pn3)
+ pn3->pn_dval = CURRENT_TOKEN(ts).t_dval;
+ break;
+ case TOK_NAME:
+#if JS_HAS_GETTER_SETTER
+ {
+ JSAtom *atom;
+
+ atom = CURRENT_TOKEN(ts).t_atom;
+ if (atom == cx->runtime->atomState.getAtom)
+ op = JSOP_GETTER;
+ else if (atom == cx->runtime->atomState.setAtom)
+ op = JSOP_SETTER;
+ else
+ goto property_name;
+
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ if (tt != TOK_NAME) {
+ js_UngetToken(ts);
+ goto property_name;
+ }
+ pn3 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn3)
+ return NULL;
+ pn3->pn_atom = CURRENT_TOKEN(ts).t_atom;
+ pn3->pn_slot = -1;
+
+ /* We have to fake a 'function' token here. */
+ CURRENT_TOKEN(ts).t_op = JSOP_NOP;
+ CURRENT_TOKEN(ts).type = TOK_FUNCTION;
+ pn2 = FunctionExpr(cx, ts, tc);
+ pn2 = NewBinary(cx, TOK_COLON, op, pn3, pn2, tc);
+ goto skip;
+ }
+ property_name:
+#endif
+ case TOK_STRING:
+ pn3 = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (pn3)
+ pn3->pn_atom = CURRENT_TOKEN(ts).t_atom;
+ break;
+ case TOK_RC:
+ if (afterComma &&
+ !js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING |
+ JSREPORT_STRICT,
+ JSMSG_TRAILING_COMMA)) {
+ return NULL;
+ }
+ goto end_obj_init;
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_PROP_ID);
+ return NULL;
+ }
+
+ tt = js_GetToken(cx, ts);
+#if JS_HAS_GETTER_SETTER
+ if (tt == TOK_NAME) {
+ tt = CheckGetterOrSetter(cx, ts, TOK_COLON);
+ if (tt == TOK_ERROR)
+ return NULL;
+ }
+#endif
+
+ if (tt != TOK_COLON) {
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ if (tt != TOK_COMMA && tt != TOK_RC) {
+#endif
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_COLON_AFTER_ID);
+ return NULL;
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ }
+
+ /*
+ * Support, e.g., |var {x, y} = o| as destructuring shorthand
+ * for |var {x: x, y: y} = o|, per proposed JS2/ES4 for JS1.8.
+ */
+ js_UngetToken(ts);
+ pn->pn_extra |= PNX_SHORTHAND;
+ pnval = pn3;
+ if (pnval->pn_type == TOK_NAME) {
+ pnval->pn_arity = PN_NAME;
+ pnval->pn_expr = NULL;
+ pnval->pn_slot = -1;
+ pnval->pn_const = JS_FALSE;
+ }
+ op = JSOP_NOP;
+#endif
+ } else {
+ op = CURRENT_TOKEN(ts).t_op;
+ pnval = AssignExpr(cx, ts, tc);
+ }
+
+ pn2 = NewBinary(cx, TOK_COLON, op, pn3, pnval, tc);
+#if JS_HAS_GETTER_SETTER
+ skip:
+#endif
+ if (!pn2)
+ return NULL;
+ PN_APPEND(pn, pn2);
+
+ tt = js_GetToken(cx, ts);
+ if (tt == TOK_RC)
+ goto end_obj_init;
+ if (tt != TOK_COMMA) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_CURLY_AFTER_LIST);
+ return NULL;
+ }
+ afterComma = JS_TRUE;
+ }
+
+ end_obj_init:
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ return pn;
+ }
+
+#if JS_HAS_BLOCK_SCOPE
+ case TOK_LET:
+ pn = LetBlock(cx, ts, tc, JS_FALSE);
+ if (!pn)
+ return NULL;
+ break;
+#endif
+
+#if JS_HAS_SHARP_VARS
+ case TOK_DEFSHARP:
+ if (defsharp)
+ goto badsharp;
+ defsharp = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!defsharp)
+ return NULL;
+ defsharp->pn_num = (jsint) CURRENT_TOKEN(ts).t_dval;
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ goto again;
+
+ case TOK_USESHARP:
+ /* Check for forward/dangling references at runtime, to allow eval. */
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_num = (jsint) CURRENT_TOKEN(ts).t_dval;
+ notsharp = JS_TRUE;
+ break;
+#endif /* JS_HAS_SHARP_VARS */
+
+ case TOK_LP:
+ {
+ JSBool genexp;
+
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn2 = ParenExpr(cx, ts, tc, pn, &genexp);
+ if (!pn2)
+ return NULL;
+ if (genexp)
+ return pn2;
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
+ if (pn2->pn_type == TOK_RP ||
+ (js_CodeSpec[pn2->pn_op].prec >= js_CodeSpec[JSOP_GETPROP].prec &&
+ !afterDot)) {
+ /*
+ * Avoid redundant JSOP_GROUP opcodes, for efficiency and mainly
+ * to help the decompiler look ahead from a JSOP_ENDINIT to see a
+ * JSOP_GROUP followed by a POP or POPV. That sequence means the
+ * parentheses are mandatory, to disambiguate object initialisers
+ * as expression statements from block statements.
+ *
+ * Also drop pn if pn2 is a member or a primary expression of any
+ * kind. This is required to avoid generating a JSOP_GROUP that
+ * will null the |obj| interpreter register, causing |this| in any
+ * call of that member expression to bind to the global object.
+ */
+ RecycleTree(pn, tc);
+ pn = pn2;
+ } else {
+ pn->pn_type = TOK_RP;
+ pn->pn_kid = pn2;
+ }
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ break;
+ }
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_STAR:
+ pn = QualifiedIdentifier(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ notsharp = JS_TRUE;
+ break;
+
+ case TOK_AT:
+ pn = AttributeIdentifier(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ notsharp = JS_TRUE;
+ break;
+
+ case TOK_XMLSTAGO:
+ pn = XMLElementOrListRoot(cx, ts, tc, JS_TRUE);
+ if (!pn)
+ return NULL;
+ notsharp = JS_TRUE; /* XXXbe could be sharp? */
+ break;
+#endif /* JS_HAS_XML_SUPPORT */
+
+ case TOK_STRING:
+#if JS_HAS_SHARP_VARS
+ notsharp = JS_TRUE;
+ /* FALL THROUGH */
+#endif
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_XMLCDATA:
+ case TOK_XMLCOMMENT:
+ case TOK_XMLPI:
+#endif
+ case TOK_NAME:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_atom = CURRENT_TOKEN(ts).t_atom;
+#if JS_HAS_XML_SUPPORT
+ if (tt == TOK_XMLPI)
+ pn->pn_atom2 = CURRENT_TOKEN(ts).t_atom2;
+ else
+#endif
+ pn->pn_op = CURRENT_TOKEN(ts).t_op;
+ if (tt == TOK_NAME) {
+ pn->pn_arity = PN_NAME;
+ pn->pn_slot = -1;
+
+#if JS_HAS_XML_SUPPORT
+ if (js_MatchToken(cx, ts, TOK_DBLCOLON)) {
+ if (afterDot) {
+ JSString *str;
+
+ /*
+ * Here PrimaryExpr is called after '.' or '..' and we
+ * just scanned .name:: or ..name:: . This is the only
+ * case where a keyword after '.' or '..' is not
+ * treated as a property name.
+ */
+ str = ATOM_TO_STRING(pn->pn_atom);
+ tt = js_CheckKeyword(JSSTRING_CHARS(str),
+ JSSTRING_LENGTH(str));
+ if (tt == TOK_FUNCTION) {
+ pn->pn_arity = PN_NULLARY;
+ pn->pn_type = TOK_FUNCTION;
+ } else if (tt != TOK_EOF) {
+ js_ReportCompileErrorNumber(
+ cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_KEYWORD_NOT_NS);
+ return NULL;
+ }
+ }
+ pn = QualifiedSuffix(cx, ts, pn, tc);
+ if (!pn)
+ return NULL;
+ break;
+ }
+#endif
+
+ /* Unqualified __parent__ and __proto__ uses require activations. */
+ if (pn->pn_atom == cx->runtime->atomState.parentAtom ||
+ pn->pn_atom == cx->runtime->atomState.protoAtom) {
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ }
+ }
+ break;
+
+ case TOK_REGEXP:
+ {
+ JSObject *obj;
+
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+
+ /* Token stream ensures that tokenbuf is NUL-terminated. */
+ JS_ASSERT(*ts->tokenbuf.ptr == (jschar) 0);
+ obj = js_NewRegExpObject(cx, ts,
+ ts->tokenbuf.base,
+ ts->tokenbuf.ptr - ts->tokenbuf.base,
+ CURRENT_TOKEN(ts).t_reflags);
+ if (!obj)
+ return NULL;
+ if (!(tc->flags & TCF_COMPILE_N_GO)) {
+ STOBJ_CLEAR_PARENT(obj);
+ STOBJ_CLEAR_PROTO(obj);
+ }
+
+ pn->pn_pob = js_NewParsedObjectBox(cx, tc->parseContext, obj);
+ if (!pn->pn_pob)
+ return NULL;
+
+ pn->pn_op = JSOP_REGEXP;
+ break;
+ }
+
+ case TOK_NUMBER:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_op = JSOP_DOUBLE;
+ pn->pn_dval = CURRENT_TOKEN(ts).t_dval;
+#if JS_HAS_SHARP_VARS
+ notsharp = JS_TRUE;
+#endif
+ break;
+
+ case TOK_PRIMARY:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_op = CURRENT_TOKEN(ts).t_op;
+#if JS_HAS_SHARP_VARS
+ notsharp = JS_TRUE;
+#endif
+ break;
+
+ case TOK_ERROR:
+ /* The scanner or one of its subroutines reported the error. */
+ return NULL;
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+
+#if JS_HAS_SHARP_VARS
+ if (defsharp) {
+ if (notsharp) {
+ badsharp:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_SHARP_VAR_DEF);
+ return NULL;
+ }
+ defsharp->pn_kid = pn;
+ return defsharp;
+ }
+#endif
+ return pn;
+}
+
+static JSParseNode *
+ParenExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSParseNode *pn1, JSBool *genexp)
+{
+ JSTokenPtr begin;
+ JSParseNode *pn;
+#if JS_HAS_GENERATOR_EXPRS
+ uintN oldflags = tc->flags;
+#endif
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_LP);
+ begin = CURRENT_TOKEN(ts).pos.begin;
+
+ if (genexp)
+ *genexp = JS_FALSE;
+ pn = BracketedExpr(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+#if JS_HAS_GENERATOR_EXPRS
+ if (js_MatchToken(cx, ts, TOK_FOR)) {
+ if (pn->pn_type == TOK_YIELD) {
+ js_ReportCompileErrorNumber(cx, ts, pn, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_yield_str);
+ return NULL;
+ }
+ if (pn->pn_type == TOK_COMMA) {
+ js_ReportCompileErrorNumber(cx, ts, PN_LAST(pn), JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_generator_str);
+ return NULL;
+ }
+ if (!pn1) {
+ pn1 = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn1)
+ return NULL;
+ }
+ pn->pn_pos.begin = begin;
+ pn = GeneratorExpr(cx, ts, tc, oldflags, pn1, pn);
+ if (!pn)
+ return NULL;
+ if (genexp) {
+ if (js_GetToken(cx, ts) != TOK_RP) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_generator_str);
+ return NULL;
+ }
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ *genexp = JS_TRUE;
+ }
+ }
+#endif /* JS_HAS_GENERATOR_EXPRS */
+
+ return pn;
+}
+
+/*
+ * Fold from one constant type to another.
+ * XXX handles only strings and numbers for now
+ */
+static JSBool
+FoldType(JSContext *cx, JSParseNode *pn, JSTokenType type)
+{
+ if (pn->pn_type != type) {
+ switch (type) {
+ case TOK_NUMBER:
+ if (pn->pn_type == TOK_STRING) {
+ jsdouble d;
+ if (!JS_ValueToNumber(cx, ATOM_KEY(pn->pn_atom), &d))
+ return JS_FALSE;
+ pn->pn_dval = d;
+ pn->pn_type = TOK_NUMBER;
+ pn->pn_op = JSOP_DOUBLE;
+ }
+ break;
+
+ case TOK_STRING:
+ if (pn->pn_type == TOK_NUMBER) {
+ JSString *str = js_NumberToString(cx, pn->pn_dval);
+ if (!str)
+ return JS_FALSE;
+ pn->pn_atom = js_AtomizeString(cx, str, 0);
+ if (!pn->pn_atom)
+ return JS_FALSE;
+ pn->pn_type = TOK_STRING;
+ pn->pn_op = JSOP_STRING;
+ }
+ break;
+
+ default:;
+ }
+ }
+ return JS_TRUE;
+}
+
+/*
+ * Fold two numeric constants. Beware that pn1 and pn2 are recycled, unless
+ * one of them aliases pn, so you can't safely fetch pn2->pn_next, e.g., after
+ * a successful call to this function.
+ */
+static JSBool
+FoldBinaryNumeric(JSContext *cx, JSOp op, JSParseNode *pn1, JSParseNode *pn2,
+ JSParseNode *pn, JSTreeContext *tc)
+{
+ jsdouble d, d2;
+ int32 i, j;
+
+ JS_ASSERT(pn1->pn_type == TOK_NUMBER && pn2->pn_type == TOK_NUMBER);
+ d = pn1->pn_dval;
+ d2 = pn2->pn_dval;
+ switch (op) {
+ case JSOP_LSH:
+ case JSOP_RSH:
+ i = js_DoubleToECMAInt32(d);
+ j = js_DoubleToECMAInt32(d2);
+ j &= 31;
+ d = (op == JSOP_LSH) ? i << j : i >> j;
+ break;
+
+ case JSOP_URSH:
+ j = js_DoubleToECMAInt32(d2);
+ j &= 31;
+ d = js_DoubleToECMAUint32(d) >> j;
+ break;
+
+ case JSOP_ADD:
+ d += d2;
+ break;
+
+ case JSOP_SUB:
+ d -= d2;
+ break;
+
+ case JSOP_MUL:
+ d *= d2;
+ break;
+
+ case JSOP_DIV:
+ if (d2 == 0) {
+#if defined(XP_WIN)
+ /* XXX MSVC miscompiles such that (NaN == 0) */
+ if (JSDOUBLE_IS_NaN(d2))
+ d = *cx->runtime->jsNaN;
+ else
+#endif
+ if (d == 0 || JSDOUBLE_IS_NaN(d))
+ d = *cx->runtime->jsNaN;
+ else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)
+ d = *cx->runtime->jsNegativeInfinity;
+ else
+ d = *cx->runtime->jsPositiveInfinity;
+ } else {
+ d /= d2;
+ }
+ break;
+
+ case JSOP_MOD:
+ if (d2 == 0) {
+ d = *cx->runtime->jsNaN;
+ } else {
+#if defined(XP_WIN)
+ /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
+ if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)))
+#endif
+ d = fmod(d, d2);
+ }
+ break;
+
+ default:;
+ }
+
+ /* Take care to allow pn1 or pn2 to alias pn. */
+ if (pn1 != pn)
+ RecycleTree(pn1, tc);
+ if (pn2 != pn)
+ RecycleTree(pn2, tc);
+ pn->pn_type = TOK_NUMBER;
+ pn->pn_op = JSOP_DOUBLE;
+ pn->pn_arity = PN_NULLARY;
+ pn->pn_dval = d;
+ return JS_TRUE;
+}
+
+#if JS_HAS_XML_SUPPORT
+
+static JSBool
+FoldXMLConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc)
+{
+ JSTokenType tt;
+ JSParseNode **pnp, *pn1, *pn2;
+ JSString *accum, *str;
+ uint32 i, j;
+ JSTempValueRooter tvr;
+
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ tt = PN_TYPE(pn);
+ pnp = &pn->pn_head;
+ pn1 = *pnp;
+ accum = NULL;
+ if ((pn->pn_extra & PNX_CANTFOLD) == 0) {
+ if (tt == TOK_XMLETAGO)
+ accum = ATOM_TO_STRING(cx->runtime->atomState.etagoAtom);
+ else if (tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC)
+ accum = ATOM_TO_STRING(cx->runtime->atomState.stagoAtom);
+ }
+
+ /*
+ * GC Rooting here is tricky: for most of the loop, |accum| is safe via
+ * the newborn string root. However, when |pn2->pn_type| is TOK_XMLCDATA,
+ * TOK_XMLCOMMENT, or TOK_XMLPI it is knocked out of the newborn root.
+ * Therefore, we have to add additonal protection from GC nesting under
+ * js_ConcatStrings.
+ */
+ for (pn2 = pn1, i = j = 0; pn2; pn2 = pn2->pn_next, i++) {
+ /* The parser already rejected end-tags with attributes. */
+ JS_ASSERT(tt != TOK_XMLETAGO || i == 0);
+ switch (pn2->pn_type) {
+ case TOK_XMLATTR:
+ if (!accum)
+ goto cantfold;
+ /* FALL THROUGH */
+ case TOK_XMLNAME:
+ case TOK_XMLSPACE:
+ case TOK_XMLTEXT:
+ case TOK_STRING:
+ if (pn2->pn_arity == PN_LIST)
+ goto cantfold;
+ str = ATOM_TO_STRING(pn2->pn_atom);
+ break;
+
+ case TOK_XMLCDATA:
+ str = js_MakeXMLCDATAString(cx, ATOM_TO_STRING(pn2->pn_atom));
+ if (!str)
+ return JS_FALSE;
+ break;
+
+ case TOK_XMLCOMMENT:
+ str = js_MakeXMLCommentString(cx, ATOM_TO_STRING(pn2->pn_atom));
+ if (!str)
+ return JS_FALSE;
+ break;
+
+ case TOK_XMLPI:
+ str = js_MakeXMLPIString(cx, ATOM_TO_STRING(pn2->pn_atom),
+ ATOM_TO_STRING(pn2->pn_atom2));
+ if (!str)
+ return JS_FALSE;
+ break;
+
+ cantfold:
+ default:
+ JS_ASSERT(*pnp == pn1);
+ if ((tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC) &&
+ (i & 1) ^ (j & 1)) {
+#ifdef DEBUG_brendanXXX
+ printf("1: %d, %d => ", i, j);
+ if (accum)
+ js_FileEscapedString(stdout, accum, 0);
+ else
+ fputs("NULL", stdout);
+ fputc('\n', stdout);
+#endif
+ } else if (accum && pn1 != pn2) {
+ while (pn1->pn_next != pn2) {
+ pn1 = RecycleTree(pn1, tc);
+ --pn->pn_count;
+ }
+ pn1->pn_type = TOK_XMLTEXT;
+ pn1->pn_op = JSOP_STRING;
+ pn1->pn_arity = PN_NULLARY;
+ pn1->pn_atom = js_AtomizeString(cx, accum, 0);
+ if (!pn1->pn_atom)
+ return JS_FALSE;
+ JS_ASSERT(pnp != &pn1->pn_next);
+ *pnp = pn1;
+ }
+ pnp = &pn2->pn_next;
+ pn1 = *pnp;
+ accum = NULL;
+ continue;
+ }
+
+ if (accum) {
+ JS_PUSH_TEMP_ROOT_STRING(cx, accum, &tvr);
+ str = ((tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC) && i != 0)
+ ? js_AddAttributePart(cx, i & 1, accum, str)
+ : js_ConcatStrings(cx, accum, str);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!str)
+ return JS_FALSE;
+#ifdef DEBUG_brendanXXX
+ printf("2: %d, %d => ", i, j);
+ js_FileEscapedString(stdout, str, 0);
+ printf(" (%u)\n", JSSTRING_LENGTH(str));
+#endif
+ ++j;
+ }
+ accum = str;
+ }
+
+ if (accum) {
+ str = NULL;
+ if ((pn->pn_extra & PNX_CANTFOLD) == 0) {
+ if (tt == TOK_XMLPTAGC)
+ str = ATOM_TO_STRING(cx->runtime->atomState.ptagcAtom);
+ else if (tt == TOK_XMLSTAGO || tt == TOK_XMLETAGO)
+ str = ATOM_TO_STRING(cx->runtime->atomState.tagcAtom);
+ }
+ if (str) {
+ accum = js_ConcatStrings(cx, accum, str);
+ if (!accum)
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(*pnp == pn1);
+ while (pn1->pn_next) {
+ pn1 = RecycleTree(pn1, tc);
+ --pn->pn_count;
+ }
+ pn1->pn_type = TOK_XMLTEXT;
+ pn1->pn_op = JSOP_STRING;
+ pn1->pn_arity = PN_NULLARY;
+ pn1->pn_atom = js_AtomizeString(cx, accum, 0);
+ if (!pn1->pn_atom)
+ return JS_FALSE;
+ JS_ASSERT(pnp != &pn1->pn_next);
+ *pnp = pn1;
+ }
+
+ if (pn1 && pn->pn_count == 1) {
+ /*
+ * Only one node under pn, and it has been folded: move pn1 onto pn
+ * unless pn is an XML root (in which case we need it to tell the code
+ * generator to emit a JSOP_TOXML or JSOP_TOXMLLIST op). If pn is an
+ * XML root *and* it's a point-tag, rewrite it to TOK_XMLELEM to avoid
+ * extra "<" and "/>" bracketing at runtime.
+ */
+ if (!(pn->pn_extra & PNX_XMLROOT)) {
+ PN_MOVE_NODE(pn, pn1);
+ } else if (tt == TOK_XMLPTAGC) {
+ pn->pn_type = TOK_XMLELEM;
+ pn->pn_op = JSOP_TOXML;
+ }
+ }
+ return JS_TRUE;
+}
+
+#endif /* JS_HAS_XML_SUPPORT */
+
+static JSBool
+StartsWith(JSParseNode *pn, JSTokenType tt)
+{
+#define TAIL_RECURSE(pn2) JS_BEGIN_MACRO pn = (pn2); goto recur; JS_END_MACRO
+
+recur:
+ if (pn->pn_type == tt)
+ return JS_TRUE;
+ switch (pn->pn_arity) {
+ case PN_FUNC:
+ return tt == TOK_FUNCTION;
+ case PN_LIST:
+ if (pn->pn_head)
+ TAIL_RECURSE(pn->pn_head);
+ break;
+ case PN_TERNARY:
+ if (pn->pn_kid1)
+ TAIL_RECURSE(pn->pn_kid1);
+ break;
+ case PN_BINARY:
+ if (pn->pn_left)
+ TAIL_RECURSE(pn->pn_left);
+ break;
+ case PN_UNARY:
+ /* A parenthesized expression starts with a left parenthesis. */
+ if (pn->pn_type == TOK_RP)
+ return tt == TOK_LP;
+ if (pn->pn_kid)
+ TAIL_RECURSE(pn->pn_kid);
+ break;
+ case PN_NAME:
+ if (pn->pn_type == TOK_DOT || pn->pn_type == TOK_DBLDOT)
+ TAIL_RECURSE(pn->pn_expr);
+ /* FALL THROUGH */
+ }
+ return JS_FALSE;
+#undef TAIL_RECURSE
+}
+
+static int
+Boolish(JSParseNode *pn)
+{
+ switch (pn->pn_op) {
+ case JSOP_DOUBLE:
+ return pn->pn_dval != 0 && !JSDOUBLE_IS_NaN(pn->pn_dval);
+
+ case JSOP_STRING:
+ return JSSTRING_LENGTH(ATOM_TO_STRING(pn->pn_atom)) != 0;
+
+#if JS_HAS_GENERATOR_EXPRS
+ case JSOP_CALL:
+ {
+ /*
+ * A generator expression as an if or loop condition has no effects, it
+ * simply results in a truthy object reference. This condition folding
+ * is needed for the decompiler. See bug 442342 and bug 443074.
+ */
+ if (pn->pn_count != 1)
+ break;
+ JSParseNode *pn2 = pn->pn_head;
+ if (pn2->pn_type != TOK_FUNCTION)
+ break;
+ if (!(pn2->pn_flags & TCF_GENEXP_LAMBDA))
+ break;
+ /* FALL THROUGH */
+ }
+#endif
+
+ case JSOP_DEFFUN:
+ case JSOP_NAMEDFUNOBJ:
+ case JSOP_ANONFUNOBJ:
+ case JSOP_THIS:
+ case JSOP_TRUE:
+ return 1;
+
+ case JSOP_NULL:
+ case JSOP_FALSE:
+ return 0;
+
+ default:;
+ }
+ return -1;
+}
+
+JSBool
+js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond)
+{
+ JSParseNode *pn1 = NULL, *pn2 = NULL, *pn3 = NULL;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ switch (pn->pn_arity) {
+ case PN_FUNC:
+ {
+ uint16 oldflags = tc->flags;
+
+ tc->flags = (uint16) pn->pn_flags;
+ if (!js_FoldConstants(cx, pn->pn_body, tc))
+ return JS_FALSE;
+ tc->flags = oldflags;
+ break;
+ }
+
+ case PN_LIST:
+ {
+ /* Propagate inCond through logical connectives. */
+ bool cond = inCond && (pn->pn_type == TOK_OR || pn->pn_type == TOK_AND);
+
+ /* Save the list head in pn1 for later use. */
+ for (pn1 = pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (!js_FoldConstants(cx, pn2, tc, cond))
+ return JS_FALSE;
+ }
+ break;
+ }
+
+ case PN_TERNARY:
+ /* Any kid may be null (e.g. for (;;)). */
+ pn1 = pn->pn_kid1;
+ pn2 = pn->pn_kid2;
+ pn3 = pn->pn_kid3;
+ if (pn1 && !js_FoldConstants(cx, pn1, tc, pn->pn_type == TOK_IF))
+ return JS_FALSE;
+ if (pn2) {
+ if (!js_FoldConstants(cx, pn2, tc, pn->pn_type == TOK_FORHEAD))
+ return JS_FALSE;
+ if (pn->pn_type == TOK_FORHEAD && pn2->pn_op == JSOP_TRUE) {
+ RecycleTree(pn2, tc);
+ pn->pn_kid2 = NULL;
+ }
+ }
+ if (pn3 && !js_FoldConstants(cx, pn3, tc))
+ return JS_FALSE;
+ break;
+
+ case PN_BINARY:
+ pn1 = pn->pn_left;
+ pn2 = pn->pn_right;
+
+ /* Propagate inCond through logical connectives. */
+ if (pn->pn_type == TOK_OR || pn->pn_type == TOK_AND) {
+ if (!js_FoldConstants(cx, pn1, tc, inCond))
+ return JS_FALSE;
+ if (!js_FoldConstants(cx, pn2, tc, inCond))
+ return JS_FALSE;
+ break;
+ }
+
+ /* First kid may be null (for default case in switch). */
+ if (pn1 && !js_FoldConstants(cx, pn1, tc, pn->pn_type == TOK_WHILE))
+ return JS_FALSE;
+ if (!js_FoldConstants(cx, pn2, tc, pn->pn_type == TOK_DO))
+ return JS_FALSE;
+ break;
+
+ case PN_UNARY:
+ /* Our kid may be null (e.g. return; vs. return e;). */
+ pn1 = pn->pn_kid;
+ if (pn1 &&
+ !js_FoldConstants(cx, pn1, tc,
+ (inCond && pn->pn_type == TOK_RP) ||
+ pn->pn_op == JSOP_NOT)) {
+ return JS_FALSE;
+ }
+ break;
+
+ case PN_NAME:
+ /*
+ * Skip pn1 down along a chain of dotted member expressions to avoid
+ * excessive recursion. Our only goal here is to fold constants (if
+ * any) in the primary expression operand to the left of the first
+ * dot in the chain.
+ */
+ pn1 = pn->pn_expr;
+ while (pn1 && pn1->pn_arity == PN_NAME)
+ pn1 = pn1->pn_expr;
+ if (pn1 && !js_FoldConstants(cx, pn1, tc))
+ return JS_FALSE;
+ break;
+
+ case PN_NULLARY:
+ break;
+ }
+
+ switch (pn->pn_type) {
+ case TOK_IF:
+ if (ContainsStmt(pn2, TOK_VAR) || ContainsStmt(pn3, TOK_VAR))
+ break;
+ /* FALL THROUGH */
+
+ case TOK_HOOK:
+ /* Reduce 'if (C) T; else E' into T for true C, E for false. */
+ while (pn1->pn_type == TOK_RP)
+ pn1 = pn1->pn_kid;
+ switch (pn1->pn_type) {
+ case TOK_NUMBER:
+ if (pn1->pn_dval == 0 || JSDOUBLE_IS_NaN(pn1->pn_dval))
+ pn2 = pn3;
+ break;
+ case TOK_STRING:
+ if (JSSTRING_LENGTH(ATOM_TO_STRING(pn1->pn_atom)) == 0)
+ pn2 = pn3;
+ break;
+ case TOK_PRIMARY:
+ if (pn1->pn_op == JSOP_TRUE)
+ break;
+ if (pn1->pn_op == JSOP_FALSE || pn1->pn_op == JSOP_NULL) {
+ pn2 = pn3;
+ break;
+ }
+ /* FALL THROUGH */
+ default:
+ /* Early return to dodge common code that copies pn2 to pn. */
+ return JS_TRUE;
+ }
+
+#if JS_HAS_GENERATOR_EXPRS
+ /* Don't fold a trailing |if (0)| in a generator expression. */
+ if (!pn2 && (tc->flags & TCF_GENEXP_LAMBDA))
+ break;
+#endif
+
+ if (pn2) {
+ /*
+ * pn2 is the then- or else-statement subtree to compile. Take
+ * care not to expose an object initialiser, which would be parsed
+ * as a block, to the Statement parser via eval(uneval(e)) where e
+ * is '1 ? {p:2, q:3}[i] : r;' or the like.
+ */
+ if (pn->pn_type == TOK_HOOK && StartsWith(pn2, TOK_RC)) {
+ pn->pn_type = TOK_RP;
+ pn->pn_arity = PN_UNARY;
+ pn->pn_kid = pn2;
+ if (pn3 && pn3 != pn2)
+ RecycleTree(pn3, tc);
+ break;
+ }
+ PN_MOVE_NODE(pn, pn2);
+ }
+ if (!pn2 || (pn->pn_type == TOK_SEMI && !pn->pn_kid)) {
+ /*
+ * False condition and no else, or an empty then-statement was
+ * moved up over pn. Either way, make pn an empty block (not an
+ * empty statement, which does not decompile, even when labeled).
+ * NB: pn must be a TOK_IF as TOK_HOOK can never have a null kid
+ * or an empty statement for a child.
+ */
+ pn->pn_type = TOK_LC;
+ pn->pn_arity = PN_LIST;
+ PN_INIT_LIST(pn);
+ }
+ RecycleTree(pn2, tc);
+ if (pn3 && pn3 != pn2)
+ RecycleTree(pn3, tc);
+ break;
+
+ case TOK_OR:
+ case TOK_AND:
+ if (inCond) {
+ if (pn->pn_arity == PN_LIST) {
+ JSParseNode **pnp = &pn->pn_head;
+ JS_ASSERT(*pnp == pn1);
+ do {
+ int cond = Boolish(pn1);
+ if (cond == (pn->pn_type == TOK_OR)) {
+ for (pn2 = pn1->pn_next; pn2; pn2 = pn3) {
+ pn3 = pn2->pn_next;
+ RecycleTree(pn2, tc);
+ --pn->pn_count;
+ }
+ pn1->pn_next = NULL;
+ break;
+ }
+ if (cond != -1) {
+ JS_ASSERT(cond == (pn->pn_type == TOK_AND));
+ if (pn->pn_count == 1)
+ break;
+ *pnp = pn1->pn_next;
+ RecycleTree(pn1, tc);
+ --pn->pn_count;
+ } else {
+ pnp = &pn1->pn_next;
+ }
+ } while ((pn1 = *pnp) != NULL);
+
+ // We may have to change arity from LIST to BINARY.
+ pn1 = pn->pn_head;
+ if (pn->pn_count == 2) {
+ pn2 = pn1->pn_next;
+ pn1->pn_next = NULL;
+ JS_ASSERT(!pn2->pn_next);
+ pn->pn_arity = PN_BINARY;
+ pn->pn_left = pn1;
+ pn->pn_right = pn2;
+ } else if (pn->pn_count == 1) {
+ PN_MOVE_NODE(pn, pn1);
+ RecycleTree(pn1, tc);
+ }
+ } else {
+ int cond = Boolish(pn1);
+ if (cond == (pn->pn_type == TOK_OR)) {
+ RecycleTree(pn2, tc);
+ PN_MOVE_NODE(pn, pn1);
+ } else if (cond != -1) {
+ JS_ASSERT(cond == (pn->pn_type == TOK_AND));
+ RecycleTree(pn1, tc);
+ PN_MOVE_NODE(pn, pn2);
+ }
+ }
+ }
+ break;
+
+ case TOK_ASSIGN:
+ /*
+ * Compound operators such as *= should be subject to folding, in case
+ * the left-hand side is constant, and so that the decompiler produces
+ * the same string that you get from decompiling a script or function
+ * compiled from that same string. As with +, += is special.
+ */
+ if (pn->pn_op == JSOP_NOP)
+ break;
+ if (pn->pn_op != JSOP_ADD)
+ goto do_binary_op;
+ /* FALL THROUGH */
+
+ case TOK_PLUS:
+ if (pn->pn_arity == PN_LIST) {
+ size_t length, length2;
+ jschar *chars;
+ JSString *str, *str2;
+
+ /*
+ * Any string literal term with all others number or string means
+ * this is a concatenation. If any term is not a string or number
+ * literal, we can't fold.
+ */
+ JS_ASSERT(pn->pn_count > 2);
+ if (pn->pn_extra & PNX_CANTFOLD)
+ return JS_TRUE;
+ if (pn->pn_extra != PNX_STRCAT)
+ goto do_binary_op;
+
+ /* Ok, we're concatenating: convert non-string constant operands. */
+ length = 0;
+ for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
+ if (!FoldType(cx, pn2, TOK_STRING))
+ return JS_FALSE;
+ /* XXX fold only if all operands convert to string */
+ if (pn2->pn_type != TOK_STRING)
+ return JS_TRUE;
+ length += JSFLATSTR_LENGTH(ATOM_TO_STRING(pn2->pn_atom));
+ }
+
+ /* Allocate a new buffer and string descriptor for the result. */
+ chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+ str = js_NewString(cx, chars, length);
+ if (!str) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+
+ /* Fill the buffer, advancing chars and recycling kids as we go. */
+ for (pn2 = pn1; pn2; pn2 = RecycleTree(pn2, tc)) {
+ str2 = ATOM_TO_STRING(pn2->pn_atom);
+ length2 = JSFLATSTR_LENGTH(str2);
+ js_strncpy(chars, JSFLATSTR_CHARS(str2), length2);
+ chars += length2;
+ }
+ *chars = 0;
+
+ /* Atomize the result string and mutate pn to refer to it. */
+ pn->pn_atom = js_AtomizeString(cx, str, 0);
+ if (!pn->pn_atom)
+ return JS_FALSE;
+ pn->pn_type = TOK_STRING;
+ pn->pn_op = JSOP_STRING;
+ pn->pn_arity = PN_NULLARY;
+ break;
+ }
+
+ /* Handle a binary string concatenation. */
+ JS_ASSERT(pn->pn_arity == PN_BINARY);
+ if (pn1->pn_type == TOK_STRING || pn2->pn_type == TOK_STRING) {
+ JSString *left, *right, *str;
+
+ if (!FoldType(cx, (pn1->pn_type != TOK_STRING) ? pn1 : pn2,
+ TOK_STRING)) {
+ return JS_FALSE;
+ }
+ if (pn1->pn_type != TOK_STRING || pn2->pn_type != TOK_STRING)
+ return JS_TRUE;
+ left = ATOM_TO_STRING(pn1->pn_atom);
+ right = ATOM_TO_STRING(pn2->pn_atom);
+ str = js_ConcatStrings(cx, left, right);
+ if (!str)
+ return JS_FALSE;
+ pn->pn_atom = js_AtomizeString(cx, str, 0);
+ if (!pn->pn_atom)
+ return JS_FALSE;
+ pn->pn_type = TOK_STRING;
+ pn->pn_op = JSOP_STRING;
+ pn->pn_arity = PN_NULLARY;
+ RecycleTree(pn1, tc);
+ RecycleTree(pn2, tc);
+ break;
+ }
+
+ /* Can't concatenate string literals, let's try numbers. */
+ goto do_binary_op;
+
+ case TOK_STAR:
+ case TOK_SHOP:
+ case TOK_MINUS:
+ case TOK_DIVOP:
+ do_binary_op:
+ if (pn->pn_arity == PN_LIST) {
+ JS_ASSERT(pn->pn_count > 2);
+ for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
+ if (!FoldType(cx, pn2, TOK_NUMBER))
+ return JS_FALSE;
+ }
+ for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
+ /* XXX fold only if all operands convert to number */
+ if (pn2->pn_type != TOK_NUMBER)
+ break;
+ }
+ if (!pn2) {
+ JSOp op = PN_OP(pn);
+
+ pn2 = pn1->pn_next;
+ pn3 = pn2->pn_next;
+ if (!FoldBinaryNumeric(cx, op, pn1, pn2, pn, tc))
+ return JS_FALSE;
+ while ((pn2 = pn3) != NULL) {
+ pn3 = pn2->pn_next;
+ if (!FoldBinaryNumeric(cx, op, pn, pn2, pn, tc))
+ return JS_FALSE;
+ }
+ }
+ } else {
+ JS_ASSERT(pn->pn_arity == PN_BINARY);
+ if (!FoldType(cx, pn1, TOK_NUMBER) ||
+ !FoldType(cx, pn2, TOK_NUMBER)) {
+ return JS_FALSE;
+ }
+ if (pn1->pn_type == TOK_NUMBER && pn2->pn_type == TOK_NUMBER) {
+ if (!FoldBinaryNumeric(cx, PN_OP(pn), pn1, pn2, pn, tc))
+ return JS_FALSE;
+ }
+ }
+ break;
+
+ case TOK_UNARYOP:
+ while (pn1->pn_type == TOK_RP)
+ pn1 = pn1->pn_kid;
+ if (pn1->pn_type == TOK_NUMBER) {
+ jsdouble d;
+
+ /* Operate on one numeric constant. */
+ d = pn1->pn_dval;
+ switch (pn->pn_op) {
+ case JSOP_BITNOT:
+ d = ~js_DoubleToECMAInt32(d);
+ break;
+
+ case JSOP_NEG:
+#ifdef HPUX
+ /*
+ * Negation of a zero doesn't produce a negative
+ * zero on HPUX. Perform the operation by bit
+ * twiddling.
+ */
+ JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT;
+#else
+ d = -d;
+#endif
+ break;
+
+ case JSOP_POS:
+ break;
+
+ case JSOP_NOT:
+ pn->pn_type = TOK_PRIMARY;
+ pn->pn_op = (d == 0 || JSDOUBLE_IS_NaN(d)) ? JSOP_TRUE : JSOP_FALSE;
+ pn->pn_arity = PN_NULLARY;
+ /* FALL THROUGH */
+
+ default:
+ /* Return early to dodge the common TOK_NUMBER code. */
+ return JS_TRUE;
+ }
+ pn->pn_type = TOK_NUMBER;
+ pn->pn_op = JSOP_DOUBLE;
+ pn->pn_arity = PN_NULLARY;
+ pn->pn_dval = d;
+ RecycleTree(pn1, tc);
+ } else if (pn1->pn_type == TOK_PRIMARY) {
+ if (pn->pn_op == JSOP_NOT &&
+ (pn1->pn_op == JSOP_TRUE ||
+ pn1->pn_op == JSOP_FALSE)) {
+ PN_MOVE_NODE(pn, pn1);
+ pn->pn_op = (pn->pn_op == JSOP_TRUE) ? JSOP_FALSE : JSOP_TRUE;
+ RecycleTree(pn1, tc);
+ }
+ }
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_XMLELEM:
+ case TOK_XMLLIST:
+ case TOK_XMLPTAGC:
+ case TOK_XMLSTAGO:
+ case TOK_XMLETAGO:
+ case TOK_XMLNAME:
+ if (pn->pn_arity == PN_LIST) {
+ JS_ASSERT(pn->pn_type == TOK_XMLLIST || pn->pn_count != 0);
+ if (!FoldXMLConstants(cx, pn, tc))
+ return JS_FALSE;
+ }
+ break;
+
+ case TOK_AT:
+ if (pn1->pn_type == TOK_XMLNAME) {
+ jsval v;
+ JSParsedObjectBox *xmlpob;
+
+ v = ATOM_KEY(pn1->pn_atom);
+ if (!js_ToAttributeName(cx, &v))
+ return JS_FALSE;
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+
+ xmlpob = js_NewParsedObjectBox(cx, tc->parseContext,
+ JSVAL_TO_OBJECT(v));
+ if (!xmlpob)
+ return JS_FALSE;
+
+ pn->pn_type = TOK_XMLNAME;
+ pn->pn_op = JSOP_OBJECT;
+ pn->pn_arity = PN_NULLARY;
+ pn->pn_pob = xmlpob;
+ RecycleTree(pn1, tc);
+ }
+ break;
+#endif /* JS_HAS_XML_SUPPORT */
+
+ default:;
+ }
+
+ if (inCond) {
+ int cond = Boolish(pn);
+ if (cond >= 0) {
+ if (pn->pn_arity == PN_LIST) {
+ pn2 = pn->pn_head;
+ do {
+ pn3 = pn2->pn_next;
+ RecycleTree(pn2, tc);
+ } while ((pn2 = pn3) != NULL);
+ }
+ pn->pn_type = TOK_PRIMARY;
+ pn->pn_op = cond ? JSOP_TRUE : JSOP_FALSE;
+ pn->pn_arity = PN_NULLARY;
+ }
+ }
+
+ return JS_TRUE;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsparse.h b/tools/node_modules/expresso/deps/jscoverage/js/jsparse.h
new file mode 100644
index 0000000..90499db
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsparse.h
@@ -0,0 +1,508 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsparse_h___
+#define jsparse_h___
+/*
+ * JS parser definitions.
+ */
+#include "jsversion.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsscan.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Parsing builds a tree of nodes that directs code generation. This tree is
+ * not a concrete syntax tree in all respects (for example, || and && are left
+ * associative, but (A && B && C) translates into the right-associated tree
+ * <A && <B && C>> so that code generation can emit a left-associative branch
+ * around <B && C> when A is false). Nodes are labeled by token type, with a
+ * JSOp secondary label when needed:
+ *
+ * Label Variant Members
+ * ----- ------- -------
+ * <Definitions>
+ * TOK_FUNCTION func pn_funpob: JSParsedObjectBox holding function
+ * object containing arg and var properties. We
+ * create the function object at parse (not emit)
+ * time to specialize arg and var bytecodes early.
+ * pn_body: TOK_LC node for function body statements
+ * pn_flags: TCF_FUN_* flags (see jsemit.h) collected
+ * while parsing the function's body
+ *
+ * <Statements>
+ * TOK_LC list pn_head: list of pn_count statements
+ * TOK_IF ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else or null
+ * TOK_SWITCH binary pn_left: discriminant
+ * pn_right: list of TOK_CASE nodes, with at most one
+ * TOK_DEFAULT node, or if there are let bindings
+ * in the top level of the switch body's cases, a
+ * TOK_LEXICALSCOPE node that contains the list of
+ * TOK_CASE nodes.
+ * TOK_CASE, binary pn_left: case expr or null if TOK_DEFAULT
+ * TOK_DEFAULT pn_right: TOK_LC node for this case's statements
+ * pn_val: constant value if lookup or table switch
+ * TOK_WHILE binary pn_left: cond, pn_right: body
+ * TOK_DO binary pn_left: body, pn_right: cond
+ * TOK_FOR binary pn_left: either
+ * for/in loop: a binary TOK_IN node with
+ * pn_left: TOK_VAR or TOK_NAME to left of 'in'
+ * if TOK_VAR, its pn_extra may have PNX_POPVAR
+ * and PNX_FORINVAR bits set
+ * pn_right: object expr to right of 'in'
+ * for(;;) loop: a ternary TOK_RESERVED node with
+ * pn_kid1: init expr before first ';'
+ * pn_kid2: cond expr before second ';'
+ * pn_kid3: update expr after second ';'
+ * any kid may be null
+ * pn_right: body
+ * TOK_THROW unary pn_op: JSOP_THROW, pn_kid: exception
+ * TOK_TRY ternary pn_kid1: try block
+ * pn_kid2: null or TOK_RESERVED list of
+ * TOK_LEXICALSCOPE nodes, each with pn_expr pointing
+ * to a TOK_CATCH node
+ * pn_kid3: null or finally block
+ * TOK_CATCH ternary pn_kid1: TOK_NAME, TOK_RB, or TOK_RC catch var node
+ * (TOK_RB or TOK_RC if destructuring)
+ * pn_kid2: null or the catch guard expression
+ * pn_kid3: catch block statements
+ * TOK_BREAK name pn_atom: label or null
+ * TOK_CONTINUE name pn_atom: label or null
+ * TOK_WITH binary pn_left: head expr, pn_right: body
+ * TOK_VAR list pn_head: list of pn_count TOK_NAME nodes
+ * each name node has
+ * pn_atom: variable name
+ * pn_expr: initializer or null
+ * TOK_RETURN unary pn_kid: return expr or null
+ * TOK_SEMI unary pn_kid: expr or null statement
+ * TOK_COLON name pn_atom: label, pn_expr: labeled statement
+ *
+ * <Expressions>
+ * All left-associated binary trees of the same type are optimized into lists
+ * to avoid recursion when processing expression chains.
+ * TOK_COMMA list pn_head: list of pn_count comma-separated exprs
+ * TOK_ASSIGN binary pn_left: lvalue, pn_right: rvalue
+ * pn_op: JSOP_ADD for +=, etc.
+ * TOK_HOOK ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else
+ * TOK_OR binary pn_left: first in || chain, pn_right: rest of chain
+ * TOK_AND binary pn_left: first in && chain, pn_right: rest of chain
+ * TOK_BITOR binary pn_left: left-assoc | expr, pn_right: ^ expr
+ * TOK_BITXOR binary pn_left: left-assoc ^ expr, pn_right: & expr
+ * TOK_BITAND binary pn_left: left-assoc & expr, pn_right: EQ expr
+ * TOK_EQOP binary pn_left: left-assoc EQ expr, pn_right: REL expr
+ * pn_op: JSOP_EQ, JSOP_NE,
+ * JSOP_STRICTEQ, JSOP_STRICTNE
+ * TOK_RELOP binary pn_left: left-assoc REL expr, pn_right: SH expr
+ * pn_op: JSOP_LT, JSOP_LE, JSOP_GT, JSOP_GE
+ * TOK_SHOP binary pn_left: left-assoc SH expr, pn_right: ADD expr
+ * pn_op: JSOP_LSH, JSOP_RSH, JSOP_URSH
+ * TOK_PLUS, binary pn_left: left-assoc ADD expr, pn_right: MUL expr
+ * pn_extra: if a left-associated binary TOK_PLUS
+ * tree has been flattened into a list (see above
+ * under <Expressions>), pn_extra will contain
+ * PNX_STRCAT if at least one list element is a
+ * string literal (TOK_STRING); if such a list has
+ * any non-string, non-number term, pn_extra will
+ * contain PNX_CANTFOLD.
+ * pn_
+ * TOK_MINUS pn_op: JSOP_ADD, JSOP_SUB
+ * TOK_STAR, binary pn_left: left-assoc MUL expr, pn_right: UNARY expr
+ * TOK_DIVOP pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
+ * TOK_UNARYOP unary pn_kid: UNARY expr, pn_op: JSOP_NEG, JSOP_POS,
+ * JSOP_NOT, JSOP_BITNOT, JSOP_TYPEOF, JSOP_VOID
+ * TOK_INC, unary pn_kid: MEMBER expr
+ * TOK_DEC
+ * TOK_NEW list pn_head: list of ctor, arg1, arg2, ... argN
+ * pn_count: 1 + N (where N is number of args)
+ * ctor is a MEMBER expr
+ * TOK_DELETE unary pn_kid: MEMBER expr
+ * TOK_DOT, name pn_expr: MEMBER expr to left of .
+ * TOK_DBLDOT pn_atom: name to right of .
+ * TOK_LB binary pn_left: MEMBER expr to left of [
+ * pn_right: expr between [ and ]
+ * TOK_LP list pn_head: list of call, arg1, arg2, ... argN
+ * pn_count: 1 + N (where N is number of args)
+ * call is a MEMBER expr naming a callable object
+ * TOK_RB list pn_head: list of pn_count array element exprs
+ * [,,] holes are represented by TOK_COMMA nodes
+ * #n=[...] produces TOK_DEFSHARP at head of list
+ * pn_extra: PN_ENDCOMMA if extra comma at end
+ * TOK_RC list pn_head: list of pn_count TOK_COLON nodes where
+ * each has pn_left: property id, pn_right: value
+ * #n={...} produces TOK_DEFSHARP at head of list
+ * var {x} = object destructuring shorthand shares
+ * PN_NAME node for x on left and right of TOK_COLON
+ * node in TOK_RC's list, has PNX_SHORTHAND flag
+ * TOK_DEFSHARP unary pn_num: jsint value of n in #n=
+ * pn_kid: null for #n=[...] and #n={...}, primary
+ * if #n=primary for function, paren, name, object
+ * literal expressions
+ * TOK_USESHARP nullary pn_num: jsint value of n in #n#
+ * TOK_RP unary pn_kid: parenthesized expression
+ * TOK_NAME, name pn_atom: name, string, or object atom
+ * TOK_STRING, pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT, or
+ * JSOP_REGEXP
+ * TOK_REGEXP If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
+ * with pn_slot >= 0 and pn_const telling const-ness
+ * TOK_NUMBER dval pn_dval: double value of numeric literal
+ * TOK_PRIMARY nullary pn_op: JSOp bytecode
+ *
+ * <E4X node descriptions>
+ * TOK_ANYNAME nullary pn_op: JSOP_ANYNAME
+ * pn_atom: cx->runtime->atomState.starAtom
+ * TOK_AT unary pn_op: JSOP_TOATTRNAME; pn_kid attribute id/expr
+ * TOK_DBLCOLON binary pn_op: JSOP_QNAME
+ * pn_left: TOK_ANYNAME or TOK_NAME node
+ * pn_right: TOK_STRING "*" node, or expr within []
+ * name pn_op: JSOP_QNAMECONST
+ * pn_expr: TOK_ANYNAME or TOK_NAME left operand
+ * pn_atom: name on right of ::
+ * TOK_XMLELEM list XML element node
+ * pn_head: start tag, content1, ... contentN, end tag
+ * pn_count: 2 + N where N is number of content nodes
+ * N may be > x.length() if {expr} embedded
+ * TOK_XMLLIST list XML list node
+ * pn_head: content1, ... contentN
+ * TOK_XMLSTAGO, list XML start, end, and point tag contents
+ * TOK_XMLETAGC, pn_head: tag name or {expr}, ... XML attrs ...
+ * TOK_XMLPTAGO
+ * TOK_XMLNAME nullary pn_atom: XML name, with no {expr} embedded
+ * TOK_XMLNAME list pn_head: tag name or {expr}, ... name or {expr}
+ * TOK_XMLATTR, nullary pn_atom: attribute value string; pn_op: JSOP_STRING
+ * TOK_XMLCDATA,
+ * TOK_XMLCOMMENT
+ * TOK_XMLPI nullary pn_atom: XML processing instruction target
+ * pn_atom2: XML PI content, or null if no content
+ * TOK_XMLTEXT nullary pn_atom: marked-up text, or null if empty string
+ * TOK_LC unary {expr} in XML tag or content; pn_kid is expr
+ *
+ * So an XML tag with no {expr} and three attributes is a list with the form:
+ *
+ * (tagname attrname1 attrvalue1 attrname2 attrvalue2 attrname2 attrvalue3)
+ *
+ * An XML tag with embedded expressions like so:
+ *
+ * <name1{expr1} name2{expr2}name3={expr3}>
+ *
+ * would have the form:
+ *
+ * ((name1 {expr1}) (name2 {expr2} name3) {expr3})
+ *
+ * where () bracket a list with elements separated by spaces, and {expr} is a
+ * TOK_LC unary node with expr as its kid.
+ *
+ * Thus, the attribute name/value pairs occupy successive odd and even list
+ * locations, where pn_head is the TOK_XMLNAME node at list location 0. The
+ * parser builds the same sort of structures for elements:
+ *
+ * <a x={x}>Hi there!<b y={y}>How are you?</b><answer>{x + y}</answer></a>
+ *
+ * translates to:
+ *
+ * ((a x {x}) 'Hi there!' ((b y {y}) 'How are you?') ((answer) {x + y}))
+ *
+ * <Non-E4X node descriptions, continued>
+ *
+ * Label Variant Members
+ * ----- ------- -------
+ * TOK_LEXICALSCOPE name pn_op: JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR
+ * pn_pob: block object
+ * pn_expr: block body
+ * TOK_ARRAYCOMP list pn_head: list of pn_count (1 or 2) elements
+ * if pn_count is 2, first element is #n=[...]
+ * last element is block enclosing for loop(s)
+ * and optionally if-guarded TOK_ARRAYPUSH
+ * pn_extra: stack slot, used during code gen
+ * TOK_ARRAYPUSH unary pn_op: JSOP_ARRAYCOMP
+ * pn_kid: array comprehension expression
+ */
+typedef enum JSParseNodeArity {
+ PN_FUNC = -3,
+ PN_LIST = -2,
+ PN_TERNARY = 3,
+ PN_BINARY = 2,
+ PN_UNARY = 1,
+ PN_NAME = -1,
+ PN_NULLARY = 0
+} JSParseNodeArity;
+
+struct JSParseNode {
+ uint16 pn_type;
+ uint8 pn_op;
+ int8 pn_arity;
+ JSTokenPos pn_pos;
+ ptrdiff_t pn_offset; /* first generated bytecode offset */
+ union {
+ struct { /* TOK_FUNCTION node */
+ JSParsedObjectBox *funpob; /* function object */
+ JSParseNode *body; /* TOK_LC list of statements */
+ uint16 flags; /* accumulated tree context flags */
+ uint32 index; /* emitter's index */
+ } func;
+ struct { /* list of next-linked nodes */
+ JSParseNode *head; /* first node in list */
+ JSParseNode **tail; /* ptr to ptr to last node in list */
+ uint32 count; /* number of nodes in list */
+ uint32 extra; /* extra flags, see below */
+ } list;
+ struct { /* ternary: if, for(;;), ?: */
+ JSParseNode *kid1; /* condition, discriminant, etc. */
+ JSParseNode *kid2; /* then-part, case list, etc. */
+ JSParseNode *kid3; /* else-part, default case, etc. */
+ } ternary;
+ struct { /* two kids if binary */
+ JSParseNode *left;
+ JSParseNode *right;
+ jsval val; /* switch case value */
+ uintN iflags; /* JSITER_* flags for TOK_FOR node */
+ } binary;
+ struct { /* one kid if unary */
+ JSParseNode *kid;
+ jsint num; /* -1 or sharp variable number */
+ JSBool hidden; /* hidden genexp-induced JSOP_YIELD */
+ } unary;
+ struct { /* name, labeled statement, etc. */
+ JSAtom *atom; /* name or label atom, null if slot */
+ JSParseNode *expr; /* object or initializer */
+ jsint slot; /* -1 or arg or local var slot */
+ JSBool isconst; /* true for const names */
+ } name;
+ struct { /* lexical scope. */
+ JSParsedObjectBox *pob; /* block object */
+ JSParseNode *expr; /* object or initializer */
+ jsint slot; /* -1 or arg or local var slot */
+ } lexical;
+ struct {
+ JSAtom *atom; /* first atom in pair */
+ JSAtom *atom2; /* second atom in pair or null */
+ } apair;
+ struct { /* object literal */
+ JSParsedObjectBox *pob;
+ } object;
+ jsdouble dval; /* aligned numeric literal value */
+ } pn_u;
+ JSParseNode *pn_next; /* to align dval and pn_u on RISCs */
+};
+
+#define pn_funpob pn_u.func.funpob
+#define pn_body pn_u.func.body
+#define pn_flags pn_u.func.flags
+#define pn_index pn_u.func.index
+#define pn_head pn_u.list.head
+#define pn_tail pn_u.list.tail
+#define pn_count pn_u.list.count
+#define pn_extra pn_u.list.extra
+#define pn_kid1 pn_u.ternary.kid1
+#define pn_kid2 pn_u.ternary.kid2
+#define pn_kid3 pn_u.ternary.kid3
+#define pn_left pn_u.binary.left
+#define pn_right pn_u.binary.right
+#define pn_val pn_u.binary.val
+#define pn_iflags pn_u.binary.iflags
+#define pn_kid pn_u.unary.kid
+#define pn_num pn_u.unary.num
+#define pn_hidden pn_u.unary.hidden
+#define pn_atom pn_u.name.atom
+#define pn_expr pn_u.name.expr
+#define pn_slot pn_u.name.slot
+#define pn_const pn_u.name.isconst
+#define pn_dval pn_u.dval
+#define pn_atom2 pn_u.apair.atom2
+#define pn_pob pn_u.object.pob
+
+/* PN_LIST pn_extra flags. */
+#define PNX_STRCAT 0x01 /* TOK_PLUS list has string term */
+#define PNX_CANTFOLD 0x02 /* TOK_PLUS list has unfoldable term */
+#define PNX_POPVAR 0x04 /* TOK_VAR last result needs popping */
+#define PNX_FORINVAR 0x08 /* TOK_VAR is left kid of TOK_IN node,
+ which is left kid of TOK_FOR */
+#define PNX_ENDCOMMA 0x10 /* array literal has comma at end */
+#define PNX_XMLROOT 0x20 /* top-most node in XML literal tree */
+#define PNX_GROUPINIT 0x40 /* var [a, b] = [c, d]; unit list */
+#define PNX_NEEDBRACES 0x80 /* braces necessary due to closure */
+#define PNX_FUNCDEFS 0x100 /* contains top-level function
+ statements */
+#define PNX_SHORTHAND 0x200 /* shorthand syntax used, at present
+ object destructuring ({x,y}) only */
+
+/*
+ * Move pn2 into pn, preserving pn->pn_pos and pn->pn_offset and handing off
+ * any kids in pn2->pn_u, by clearing pn2.
+ */
+#define PN_MOVE_NODE(pn, pn2) \
+ JS_BEGIN_MACRO \
+ (pn)->pn_type = (pn2)->pn_type; \
+ (pn)->pn_op = (pn2)->pn_op; \
+ (pn)->pn_arity = (pn2)->pn_arity; \
+ (pn)->pn_u = (pn2)->pn_u; \
+ PN_CLEAR_NODE(pn2); \
+ JS_END_MACRO
+
+#define PN_CLEAR_NODE(pn) \
+ JS_BEGIN_MACRO \
+ (pn)->pn_type = TOK_EOF; \
+ (pn)->pn_op = JSOP_NOP; \
+ (pn)->pn_arity = PN_NULLARY; \
+ JS_END_MACRO
+
+/* True if pn is a parsenode representing a literal constant. */
+#define PN_IS_CONSTANT(pn) \
+ ((pn)->pn_type == TOK_NUMBER || \
+ (pn)->pn_type == TOK_STRING || \
+ ((pn)->pn_type == TOK_PRIMARY && (pn)->pn_op != JSOP_THIS))
+
+#define PN_OP(pn) ((JSOp)(pn)->pn_op)
+#define PN_TYPE(pn) ((JSTokenType)(pn)->pn_type)
+
+/*
+ * Compute a pointer to the last JSParseNode element in a singly-linked list.
+ * NB: list must be non-empty for correct PN_LAST usage!
+ */
+#define PN_LAST(list) \
+ ((JSParseNode *)((char *)(list)->pn_tail - offsetof(JSParseNode, pn_next)))
+
+#define PN_INIT_LIST(list) \
+ JS_BEGIN_MACRO \
+ (list)->pn_head = NULL; \
+ (list)->pn_tail = &(list)->pn_head; \
+ (list)->pn_count = (list)->pn_extra = 0; \
+ JS_END_MACRO
+
+#define PN_INIT_LIST_1(list, pn) \
+ JS_BEGIN_MACRO \
+ (list)->pn_head = (pn); \
+ (list)->pn_tail = &(pn)->pn_next; \
+ (list)->pn_count = 1; \
+ (list)->pn_extra = 0; \
+ JS_END_MACRO
+
+#define PN_APPEND(list, pn) \
+ JS_BEGIN_MACRO \
+ *(list)->pn_tail = (pn); \
+ (list)->pn_tail = &(pn)->pn_next; \
+ (list)->pn_count++; \
+ JS_END_MACRO
+
+struct JSParsedObjectBox {
+ JSParsedObjectBox *traceLink;
+ JSParsedObjectBox *emitLink;
+ JSObject *object;
+};
+
+struct JSParseContext {
+ JSTokenStream tokenStream;
+ void *tempPoolMark; /* initial JSContext.tempPool mark */
+ JSPrincipals *principals; /* principals associated with source */
+ JSStackFrame *callerFrame; /* scripted caller frame for eval and
+ debug scripts */
+ JSParseNode *nodeList; /* list of recyclable parse-node
+ structs */
+ JSParsedObjectBox *traceListHead; /* list of parsed object for GC
+ tracing */
+ JSTempValueRooter tempRoot; /* root to trace traceListHead */
+};
+
+/*
+ * Convenience macro to access JSParseContext.tokenStream as a pointer.
+ */
+#define TS(pc) (&(pc)->tokenStream)
+
+/*
+ * Parse a top-level JS script.
+ */
+extern JSParseNode *
+js_ParseScript(JSContext *cx, JSObject *chain, JSParseContext *pc);
+
+extern JSScript *
+js_CompileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *callerFrame,
+ JSPrincipals *principals, uint32 tcflags,
+ const jschar *chars, size_t length,
+ FILE *file, const char *filename, uintN lineno);
+
+extern JSBool
+js_CompileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *principals,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno);
+
+extern JSBool
+js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc,
+ bool inCond = false);
+
+#if JS_HAS_XML_SUPPORT
+JS_FRIEND_API(JSParseNode *)
+js_ParseXMLText(JSContext *cx, JSObject *chain, JSParseContext *pc,
+ JSBool allowList);
+#endif
+
+/*
+ * Initialize a parse context. All parameters after pc are passed to
+ * js_InitTokenStream.
+ *
+ * The parse context owns the arena pool "tops-of-stack" space above the
+ * current JSContext.tempPool mark. This means you cannot allocate from
+ * tempPool and save the pointer beyond the next js_FinishParseContext.
+ */
+extern JSBool
+js_InitParseContext(JSContext *cx, JSParseContext *pc, JSPrincipals *principals,
+ JSStackFrame *callerFrame,
+ const jschar *base, size_t length, FILE *fp,
+ const char *filename, uintN lineno);
+
+extern void
+js_FinishParseContext(JSContext *cx, JSParseContext *pc);
+
+extern void
+js_InitCompilePrincipals(JSContext *cx, JSParseContext *pc,
+ JSPrincipals *principals);
+
+/*
+ * Allocate a new parseed object node from cx->tempPool.
+ */
+extern JSParsedObjectBox *
+js_NewParsedObjectBox(JSContext *cx, JSParseContext *pc, JSObject *obj);
+
+extern void
+js_TraceParseContext(JSTracer *trc, JSParseContext *pc);
+
+JS_END_EXTERN_C
+
+#endif /* jsparse_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsprf.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsprf.cpp
new file mode 100644
index 0000000..4285737
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsprf.cpp
@@ -0,0 +1,1262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+** Portable safe sprintf code.
+**
+** Author: Kipp E.B. Hickman
+*/
+#include "jsstddef.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "jsprf.h"
+#include "jslong.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jspubtd.h"
+#include "jsstr.h"
+
+/*
+** Note: on some platforms va_list is defined as an array,
+** and requires array notation.
+*/
+#ifdef HAVE_VA_COPY
+#define VARARGS_ASSIGN(foo, bar) VA_COPY(foo,bar)
+#elif defined(HAVE_VA_LIST_AS_ARRAY)
+#define VARARGS_ASSIGN(foo, bar) foo[0] = bar[0]
+#else
+#define VARARGS_ASSIGN(foo, bar) (foo) = (bar)
+#endif
+
+/*
+** WARNING: This code may *NOT* call JS_LOG (because JS_LOG calls it)
+*/
+
+/*
+** XXX This needs to be internationalized!
+*/
+
+typedef struct SprintfStateStr SprintfState;
+
+struct SprintfStateStr {
+ int (*stuff)(SprintfState *ss, const char *sp, JSUint32 len);
+
+ char *base;
+ char *cur;
+ JSUint32 maxlen;
+
+ int (*func)(void *arg, const char *sp, JSUint32 len);
+ void *arg;
+};
+
+/*
+** Numbered Arguement State
+*/
+struct NumArgState{
+ int type; /* type of the current ap */
+ va_list ap; /* point to the corresponding position on ap */
+};
+
+#define NAS_DEFAULT_NUM 20 /* default number of NumberedArgumentState array */
+
+
+#define TYPE_INT16 0
+#define TYPE_UINT16 1
+#define TYPE_INTN 2
+#define TYPE_UINTN 3
+#define TYPE_INT32 4
+#define TYPE_UINT32 5
+#define TYPE_INT64 6
+#define TYPE_UINT64 7
+#define TYPE_STRING 8
+#define TYPE_DOUBLE 9
+#define TYPE_INTSTR 10
+#define TYPE_WSTRING 11
+#define TYPE_UNKNOWN 20
+
+#define FLAG_LEFT 0x1
+#define FLAG_SIGNED 0x2
+#define FLAG_SPACED 0x4
+#define FLAG_ZEROS 0x8
+#define FLAG_NEG 0x10
+
+/*
+** Fill into the buffer using the data in src
+*/
+static int fill2(SprintfState *ss, const char *src, int srclen, int width,
+ int flags)
+{
+ char space = ' ';
+ int rv;
+
+ width -= srclen;
+ if ((width > 0) && ((flags & FLAG_LEFT) == 0)) { /* Right adjusting */
+ if (flags & FLAG_ZEROS) {
+ space = '0';
+ }
+ while (--width >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+
+ /* Copy out the source data */
+ rv = (*ss->stuff)(ss, src, (JSUint32)srclen);
+ if (rv < 0) {
+ return rv;
+ }
+
+ if ((width > 0) && ((flags & FLAG_LEFT) != 0)) { /* Left adjusting */
+ while (--width >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Fill a number. The order is: optional-sign zero-filling conversion-digits
+*/
+static int fill_n(SprintfState *ss, const char *src, int srclen, int width,
+ int prec, int type, int flags)
+{
+ int zerowidth = 0;
+ int precwidth = 0;
+ int signwidth = 0;
+ int leftspaces = 0;
+ int rightspaces = 0;
+ int cvtwidth;
+ int rv;
+ char sign;
+
+ if ((type & 1) == 0) {
+ if (flags & FLAG_NEG) {
+ sign = '-';
+ signwidth = 1;
+ } else if (flags & FLAG_SIGNED) {
+ sign = '+';
+ signwidth = 1;
+ } else if (flags & FLAG_SPACED) {
+ sign = ' ';
+ signwidth = 1;
+ }
+ }
+ cvtwidth = signwidth + srclen;
+
+ if (prec > 0) {
+ if (prec > srclen) {
+ precwidth = prec - srclen; /* Need zero filling */
+ cvtwidth += precwidth;
+ }
+ }
+
+ if ((flags & FLAG_ZEROS) && (prec < 0)) {
+ if (width > cvtwidth) {
+ zerowidth = width - cvtwidth; /* Zero filling */
+ cvtwidth += zerowidth;
+ }
+ }
+
+ if (flags & FLAG_LEFT) {
+ if (width > cvtwidth) {
+ /* Space filling on the right (i.e. left adjusting) */
+ rightspaces = width - cvtwidth;
+ }
+ } else {
+ if (width > cvtwidth) {
+ /* Space filling on the left (i.e. right adjusting) */
+ leftspaces = width - cvtwidth;
+ }
+ }
+ while (--leftspaces >= 0) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ if (signwidth) {
+ rv = (*ss->stuff)(ss, &sign, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ while (--precwidth >= 0) {
+ rv = (*ss->stuff)(ss, "0", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ while (--zerowidth >= 0) {
+ rv = (*ss->stuff)(ss, "0", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ rv = (*ss->stuff)(ss, src, (JSUint32)srclen);
+ if (rv < 0) {
+ return rv;
+ }
+ while (--rightspaces >= 0) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ return 0;
+}
+
+/*
+** Convert a long into its printable form
+*/
+static int cvt_l(SprintfState *ss, long num, int width, int prec, int radix,
+ int type, int flags, const char *hexp)
+{
+ char cvtbuf[100];
+ char *cvt;
+ int digits;
+
+ /* according to the man page this needs to happen */
+ if ((prec == 0) && (num == 0)) {
+ return 0;
+ }
+
+ /*
+ ** Converting decimal is a little tricky. In the unsigned case we
+ ** need to stop when we hit 10 digits. In the signed case, we can
+ ** stop when the number is zero.
+ */
+ cvt = cvtbuf + sizeof(cvtbuf);
+ digits = 0;
+ while (num) {
+ int digit = (((unsigned long)num) % radix) & 0xF;
+ *--cvt = hexp[digit];
+ digits++;
+ num = (long)(((unsigned long)num) / radix);
+ }
+ if (digits == 0) {
+ *--cvt = '0';
+ digits++;
+ }
+
+ /*
+ ** Now that we have the number converted without its sign, deal with
+ ** the sign and zero padding.
+ */
+ return fill_n(ss, cvt, digits, width, prec, type, flags);
+}
+
+/*
+** Convert a 64-bit integer into its printable form
+*/
+static int cvt_ll(SprintfState *ss, JSInt64 num, int width, int prec, int radix,
+ int type, int flags, const char *hexp)
+{
+ char cvtbuf[100];
+ char *cvt;
+ int digits;
+ JSInt64 rad;
+
+ /* according to the man page this needs to happen */
+ if ((prec == 0) && (JSLL_IS_ZERO(num))) {
+ return 0;
+ }
+
+ /*
+ ** Converting decimal is a little tricky. In the unsigned case we
+ ** need to stop when we hit 10 digits. In the signed case, we can
+ ** stop when the number is zero.
+ */
+ JSLL_I2L(rad, radix);
+ cvt = cvtbuf + sizeof(cvtbuf);
+ digits = 0;
+ while (!JSLL_IS_ZERO(num)) {
+ JSInt32 digit;
+ JSInt64 quot, rem;
+ JSLL_UDIVMOD(&quot, &rem, num, rad);
+ JSLL_L2I(digit, rem);
+ *--cvt = hexp[digit & 0xf];
+ digits++;
+ num = quot;
+ }
+ if (digits == 0) {
+ *--cvt = '0';
+ digits++;
+ }
+
+ /*
+ ** Now that we have the number converted without its sign, deal with
+ ** the sign and zero padding.
+ */
+ return fill_n(ss, cvt, digits, width, prec, type, flags);
+}
+
+/*
+** Convert a double precision floating point number into its printable
+** form.
+**
+** XXX stop using sprintf to convert floating point
+*/
+static int cvt_f(SprintfState *ss, double d, const char *fmt0, const char *fmt1)
+{
+ char fin[20];
+ char fout[300];
+ int amount = fmt1 - fmt0;
+
+ JS_ASSERT((amount > 0) && (amount < (int)sizeof(fin)));
+ if (amount >= (int)sizeof(fin)) {
+ /* Totally bogus % command to sprintf. Just ignore it */
+ return 0;
+ }
+ memcpy(fin, fmt0, (size_t)amount);
+ fin[amount] = 0;
+
+ /* Convert floating point using the native sprintf code */
+#ifdef DEBUG
+ {
+ const char *p = fin;
+ while (*p) {
+ JS_ASSERT(*p != 'L');
+ p++;
+ }
+ }
+#endif
+ sprintf(fout, fin, d);
+
+ /*
+ ** This assert will catch overflow's of fout, when building with
+ ** debugging on. At least this way we can track down the evil piece
+ ** of calling code and fix it!
+ */
+ JS_ASSERT(strlen(fout) < sizeof(fout));
+
+ return (*ss->stuff)(ss, fout, strlen(fout));
+}
+
+/*
+** Convert a string into its printable form. "width" is the output
+** width. "prec" is the maximum number of characters of "s" to output,
+** where -1 means until NUL.
+*/
+static int cvt_s(SprintfState *ss, const char *s, int width, int prec,
+ int flags)
+{
+ int slen;
+
+ if (prec == 0)
+ return 0;
+
+ /* Limit string length by precision value */
+ slen = s ? strlen(s) : 6;
+ if (prec > 0) {
+ if (prec < slen) {
+ slen = prec;
+ }
+ }
+
+ /* and away we go */
+ return fill2(ss, s ? s : "(null)", slen, width, flags);
+}
+
+static int cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec,
+ int flags)
+{
+ int result;
+ /*
+ * Supply NULL as the JSContext; errors are not reported,
+ * and malloc() is used to allocate the buffer buffer.
+ */
+ if (ws) {
+ int slen = js_strlen(ws);
+ char *s = js_DeflateString(NULL, ws, slen);
+ if (!s)
+ return -1; /* JSStuffFunc error indicator. */
+ result = cvt_s(ss, s, width, prec, flags);
+ free(s);
+ } else {
+ result = cvt_s(ss, NULL, width, prec, flags);
+ }
+ return result;
+}
+
+/*
+** BuildArgArray stands for Numbered Argument list Sprintf
+** for example,
+** fmp = "%4$i, %2$d, %3s, %1d";
+** the number must start from 1, and no gap among them
+*/
+
+static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, struct NumArgState* nasArray )
+{
+ int number = 0, cn = 0, i;
+ const char *p;
+ char c;
+ struct NumArgState *nas;
+
+
+ /*
+ ** first pass:
+ ** detemine how many legal % I have got, then allocate space
+ */
+
+ p = fmt;
+ *rv = 0;
+ i = 0;
+ while( ( c = *p++ ) != 0 ){
+ if( c != '%' )
+ continue;
+ if( ( c = *p++ ) == '%' ) /* skip %% case */
+ continue;
+
+ while( c != 0 ){
+ if( c > '9' || c < '0' ){
+ if( c == '$' ){ /* numbered argument csae */
+ if( i > 0 ){
+ *rv = -1;
+ return NULL;
+ }
+ number++;
+ } else { /* non-numbered argument case */
+ if( number > 0 ){
+ *rv = -1;
+ return NULL;
+ }
+ i = 1;
+ }
+ break;
+ }
+
+ c = *p++;
+ }
+ }
+
+ if( number == 0 ){
+ return NULL;
+ }
+
+
+ if( number > NAS_DEFAULT_NUM ){
+ nas = (struct NumArgState*)malloc( number * sizeof( struct NumArgState ) );
+ if( !nas ){
+ *rv = -1;
+ return NULL;
+ }
+ } else {
+ nas = nasArray;
+ }
+
+ for( i = 0; i < number; i++ ){
+ nas[i].type = TYPE_UNKNOWN;
+ }
+
+
+ /*
+ ** second pass:
+ ** set nas[].type
+ */
+
+ p = fmt;
+ while( ( c = *p++ ) != 0 ){
+ if( c != '%' ) continue;
+ c = *p++;
+ if( c == '%' ) continue;
+
+ cn = 0;
+ while( c && c != '$' ){ /* should improve error check later */
+ cn = cn*10 + c - '0';
+ c = *p++;
+ }
+
+ if( !c || cn < 1 || cn > number ){
+ *rv = -1;
+ break;
+ }
+
+ /* nas[cn] starts from 0, and make sure nas[cn].type is not assigned */
+ cn--;
+ if( nas[cn].type != TYPE_UNKNOWN )
+ continue;
+
+ c = *p++;
+
+ /* width */
+ if (c == '*') {
+ /* not supported feature, for the argument is not numbered */
+ *rv = -1;
+ break;
+ }
+
+ while ((c >= '0') && (c <= '9')) {
+ c = *p++;
+ }
+
+ /* precision */
+ if (c == '.') {
+ c = *p++;
+ if (c == '*') {
+ /* not supported feature, for the argument is not numbered */
+ *rv = -1;
+ break;
+ }
+
+ while ((c >= '0') && (c <= '9')) {
+ c = *p++;
+ }
+ }
+
+ /* size */
+ nas[cn].type = TYPE_INTN;
+ if (c == 'h') {
+ nas[cn].type = TYPE_INT16;
+ c = *p++;
+ } else if (c == 'L') {
+ /* XXX not quite sure here */
+ nas[cn].type = TYPE_INT64;
+ c = *p++;
+ } else if (c == 'l') {
+ nas[cn].type = TYPE_INT32;
+ c = *p++;
+ if (c == 'l') {
+ nas[cn].type = TYPE_INT64;
+ c = *p++;
+ }
+ }
+
+ /* format */
+ switch (c) {
+ case 'd':
+ case 'c':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ break;
+
+ case 'e':
+ case 'f':
+ case 'g':
+ nas[ cn ].type = TYPE_DOUBLE;
+ break;
+
+ case 'p':
+ /* XXX should use cpp */
+ if (sizeof(void *) == sizeof(JSInt32)) {
+ nas[ cn ].type = TYPE_UINT32;
+ } else if (sizeof(void *) == sizeof(JSInt64)) {
+ nas[ cn ].type = TYPE_UINT64;
+ } else if (sizeof(void *) == sizeof(JSIntn)) {
+ nas[ cn ].type = TYPE_UINTN;
+ } else {
+ nas[ cn ].type = TYPE_UNKNOWN;
+ }
+ break;
+
+ case 'C':
+ case 'S':
+ case 'E':
+ case 'G':
+ /* XXX not supported I suppose */
+ JS_ASSERT(0);
+ nas[ cn ].type = TYPE_UNKNOWN;
+ break;
+
+ case 's':
+ nas[ cn ].type = (nas[ cn ].type == TYPE_UINT16) ? TYPE_WSTRING : TYPE_STRING;
+ break;
+
+ case 'n':
+ nas[ cn ].type = TYPE_INTSTR;
+ break;
+
+ default:
+ JS_ASSERT(0);
+ nas[ cn ].type = TYPE_UNKNOWN;
+ break;
+ }
+
+ /* get a legal para. */
+ if( nas[ cn ].type == TYPE_UNKNOWN ){
+ *rv = -1;
+ break;
+ }
+ }
+
+
+ /*
+ ** third pass
+ ** fill the nas[cn].ap
+ */
+
+ if( *rv < 0 ){
+ if( nas != nasArray )
+ free( nas );
+ return NULL;
+ }
+
+ cn = 0;
+ while( cn < number ){
+ if( nas[cn].type == TYPE_UNKNOWN ){
+ cn++;
+ continue;
+ }
+
+ VARARGS_ASSIGN(nas[cn].ap, ap);
+
+ switch( nas[cn].type ){
+ case TYPE_INT16:
+ case TYPE_UINT16:
+ case TYPE_INTN:
+ case TYPE_UINTN: (void)va_arg( ap, JSIntn ); break;
+
+ case TYPE_INT32: (void)va_arg( ap, JSInt32 ); break;
+
+ case TYPE_UINT32: (void)va_arg( ap, JSUint32 ); break;
+
+ case TYPE_INT64: (void)va_arg( ap, JSInt64 ); break;
+
+ case TYPE_UINT64: (void)va_arg( ap, JSUint64 ); break;
+
+ case TYPE_STRING: (void)va_arg( ap, char* ); break;
+
+ case TYPE_WSTRING: (void)va_arg( ap, jschar* ); break;
+
+ case TYPE_INTSTR: (void)va_arg( ap, JSIntn* ); break;
+
+ case TYPE_DOUBLE: (void)va_arg( ap, double ); break;
+
+ default:
+ if( nas != nasArray )
+ free( nas );
+ *rv = -1;
+ return NULL;
+ }
+
+ cn++;
+ }
+
+
+ return nas;
+}
+
+/*
+** The workhorse sprintf code.
+*/
+static int dosprintf(SprintfState *ss, const char *fmt, va_list ap)
+{
+ char c;
+ int flags, width, prec, radix, type;
+ union {
+ char ch;
+ jschar wch;
+ int i;
+ long l;
+ JSInt64 ll;
+ double d;
+ const char *s;
+ const jschar* ws;
+ int *ip;
+ } u;
+ const char *fmt0;
+ static const char hex[] = "0123456789abcdef";
+ static const char HEX[] = "0123456789ABCDEF";
+ const char *hexp;
+ int rv, i;
+ struct NumArgState *nas = NULL;
+ struct NumArgState nasArray[ NAS_DEFAULT_NUM ];
+ char pattern[20];
+ const char *dolPt = NULL; /* in "%4$.2f", dolPt will poiont to . */
+ uint8 utf8buf[6];
+ int utf8len;
+
+ /*
+ ** build an argument array, IF the fmt is numbered argument
+ ** list style, to contain the Numbered Argument list pointers
+ */
+
+ nas = BuildArgArray( fmt, ap, &rv, nasArray );
+ if( rv < 0 ){
+ /* the fmt contains error Numbered Argument format, jliu@netscape.com */
+ JS_ASSERT(0);
+ return rv;
+ }
+
+ while ((c = *fmt++) != 0) {
+ if (c != '%') {
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ continue;
+ }
+ fmt0 = fmt - 1;
+
+ /*
+ ** Gobble up the % format string. Hopefully we have handled all
+ ** of the strange cases!
+ */
+ flags = 0;
+ c = *fmt++;
+ if (c == '%') {
+ /* quoting a % with %% */
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ continue;
+ }
+
+ if( nas != NULL ){
+ /* the fmt contains the Numbered Arguments feature */
+ i = 0;
+ while( c && c != '$' ){ /* should imporve error check later */
+ i = ( i * 10 ) + ( c - '0' );
+ c = *fmt++;
+ }
+
+ if( nas[i-1].type == TYPE_UNKNOWN ){
+ if( nas && ( nas != nasArray ) )
+ free( nas );
+ return -1;
+ }
+
+ ap = nas[i-1].ap;
+ dolPt = fmt;
+ c = *fmt++;
+ }
+
+ /*
+ * Examine optional flags. Note that we do not implement the
+ * '#' flag of sprintf(). The ANSI C spec. of the '#' flag is
+ * somewhat ambiguous and not ideal, which is perhaps why
+ * the various sprintf() implementations are inconsistent
+ * on this feature.
+ */
+ while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) {
+ if (c == '-') flags |= FLAG_LEFT;
+ if (c == '+') flags |= FLAG_SIGNED;
+ if (c == ' ') flags |= FLAG_SPACED;
+ if (c == '0') flags |= FLAG_ZEROS;
+ c = *fmt++;
+ }
+ if (flags & FLAG_SIGNED) flags &= ~FLAG_SPACED;
+ if (flags & FLAG_LEFT) flags &= ~FLAG_ZEROS;
+
+ /* width */
+ if (c == '*') {
+ c = *fmt++;
+ width = va_arg(ap, int);
+ } else {
+ width = 0;
+ while ((c >= '0') && (c <= '9')) {
+ width = (width * 10) + (c - '0');
+ c = *fmt++;
+ }
+ }
+
+ /* precision */
+ prec = -1;
+ if (c == '.') {
+ c = *fmt++;
+ if (c == '*') {
+ c = *fmt++;
+ prec = va_arg(ap, int);
+ } else {
+ prec = 0;
+ while ((c >= '0') && (c <= '9')) {
+ prec = (prec * 10) + (c - '0');
+ c = *fmt++;
+ }
+ }
+ }
+
+ /* size */
+ type = TYPE_INTN;
+ if (c == 'h') {
+ type = TYPE_INT16;
+ c = *fmt++;
+ } else if (c == 'L') {
+ /* XXX not quite sure here */
+ type = TYPE_INT64;
+ c = *fmt++;
+ } else if (c == 'l') {
+ type = TYPE_INT32;
+ c = *fmt++;
+ if (c == 'l') {
+ type = TYPE_INT64;
+ c = *fmt++;
+ }
+ }
+
+ /* format */
+ hexp = hex;
+ switch (c) {
+ case 'd': case 'i': /* decimal/integer */
+ radix = 10;
+ goto fetch_and_convert;
+
+ case 'o': /* octal */
+ radix = 8;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'u': /* unsigned decimal */
+ radix = 10;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'x': /* unsigned hex */
+ radix = 16;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'X': /* unsigned HEX */
+ radix = 16;
+ hexp = HEX;
+ type |= 1;
+ goto fetch_and_convert;
+
+ fetch_and_convert:
+ switch (type) {
+ case TYPE_INT16:
+ u.l = va_arg(ap, int);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= FLAG_NEG;
+ }
+ goto do_long;
+ case TYPE_UINT16:
+ u.l = va_arg(ap, int) & 0xffff;
+ goto do_long;
+ case TYPE_INTN:
+ u.l = va_arg(ap, int);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= FLAG_NEG;
+ }
+ goto do_long;
+ case TYPE_UINTN:
+ u.l = (long)va_arg(ap, unsigned int);
+ goto do_long;
+
+ case TYPE_INT32:
+ u.l = va_arg(ap, JSInt32);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= FLAG_NEG;
+ }
+ goto do_long;
+ case TYPE_UINT32:
+ u.l = (long)va_arg(ap, JSUint32);
+ do_long:
+ rv = cvt_l(ss, u.l, width, prec, radix, type, flags, hexp);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case TYPE_INT64:
+ u.ll = va_arg(ap, JSInt64);
+ if (!JSLL_GE_ZERO(u.ll)) {
+ JSLL_NEG(u.ll, u.ll);
+ flags |= FLAG_NEG;
+ }
+ goto do_longlong;
+ case TYPE_UINT64:
+ u.ll = va_arg(ap, JSUint64);
+ do_longlong:
+ rv = cvt_ll(ss, u.ll, width, prec, radix, type, flags, hexp);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+ }
+ break;
+
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ u.d = va_arg(ap, double);
+ if( nas != NULL ){
+ i = fmt - dolPt;
+ if( i < (int)sizeof( pattern ) ){
+ pattern[0] = '%';
+ memcpy( &pattern[1], dolPt, (size_t)i );
+ rv = cvt_f(ss, u.d, pattern, &pattern[i+1] );
+ }
+ } else
+ rv = cvt_f(ss, u.d, fmt0, fmt);
+
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 'c':
+ if ((flags & FLAG_LEFT) == 0) {
+ while (width-- > 1) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ switch (type) {
+ case TYPE_INT16:
+ /* Treat %hc as %c unless js_CStringsAreUTF8. */
+ if (js_CStringsAreUTF8) {
+ u.wch = va_arg(ap, int);
+ utf8len = js_OneUcs4ToUtf8Char (utf8buf, u.wch);
+ rv = (*ss->stuff)(ss, (char *)utf8buf, utf8len);
+ break;
+ }
+ case TYPE_INTN:
+ u.ch = va_arg(ap, int);
+ rv = (*ss->stuff)(ss, &u.ch, 1);
+ break;
+ }
+ if (rv < 0) {
+ return rv;
+ }
+ if (flags & FLAG_LEFT) {
+ while (width-- > 1) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ break;
+
+ case 'p':
+ if (sizeof(void *) == sizeof(JSInt32)) {
+ type = TYPE_UINT32;
+ } else if (sizeof(void *) == sizeof(JSInt64)) {
+ type = TYPE_UINT64;
+ } else if (sizeof(void *) == sizeof(int)) {
+ type = TYPE_UINTN;
+ } else {
+ JS_ASSERT(0);
+ break;
+ }
+ radix = 16;
+ goto fetch_and_convert;
+
+#if 0
+ case 'C':
+ case 'S':
+ case 'E':
+ case 'G':
+ /* XXX not supported I suppose */
+ JS_ASSERT(0);
+ break;
+#endif
+
+ case 's':
+ if(type == TYPE_INT16) {
+ /*
+ * This would do a simple string/byte conversion
+ * unless js_CStringsAreUTF8.
+ */
+ u.ws = va_arg(ap, const jschar*);
+ rv = cvt_ws(ss, u.ws, width, prec, flags);
+ } else {
+ u.s = va_arg(ap, const char*);
+ rv = cvt_s(ss, u.s, width, prec, flags);
+ }
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 'n':
+ u.ip = va_arg(ap, int*);
+ if (u.ip) {
+ *u.ip = ss->cur - ss->base;
+ }
+ break;
+
+ default:
+ /* Not a % token after all... skip it */
+#if 0
+ JS_ASSERT(0);
+#endif
+ rv = (*ss->stuff)(ss, "%", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+
+ /* Stuff trailing NUL */
+ rv = (*ss->stuff)(ss, "\0", 1);
+
+ if( nas && ( nas != nasArray ) ){
+ free( nas );
+ }
+
+ return rv;
+}
+
+/************************************************************************/
+
+static int FuncStuff(SprintfState *ss, const char *sp, JSUint32 len)
+{
+ int rv;
+
+ rv = (*ss->func)(ss->arg, sp, len);
+ if (rv < 0) {
+ return rv;
+ }
+ ss->maxlen += len;
+ return 0;
+}
+
+JS_PUBLIC_API(JSUint32) JS_sxprintf(JSStuffFunc func, void *arg,
+ const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+
+ va_start(ap, fmt);
+ rv = JS_vsxprintf(func, arg, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+JS_PUBLIC_API(JSUint32) JS_vsxprintf(JSStuffFunc func, void *arg,
+ const char *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = FuncStuff;
+ ss.func = func;
+ ss.arg = arg;
+ ss.maxlen = 0;
+ rv = dosprintf(&ss, fmt, ap);
+ return (rv < 0) ? (JSUint32)-1 : ss.maxlen;
+}
+
+/*
+** Stuff routine that automatically grows the malloc'd output buffer
+** before it overflows.
+*/
+static int GrowStuff(SprintfState *ss, const char *sp, JSUint32 len)
+{
+ ptrdiff_t off;
+ char *newbase;
+ JSUint32 newlen;
+
+ off = ss->cur - ss->base;
+ if (off + len >= ss->maxlen) {
+ /* Grow the buffer */
+ newlen = ss->maxlen + ((len > 32) ? len : 32);
+ if (ss->base) {
+ newbase = (char*) realloc(ss->base, newlen);
+ } else {
+ newbase = (char*) malloc(newlen);
+ }
+ if (!newbase) {
+ /* Ran out of memory */
+ return -1;
+ }
+ ss->base = newbase;
+ ss->maxlen = newlen;
+ ss->cur = ss->base + off;
+ }
+
+ /* Copy data */
+ while (len) {
+ --len;
+ *ss->cur++ = *sp++;
+ }
+ JS_ASSERT((JSUint32)(ss->cur - ss->base) <= ss->maxlen);
+ return 0;
+}
+
+/*
+** sprintf into a malloc'd buffer
+*/
+JS_PUBLIC_API(char *) JS_smprintf(const char *fmt, ...)
+{
+ va_list ap;
+ char *rv;
+
+ va_start(ap, fmt);
+ rv = JS_vsmprintf(fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+/*
+** Free memory allocated, for the caller, by JS_smprintf
+*/
+JS_PUBLIC_API(void) JS_smprintf_free(char *mem)
+{
+ free(mem);
+}
+
+JS_PUBLIC_API(char *) JS_vsmprintf(const char *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = GrowStuff;
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ rv = dosprintf(&ss, fmt, ap);
+ if (rv < 0) {
+ if (ss.base) {
+ free(ss.base);
+ }
+ return 0;
+ }
+ return ss.base;
+}
+
+/*
+** Stuff routine that discards overflow data
+*/
+static int LimitStuff(SprintfState *ss, const char *sp, JSUint32 len)
+{
+ JSUint32 limit = ss->maxlen - (ss->cur - ss->base);
+
+ if (len > limit) {
+ len = limit;
+ }
+ while (len) {
+ --len;
+ *ss->cur++ = *sp++;
+ }
+ return 0;
+}
+
+/*
+** sprintf into a fixed size buffer. Make sure there is a NUL at the end
+** when finished.
+*/
+JS_PUBLIC_API(JSUint32) JS_snprintf(char *out, JSUint32 outlen, const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+
+ JS_ASSERT((JSInt32)outlen > 0);
+ if ((JSInt32)outlen <= 0) {
+ return 0;
+ }
+
+ va_start(ap, fmt);
+ rv = JS_vsnprintf(out, outlen, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+JS_PUBLIC_API(JSUint32) JS_vsnprintf(char *out, JSUint32 outlen,const char *fmt,
+ va_list ap)
+{
+ SprintfState ss;
+ JSUint32 n;
+
+ JS_ASSERT((JSInt32)outlen > 0);
+ if ((JSInt32)outlen <= 0) {
+ return 0;
+ }
+
+ ss.stuff = LimitStuff;
+ ss.base = out;
+ ss.cur = out;
+ ss.maxlen = outlen;
+ (void) dosprintf(&ss, fmt, ap);
+
+ /* If we added chars, and we didn't append a null, do it now. */
+ if( (ss.cur != ss.base) && (ss.cur[-1] != '\0') )
+ ss.cur[-1] = '\0';
+
+ n = ss.cur - ss.base;
+ return n ? n - 1 : n;
+}
+
+JS_PUBLIC_API(char *) JS_sprintf_append(char *last, const char *fmt, ...)
+{
+ va_list ap;
+ char *rv;
+
+ va_start(ap, fmt);
+ rv = JS_vsprintf_append(last, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+JS_PUBLIC_API(char *) JS_vsprintf_append(char *last, const char *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = GrowStuff;
+ if (last) {
+ int lastlen = strlen(last);
+ ss.base = last;
+ ss.cur = last + lastlen;
+ ss.maxlen = lastlen;
+ } else {
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ }
+ rv = dosprintf(&ss, fmt, ap);
+ if (rv < 0) {
+ if (ss.base) {
+ free(ss.base);
+ }
+ return 0;
+ }
+ return ss.base;
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsprf.h b/tools/node_modules/expresso/deps/jscoverage/js/jsprf.h
new file mode 100644
index 0000000..1f3200d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsprf.h
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsprf_h___
+#define jsprf_h___
+
+/*
+** API for PR printf like routines. Supports the following formats
+** %d - decimal
+** %u - unsigned decimal
+** %x - unsigned hex
+** %X - unsigned uppercase hex
+** %o - unsigned octal
+** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
+** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
+** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
+** %s - string
+** %hs - 16-bit version of above (only available if js_CStringsAreUTF8)
+** %c - character
+** %hc - 16-bit version of above (only available if js_CStringsAreUTF8)
+** %p - pointer (deals with machine dependent pointer size)
+** %f - float
+** %g - float
+*/
+#include "jstypes.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+JS_BEGIN_EXTERN_C
+
+/*
+** sprintf into a fixed size buffer. Guarantees that a NUL is at the end
+** of the buffer. Returns the length of the written output, NOT including
+** the NUL, or (JSUint32)-1 if an error occurs.
+*/
+extern JS_PUBLIC_API(JSUint32) JS_snprintf(char *out, JSUint32 outlen, const char *fmt, ...);
+
+/*
+** sprintf into a malloc'd buffer. Return a pointer to the malloc'd
+** buffer on success, NULL on failure. Call "JS_smprintf_free" to release
+** the memory returned.
+*/
+extern JS_PUBLIC_API(char*) JS_smprintf(const char *fmt, ...);
+
+/*
+** Free the memory allocated, for the caller, by JS_smprintf
+*/
+extern JS_PUBLIC_API(void) JS_smprintf_free(char *mem);
+
+/*
+** "append" sprintf into a malloc'd buffer. "last" is the last value of
+** the malloc'd buffer. sprintf will append data to the end of last,
+** growing it as necessary using realloc. If last is NULL, JS_sprintf_append
+** will allocate the initial string. The return value is the new value of
+** last for subsequent calls, or NULL if there is a malloc failure.
+*/
+extern JS_PUBLIC_API(char*) JS_sprintf_append(char *last, const char *fmt, ...);
+
+/*
+** sprintf into a function. The function "f" is called with a string to
+** place into the output. "arg" is an opaque pointer used by the stuff
+** function to hold any state needed to do the storage of the output
+** data. The return value is a count of the number of characters fed to
+** the stuff function, or (JSUint32)-1 if an error occurs.
+*/
+typedef JSIntn (*JSStuffFunc)(void *arg, const char *s, JSUint32 slen);
+
+extern JS_PUBLIC_API(JSUint32) JS_sxprintf(JSStuffFunc f, void *arg, const char *fmt, ...);
+
+/*
+** va_list forms of the above.
+*/
+extern JS_PUBLIC_API(JSUint32) JS_vsnprintf(char *out, JSUint32 outlen, const char *fmt, va_list ap);
+extern JS_PUBLIC_API(char*) JS_vsmprintf(const char *fmt, va_list ap);
+extern JS_PUBLIC_API(char*) JS_vsprintf_append(char *last, const char *fmt, va_list ap);
+extern JS_PUBLIC_API(JSUint32) JS_vsxprintf(JSStuffFunc f, void *arg, const char *fmt, va_list ap);
+
+/*
+***************************************************************************
+** FUNCTION: JS_sscanf
+** DESCRIPTION:
+** JS_sscanf() scans the input character string, performs data
+** conversions, and stores the converted values in the data objects
+** pointed to by its arguments according to the format control
+** string.
+**
+** JS_sscanf() behaves the same way as the sscanf() function in the
+** Standard C Library (stdio.h), with the following exceptions:
+** - JS_sscanf() handles the NSPR integer and floating point types,
+** such as JSInt16, JSInt32, JSInt64, and JSFloat64, whereas
+** sscanf() handles the standard C types like short, int, long,
+** and double.
+** - JS_sscanf() has no multibyte character support, while sscanf()
+** does.
+** INPUTS:
+** const char *buf
+** a character string holding the input to scan
+** const char *fmt
+** the format control string for the conversions
+** ...
+** variable number of arguments, each of them is a pointer to
+** a data object in which the converted value will be stored
+** OUTPUTS: none
+** RETURNS: JSInt32
+** The number of values converted and stored.
+** RESTRICTIONS:
+** Multibyte characters in 'buf' or 'fmt' are not allowed.
+***************************************************************************
+*/
+
+extern JS_PUBLIC_API(JSInt32) JS_sscanf(const char *buf, const char *fmt, ...);
+
+JS_END_EXTERN_C
+
+#endif /* jsprf_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsproto.tbl b/tools/node_modules/expresso/deps/jscoverage/js/jsproto.tbl
new file mode 100644
index 0000000..e713d6f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsproto.tbl
@@ -0,0 +1,129 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=80 ft=c:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey 1.7 work in progress, released
+ * February 14, 2006.
+ *
+ * The Initial Developer of the Original Code is
+ * Brendan Eich <brendan@mozilla.org>
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsversion.h"
+
+#if JS_HAS_SCRIPT_OBJECT
+# define SCRIPT_INIT js_InitScriptClass
+#else
+# define SCRIPT_INIT js_InitNullClass
+#endif
+
+#if JS_HAS_XML_SUPPORT
+# define XML_INIT js_InitXMLClass
+# define NAMESPACE_INIT js_InitNamespaceClass
+# define QNAME_INIT js_InitQNameClass
+# define ANYNAME_INIT js_InitAnyNameClass
+# define ATTRIBUTE_INIT js_InitAttributeNameClass
+# define XMLFILTER_INIT js_InitXMLFilterClass
+#else
+# define XML_INIT js_InitNullClass
+# define NAMESPACE_INIT js_InitNullClass
+# define QNAME_INIT js_InitNullClass
+# define ANYNAME_INIT js_InitNullClass
+# define ATTRIBUTE_INIT js_InitNullClass
+# define XMLFILTER_INIT js_InitNullClass
+#endif
+
+#if JS_HAS_GENERATORS
+# define GENERATOR_INIT js_InitIteratorClasses
+#else
+# define GENERATOR_INIT js_InitNullClass
+#endif
+
+#if JS_HAS_NO_SUCH_METHOD
+# define NO_SUCH_METHOD_INIT js_InitNoSuchMethodClass
+#else
+# define NO_SUCH_METHOD_INIT js_InitNullClass
+#endif
+
+#if JS_HAS_FILE_OBJECT
+# define FILE_INIT js_InitFileClass
+#else
+# define FILE_INIT js_InitNullClass
+#endif
+
+/*
+ * Enumerator codes in the second column must not change -- they are part of
+ * the JS XDR API. Client modules including jsproto.tbl should consider
+ * wrapping the inclusion with JS_BEGIN_EXTERN_C and JS_END_EXTERN_C.
+ */
+JS_PROTO(Null, 0, js_InitNullClass)
+JS_PROTO(Object, 1, js_InitFunctionAndObjectClasses)
+JS_PROTO(Function, 2, js_InitFunctionAndObjectClasses)
+JS_PROTO(Array, 3, js_InitArrayClass)
+JS_PROTO(Boolean, 4, js_InitBooleanClass)
+JS_PROTO(Call, 5, js_InitCallClass)
+JS_PROTO(Date, 6, js_InitDateClass)
+JS_PROTO(Math, 7, js_InitMathClass)
+JS_PROTO(Number, 8, js_InitNumberClass)
+JS_PROTO(String, 9, js_InitStringClass)
+JS_PROTO(RegExp, 10, js_InitRegExpClass)
+JS_PROTO(Script, 11, SCRIPT_INIT)
+JS_PROTO(XML, 12, XML_INIT)
+JS_PROTO(Namespace, 13, NAMESPACE_INIT)
+JS_PROTO(QName, 14, QNAME_INIT)
+JS_PROTO(AnyName, 15, ANYNAME_INIT)
+JS_PROTO(AttributeName, 16, ATTRIBUTE_INIT)
+JS_PROTO(Error, 17, js_InitExceptionClasses)
+JS_PROTO(InternalError, 18, js_InitExceptionClasses)
+JS_PROTO(EvalError, 19, js_InitExceptionClasses)
+JS_PROTO(RangeError, 20, js_InitExceptionClasses)
+JS_PROTO(ReferenceError, 21, js_InitExceptionClasses)
+JS_PROTO(SyntaxError, 22, js_InitExceptionClasses)
+JS_PROTO(TypeError, 23, js_InitExceptionClasses)
+JS_PROTO(URIError, 24, js_InitExceptionClasses)
+JS_PROTO(Generator, 25, GENERATOR_INIT)
+JS_PROTO(Iterator, 26, js_InitIteratorClasses)
+JS_PROTO(StopIteration, 27, js_InitIteratorClasses)
+JS_PROTO(UnusedProto28, 28, js_InitNullClass)
+JS_PROTO(File, 29, FILE_INIT)
+JS_PROTO(Block, 30, js_InitBlockClass)
+JS_PROTO(XMLFilter, 31, XMLFILTER_INIT)
+JS_PROTO(NoSuchMethod, 32, NO_SUCH_METHOD_INIT)
+JS_PROTO(JSON, 33, js_InitJSONClass)
+
+#undef SCRIPT_INIT
+#undef XML_INIT
+#undef NAMESPACE_INIT
+#undef QNAME_INIT
+#undef ANYNAME_INIT
+#undef ATTRIBUTE_INIT
+#undef GENERATOR_INIT
+#undef FILE_INIT
+#undef NO_SUCH_METHOD_INIT
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsprvtd.h b/tools/node_modules/expresso/deps/jscoverage/js/jsprvtd.h
new file mode 100644
index 0000000..710fa99
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsprvtd.h
@@ -0,0 +1,263 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsprvtd_h___
+#define jsprvtd_h___
+/*
+ * JS private typename definitions.
+ *
+ * This header is included only in other .h files, for convenience and for
+ * simplicity of type naming. The alternative for structures is to use tags,
+ * which are named the same as their typedef names (legal in C/C++, and less
+ * noisy than suffixing the typedef name with "Struct" or "Str"). Instead,
+ * all .h files that include this file may use the same typedef name, whether
+ * declaring a pointer to struct type, or defining a member of struct type.
+ *
+ * A few fundamental scalar types are defined here too. Neither the scalar
+ * nor the struct typedefs should change much, therefore the nearly-global
+ * make dependency induced by this file should not prove painful.
+ */
+
+#include "jspubtd.h"
+
+/* Internal identifier (jsid) macros. */
+
+#define JSID_IS_ATOM(id) JSVAL_IS_STRING((jsval)(id))
+#define JSID_TO_ATOM(id) ((JSAtom *)(id))
+#define ATOM_TO_JSID(atom) (JS_ASSERT(ATOM_IS_STRING(atom)), \
+ (jsid)(atom))
+
+#define JSID_IS_INT(id) JSVAL_IS_INT((jsval)(id))
+#define JSID_TO_INT(id) JSVAL_TO_INT((jsval)(id))
+#define INT_TO_JSID(i) ((jsid)INT_TO_JSVAL(i))
+#define INT_JSVAL_TO_JSID(v) ((jsid)(v))
+#define INT_JSID_TO_JSVAL(id) ((jsval)(id))
+
+#define JSID_IS_OBJECT(id) JSVAL_IS_OBJECT((jsval)(id))
+#define JSID_TO_OBJECT(id) JSVAL_TO_OBJECT((jsval)(id))
+#define OBJECT_TO_JSID(obj) ((jsid)OBJECT_TO_JSVAL(obj))
+#define OBJECT_JSVAL_TO_JSID(v) ((jsid)v)
+
+#define ID_TO_VALUE(id) ((jsval)(id))
+
+/*
+ * Convenience constants.
+ */
+#define JS_BITS_PER_UINT32_LOG2 5
+#define JS_BITS_PER_UINT32 32
+
+/* Scalar typedefs. */
+typedef uint8 jsbytecode;
+typedef uint8 jssrcnote;
+typedef uint32 jsatomid;
+
+/* Struct typedefs. */
+typedef struct JSArgumentFormatMap JSArgumentFormatMap;
+typedef struct JSCodeGenerator JSCodeGenerator;
+typedef struct JSGCThing JSGCThing;
+typedef struct JSGenerator JSGenerator;
+typedef struct JSNativeEnumerator JSNativeEnumerator;
+typedef struct JSParseContext JSParseContext;
+typedef struct JSParsedObjectBox JSParsedObjectBox;
+typedef struct JSParseNode JSParseNode;
+typedef struct JSPropCacheEntry JSPropCacheEntry;
+typedef struct JSSharpObjectMap JSSharpObjectMap;
+typedef struct JSTempValueRooter JSTempValueRooter;
+typedef struct JSThread JSThread;
+typedef struct JSToken JSToken;
+typedef struct JSTokenPos JSTokenPos;
+typedef struct JSTokenPtr JSTokenPtr;
+typedef struct JSTokenStream JSTokenStream;
+typedef struct JSTreeContext JSTreeContext;
+typedef struct JSTryNote JSTryNote;
+typedef struct JSWeakRoots JSWeakRoots;
+
+/* Friend "Advanced API" typedefs. */
+typedef struct JSAtom JSAtom;
+typedef struct JSAtomList JSAtomList;
+typedef struct JSAtomListElement JSAtomListElement;
+typedef struct JSAtomMap JSAtomMap;
+typedef struct JSAtomState JSAtomState;
+typedef struct JSCodeSpec JSCodeSpec;
+typedef struct JSPrinter JSPrinter;
+typedef struct JSRegExp JSRegExp;
+typedef struct JSRegExpStatics JSRegExpStatics;
+typedef struct JSScope JSScope;
+typedef struct JSScopeOps JSScopeOps;
+typedef struct JSScopeProperty JSScopeProperty;
+typedef struct JSStackHeader JSStackHeader;
+typedef struct JSStringBuffer JSStringBuffer;
+typedef struct JSSubString JSSubString;
+typedef struct JSTraceableNative JSTraceableNative;
+typedef struct JSXML JSXML;
+typedef struct JSXMLArray JSXMLArray;
+typedef struct JSXMLArrayCursor JSXMLArrayCursor;
+
+/* "Friend" types used by jscntxt.h and jsdbgapi.h. */
+typedef enum JSTrapStatus {
+ JSTRAP_ERROR,
+ JSTRAP_CONTINUE,
+ JSTRAP_RETURN,
+ JSTRAP_THROW,
+ JSTRAP_LIMIT
+} JSTrapStatus;
+
+typedef JSTrapStatus
+(* JSTrapHandler)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
+ void *closure);
+
+typedef JSBool
+(* JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsval id, jsval old,
+ jsval *newp, void *closure);
+
+/* called just after script creation */
+typedef void
+(* JSNewScriptHook)(JSContext *cx,
+ const char *filename, /* URL of script */
+ uintN lineno, /* first line */
+ JSScript *script,
+ JSFunction *fun,
+ void *callerdata);
+
+/* called just before script destruction */
+typedef void
+(* JSDestroyScriptHook)(JSContext *cx,
+ JSScript *script,
+ void *callerdata);
+
+typedef void
+(* JSSourceHandler)(const char *filename, uintN lineno, jschar *str,
+ size_t length, void **listenerTSData, void *closure);
+
+/*
+ * This hook captures high level script execution and function calls (JS or
+ * native). It is used by JS_SetExecuteHook to hook top level scripts and by
+ * JS_SetCallHook to hook function calls. It will get called twice per script
+ * or function call: just before execution begins and just after it finishes.
+ * In both cases the 'current' frame is that of the executing code.
+ *
+ * The 'before' param is JS_TRUE for the hook invocation before the execution
+ * and JS_FALSE for the invocation after the code has run.
+ *
+ * The 'ok' param is significant only on the post execution invocation to
+ * signify whether or not the code completed 'normally'.
+ *
+ * The 'closure' param is as passed to JS_SetExecuteHook or JS_SetCallHook
+ * for the 'before'invocation, but is whatever value is returned from that
+ * invocation for the 'after' invocation. Thus, the hook implementor *could*
+ * allocate a structure in the 'before' invocation and return a pointer to that
+ * structure. The pointer would then be handed to the hook for the 'after'
+ * invocation. Alternately, the 'before' could just return the same value as
+ * in 'closure' to cause the 'after' invocation to be called with the same
+ * 'closure' value as the 'before'.
+ *
+ * Returning NULL in the 'before' hook will cause the 'after' hook *not* to
+ * be called.
+ */
+typedef void *
+(* JSInterpreterHook)(JSContext *cx, JSStackFrame *fp, JSBool before,
+ JSBool *ok, void *closure);
+
+typedef void
+(* JSObjectHook)(JSContext *cx, JSObject *obj, JSBool isNew, void *closure);
+
+typedef JSBool
+(* JSDebugErrorHook)(JSContext *cx, const char *message, JSErrorReport *report,
+ void *closure);
+
+typedef struct JSDebugHooks {
+ JSTrapHandler interruptHandler;
+ void *interruptHandlerData;
+ JSNewScriptHook newScriptHook;
+ void *newScriptHookData;
+ JSDestroyScriptHook destroyScriptHook;
+ void *destroyScriptHookData;
+ JSTrapHandler debuggerHandler;
+ void *debuggerHandlerData;
+ JSSourceHandler sourceHandler;
+ void *sourceHandlerData;
+ JSInterpreterHook executeHook;
+ void *executeHookData;
+ JSInterpreterHook callHook;
+ void *callHookData;
+ JSObjectHook objectHook;
+ void *objectHookData;
+ JSTrapHandler throwHook;
+ void *throwHookData;
+ JSDebugErrorHook debugErrorHook;
+ void *debugErrorHookData;
+} JSDebugHooks;
+
+/*
+ * Type definitions for temporary GC roots that register with GC local C
+ * variables. See jscntxt.h for details.
+ */
+typedef void
+(* JSTempValueTrace)(JSTracer *trc, JSTempValueRooter *tvr);
+
+typedef union JSTempValueUnion {
+ jsval value;
+ JSObject *object;
+ JSString *string;
+ JSXML *xml;
+ JSTempValueTrace trace;
+ JSScopeProperty *sprop;
+ JSWeakRoots *weakRoots;
+ JSParseContext *parseContext;
+ JSScript *script;
+ jsval *array;
+} JSTempValueUnion;
+
+struct JSTempValueRooter {
+ JSTempValueRooter *down;
+ ptrdiff_t count;
+ JSTempValueUnion u;
+};
+
+/*
+ * The following determines whether JS_EncodeCharacters and JS_DecodeBytes
+ * treat char[] as utf-8 or simply as bytes that need to be inflated/deflated.
+ */
+#ifdef JS_C_STRINGS_ARE_UTF8
+# define js_CStringsAreUTF8 JS_TRUE
+#else
+extern JSBool js_CStringsAreUTF8;
+#endif
+
+#endif /* jsprvtd_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jspubtd.h b/tools/node_modules/expresso/deps/jscoverage/js/jspubtd.h
new file mode 100644
index 0000000..1e3f33a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jspubtd.h
@@ -0,0 +1,727 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jspubtd_h___
+#define jspubtd_h___
+/*
+ * JS public API typedefs.
+ */
+#include "jstypes.h"
+#include "jscompat.h"
+
+JS_BEGIN_EXTERN_C
+
+/* Scalar typedefs. */
+typedef uint16 jschar;
+typedef int32 jsint;
+typedef uint32 jsuint;
+typedef float64 jsdouble;
+typedef jsword jsval;
+typedef jsword jsid;
+typedef int32 jsrefcount; /* PRInt32 if JS_THREADSAFE, see jslock.h */
+
+/*
+ * Run-time version enumeration. See jsversion.h for compile-time counterparts
+ * to these values that may be selected by the JS_VERSION macro, and tested by
+ * #if expressions.
+ */
+typedef enum JSVersion {
+ JSVERSION_1_0 = 100,
+ JSVERSION_1_1 = 110,
+ JSVERSION_1_2 = 120,
+ JSVERSION_1_3 = 130,
+ JSVERSION_1_4 = 140,
+ JSVERSION_ECMA_3 = 148,
+ JSVERSION_1_5 = 150,
+ JSVERSION_1_6 = 160,
+ JSVERSION_1_7 = 170,
+ JSVERSION_1_8 = 180,
+ JSVERSION_DEFAULT = 0,
+ JSVERSION_UNKNOWN = -1,
+ JSVERSION_LATEST = JSVERSION_1_8
+} JSVersion;
+
+#define JSVERSION_IS_ECMA(version) \
+ ((version) == JSVERSION_DEFAULT || (version) >= JSVERSION_1_3)
+
+/* Result of typeof operator enumeration. */
+typedef enum JSType {
+ JSTYPE_VOID, /* undefined */
+ JSTYPE_OBJECT, /* object */
+ JSTYPE_FUNCTION, /* function */
+ JSTYPE_STRING, /* string */
+ JSTYPE_NUMBER, /* number */
+ JSTYPE_BOOLEAN, /* boolean */
+ JSTYPE_NULL, /* null */
+ JSTYPE_XML, /* xml object */
+ JSTYPE_LIMIT
+} JSType;
+
+/* Dense index into cached prototypes and class atoms for standard objects. */
+typedef enum JSProtoKey {
+#define JS_PROTO(name,code,init) JSProto_##name = code,
+#include "jsproto.tbl"
+#undef JS_PROTO
+ JSProto_LIMIT
+} JSProtoKey;
+
+/* JSObjectOps.checkAccess mode enumeration. */
+typedef enum JSAccessMode {
+ JSACC_PROTO = 0, /* XXXbe redundant w.r.t. id */
+ JSACC_PARENT = 1, /* XXXbe redundant w.r.t. id */
+
+ /*
+ * enum value #2 formerly called JSACC_IMPORT,
+ * gap preserved for liveconnect ABI compatibility.
+ */
+
+ JSACC_WATCH = 3, /* a watchpoint on object foo for id 'bar' */
+ JSACC_READ = 4, /* a "get" of foo.bar */
+ JSACC_WRITE = 8, /* a "set" of foo.bar = baz */
+ JSACC_LIMIT
+} JSAccessMode;
+
+#define JSACC_TYPEMASK (JSACC_WRITE - 1)
+
+/*
+ * This enum type is used to control the behavior of a JSObject property
+ * iterator function that has type JSNewEnumerate.
+ */
+typedef enum JSIterateOp {
+ JSENUMERATE_INIT, /* Create new iterator state */
+ JSENUMERATE_NEXT, /* Iterate once */
+ JSENUMERATE_DESTROY /* Destroy iterator state */
+} JSIterateOp;
+
+/* Struct typedefs. */
+typedef struct JSClass JSClass;
+typedef struct JSExtendedClass JSExtendedClass;
+typedef struct JSConstDoubleSpec JSConstDoubleSpec;
+typedef struct JSContext JSContext;
+typedef struct JSErrorReport JSErrorReport;
+typedef struct JSFunction JSFunction;
+typedef struct JSFunctionSpec JSFunctionSpec;
+typedef struct JSTracer JSTracer;
+typedef struct JSIdArray JSIdArray;
+typedef struct JSProperty JSProperty;
+typedef struct JSPropertySpec JSPropertySpec;
+typedef struct JSObject JSObject;
+typedef struct JSObjectMap JSObjectMap;
+typedef struct JSObjectOps JSObjectOps;
+typedef struct JSXMLObjectOps JSXMLObjectOps;
+typedef struct JSRuntime JSRuntime;
+typedef struct JSRuntime JSTaskState; /* XXX deprecated name */
+typedef struct JSScript JSScript;
+typedef struct JSStackFrame JSStackFrame;
+typedef struct JSString JSString;
+typedef struct JSXDRState JSXDRState;
+typedef struct JSExceptionState JSExceptionState;
+typedef struct JSLocaleCallbacks JSLocaleCallbacks;
+typedef struct JSSecurityCallbacks JSSecurityCallbacks;
+typedef struct JSONParser JSONParser;
+
+/* JSClass (and JSObjectOps where appropriate) function pointer typedefs. */
+
+/*
+ * Add, delete, get or set a property named by id in obj. Note the jsval id
+ * type -- id may be a string (Unicode property identifier) or an int (element
+ * index). The *vp out parameter, on success, is the new property value after
+ * an add, get, or set. After a successful delete, *vp is JSVAL_FALSE iff
+ * obj[id] can't be deleted (because it's permanent).
+ */
+typedef JSBool
+(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+/*
+ * This function type is used for callbacks that enumerate the properties of
+ * a JSObject. The behavior depends on the value of enum_op:
+ *
+ * JSENUMERATE_INIT
+ * A new, opaque iterator state should be allocated and stored in *statep.
+ * (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
+ *
+ * The number of properties that will be enumerated should be returned as
+ * an integer jsval in *idp, if idp is non-null, and provided the number of
+ * enumerable properties is known. If idp is non-null and the number of
+ * enumerable properties can't be computed in advance, *idp should be set
+ * to JSVAL_ZERO.
+ *
+ * JSENUMERATE_NEXT
+ * A previously allocated opaque iterator state is passed in via statep.
+ * Return the next jsid in the iteration using *idp. The opaque iterator
+ * state pointed at by statep is destroyed and *statep is set to JSVAL_NULL
+ * if there are no properties left to enumerate.
+ *
+ * JSENUMERATE_DESTROY
+ * Destroy the opaque iterator state previously allocated in *statep by a
+ * call to this function when enum_op was JSENUMERATE_INIT.
+ *
+ * The return value is used to indicate success, with a value of JS_FALSE
+ * indicating failure.
+ */
+typedef JSBool
+(* JSNewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp);
+
+/*
+ * The old-style JSClass.enumerate op should define all lazy properties not
+ * yet reflected in obj.
+ */
+typedef JSBool
+(* JSEnumerateOp)(JSContext *cx, JSObject *obj);
+
+/*
+ * Resolve a lazy property named by id in obj by defining it directly in obj.
+ * Lazy properties are those reflected from some peer native property space
+ * (e.g., the DOM attributes for a given node reflected as obj) on demand.
+ *
+ * JS looks for a property in an object, and if not found, tries to resolve
+ * the given id. If resolve succeeds, the engine looks again in case resolve
+ * defined obj[id]. If no such property exists directly in obj, the process
+ * is repeated with obj's prototype, etc.
+ *
+ * NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
+ */
+typedef JSBool
+(* JSResolveOp)(JSContext *cx, JSObject *obj, jsval id);
+
+/*
+ * Like JSResolveOp, but flags provide contextual information as follows:
+ *
+ * JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id
+ * JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment
+ * JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence
+ * JSRESOLVE_DECLARING var, const, or function prolog declaration opcode
+ * JSRESOLVE_CLASSNAME class name used when constructing
+ *
+ * The *objp out parameter, on success, should be null to indicate that id
+ * was not resolved; and non-null, referring to obj or one of its prototypes,
+ * if id was resolved.
+ *
+ * This hook instead of JSResolveOp is called via the JSClass.resolve member
+ * if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
+ *
+ * Setting JSCLASS_NEW_RESOLVE and JSCLASS_NEW_RESOLVE_GETS_START further
+ * extends this hook by passing in the starting object on the prototype chain
+ * via *objp. Thus a resolve hook implementation may define the property id
+ * being resolved in the object in which the id was first sought, rather than
+ * in a prototype object whose class led to the resolve hook being called.
+ *
+ * When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore
+ * null *objp to signify "not resolved". With only JSCLASS_NEW_RESOLVE and no
+ * JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry.
+ * This is not good practice, but enough existing hook implementations count
+ * on it that we can't break compatibility by passing the starting object in
+ * *objp without a new JSClass flag.
+ */
+typedef JSBool
+(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp);
+
+/*
+ * Convert obj to the given type, returning true with the resulting value in
+ * *vp on success, and returning false on error or exception.
+ */
+typedef JSBool
+(* JSConvertOp)(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+
+/*
+ * Finalize obj, which the garbage collector has determined to be unreachable
+ * from other live objects or from GC roots. Obviously, finalizers must never
+ * store a reference to obj.
+ */
+typedef void
+(* JSFinalizeOp)(JSContext *cx, JSObject *obj);
+
+/*
+ * Used by JS_AddExternalStringFinalizer and JS_RemoveExternalStringFinalizer
+ * to extend and reduce the set of string types finalized by the GC.
+ */
+typedef void
+(* JSStringFinalizeOp)(JSContext *cx, JSString *str);
+
+/*
+ * The signature for JSClass.getObjectOps, used by JS_NewObject's internals
+ * to discover the set of high-level object operations to use for new objects
+ * of the given class. All native objects have a JSClass, which is stored as
+ * a private (int-tagged) pointer in obj slots. In contrast, all native and
+ * host objects have a JSObjectMap at obj->map, which may be shared among a
+ * number of objects, and which contains the JSObjectOps *ops pointer used to
+ * dispatch object operations from API calls.
+ *
+ * Thus JSClass (which pre-dates JSObjectOps in the API) provides a low-level
+ * interface to class-specific code and data, while JSObjectOps allows for a
+ * higher level of operation, which does not use the object's class except to
+ * find the class's JSObjectOps struct, by calling clasp->getObjectOps, and to
+ * finalize the object.
+ *
+ * If this seems backwards, that's because it is! API compatibility requires
+ * a JSClass *clasp parameter to JS_NewObject, etc. Most host objects do not
+ * need to implement the larger JSObjectOps, and can share the common JSScope
+ * code and data used by the native (js_ObjectOps, see jsobj.c) ops.
+ *
+ * Further extension to preserve API compatibility: if this function returns
+ * a pointer to JSXMLObjectOps.base, not to JSObjectOps, then the engine calls
+ * extended hooks needed for E4X.
+ */
+typedef JSObjectOps *
+(* JSGetObjectOps)(JSContext *cx, JSClass *clasp);
+
+/*
+ * JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
+ * returning false on error/exception, true on success with obj[id]'s last-got
+ * value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id
+ * is either a string or an int jsval.
+ *
+ * See JSCheckAccessIdOp, below, for the JSObjectOps counterpart, which takes
+ * a jsid (a tagged int or aligned, unique identifier pointer) rather than a
+ * jsval. The native js_ObjectOps.checkAccess simply forwards to the object's
+ * clasp->checkAccess, so that both JSClass and JSObjectOps implementors may
+ * specialize access checks.
+ */
+typedef JSBool
+(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsval id, JSAccessMode mode,
+ jsval *vp);
+
+/*
+ * Encode or decode an object, given an XDR state record representing external
+ * data. See jsxdrapi.h.
+ */
+typedef JSBool
+(* JSXDRObjectOp)(JSXDRState *xdr, JSObject **objp);
+
+/*
+ * Check whether v is an instance of obj. Return false on error or exception,
+ * true on success with JS_TRUE in *bp if v is an instance of obj, JS_FALSE in
+ * *bp otherwise.
+ */
+typedef JSBool
+(* JSHasInstanceOp)(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+/*
+ * Deprecated function type for JSClass.mark. All new code should define
+ * JSTraceOp instead to ensure the traversal of traceable things stored in
+ * the native structures.
+ */
+typedef uint32
+(* JSMarkOp)(JSContext *cx, JSObject *obj, void *arg);
+
+/*
+ * Function type for trace operation of the class called to enumerate all
+ * traceable things reachable from obj's private data structure. For each such
+ * thing, a trace implementation must call
+ *
+ * JS_CallTracer(trc, thing, kind);
+ *
+ * or one of its convenience macros as described in jsapi.h.
+ *
+ * JSTraceOp implementation can assume that no other threads mutates object
+ * state. It must not change state of the object or corresponding native
+ * structures. The only exception for this rule is the case when the embedding
+ * needs a tight integration with GC. In that case the embedding can check if
+ * the traversal is a part of the marking phase through calling
+ * JS_IsGCMarkingTracer and apply a special code like emptying caches or
+ * marking its native structures.
+ *
+ * To define the tracer for a JSClass, the implementation must add
+ * JSCLASS_MARK_IS_TRACE to class flags and use JS_CLASS_TRACE(method)
+ * macro below to convert JSTraceOp to JSMarkOp when initializing or
+ * assigning JSClass.mark field.
+ */
+typedef void
+(* JSTraceOp)(JSTracer *trc, JSObject *obj);
+
+#if defined __GNUC__ && __GNUC__ >= 4 && !defined __cplusplus
+# define JS_CLASS_TRACE(method) \
+ (__builtin_types_compatible_p(JSTraceOp, __typeof(&(method))) \
+ ? (JSMarkOp)(method) \
+ : js_WrongTypeForClassTracer)
+
+extern JSMarkOp js_WrongTypeForClassTracer;
+
+#else
+# define JS_CLASS_TRACE(method) ((JSMarkOp)(method))
+#endif
+
+/*
+ * Tracer callback, called for each traceable thing directly refrenced by a
+ * particular object or runtime structure. It is the callback responsibility
+ * to ensure the traversal of the full object graph via calling eventually
+ * JS_TraceChildren on the passed thing. In this case the callback must be
+ * prepared to deal with cycles in the traversal graph.
+ *
+ * kind argument is one of JSTRACE_OBJECT, JSTRACE_DOUBLE, JSTRACE_STRING or
+ * a tag denoting internal implementation-specific traversal kind. In the
+ * latter case the only operations on thing that the callback can do is to call
+ * JS_TraceChildren or DEBUG-only JS_PrintTraceThingInfo.
+ */
+typedef void
+(* JSTraceCallback)(JSTracer *trc, void *thing, uint32 kind);
+
+/*
+ * DEBUG only callback that JSTraceOp implementation can provide to return
+ * a string describing the reference traced with JS_CallTracer.
+ */
+#ifdef DEBUG
+typedef void
+(* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
+#endif
+
+/*
+ * The optional JSClass.reserveSlots hook allows a class to make computed
+ * per-instance object slots reservations, in addition to or instead of using
+ * JSCLASS_HAS_RESERVED_SLOTS(n) in the JSClass.flags initializer to reserve
+ * a constant-per-class number of slots. Implementations of this hook should
+ * return the number of slots to reserve, not including any reserved by using
+ * JSCLASS_HAS_RESERVED_SLOTS(n) in JSClass.flags.
+ *
+ * NB: called with obj locked by the JSObjectOps-specific mutual exclusion
+ * mechanism appropriate for obj, so don't nest other operations that might
+ * also lock obj.
+ */
+typedef uint32
+(* JSReserveSlotsOp)(JSContext *cx, JSObject *obj);
+
+/* JSObjectOps function pointer typedefs. */
+
+/*
+ * Create a new subclass of JSObjectMap (see jsobj.h), with the nrefs and ops
+ * members initialized from the same-named parameters, and with the nslots and
+ * freeslot members initialized according to ops and clasp. Return null on
+ * error, non-null on success.
+ *
+ * JSObjectMaps are reference-counted by generic code in the engine. Usually,
+ * the nrefs parameter to JSObjectOps.newObjectMap will be 1, to count the ref
+ * returned to the caller on success. After a successful construction, some
+ * number of js_HoldObjectMap and js_DropObjectMap calls ensue. When nrefs
+ * reaches 0 due to a js_DropObjectMap call, JSObjectOps.destroyObjectMap will
+ * be called to dispose of the map.
+ */
+typedef JSObjectMap *
+(* JSNewObjectMapOp)(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp, JSObject *obj);
+
+/*
+ * Generic type for an infallible JSObjectMap operation, used currently by
+ * JSObjectOps.destroyObjectMap.
+ */
+typedef void
+(* JSObjectMapOp)(JSContext *cx, JSObjectMap *map);
+
+/*
+ * Look for id in obj and its prototype chain, returning false on error or
+ * exception, true on success. On success, return null in *propp if id was
+ * not found. If id was found, return the first object searching from obj
+ * along its prototype chain in which id names a direct property in *objp, and
+ * return a non-null, opaque property pointer in *propp.
+ *
+ * If JSLookupPropOp succeeds and returns with *propp non-null, that pointer
+ * may be passed as the prop parameter to a JSAttributesOp, as a short-cut
+ * that bypasses id re-lookup. In any case, a non-null *propp result after a
+ * successful lookup must be dropped via JSObjectOps.dropProperty.
+ *
+ * NB: successful return with non-null *propp means the implementation may
+ * have locked *objp and added a reference count associated with *propp, so
+ * callers should not risk deadlock by nesting or interleaving other lookups
+ * or any obj-bearing ops before dropping *propp.
+ */
+typedef JSBool
+(* JSLookupPropOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp);
+
+/*
+ * Define obj[id], a direct property of obj named id, having the given initial
+ * value, with the specified getter, setter, and attributes. If the propp out
+ * param is non-null, *propp on successful return contains an opaque property
+ * pointer usable as a speedup hint with JSAttributesOp. But note that propp
+ * may be null, indicating that the caller is not interested in recovering an
+ * opaque pointer to the newly-defined property.
+ *
+ * If propp is non-null and JSDefinePropOp succeeds, its caller must be sure
+ * to drop *propp using JSObjectOps.dropProperty in short order, just as with
+ * JSLookupPropOp.
+ */
+typedef JSBool
+(* JSDefinePropOp)(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ JSProperty **propp);
+
+/*
+ * Get, set, or delete obj[id], returning false on error or exception, true
+ * on success. If getting or setting, the new value is returned in *vp on
+ * success. If deleting without error, *vp will be JSVAL_FALSE if obj[id] is
+ * permanent, and JSVAL_TRUE if id named a direct property of obj that was in
+ * fact deleted, or if id names no direct property of obj (id could name a
+ * prototype property, or no property in obj or its prototype chain).
+ */
+typedef JSBool
+(* JSPropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+/*
+ * Get or set attributes of the property obj[id]. Return false on error or
+ * exception, true with current attributes in *attrsp. If prop is non-null,
+ * it must come from the *propp out parameter of a prior JSDefinePropOp or
+ * JSLookupPropOp call.
+ */
+typedef JSBool
+(* JSAttributesOp)(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp);
+
+/*
+ * JSObjectOps.checkAccess type: check whether obj[id] may be accessed per
+ * mode, returning false on error/exception, true on success with obj[id]'s
+ * last-got value in *vp, and its attributes in *attrsp.
+ */
+typedef JSBool
+(* JSCheckAccessIdOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp);
+
+/*
+ * A generic type for functions mapping an object to another object, or null
+ * if an error or exception was thrown on cx. Used by JSObjectOps.thisObject
+ * at present.
+ */
+typedef JSObject *
+(* JSObjectOp)(JSContext *cx, JSObject *obj);
+
+/*
+ * Hook that creates an iterator object for a given object. Returns the
+ * iterator object or null if an error or exception was thrown on cx.
+ */
+typedef JSObject *
+(* JSIteratorOp)(JSContext *cx, JSObject *obj, JSBool keysonly);
+
+/*
+ * A generic type for functions taking a context, object, and property, with
+ * no return value. Used by JSObjectOps.dropProperty currently (see above,
+ * JSDefinePropOp and JSLookupPropOp, for the object-locking protocol in which
+ * dropProperty participates).
+ */
+typedef void
+(* JSPropertyRefOp)(JSContext *cx, JSObject *obj, JSProperty *prop);
+
+/*
+ * Function pointer type for JSObjectOps.setProto and JSObjectOps.setParent.
+ * These hooks must check for cycles without deadlocking, and otherwise take
+ * special steps. See jsobj.c and jsgc.c for details.
+ */
+typedef JSBool
+(* JSSetObjectSlotOp)(JSContext *cx, JSObject *obj, uint32 slot,
+ JSObject *pobj);
+
+/*
+ * Get and set a required slot, one that should already have been allocated.
+ * These operations are infallible, so required slots must be pre-allocated,
+ * or implementations must suppress out-of-memory errors. The native ops
+ * (js_ObjectOps, see jsobj.c) access slots reserved by including a call to
+ * the JSCLASS_HAS_RESERVED_SLOTS(n) macro in the JSClass.flags initializer.
+ *
+ * NB: the slot parameter is a zero-based index into obj slots, unlike the
+ * index parameter to the JS_GetReservedSlot and JS_SetReservedSlot API entry
+ * points, which is a zero-based index into the JSCLASS_RESERVED_SLOTS(clasp)
+ * reserved slots that come after the initial well-known slots: proto, parent,
+ * class, and optionally, the private data slot.
+ */
+typedef jsval
+(* JSGetRequiredSlotOp)(JSContext *cx, JSObject *obj, uint32 slot);
+
+typedef JSBool
+(* JSSetRequiredSlotOp)(JSContext *cx, JSObject *obj, uint32 slot, jsval v);
+
+typedef JSObject *
+(* JSGetMethodOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+typedef JSBool
+(* JSSetMethodOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+typedef JSBool
+(* JSEnumerateValuesOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp, jsval *vp);
+
+typedef JSBool
+(* JSEqualityOp)(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+typedef JSBool
+(* JSConcatenateOp)(JSContext *cx, JSObject *obj, jsval v, jsval *vp);
+
+/* Typedef for native functions called by the JS VM. */
+
+typedef JSBool
+(* JSNative)(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+/* See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros. */
+typedef JSBool
+(* JSFastNative)(JSContext *cx, uintN argc, jsval *vp);
+
+/* Callbacks and their arguments. */
+
+typedef enum JSContextOp {
+ JSCONTEXT_NEW,
+ JSCONTEXT_DESTROY
+} JSContextOp;
+
+/*
+ * The possible values for contextOp when the runtime calls the callback are:
+ * JSCONTEXT_NEW JS_NewContext successfully created a new JSContext
+ * instance. The callback can initialize the instance as
+ * required. If the callback returns false, the instance
+ * will be destroyed and JS_NewContext returns null. In
+ * this case the callback is not called again.
+ * JSCONTEXT_DESTROY One of JS_DestroyContext* methods is called. The
+ * callback may perform its own cleanup and must always
+ * return true.
+ * Any other value For future compatibility the callback must do nothing
+ * and return true in this case.
+ */
+typedef JSBool
+(* JSContextCallback)(JSContext *cx, uintN contextOp);
+
+typedef enum JSGCStatus {
+ JSGC_BEGIN,
+ JSGC_END,
+ JSGC_MARK_END,
+ JSGC_FINALIZE_END
+} JSGCStatus;
+
+typedef JSBool
+(* JSGCCallback)(JSContext *cx, JSGCStatus status);
+
+/*
+ * Generic trace operation that calls JS_CallTracer on each traceable thing
+ * stored in data.
+ */
+typedef void
+(* JSTraceDataOp)(JSTracer *trc, void *data);
+
+typedef JSBool
+(* JSOperationCallback)(JSContext *cx);
+
+/*
+ * Deprecated form of JSOperationCallback.
+ */
+typedef JSBool
+(* JSBranchCallback)(JSContext *cx, JSScript *script);
+
+typedef void
+(* JSErrorReporter)(JSContext *cx, const char *message, JSErrorReport *report);
+
+/*
+ * Possible exception types. These types are part of a JSErrorFormatString
+ * structure. They define which error to throw in case of a runtime error.
+ * JSEXN_NONE marks an unthrowable error.
+ */
+typedef enum JSExnType {
+ JSEXN_NONE = -1,
+ JSEXN_ERR,
+ JSEXN_INTERNALERR,
+ JSEXN_EVALERR,
+ JSEXN_RANGEERR,
+ JSEXN_REFERENCEERR,
+ JSEXN_SYNTAXERR,
+ JSEXN_TYPEERR,
+ JSEXN_URIERR,
+ JSEXN_LIMIT
+} JSExnType;
+
+typedef struct JSErrorFormatString {
+ /* The error format string (UTF-8 if js_CStringsAreUTF8). */
+ const char *format;
+
+ /* The number of arguments to expand in the formatted error message. */
+ uint16 argCount;
+
+ /* One of the JSExnType constants above. */
+ int16 exnType;
+} JSErrorFormatString;
+
+typedef const JSErrorFormatString *
+(* JSErrorCallback)(void *userRef, const char *locale,
+ const uintN errorNumber);
+
+#ifdef va_start
+#define JS_ARGUMENT_FORMATTER_DEFINED 1
+
+typedef JSBool
+(* JSArgumentFormatter)(JSContext *cx, const char *format, JSBool fromJS,
+ jsval **vpp, va_list *app);
+#endif
+
+typedef JSBool
+(* JSLocaleToUpperCase)(JSContext *cx, JSString *src, jsval *rval);
+
+typedef JSBool
+(* JSLocaleToLowerCase)(JSContext *cx, JSString *src, jsval *rval);
+
+typedef JSBool
+(* JSLocaleCompare)(JSContext *cx, JSString *src1, JSString *src2,
+ jsval *rval);
+
+typedef JSBool
+(* JSLocaleToUnicode)(JSContext *cx, char *src, jsval *rval);
+
+/*
+ * Security protocol types.
+ */
+typedef struct JSPrincipals JSPrincipals;
+
+/*
+ * XDR-encode or -decode a principals instance, based on whether xdr->mode is
+ * JSXDR_ENCODE, in which case *principalsp should be encoded; or JSXDR_DECODE,
+ * in which case implementations must return a held (via JSPRINCIPALS_HOLD),
+ * non-null *principalsp out parameter. Return true on success, false on any
+ * error, which the implementation must have reported.
+ */
+typedef JSBool
+(* JSPrincipalsTranscoder)(JSXDRState *xdr, JSPrincipals **principalsp);
+
+/*
+ * Return a weak reference to the principals associated with obj, possibly via
+ * the immutable parent chain leading from obj to a top-level container (e.g.,
+ * a window object in the DOM level 0). If there are no principals associated
+ * with obj, return null. Therefore null does not mean an error was reported;
+ * in no event should an error be reported or an exception be thrown by this
+ * callback's implementation.
+ */
+typedef JSPrincipals *
+(* JSObjectPrincipalsFinder)(JSContext *cx, JSObject *obj);
+
+JS_END_EXTERN_C
+
+#endif /* jspubtd_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.cpp
new file mode 100644
index 0000000..778f342
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.cpp
@@ -0,0 +1,4772 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS regular expressions, after Perl.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsregexp.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsstr.h"
+
+#ifdef JS_TRACER
+#include "jstracer.h"
+using namespace avmplus;
+using namespace nanojit;
+
+/*
+ * FIXME Duplicated with jstracer.cpp, doing it this way for now
+ * to keep it private to files that need it.
+ */
+#ifdef JS_JIT_SPEW
+static bool verbose_debug = getenv("TRACEMONKEY") && strstr(getenv("TRACEMONKEY"), "verbose");
+#define debug_only_v(x) if (verbose_debug) { x; }
+#else
+#define debug_only_v(x)
+#endif
+#endif
+
+typedef enum REOp {
+#define REOP_DEF(opcode, name) opcode,
+#include "jsreops.tbl"
+#undef REOP_DEF
+ REOP_LIMIT /* META: no operator >= to this */
+} REOp;
+
+#define REOP_IS_SIMPLE(op) ((op) <= REOP_NCLASS)
+
+#ifdef REGEXP_DEBUG
+const char *reop_names[] = {
+#define REOP_DEF(opcode, name) name,
+#include "jsreops.tbl"
+#undef REOP_DEF
+ NULL
+};
+#endif
+
+#ifdef __GNUC__
+static int
+re_debug(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
+#endif
+
+#ifdef REGEXP_DEBUG
+static int
+re_debug(const char *fmt, ...)
+{
+ va_list ap;
+ int retval;
+
+ va_start(ap, fmt);
+ retval = vprintf(fmt, ap);
+ va_end(ap);
+ return retval;
+}
+
+static void
+re_debug_chars(const jschar *chrs, size_t length)
+{
+ int i = 0;
+
+ printf(" \"");
+ while (*chrs && i++ < length) {
+ putchar((char)*chrs++);
+ }
+ printf("\"");
+}
+#else /* !REGEXP_DEBUG */
+/* This should be optimized to a no-op by our tier-1 compilers. */
+static int
+re_debug(const char *fmt, ...)
+{
+ return 0;
+}
+
+static void
+re_debug_chars(const jschar *chrs, size_t length)
+{
+}
+#endif /* !REGEXP_DEBUG */
+
+struct RENode {
+ REOp op; /* r.e. op bytecode */
+ RENode *next; /* next in concatenation order */
+ void *kid; /* first operand */
+ union {
+ void *kid2; /* second operand */
+ jsint num; /* could be a number */
+ size_t parenIndex; /* or a parenthesis index */
+ struct { /* or a quantifier range */
+ uintN min;
+ uintN max;
+ JSPackedBool greedy;
+ } range;
+ struct { /* or a character class */
+ size_t startIndex;
+ size_t kidlen; /* length of string at kid, in jschars */
+ size_t index; /* index into class list */
+ uint16 bmsize; /* bitmap size, based on max char code */
+ JSPackedBool sense;
+ } ucclass;
+ struct { /* or a literal sequence */
+ jschar chr; /* of one character */
+ size_t length; /* or many (via the kid) */
+ } flat;
+ struct {
+ RENode *kid2; /* second operand from ALT */
+ jschar ch1; /* match char for ALTPREREQ */
+ jschar ch2; /* ditto, or class index for ALTPREREQ2 */
+ } altprereq;
+ } u;
+};
+
+#define RE_IS_LETTER(c) (((c >= 'A') && (c <= 'Z')) || \
+ ((c >= 'a') && (c <= 'z')) )
+#define RE_IS_LINE_TERM(c) ((c == '\n') || (c == '\r') || \
+ (c == LINE_SEPARATOR) || (c == PARA_SEPARATOR))
+
+#define CLASS_CACHE_SIZE 4
+
+typedef struct CompilerState {
+ JSContext *context;
+ JSTokenStream *tokenStream; /* For reporting errors */
+ const jschar *cpbegin;
+ const jschar *cpend;
+ const jschar *cp;
+ size_t parenCount;
+ size_t classCount; /* number of [] encountered */
+ size_t treeDepth; /* maximum depth of parse tree */
+ size_t progLength; /* estimated bytecode length */
+ RENode *result;
+ size_t classBitmapsMem; /* memory to hold all class bitmaps */
+ struct {
+ const jschar *start; /* small cache of class strings */
+ size_t length; /* since they're often the same */
+ size_t index;
+ } classCache[CLASS_CACHE_SIZE];
+ uint16 flags;
+} CompilerState;
+
+typedef struct EmitStateStackEntry {
+ jsbytecode *altHead; /* start of REOP_ALT* opcode */
+ jsbytecode *nextAltFixup; /* fixup pointer to next-alt offset */
+ jsbytecode *nextTermFixup; /* fixup ptr. to REOP_JUMP offset */
+ jsbytecode *endTermFixup; /* fixup ptr. to REOPT_ALTPREREQ* offset */
+ RENode *continueNode; /* original REOP_ALT* node being stacked */
+ jsbytecode continueOp; /* REOP_JUMP or REOP_ENDALT continuation */
+ JSPackedBool jumpToJumpFlag; /* true if we've patched jump-to-jump to
+ avoid 16-bit unsigned offset overflow */
+} EmitStateStackEntry;
+
+/*
+ * Immediate operand sizes and getter/setters. Unlike the ones in jsopcode.h,
+ * the getters and setters take the pc of the offset, not of the opcode before
+ * the offset.
+ */
+#define ARG_LEN 2
+#define GET_ARG(pc) ((uint16)(((pc)[0] << 8) | (pc)[1]))
+#define SET_ARG(pc, arg) ((pc)[0] = (jsbytecode) ((arg) >> 8), \
+ (pc)[1] = (jsbytecode) (arg))
+
+#define OFFSET_LEN ARG_LEN
+#define OFFSET_MAX (JS_BIT(ARG_LEN * 8) - 1)
+#define GET_OFFSET(pc) GET_ARG(pc)
+
+/*
+ * Maximum supported tree depth is maximum size of EmitStateStackEntry stack.
+ * For sanity, we limit it to 2^24 bytes.
+ */
+#define TREE_DEPTH_MAX (JS_BIT(24) / sizeof(EmitStateStackEntry))
+
+/*
+ * The maximum memory that can be allocated for class bitmaps.
+ * For sanity, we limit it to 2^24 bytes.
+ */
+#define CLASS_BITMAPS_MEM_LIMIT JS_BIT(24)
+
+/*
+ * Functions to get size and write/read bytecode that represent small indexes
+ * compactly.
+ * Each byte in the code represent 7-bit chunk of the index. 8th bit when set
+ * indicates that the following byte brings more bits to the index. Otherwise
+ * this is the last byte in the index bytecode representing highest index bits.
+ */
+static size_t
+GetCompactIndexWidth(size_t index)
+{
+ size_t width;
+
+ for (width = 1; (index >>= 7) != 0; ++width) { }
+ return width;
+}
+
+static JS_ALWAYS_INLINE jsbytecode *
+WriteCompactIndex(jsbytecode *pc, size_t index)
+{
+ size_t next;
+
+ while ((next = index >> 7) != 0) {
+ *pc++ = (jsbytecode)(index | 0x80);
+ index = next;
+ }
+ *pc++ = (jsbytecode)index;
+ return pc;
+}
+
+static JS_ALWAYS_INLINE jsbytecode *
+ReadCompactIndex(jsbytecode *pc, size_t *result)
+{
+ size_t nextByte;
+
+ nextByte = *pc++;
+ if ((nextByte & 0x80) == 0) {
+ /*
+ * Short-circuit the most common case when compact index <= 127.
+ */
+ *result = nextByte;
+ } else {
+ size_t shift = 7;
+ *result = 0x7F & nextByte;
+ do {
+ nextByte = *pc++;
+ *result |= (nextByte & 0x7F) << shift;
+ shift += 7;
+ } while ((nextByte & 0x80) != 0);
+ }
+ return pc;
+}
+
+typedef struct RECapture {
+ ptrdiff_t index; /* start of contents, -1 for empty */
+ size_t length; /* length of capture */
+} RECapture;
+
+typedef struct REMatchState {
+ const jschar *cp;
+ RECapture parens[1]; /* first of 're->parenCount' captures,
+ allocated at end of this struct */
+} REMatchState;
+
+struct REBackTrackData;
+
+typedef struct REProgState {
+ jsbytecode *continue_pc; /* current continuation data */
+ jsbytecode continue_op;
+ ptrdiff_t index; /* progress in text */
+ size_t parenSoFar; /* highest indexed paren started */
+ union {
+ struct {
+ uintN min; /* current quantifier limits */
+ uintN max;
+ } quantifier;
+ struct {
+ size_t top; /* backtrack stack state */
+ size_t sz;
+ } assertion;
+ } u;
+} REProgState;
+
+typedef struct REBackTrackData {
+ size_t sz; /* size of previous stack entry */
+ jsbytecode *backtrack_pc; /* where to backtrack to */
+ jsbytecode backtrack_op;
+ const jschar *cp; /* index in text of match at backtrack */
+ size_t parenIndex; /* start index of saved paren contents */
+ size_t parenCount; /* # of saved paren contents */
+ size_t saveStateStackTop; /* number of parent states */
+ /* saved parent states follow */
+ /* saved paren contents follow */
+} REBackTrackData;
+
+#define INITIAL_STATESTACK 100
+#define INITIAL_BACKTRACK 8000
+
+typedef struct REGlobalData {
+ JSContext *cx;
+ JSRegExp *regexp; /* the RE in execution */
+ JSBool ok; /* runtime error (out_of_memory only?) */
+ size_t start; /* offset to start at */
+ ptrdiff_t skipped; /* chars skipped anchoring this r.e. */
+ const jschar *cpbegin; /* text base address */
+ const jschar *cpend; /* text limit address */
+
+ REProgState *stateStack; /* stack of state of current parents */
+ size_t stateStackTop;
+ size_t stateStackLimit;
+
+ REBackTrackData *backTrackStack;/* stack of matched-so-far positions */
+ REBackTrackData *backTrackSP;
+ size_t backTrackStackSize;
+ size_t cursz; /* size of current stack entry */
+ size_t backTrackCount; /* how many times we've backtracked */
+ size_t backTrackLimit; /* upper limit on backtrack states */
+} REGlobalData;
+
+/*
+ * 1. If IgnoreCase is false, return ch.
+ * 2. Let u be ch converted to upper case as if by calling
+ * String.prototype.toUpperCase on the one-character string ch.
+ * 3. If u does not consist of a single character, return ch.
+ * 4. Let cu be u's character.
+ * 5. If ch's code point value is greater than or equal to decimal 128 and cu's
+ * code point value is less than decimal 128, then return ch.
+ * 6. Return cu.
+ */
+static JS_ALWAYS_INLINE uintN
+upcase(uintN ch)
+{
+ uintN cu;
+
+ JS_ASSERT((uintN) (jschar) ch == ch);
+ if (ch < 128) {
+ if (ch - (uintN) 'a' <= (uintN) ('z' - 'a'))
+ ch -= (uintN) ('a' - 'A');
+ return ch;
+ }
+
+ cu = JS_TOUPPER(ch);
+ return (cu < 128) ? ch : cu;
+}
+
+static JS_ALWAYS_INLINE uintN
+downcase(uintN ch)
+{
+ JS_ASSERT((uintN) (jschar) ch == ch);
+ if (ch < 128) {
+ if (ch - (uintN) 'A' <= (uintN) ('Z' - 'A'))
+ ch += (uintN) ('a' - 'A');
+ return ch;
+ }
+
+ return JS_TOLOWER(ch);
+}
+
+/* Construct and initialize an RENode, returning NULL for out-of-memory */
+static RENode *
+NewRENode(CompilerState *state, REOp op)
+{
+ JSContext *cx;
+ RENode *ren;
+
+ cx = state->context;
+ JS_ARENA_ALLOCATE_CAST(ren, RENode *, &cx->tempPool, sizeof *ren);
+ if (!ren) {
+ js_ReportOutOfScriptQuota(cx);
+ return NULL;
+ }
+ ren->op = op;
+ ren->next = NULL;
+ ren->kid = NULL;
+ return ren;
+}
+
+/*
+ * Validates and converts hex ascii value.
+ */
+static JSBool
+isASCIIHexDigit(jschar c, uintN *digit)
+{
+ uintN cv = c;
+
+ if (cv < '0')
+ return JS_FALSE;
+ if (cv <= '9') {
+ *digit = cv - '0';
+ return JS_TRUE;
+ }
+ cv |= 0x20;
+ if (cv >= 'a' && cv <= 'f') {
+ *digit = cv - 'a' + 10;
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+
+typedef struct {
+ REOp op;
+ const jschar *errPos;
+ size_t parenIndex;
+} REOpData;
+
+static JSBool
+ReportRegExpErrorHelper(CompilerState *state, uintN flags, uintN errorNumber,
+ const jschar *arg)
+{
+ if (state->tokenStream) {
+ return js_ReportCompileErrorNumber(state->context, state->tokenStream,
+ NULL, JSREPORT_UC | flags,
+ errorNumber, arg);
+ }
+ return JS_ReportErrorFlagsAndNumberUC(state->context, flags,
+ js_GetErrorMessage, NULL,
+ errorNumber, arg);
+}
+
+static JSBool
+ReportRegExpError(CompilerState *state, uintN flags, uintN errorNumber)
+{
+ return ReportRegExpErrorHelper(state, flags, errorNumber, NULL);
+}
+
+/*
+ * Process the op against the two top operands, reducing them to a single
+ * operand in the penultimate slot. Update progLength and treeDepth.
+ */
+static JSBool
+ProcessOp(CompilerState *state, REOpData *opData, RENode **operandStack,
+ intN operandSP)
+{
+ RENode *result;
+
+ switch (opData->op) {
+ case REOP_ALT:
+ result = NewRENode(state, REOP_ALT);
+ if (!result)
+ return JS_FALSE;
+ result->kid = operandStack[operandSP - 2];
+ result->u.kid2 = operandStack[operandSP - 1];
+ operandStack[operandSP - 2] = result;
+
+ if (state->treeDepth == TREE_DEPTH_MAX) {
+ ReportRegExpError(state, JSREPORT_ERROR, JSMSG_REGEXP_TOO_COMPLEX);
+ return JS_FALSE;
+ }
+ ++state->treeDepth;
+
+ /*
+ * Look at both alternates to see if there's a FLAT or a CLASS at
+ * the start of each. If so, use a prerequisite match.
+ */
+ if (((RENode *) result->kid)->op == REOP_FLAT &&
+ ((RENode *) result->u.kid2)->op == REOP_FLAT &&
+ (state->flags & JSREG_FOLD) == 0) {
+ result->op = REOP_ALTPREREQ;
+ result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr;
+ result->u.altprereq.ch2 = ((RENode *) result->u.kid2)->u.flat.chr;
+ /* ALTPREREQ, <end>, uch1, uch2, <next>, ...,
+ JUMP, <end> ... ENDALT */
+ state->progLength += 13;
+ }
+ else
+ if (((RENode *) result->kid)->op == REOP_CLASS &&
+ ((RENode *) result->kid)->u.ucclass.index < 256 &&
+ ((RENode *) result->u.kid2)->op == REOP_FLAT &&
+ (state->flags & JSREG_FOLD) == 0) {
+ result->op = REOP_ALTPREREQ2;
+ result->u.altprereq.ch1 = ((RENode *) result->u.kid2)->u.flat.chr;
+ result->u.altprereq.ch2 = ((RENode *) result->kid)->u.ucclass.index;
+ /* ALTPREREQ2, <end>, uch1, uch2, <next>, ...,
+ JUMP, <end> ... ENDALT */
+ state->progLength += 13;
+ }
+ else
+ if (((RENode *) result->kid)->op == REOP_FLAT &&
+ ((RENode *) result->u.kid2)->op == REOP_CLASS &&
+ ((RENode *) result->u.kid2)->u.ucclass.index < 256 &&
+ (state->flags & JSREG_FOLD) == 0) {
+ result->op = REOP_ALTPREREQ2;
+ result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr;
+ result->u.altprereq.ch2 =
+ ((RENode *) result->u.kid2)->u.ucclass.index;
+ /* ALTPREREQ2, <end>, uch1, uch2, <next>, ...,
+ JUMP, <end> ... ENDALT */
+ state->progLength += 13;
+ }
+ else {
+ /* ALT, <next>, ..., JUMP, <end> ... ENDALT */
+ state->progLength += 7;
+ }
+ break;
+
+ case REOP_CONCAT:
+ result = operandStack[operandSP - 2];
+ while (result->next)
+ result = result->next;
+ result->next = operandStack[operandSP - 1];
+ break;
+
+ case REOP_ASSERT:
+ case REOP_ASSERT_NOT:
+ case REOP_LPARENNON:
+ case REOP_LPAREN:
+ /* These should have been processed by a close paren. */
+ ReportRegExpErrorHelper(state, JSREPORT_ERROR, JSMSG_MISSING_PAREN,
+ opData->errPos);
+ return JS_FALSE;
+
+ default:;
+ }
+ return JS_TRUE;
+}
+
+/*
+ * Parser forward declarations.
+ */
+static JSBool ParseTerm(CompilerState *state);
+static JSBool ParseQuantifier(CompilerState *state);
+static intN ParseMinMaxQuantifier(CompilerState *state, JSBool ignoreValues);
+
+/*
+ * Top-down regular expression grammar, based closely on Perl4.
+ *
+ * regexp: altern A regular expression is one or more
+ * altern '|' regexp alternatives separated by vertical bar.
+ */
+#define INITIAL_STACK_SIZE 128
+
+static JSBool
+ParseRegExp(CompilerState *state)
+{
+ size_t parenIndex;
+ RENode *operand;
+ REOpData *operatorStack;
+ RENode **operandStack;
+ REOp op;
+ intN i;
+ JSBool result = JS_FALSE;
+
+ intN operatorSP = 0, operatorStackSize = INITIAL_STACK_SIZE;
+ intN operandSP = 0, operandStackSize = INITIAL_STACK_SIZE;
+
+ /* Watch out for empty regexp */
+ if (state->cp == state->cpend) {
+ state->result = NewRENode(state, REOP_EMPTY);
+ return (state->result != NULL);
+ }
+
+ operatorStack = (REOpData *)
+ JS_malloc(state->context, sizeof(REOpData) * operatorStackSize);
+ if (!operatorStack)
+ return JS_FALSE;
+
+ operandStack = (RENode **)
+ JS_malloc(state->context, sizeof(RENode *) * operandStackSize);
+ if (!operandStack)
+ goto out;
+
+ for (;;) {
+ parenIndex = state->parenCount;
+ if (state->cp == state->cpend) {
+ /*
+ * If we are at the end of the regexp and we're short one or more
+ * operands, the regexp must have the form /x|/ or some such, with
+ * left parentheses making us short more than one operand.
+ */
+ if (operatorSP >= operandSP) {
+ operand = NewRENode(state, REOP_EMPTY);
+ if (!operand)
+ goto out;
+ goto pushOperand;
+ }
+ } else {
+ switch (*state->cp) {
+ case '(':
+ ++state->cp;
+ if (state->cp + 1 < state->cpend &&
+ *state->cp == '?' &&
+ (state->cp[1] == '=' ||
+ state->cp[1] == '!' ||
+ state->cp[1] == ':')) {
+ switch (state->cp[1]) {
+ case '=':
+ op = REOP_ASSERT;
+ /* ASSERT, <next>, ... ASSERTTEST */
+ state->progLength += 4;
+ break;
+ case '!':
+ op = REOP_ASSERT_NOT;
+ /* ASSERTNOT, <next>, ... ASSERTNOTTEST */
+ state->progLength += 4;
+ break;
+ default:
+ op = REOP_LPARENNON;
+ break;
+ }
+ state->cp += 2;
+ } else {
+ op = REOP_LPAREN;
+ /* LPAREN, <index>, ... RPAREN, <index> */
+ state->progLength
+ += 2 * (1 + GetCompactIndexWidth(parenIndex));
+ state->parenCount++;
+ if (state->parenCount == 65535) {
+ ReportRegExpError(state, JSREPORT_ERROR,
+ JSMSG_TOO_MANY_PARENS);
+ goto out;
+ }
+ }
+ goto pushOperator;
+
+ case ')':
+ /*
+ * If there's no stacked open parenthesis, throw syntax error.
+ */
+ for (i = operatorSP - 1; ; i--) {
+ if (i < 0) {
+ ReportRegExpError(state, JSREPORT_ERROR,
+ JSMSG_UNMATCHED_RIGHT_PAREN);
+ goto out;
+ }
+ if (operatorStack[i].op == REOP_ASSERT ||
+ operatorStack[i].op == REOP_ASSERT_NOT ||
+ operatorStack[i].op == REOP_LPARENNON ||
+ operatorStack[i].op == REOP_LPAREN) {
+ break;
+ }
+ }
+ /* FALL THROUGH */
+
+ case '|':
+ /* Expected an operand before these, so make an empty one */
+ operand = NewRENode(state, REOP_EMPTY);
+ if (!operand)
+ goto out;
+ goto pushOperand;
+
+ default:
+ if (!ParseTerm(state))
+ goto out;
+ operand = state->result;
+pushOperand:
+ if (operandSP == operandStackSize) {
+ RENode **tmp;
+ operandStackSize += operandStackSize;
+ tmp = (RENode **)
+ JS_realloc(state->context, operandStack,
+ sizeof(RENode *) * operandStackSize);
+ if (!tmp)
+ goto out;
+ operandStack = tmp;
+ }
+ operandStack[operandSP++] = operand;
+ break;
+ }
+ }
+
+ /* At the end; process remaining operators. */
+restartOperator:
+ if (state->cp == state->cpend) {
+ while (operatorSP) {
+ --operatorSP;
+ if (!ProcessOp(state, &operatorStack[operatorSP],
+ operandStack, operandSP))
+ goto out;
+ --operandSP;
+ }
+ JS_ASSERT(operandSP == 1);
+ state->result = operandStack[0];
+ result = JS_TRUE;
+ goto out;
+ }
+
+ switch (*state->cp) {
+ case '|':
+ /* Process any stacked 'concat' operators */
+ ++state->cp;
+ while (operatorSP &&
+ operatorStack[operatorSP - 1].op == REOP_CONCAT) {
+ --operatorSP;
+ if (!ProcessOp(state, &operatorStack[operatorSP],
+ operandStack, operandSP)) {
+ goto out;
+ }
+ --operandSP;
+ }
+ op = REOP_ALT;
+ goto pushOperator;
+
+ case ')':
+ /*
+ * If there's no stacked open parenthesis, throw syntax error.
+ */
+ for (i = operatorSP - 1; ; i--) {
+ if (i < 0) {
+ ReportRegExpError(state, JSREPORT_ERROR,
+ JSMSG_UNMATCHED_RIGHT_PAREN);
+ goto out;
+ }
+ if (operatorStack[i].op == REOP_ASSERT ||
+ operatorStack[i].op == REOP_ASSERT_NOT ||
+ operatorStack[i].op == REOP_LPARENNON ||
+ operatorStack[i].op == REOP_LPAREN) {
+ break;
+ }
+ }
+ ++state->cp;
+
+ /* Process everything on the stack until the open parenthesis. */
+ for (;;) {
+ JS_ASSERT(operatorSP);
+ --operatorSP;
+ switch (operatorStack[operatorSP].op) {
+ case REOP_ASSERT:
+ case REOP_ASSERT_NOT:
+ case REOP_LPAREN:
+ operand = NewRENode(state, operatorStack[operatorSP].op);
+ if (!operand)
+ goto out;
+ operand->u.parenIndex =
+ operatorStack[operatorSP].parenIndex;
+ JS_ASSERT(operandSP);
+ operand->kid = operandStack[operandSP - 1];
+ operandStack[operandSP - 1] = operand;
+ if (state->treeDepth == TREE_DEPTH_MAX) {
+ ReportRegExpError(state, JSREPORT_ERROR,
+ JSMSG_REGEXP_TOO_COMPLEX);
+ goto out;
+ }
+ ++state->treeDepth;
+ /* FALL THROUGH */
+
+ case REOP_LPARENNON:
+ state->result = operandStack[operandSP - 1];
+ if (!ParseQuantifier(state))
+ goto out;
+ operandStack[operandSP - 1] = state->result;
+ goto restartOperator;
+ default:
+ if (!ProcessOp(state, &operatorStack[operatorSP],
+ operandStack, operandSP))
+ goto out;
+ --operandSP;
+ break;
+ }
+ }
+ break;
+
+ case '{':
+ {
+ const jschar *errp = state->cp;
+
+ if (ParseMinMaxQuantifier(state, JS_TRUE) < 0) {
+ /*
+ * This didn't even scan correctly as a quantifier, so we should
+ * treat it as flat.
+ */
+ op = REOP_CONCAT;
+ goto pushOperator;
+ }
+
+ state->cp = errp;
+ /* FALL THROUGH */
+ }
+
+ case '+':
+ case '*':
+ case '?':
+ ReportRegExpErrorHelper(state, JSREPORT_ERROR, JSMSG_BAD_QUANTIFIER,
+ state->cp);
+ result = JS_FALSE;
+ goto out;
+
+ default:
+ /* Anything else is the start of the next term. */
+ op = REOP_CONCAT;
+pushOperator:
+ if (operatorSP == operatorStackSize) {
+ REOpData *tmp;
+ operatorStackSize += operatorStackSize;
+ tmp = (REOpData *)
+ JS_realloc(state->context, operatorStack,
+ sizeof(REOpData) * operatorStackSize);
+ if (!tmp)
+ goto out;
+ operatorStack = tmp;
+ }
+ operatorStack[operatorSP].op = op;
+ operatorStack[operatorSP].errPos = state->cp;
+ operatorStack[operatorSP++].parenIndex = parenIndex;
+ break;
+ }
+ }
+out:
+ if (operatorStack)
+ JS_free(state->context, operatorStack);
+ if (operandStack)
+ JS_free(state->context, operandStack);
+ return result;
+}
+
+/*
+ * Hack two bits in CompilerState.flags, for use within FindParenCount to flag
+ * its being on the stack, and to propagate errors to its callers.
+ */
+#define JSREG_FIND_PAREN_COUNT 0x8000
+#define JSREG_FIND_PAREN_ERROR 0x4000
+
+/*
+ * Magic return value from FindParenCount and GetDecimalValue, to indicate
+ * overflow beyond GetDecimalValue's max parameter, or a computed maximum if
+ * its findMax parameter is non-null.
+ */
+#define OVERFLOW_VALUE ((uintN)-1)
+
+static uintN
+FindParenCount(CompilerState *state)
+{
+ CompilerState temp;
+ int i;
+
+ if (state->flags & JSREG_FIND_PAREN_COUNT)
+ return OVERFLOW_VALUE;
+
+ /*
+ * Copy state into temp, flag it so we never report an invalid backref,
+ * and reset its members to parse the entire regexp. This is obviously
+ * suboptimal, but GetDecimalValue calls us only if a backref appears to
+ * refer to a forward parenthetical, which is rare.
+ */
+ temp = *state;
+ temp.flags |= JSREG_FIND_PAREN_COUNT;
+ temp.cp = temp.cpbegin;
+ temp.parenCount = 0;
+ temp.classCount = 0;
+ temp.progLength = 0;
+ temp.treeDepth = 0;
+ temp.classBitmapsMem = 0;
+ for (i = 0; i < CLASS_CACHE_SIZE; i++)
+ temp.classCache[i].start = NULL;
+
+ if (!ParseRegExp(&temp)) {
+ state->flags |= JSREG_FIND_PAREN_ERROR;
+ return OVERFLOW_VALUE;
+ }
+ return temp.parenCount;
+}
+
+/*
+ * Extract and return a decimal value at state->cp. The initial character c
+ * has already been read. Return OVERFLOW_VALUE if the result exceeds max.
+ * Callers who pass a non-null findMax should test JSREG_FIND_PAREN_ERROR in
+ * state->flags to discover whether an error occurred under findMax.
+ */
+static uintN
+GetDecimalValue(jschar c, uintN max, uintN (*findMax)(CompilerState *state),
+ CompilerState *state)
+{
+ uintN value = JS7_UNDEC(c);
+ JSBool overflow = (value > max && (!findMax || value > findMax(state)));
+
+ /* The following restriction allows simpler overflow checks. */
+ JS_ASSERT(max <= ((uintN)-1 - 9) / 10);
+ while (state->cp < state->cpend) {
+ c = *state->cp;
+ if (!JS7_ISDEC(c))
+ break;
+ value = 10 * value + JS7_UNDEC(c);
+ if (!overflow && value > max && (!findMax || value > findMax(state)))
+ overflow = JS_TRUE;
+ ++state->cp;
+ }
+ return overflow ? OVERFLOW_VALUE : value;
+}
+
+/*
+ * Calculate the total size of the bitmap required for a class expression.
+ */
+static JSBool
+CalculateBitmapSize(CompilerState *state, RENode *target, const jschar *src,
+ const jschar *end)
+{
+ uintN max = 0;
+ JSBool inRange = JS_FALSE;
+ jschar c, rangeStart = 0;
+ uintN n, digit, nDigits, i;
+
+ target->u.ucclass.bmsize = 0;
+ target->u.ucclass.sense = JS_TRUE;
+
+ if (src == end)
+ return JS_TRUE;
+
+ if (*src == '^') {
+ ++src;
+ target->u.ucclass.sense = JS_FALSE;
+ }
+
+ while (src != end) {
+ JSBool canStartRange = JS_TRUE;
+ uintN localMax = 0;
+
+ switch (*src) {
+ case '\\':
+ ++src;
+ c = *src++;
+ switch (c) {
+ case 'b':
+ localMax = 0x8;
+ break;
+ case 'f':
+ localMax = 0xC;
+ break;
+ case 'n':
+ localMax = 0xA;
+ break;
+ case 'r':
+ localMax = 0xD;
+ break;
+ case 't':
+ localMax = 0x9;
+ break;
+ case 'v':
+ localMax = 0xB;
+ break;
+ case 'c':
+ if (src < end && RE_IS_LETTER(*src)) {
+ localMax = (uintN) (*src++) & 0x1F;
+ } else {
+ --src;
+ localMax = '\\';
+ }
+ break;
+ case 'x':
+ nDigits = 2;
+ goto lexHex;
+ case 'u':
+ nDigits = 4;
+lexHex:
+ n = 0;
+ for (i = 0; (i < nDigits) && (src < end); i++) {
+ c = *src++;
+ if (!isASCIIHexDigit(c, &digit)) {
+ /*
+ * Back off to accepting the original
+ *'\' as a literal.
+ */
+ src -= i + 1;
+ n = '\\';
+ break;
+ }
+ n = (n << 4) | digit;
+ }
+ localMax = n;
+ break;
+ case 'd':
+ canStartRange = JS_FALSE;
+ if (inRange) {
+ JS_ReportErrorNumber(state->context,
+ js_GetErrorMessage, NULL,
+ JSMSG_BAD_CLASS_RANGE);
+ return JS_FALSE;
+ }
+ localMax = '9';
+ break;
+ case 'D':
+ case 's':
+ case 'S':
+ case 'w':
+ case 'W':
+ canStartRange = JS_FALSE;
+ if (inRange) {
+ JS_ReportErrorNumber(state->context,
+ js_GetErrorMessage, NULL,
+ JSMSG_BAD_CLASS_RANGE);
+ return JS_FALSE;
+ }
+ max = 65535;
+
+ /*
+ * If this is the start of a range, ensure that it's less than
+ * the end.
+ */
+ localMax = 0;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ /*
+ * This is a non-ECMA extension - decimal escapes (in this
+ * case, octal!) are supposed to be an error inside class
+ * ranges, but supported here for backwards compatibility.
+ *
+ */
+ n = JS7_UNDEC(c);
+ c = *src;
+ if ('0' <= c && c <= '7') {
+ src++;
+ n = 8 * n + JS7_UNDEC(c);
+ c = *src;
+ if ('0' <= c && c <= '7') {
+ src++;
+ i = 8 * n + JS7_UNDEC(c);
+ if (i <= 0377)
+ n = i;
+ else
+ src--;
+ }
+ }
+ localMax = n;
+ break;
+
+ default:
+ localMax = c;
+ break;
+ }
+ break;
+ default:
+ localMax = *src++;
+ break;
+ }
+
+ if (inRange) {
+ /* Throw a SyntaxError here, per ECMA-262, 15.10.2.15. */
+ if (rangeStart > localMax) {
+ JS_ReportErrorNumber(state->context,
+ js_GetErrorMessage, NULL,
+ JSMSG_BAD_CLASS_RANGE);
+ return JS_FALSE;
+ }
+ inRange = JS_FALSE;
+ } else {
+ if (canStartRange && src < end - 1) {
+ if (*src == '-') {
+ ++src;
+ inRange = JS_TRUE;
+ rangeStart = (jschar)localMax;
+ continue;
+ }
+ }
+ if (state->flags & JSREG_FOLD)
+ rangeStart = localMax; /* one run of the uc/dc loop below */
+ }
+
+ if (state->flags & JSREG_FOLD) {
+ jschar maxch = localMax;
+
+ for (i = rangeStart; i <= localMax; i++) {
+ jschar uch, dch;
+
+ uch = upcase(i);
+ dch = downcase(i);
+ maxch = JS_MAX(maxch, uch);
+ maxch = JS_MAX(maxch, dch);
+ }
+ localMax = maxch;
+ }
+
+ if (localMax > max)
+ max = localMax;
+ }
+ target->u.ucclass.bmsize = max;
+ return JS_TRUE;
+}
+
+/*
+ * item: assertion An item is either an assertion or
+ * quantatom a quantified atom.
+ *
+ * assertion: '^' Assertions match beginning of string
+ * (or line if the class static property
+ * RegExp.multiline is true).
+ * '$' End of string (or line if the class
+ * static property RegExp.multiline is
+ * true).
+ * '\b' Word boundary (between \w and \W).
+ * '\B' Word non-boundary.
+ *
+ * quantatom: atom An unquantified atom.
+ * quantatom '{' n ',' m '}'
+ * Atom must occur between n and m times.
+ * quantatom '{' n ',' '}' Atom must occur at least n times.
+ * quantatom '{' n '}' Atom must occur exactly n times.
+ * quantatom '*' Zero or more times (same as {0,}).
+ * quantatom '+' One or more times (same as {1,}).
+ * quantatom '?' Zero or one time (same as {0,1}).
+ *
+ * any of which can be optionally followed by '?' for ungreedy
+ *
+ * atom: '(' regexp ')' A parenthesized regexp (what matched
+ * can be addressed using a backreference,
+ * see '\' n below).
+ * '.' Matches any char except '\n'.
+ * '[' classlist ']' A character class.
+ * '[' '^' classlist ']' A negated character class.
+ * '\f' Form Feed.
+ * '\n' Newline (Line Feed).
+ * '\r' Carriage Return.
+ * '\t' Horizontal Tab.
+ * '\v' Vertical Tab.
+ * '\d' A digit (same as [0-9]).
+ * '\D' A non-digit.
+ * '\w' A word character, [0-9a-z_A-Z].
+ * '\W' A non-word character.
+ * '\s' A whitespace character, [ \b\f\n\r\t\v].
+ * '\S' A non-whitespace character.
+ * '\' n A backreference to the nth (n decimal
+ * and positive) parenthesized expression.
+ * '\' octal An octal escape sequence (octal must be
+ * two or three digits long, unless it is
+ * 0 for the null character).
+ * '\x' hex A hex escape (hex must be two digits).
+ * '\u' unicode A unicode escape (must be four digits).
+ * '\c' ctrl A control character, ctrl is a letter.
+ * '\' literalatomchar Any character except one of the above
+ * that follow '\' in an atom.
+ * otheratomchar Any character not first among the other
+ * atom right-hand sides.
+ */
+static JSBool
+ParseTerm(CompilerState *state)
+{
+ jschar c = *state->cp++;
+ uintN nDigits;
+ uintN num, tmp, n, i;
+ const jschar *termStart;
+
+ switch (c) {
+ /* assertions and atoms */
+ case '^':
+ state->result = NewRENode(state, REOP_BOL);
+ if (!state->result)
+ return JS_FALSE;
+ state->progLength++;
+ return JS_TRUE;
+ case '$':
+ state->result = NewRENode(state, REOP_EOL);
+ if (!state->result)
+ return JS_FALSE;
+ state->progLength++;
+ return JS_TRUE;
+ case '\\':
+ if (state->cp >= state->cpend) {
+ /* a trailing '\' is an error */
+ ReportRegExpError(state, JSREPORT_ERROR, JSMSG_TRAILING_SLASH);
+ return JS_FALSE;
+ }
+ c = *state->cp++;
+ switch (c) {
+ /* assertion escapes */
+ case 'b' :
+ state->result = NewRENode(state, REOP_WBDRY);
+ if (!state->result)
+ return JS_FALSE;
+ state->progLength++;
+ return JS_TRUE;
+ case 'B':
+ state->result = NewRENode(state, REOP_WNONBDRY);
+ if (!state->result)
+ return JS_FALSE;
+ state->progLength++;
+ return JS_TRUE;
+ /* Decimal escape */
+ case '0':
+ /* Give a strict warning. See also the note below. */
+ if (!ReportRegExpError(state, JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_INVALID_BACKREF)) {
+ return JS_FALSE;
+ }
+ doOctal:
+ num = 0;
+ while (state->cp < state->cpend) {
+ c = *state->cp;
+ if (c < '0' || '7' < c)
+ break;
+ state->cp++;
+ tmp = 8 * num + (uintN)JS7_UNDEC(c);
+ if (tmp > 0377)
+ break;
+ num = tmp;
+ }
+ c = (jschar)num;
+ doFlat:
+ state->result = NewRENode(state, REOP_FLAT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.flat.chr = c;
+ state->result->u.flat.length = 1;
+ state->progLength += 3;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ termStart = state->cp - 1;
+ num = GetDecimalValue(c, state->parenCount, FindParenCount, state);
+ if (state->flags & JSREG_FIND_PAREN_ERROR)
+ return JS_FALSE;
+ if (num == OVERFLOW_VALUE) {
+ /* Give a strict mode warning. */
+ if (!ReportRegExpError(state,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ (c >= '8')
+ ? JSMSG_INVALID_BACKREF
+ : JSMSG_BAD_BACKREF)) {
+ return JS_FALSE;
+ }
+
+ /*
+ * Note: ECMA 262, 15.10.2.9 says that we should throw a syntax
+ * error here. However, for compatibility with IE, we treat the
+ * whole backref as flat if the first character in it is not a
+ * valid octal character, and as an octal escape otherwise.
+ */
+ state->cp = termStart;
+ if (c >= '8') {
+ /* Treat this as flat. termStart - 1 is the \. */
+ c = '\\';
+ goto asFlat;
+ }
+
+ /* Treat this as an octal escape. */
+ goto doOctal;
+ }
+ JS_ASSERT(1 <= num && num <= 0x10000);
+ state->result = NewRENode(state, REOP_BACKREF);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.parenIndex = num - 1;
+ state->progLength
+ += 1 + GetCompactIndexWidth(state->result->u.parenIndex);
+ break;
+ /* Control escape */
+ case 'f':
+ c = 0xC;
+ goto doFlat;
+ case 'n':
+ c = 0xA;
+ goto doFlat;
+ case 'r':
+ c = 0xD;
+ goto doFlat;
+ case 't':
+ c = 0x9;
+ goto doFlat;
+ case 'v':
+ c = 0xB;
+ goto doFlat;
+ /* Control letter */
+ case 'c':
+ if (state->cp < state->cpend && RE_IS_LETTER(*state->cp)) {
+ c = (jschar) (*state->cp++ & 0x1F);
+ } else {
+ /* back off to accepting the original '\' as a literal */
+ --state->cp;
+ c = '\\';
+ }
+ goto doFlat;
+ /* HexEscapeSequence */
+ case 'x':
+ nDigits = 2;
+ goto lexHex;
+ /* UnicodeEscapeSequence */
+ case 'u':
+ nDigits = 4;
+lexHex:
+ n = 0;
+ for (i = 0; i < nDigits && state->cp < state->cpend; i++) {
+ uintN digit;
+ c = *state->cp++;
+ if (!isASCIIHexDigit(c, &digit)) {
+ /*
+ * Back off to accepting the original 'u' or 'x' as a
+ * literal.
+ */
+ state->cp -= i + 2;
+ n = *state->cp++;
+ break;
+ }
+ n = (n << 4) | digit;
+ }
+ c = (jschar) n;
+ goto doFlat;
+ /* Character class escapes */
+ case 'd':
+ state->result = NewRENode(state, REOP_DIGIT);
+doSimple:
+ if (!state->result)
+ return JS_FALSE;
+ state->progLength++;
+ break;
+ case 'D':
+ state->result = NewRENode(state, REOP_NONDIGIT);
+ goto doSimple;
+ case 's':
+ state->result = NewRENode(state, REOP_SPACE);
+ goto doSimple;
+ case 'S':
+ state->result = NewRENode(state, REOP_NONSPACE);
+ goto doSimple;
+ case 'w':
+ state->result = NewRENode(state, REOP_ALNUM);
+ goto doSimple;
+ case 'W':
+ state->result = NewRENode(state, REOP_NONALNUM);
+ goto doSimple;
+ /* IdentityEscape */
+ default:
+ state->result = NewRENode(state, REOP_FLAT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.flat.chr = c;
+ state->result->u.flat.length = 1;
+ state->result->kid = (void *) (state->cp - 1);
+ state->progLength += 3;
+ break;
+ }
+ break;
+ case '[':
+ state->result = NewRENode(state, REOP_CLASS);
+ if (!state->result)
+ return JS_FALSE;
+ termStart = state->cp;
+ state->result->u.ucclass.startIndex = termStart - state->cpbegin;
+ for (;;) {
+ if (state->cp == state->cpend) {
+ ReportRegExpErrorHelper(state, JSREPORT_ERROR,
+ JSMSG_UNTERM_CLASS, termStart);
+
+ return JS_FALSE;
+ }
+ if (*state->cp == '\\') {
+ state->cp++;
+ if (state->cp != state->cpend)
+ state->cp++;
+ continue;
+ }
+ if (*state->cp == ']') {
+ state->result->u.ucclass.kidlen = state->cp - termStart;
+ break;
+ }
+ state->cp++;
+ }
+ for (i = 0; i < CLASS_CACHE_SIZE; i++) {
+ if (!state->classCache[i].start) {
+ state->classCache[i].start = termStart;
+ state->classCache[i].length = state->result->u.ucclass.kidlen;
+ state->classCache[i].index = state->classCount;
+ break;
+ }
+ if (state->classCache[i].length ==
+ state->result->u.ucclass.kidlen) {
+ for (n = 0; ; n++) {
+ if (n == state->classCache[i].length) {
+ state->result->u.ucclass.index
+ = state->classCache[i].index;
+ goto claim;
+ }
+ if (state->classCache[i].start[n] != termStart[n])
+ break;
+ }
+ }
+ }
+ state->result->u.ucclass.index = state->classCount++;
+
+ claim:
+ /*
+ * Call CalculateBitmapSize now as we want any errors it finds
+ * to be reported during the parse phase, not at execution.
+ */
+ if (!CalculateBitmapSize(state, state->result, termStart, state->cp++))
+ return JS_FALSE;
+ /*
+ * Update classBitmapsMem with number of bytes to hold bmsize bits,
+ * which is (bitsCount + 7) / 8 or (highest_bit + 1 + 7) / 8
+ * or highest_bit / 8 + 1 where highest_bit is u.ucclass.bmsize.
+ */
+ n = (state->result->u.ucclass.bmsize >> 3) + 1;
+ if (n > CLASS_BITMAPS_MEM_LIMIT - state->classBitmapsMem) {
+ ReportRegExpError(state, JSREPORT_ERROR, JSMSG_REGEXP_TOO_COMPLEX);
+ return JS_FALSE;
+ }
+ state->classBitmapsMem += n;
+ /* CLASS, <index> */
+ state->progLength
+ += 1 + GetCompactIndexWidth(state->result->u.ucclass.index);
+ break;
+
+ case '.':
+ state->result = NewRENode(state, REOP_DOT);
+ goto doSimple;
+
+ case '{':
+ {
+ const jschar *errp = state->cp--;
+ intN err;
+
+ err = ParseMinMaxQuantifier(state, JS_TRUE);
+ state->cp = errp;
+
+ if (err < 0)
+ goto asFlat;
+
+ /* FALL THROUGH */
+ }
+ case '*':
+ case '+':
+ case '?':
+ ReportRegExpErrorHelper(state, JSREPORT_ERROR,
+ JSMSG_BAD_QUANTIFIER, state->cp - 1);
+ return JS_FALSE;
+ default:
+asFlat:
+ state->result = NewRENode(state, REOP_FLAT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.flat.chr = c;
+ state->result->u.flat.length = 1;
+ state->result->kid = (void *) (state->cp - 1);
+ state->progLength += 3;
+ break;
+ }
+ return ParseQuantifier(state);
+}
+
+static JSBool
+ParseQuantifier(CompilerState *state)
+{
+ RENode *term;
+ term = state->result;
+ if (state->cp < state->cpend) {
+ switch (*state->cp) {
+ case '+':
+ state->result = NewRENode(state, REOP_QUANT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.range.min = 1;
+ state->result->u.range.max = (uintN)-1;
+ /* <PLUS>, <next> ... <ENDCHILD> */
+ state->progLength += 4;
+ goto quantifier;
+ case '*':
+ state->result = NewRENode(state, REOP_QUANT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.range.min = 0;
+ state->result->u.range.max = (uintN)-1;
+ /* <STAR>, <next> ... <ENDCHILD> */
+ state->progLength += 4;
+ goto quantifier;
+ case '?':
+ state->result = NewRENode(state, REOP_QUANT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.range.min = 0;
+ state->result->u.range.max = 1;
+ /* <OPT>, <next> ... <ENDCHILD> */
+ state->progLength += 4;
+ goto quantifier;
+ case '{': /* balance '}' */
+ {
+ intN err;
+ const jschar *errp = state->cp;
+
+ err = ParseMinMaxQuantifier(state, JS_FALSE);
+ if (err == 0)
+ goto quantifier;
+ if (err == -1)
+ return JS_TRUE;
+
+ ReportRegExpErrorHelper(state, JSREPORT_ERROR, err, errp);
+ return JS_FALSE;
+ }
+ default:;
+ }
+ }
+ return JS_TRUE;
+
+quantifier:
+ if (state->treeDepth == TREE_DEPTH_MAX) {
+ ReportRegExpError(state, JSREPORT_ERROR, JSMSG_REGEXP_TOO_COMPLEX);
+ return JS_FALSE;
+ }
+
+ ++state->treeDepth;
+ ++state->cp;
+ state->result->kid = term;
+ if (state->cp < state->cpend && *state->cp == '?') {
+ ++state->cp;
+ state->result->u.range.greedy = JS_FALSE;
+ } else {
+ state->result->u.range.greedy = JS_TRUE;
+ }
+ return JS_TRUE;
+}
+
+static intN
+ParseMinMaxQuantifier(CompilerState *state, JSBool ignoreValues)
+{
+ uintN min, max;
+ jschar c;
+ const jschar *errp = state->cp++;
+
+ c = *state->cp;
+ if (JS7_ISDEC(c)) {
+ ++state->cp;
+ min = GetDecimalValue(c, 0xFFFF, NULL, state);
+ c = *state->cp;
+
+ if (!ignoreValues && min == OVERFLOW_VALUE)
+ return JSMSG_MIN_TOO_BIG;
+
+ if (c == ',') {
+ c = *++state->cp;
+ if (JS7_ISDEC(c)) {
+ ++state->cp;
+ max = GetDecimalValue(c, 0xFFFF, NULL, state);
+ c = *state->cp;
+ if (!ignoreValues && max == OVERFLOW_VALUE)
+ return JSMSG_MAX_TOO_BIG;
+ if (!ignoreValues && min > max)
+ return JSMSG_OUT_OF_ORDER;
+ } else {
+ max = (uintN)-1;
+ }
+ } else {
+ max = min;
+ }
+ if (c == '}') {
+ state->result = NewRENode(state, REOP_QUANT);
+ if (!state->result)
+ return JSMSG_OUT_OF_MEMORY;
+ state->result->u.range.min = min;
+ state->result->u.range.max = max;
+ /*
+ * QUANT, <min>, <max>, <next> ... <ENDCHILD>
+ * where <max> is written as compact(max+1) to make
+ * (uintN)-1 sentinel to occupy 1 byte, not width_of(max)+1.
+ */
+ state->progLength += (1 + GetCompactIndexWidth(min)
+ + GetCompactIndexWidth(max + 1)
+ +3);
+ return 0;
+ }
+ }
+
+ state->cp = errp;
+ return -1;
+}
+
+static JSBool
+SetForwardJumpOffset(jsbytecode *jump, jsbytecode *target)
+{
+ ptrdiff_t offset = target - jump;
+
+ /* Check that target really points forward. */
+ JS_ASSERT(offset >= 2);
+ if ((size_t)offset > OFFSET_MAX)
+ return JS_FALSE;
+
+ jump[0] = JUMP_OFFSET_HI(offset);
+ jump[1] = JUMP_OFFSET_LO(offset);
+ return JS_TRUE;
+}
+
+/* Copy the charset data from a character class node to the charset list
+ * in the regexp object. */
+static JS_ALWAYS_INLINE RECharSet *
+InitNodeCharSet(JSRegExp *re, RENode *node)
+{
+ RECharSet *charSet = &re->classList[node->u.ucclass.index];
+ charSet->converted = JS_FALSE;
+ charSet->length = node->u.ucclass.bmsize;
+ charSet->u.src.startIndex = node->u.ucclass.startIndex;
+ charSet->u.src.length = node->u.ucclass.kidlen;
+ charSet->sense = node->u.ucclass.sense;
+ return charSet;
+}
+
+/*
+ * Generate bytecode for the tree rooted at t using an explicit stack instead
+ * of recursion.
+ */
+static jsbytecode *
+EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth,
+ jsbytecode *pc, RENode *t)
+{
+ EmitStateStackEntry *emitStateSP, *emitStateStack;
+ REOp op;
+
+ if (treeDepth == 0) {
+ emitStateStack = NULL;
+ } else {
+ emitStateStack =
+ (EmitStateStackEntry *)JS_malloc(state->context,
+ sizeof(EmitStateStackEntry) *
+ treeDepth);
+ if (!emitStateStack)
+ return NULL;
+ }
+ emitStateSP = emitStateStack;
+ op = t->op;
+ JS_ASSERT(op < REOP_LIMIT);
+
+ for (;;) {
+ *pc++ = op;
+ switch (op) {
+ case REOP_EMPTY:
+ --pc;
+ break;
+
+ case REOP_ALTPREREQ2:
+ case REOP_ALTPREREQ:
+ JS_ASSERT(emitStateSP);
+ emitStateSP->altHead = pc - 1;
+ emitStateSP->endTermFixup = pc;
+ pc += OFFSET_LEN;
+ SET_ARG(pc, t->u.altprereq.ch1);
+ pc += ARG_LEN;
+ SET_ARG(pc, t->u.altprereq.ch2);
+ pc += ARG_LEN;
+
+ emitStateSP->nextAltFixup = pc; /* offset to next alternate */
+ pc += OFFSET_LEN;
+
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_JUMP;
+ emitStateSP->jumpToJumpFlag = JS_FALSE;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ JS_ASSERT(op < REOP_LIMIT);
+ continue;
+
+ case REOP_JUMP:
+ emitStateSP->nextTermFixup = pc; /* offset to following term */
+ pc += OFFSET_LEN;
+ if (!SetForwardJumpOffset(emitStateSP->nextAltFixup, pc))
+ goto jump_too_big;
+ emitStateSP->continueOp = REOP_ENDALT;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->u.kid2;
+ op = t->op;
+ JS_ASSERT(op < REOP_LIMIT);
+ continue;
+
+ case REOP_ENDALT:
+ /*
+ * If we already patched emitStateSP->nextTermFixup to jump to
+ * a nearer jump, to avoid 16-bit immediate offset overflow, we
+ * are done here.
+ */
+ if (emitStateSP->jumpToJumpFlag)
+ break;
+
+ /*
+ * Fix up the REOP_JUMP offset to go to the op after REOP_ENDALT.
+ * REOP_ENDALT is executed only on successful match of the last
+ * alternate in a group.
+ */
+ if (!SetForwardJumpOffset(emitStateSP->nextTermFixup, pc))
+ goto jump_too_big;
+ if (t->op != REOP_ALT) {
+ if (!SetForwardJumpOffset(emitStateSP->endTermFixup, pc))
+ goto jump_too_big;
+ }
+
+ /*
+ * If the program is bigger than the REOP_JUMP offset range, then
+ * we must check for alternates before this one that are part of
+ * the same group, and fix up their jump offsets to target jumps
+ * close enough to fit in a 16-bit unsigned offset immediate.
+ */
+ if ((size_t)(pc - re->program) > OFFSET_MAX &&
+ emitStateSP > emitStateStack) {
+ EmitStateStackEntry *esp, *esp2;
+ jsbytecode *alt, *jump;
+ ptrdiff_t span, header;
+
+ esp2 = emitStateSP;
+ alt = esp2->altHead;
+ for (esp = esp2 - 1; esp >= emitStateStack; --esp) {
+ if (esp->continueOp == REOP_ENDALT &&
+ !esp->jumpToJumpFlag &&
+ esp->nextTermFixup + OFFSET_LEN == alt &&
+ (size_t)(pc - ((esp->continueNode->op != REOP_ALT)
+ ? esp->endTermFixup
+ : esp->nextTermFixup)) > OFFSET_MAX) {
+ alt = esp->altHead;
+ jump = esp->nextTermFixup;
+
+ /*
+ * The span must be 1 less than the distance from
+ * jump offset to jump offset, so we actually jump
+ * to a REOP_JUMP bytecode, not to its offset!
+ */
+ for (;;) {
+ JS_ASSERT(jump < esp2->nextTermFixup);
+ span = esp2->nextTermFixup - jump - 1;
+ if ((size_t)span <= OFFSET_MAX)
+ break;
+ do {
+ if (--esp2 == esp)
+ goto jump_too_big;
+ } while (esp2->continueOp != REOP_ENDALT);
+ }
+
+ jump[0] = JUMP_OFFSET_HI(span);
+ jump[1] = JUMP_OFFSET_LO(span);
+
+ if (esp->continueNode->op != REOP_ALT) {
+ /*
+ * We must patch the offset at esp->endTermFixup
+ * as well, for the REOP_ALTPREREQ{,2} opcodes.
+ * If we're unlucky and endTermFixup is more than
+ * OFFSET_MAX bytes from its target, we cheat by
+ * jumping 6 bytes to the jump whose offset is at
+ * esp->nextTermFixup, which has the same target.
+ */
+ jump = esp->endTermFixup;
+ header = esp->nextTermFixup - jump;
+ span += header;
+ if ((size_t)span > OFFSET_MAX)
+ span = header;
+
+ jump[0] = JUMP_OFFSET_HI(span);
+ jump[1] = JUMP_OFFSET_LO(span);
+ }
+
+ esp->jumpToJumpFlag = JS_TRUE;
+ }
+ }
+ }
+ break;
+
+ case REOP_ALT:
+ JS_ASSERT(emitStateSP);
+ emitStateSP->altHead = pc - 1;
+ emitStateSP->nextAltFixup = pc; /* offset to next alternate */
+ pc += OFFSET_LEN;
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_JUMP;
+ emitStateSP->jumpToJumpFlag = JS_FALSE;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ JS_ASSERT(op < REOP_LIMIT);
+ continue;
+
+ case REOP_FLAT:
+ /*
+ * Coalesce FLATs if possible and if it would not increase bytecode
+ * beyond preallocated limit. The latter happens only when bytecode
+ * size for coalesced string with offset p and length 2 exceeds 6
+ * bytes preallocated for 2 single char nodes, i.e. when
+ * 1 + GetCompactIndexWidth(p) + GetCompactIndexWidth(2) > 6 or
+ * GetCompactIndexWidth(p) > 4.
+ * Since when GetCompactIndexWidth(p) <= 4 coalescing of 3 or more
+ * nodes strictly decreases bytecode size, the check has to be
+ * done only for the first coalescing.
+ */
+ if (t->kid &&
+ GetCompactIndexWidth((jschar *)t->kid - state->cpbegin) <= 4)
+ {
+ while (t->next &&
+ t->next->op == REOP_FLAT &&
+ (jschar*)t->kid + t->u.flat.length ==
+ (jschar*)t->next->kid) {
+ t->u.flat.length += t->next->u.flat.length;
+ t->next = t->next->next;
+ }
+ }
+ if (t->kid && t->u.flat.length > 1) {
+ pc[-1] = (state->flags & JSREG_FOLD) ? REOP_FLATi : REOP_FLAT;
+ pc = WriteCompactIndex(pc, (jschar *)t->kid - state->cpbegin);
+ pc = WriteCompactIndex(pc, t->u.flat.length);
+ } else if (t->u.flat.chr < 256) {
+ pc[-1] = (state->flags & JSREG_FOLD) ? REOP_FLAT1i : REOP_FLAT1;
+ *pc++ = (jsbytecode) t->u.flat.chr;
+ } else {
+ pc[-1] = (state->flags & JSREG_FOLD)
+ ? REOP_UCFLAT1i
+ : REOP_UCFLAT1;
+ SET_ARG(pc, t->u.flat.chr);
+ pc += ARG_LEN;
+ }
+ break;
+
+ case REOP_LPAREN:
+ JS_ASSERT(emitStateSP);
+ pc = WriteCompactIndex(pc, t->u.parenIndex);
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_RPAREN;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ continue;
+
+ case REOP_RPAREN:
+ pc = WriteCompactIndex(pc, t->u.parenIndex);
+ break;
+
+ case REOP_BACKREF:
+ pc = WriteCompactIndex(pc, t->u.parenIndex);
+ break;
+
+ case REOP_ASSERT:
+ JS_ASSERT(emitStateSP);
+ emitStateSP->nextTermFixup = pc;
+ pc += OFFSET_LEN;
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_ASSERTTEST;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ continue;
+
+ case REOP_ASSERTTEST:
+ case REOP_ASSERTNOTTEST:
+ if (!SetForwardJumpOffset(emitStateSP->nextTermFixup, pc))
+ goto jump_too_big;
+ break;
+
+ case REOP_ASSERT_NOT:
+ JS_ASSERT(emitStateSP);
+ emitStateSP->nextTermFixup = pc;
+ pc += OFFSET_LEN;
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_ASSERTNOTTEST;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ continue;
+
+ case REOP_QUANT:
+ JS_ASSERT(emitStateSP);
+ if (t->u.range.min == 0 && t->u.range.max == (uintN)-1) {
+ pc[-1] = (t->u.range.greedy) ? REOP_STAR : REOP_MINIMALSTAR;
+ } else if (t->u.range.min == 0 && t->u.range.max == 1) {
+ pc[-1] = (t->u.range.greedy) ? REOP_OPT : REOP_MINIMALOPT;
+ } else if (t->u.range.min == 1 && t->u.range.max == (uintN) -1) {
+ pc[-1] = (t->u.range.greedy) ? REOP_PLUS : REOP_MINIMALPLUS;
+ } else {
+ if (!t->u.range.greedy)
+ pc[-1] = REOP_MINIMALQUANT;
+ pc = WriteCompactIndex(pc, t->u.range.min);
+ /*
+ * Write max + 1 to avoid using size_t(max) + 1 bytes
+ * for (uintN)-1 sentinel.
+ */
+ pc = WriteCompactIndex(pc, t->u.range.max + 1);
+ }
+ emitStateSP->nextTermFixup = pc;
+ pc += OFFSET_LEN;
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_ENDCHILD;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ continue;
+
+ case REOP_ENDCHILD:
+ if (!SetForwardJumpOffset(emitStateSP->nextTermFixup, pc))
+ goto jump_too_big;
+ break;
+
+ case REOP_CLASS:
+ if (!t->u.ucclass.sense)
+ pc[-1] = REOP_NCLASS;
+ pc = WriteCompactIndex(pc, t->u.ucclass.index);
+ InitNodeCharSet(re, t);
+ break;
+
+ default:
+ break;
+ }
+
+ t = t->next;
+ if (t) {
+ op = t->op;
+ } else {
+ if (emitStateSP == emitStateStack)
+ break;
+ --emitStateSP;
+ t = emitStateSP->continueNode;
+ op = (REOp) emitStateSP->continueOp;
+ }
+ }
+
+ cleanup:
+ if (emitStateStack)
+ JS_free(state->context, emitStateStack);
+ return pc;
+
+ jump_too_big:
+ ReportRegExpError(state, JSREPORT_ERROR, JSMSG_REGEXP_TOO_COMPLEX);
+ pc = NULL;
+ goto cleanup;
+}
+
+#ifdef JS_TRACER
+typedef List<LIns*, LIST_NonGCObjects> LInsList;
+
+/* Dummy GC for nanojit placement new. */
+static GC gc;
+
+class RegExpNativeCompiler {
+ private:
+ JSRegExp* re; /* Careful: not fully initialized */
+ CompilerState* cs; /* RegExp to compile */
+ Fragment* fragment;
+ LirWriter* lir;
+
+ LIns* state;
+ LIns* gdata;
+ LIns* cpend;
+
+ JSBool isCaseInsensitive() const { return cs->flags & JSREG_FOLD; }
+
+ void targetCurrentPoint(LIns* ins) { ins->target(lir->ins0(LIR_label)); }
+
+ void targetCurrentPoint(LInsList& fails)
+ {
+ LIns* fail = lir->ins0(LIR_label);
+ for (size_t i = 0; i < fails.size(); ++i) {
+ fails[i]->target(fail);
+ }
+ fails.clear();
+ }
+
+ /*
+ * These functions return the new position after their match operation,
+ * or NULL if there was an error.
+ */
+ LIns* compileEmpty(RENode* node, LIns* pos, LInsList& fails)
+ {
+ return pos;
+ }
+
+ LIns* compileFlatSingleChar(RENode* node, LIns* pos, LInsList& fails)
+ {
+ /*
+ * Fast case-insensitive test for ASCII letters: convert text
+ * char to lower case by bit-or-ing in 32 and compare.
+ */
+ JSBool useFastCI = JS_FALSE;
+ jschar ch = node->u.flat.chr; /* char to test for */
+ jschar ch2 = ch; /* 2nd char to test for if ci */
+ if (cs->flags & JSREG_FOLD) {
+ if (L'A' <= ch && ch <= L'Z' || L'a' <= ch || ch <= L'z') {
+ ch |= 32;
+ ch2 = ch;
+ useFastCI = JS_TRUE;
+ } else if (JS_TOLOWER(ch) != ch) {
+ ch2 = JS_TOLOWER(ch);
+ ch = JS_TOUPPER(ch);
+ }
+ }
+
+ LIns* to_fail = lir->insBranch(LIR_jf, lir->ins2(LIR_lt, pos, cpend), 0);
+ fails.add(to_fail);
+ LIns* text_ch = lir->insLoad(LIR_ldcs, pos, lir->insImm(0));
+ LIns* comp_ch = useFastCI ?
+ lir->ins2(LIR_or, text_ch, lir->insImm(32)) :
+ text_ch;
+ if (ch == ch2) {
+ fails.add(lir->insBranch(LIR_jf, lir->ins2(LIR_eq, comp_ch, lir->insImm(ch)), 0));
+ } else {
+ LIns* to_ok = lir->insBranch(LIR_jt, lir->ins2(LIR_eq, comp_ch, lir->insImm(ch)), 0);
+ fails.add(lir->insBranch(LIR_jf, lir->ins2(LIR_eq, comp_ch, lir->insImm(ch2)), 0));
+ targetCurrentPoint(to_ok);
+ }
+
+ return lir->ins2(LIR_piadd, pos, lir->insImm(2));
+ }
+
+ LIns* compileClass(RENode* node, LIns* pos, LInsList& fails)
+ {
+ if (!node->u.ucclass.sense)
+ return JS_FALSE;
+
+ RECharSet* charSet = InitNodeCharSet(re, node);
+ LIns* to_fail = lir->insBranch(LIR_jf, lir->ins2(LIR_lt, pos, cpend), 0);
+ fails.add(to_fail);
+ LIns* text_ch = lir->insLoad(LIR_ldcs, pos, lir->insImm(0));
+ fails.add(lir->insBranch(LIR_jf, lir->ins2(LIR_le, text_ch, lir->insImm(charSet->length)), 0));
+ LIns* byteIndex = lir->ins2(LIR_rsh, text_ch, lir->insImm(3));
+ LIns* bitmap = lir->insLoad(LIR_ld, lir->insImmPtr(charSet), (int) offsetof(RECharSet, u.bits));
+ LIns* byte = lir->insLoad(LIR_ldcb, lir->ins2(LIR_piadd, bitmap, byteIndex), (int) 0);
+ LIns* bitMask = lir->ins2(LIR_lsh, lir->insImm(1),
+ lir->ins2(LIR_and, text_ch, lir->insImm(0x7)));
+ LIns* test = lir->ins2(LIR_eq, lir->ins2(LIR_and, byte, bitMask), lir->insImm(0));
+
+ LIns* to_next = lir->insBranch(LIR_jt, test, 0);
+ fails.add(to_next);
+ return lir->ins2(LIR_piadd, pos, lir->insImm(2));
+ }
+
+ LIns* compileAlt(RENode* node, LIns* pos, LInsList& fails)
+ {
+ LInsList kidFails(NULL);
+ if (!compileNode((RENode *) node->kid, pos, kidFails))
+ return JS_FALSE;
+ if (!compileNode(node->next, pos, kidFails))
+ return JS_FALSE;
+
+ targetCurrentPoint(kidFails);
+ if (!compileNode(node->u.altprereq.kid2, pos, fails))
+ return JS_FALSE;
+ /*
+ * Disable compilation for any regexp where something follows an
+ * alternation. To make this work, we need to redesign to either
+ * (a) pass around continuations so we know the right place to go
+ * when we logically return, or (b) generate explicit backtracking
+ * code.
+ */
+ if (node->next)
+ return JS_FALSE;
+ return pos;
+ }
+
+ JSBool compileNode(RENode* node, LIns* pos, LInsList& fails)
+ {
+ for (; node; node = node->next) {
+ if (fragment->lirbuf->outOmem())
+ return JS_FALSE;
+
+ switch (node->op) {
+ case REOP_EMPTY:
+ pos = compileEmpty(node, pos, fails);
+ break;
+ case REOP_FLAT:
+ if (node->u.flat.length != 1)
+ return JS_FALSE;
+ pos = compileFlatSingleChar(node, pos, fails);
+ break;
+ case REOP_ALT:
+ case REOP_ALTPREREQ:
+ pos = compileAlt(node, pos, fails);
+ break;
+ case REOP_CLASS:
+ pos = compileClass(node, pos, fails);
+ break;
+ default:
+ return JS_FALSE;
+ }
+ if (!pos)
+ return JS_FALSE;
+ }
+
+ lir->insStorei(pos, state, (int) offsetof(REMatchState, cp));
+ lir->ins1(LIR_ret, state);
+ return JS_TRUE;
+ }
+
+ JSBool compileSticky(RENode* root, LIns* start)
+ {
+ LInsList fails(NULL);
+ if (!compileNode(root, start, fails))
+ return JS_FALSE;
+ targetCurrentPoint(fails);
+ lir->ins1(LIR_ret, lir->insImm(0));
+ return JS_TRUE;
+ }
+
+ JSBool compileAnchoring(RENode* root, LIns* start)
+ {
+ /* Even at the end, the empty regexp would match. */
+ LIns* to_next = lir->insBranch(LIR_jf,
+ lir->ins2(LIR_le, start, cpend), 0);
+ LInsList fails(NULL);
+ if (!compileNode(root, start, fails))
+ return JS_FALSE;
+
+ targetCurrentPoint(to_next);
+ lir->ins1(LIR_ret, lir->insImm(0));
+
+ targetCurrentPoint(fails);
+ lir->insStorei(lir->ins2(LIR_piadd, start, lir->insImm(2)), gdata,
+ (int) offsetof(REGlobalData, skipped));
+
+ return JS_TRUE;
+ }
+
+ inline LIns*
+ addName(LirBuffer* lirbuf, LIns* ins, const char* name)
+ {
+ debug_only_v(lirbuf->names->addName(ins, name);)
+ return ins;
+ }
+
+ public:
+ RegExpNativeCompiler(JSRegExp *re, CompilerState *cs)
+ : re(re), cs(cs), fragment(NULL) { }
+
+ JSBool compile(JSContext* cx)
+ {
+ GuardRecord* guard;
+ LIns* skip;
+ LIns* start;
+ bool oom = false;
+
+ Fragmento* fragmento = JS_TRACE_MONITOR(cx).reFragmento;
+ fragment = fragmento->getLoop(re);
+ if (!fragment) {
+ fragment = fragmento->getAnchor(re);
+ fragment->lirbuf = new (&gc) LirBuffer(fragmento, NULL);
+ /* Scary: required to have the onDestroy method delete the lirbuf. */
+ fragment->root = fragment;
+ }
+ LirBuffer* lirbuf = fragment->lirbuf;
+ LirBufWriter* lirb;
+ if (lirbuf->outOmem()) goto fail2;
+ /* FIXME Use bug 463260 smart pointer when available. */
+ lir = lirb = new (&gc) LirBufWriter(lirbuf);
+
+ /* FIXME Use bug 463260 smart pointer when available. */
+ debug_only_v(fragment->lirbuf->names = new (&gc) LirNameMap(&gc, NULL, fragmento->labels);)
+ /* FIXME Use bug 463260 smart pointer when available. */
+ debug_only_v(lir = new (&gc) VerboseWriter(&gc, lir, lirbuf->names);)
+
+ lir->ins0(LIR_start);
+ lirbuf->state = state = addName(lirbuf, lir->insParam(0, 0), "state");
+ lirbuf->param1 = gdata = addName(lirbuf, lir->insParam(1, 0), "gdata");
+ start = addName(lirbuf, lir->insLoad(LIR_ldp, lirbuf->param1, (int) offsetof(REGlobalData, skipped)), "start");
+ cpend = addName(lirbuf, lir->insLoad(LIR_ldp, lirbuf->param1, offsetof(REGlobalData, cpend)), "cpend");
+
+ if (cs->flags & JSREG_STICKY) {
+ if (!compileSticky(cs->result, start)) goto fail;
+ } else {
+ if (!compileAnchoring(cs->result, start)) goto fail;
+ }
+
+ /* Create fake guard record for loop edge. */
+ skip = lirb->skip(sizeof(GuardRecord) + sizeof(SideExit));
+ guard = (GuardRecord *) skip->payload();
+ memset(guard, 0, sizeof(*guard));
+ guard->exit = (SideExit *) guard+1;
+ guard->exit->target = fragment;
+ fragment->lastIns = lir->insGuard(LIR_loop, lir->insImm(1), skip);
+
+ ::compile(fragmento->assm(), fragment);
+ if (fragmento->assm()->error() != nanojit::None) {
+ oom = fragmento->assm()->error() == nanojit::OutOMem;
+ goto fail;
+ }
+
+ delete lirb;
+ debug_only_v(delete lir;)
+ return JS_TRUE;
+ fail:
+ delete lirb;
+ debug_only_v(delete lir;)
+ fail2:
+ if (lirbuf->outOmem() || oom)
+ fragmento->clearFrags();
+ return JS_FALSE;
+ }
+};
+
+static inline JSBool
+js_CompileRegExpToNative(JSContext *cx, JSRegExp *re, CompilerState *cs)
+{
+ RegExpNativeCompiler rc(re, cs);
+ return rc.compile(cx);
+}
+#endif
+
+JSRegExp *
+js_NewRegExp(JSContext *cx, JSTokenStream *ts,
+ JSString *str, uintN flags, JSBool flat)
+{
+ JSRegExp *re;
+ void *mark;
+ CompilerState state;
+ size_t resize;
+ jsbytecode *endPC;
+ uintN i;
+ size_t len;
+
+ re = NULL;
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ len = JSSTRING_LENGTH(str);
+
+ state.context = cx;
+ state.tokenStream = ts;
+ state.cp = js_UndependString(cx, str);
+ if (!state.cp)
+ goto out;
+ state.cpbegin = state.cp;
+ state.cpend = state.cp + len;
+ state.flags = flags;
+ state.parenCount = 0;
+ state.classCount = 0;
+ state.progLength = 0;
+ state.treeDepth = 0;
+ state.classBitmapsMem = 0;
+ for (i = 0; i < CLASS_CACHE_SIZE; i++)
+ state.classCache[i].start = NULL;
+
+ if (len != 0 && flat) {
+ state.result = NewRENode(&state, REOP_FLAT);
+ if (!state.result)
+ goto out;
+ state.result->u.flat.chr = *state.cpbegin;
+ state.result->u.flat.length = len;
+ state.result->kid = (void *) state.cpbegin;
+ /* Flat bytecode: REOP_FLAT compact(string_offset) compact(len). */
+ state.progLength += 1 + GetCompactIndexWidth(0)
+ + GetCompactIndexWidth(len);
+ } else {
+ if (!ParseRegExp(&state))
+ goto out;
+ }
+
+ resize = offsetof(JSRegExp, program) + state.progLength + 1;
+ re = (JSRegExp *) JS_malloc(cx, resize);
+ if (!re)
+ goto out;
+
+ re->nrefs = 1;
+ JS_ASSERT(state.classBitmapsMem <= CLASS_BITMAPS_MEM_LIMIT);
+ re->classCount = state.classCount;
+ if (re->classCount) {
+ re->classList = (RECharSet *)
+ JS_malloc(cx, re->classCount * sizeof(RECharSet));
+ if (!re->classList) {
+ js_DestroyRegExp(cx, re);
+ re = NULL;
+ goto out;
+ }
+ for (i = 0; i < re->classCount; i++)
+ re->classList[i].converted = JS_FALSE;
+ } else {
+ re->classList = NULL;
+ }
+
+#ifdef JS_TRACER
+ /*
+ * Try compiling the native code version. For the time being we also
+ * compile the bytecode version in case we evict the native code
+ * version from the code cache.
+ */
+ if (TRACING_ENABLED(cx))
+ js_CompileRegExpToNative(cx, re, &state);
+#endif
+ /* Compile the bytecode version. */
+ endPC = EmitREBytecode(&state, re, state.treeDepth, re->program, state.result);
+ if (!endPC) {
+ js_DestroyRegExp(cx, re);
+ re = NULL;
+ goto out;
+ }
+ *endPC++ = REOP_END;
+ /*
+ * Check whether size was overestimated and shrink using realloc.
+ * This is safe since no pointers to newly parsed regexp or its parts
+ * besides re exist here.
+ */
+#if 0
+ /*
+ * FIXME: Until bug 464866 is fixed, we can't move the re object so
+ * don't shrink it for now.
+ */
+ if ((size_t)(endPC - re->program) != state.progLength + 1) {
+ JSRegExp *tmp;
+ JS_ASSERT((size_t)(endPC - re->program) < state.progLength + 1);
+ resize = offsetof(JSRegExp, program) + (endPC - re->program);
+ tmp = (JSRegExp *) JS_realloc(cx, re, resize);
+ if (tmp)
+ re = tmp;
+ }
+#endif
+
+ re->flags = flags;
+ re->parenCount = state.parenCount;
+ re->source = str;
+
+out:
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return re;
+}
+
+JSRegExp *
+js_NewRegExpOpt(JSContext *cx, JSString *str, JSString *opt, JSBool flat)
+{
+ uintN flags;
+ jschar *s;
+ size_t i, n;
+ char charBuf[2];
+
+ flags = 0;
+ if (opt) {
+ JSSTRING_CHARS_AND_LENGTH(opt, s, n);
+ for (i = 0; i < n; i++) {
+ switch (s[i]) {
+ case 'g':
+ flags |= JSREG_GLOB;
+ break;
+ case 'i':
+ flags |= JSREG_FOLD;
+ break;
+ case 'm':
+ flags |= JSREG_MULTILINE;
+ break;
+ case 'y':
+ flags |= JSREG_STICKY;
+ break;
+ default:
+ charBuf[0] = (char)s[i];
+ charBuf[1] = '\0';
+ JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_BAD_FLAG, charBuf);
+ return NULL;
+ }
+ }
+ }
+ return js_NewRegExp(cx, NULL, str, flags, flat);
+}
+
+/*
+ * Save the current state of the match - the position in the input
+ * text as well as the position in the bytecode. The state of any
+ * parent expressions is also saved (preceding state).
+ * Contents of parenCount parentheses from parenIndex are also saved.
+ */
+static REBackTrackData *
+PushBackTrackState(REGlobalData *gData, REOp op,
+ jsbytecode *target, REMatchState *x, const jschar *cp,
+ size_t parenIndex, size_t parenCount)
+{
+ size_t i;
+ REBackTrackData *result =
+ (REBackTrackData *) ((char *)gData->backTrackSP + gData->cursz);
+
+ size_t sz = sizeof(REBackTrackData) +
+ gData->stateStackTop * sizeof(REProgState) +
+ parenCount * sizeof(RECapture);
+
+ ptrdiff_t btsize = gData->backTrackStackSize;
+ ptrdiff_t btincr = ((char *)result + sz) -
+ ((char *)gData->backTrackStack + btsize);
+
+ re_debug("\tBT_Push: %lu,%lu",
+ (unsigned long) parenIndex, (unsigned long) parenCount);
+
+ JS_COUNT_OPERATION(gData->cx, JSOW_JUMP * (1 + parenCount));
+ if (btincr > 0) {
+ ptrdiff_t offset = (char *)result - (char *)gData->backTrackStack;
+
+ JS_COUNT_OPERATION(gData->cx, JSOW_ALLOCATION);
+ btincr = JS_ROUNDUP(btincr, btsize);
+ JS_ARENA_GROW_CAST(gData->backTrackStack, REBackTrackData *,
+ &gData->cx->regexpPool, btsize, btincr);
+ if (!gData->backTrackStack) {
+ js_ReportOutOfScriptQuota(gData->cx);
+ gData->ok = JS_FALSE;
+ return NULL;
+ }
+ gData->backTrackStackSize = btsize + btincr;
+ result = (REBackTrackData *) ((char *)gData->backTrackStack + offset);
+ }
+ gData->backTrackSP = result;
+ result->sz = gData->cursz;
+ gData->cursz = sz;
+
+ result->backtrack_op = op;
+ result->backtrack_pc = target;
+ result->cp = cp;
+ result->parenCount = parenCount;
+ result->parenIndex = parenIndex;
+
+ result->saveStateStackTop = gData->stateStackTop;
+ JS_ASSERT(gData->stateStackTop);
+ memcpy(result + 1, gData->stateStack,
+ sizeof(REProgState) * result->saveStateStackTop);
+
+ if (parenCount != 0) {
+ memcpy((char *)(result + 1) +
+ sizeof(REProgState) * result->saveStateStackTop,
+ &x->parens[parenIndex],
+ sizeof(RECapture) * parenCount);
+ for (i = 0; i != parenCount; i++)
+ x->parens[parenIndex + i].index = -1;
+ }
+
+ return result;
+}
+
+
+/*
+ * Consecutive literal characters.
+ */
+#if 0
+static REMatchState *
+FlatNMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars,
+ size_t length)
+{
+ size_t i;
+ if (length > gData->cpend - x->cp)
+ return NULL;
+ for (i = 0; i != length; i++) {
+ if (matchChars[i] != x->cp[i])
+ return NULL;
+ }
+ x->cp += length;
+ return x;
+}
+#endif
+
+static JS_ALWAYS_INLINE REMatchState *
+FlatNIMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars,
+ size_t length)
+{
+ size_t i;
+ JS_ASSERT(gData->cpend >= x->cp);
+ if (length > (size_t)(gData->cpend - x->cp))
+ return NULL;
+ for (i = 0; i != length; i++) {
+ if (upcase(matchChars[i]) != upcase(x->cp[i]))
+ return NULL;
+ }
+ x->cp += length;
+ return x;
+}
+
+/*
+ * 1. Evaluate DecimalEscape to obtain an EscapeValue E.
+ * 2. If E is not a character then go to step 6.
+ * 3. Let ch be E's character.
+ * 4. Let A be a one-element RECharSet containing the character ch.
+ * 5. Call CharacterSetMatcher(A, false) and return its Matcher result.
+ * 6. E must be an integer. Let n be that integer.
+ * 7. If n=0 or n>NCapturingParens then throw a SyntaxError exception.
+ * 8. Return an internal Matcher closure that takes two arguments, a State x
+ * and a Continuation c, and performs the following:
+ * 1. Let cap be x's captures internal array.
+ * 2. Let s be cap[n].
+ * 3. If s is undefined, then call c(x) and return its result.
+ * 4. Let e be x's endIndex.
+ * 5. Let len be s's length.
+ * 6. Let f be e+len.
+ * 7. If f>InputLength, return failure.
+ * 8. If there exists an integer i between 0 (inclusive) and len (exclusive)
+ * such that Canonicalize(s[i]) is not the same character as
+ * Canonicalize(Input [e+i]), then return failure.
+ * 9. Let y be the State (f, cap).
+ * 10. Call c(y) and return its result.
+ */
+static REMatchState *
+BackrefMatcher(REGlobalData *gData, REMatchState *x, size_t parenIndex)
+{
+ size_t len, i;
+ const jschar *parenContent;
+ RECapture *cap = &x->parens[parenIndex];
+
+ if (cap->index == -1)
+ return x;
+
+ len = cap->length;
+ if (x->cp + len > gData->cpend)
+ return NULL;
+
+ parenContent = &gData->cpbegin[cap->index];
+ if (gData->regexp->flags & JSREG_FOLD) {
+ for (i = 0; i < len; i++) {
+ if (upcase(parenContent[i]) != upcase(x->cp[i]))
+ return NULL;
+ }
+ } else {
+ for (i = 0; i < len; i++) {
+ if (parenContent[i] != x->cp[i])
+ return NULL;
+ }
+ }
+ x->cp += len;
+ return x;
+}
+
+
+/* Add a single character to the RECharSet */
+static void
+AddCharacterToCharSet(RECharSet *cs, jschar c)
+{
+ uintN byteIndex = (uintN)(c >> 3);
+ JS_ASSERT(c <= cs->length);
+ cs->u.bits[byteIndex] |= 1 << (c & 0x7);
+}
+
+
+/* Add a character range, c1 to c2 (inclusive) to the RECharSet */
+static void
+AddCharacterRangeToCharSet(RECharSet *cs, uintN c1, uintN c2)
+{
+ uintN i;
+
+ uintN byteIndex1 = c1 >> 3;
+ uintN byteIndex2 = c2 >> 3;
+
+ JS_ASSERT(c2 <= cs->length && c1 <= c2);
+
+ c1 &= 0x7;
+ c2 &= 0x7;
+
+ if (byteIndex1 == byteIndex2) {
+ cs->u.bits[byteIndex1] |= ((uint8)0xFF >> (7 - (c2 - c1))) << c1;
+ } else {
+ cs->u.bits[byteIndex1] |= 0xFF << c1;
+ for (i = byteIndex1 + 1; i < byteIndex2; i++)
+ cs->u.bits[i] = 0xFF;
+ cs->u.bits[byteIndex2] |= (uint8)0xFF >> (7 - c2);
+ }
+}
+
+struct CharacterRange {
+ jschar start;
+ jschar end;
+};
+
+/*
+ * The following characters are taken from the ECMA-262 standard, section 7.2
+ * and 7.3, and the Unicode 3 standard, Table 6-1.
+ */
+static const CharacterRange WhiteSpaceRanges[] = {
+ /* TAB, LF, VT, FF, CR */
+ { 0x0009, 0x000D },
+ /* SPACE */
+ { 0x0020, 0x0020 },
+ /* NO-BREAK SPACE */
+ { 0x00A0, 0x00A0 },
+ /*
+ * EN QUAD, EM QUAD, EN SPACE, EM SPACE, THREE-PER-EM SPACE, FOUR-PER-EM
+ * SPACE, SIX-PER-EM SPACE, FIGURE SPACE, PUNCTUATION SPACE, THIN SPACE,
+ * HAIR SPACE, ZERO WIDTH SPACE
+ */
+ { 0x2000, 0x200B },
+ /* LS, PS */
+ { 0x2028, 0x2029 },
+ /* NARROW NO-BREAK SPACE */
+ { 0x202F, 0x202F },
+ /* IDEOGRAPHIC SPACE */
+ { 0x3000, 0x3000 }
+};
+
+/* ECMA-262 standard, section 15.10.2.6. */
+static const CharacterRange WordRanges[] = {
+ { jschar('0'), jschar('9') },
+ { jschar('A'), jschar('Z') },
+ { jschar('_'), jschar('_') },
+ { jschar('a'), jschar('z') }
+};
+
+static void
+AddCharacterRanges(RECharSet *charSet,
+ const CharacterRange *range,
+ const CharacterRange *end)
+{
+ for (; range < end; ++range)
+ AddCharacterRangeToCharSet(charSet, range->start, range->end);
+}
+
+static void
+AddInvertedCharacterRanges(RECharSet *charSet,
+ const CharacterRange *range,
+ const CharacterRange *end)
+{
+ uint16 previous = 0;
+ for (; range < end; ++range) {
+ AddCharacterRangeToCharSet(charSet, previous, range->start - 1);
+ previous = range->end + 1;
+ }
+ AddCharacterRangeToCharSet(charSet, previous, charSet->length);
+}
+
+/* Compile the source of the class into a RECharSet */
+static JSBool
+ProcessCharSet(REGlobalData *gData, RECharSet *charSet)
+{
+ const jschar *src, *end;
+ JSBool inRange = JS_FALSE;
+ jschar rangeStart = 0;
+ uintN byteLength, n;
+ jschar c, thisCh;
+ intN nDigits, i;
+
+ JS_ASSERT(!charSet->converted);
+ /*
+ * Assert that startIndex and length points to chars inside [] inside
+ * source string.
+ */
+ JS_ASSERT(1 <= charSet->u.src.startIndex);
+ JS_ASSERT(charSet->u.src.startIndex
+ < JSSTRING_LENGTH(gData->regexp->source));
+ JS_ASSERT(charSet->u.src.length <= JSSTRING_LENGTH(gData->regexp->source)
+ - 1 - charSet->u.src.startIndex);
+
+ charSet->converted = JS_TRUE;
+ src = JSSTRING_CHARS(gData->regexp->source) + charSet->u.src.startIndex;
+ end = src + charSet->u.src.length;
+ JS_ASSERT(src[-1] == '[');
+ JS_ASSERT(end[0] == ']');
+
+ byteLength = (charSet->length >> 3) + 1;
+ charSet->u.bits = (uint8 *)JS_malloc(gData->cx, byteLength);
+ if (!charSet->u.bits) {
+ JS_ReportOutOfMemory(gData->cx);
+ gData->ok = JS_FALSE;
+ return JS_FALSE;
+ }
+ memset(charSet->u.bits, 0, byteLength);
+
+ if (src == end)
+ return JS_TRUE;
+
+ if (*src == '^') {
+ JS_ASSERT(charSet->sense == JS_FALSE);
+ ++src;
+ } else {
+ JS_ASSERT(charSet->sense == JS_TRUE);
+ }
+
+ while (src != end) {
+ switch (*src) {
+ case '\\':
+ ++src;
+ c = *src++;
+ switch (c) {
+ case 'b':
+ thisCh = 0x8;
+ break;
+ case 'f':
+ thisCh = 0xC;
+ break;
+ case 'n':
+ thisCh = 0xA;
+ break;
+ case 'r':
+ thisCh = 0xD;
+ break;
+ case 't':
+ thisCh = 0x9;
+ break;
+ case 'v':
+ thisCh = 0xB;
+ break;
+ case 'c':
+ if (src < end && JS_ISWORD(*src)) {
+ thisCh = (jschar)(*src++ & 0x1F);
+ } else {
+ --src;
+ thisCh = '\\';
+ }
+ break;
+ case 'x':
+ nDigits = 2;
+ goto lexHex;
+ case 'u':
+ nDigits = 4;
+ lexHex:
+ n = 0;
+ for (i = 0; (i < nDigits) && (src < end); i++) {
+ uintN digit;
+ c = *src++;
+ if (!isASCIIHexDigit(c, &digit)) {
+ /*
+ * Back off to accepting the original '\'
+ * as a literal
+ */
+ src -= i + 1;
+ n = '\\';
+ break;
+ }
+ n = (n << 4) | digit;
+ }
+ thisCh = (jschar)n;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ /*
+ * This is a non-ECMA extension - decimal escapes (in this
+ * case, octal!) are supposed to be an error inside class
+ * ranges, but supported here for backwards compatibility.
+ */
+ n = JS7_UNDEC(c);
+ c = *src;
+ if ('0' <= c && c <= '7') {
+ src++;
+ n = 8 * n + JS7_UNDEC(c);
+ c = *src;
+ if ('0' <= c && c <= '7') {
+ src++;
+ i = 8 * n + JS7_UNDEC(c);
+ if (i <= 0377)
+ n = i;
+ else
+ src--;
+ }
+ }
+ thisCh = (jschar)n;
+ break;
+
+ case 'd':
+ AddCharacterRangeToCharSet(charSet, '0', '9');
+ continue; /* don't need range processing */
+ case 'D':
+ AddCharacterRangeToCharSet(charSet, 0, '0' - 1);
+ AddCharacterRangeToCharSet(charSet,
+ (jschar)('9' + 1),
+ (jschar)charSet->length);
+ continue;
+ case 's':
+ AddCharacterRanges(charSet, WhiteSpaceRanges,
+ WhiteSpaceRanges + JS_ARRAY_LENGTH(WhiteSpaceRanges));
+ continue;
+ case 'S':
+ AddInvertedCharacterRanges(charSet, WhiteSpaceRanges,
+ WhiteSpaceRanges + JS_ARRAY_LENGTH(WhiteSpaceRanges));
+ continue;
+ case 'w':
+ AddCharacterRanges(charSet, WordRanges,
+ WordRanges + JS_ARRAY_LENGTH(WordRanges));
+ continue;
+ case 'W':
+ AddInvertedCharacterRanges(charSet, WordRanges,
+ WordRanges + JS_ARRAY_LENGTH(WordRanges));
+ continue;
+ default:
+ thisCh = c;
+ break;
+
+ }
+ break;
+
+ default:
+ thisCh = *src++;
+ break;
+
+ }
+ if (inRange) {
+ if (gData->regexp->flags & JSREG_FOLD) {
+ int i;
+
+ JS_ASSERT(rangeStart <= thisCh);
+ for (i = rangeStart; i <= thisCh; i++) {
+ jschar uch, dch;
+
+ AddCharacterToCharSet(charSet, i);
+ uch = upcase(i);
+ dch = downcase(i);
+ if (i != uch)
+ AddCharacterToCharSet(charSet, uch);
+ if (i != dch)
+ AddCharacterToCharSet(charSet, dch);
+ }
+ } else {
+ AddCharacterRangeToCharSet(charSet, rangeStart, thisCh);
+ }
+ inRange = JS_FALSE;
+ } else {
+ if (gData->regexp->flags & JSREG_FOLD) {
+ AddCharacterToCharSet(charSet, upcase(thisCh));
+ AddCharacterToCharSet(charSet, downcase(thisCh));
+ } else {
+ AddCharacterToCharSet(charSet, thisCh);
+ }
+ if (src < end - 1) {
+ if (*src == '-') {
+ ++src;
+ inRange = JS_TRUE;
+ rangeStart = thisCh;
+ }
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+void
+js_DestroyRegExp(JSContext *cx, JSRegExp *re)
+{
+ if (JS_ATOMIC_DECREMENT(&re->nrefs) == 0) {
+#ifdef JS_TRACER
+ /* Don't reuse this compiled code for some new regexp at same addr. */
+ Fragment* fragment = JS_TRACE_MONITOR(cx).reFragmento->getLoop(re);
+ if (fragment)
+ fragment->blacklist();
+#endif
+ if (re->classList) {
+ uintN i;
+ for (i = 0; i < re->classCount; i++) {
+ if (re->classList[i].converted)
+ JS_free(cx, re->classList[i].u.bits);
+ re->classList[i].u.bits = NULL;
+ }
+ JS_free(cx, re->classList);
+ }
+ JS_free(cx, re);
+ }
+}
+
+static JSBool
+ReallocStateStack(REGlobalData *gData)
+{
+ size_t limit = gData->stateStackLimit;
+ size_t sz = sizeof(REProgState) * limit;
+
+ JS_ARENA_GROW_CAST(gData->stateStack, REProgState *,
+ &gData->cx->regexpPool, sz, sz);
+ if (!gData->stateStack) {
+ js_ReportOutOfScriptQuota(gData->cx);
+ gData->ok = JS_FALSE;
+ return JS_FALSE;
+ }
+ gData->stateStackLimit = limit + limit;
+ return JS_TRUE;
+}
+
+#define PUSH_STATE_STACK(data) \
+ JS_BEGIN_MACRO \
+ ++(data)->stateStackTop; \
+ if ((data)->stateStackTop == (data)->stateStackLimit && \
+ !ReallocStateStack((data))) { \
+ return NULL; \
+ } \
+ JS_END_MACRO
+
+/*
+ * Apply the current op against the given input to see if it's going to match
+ * or fail. Return false if we don't get a match, true if we do. If updatecp is
+ * true, then update the current state's cp. Always update startpc to the next
+ * op.
+ */
+static JS_ALWAYS_INLINE REMatchState *
+SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op,
+ jsbytecode **startpc, JSBool updatecp)
+{
+ REMatchState *result = NULL;
+ jschar matchCh;
+ size_t parenIndex;
+ size_t offset, length, index;
+ jsbytecode *pc = *startpc; /* pc has already been incremented past op */
+ jschar *source;
+ const jschar *startcp = x->cp;
+ jschar ch;
+ RECharSet *charSet;
+
+#ifdef REGEXP_DEBUG
+ const char *opname = reop_names[op];
+ re_debug("\n%06d: %*s%s", pc - gData->regexp->program,
+ gData->stateStackTop * 2, "", opname);
+#endif
+ switch (op) {
+ case REOP_EMPTY:
+ result = x;
+ break;
+ case REOP_BOL:
+ if (x->cp != gData->cpbegin) {
+ if (!gData->cx->regExpStatics.multiline &&
+ !(gData->regexp->flags & JSREG_MULTILINE)) {
+ break;
+ }
+ if (!RE_IS_LINE_TERM(x->cp[-1]))
+ break;
+ }
+ result = x;
+ break;
+ case REOP_EOL:
+ if (x->cp != gData->cpend) {
+ if (!gData->cx->regExpStatics.multiline &&
+ !(gData->regexp->flags & JSREG_MULTILINE)) {
+ break;
+ }
+ if (!RE_IS_LINE_TERM(*x->cp))
+ break;
+ }
+ result = x;
+ break;
+ case REOP_WBDRY:
+ if ((x->cp == gData->cpbegin || !JS_ISWORD(x->cp[-1])) ^
+ !(x->cp != gData->cpend && JS_ISWORD(*x->cp))) {
+ result = x;
+ }
+ break;
+ case REOP_WNONBDRY:
+ if ((x->cp == gData->cpbegin || !JS_ISWORD(x->cp[-1])) ^
+ (x->cp != gData->cpend && JS_ISWORD(*x->cp))) {
+ result = x;
+ }
+ break;
+ case REOP_DOT:
+ if (x->cp != gData->cpend && !RE_IS_LINE_TERM(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_DIGIT:
+ if (x->cp != gData->cpend && JS7_ISDEC(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_NONDIGIT:
+ if (x->cp != gData->cpend && !JS7_ISDEC(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_ALNUM:
+ if (x->cp != gData->cpend && JS_ISWORD(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_NONALNUM:
+ if (x->cp != gData->cpend && !JS_ISWORD(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_SPACE:
+ if (x->cp != gData->cpend && JS_ISSPACE(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_NONSPACE:
+ if (x->cp != gData->cpend && !JS_ISSPACE(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_BACKREF:
+ pc = ReadCompactIndex(pc, &parenIndex);
+ JS_ASSERT(parenIndex < gData->regexp->parenCount);
+ result = BackrefMatcher(gData, x, parenIndex);
+ break;
+ case REOP_FLAT:
+ pc = ReadCompactIndex(pc, &offset);
+ JS_ASSERT(offset < JSSTRING_LENGTH(gData->regexp->source));
+ pc = ReadCompactIndex(pc, &length);
+ JS_ASSERT(1 <= length);
+ JS_ASSERT(length <= JSSTRING_LENGTH(gData->regexp->source) - offset);
+ if (length <= (size_t)(gData->cpend - x->cp)) {
+ source = JSSTRING_CHARS(gData->regexp->source) + offset;
+ re_debug_chars(source, length);
+ for (index = 0; index != length; index++) {
+ if (source[index] != x->cp[index])
+ return NULL;
+ }
+ x->cp += length;
+ result = x;
+ }
+ break;
+ case REOP_FLAT1:
+ matchCh = *pc++;
+ re_debug(" '%c' == '%c'", (char)matchCh, (char)*x->cp);
+ if (x->cp != gData->cpend && *x->cp == matchCh) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_FLATi:
+ pc = ReadCompactIndex(pc, &offset);
+ JS_ASSERT(offset < JSSTRING_LENGTH(gData->regexp->source));
+ pc = ReadCompactIndex(pc, &length);
+ JS_ASSERT(1 <= length);
+ JS_ASSERT(length <= JSSTRING_LENGTH(gData->regexp->source) - offset);
+ source = JSSTRING_CHARS(gData->regexp->source);
+ result = FlatNIMatcher(gData, x, source + offset, length);
+ break;
+ case REOP_FLAT1i:
+ matchCh = *pc++;
+ if (x->cp != gData->cpend && upcase(*x->cp) == upcase(matchCh)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_UCFLAT1:
+ matchCh = GET_ARG(pc);
+ re_debug(" '%c' == '%c'", (char)matchCh, (char)*x->cp);
+ pc += ARG_LEN;
+ if (x->cp != gData->cpend && *x->cp == matchCh) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_UCFLAT1i:
+ matchCh = GET_ARG(pc);
+ pc += ARG_LEN;
+ if (x->cp != gData->cpend && upcase(*x->cp) == upcase(matchCh)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_CLASS:
+ pc = ReadCompactIndex(pc, &index);
+ JS_ASSERT(index < gData->regexp->classCount);
+ if (x->cp != gData->cpend) {
+ charSet = &gData->regexp->classList[index];
+ JS_ASSERT(charSet->converted);
+ ch = *x->cp;
+ index = ch >> 3;
+ if (charSet->length != 0 &&
+ ch <= charSet->length &&
+ (charSet->u.bits[index] & (1 << (ch & 0x7)))) {
+ result = x;
+ result->cp++;
+ }
+ }
+ break;
+ case REOP_NCLASS:
+ pc = ReadCompactIndex(pc, &index);
+ JS_ASSERT(index < gData->regexp->classCount);
+ if (x->cp != gData->cpend) {
+ charSet = &gData->regexp->classList[index];
+ JS_ASSERT(charSet->converted);
+ ch = *x->cp;
+ index = ch >> 3;
+ if (charSet->length == 0 ||
+ ch > charSet->length ||
+ !(charSet->u.bits[index] & (1 << (ch & 0x7)))) {
+ result = x;
+ result->cp++;
+ }
+ }
+ break;
+
+ default:
+ JS_ASSERT(JS_FALSE);
+ }
+ if (result) {
+ if (!updatecp)
+ x->cp = startcp;
+ *startpc = pc;
+ re_debug(" * ");
+ return result;
+ }
+ x->cp = startcp;
+ return NULL;
+}
+
+static JS_ALWAYS_INLINE REMatchState *
+ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
+{
+ REMatchState *result = NULL;
+ REBackTrackData *backTrackData;
+ jsbytecode *nextpc, *testpc;
+ REOp nextop;
+ RECapture *cap;
+ REProgState *curState;
+ const jschar *startcp;
+ size_t parenIndex, k;
+ size_t parenSoFar = 0;
+
+ jschar matchCh1, matchCh2;
+ RECharSet *charSet;
+
+ JSBool anchor;
+ jsbytecode *pc = gData->regexp->program;
+ REOp op = (REOp) *pc++;
+
+ /*
+ * If the first node is a simple match, step the index into the string
+ * until that match is made, or fail if it can't be found at all.
+ */
+ if (REOP_IS_SIMPLE(op) && !(gData->regexp->flags & JSREG_STICKY)) {
+ anchor = JS_FALSE;
+ while (x->cp <= gData->cpend) {
+ nextpc = pc; /* reset back to start each time */
+ result = SimpleMatch(gData, x, op, &nextpc, JS_TRUE);
+ if (result) {
+ anchor = JS_TRUE;
+ x = result;
+ pc = nextpc; /* accept skip to next opcode */
+ op = (REOp) *pc++;
+ JS_ASSERT(op < REOP_LIMIT);
+ break;
+ }
+ gData->skipped++;
+ x->cp++;
+ }
+ if (!anchor)
+ goto bad;
+ }
+
+ for (;;) {
+#ifdef REGEXP_DEBUG
+ const char *opname = reop_names[op];
+ re_debug("\n%06d: %*s%s", pc - gData->regexp->program,
+ gData->stateStackTop * 2, "", opname);
+#endif
+ if (REOP_IS_SIMPLE(op)) {
+ result = SimpleMatch(gData, x, op, &pc, JS_TRUE);
+ } else {
+ curState = &gData->stateStack[gData->stateStackTop];
+ switch (op) {
+ case REOP_END:
+ goto good;
+ case REOP_ALTPREREQ2:
+ nextpc = pc + GET_OFFSET(pc); /* start of next op */
+ pc += ARG_LEN;
+ matchCh2 = GET_ARG(pc);
+ pc += ARG_LEN;
+ k = GET_ARG(pc);
+ pc += ARG_LEN;
+
+ if (x->cp != gData->cpend) {
+ if (*x->cp == matchCh2)
+ goto doAlt;
+
+ charSet = &gData->regexp->classList[k];
+ if (!charSet->converted && !ProcessCharSet(gData, charSet))
+ goto bad;
+ matchCh1 = *x->cp;
+ k = matchCh1 >> 3;
+ if ((charSet->length == 0 ||
+ matchCh1 > charSet->length ||
+ !(charSet->u.bits[k] & (1 << (matchCh1 & 0x7)))) ^
+ charSet->sense) {
+ goto doAlt;
+ }
+ }
+ result = NULL;
+ break;
+
+ case REOP_ALTPREREQ:
+ nextpc = pc + GET_OFFSET(pc); /* start of next op */
+ pc += ARG_LEN;
+ matchCh1 = GET_ARG(pc);
+ pc += ARG_LEN;
+ matchCh2 = GET_ARG(pc);
+ pc += ARG_LEN;
+ if (x->cp == gData->cpend ||
+ (*x->cp != matchCh1 && *x->cp != matchCh2)) {
+ result = NULL;
+ break;
+ }
+ /* else false thru... */
+
+ case REOP_ALT:
+ doAlt:
+ nextpc = pc + GET_OFFSET(pc); /* start of next alternate */
+ pc += ARG_LEN; /* start of this alternate */
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ op = (REOp) *pc++;
+ startcp = x->cp;
+ if (REOP_IS_SIMPLE(op)) {
+ if (!SimpleMatch(gData, x, op, &pc, JS_TRUE)) {
+ op = (REOp) *nextpc++;
+ pc = nextpc;
+ continue;
+ }
+ result = x;
+ op = (REOp) *pc++;
+ }
+ nextop = (REOp) *nextpc++;
+ if (!PushBackTrackState(gData, nextop, nextpc, x, startcp, 0, 0))
+ goto bad;
+ continue;
+
+ /*
+ * Occurs at (successful) end of REOP_ALT,
+ */
+ case REOP_JUMP:
+ /*
+ * If we have not gotten a result here, it is because of an
+ * empty match. Do the same thing REOP_EMPTY would do.
+ */
+ if (!result)
+ result = x;
+
+ --gData->stateStackTop;
+ pc += GET_OFFSET(pc);
+ op = (REOp) *pc++;
+ continue;
+
+ /*
+ * Occurs at last (successful) end of REOP_ALT,
+ */
+ case REOP_ENDALT:
+ /*
+ * If we have not gotten a result here, it is because of an
+ * empty match. Do the same thing REOP_EMPTY would do.
+ */
+ if (!result)
+ result = x;
+
+ --gData->stateStackTop;
+ op = (REOp) *pc++;
+ continue;
+
+ case REOP_LPAREN:
+ pc = ReadCompactIndex(pc, &parenIndex);
+ re_debug("[ %lu ]", (unsigned long) parenIndex);
+ JS_ASSERT(parenIndex < gData->regexp->parenCount);
+ if (parenIndex + 1 > parenSoFar)
+ parenSoFar = parenIndex + 1;
+ x->parens[parenIndex].index = x->cp - gData->cpbegin;
+ x->parens[parenIndex].length = 0;
+ op = (REOp) *pc++;
+ continue;
+
+ case REOP_RPAREN:
+ {
+ ptrdiff_t delta;
+
+ pc = ReadCompactIndex(pc, &parenIndex);
+ JS_ASSERT(parenIndex < gData->regexp->parenCount);
+ cap = &x->parens[parenIndex];
+ delta = x->cp - (gData->cpbegin + cap->index);
+ cap->length = (delta < 0) ? 0 : (size_t) delta;
+ op = (REOp) *pc++;
+
+ if (!result)
+ result = x;
+ continue;
+ }
+ case REOP_ASSERT:
+ nextpc = pc + GET_OFFSET(pc); /* start of term after ASSERT */
+ pc += ARG_LEN; /* start of ASSERT child */
+ op = (REOp) *pc++;
+ testpc = pc;
+ if (REOP_IS_SIMPLE(op) &&
+ !SimpleMatch(gData, x, op, &testpc, JS_FALSE)) {
+ result = NULL;
+ break;
+ }
+ curState->u.assertion.top =
+ (char *)gData->backTrackSP - (char *)gData->backTrackStack;
+ curState->u.assertion.sz = gData->cursz;
+ curState->index = x->cp - gData->cpbegin;
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ if (!PushBackTrackState(gData, REOP_ASSERTTEST,
+ nextpc, x, x->cp, 0, 0)) {
+ goto bad;
+ }
+ continue;
+
+ case REOP_ASSERT_NOT:
+ nextpc = pc + GET_OFFSET(pc);
+ pc += ARG_LEN;
+ op = (REOp) *pc++;
+ testpc = pc;
+ if (REOP_IS_SIMPLE(op) /* Note - fail to fail! */ &&
+ SimpleMatch(gData, x, op, &testpc, JS_FALSE) &&
+ *testpc == REOP_ASSERTNOTTEST) {
+ result = NULL;
+ break;
+ }
+ curState->u.assertion.top
+ = (char *)gData->backTrackSP -
+ (char *)gData->backTrackStack;
+ curState->u.assertion.sz = gData->cursz;
+ curState->index = x->cp - gData->cpbegin;
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ if (!PushBackTrackState(gData, REOP_ASSERTNOTTEST,
+ nextpc, x, x->cp, 0, 0)) {
+ goto bad;
+ }
+ continue;
+
+ case REOP_ASSERTTEST:
+ --gData->stateStackTop;
+ --curState;
+ x->cp = gData->cpbegin + curState->index;
+ gData->backTrackSP =
+ (REBackTrackData *) ((char *)gData->backTrackStack +
+ curState->u.assertion.top);
+ gData->cursz = curState->u.assertion.sz;
+ if (result)
+ result = x;
+ break;
+
+ case REOP_ASSERTNOTTEST:
+ --gData->stateStackTop;
+ --curState;
+ x->cp = gData->cpbegin + curState->index;
+ gData->backTrackSP =
+ (REBackTrackData *) ((char *)gData->backTrackStack +
+ curState->u.assertion.top);
+ gData->cursz = curState->u.assertion.sz;
+ result = (!result) ? x : NULL;
+ break;
+ case REOP_STAR:
+ curState->u.quantifier.min = 0;
+ curState->u.quantifier.max = (uintN)-1;
+ goto quantcommon;
+ case REOP_PLUS:
+ curState->u.quantifier.min = 1;
+ curState->u.quantifier.max = (uintN)-1;
+ goto quantcommon;
+ case REOP_OPT:
+ curState->u.quantifier.min = 0;
+ curState->u.quantifier.max = 1;
+ goto quantcommon;
+ case REOP_QUANT:
+ pc = ReadCompactIndex(pc, &k);
+ curState->u.quantifier.min = k;
+ pc = ReadCompactIndex(pc, &k);
+ /* max is k - 1 to use one byte for (uintN)-1 sentinel. */
+ curState->u.quantifier.max = k - 1;
+ JS_ASSERT(curState->u.quantifier.min
+ <= curState->u.quantifier.max);
+ quantcommon:
+ if (curState->u.quantifier.max == 0) {
+ pc = pc + GET_OFFSET(pc);
+ op = (REOp) *pc++;
+ result = x;
+ continue;
+ }
+ /* Step over <next> */
+ nextpc = pc + ARG_LEN;
+ op = (REOp) *nextpc++;
+ startcp = x->cp;
+ if (REOP_IS_SIMPLE(op)) {
+ if (!SimpleMatch(gData, x, op, &nextpc, JS_TRUE)) {
+ if (curState->u.quantifier.min == 0)
+ result = x;
+ else
+ result = NULL;
+ pc = pc + GET_OFFSET(pc);
+ break;
+ }
+ op = (REOp) *nextpc++;
+ result = x;
+ }
+ curState->index = startcp - gData->cpbegin;
+ curState->continue_op = REOP_REPEAT;
+ curState->continue_pc = pc;
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ if (curState->u.quantifier.min == 0 &&
+ !PushBackTrackState(gData, REOP_REPEAT, pc, x, startcp,
+ 0, 0)) {
+ goto bad;
+ }
+ pc = nextpc;
+ continue;
+
+ case REOP_ENDCHILD: /* marks the end of a quantifier child */
+ pc = curState[-1].continue_pc;
+ op = (REOp) curState[-1].continue_op;
+
+ if (!result)
+ result = x;
+ continue;
+
+ case REOP_REPEAT:
+ --curState;
+ do {
+ --gData->stateStackTop;
+ if (!result) {
+ /* Failed, see if we have enough children. */
+ if (curState->u.quantifier.min == 0)
+ goto repeatDone;
+ goto break_switch;
+ }
+ if (curState->u.quantifier.min == 0 &&
+ x->cp == gData->cpbegin + curState->index) {
+ /* matched an empty string, that'll get us nowhere */
+ result = NULL;
+ goto break_switch;
+ }
+ if (curState->u.quantifier.min != 0)
+ curState->u.quantifier.min--;
+ if (curState->u.quantifier.max != (uintN) -1)
+ curState->u.quantifier.max--;
+ if (curState->u.quantifier.max == 0)
+ goto repeatDone;
+ nextpc = pc + ARG_LEN;
+ nextop = (REOp) *nextpc;
+ startcp = x->cp;
+ if (REOP_IS_SIMPLE(nextop)) {
+ nextpc++;
+ if (!SimpleMatch(gData, x, nextop, &nextpc, JS_TRUE)) {
+ if (curState->u.quantifier.min == 0)
+ goto repeatDone;
+ result = NULL;
+ goto break_switch;
+ }
+ result = x;
+ }
+ curState->index = startcp - gData->cpbegin;
+ PUSH_STATE_STACK(gData);
+ if (curState->u.quantifier.min == 0 &&
+ !PushBackTrackState(gData, REOP_REPEAT,
+ pc, x, startcp,
+ curState->parenSoFar,
+ parenSoFar -
+ curState->parenSoFar)) {
+ goto bad;
+ }
+ } while (*nextpc == REOP_ENDCHILD);
+ pc = nextpc;
+ op = (REOp) *pc++;
+ parenSoFar = curState->parenSoFar;
+ continue;
+
+ repeatDone:
+ result = x;
+ pc += GET_OFFSET(pc);
+ goto break_switch;
+
+ case REOP_MINIMALSTAR:
+ curState->u.quantifier.min = 0;
+ curState->u.quantifier.max = (uintN)-1;
+ goto minimalquantcommon;
+ case REOP_MINIMALPLUS:
+ curState->u.quantifier.min = 1;
+ curState->u.quantifier.max = (uintN)-1;
+ goto minimalquantcommon;
+ case REOP_MINIMALOPT:
+ curState->u.quantifier.min = 0;
+ curState->u.quantifier.max = 1;
+ goto minimalquantcommon;
+ case REOP_MINIMALQUANT:
+ pc = ReadCompactIndex(pc, &k);
+ curState->u.quantifier.min = k;
+ pc = ReadCompactIndex(pc, &k);
+ /* See REOP_QUANT comments about k - 1. */
+ curState->u.quantifier.max = k - 1;
+ JS_ASSERT(curState->u.quantifier.min
+ <= curState->u.quantifier.max);
+ minimalquantcommon:
+ curState->index = x->cp - gData->cpbegin;
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ if (curState->u.quantifier.min != 0) {
+ curState->continue_op = REOP_MINIMALREPEAT;
+ curState->continue_pc = pc;
+ /* step over <next> */
+ pc += OFFSET_LEN;
+ op = (REOp) *pc++;
+ } else {
+ if (!PushBackTrackState(gData, REOP_MINIMALREPEAT,
+ pc, x, x->cp, 0, 0)) {
+ goto bad;
+ }
+ --gData->stateStackTop;
+ pc = pc + GET_OFFSET(pc);
+ op = (REOp) *pc++;
+ }
+ continue;
+
+ case REOP_MINIMALREPEAT:
+ --gData->stateStackTop;
+ --curState;
+
+ re_debug("{%d,%d}", curState->u.quantifier.min,
+ curState->u.quantifier.max);
+#define PREPARE_REPEAT() \
+ JS_BEGIN_MACRO \
+ curState->index = x->cp - gData->cpbegin; \
+ curState->continue_op = REOP_MINIMALREPEAT; \
+ curState->continue_pc = pc; \
+ pc += ARG_LEN; \
+ for (k = curState->parenSoFar; k < parenSoFar; k++) \
+ x->parens[k].index = -1; \
+ PUSH_STATE_STACK(gData); \
+ op = (REOp) *pc++; \
+ JS_ASSERT(op < REOP_LIMIT); \
+ JS_END_MACRO
+
+ if (!result) {
+ re_debug(" - ");
+ /*
+ * Non-greedy failure - try to consume another child.
+ */
+ if (curState->u.quantifier.max == (uintN) -1 ||
+ curState->u.quantifier.max > 0) {
+ PREPARE_REPEAT();
+ continue;
+ }
+ /* Don't need to adjust pc since we're going to pop. */
+ break;
+ }
+ if (curState->u.quantifier.min == 0 &&
+ x->cp == gData->cpbegin + curState->index) {
+ /* Matched an empty string, that'll get us nowhere. */
+ result = NULL;
+ break;
+ }
+ if (curState->u.quantifier.min != 0)
+ curState->u.quantifier.min--;
+ if (curState->u.quantifier.max != (uintN) -1)
+ curState->u.quantifier.max--;
+ if (curState->u.quantifier.min != 0) {
+ PREPARE_REPEAT();
+ continue;
+ }
+ curState->index = x->cp - gData->cpbegin;
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ if (!PushBackTrackState(gData, REOP_MINIMALREPEAT,
+ pc, x, x->cp,
+ curState->parenSoFar,
+ parenSoFar - curState->parenSoFar)) {
+ goto bad;
+ }
+ --gData->stateStackTop;
+ pc = pc + GET_OFFSET(pc);
+ op = (REOp) *pc++;
+ JS_ASSERT(op < REOP_LIMIT);
+ continue;
+ default:
+ JS_ASSERT(JS_FALSE);
+ result = NULL;
+ }
+ break_switch:;
+ }
+
+ /*
+ * If the match failed and there's a backtrack option, take it.
+ * Otherwise this is a complete and utter failure.
+ */
+ if (!result) {
+ if (gData->cursz == 0)
+ return NULL;
+ if (!JS_CHECK_OPERATION_LIMIT(gData->cx, JSOW_JUMP)) {
+ gData->ok = JS_FALSE;
+ return NULL;
+ }
+
+ /* Potentially detect explosive regex here. */
+ gData->backTrackCount++;
+ if (gData->backTrackLimit &&
+ gData->backTrackCount >= gData->backTrackLimit) {
+ JS_ReportErrorNumber(gData->cx, js_GetErrorMessage, NULL,
+ JSMSG_REGEXP_TOO_COMPLEX);
+ gData->ok = JS_FALSE;
+ return NULL;
+ }
+
+ backTrackData = gData->backTrackSP;
+ gData->cursz = backTrackData->sz;
+ gData->backTrackSP =
+ (REBackTrackData *) ((char *)backTrackData - backTrackData->sz);
+ x->cp = backTrackData->cp;
+ pc = backTrackData->backtrack_pc;
+ op = (REOp) backTrackData->backtrack_op;
+ JS_ASSERT(op < REOP_LIMIT);
+ gData->stateStackTop = backTrackData->saveStateStackTop;
+ JS_ASSERT(gData->stateStackTop);
+
+ memcpy(gData->stateStack, backTrackData + 1,
+ sizeof(REProgState) * backTrackData->saveStateStackTop);
+ curState = &gData->stateStack[gData->stateStackTop - 1];
+
+ if (backTrackData->parenCount) {
+ memcpy(&x->parens[backTrackData->parenIndex],
+ (char *)(backTrackData + 1) +
+ sizeof(REProgState) * backTrackData->saveStateStackTop,
+ sizeof(RECapture) * backTrackData->parenCount);
+ parenSoFar = backTrackData->parenIndex + backTrackData->parenCount;
+ } else {
+ for (k = curState->parenSoFar; k < parenSoFar; k++)
+ x->parens[k].index = -1;
+ parenSoFar = curState->parenSoFar;
+ }
+
+ re_debug("\tBT_Pop: %ld,%ld",
+ (unsigned long) backTrackData->parenIndex,
+ (unsigned long) backTrackData->parenCount);
+ continue;
+ }
+ x = result;
+
+ /*
+ * Continue with the expression.
+ */
+ op = (REOp)*pc++;
+ JS_ASSERT(op < REOP_LIMIT);
+ }
+
+bad:
+ re_debug("\n");
+ return NULL;
+
+good:
+ re_debug("\n");
+ return x;
+}
+
+static REMatchState *
+MatchRegExp(REGlobalData *gData, REMatchState *x)
+{
+ REMatchState *result;
+ const jschar *cp = x->cp;
+ const jschar *cp2;
+ uintN j;
+#ifdef JS_TRACER
+ Fragment *fragment;
+
+ /* Run with native regexp if possible. */
+ if (TRACING_ENABLED(gData->cx) &&
+ ((fragment = JS_TRACE_MONITOR(gData->cx).reFragmento->getLoop(gData->regexp)) != NULL)
+ && fragment->code() && !fragment->isBlacklisted()) {
+ union { NIns *code; REMatchState* (FASTCALL *func)(void*, void*); } u;
+ u.code = fragment->code();
+ REMatchState *lr;
+ gData->skipped = (ptrdiff_t) x->cp;
+
+ debug_only_v(printf("entering REGEXP trace at %s:%u@%u, code: %p\n",
+ gData->cx->fp->script->filename,
+ js_FramePCToLineNumber(gData->cx, gData->cx->fp),
+ FramePCOffset(gData->cx->fp),
+ fragment->code()););
+
+#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
+ SIMULATE_FASTCALL(lr, x, gData, u.func);
+#else
+ lr = u.func(x, gData);
+#endif
+
+ debug_only_v(printf("leaving REGEXP trace\n"));
+
+ gData->skipped = ((const jschar *) gData->skipped) - cp;
+ return lr;
+ }
+#endif
+ /*
+ * Have to include the position beyond the last character
+ * in order to detect end-of-input/line condition.
+ */
+ for (cp2 = cp; cp2 <= gData->cpend; cp2++) {
+ gData->skipped = cp2 - cp;
+ x->cp = cp2;
+ for (j = 0; j < gData->regexp->parenCount; j++)
+ x->parens[j].index = -1;
+ result = ExecuteREBytecode(gData, x);
+ if (!gData->ok || result || (gData->regexp->flags & JSREG_STICKY))
+ return result;
+ gData->backTrackSP = gData->backTrackStack;
+ gData->cursz = 0;
+ gData->stateStackTop = 0;
+ cp2 = cp + gData->skipped;
+ }
+ return NULL;
+}
+
+#define MIN_BACKTRACK_LIMIT 400000
+
+static REMatchState *
+InitMatch(JSContext *cx, REGlobalData *gData, JSRegExp *re, size_t length)
+{
+ REMatchState *result;
+ uintN i;
+
+ gData->backTrackStackSize = INITIAL_BACKTRACK;
+ JS_ARENA_ALLOCATE_CAST(gData->backTrackStack, REBackTrackData *,
+ &cx->regexpPool,
+ INITIAL_BACKTRACK);
+ if (!gData->backTrackStack)
+ goto bad;
+
+ gData->backTrackSP = gData->backTrackStack;
+ gData->cursz = 0;
+ gData->backTrackCount = 0;
+ gData->backTrackLimit = 0;
+ if (JS_GetOptions(cx) & JSOPTION_RELIMIT) {
+ gData->backTrackLimit = length * length * length; /* O(n^3) */
+ if (gData->backTrackLimit < MIN_BACKTRACK_LIMIT)
+ gData->backTrackLimit = MIN_BACKTRACK_LIMIT;
+ }
+
+ gData->stateStackLimit = INITIAL_STATESTACK;
+ JS_ARENA_ALLOCATE_CAST(gData->stateStack, REProgState *,
+ &cx->regexpPool,
+ sizeof(REProgState) * INITIAL_STATESTACK);
+ if (!gData->stateStack)
+ goto bad;
+
+ gData->stateStackTop = 0;
+ gData->cx = cx;
+ gData->regexp = re;
+ gData->ok = JS_TRUE;
+
+ JS_ARENA_ALLOCATE_CAST(result, REMatchState *,
+ &cx->regexpPool,
+ offsetof(REMatchState, parens)
+ + re->parenCount * sizeof(RECapture));
+ if (!result)
+ goto bad;
+
+ for (i = 0; i < re->classCount; i++) {
+ if (!re->classList[i].converted &&
+ !ProcessCharSet(gData, &re->classList[i])) {
+ return NULL;
+ }
+ }
+
+ return result;
+
+bad:
+ js_ReportOutOfScriptQuota(cx);
+ gData->ok = JS_FALSE;
+ return NULL;
+}
+
+JSBool
+js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
+ JSBool test, jsval *rval)
+{
+ REGlobalData gData;
+ REMatchState *x, *result;
+
+ const jschar *cp, *ep;
+ size_t i, length, start;
+ JSSubString *morepar;
+ JSBool ok;
+ JSRegExpStatics *res;
+ ptrdiff_t matchlen;
+ uintN num, morenum;
+ JSString *parstr, *matchstr;
+ JSObject *obj;
+
+ RECapture *parsub = NULL;
+ void *mark;
+ int64 *timestamp;
+
+ /*
+ * It's safe to load from cp because JSStrings have a zero at the end,
+ * and we never let cp get beyond cpend.
+ */
+ start = *indexp;
+ JSSTRING_CHARS_AND_LENGTH(str, cp, length);
+ if (start > length)
+ start = length;
+ gData.cpbegin = cp;
+ gData.cpend = cp + length;
+ cp += start;
+ gData.start = start;
+ gData.skipped = 0;
+
+ if (!cx->regexpPool.first.next) {
+ /*
+ * The first arena in the regexpPool must have a timestamp at its base.
+ */
+ JS_ARENA_ALLOCATE_CAST(timestamp, int64 *,
+ &cx->regexpPool, sizeof *timestamp);
+ if (!timestamp)
+ return JS_FALSE;
+ *timestamp = JS_Now();
+ }
+ mark = JS_ARENA_MARK(&cx->regexpPool);
+
+ x = InitMatch(cx, &gData, re, length);
+
+ if (!x) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ x->cp = cp;
+
+ /*
+ * Call the recursive matcher to do the real work. Return null on mismatch
+ * whether testing or not. On match, return an extended Array object.
+ */
+ result = MatchRegExp(&gData, x);
+ ok = gData.ok;
+ if (!ok)
+ goto out;
+ if (!result) {
+ *rval = JSVAL_NULL;
+ goto out;
+ }
+ cp = result->cp;
+ i = cp - gData.cpbegin;
+ *indexp = i;
+ matchlen = i - (start + gData.skipped);
+ ep = cp;
+ cp -= matchlen;
+
+ if (test) {
+ /*
+ * Testing for a match and updating cx->regExpStatics: don't allocate
+ * an array object, do return true.
+ */
+ *rval = JSVAL_TRUE;
+
+ /* Avoid warning. (gcc doesn't detect that obj is needed iff !test); */
+ obj = NULL;
+ } else {
+ /*
+ * The array returned on match has element 0 bound to the matched
+ * string, elements 1 through state.parenCount bound to the paren
+ * matches, an index property telling the length of the left context,
+ * and an input property referring to the input string.
+ */
+ obj = js_NewSlowArrayObject(cx);
+ if (!obj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ *rval = OBJECT_TO_JSVAL(obj);
+
+#define DEFVAL(val, id) { \
+ ok = js_DefineProperty(cx, obj, id, val, \
+ JS_PropertyStub, JS_PropertyStub, \
+ JSPROP_ENUMERATE, NULL); \
+ if (!ok) { \
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL; \
+ cx->weakRoots.newborn[GCX_STRING] = NULL; \
+ goto out; \
+ } \
+}
+
+ matchstr = js_NewStringCopyN(cx, cp, matchlen);
+ if (!matchstr) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ ok = JS_FALSE;
+ goto out;
+ }
+ DEFVAL(STRING_TO_JSVAL(matchstr), INT_TO_JSID(0));
+ }
+
+ res = &cx->regExpStatics;
+ res->input = str;
+ res->parenCount = re->parenCount;
+ if (re->parenCount == 0) {
+ res->lastParen = js_EmptySubString;
+ } else {
+ for (num = 0; num < re->parenCount; num++) {
+ parsub = &result->parens[num];
+ if (num < 9) {
+ if (parsub->index == -1) {
+ res->parens[num].chars = NULL;
+ res->parens[num].length = 0;
+ } else {
+ res->parens[num].chars = gData.cpbegin + parsub->index;
+ res->parens[num].length = parsub->length;
+ }
+ } else {
+ morenum = num - 9;
+ morepar = res->moreParens;
+ if (!morepar) {
+ res->moreLength = 10;
+ morepar = (JSSubString*)
+ JS_malloc(cx, 10 * sizeof(JSSubString));
+ } else if (morenum >= res->moreLength) {
+ res->moreLength += 10;
+ morepar = (JSSubString*)
+ JS_realloc(cx, morepar,
+ res->moreLength * sizeof(JSSubString));
+ }
+ if (!morepar) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ cx->weakRoots.newborn[GCX_STRING] = NULL;
+ ok = JS_FALSE;
+ goto out;
+ }
+ res->moreParens = morepar;
+ if (parsub->index == -1) {
+ morepar[morenum].chars = NULL;
+ morepar[morenum].length = 0;
+ } else {
+ morepar[morenum].chars = gData.cpbegin + parsub->index;
+ morepar[morenum].length = parsub->length;
+ }
+ }
+ if (test)
+ continue;
+ if (parsub->index == -1) {
+ ok = js_DefineProperty(cx, obj, INT_TO_JSID(num + 1),
+ JSVAL_VOID, NULL, NULL,
+ JSPROP_ENUMERATE, NULL);
+ } else {
+ parstr = js_NewStringCopyN(cx, gData.cpbegin + parsub->index,
+ parsub->length);
+ if (!parstr) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ cx->weakRoots.newborn[GCX_STRING] = NULL;
+ ok = JS_FALSE;
+ goto out;
+ }
+ ok = js_DefineProperty(cx, obj, INT_TO_JSID(num + 1),
+ STRING_TO_JSVAL(parstr), NULL, NULL,
+ JSPROP_ENUMERATE, NULL);
+ }
+ if (!ok) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ cx->weakRoots.newborn[GCX_STRING] = NULL;
+ goto out;
+ }
+ }
+ if (parsub->index == -1) {
+ res->lastParen = js_EmptySubString;
+ } else {
+ res->lastParen.chars = gData.cpbegin + parsub->index;
+ res->lastParen.length = parsub->length;
+ }
+ }
+
+ if (!test) {
+ /*
+ * Define the index and input properties last for better for/in loop
+ * order (so they come after the elements).
+ */
+ DEFVAL(INT_TO_JSVAL(start + gData.skipped),
+ ATOM_TO_JSID(cx->runtime->atomState.indexAtom));
+ DEFVAL(STRING_TO_JSVAL(str),
+ ATOM_TO_JSID(cx->runtime->atomState.inputAtom));
+ }
+
+#undef DEFVAL
+
+ res->lastMatch.chars = cp;
+ res->lastMatch.length = matchlen;
+
+ /*
+ * For JS1.3 and ECMAv2, emulate Perl5 exactly:
+ *
+ * js1.3 "hi", "hi there" "hihitherehi therebye"
+ */
+ res->leftContext.chars = JSSTRING_CHARS(str);
+ res->leftContext.length = start + gData.skipped;
+ res->rightContext.chars = ep;
+ res->rightContext.length = gData.cpend - ep;
+
+out:
+ JS_ARENA_RELEASE(&cx->regexpPool, mark);
+ return ok;
+}
+
+/************************************************************************/
+
+#define REGEXP_PROP_ATTRS (JSPROP_PERMANENT | JSPROP_SHARED)
+#define RO_REGEXP_PROP_ATTRS (REGEXP_PROP_ATTRS | JSPROP_READONLY)
+
+static JSPropertySpec regexp_props[] = {
+ {"source", REGEXP_SOURCE, RO_REGEXP_PROP_ATTRS,0,0},
+ {"global", REGEXP_GLOBAL, RO_REGEXP_PROP_ATTRS,0,0},
+ {"ignoreCase", REGEXP_IGNORE_CASE, RO_REGEXP_PROP_ATTRS,0,0},
+ {"lastIndex", REGEXP_LAST_INDEX, REGEXP_PROP_ATTRS,0,0},
+ {"multiline", REGEXP_MULTILINE, RO_REGEXP_PROP_ATTRS,0,0},
+ {"sticky", REGEXP_STICKY, RO_REGEXP_PROP_ATTRS,0,0},
+ {0,0,0,0,0}
+};
+
+static JSBool
+regexp_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsint slot;
+ JSRegExp *re;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ while (OBJ_GET_CLASS(cx, obj) != &js_RegExpClass) {
+ obj = OBJ_GET_PROTO(cx, obj);
+ if (!obj)
+ return JS_TRUE;
+ }
+ slot = JSVAL_TO_INT(id);
+ if (slot == REGEXP_LAST_INDEX)
+ return JS_GetReservedSlot(cx, obj, 0, vp);
+
+ JS_LOCK_OBJ(cx, obj);
+ re = (JSRegExp *) JS_GetPrivate(cx, obj);
+ if (re) {
+ switch (slot) {
+ case REGEXP_SOURCE:
+ *vp = STRING_TO_JSVAL(re->source);
+ break;
+ case REGEXP_GLOBAL:
+ *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_GLOB) != 0);
+ break;
+ case REGEXP_IGNORE_CASE:
+ *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_FOLD) != 0);
+ break;
+ case REGEXP_MULTILINE:
+ *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_MULTILINE) != 0);
+ break;
+ case REGEXP_STICKY:
+ *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_STICKY) != 0);
+ break;
+ }
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_TRUE;
+}
+
+static JSBool
+regexp_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSBool ok;
+ jsint slot;
+ jsdouble lastIndex;
+
+ ok = JS_TRUE;
+ if (!JSVAL_IS_INT(id))
+ return ok;
+ while (OBJ_GET_CLASS(cx, obj) != &js_RegExpClass) {
+ obj = OBJ_GET_PROTO(cx, obj);
+ if (!obj)
+ return JS_TRUE;
+ }
+ slot = JSVAL_TO_INT(id);
+ if (slot == REGEXP_LAST_INDEX) {
+ if (!JS_ValueToNumber(cx, *vp, &lastIndex))
+ return JS_FALSE;
+ lastIndex = js_DoubleToInteger(lastIndex);
+ ok = JS_NewNumberValue(cx, lastIndex, vp) &&
+ JS_SetReservedSlot(cx, obj, 0, *vp);
+ }
+ return ok;
+}
+
+/*
+ * RegExp class static properties and their Perl counterparts:
+ *
+ * RegExp.input $_
+ * RegExp.multiline $*
+ * RegExp.lastMatch $&
+ * RegExp.lastParen $+
+ * RegExp.leftContext $`
+ * RegExp.rightContext $'
+ */
+enum regexp_static_tinyid {
+ REGEXP_STATIC_INPUT = -1,
+ REGEXP_STATIC_MULTILINE = -2,
+ REGEXP_STATIC_LAST_MATCH = -3,
+ REGEXP_STATIC_LAST_PAREN = -4,
+ REGEXP_STATIC_LEFT_CONTEXT = -5,
+ REGEXP_STATIC_RIGHT_CONTEXT = -6
+};
+
+JSBool
+js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res)
+{
+ JS_ClearRegExpStatics(cx);
+ return js_AddRoot(cx, &res->input, "res->input");
+}
+
+void
+js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res)
+{
+ if (res->moreParens) {
+ JS_free(cx, res->moreParens);
+ res->moreParens = NULL;
+ }
+ js_RemoveRoot(cx->runtime, &res->input);
+}
+
+static JSBool
+regexp_static_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsint slot;
+ JSRegExpStatics *res;
+ JSString *str;
+ JSSubString *sub;
+
+ res = &cx->regExpStatics;
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ slot = JSVAL_TO_INT(id);
+ switch (slot) {
+ case REGEXP_STATIC_INPUT:
+ *vp = res->input ? STRING_TO_JSVAL(res->input)
+ : JS_GetEmptyStringValue(cx);
+ return JS_TRUE;
+ case REGEXP_STATIC_MULTILINE:
+ *vp = BOOLEAN_TO_JSVAL(res->multiline);
+ return JS_TRUE;
+ case REGEXP_STATIC_LAST_MATCH:
+ sub = &res->lastMatch;
+ break;
+ case REGEXP_STATIC_LAST_PAREN:
+ sub = &res->lastParen;
+ break;
+ case REGEXP_STATIC_LEFT_CONTEXT:
+ sub = &res->leftContext;
+ break;
+ case REGEXP_STATIC_RIGHT_CONTEXT:
+ sub = &res->rightContext;
+ break;
+ default:
+ sub = REGEXP_PAREN_SUBSTRING(res, slot);
+ break;
+ }
+ str = js_NewStringCopyN(cx, sub->chars, sub->length);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+regexp_static_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSRegExpStatics *res;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ res = &cx->regExpStatics;
+ /* XXX use if-else rather than switch to keep MSVC1.52 from crashing */
+ if (JSVAL_TO_INT(id) == REGEXP_STATIC_INPUT) {
+ if (!JSVAL_IS_STRING(*vp) &&
+ !JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp)) {
+ return JS_FALSE;
+ }
+ res->input = JSVAL_TO_STRING(*vp);
+ } else if (JSVAL_TO_INT(id) == REGEXP_STATIC_MULTILINE) {
+ if (!JSVAL_IS_BOOLEAN(*vp) &&
+ !JS_ConvertValue(cx, *vp, JSTYPE_BOOLEAN, vp)) {
+ return JS_FALSE;
+ }
+ res->multiline = JSVAL_TO_BOOLEAN(*vp);
+ }
+ return JS_TRUE;
+}
+#define REGEXP_STATIC_PROP_ATTRS (REGEXP_PROP_ATTRS | JSPROP_ENUMERATE)
+#define RO_REGEXP_STATIC_PROP_ATTRS (REGEXP_STATIC_PROP_ATTRS | JSPROP_READONLY)
+
+static JSPropertySpec regexp_static_props[] = {
+ {"input",
+ REGEXP_STATIC_INPUT,
+ REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_setProperty},
+ {"multiline",
+ REGEXP_STATIC_MULTILINE,
+ REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_setProperty},
+ {"lastMatch",
+ REGEXP_STATIC_LAST_MATCH,
+ RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"lastParen",
+ REGEXP_STATIC_LAST_PAREN,
+ RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"leftContext",
+ REGEXP_STATIC_LEFT_CONTEXT,
+ RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"rightContext",
+ REGEXP_STATIC_RIGHT_CONTEXT,
+ RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+
+ /* XXX should have block scope and local $1, etc. */
+ {"$1", 0, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$2", 1, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$3", 2, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$4", 3, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$5", 4, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$6", 5, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$7", 6, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$8", 7, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$9", 8, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+
+ {0,0,0,0,0}
+};
+
+static void
+regexp_finalize(JSContext *cx, JSObject *obj)
+{
+ JSRegExp *re;
+
+ re = (JSRegExp *) JS_GetPrivate(cx, obj);
+ if (!re)
+ return;
+ js_DestroyRegExp(cx, re);
+}
+
+/* Forward static prototype. */
+static JSBool
+regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ JSBool test, jsval *rval);
+
+static JSBool
+regexp_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ return regexp_exec_sub(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv,
+ JS_FALSE, rval);
+}
+
+#if JS_HAS_XDR
+
+#include "jsxdrapi.h"
+
+static JSBool
+regexp_xdrObject(JSXDRState *xdr, JSObject **objp)
+{
+ JSRegExp *re;
+ JSString *source;
+ uint32 flagsword;
+ JSObject *obj;
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ re = (JSRegExp *) JS_GetPrivate(xdr->cx, *objp);
+ if (!re)
+ return JS_FALSE;
+ source = re->source;
+ flagsword = (uint32)re->flags;
+ }
+ if (!JS_XDRString(xdr, &source) ||
+ !JS_XDRUint32(xdr, &flagsword)) {
+ return JS_FALSE;
+ }
+ if (xdr->mode == JSXDR_DECODE) {
+ obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ STOBJ_CLEAR_PARENT(obj);
+ STOBJ_CLEAR_PROTO(obj);
+ re = js_NewRegExp(xdr->cx, NULL, source, (uint8)flagsword, JS_FALSE);
+ if (!re)
+ return JS_FALSE;
+ if (!JS_SetPrivate(xdr->cx, obj, re) ||
+ !js_SetLastIndex(xdr->cx, obj, 0)) {
+ js_DestroyRegExp(xdr->cx, re);
+ return JS_FALSE;
+ }
+ *objp = obj;
+ }
+ return JS_TRUE;
+}
+
+#else /* !JS_HAS_XDR */
+
+#define regexp_xdrObject NULL
+
+#endif /* !JS_HAS_XDR */
+
+static void
+regexp_trace(JSTracer *trc, JSObject *obj)
+{
+ JSRegExp *re;
+
+ re = (JSRegExp *) JS_GetPrivate(trc->context, obj);
+ if (re && re->source)
+ JS_CALL_STRING_TRACER(trc, re->source, "source");
+}
+
+JSClass js_RegExpClass = {
+ js_RegExp_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
+ JS_PropertyStub, JS_PropertyStub,
+ regexp_getProperty, regexp_setProperty,
+ JS_EnumerateStub, JS_ResolveStub,
+ JS_ConvertStub, regexp_finalize,
+ NULL, NULL,
+ regexp_call, NULL,
+ regexp_xdrObject, NULL,
+ JS_CLASS_TRACE(regexp_trace), 0
+};
+
+static const jschar empty_regexp_ucstr[] = {'(', '?', ':', ')', 0};
+
+JSBool
+js_regexp_toString(JSContext *cx, JSObject *obj, jsval *vp)
+{
+ JSRegExp *re;
+ const jschar *source;
+ jschar *chars;
+ size_t length, nflags;
+ uintN flags;
+ JSString *str;
+
+ if (!JS_InstanceOf(cx, obj, &js_RegExpClass, vp + 2))
+ return JS_FALSE;
+ JS_LOCK_OBJ(cx, obj);
+ re = (JSRegExp *) JS_GetPrivate(cx, obj);
+ if (!re) {
+ JS_UNLOCK_OBJ(cx, obj);
+ *vp = STRING_TO_JSVAL(cx->runtime->emptyString);
+ return JS_TRUE;
+ }
+
+ JSSTRING_CHARS_AND_LENGTH(re->source, source, length);
+ if (length == 0) {
+ source = empty_regexp_ucstr;
+ length = JS_ARRAY_LENGTH(empty_regexp_ucstr) - 1;
+ }
+ length += 2;
+ nflags = 0;
+ for (flags = re->flags; flags != 0; flags &= flags - 1)
+ nflags++;
+ chars = (jschar*) JS_malloc(cx, (length + nflags + 1) * sizeof(jschar));
+ if (!chars) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+ }
+
+ chars[0] = '/';
+ js_strncpy(&chars[1], source, length - 2);
+ chars[length-1] = '/';
+ if (nflags) {
+ if (re->flags & JSREG_GLOB)
+ chars[length++] = 'g';
+ if (re->flags & JSREG_FOLD)
+ chars[length++] = 'i';
+ if (re->flags & JSREG_MULTILINE)
+ chars[length++] = 'm';
+ if (re->flags & JSREG_STICKY)
+ chars[length++] = 'y';
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ chars[length] = 0;
+
+ str = js_NewString(cx, chars, length);
+ if (!str) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+regexp_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && js_regexp_toString(cx, obj, vp);
+}
+
+static JSBool
+regexp_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSString *opt, *str;
+ JSRegExp *oldre, *re;
+ JSBool ok, ok2;
+ JSObject *obj2;
+ size_t length, nbytes;
+ const jschar *cp, *start, *end;
+ jschar *nstart, *ncp, *tmp;
+
+ if (!JS_InstanceOf(cx, obj, &js_RegExpClass, argv))
+ return JS_FALSE;
+ opt = NULL;
+ if (argc == 0) {
+ str = cx->runtime->emptyString;
+ } else {
+ if (JSVAL_IS_OBJECT(argv[0])) {
+ /*
+ * If we get passed in a RegExp object we construct a new
+ * RegExp that is a duplicate of it by re-compiling the
+ * original source code. ECMA requires that it be an error
+ * here if the flags are specified. (We must use the flags
+ * from the original RegExp also).
+ */
+ obj2 = JSVAL_TO_OBJECT(argv[0]);
+ if (obj2 && OBJ_GET_CLASS(cx, obj2) == &js_RegExpClass) {
+ if (argc >= 2 && !JSVAL_IS_VOID(argv[1])) { /* 'flags' passed */
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_NEWREGEXP_FLAGGED);
+ return JS_FALSE;
+ }
+ JS_LOCK_OBJ(cx, obj2);
+ re = (JSRegExp *) JS_GetPrivate(cx, obj2);
+ if (!re) {
+ JS_UNLOCK_OBJ(cx, obj2);
+ return JS_FALSE;
+ }
+ re = js_NewRegExp(cx, NULL, re->source, re->flags, JS_FALSE);
+ JS_UNLOCK_OBJ(cx, obj2);
+ goto created;
+ }
+ }
+ str = js_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(str);
+ if (argc > 1) {
+ if (JSVAL_IS_VOID(argv[1])) {
+ opt = NULL;
+ } else {
+ opt = js_ValueToString(cx, argv[1]);
+ if (!opt)
+ return JS_FALSE;
+ argv[1] = STRING_TO_JSVAL(opt);
+ }
+ }
+
+ /* Escape any naked slashes in the regexp source. */
+ JSSTRING_CHARS_AND_LENGTH(str, start, length);
+ end = start + length;
+ nstart = ncp = NULL;
+ for (cp = start; cp < end; cp++) {
+ if (*cp == '/' && (cp == start || cp[-1] != '\\')) {
+ nbytes = (++length + 1) * sizeof(jschar);
+ if (!nstart) {
+ nstart = (jschar *) JS_malloc(cx, nbytes);
+ if (!nstart)
+ return JS_FALSE;
+ ncp = nstart + (cp - start);
+ js_strncpy(nstart, start, cp - start);
+ } else {
+ tmp = (jschar *) JS_realloc(cx, nstart, nbytes);
+ if (!tmp) {
+ JS_free(cx, nstart);
+ return JS_FALSE;
+ }
+ ncp = tmp + (ncp - nstart);
+ nstart = tmp;
+ }
+ *ncp++ = '\\';
+ }
+ if (nstart)
+ *ncp++ = *cp;
+ }
+
+ if (nstart) {
+ /* Don't forget to store the backstop after the new string. */
+ JS_ASSERT((size_t)(ncp - nstart) == length);
+ *ncp = 0;
+ str = js_NewString(cx, nstart, length);
+ if (!str) {
+ JS_free(cx, nstart);
+ return JS_FALSE;
+ }
+ argv[0] = STRING_TO_JSVAL(str);
+ }
+ }
+
+ re = js_NewRegExpOpt(cx, str, opt, JS_FALSE);
+created:
+ if (!re)
+ return JS_FALSE;
+ JS_LOCK_OBJ(cx, obj);
+ oldre = (JSRegExp *) JS_GetPrivate(cx, obj);
+ ok = JS_SetPrivate(cx, obj, re);
+ ok2 = js_SetLastIndex(cx, obj, 0);
+ JS_UNLOCK_OBJ(cx, obj);
+ if (!ok) {
+ js_DestroyRegExp(cx, re);
+ return JS_FALSE;
+ }
+ if (oldre)
+ js_DestroyRegExp(cx, oldre);
+ *rval = OBJECT_TO_JSVAL(obj);
+ return ok2;
+}
+
+static JSBool
+regexp_compile(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && regexp_compile_sub(cx, obj, argc, vp + 2, vp);
+}
+
+static JSBool
+regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ JSBool test, jsval *rval)
+{
+ JSBool ok, sticky;
+ JSRegExp *re;
+ jsdouble lastIndex;
+ JSString *str;
+ size_t i;
+
+ ok = JS_InstanceOf(cx, obj, &js_RegExpClass, argv);
+ if (!ok)
+ return JS_FALSE;
+ JS_LOCK_OBJ(cx, obj);
+ re = (JSRegExp *) JS_GetPrivate(cx, obj);
+ if (!re) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_TRUE;
+ }
+
+ /* NB: we must reach out: after this paragraph, in order to drop re. */
+ HOLD_REGEXP(cx, re);
+ sticky = (re->flags & JSREG_STICKY) != 0;
+ if (re->flags & (JSREG_GLOB | JSREG_STICKY)) {
+ ok = js_GetLastIndex(cx, obj, &lastIndex);
+ } else {
+ lastIndex = 0;
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ if (!ok)
+ goto out;
+
+ /* Now that obj is unlocked, it's safe to (potentially) grab the GC lock. */
+ if (argc == 0) {
+ str = cx->regExpStatics.input;
+ if (!str) {
+ const char *bytes = js_GetStringBytes(cx, re->source);
+
+ if (bytes) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_NO_INPUT,
+ bytes,
+ (re->flags & JSREG_GLOB) ? "g" : "",
+ (re->flags & JSREG_FOLD) ? "i" : "",
+ (re->flags & JSREG_MULTILINE) ? "m" : "",
+ (re->flags & JSREG_STICKY) ? "y" : "");
+ }
+ ok = JS_FALSE;
+ goto out;
+ }
+ } else {
+ str = js_ValueToString(cx, argv[0]);
+ if (!str) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ argv[0] = STRING_TO_JSVAL(str);
+ }
+
+ if (lastIndex < 0 || JSSTRING_LENGTH(str) < lastIndex) {
+ ok = js_SetLastIndex(cx, obj, 0);
+ *rval = JSVAL_NULL;
+ } else {
+ i = (size_t) lastIndex;
+ ok = js_ExecuteRegExp(cx, re, str, &i, test, rval);
+ if (ok &&
+ ((re->flags & JSREG_GLOB) || (*rval != JSVAL_NULL && sticky))) {
+ ok = js_SetLastIndex(cx, obj, (*rval == JSVAL_NULL) ? 0 : i);
+ }
+ }
+
+out:
+ DROP_REGEXP(cx, re);
+ return ok;
+}
+
+static JSBool
+regexp_exec(JSContext *cx, uintN argc, jsval *vp)
+{
+ return regexp_exec_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, JS_FALSE,
+ vp);
+}
+
+static JSBool
+regexp_test(JSContext *cx, uintN argc, jsval *vp)
+{
+ if (!regexp_exec_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, JS_TRUE, vp))
+ return JS_FALSE;
+ if (*vp != JSVAL_TRUE)
+ *vp = JSVAL_FALSE;
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static jsint FASTCALL
+Regexp_p_test(JSContext* cx, JSObject* regexp, JSString* str)
+{
+ jsval vp[3] = { JSVAL_NULL, OBJECT_TO_JSVAL(regexp), STRING_TO_JSVAL(str) };
+ if (!regexp_exec_sub(cx, regexp, 1, vp + 2, JS_TRUE, vp))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ return *vp == JSVAL_TRUE;
+}
+
+JS_DEFINE_TRCINFO_1(regexp_test,
+ (3, (static, BOOL_FAIL, Regexp_p_test, CONTEXT, THIS, STRING, 1, 1)))
+
+#endif
+
+static JSFunctionSpec regexp_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, regexp_toString, 0,0),
+#endif
+ JS_FN(js_toString_str, regexp_toString, 0,0),
+ JS_FN("compile", regexp_compile, 2,0),
+ JS_FN("exec", regexp_exec, 1,0),
+ JS_TN("test", regexp_test, 1,0, regexp_test_trcinfo),
+ JS_FS_END
+};
+
+static JSBool
+RegExp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ /*
+ * If first arg is regexp and no flags are given, just return the arg.
+ * (regexp_compile_sub detects the regexp + flags case and throws a
+ * TypeError.) See 10.15.3.1.
+ */
+ if ((argc < 2 || JSVAL_IS_VOID(argv[1])) &&
+ !JSVAL_IS_PRIMITIVE(argv[0]) &&
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[0])) == &js_RegExpClass) {
+ *rval = argv[0];
+ return JS_TRUE;
+ }
+
+ /* Otherwise, replace obj with a new RegExp object. */
+ obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+
+ /*
+ * regexp_compile_sub does not use rval to root its temporaries so we
+ * can use it to root obj.
+ */
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+ return regexp_compile_sub(cx, obj, argc, argv, rval);
+}
+
+JSObject *
+js_InitRegExpClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto, *ctor;
+ jsval rval;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_RegExpClass, RegExp, 1,
+ regexp_props, regexp_methods,
+ regexp_static_props, NULL);
+
+ if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
+ return NULL;
+ if (!JS_AliasProperty(cx, ctor, "input", "$_") ||
+ !JS_AliasProperty(cx, ctor, "multiline", "$*") ||
+ !JS_AliasProperty(cx, ctor, "lastMatch", "$&") ||
+ !JS_AliasProperty(cx, ctor, "lastParen", "$+") ||
+ !JS_AliasProperty(cx, ctor, "leftContext", "$`") ||
+ !JS_AliasProperty(cx, ctor, "rightContext", "$'")) {
+ goto bad;
+ }
+
+ /* Give RegExp.prototype private data so it matches the empty string. */
+ if (!regexp_compile_sub(cx, proto, 0, NULL, &rval))
+ goto bad;
+ return proto;
+
+bad:
+ JS_DeleteProperty(cx, obj, js_RegExpClass.name);
+ return NULL;
+}
+
+JSObject *
+js_NewRegExpObject(JSContext *cx, JSTokenStream *ts,
+ jschar *chars, size_t length, uintN flags)
+{
+ JSString *str;
+ JSObject *obj;
+ JSRegExp *re;
+ JSTempValueRooter tvr;
+
+ str = js_NewStringCopyN(cx, chars, length);
+ if (!str)
+ return NULL;
+ re = js_NewRegExp(cx, ts, str, flags, JS_FALSE);
+ if (!re)
+ return NULL;
+ JS_PUSH_TEMP_ROOT_STRING(cx, str, &tvr);
+ obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL, 0);
+ if (!obj || !JS_SetPrivate(cx, obj, re)) {
+ js_DestroyRegExp(cx, re);
+ obj = NULL;
+ }
+ if (obj && !js_SetLastIndex(cx, obj, 0))
+ obj = NULL;
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return obj;
+}
+
+JSObject *
+js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent)
+{
+ JSObject *clone;
+ JSRegExp *re;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
+ clone = js_NewObject(cx, &js_RegExpClass, NULL, parent, 0);
+ if (!clone)
+ return NULL;
+ re = (JSRegExp *) JS_GetPrivate(cx, obj);
+ if (!JS_SetPrivate(cx, clone, re) || !js_SetLastIndex(cx, clone, 0)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+ }
+ HOLD_REGEXP(cx, re);
+ return clone;
+}
+
+JSBool
+js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex)
+{
+ jsval v;
+
+ return JS_GetReservedSlot(cx, obj, 0, &v) &&
+ JS_ValueToNumber(cx, v, lastIndex);
+}
+
+JSBool
+js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex)
+{
+ jsval v;
+
+ return JS_NewNumberValue(cx, lastIndex, &v) &&
+ JS_SetReservedSlot(cx, obj, 0, v);
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.h b/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.h
new file mode 100644
index 0000000..12d74a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.h
@@ -0,0 +1,192 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsregexp_h___
+#define jsregexp_h___
+/*
+ * JS regular expression interface.
+ */
+#include <stddef.h>
+#include "jspubtd.h"
+#include "jsstr.h"
+
+#ifdef JS_THREADSAFE
+#include "jsdhash.h"
+#endif
+
+JS_BEGIN_EXTERN_C
+
+struct JSRegExpStatics {
+ JSString *input; /* input string to match (perl $_, GC root) */
+ JSBool multiline; /* whether input contains newlines (perl $*) */
+ uint16 parenCount; /* number of valid elements in parens[] */
+ uint16 moreLength; /* number of allocated elements in moreParens */
+ JSSubString parens[9]; /* last set of parens matched (perl $1, $2) */
+ JSSubString *moreParens; /* null or realloc'd vector for $10, etc. */
+ JSSubString lastMatch; /* last string matched (perl $&) */
+ JSSubString lastParen; /* last paren matched (perl $+) */
+ JSSubString leftContext; /* input to left of last match (perl $`) */
+ JSSubString rightContext; /* input to right of last match (perl $') */
+};
+
+/*
+ * This struct holds a bitmap representation of a class from a regexp.
+ * There's a list of these referenced by the classList field in the JSRegExp
+ * struct below. The initial state has startIndex set to the offset in the
+ * original regexp source of the beginning of the class contents. The first
+ * use of the class converts the source representation into a bitmap.
+ *
+ */
+typedef struct RECharSet {
+ JSPackedBool converted;
+ JSPackedBool sense;
+ uint16 length;
+ union {
+ uint8 *bits;
+ struct {
+ size_t startIndex;
+ size_t length;
+ } src;
+ } u;
+} RECharSet;
+
+/*
+ * This macro is safe because moreParens is guaranteed to be allocated and big
+ * enough to hold parenCount, or else be null when parenCount is 0.
+ */
+#define REGEXP_PAREN_SUBSTRING(res, num) \
+ (((jsuint)(num) < (jsuint)(res)->parenCount) \
+ ? ((jsuint)(num) < 9) \
+ ? &(res)->parens[num] \
+ : &(res)->moreParens[(num) - 9] \
+ : &js_EmptySubString)
+
+typedef struct RENode RENode;
+
+struct JSRegExp {
+ jsrefcount nrefs; /* reference count */
+ uint16 flags; /* flags, see jsapi.h's JSREG_* defines */
+ size_t parenCount; /* number of parenthesized submatches */
+ size_t classCount; /* count [...] bitmaps */
+ RECharSet *classList; /* list of [...] bitmaps */
+ JSString *source; /* locked source string, sans // */
+ jsbytecode program[1]; /* regular expression bytecode */
+};
+
+extern JSRegExp *
+js_NewRegExp(JSContext *cx, JSTokenStream *ts,
+ JSString *str, uintN flags, JSBool flat);
+
+extern JSRegExp *
+js_NewRegExpOpt(JSContext *cx, JSString *str, JSString *opt, JSBool flat);
+
+#define HOLD_REGEXP(cx, re) JS_ATOMIC_INCREMENT(&(re)->nrefs)
+#define DROP_REGEXP(cx, re) js_DestroyRegExp(cx, re)
+
+extern void
+js_DestroyRegExp(JSContext *cx, JSRegExp *re);
+
+/*
+ * Execute re on input str at *indexp, returning null in *rval on mismatch.
+ * On match, return true if test is true, otherwise return an array object.
+ * Update *indexp and cx->regExpStatics always on match.
+ */
+extern JSBool
+js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
+ JSBool test, jsval *rval);
+
+/*
+ * These two add and remove GC roots, respectively, so their calls must be
+ * well-ordered.
+ */
+extern JSBool
+js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res);
+
+extern void
+js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res);
+
+#define VALUE_IS_REGEXP(cx, v) \
+ (JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) && \
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_RegExpClass)
+
+extern JSClass js_RegExpClass;
+
+enum regexp_tinyid {
+ REGEXP_SOURCE = -1,
+ REGEXP_GLOBAL = -2,
+ REGEXP_IGNORE_CASE = -3,
+ REGEXP_LAST_INDEX = -4,
+ REGEXP_MULTILINE = -5,
+ REGEXP_STICKY = -6
+};
+
+extern JSObject *
+js_InitRegExpClass(JSContext *cx, JSObject *obj);
+
+/*
+ * Export js_regexp_toString to the decompiler.
+ */
+extern JSBool
+js_regexp_toString(JSContext *cx, JSObject *obj, jsval *vp);
+
+/*
+ * Create, serialize/deserialize, or clone a RegExp object.
+ */
+extern JSObject *
+js_NewRegExpObject(JSContext *cx, JSTokenStream *ts,
+ jschar *chars, size_t length, uintN flags);
+
+extern JSBool
+js_XDRRegExp(JSXDRState *xdr, JSObject **objp);
+
+extern JSObject *
+js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent);
+
+/*
+ * Get and set the per-object (clone or clone-parent) lastIndex slot.
+ */
+extern JSBool
+js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex);
+
+extern JSBool
+js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex);
+
+JS_END_EXTERN_C
+
+#endif /* jsregexp_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsreops.tbl b/tools/node_modules/expresso/deps/jscoverage/js/jsreops.tbl
new file mode 100644
index 0000000..d7454c1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsreops.tbl
@@ -0,0 +1,145 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=0 ft=C:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "license"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "as is" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contentsof this file are subject to the Mozilla Public License Version
+ * 1.1 (the "license"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of thter (the "lgpl"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/* Note : contiguity of 'simple opcodes' is important for SimpleMatch() */
+
+/* match rest of input against rest of r.e. */
+REOP_DEF(REOP_EMPTY, "empty")
+/* beginning of input (or line if multiline) */
+REOP_DEF(REOP_BOL, "bol")
+/* end of input (or line if multiline) */
+REOP_DEF(REOP_EOL, "eol")
+/* match "" at word boundary */
+REOP_DEF(REOP_WBDRY, "wbdry")
+/* match "" at word non-boundary */
+REOP_DEF(REOP_WNONBDRY, "wnonbdry")
+/* stands for any character */
+REOP_DEF(REOP_DOT, "dot")
+/* match a digit char: [0-9] */
+REOP_DEF(REOP_DIGIT, "digit")
+/* match a non-digit char: [^0-9] */
+REOP_DEF(REOP_NONDIGIT, "nondigit")
+/* match an alphanumeric char: [0-9a-z_A-Z] */
+REOP_DEF(REOP_ALNUM, "alnum")
+/* match a non-alphanumeric char: [^0-9a-z_A-Z] */
+REOP_DEF(REOP_NONALNUM, "nonalnum")
+/* match a whitespace char */
+REOP_DEF(REOP_SPACE, "space")
+/* match a non-whitespace char */
+REOP_DEF(REOP_NONSPACE, "nonspace")
+/* back-reference (e.g., \1) to a parenthetical */
+REOP_DEF(REOP_BACKREF, "backref")
+/* match a flat string */
+REOP_DEF(REOP_FLAT, "flat")
+/* match a single char */
+REOP_DEF(REOP_FLAT1, "flat1")
+/* case-independent REOP_FLAT */
+REOP_DEF(REOP_FLATi, "flati")
+/* case-independent REOP_FLAT1 */
+REOP_DEF(REOP_FLAT1i, "flat1i")
+/* single Unicode char */
+REOP_DEF(REOP_UCFLAT1, "ucflat1")
+/* case-independent REOP_UCFLAT1 */
+REOP_DEF(REOP_UCFLAT1i, "ucflat1i")
+/* flat Unicode string; len immediate counts chars */
+REOP_DEF(REOP_UCFLAT, "ucflat")
+/* case-independent REOP_UCFLAT */
+REOP_DEF(REOP_UCFLATi, "ucflati")
+/* character class with index */
+REOP_DEF(REOP_CLASS, "class")
+/* negated character class with index */
+REOP_DEF(REOP_NCLASS, "nclass")
+
+/* NCLASS is considered to be the last "simple" op-code */
+
+
+/* alternative subexpressions in kid and next */
+REOP_DEF(REOP_ALT, "alt")
+/* quantified atom: atom{1,2} */
+REOP_DEF(REOP_QUANT, "quant")
+/* zero or more occurrences of kid */
+REOP_DEF(REOP_STAR, "star")
+/* one or more occurrences of kid */
+REOP_DEF(REOP_PLUS, "plus")
+/* optional subexpression in kid */
+REOP_DEF(REOP_OPT, "opt")
+/* left paren bytecode: kid is u.num'th sub-regexp */
+REOP_DEF(REOP_LPAREN, "lparen")
+/* right paren bytecode */
+REOP_DEF(REOP_RPAREN, "rparen")
+/* for deoptimized closure loops */
+REOP_DEF(REOP_JUMP, "jump")
+/* optimize .* to use a single opcode */
+REOP_DEF(REOP_DOTSTAR, "dotstar")
+/* non-capturing version of REOP_LPAREN */
+REOP_DEF(REOP_LPARENNON, "lparennon")
+/* zero width positive lookahead assertion */
+REOP_DEF(REOP_ASSERT, "assert")
+/* zero width negative lookahead assertion */
+REOP_DEF(REOP_ASSERT_NOT, "assert_not")
+/* sentinel at end of assertion child */
+REOP_DEF(REOP_ASSERTTEST, "asserttest")
+/* sentinel at end of !assertion child */
+REOP_DEF(REOP_ASSERTNOTTEST, "assertnottest")
+/* non-greedy version of * */
+REOP_DEF(REOP_MINIMALSTAR, "minimalstar")
+/* non-greedy version of + */
+REOP_DEF(REOP_MINIMALPLUS, "minimalplus")
+/* non-greedy version of ? */
+REOP_DEF(REOP_MINIMALOPT, "minimalopt")
+/* non-greedy version of {} */
+REOP_DEF(REOP_MINIMALQUANT, "minimalquant")
+/* sentinel at end of quantifier child */
+REOP_DEF(REOP_ENDCHILD, "endchild")
+/* directs execution of greedy quantifier */
+REOP_DEF(REOP_REPEAT, "repeat")
+/* directs execution of non-greedy quantifier */
+REOP_DEF(REOP_MINIMALREPEAT, "minimalrepeat")
+/* prerequisite for ALT, either of two chars */
+REOP_DEF(REOP_ALTPREREQ, "altprereq")
+/* prerequisite for ALT, a char or a class */
+REOP_DEF(REOP_ALTPREREQ2, "altprereq2")
+/* end of final alternate */
+REOP_DEF(REOP_ENDALT, "endalt")
+/* concatenation of terms (parse time only) */
+REOP_DEF(REOP_CONCAT, "concat")
+/* end of expression */
+REOP_DEF(REOP_END, "end")
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscan.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsscan.cpp
new file mode 100644
index 0000000..f112a9a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscan.cpp
@@ -0,0 +1,2017 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS lexical scanner.
+ */
+#include "jsstddef.h"
+#include <stdio.h> /* first to avoid trouble on some systems */
+#include <errno.h>
+#include <limits.h>
+#include <math.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsdtoa.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsemit.h"
+#include "jsexn.h"
+#include "jsnum.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsregexp.h"
+#include "jsscan.h"
+#include "jsscript.h"
+#include "jsstaticcheck.h"
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#define JS_KEYWORD(keyword, type, op, version) \
+ const char js_##keyword##_str[] = #keyword;
+#include "jskeyword.tbl"
+#undef JS_KEYWORD
+
+struct keyword {
+ const char *chars; /* C string with keyword text */
+ JSTokenType tokentype; /* JSTokenType */
+ JSOp op; /* JSOp */
+ JSVersion version; /* JSVersion */
+};
+
+static const struct keyword keyword_defs[] = {
+#define JS_KEYWORD(keyword, type, op, version) \
+ {js_##keyword##_str, type, op, version},
+#include "jskeyword.tbl"
+#undef JS_KEYWORD
+};
+
+#define KEYWORD_COUNT JS_ARRAY_LENGTH(keyword_defs)
+
+static const struct keyword *
+FindKeyword(const jschar *s, size_t length)
+{
+ register size_t i;
+ const struct keyword *kw;
+ const char *chars;
+
+ JS_ASSERT(length != 0);
+
+#define JSKW_LENGTH() length
+#define JSKW_AT(column) s[column]
+#define JSKW_GOT_MATCH(index) i = (index); goto got_match;
+#define JSKW_TEST_GUESS(index) i = (index); goto test_guess;
+#define JSKW_NO_MATCH() goto no_match;
+#include "jsautokw.h"
+#undef JSKW_NO_MATCH
+#undef JSKW_TEST_GUESS
+#undef JSKW_GOT_MATCH
+#undef JSKW_AT
+#undef JSKW_LENGTH
+
+ got_match:
+ return &keyword_defs[i];
+
+ test_guess:
+ kw = &keyword_defs[i];
+ chars = kw->chars;
+ do {
+ if (*s++ != (unsigned char)(*chars++))
+ goto no_match;
+ } while (--length != 0);
+ return kw;
+
+ no_match:
+ return NULL;
+}
+
+JSTokenType
+js_CheckKeyword(const jschar *str, size_t length)
+{
+ const struct keyword *kw;
+
+ JS_ASSERT(length != 0);
+ kw = FindKeyword(str, length);
+ return kw ? kw->tokentype : TOK_EOF;
+}
+
+JS_FRIEND_API(void)
+js_MapKeywords(void (*mapfun)(const char *))
+{
+ size_t i;
+
+ for (i = 0; i != KEYWORD_COUNT; ++i)
+ mapfun(keyword_defs[i].chars);
+}
+
+JSBool
+js_IsIdentifier(JSString *str)
+{
+ size_t length;
+ jschar c, *chars, *end;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ if (length == 0)
+ return JS_FALSE;
+ c = *chars;
+ if (!JS_ISIDSTART(c))
+ return JS_FALSE;
+ end = chars + length;
+ while (++chars != end) {
+ c = *chars;
+ if (!JS_ISIDENT(c))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+#define TBMIN 64
+
+static JSBool
+GrowTokenBuf(JSStringBuffer *sb, size_t newlength)
+{
+ JSContext *cx;
+ jschar *base;
+ ptrdiff_t offset, length;
+ size_t tbsize;
+ JSArenaPool *pool;
+
+ cx = (JSContext*) sb->data;
+ base = sb->base;
+ offset = PTRDIFF(sb->ptr, base, jschar);
+ pool = &cx->tempPool;
+ if (!base) {
+ tbsize = TBMIN * sizeof(jschar);
+ length = TBMIN - 1;
+ JS_ARENA_ALLOCATE_CAST(base, jschar *, pool, tbsize);
+ } else {
+ length = PTRDIFF(sb->limit, base, jschar);
+ if ((size_t)length >= ~(size_t)0 / sizeof(jschar)) {
+ base = NULL;
+ } else {
+ tbsize = (length + 1) * sizeof(jschar);
+ length += length + 1;
+ JS_ARENA_GROW_CAST(base, jschar *, pool, tbsize, tbsize);
+ }
+ }
+ if (!base) {
+ js_ReportOutOfScriptQuota(cx);
+ sb->base = STRING_BUFFER_ERROR_BASE;
+ return JS_FALSE;
+ }
+ sb->base = base;
+ sb->limit = base + length;
+ sb->ptr = base + offset;
+ return JS_TRUE;
+}
+
+JSBool
+js_InitTokenStream(JSContext *cx, JSTokenStream *ts,
+ const jschar *base, size_t length,
+ FILE *fp, const char *filename, uintN lineno)
+{
+ jschar *buf;
+ size_t nb;
+
+ JS_ASSERT_IF(fp, !base);
+ JS_ASSERT_IF(!base, length == 0);
+ nb = fp
+ ? 2 * JS_LINE_LIMIT * sizeof(jschar)
+ : JS_LINE_LIMIT * sizeof(jschar);
+ JS_ARENA_ALLOCATE_CAST(buf, jschar *, &cx->tempPool, nb);
+ if (!buf) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ memset(buf, 0, nb);
+ memset(ts, 0, sizeof(*ts));
+ ts->filename = filename;
+ ts->lineno = lineno;
+ ts->linebuf.base = ts->linebuf.limit = ts->linebuf.ptr = buf;
+ if (fp) {
+ ts->file = fp;
+ ts->userbuf.base = buf + JS_LINE_LIMIT;
+ ts->userbuf.ptr = ts->userbuf.limit = ts->userbuf.base + JS_LINE_LIMIT;
+ } else {
+ ts->userbuf.base = (jschar *)base;
+ ts->userbuf.limit = (jschar *)base + length;
+ ts->userbuf.ptr = (jschar *)base;
+ }
+ ts->tokenbuf.grow = GrowTokenBuf;
+ ts->tokenbuf.data = cx;
+ ts->listener = cx->debugHooks->sourceHandler;
+ ts->listenerData = cx->debugHooks->sourceHandlerData;
+ return JS_TRUE;
+}
+
+void
+js_CloseTokenStream(JSContext *cx, JSTokenStream *ts)
+{
+ if (ts->flags & TSF_OWNFILENAME)
+ JS_free(cx, (void *) ts->filename);
+}
+
+JS_FRIEND_API(int)
+js_fgets(char *buf, int size, FILE *file)
+{
+ int n, i, c;
+ JSBool crflag;
+
+ n = size - 1;
+ if (n < 0)
+ return -1;
+
+ crflag = JS_FALSE;
+ for (i = 0; i < n && (c = getc(file)) != EOF; i++) {
+ buf[i] = c;
+ if (c == '\n') { /* any \n ends a line */
+ i++; /* keep the \n; we know there is room for \0 */
+ break;
+ }
+ if (crflag) { /* \r not followed by \n ends line at the \r */
+ ungetc(c, file);
+ break; /* and overwrite c in buf with \0 */
+ }
+ crflag = (c == '\r');
+ }
+
+ buf[i] = '\0';
+ return i;
+}
+
+static int32
+GetChar(JSTokenStream *ts)
+{
+ int32 c;
+ ptrdiff_t i, j, len, olen;
+ JSBool crflag;
+ char cbuf[JS_LINE_LIMIT];
+ jschar *ubuf, *nl;
+
+ if (ts->ungetpos != 0) {
+ c = ts->ungetbuf[--ts->ungetpos];
+ } else {
+ if (ts->linebuf.ptr == ts->linebuf.limit) {
+ len = PTRDIFF(ts->userbuf.limit, ts->userbuf.ptr, jschar);
+ if (len <= 0) {
+ if (!ts->file) {
+ ts->flags |= TSF_EOF;
+ return EOF;
+ }
+
+ /* Fill ts->userbuf so that \r and \r\n convert to \n. */
+ crflag = (ts->flags & TSF_CRFLAG) != 0;
+ len = js_fgets(cbuf, JS_LINE_LIMIT - crflag, ts->file);
+ if (len <= 0) {
+ ts->flags |= TSF_EOF;
+ return EOF;
+ }
+ olen = len;
+ ubuf = ts->userbuf.base;
+ i = 0;
+ if (crflag) {
+ ts->flags &= ~TSF_CRFLAG;
+ if (cbuf[0] != '\n') {
+ ubuf[i++] = '\n';
+ len++;
+ ts->linepos--;
+ }
+ }
+ for (j = 0; i < len; i++, j++)
+ ubuf[i] = (jschar) (unsigned char) cbuf[j];
+ ts->userbuf.limit = ubuf + len;
+ ts->userbuf.ptr = ubuf;
+ }
+ if (ts->listener) {
+ ts->listener(ts->filename, ts->lineno, ts->userbuf.ptr, len,
+ &ts->listenerTSData, ts->listenerData);
+ }
+
+ nl = ts->saveEOL;
+ if (!nl) {
+ /*
+ * Any one of \n, \r, or \r\n ends a line (the longest
+ * match wins). Also allow the Unicode line and paragraph
+ * separators.
+ */
+ for (nl = ts->userbuf.ptr; nl < ts->userbuf.limit; nl++) {
+ /*
+ * Try to prevent value-testing on most characters by
+ * filtering out characters that aren't 000x or 202x.
+ */
+ if ((*nl & 0xDFD0) == 0) {
+ if (*nl == '\n')
+ break;
+ if (*nl == '\r') {
+ if (nl + 1 < ts->userbuf.limit && nl[1] == '\n')
+ nl++;
+ break;
+ }
+ if (*nl == LINE_SEPARATOR || *nl == PARA_SEPARATOR)
+ break;
+ }
+ }
+ }
+
+ /*
+ * If there was a line terminator, copy thru it into linebuf.
+ * Else copy JS_LINE_LIMIT-1 bytes into linebuf.
+ */
+ if (nl < ts->userbuf.limit)
+ len = PTRDIFF(nl, ts->userbuf.ptr, jschar) + 1;
+ if (len >= JS_LINE_LIMIT) {
+ len = JS_LINE_LIMIT - 1;
+ ts->saveEOL = nl;
+ } else {
+ ts->saveEOL = NULL;
+ }
+ js_strncpy(ts->linebuf.base, ts->userbuf.ptr, len);
+ ts->userbuf.ptr += len;
+ olen = len;
+
+ /*
+ * Make sure linebuf contains \n for EOL (don't do this in
+ * userbuf because the user's string might be readonly).
+ */
+ if (nl < ts->userbuf.limit) {
+ if (*nl == '\r') {
+ if (ts->linebuf.base[len-1] == '\r') {
+ /*
+ * Does the line segment end in \r? We must check
+ * for a \n at the front of the next segment before
+ * storing a \n into linebuf. This case matters
+ * only when we're reading from a file.
+ */
+ if (nl + 1 == ts->userbuf.limit && ts->file) {
+ len--;
+ ts->flags |= TSF_CRFLAG; /* clear NLFLAG? */
+ if (len == 0) {
+ /*
+ * This can happen when a segment ends in
+ * \r\r. Start over. ptr == limit in this
+ * case, so we'll fall into buffer-filling
+ * code.
+ */
+ return GetChar(ts);
+ }
+ } else {
+ ts->linebuf.base[len-1] = '\n';
+ }
+ }
+ } else if (*nl == '\n') {
+ if (nl > ts->userbuf.base &&
+ nl[-1] == '\r' &&
+ ts->linebuf.base[len-2] == '\r') {
+ len--;
+ JS_ASSERT(ts->linebuf.base[len] == '\n');
+ ts->linebuf.base[len-1] = '\n';
+ }
+ } else if (*nl == LINE_SEPARATOR || *nl == PARA_SEPARATOR) {
+ ts->linebuf.base[len-1] = '\n';
+ }
+ }
+
+ /* Reset linebuf based on adjusted segment length. */
+ ts->linebuf.limit = ts->linebuf.base + len;
+ ts->linebuf.ptr = ts->linebuf.base;
+
+ /* Update position of linebuf within physical userbuf line. */
+ if (!(ts->flags & TSF_NLFLAG))
+ ts->linepos += ts->linelen;
+ else
+ ts->linepos = 0;
+ if (ts->linebuf.limit[-1] == '\n')
+ ts->flags |= TSF_NLFLAG;
+ else
+ ts->flags &= ~TSF_NLFLAG;
+
+ /* Update linelen from original segment length. */
+ ts->linelen = olen;
+ }
+ c = *ts->linebuf.ptr++;
+ }
+ if (c == '\n')
+ ts->lineno++;
+ return c;
+}
+
+static void
+UngetChar(JSTokenStream *ts, int32 c)
+{
+ if (c == EOF)
+ return;
+ JS_ASSERT(ts->ungetpos < JS_ARRAY_LENGTH(ts->ungetbuf));
+ if (c == '\n')
+ ts->lineno--;
+ ts->ungetbuf[ts->ungetpos++] = (jschar)c;
+}
+
+static int32
+PeekChar(JSTokenStream *ts)
+{
+ int32 c;
+
+ c = GetChar(ts);
+ UngetChar(ts, c);
+ return c;
+}
+
+/*
+ * Peek n chars ahead into ts. Return true if n chars were read, false if
+ * there weren't enough characters in the input stream. This function cannot
+ * be used to peek into or past a newline.
+ */
+static JSBool
+PeekChars(JSTokenStream *ts, intN n, jschar *cp)
+{
+ intN i, j;
+ int32 c;
+
+ for (i = 0; i < n; i++) {
+ c = GetChar(ts);
+ if (c == EOF)
+ break;
+ if (c == '\n') {
+ UngetChar(ts, c);
+ break;
+ }
+ cp[i] = (jschar)c;
+ }
+ for (j = i - 1; j >= 0; j--)
+ UngetChar(ts, cp[j]);
+ return i == n;
+}
+
+static void
+SkipChars(JSTokenStream *ts, intN n)
+{
+ while (--n >= 0)
+ GetChar(ts);
+}
+
+static JSBool
+MatchChar(JSTokenStream *ts, int32 expect)
+{
+ int32 c;
+
+ c = GetChar(ts);
+ if (c == expect)
+ return JS_TRUE;
+ UngetChar(ts, c);
+ return JS_FALSE;
+}
+
+JSBool
+js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, JSParseNode *pn,
+ uintN flags, uintN errorNumber, ...)
+{
+ JSErrorReport report;
+ char *message;
+ size_t linelength;
+ jschar *linechars;
+ char *linebytes;
+ va_list ap;
+ JSBool warning, ok;
+ JSTokenPos *tp;
+ uintN index, i;
+ JSErrorReporter onError;
+
+ JS_ASSERT(ts->linebuf.limit < ts->linebuf.base + JS_LINE_LIMIT);
+
+ if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
+ return JS_TRUE;
+
+ memset(&report, 0, sizeof report);
+ report.flags = flags;
+ report.errorNumber = errorNumber;
+ message = NULL;
+ linechars = NULL;
+ linebytes = NULL;
+
+ MUST_FLOW_THROUGH("out");
+ va_start(ap, errorNumber);
+ ok = js_ExpandErrorArguments(cx, js_GetErrorMessage, NULL,
+ errorNumber, &message, &report, &warning,
+ !(flags & JSREPORT_UC), ap);
+ va_end(ap);
+ if (!ok) {
+ warning = JS_FALSE;
+ goto out;
+ }
+
+ report.filename = ts->filename;
+
+ if (pn) {
+ report.lineno = pn->pn_pos.begin.lineno;
+ if (report.lineno != ts->lineno)
+ goto report;
+ tp = &pn->pn_pos;
+ } else {
+ /* Point to the current token, not the next one to get. */
+ tp = &ts->tokens[ts->cursor].pos;
+ }
+ report.lineno = ts->lineno;
+ linelength = PTRDIFF(ts->linebuf.limit, ts->linebuf.base, jschar);
+ linechars = (jschar *)JS_malloc(cx, (linelength + 1) * sizeof(jschar));
+ if (!linechars) {
+ warning = JS_FALSE;
+ goto out;
+ }
+ memcpy(linechars, ts->linebuf.base, linelength * sizeof(jschar));
+ linechars[linelength] = 0;
+ linebytes = js_DeflateString(cx, linechars, linelength);
+ if (!linebytes) {
+ warning = JS_FALSE;
+ goto out;
+ }
+ report.linebuf = linebytes;
+
+ /*
+ * FIXME: What should instead happen here is that we should
+ * find error-tokens in userbuf, if !ts->file. That will
+ * allow us to deliver a more helpful error message, which
+ * includes all or part of the bad string or bad token. The
+ * code here yields something that looks truncated.
+ * See https://bugzilla.mozilla.org/show_bug.cgi?id=352970
+ */
+ index = 0;
+ if (tp->begin.lineno == tp->end.lineno) {
+ if (tp->begin.index < ts->linepos)
+ goto report;
+
+ index = tp->begin.index - ts->linepos;
+ }
+
+ report.tokenptr = report.linebuf + index;
+ report.uclinebuf = linechars;
+ report.uctokenptr = report.uclinebuf + index;
+
+ /*
+ * If there's a runtime exception type associated with this error
+ * number, set that as the pending exception. For errors occuring at
+ * compile time, this is very likely to be a JSEXN_SYNTAXERR.
+ *
+ * If an exception is thrown but not caught, the JSREPORT_EXCEPTION
+ * flag will be set in report.flags. Proper behavior for an error
+ * reporter is to ignore a report with this flag for all but top-level
+ * compilation errors. The exception will remain pending, and so long
+ * as the non-top-level "load", "eval", or "compile" native function
+ * returns false, the top-level reporter will eventually receive the
+ * uncaught exception report.
+ *
+ * XXX it'd probably be best if there was only one call to this
+ * function, but there seem to be two error reporter call points.
+ */
+ report:
+ onError = cx->errorReporter;
+
+ /*
+ * Try to raise an exception only if there isn't one already set --
+ * otherwise the exception will describe the last compile-time error,
+ * which is likely spurious.
+ */
+ if (!(ts->flags & TSF_ERROR)) {
+ if (js_ErrorToException(cx, message, &report))
+ onError = NULL;
+ }
+
+ /*
+ * Suppress any compile-time errors that don't occur at the top level.
+ * This may still fail, as interplevel may be zero in contexts where we
+ * don't really want to call the error reporter, as when js is called
+ * by other code which could catch the error.
+ */
+ if (cx->interpLevel != 0 && !JSREPORT_IS_WARNING(flags))
+ onError = NULL;
+
+ if (onError) {
+ JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
+
+ /*
+ * If debugErrorHook is present then we give it a chance to veto
+ * sending the error on to the regular error reporter.
+ */
+ if (hook && !hook(cx, message, &report,
+ cx->debugHooks->debugErrorHookData)) {
+ onError = NULL;
+ }
+ }
+ if (onError)
+ (*onError)(cx, message, &report);
+
+ out:
+ if (linebytes)
+ JS_free(cx, linebytes);
+ if (linechars)
+ JS_free(cx, linechars);
+ if (message)
+ JS_free(cx, message);
+ if (report.ucmessage)
+ JS_free(cx, (void *)report.ucmessage);
+
+ if (report.messageArgs) {
+ if (!(flags & JSREPORT_UC)) {
+ i = 0;
+ while (report.messageArgs[i])
+ JS_free(cx, (void *)report.messageArgs[i++]);
+ }
+ JS_free(cx, (void *)report.messageArgs);
+ }
+
+ if (!JSREPORT_IS_WARNING(flags)) {
+ /* Set the error flag to suppress spurious reports. */
+ ts->flags |= TSF_ERROR;
+ }
+
+ return warning;
+}
+
+static JSBool
+GrowStringBuffer(JSStringBuffer *sb, size_t newlength)
+{
+ ptrdiff_t offset;
+ jschar *bp;
+
+ offset = PTRDIFF(sb->ptr, sb->base, jschar);
+ JS_ASSERT(offset >= 0);
+ newlength += offset + 1;
+ if ((size_t)offset < newlength && newlength < ~(size_t)0 / sizeof(jschar))
+ bp = (jschar *) realloc(sb->base, newlength * sizeof(jschar));
+ else
+ bp = NULL;
+ if (!bp) {
+ free(sb->base);
+ sb->base = STRING_BUFFER_ERROR_BASE;
+ return JS_FALSE;
+ }
+ sb->base = bp;
+ sb->ptr = bp + offset;
+ sb->limit = bp + newlength - 1;
+ return JS_TRUE;
+}
+
+static void
+FreeStringBuffer(JSStringBuffer *sb)
+{
+ JS_ASSERT(STRING_BUFFER_OK(sb));
+ if (sb->base)
+ free(sb->base);
+}
+
+void
+js_InitStringBuffer(JSStringBuffer *sb)
+{
+ sb->base = sb->limit = sb->ptr = NULL;
+ sb->data = NULL;
+ sb->grow = GrowStringBuffer;
+ sb->free = FreeStringBuffer;
+}
+
+void
+js_FinishStringBuffer(JSStringBuffer *sb)
+{
+ sb->free(sb);
+}
+
+#define ENSURE_STRING_BUFFER(sb,n) \
+ ((sb)->ptr + (n) <= (sb)->limit || sb->grow(sb, n))
+
+static void
+FastAppendChar(JSStringBuffer *sb, jschar c)
+{
+ if (!STRING_BUFFER_OK(sb))
+ return;
+ if (!ENSURE_STRING_BUFFER(sb, 1))
+ return;
+ *sb->ptr++ = c;
+}
+
+void
+js_AppendChar(JSStringBuffer *sb, jschar c)
+{
+ jschar *bp;
+
+ if (!STRING_BUFFER_OK(sb))
+ return;
+ if (!ENSURE_STRING_BUFFER(sb, 1))
+ return;
+ bp = sb->ptr;
+ *bp++ = c;
+ *bp = 0;
+ sb->ptr = bp;
+}
+
+void
+js_AppendUCString(JSStringBuffer *sb, const jschar *buf, uintN len)
+{
+ jschar *bp;
+
+ if (!STRING_BUFFER_OK(sb))
+ return;
+ if (len == 0 || !ENSURE_STRING_BUFFER(sb, len))
+ return;
+ bp = sb->ptr;
+ js_strncpy(bp, buf, len);
+ bp += len;
+ *bp = 0;
+ sb->ptr = bp;
+}
+
+#if JS_HAS_XML_SUPPORT
+
+void
+js_RepeatChar(JSStringBuffer *sb, jschar c, uintN count)
+{
+ jschar *bp;
+
+ if (!STRING_BUFFER_OK(sb) || count == 0)
+ return;
+ if (!ENSURE_STRING_BUFFER(sb, count))
+ return;
+ for (bp = sb->ptr; count; --count)
+ *bp++ = c;
+ *bp = 0;
+ sb->ptr = bp;
+}
+
+void
+js_AppendCString(JSStringBuffer *sb, const char *asciiz)
+{
+ size_t length;
+ jschar *bp;
+
+ if (!STRING_BUFFER_OK(sb) || *asciiz == '\0')
+ return;
+ length = strlen(asciiz);
+ if (!ENSURE_STRING_BUFFER(sb, length))
+ return;
+ for (bp = sb->ptr; length; --length)
+ *bp++ = (jschar) *asciiz++;
+ *bp = 0;
+ sb->ptr = bp;
+}
+
+void
+js_AppendJSString(JSStringBuffer *sb, JSString *str)
+{
+ js_AppendUCString(sb, JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
+}
+
+static JSBool
+GetXMLEntity(JSContext *cx, JSTokenStream *ts)
+{
+ ptrdiff_t offset, length, i;
+ int32 c, d;
+ JSBool ispair;
+ jschar *bp, digit;
+ char *bytes;
+ JSErrNum msg;
+
+ /* Put the entity, including the '&' already scanned, in ts->tokenbuf. */
+ offset = PTRDIFF(ts->tokenbuf.ptr, ts->tokenbuf.base, jschar);
+ FastAppendChar(&ts->tokenbuf, '&');
+ if (!STRING_BUFFER_OK(&ts->tokenbuf))
+ return JS_FALSE;
+ while ((c = GetChar(ts)) != ';') {
+ if (c == EOF || c == '\n') {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_END_OF_XML_ENTITY);
+ return JS_FALSE;
+ }
+ FastAppendChar(&ts->tokenbuf, (jschar) c);
+ if (!STRING_BUFFER_OK(&ts->tokenbuf))
+ return JS_FALSE;
+ }
+
+ /* Let length be the number of jschars after the '&', including the ';'. */
+ length = PTRDIFF(ts->tokenbuf.ptr, ts->tokenbuf.base, jschar) - offset;
+ bp = ts->tokenbuf.base + offset;
+ c = d = 0;
+ ispair = JS_FALSE;
+ if (length > 2 && bp[1] == '#') {
+ /* Match a well-formed XML Character Reference. */
+ i = 2;
+ if (length > 3 && JS_TOLOWER(bp[i]) == 'x') {
+ if (length > 9) /* at most 6 hex digits allowed */
+ goto badncr;
+ while (++i < length) {
+ digit = bp[i];
+ if (!JS7_ISHEX(digit))
+ goto badncr;
+ c = (c << 4) + JS7_UNHEX(digit);
+ }
+ } else {
+ while (i < length) {
+ digit = bp[i++];
+ if (!JS7_ISDEC(digit))
+ goto badncr;
+ c = (c * 10) + JS7_UNDEC(digit);
+ if (c < 0)
+ goto badncr;
+ }
+ }
+
+ if (0x10000 <= c && c <= 0x10FFFF) {
+ /* Form a surrogate pair (c, d) -- c is the high surrogate. */
+ d = 0xDC00 + (c & 0x3FF);
+ c = 0xD7C0 + (c >> 10);
+ ispair = JS_TRUE;
+ } else {
+ /* Enforce the http://www.w3.org/TR/REC-xml/#wf-Legalchar WFC. */
+ if (c != 0x9 && c != 0xA && c != 0xD &&
+ !(0x20 <= c && c <= 0xD7FF) &&
+ !(0xE000 <= c && c <= 0xFFFD)) {
+ goto badncr;
+ }
+ }
+ } else {
+ /* Try to match one of the five XML 1.0 predefined entities. */
+ switch (length) {
+ case 3:
+ if (bp[2] == 't') {
+ if (bp[1] == 'l')
+ c = '<';
+ else if (bp[1] == 'g')
+ c = '>';
+ }
+ break;
+ case 4:
+ if (bp[1] == 'a' && bp[2] == 'm' && bp[3] == 'p')
+ c = '&';
+ break;
+ case 5:
+ if (bp[3] == 'o') {
+ if (bp[1] == 'a' && bp[2] == 'p' && bp[4] == 's')
+ c = '\'';
+ else if (bp[1] == 'q' && bp[2] == 'u' && bp[4] == 't')
+ c = '"';
+ }
+ break;
+ }
+ if (c == 0) {
+ msg = JSMSG_UNKNOWN_XML_ENTITY;
+ goto bad;
+ }
+ }
+
+ /* If we matched, retract ts->tokenbuf and store the entity's value. */
+ *bp++ = (jschar) c;
+ if (ispair)
+ *bp++ = (jschar) d;
+ *bp = 0;
+ ts->tokenbuf.ptr = bp;
+ return JS_TRUE;
+
+badncr:
+ msg = JSMSG_BAD_XML_NCR;
+bad:
+ /* No match: throw a TypeError per ECMA-357 10.3.2.1 step 8(a). */
+ JS_ASSERT(STRING_BUFFER_OK(&ts->tokenbuf));
+ JS_ASSERT(PTRDIFF(ts->tokenbuf.ptr, bp, jschar) >= 1);
+ bytes = js_DeflateString(cx, bp + 1,
+ PTRDIFF(ts->tokenbuf.ptr, bp, jschar) - 1);
+ if (bytes) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ msg, bytes);
+ JS_free(cx, bytes);
+ }
+ return JS_FALSE;
+}
+
+#endif /* JS_HAS_XML_SUPPORT */
+
+JSTokenType
+js_PeekToken(JSContext *cx, JSTokenStream *ts)
+{
+ JSTokenType tt;
+
+ if (ts->lookahead != 0) {
+ tt = ts->tokens[(ts->cursor + ts->lookahead) & NTOKENS_MASK].type;
+ } else {
+ tt = js_GetToken(cx, ts);
+ js_UngetToken(ts);
+ }
+ return tt;
+}
+
+JSTokenType
+js_PeekTokenSameLine(JSContext *cx, JSTokenStream *ts)
+{
+ JSTokenType tt;
+
+ if (!ON_CURRENT_LINE(ts, CURRENT_TOKEN(ts).pos))
+ return TOK_EOL;
+ ts->flags |= TSF_NEWLINES;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_NEWLINES;
+ return tt;
+}
+
+/*
+ * We have encountered a '\': check for a Unicode escape sequence after it,
+ * returning the character code value if we found a Unicode escape sequence.
+ * Otherwise, non-destructively return the original '\'.
+ */
+static int32
+GetUnicodeEscape(JSTokenStream *ts)
+{
+ jschar cp[5];
+ int32 c;
+
+ if (PeekChars(ts, 5, cp) && cp[0] == 'u' &&
+ JS7_ISHEX(cp[1]) && JS7_ISHEX(cp[2]) &&
+ JS7_ISHEX(cp[3]) && JS7_ISHEX(cp[4]))
+ {
+ c = (((((JS7_UNHEX(cp[1]) << 4)
+ + JS7_UNHEX(cp[2])) << 4)
+ + JS7_UNHEX(cp[3])) << 4)
+ + JS7_UNHEX(cp[4]);
+ SkipChars(ts, 5);
+ return c;
+ }
+ return '\\';
+}
+
+static JSToken *
+NewToken(JSTokenStream *ts, ptrdiff_t adjust)
+{
+ JSToken *tp;
+
+ ts->cursor = (ts->cursor + 1) & NTOKENS_MASK;
+ tp = &CURRENT_TOKEN(ts);
+ tp->ptr = ts->linebuf.ptr + adjust;
+ tp->pos.begin.index = ts->linepos +
+ PTRDIFF(tp->ptr, ts->linebuf.base, jschar) -
+ ts->ungetpos;
+ tp->pos.begin.lineno = tp->pos.end.lineno = (uint16)ts->lineno;
+ return tp;
+}
+
+static JS_ALWAYS_INLINE JSBool
+ScanAsSpace(jschar c)
+{
+ /* Treat little- and big-endian BOMs as whitespace for compatibility. */
+ if (JS_ISSPACE(c) || c == 0xfffe || c == 0xfeff)
+ return JS_TRUE;
+ return JS_FALSE;
+}
+
+JSTokenType
+js_GetToken(JSContext *cx, JSTokenStream *ts)
+{
+ JSTokenType tt;
+ int32 c, qc;
+ JSToken *tp;
+ JSAtom *atom;
+ JSBool hadUnicodeEscape;
+ const struct keyword *kw;
+#if JS_HAS_XML_SUPPORT
+ JSBool inTarget;
+ size_t targetLength;
+ ptrdiff_t contentIndex;
+#endif
+
+#define INIT_TOKENBUF() (ts->tokenbuf.ptr = ts->tokenbuf.base)
+#define TOKENBUF_LENGTH() PTRDIFF(ts->tokenbuf.ptr, ts->tokenbuf.base, jschar)
+#define TOKENBUF_OK() STRING_BUFFER_OK(&ts->tokenbuf)
+#define TOKENBUF_TO_ATOM() (TOKENBUF_OK() \
+ ? js_AtomizeChars(cx, \
+ TOKENBUF_BASE(), \
+ TOKENBUF_LENGTH(), \
+ 0) \
+ : NULL)
+#define ADD_TO_TOKENBUF(c) FastAppendChar(&ts->tokenbuf, (jschar) (c))
+
+/* The following 4 macros should only be used when TOKENBUF_OK() is true. */
+#define TOKENBUF_BASE() (ts->tokenbuf.base)
+#define TOKENBUF_END() (ts->tokenbuf.ptr)
+#define TOKENBUF_CHAR(i) (ts->tokenbuf.base[i])
+#define TRIM_TOKENBUF(i) (ts->tokenbuf.ptr = ts->tokenbuf.base + i)
+#define NUL_TERM_TOKENBUF() (*ts->tokenbuf.ptr = 0)
+
+ /* Check for a pushed-back token resulting from mismatching lookahead. */
+ while (ts->lookahead != 0) {
+ JS_ASSERT(!(ts->flags & TSF_XMLTEXTMODE));
+ ts->lookahead--;
+ ts->cursor = (ts->cursor + 1) & NTOKENS_MASK;
+ tt = CURRENT_TOKEN(ts).type;
+ if (tt != TOK_EOL || (ts->flags & TSF_NEWLINES))
+ return tt;
+ }
+
+ /* If there was a fatal error, keep returning TOK_ERROR. */
+ if (ts->flags & TSF_ERROR)
+ return TOK_ERROR;
+
+#if JS_HAS_XML_SUPPORT
+ if (ts->flags & TSF_XMLTEXTMODE) {
+ tt = TOK_XMLSPACE; /* veto if non-space, return TOK_XMLTEXT */
+ tp = NewToken(ts, 0);
+ INIT_TOKENBUF();
+ qc = (ts->flags & TSF_XMLONLYMODE) ? '<' : '{';
+
+ while ((c = GetChar(ts)) != qc && c != '<' && c != EOF) {
+ if (c == '&' && qc == '<') {
+ if (!GetXMLEntity(cx, ts))
+ goto error;
+ tt = TOK_XMLTEXT;
+ continue;
+ }
+
+ if (!JS_ISXMLSPACE(c))
+ tt = TOK_XMLTEXT;
+ ADD_TO_TOKENBUF(c);
+ }
+ UngetChar(ts, c);
+
+ if (TOKENBUF_LENGTH() == 0) {
+ atom = NULL;
+ } else {
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ }
+ tp->pos.end.lineno = (uint16)ts->lineno;
+ tp->t_op = JSOP_STRING;
+ tp->t_atom = atom;
+ goto out;
+ }
+
+ if (ts->flags & TSF_XMLTAGMODE) {
+ tp = NewToken(ts, 0);
+ c = GetChar(ts);
+ if (JS_ISXMLSPACE(c)) {
+ do {
+ c = GetChar(ts);
+ } while (JS_ISXMLSPACE(c));
+ UngetChar(ts, c);
+ tt = TOK_XMLSPACE;
+ goto out;
+ }
+
+ if (c == EOF) {
+ tt = TOK_EOF;
+ goto out;
+ }
+
+ INIT_TOKENBUF();
+ if (JS_ISXMLNSSTART(c)) {
+ JSBool sawColon = JS_FALSE;
+
+ ADD_TO_TOKENBUF(c);
+ while ((c = GetChar(ts)) != EOF && JS_ISXMLNAME(c)) {
+ if (c == ':') {
+ int nextc;
+
+ if (sawColon ||
+ (nextc = PeekChar(ts),
+ ((ts->flags & TSF_XMLONLYMODE) || nextc != '{') &&
+ !JS_ISXMLNAME(nextc))) {
+ js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_ERROR,
+ JSMSG_BAD_XML_QNAME);
+ goto error;
+ }
+ sawColon = JS_TRUE;
+ }
+
+ ADD_TO_TOKENBUF(c);
+ }
+
+ UngetChar(ts, c);
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ tp->t_op = JSOP_STRING;
+ tp->t_atom = atom;
+ tt = TOK_XMLNAME;
+ goto out;
+ }
+
+ switch (c) {
+ case '{':
+ if (ts->flags & TSF_XMLONLYMODE)
+ goto bad_xml_char;
+ tt = TOK_LC;
+ goto out;
+
+ case '=':
+ tt = TOK_ASSIGN;
+ goto out;
+
+ case '"':
+ case '\'':
+ qc = c;
+ while ((c = GetChar(ts)) != qc) {
+ if (c == EOF) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_UNTERMINATED_STRING);
+ goto error;
+ }
+
+ /*
+ * XML attribute values are double-quoted when pretty-printed,
+ * so escape " if it is expressed directly in a single-quoted
+ * attribute value.
+ */
+ if (c == '"' && !(ts->flags & TSF_XMLONLYMODE)) {
+ JS_ASSERT(qc == '\'');
+ js_AppendCString(&ts->tokenbuf, js_quot_entity_str);
+ continue;
+ }
+
+ if (c == '&' && (ts->flags & TSF_XMLONLYMODE)) {
+ if (!GetXMLEntity(cx, ts))
+ goto error;
+ continue;
+ }
+
+ ADD_TO_TOKENBUF(c);
+ }
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ tp->pos.end.lineno = (uint16)ts->lineno;
+ tp->t_op = JSOP_STRING;
+ tp->t_atom = atom;
+ tt = TOK_XMLATTR;
+ goto out;
+
+ case '>':
+ tt = TOK_XMLTAGC;
+ goto out;
+
+ case '/':
+ if (MatchChar(ts, '>')) {
+ tt = TOK_XMLPTAGC;
+ goto out;
+ }
+ /* FALL THROUGH */
+
+ bad_xml_char:
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_CHARACTER);
+ goto error;
+ }
+ /* NOTREACHED */
+ }
+#endif /* JS_HAS_XML_SUPPORT */
+
+retry:
+ do {
+ c = GetChar(ts);
+ if (c == '\n') {
+ ts->flags &= ~TSF_DIRTYLINE;
+ if (ts->flags & TSF_NEWLINES)
+ break;
+ }
+ } while (ScanAsSpace((jschar)c));
+
+ tp = NewToken(ts, -1);
+ if (c == EOF) {
+ tt = TOK_EOF;
+ goto out;
+ }
+
+ hadUnicodeEscape = JS_FALSE;
+ if (JS_ISIDSTART(c) ||
+ (c == '\\' &&
+ (qc = GetUnicodeEscape(ts),
+ hadUnicodeEscape = JS_ISIDSTART(qc)))) {
+ if (hadUnicodeEscape)
+ c = qc;
+ INIT_TOKENBUF();
+ for (;;) {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ if (c == '\\') {
+ qc = GetUnicodeEscape(ts);
+ if (!JS_ISIDENT(qc))
+ break;
+ c = qc;
+ hadUnicodeEscape = JS_TRUE;
+ } else {
+ if (!JS_ISIDENT(c))
+ break;
+ }
+ }
+ UngetChar(ts, c);
+
+ /*
+ * Check for keywords unless we saw Unicode escape or parser asks
+ * to ignore keywords.
+ */
+ if (!hadUnicodeEscape &&
+ !(ts->flags & TSF_KEYWORD_IS_NAME) &&
+ TOKENBUF_OK() &&
+ (kw = FindKeyword(TOKENBUF_BASE(), TOKENBUF_LENGTH()))) {
+ if (kw->tokentype == TOK_RESERVED) {
+ if (!js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING |
+ JSREPORT_STRICT,
+ JSMSG_RESERVED_ID,
+ kw->chars)) {
+ goto error;
+ }
+ } else if (kw->version <= JSVERSION_NUMBER(cx)) {
+ tt = kw->tokentype;
+ tp->t_op = (JSOp) kw->op;
+ goto out;
+ }
+ }
+
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ tp->t_op = JSOP_NAME;
+ tp->t_atom = atom;
+ tt = TOK_NAME;
+ goto out;
+ }
+
+ if (JS7_ISDEC(c) || (c == '.' && JS7_ISDEC(PeekChar(ts)))) {
+ jsint radix;
+ const jschar *endptr;
+ jsdouble dval;
+
+ radix = 10;
+ INIT_TOKENBUF();
+
+ if (c == '0') {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ if (JS_TOLOWER(c) == 'x') {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ radix = 16;
+ } else if (JS7_ISDEC(c)) {
+ radix = 8;
+ }
+ }
+
+ while (JS7_ISHEX(c)) {
+ if (radix < 16) {
+ if (JS7_ISLET(c))
+ break;
+
+ /*
+ * We permit 08 and 09 as decimal numbers, which makes our
+ * behaviour a superset of the ECMA numeric grammar. We might
+ * not always be so permissive, so we warn about it.
+ */
+ if (radix == 8 && c >= '8') {
+ if (!js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING,
+ JSMSG_BAD_OCTAL,
+ c == '8' ? "08" : "09")) {
+ goto error;
+ }
+ radix = 10;
+ }
+ }
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ }
+
+ if (radix == 10 && (c == '.' || JS_TOLOWER(c) == 'e')) {
+ if (c == '.') {
+ do {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ } while (JS7_ISDEC(c));
+ }
+ if (JS_TOLOWER(c) == 'e') {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ if (c == '+' || c == '-') {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ }
+ if (!JS7_ISDEC(c)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_MISSING_EXPONENT);
+ goto error;
+ }
+ do {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ } while (JS7_ISDEC(c));
+ }
+ }
+
+ /* Put back the next char and NUL-terminate tokenbuf for js_strto*. */
+ UngetChar(ts, c);
+ ADD_TO_TOKENBUF(0);
+
+ if (!TOKENBUF_OK())
+ goto error;
+ if (radix == 10) {
+ if (!js_strtod(cx, TOKENBUF_BASE(), TOKENBUF_END(),
+ &endptr, &dval)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_OUT_OF_MEMORY);
+ goto error;
+ }
+ } else {
+ if (!js_strtointeger(cx, TOKENBUF_BASE(), TOKENBUF_END(),
+ &endptr, radix, &dval)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_OUT_OF_MEMORY);
+ goto error;
+ }
+ }
+ tp->t_dval = dval;
+ tt = TOK_NUMBER;
+ goto out;
+ }
+
+ if (c == '"' || c == '\'') {
+ qc = c;
+ INIT_TOKENBUF();
+ while ((c = GetChar(ts)) != qc) {
+ if (c == '\n' || c == EOF) {
+ UngetChar(ts, c);
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_UNTERMINATED_STRING);
+ goto error;
+ }
+ if (c == '\\') {
+ switch (c = GetChar(ts)) {
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+
+ default:
+ if ('0' <= c && c < '8') {
+ int32 val = JS7_UNDEC(c);
+
+ c = PeekChar(ts);
+ if ('0' <= c && c < '8') {
+ val = 8 * val + JS7_UNDEC(c);
+ GetChar(ts);
+ c = PeekChar(ts);
+ if ('0' <= c && c < '8') {
+ int32 save = val;
+ val = 8 * val + JS7_UNDEC(c);
+ if (val <= 0377)
+ GetChar(ts);
+ else
+ val = save;
+ }
+ }
+
+ c = (jschar)val;
+ } else if (c == 'u') {
+ jschar cp[4];
+ if (PeekChars(ts, 4, cp) &&
+ JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]) &&
+ JS7_ISHEX(cp[2]) && JS7_ISHEX(cp[3])) {
+ c = (((((JS7_UNHEX(cp[0]) << 4)
+ + JS7_UNHEX(cp[1])) << 4)
+ + JS7_UNHEX(cp[2])) << 4)
+ + JS7_UNHEX(cp[3]);
+ SkipChars(ts, 4);
+ }
+ } else if (c == 'x') {
+ jschar cp[2];
+ if (PeekChars(ts, 2, cp) &&
+ JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1])) {
+ c = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]);
+ SkipChars(ts, 2);
+ }
+ } else if (c == '\n') {
+ /* ECMA follows C by removing escaped newlines. */
+ continue;
+ }
+ break;
+ }
+ }
+ ADD_TO_TOKENBUF(c);
+ }
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ tp->pos.end.lineno = (uint16)ts->lineno;
+ tp->t_op = JSOP_STRING;
+ tp->t_atom = atom;
+ tt = TOK_STRING;
+ goto out;
+ }
+
+ switch (c) {
+ case '\n': tt = TOK_EOL; goto eol_out;
+ case ';': tt = TOK_SEMI; break;
+ case '[': tt = TOK_LB; break;
+ case ']': tt = TOK_RB; break;
+ case '{': tt = TOK_LC; break;
+ case '}': tt = TOK_RC; break;
+ case '(': tt = TOK_LP; break;
+ case ')': tt = TOK_RP; break;
+ case ',': tt = TOK_COMMA; break;
+ case '?': tt = TOK_HOOK; break;
+
+ case '.':
+#if JS_HAS_XML_SUPPORT
+ if (MatchChar(ts, c))
+ tt = TOK_DBLDOT;
+ else
+#endif
+ tt = TOK_DOT;
+ break;
+
+ case ':':
+#if JS_HAS_XML_SUPPORT
+ if (MatchChar(ts, c)) {
+ tt = TOK_DBLCOLON;
+ break;
+ }
+#endif
+ /*
+ * Default so compiler can modify to JSOP_GETTER if 'p getter: v' in an
+ * object initializer, likewise for setter.
+ */
+ tp->t_op = JSOP_NOP;
+ tt = TOK_COLON;
+ break;
+
+ case '|':
+ if (MatchChar(ts, c)) {
+ tt = TOK_OR;
+ } else if (MatchChar(ts, '=')) {
+ tp->t_op = JSOP_BITOR;
+ tt = TOK_ASSIGN;
+ } else {
+ tt = TOK_BITOR;
+ }
+ break;
+
+ case '^':
+ if (MatchChar(ts, '=')) {
+ tp->t_op = JSOP_BITXOR;
+ tt = TOK_ASSIGN;
+ } else {
+ tt = TOK_BITXOR;
+ }
+ break;
+
+ case '&':
+ if (MatchChar(ts, c)) {
+ tt = TOK_AND;
+ } else if (MatchChar(ts, '=')) {
+ tp->t_op = JSOP_BITAND;
+ tt = TOK_ASSIGN;
+ } else {
+ tt = TOK_BITAND;
+ }
+ break;
+
+ case '=':
+ if (MatchChar(ts, c)) {
+ tp->t_op = MatchChar(ts, c) ? JSOP_STRICTEQ : JSOP_EQ;
+ tt = TOK_EQOP;
+ } else {
+ tp->t_op = JSOP_NOP;
+ tt = TOK_ASSIGN;
+ }
+ break;
+
+ case '!':
+ if (MatchChar(ts, '=')) {
+ tp->t_op = MatchChar(ts, '=') ? JSOP_STRICTNE : JSOP_NE;
+ tt = TOK_EQOP;
+ } else {
+ tp->t_op = JSOP_NOT;
+ tt = TOK_UNARYOP;
+ }
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case '@':
+ tt = TOK_AT;
+ break;
+#endif
+
+ case '<':
+#if JS_HAS_XML_SUPPORT
+ /*
+ * After much testing, it's clear that Postel's advice to protocol
+ * designers ("be liberal in what you accept, and conservative in what
+ * you send") invites a natural-law repercussion for JS as "protocol":
+ *
+ * "If you are liberal in what you accept, others will utterly fail to
+ * be conservative in what they send."
+ *
+ * Which means you will get <!-- comments to end of line in the middle
+ * of .js files, and after if conditions whose then statements are on
+ * the next line, and other wonders. See at least the following bugs:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=309242
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=309712
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=310993
+ *
+ * So without JSOPTION_XML, we never scan an XML comment or CDATA
+ * literal. We always scan <! as the start of an HTML comment hack
+ * to end of line, used since Netscape 2 to hide script tag content
+ * from script-unaware browsers.
+ */
+ if ((ts->flags & TSF_OPERAND) &&
+ (JS_HAS_XML_OPTION(cx) || PeekChar(ts) != '!')) {
+ /* Check for XML comment or CDATA section. */
+ if (MatchChar(ts, '!')) {
+ INIT_TOKENBUF();
+
+ /* Scan XML comment. */
+ if (MatchChar(ts, '-')) {
+ if (!MatchChar(ts, '-'))
+ goto bad_xml_markup;
+ while ((c = GetChar(ts)) != '-' || !MatchChar(ts, '-')) {
+ if (c == EOF)
+ goto bad_xml_markup;
+ ADD_TO_TOKENBUF(c);
+ }
+ tt = TOK_XMLCOMMENT;
+ tp->t_op = JSOP_XMLCOMMENT;
+ goto finish_xml_markup;
+ }
+
+ /* Scan CDATA section. */
+ if (MatchChar(ts, '[')) {
+ jschar cp[6];
+ if (PeekChars(ts, 6, cp) &&
+ cp[0] == 'C' &&
+ cp[1] == 'D' &&
+ cp[2] == 'A' &&
+ cp[3] == 'T' &&
+ cp[4] == 'A' &&
+ cp[5] == '[') {
+ SkipChars(ts, 6);
+ while ((c = GetChar(ts)) != ']' ||
+ !PeekChars(ts, 2, cp) ||
+ cp[0] != ']' ||
+ cp[1] != '>') {
+ if (c == EOF)
+ goto bad_xml_markup;
+ ADD_TO_TOKENBUF(c);
+ }
+ GetChar(ts); /* discard ] but not > */
+ tt = TOK_XMLCDATA;
+ tp->t_op = JSOP_XMLCDATA;
+ goto finish_xml_markup;
+ }
+ goto bad_xml_markup;
+ }
+ }
+
+ /* Check for processing instruction. */
+ if (MatchChar(ts, '?')) {
+ inTarget = JS_TRUE;
+ targetLength = 0;
+ contentIndex = -1;
+
+ INIT_TOKENBUF();
+ while ((c = GetChar(ts)) != '?' || PeekChar(ts) != '>') {
+ if (c == EOF)
+ goto bad_xml_markup;
+ if (inTarget) {
+ if (JS_ISXMLSPACE(c)) {
+ if (TOKENBUF_LENGTH() == 0)
+ goto bad_xml_markup;
+ inTarget = JS_FALSE;
+ } else {
+ if (!((TOKENBUF_LENGTH() == 0)
+ ? JS_ISXMLNSSTART(c)
+ : JS_ISXMLNS(c))) {
+ goto bad_xml_markup;
+ }
+ ++targetLength;
+ }
+ } else {
+ if (contentIndex < 0 && !JS_ISXMLSPACE(c))
+ contentIndex = TOKENBUF_LENGTH();
+ }
+ ADD_TO_TOKENBUF(c);
+ }
+ if (targetLength == 0)
+ goto bad_xml_markup;
+ if (!TOKENBUF_OK())
+ goto error;
+ if (contentIndex < 0) {
+ atom = cx->runtime->atomState.emptyAtom;
+ } else {
+ atom = js_AtomizeChars(cx,
+ &TOKENBUF_CHAR(contentIndex),
+ TOKENBUF_LENGTH() - contentIndex,
+ 0);
+ if (!atom)
+ goto error;
+ }
+ TRIM_TOKENBUF(targetLength);
+ tp->t_atom2 = atom;
+ tt = TOK_XMLPI;
+
+ finish_xml_markup:
+ if (!MatchChar(ts, '>'))
+ goto bad_xml_markup;
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ tp->t_atom = atom;
+ tp->pos.end.lineno = (uint16)ts->lineno;
+ goto out;
+ }
+
+ /* An XML start-of-tag character. */
+ tt = MatchChar(ts, '/') ? TOK_XMLETAGO : TOK_XMLSTAGO;
+ goto out;
+
+ bad_xml_markup:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_MARKUP);
+ goto error;
+ }
+#endif /* JS_HAS_XML_SUPPORT */
+
+ /* NB: treat HTML begin-comment as comment-till-end-of-line */
+ if (MatchChar(ts, '!')) {
+ if (MatchChar(ts, '-')) {
+ if (MatchChar(ts, '-')) {
+ ts->flags |= TSF_IN_HTML_COMMENT;
+ goto skipline;
+ }
+ UngetChar(ts, '-');
+ }
+ UngetChar(ts, '!');
+ }
+ if (MatchChar(ts, c)) {
+ tp->t_op = JSOP_LSH;
+ tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_SHOP;
+ } else {
+ tp->t_op = MatchChar(ts, '=') ? JSOP_LE : JSOP_LT;
+ tt = TOK_RELOP;
+ }
+ break;
+
+ case '>':
+ if (MatchChar(ts, c)) {
+ tp->t_op = MatchChar(ts, c) ? JSOP_URSH : JSOP_RSH;
+ tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_SHOP;
+ } else {
+ tp->t_op = MatchChar(ts, '=') ? JSOP_GE : JSOP_GT;
+ tt = TOK_RELOP;
+ }
+ break;
+
+ case '*':
+ tp->t_op = JSOP_MUL;
+ tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_STAR;
+ break;
+
+ case '/':
+ if (MatchChar(ts, '/')) {
+ /*
+ * Hack for source filters such as the Mozilla XUL preprocessor:
+ * "//@line 123\n" sets the number of the *next* line after the
+ * comment to 123.
+ */
+ if (JS_HAS_ATLINE_OPTION(cx)) {
+ jschar cp[5];
+ uintN i, line, temp;
+ char filename[1024];
+
+ if (PeekChars(ts, 5, cp) &&
+ cp[0] == '@' &&
+ cp[1] == 'l' &&
+ cp[2] == 'i' &&
+ cp[3] == 'n' &&
+ cp[4] == 'e') {
+ SkipChars(ts, 5);
+ while ((c = GetChar(ts)) != '\n' && ScanAsSpace((jschar)c))
+ continue;
+ if (JS7_ISDEC(c)) {
+ line = JS7_UNDEC(c);
+ while ((c = GetChar(ts)) != EOF && JS7_ISDEC(c)) {
+ temp = 10 * line + JS7_UNDEC(c);
+ if (temp < line) {
+ /* Ignore overlarge line numbers. */
+ goto skipline;
+ }
+ line = temp;
+ }
+ while (c != '\n' && ScanAsSpace((jschar)c))
+ c = GetChar(ts);
+ i = 0;
+ if (c == '"') {
+ while ((c = GetChar(ts)) != EOF && c != '"') {
+ if (c == '\n') {
+ UngetChar(ts, c);
+ goto skipline;
+ }
+ if ((c >> 8) != 0 || i >= sizeof filename - 1)
+ goto skipline;
+ filename[i++] = (char) c;
+ }
+ if (c == '"') {
+ while ((c = GetChar(ts)) != '\n' &&
+ ScanAsSpace((jschar)c)) {
+ continue;
+ }
+ }
+ }
+ filename[i] = '\0';
+ if (c == '\n') {
+ if (i > 0) {
+ if (ts->flags & TSF_OWNFILENAME)
+ JS_free(cx, (void *) ts->filename);
+ ts->filename = JS_strdup(cx, filename);
+ if (!ts->filename)
+ goto error;
+ ts->flags |= TSF_OWNFILENAME;
+ }
+ ts->lineno = line;
+ }
+ }
+ UngetChar(ts, c);
+ }
+ }
+
+skipline:
+ /* Optimize line skipping if we are not in an HTML comment. */
+ if (ts->flags & TSF_IN_HTML_COMMENT) {
+ while ((c = GetChar(ts)) != EOF && c != '\n') {
+ if (c == '-' && MatchChar(ts, '-') && MatchChar(ts, '>'))
+ ts->flags &= ~TSF_IN_HTML_COMMENT;
+ }
+ } else {
+ while ((c = GetChar(ts)) != EOF && c != '\n')
+ continue;
+ }
+ UngetChar(ts, c);
+ ts->cursor = (ts->cursor - 1) & NTOKENS_MASK;
+ goto retry;
+ }
+
+ if (MatchChar(ts, '*')) {
+ while ((c = GetChar(ts)) != EOF &&
+ !(c == '*' && MatchChar(ts, '/'))) {
+ /* Ignore all characters until comment close. */
+ }
+ if (c == EOF) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_UNTERMINATED_COMMENT);
+ goto error;
+ }
+ ts->cursor = (ts->cursor - 1) & NTOKENS_MASK;
+ goto retry;
+ }
+
+ if (ts->flags & TSF_OPERAND) {
+ uintN flags;
+ JSBool inCharClass = JS_FALSE;
+
+ INIT_TOKENBUF();
+ for (;;) {
+ c = GetChar(ts);
+ if (c == '\n' || c == EOF) {
+ UngetChar(ts, c);
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_UNTERMINATED_REGEXP);
+ goto error;
+ }
+ if (c == '\\') {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ } else if (c == '[') {
+ inCharClass = JS_TRUE;
+ } else if (c == ']') {
+ inCharClass = JS_FALSE;
+ } else if (c == '/' && !inCharClass) {
+ /* For compat with IE, allow unescaped / in char classes. */
+ break;
+ }
+ ADD_TO_TOKENBUF(c);
+ }
+ for (flags = 0; ; ) {
+ c = PeekChar(ts);
+ if (c == 'g')
+ flags |= JSREG_GLOB;
+ else if (c == 'i')
+ flags |= JSREG_FOLD;
+ else if (c == 'm')
+ flags |= JSREG_MULTILINE;
+ else if (c == 'y')
+ flags |= JSREG_STICKY;
+ else
+ break;
+ GetChar(ts);
+ }
+ c = PeekChar(ts);
+ if (JS7_ISLET(c)) {
+ tp->ptr = ts->linebuf.ptr - 1;
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_REGEXP_FLAG);
+ (void) GetChar(ts);
+ goto error;
+ }
+ /* XXXbe fix jsregexp.c so it doesn't depend on NUL termination */
+ if (!TOKENBUF_OK())
+ goto error;
+ NUL_TERM_TOKENBUF();
+ tp->t_reflags = flags;
+ tt = TOK_REGEXP;
+ break;
+ }
+
+ tp->t_op = JSOP_DIV;
+ tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_DIVOP;
+ break;
+
+ case '%':
+ tp->t_op = JSOP_MOD;
+ tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_DIVOP;
+ break;
+
+ case '~':
+ tp->t_op = JSOP_BITNOT;
+ tt = TOK_UNARYOP;
+ break;
+
+ case '+':
+ if (MatchChar(ts, '=')) {
+ tp->t_op = JSOP_ADD;
+ tt = TOK_ASSIGN;
+ } else if (MatchChar(ts, c)) {
+ tt = TOK_INC;
+ } else {
+ tp->t_op = JSOP_POS;
+ tt = TOK_PLUS;
+ }
+ break;
+
+ case '-':
+ if (MatchChar(ts, '=')) {
+ tp->t_op = JSOP_SUB;
+ tt = TOK_ASSIGN;
+ } else if (MatchChar(ts, c)) {
+ if (PeekChar(ts) == '>' && !(ts->flags & TSF_DIRTYLINE)) {
+ ts->flags &= ~TSF_IN_HTML_COMMENT;
+ goto skipline;
+ }
+ tt = TOK_DEC;
+ } else {
+ tp->t_op = JSOP_NEG;
+ tt = TOK_MINUS;
+ }
+ break;
+
+#if JS_HAS_SHARP_VARS
+ case '#':
+ {
+ uint32 n;
+
+ c = GetChar(ts);
+ if (!JS7_ISDEC(c)) {
+ UngetChar(ts, c);
+ goto badchar;
+ }
+ n = (uint32)JS7_UNDEC(c);
+ for (;;) {
+ c = GetChar(ts);
+ if (!JS7_ISDEC(c))
+ break;
+ n = 10 * n + JS7_UNDEC(c);
+ if (n >= UINT16_LIMIT) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SHARPVAR_TOO_BIG);
+ goto error;
+ }
+ }
+ tp->t_dval = (jsdouble) n;
+ if (JS_HAS_STRICT_OPTION(cx) &&
+ (c == '=' || c == '#')) {
+ char buf[20];
+ JS_snprintf(buf, sizeof buf, "#%u%c", n, c);
+ if (!js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING |
+ JSREPORT_STRICT,
+ JSMSG_DEPRECATED_USAGE,
+ buf)) {
+ goto error;
+ }
+ }
+ if (c == '=')
+ tt = TOK_DEFSHARP;
+ else if (c == '#')
+ tt = TOK_USESHARP;
+ else
+ goto badchar;
+ break;
+ }
+#endif /* JS_HAS_SHARP_VARS */
+
+#if JS_HAS_SHARP_VARS || JS_HAS_XML_SUPPORT
+ badchar:
+#endif
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_ILLEGAL_CHARACTER);
+ goto error;
+ }
+
+out:
+ JS_ASSERT(tt != TOK_EOL);
+ ts->flags |= TSF_DIRTYLINE;
+
+eol_out:
+ if (!STRING_BUFFER_OK(&ts->tokenbuf))
+ tt = TOK_ERROR;
+ JS_ASSERT(tt < TOK_LIMIT);
+ tp->pos.end.index = ts->linepos +
+ PTRDIFF(ts->linebuf.ptr, ts->linebuf.base, jschar) -
+ ts->ungetpos;
+ tp->type = tt;
+ return tt;
+
+error:
+ tt = TOK_ERROR;
+ ts->flags |= TSF_ERROR;
+ goto out;
+
+#undef INIT_TOKENBUF
+#undef TOKENBUF_LENGTH
+#undef TOKENBUF_OK
+#undef TOKENBUF_TO_ATOM
+#undef ADD_TO_TOKENBUF
+#undef TOKENBUF_BASE
+#undef TOKENBUF_CHAR
+#undef TRIM_TOKENBUF
+#undef NUL_TERM_TOKENBUF
+}
+
+void
+js_UngetToken(JSTokenStream *ts)
+{
+ JS_ASSERT(ts->lookahead < NTOKENS_MASK);
+ ts->lookahead++;
+ ts->cursor = (ts->cursor - 1) & NTOKENS_MASK;
+}
+
+JSBool
+js_MatchToken(JSContext *cx, JSTokenStream *ts, JSTokenType tt)
+{
+ if (js_GetToken(cx, ts) == tt)
+ return JS_TRUE;
+ js_UngetToken(ts);
+ return JS_FALSE;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscan.h b/tools/node_modules/expresso/deps/jscoverage/js/jsscan.h
new file mode 100644
index 0000000..259aa8a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscan.h
@@ -0,0 +1,389 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsscan_h___
+#define jsscan_h___
+/*
+ * JS lexical scanner interface.
+ */
+#include <stddef.h>
+#include <stdio.h>
+#include "jsversion.h"
+#include "jsopcode.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+#define JS_KEYWORD(keyword, type, op, version) \
+ extern const char js_##keyword##_str[];
+#include "jskeyword.tbl"
+#undef JS_KEYWORD
+
+typedef enum JSTokenType {
+ TOK_ERROR = -1, /* well-known as the only code < EOF */
+ TOK_EOF = 0, /* end of file */
+ TOK_EOL = 1, /* end of line */
+ TOK_SEMI = 2, /* semicolon */
+ TOK_COMMA = 3, /* comma operator */
+ TOK_ASSIGN = 4, /* assignment ops (= += -= etc.) */
+ TOK_HOOK = 5, TOK_COLON = 6, /* conditional (?:) */
+ TOK_OR = 7, /* logical or (||) */
+ TOK_AND = 8, /* logical and (&&) */
+ TOK_BITOR = 9, /* bitwise-or (|) */
+ TOK_BITXOR = 10, /* bitwise-xor (^) */
+ TOK_BITAND = 11, /* bitwise-and (&) */
+ TOK_EQOP = 12, /* equality ops (== !=) */
+ TOK_RELOP = 13, /* relational ops (< <= > >=) */
+ TOK_SHOP = 14, /* shift ops (<< >> >>>) */
+ TOK_PLUS = 15, /* plus */
+ TOK_MINUS = 16, /* minus */
+ TOK_STAR = 17, TOK_DIVOP = 18, /* multiply/divide ops (* / %) */
+ TOK_UNARYOP = 19, /* unary prefix operator */
+ TOK_INC = 20, TOK_DEC = 21, /* increment/decrement (++ --) */
+ TOK_DOT = 22, /* member operator (.) */
+ TOK_LB = 23, TOK_RB = 24, /* left and right brackets */
+ TOK_LC = 25, TOK_RC = 26, /* left and right curlies (braces) */
+ TOK_LP = 27, TOK_RP = 28, /* left and right parentheses */
+ TOK_NAME = 29, /* identifier */
+ TOK_NUMBER = 30, /* numeric constant */
+ TOK_STRING = 31, /* string constant */
+ TOK_REGEXP = 32, /* RegExp constant */
+ TOK_PRIMARY = 33, /* true, false, null, this, super */
+ TOK_FUNCTION = 34, /* function keyword */
+ TOK_IF = 35, /* if keyword */
+ TOK_ELSE = 36, /* else keyword */
+ TOK_SWITCH = 37, /* switch keyword */
+ TOK_CASE = 38, /* case keyword */
+ TOK_DEFAULT = 39, /* default keyword */
+ TOK_WHILE = 40, /* while keyword */
+ TOK_DO = 41, /* do keyword */
+ TOK_FOR = 42, /* for keyword */
+ TOK_BREAK = 43, /* break keyword */
+ TOK_CONTINUE = 44, /* continue keyword */
+ TOK_IN = 45, /* in keyword */
+ TOK_VAR = 46, /* var keyword */
+ TOK_WITH = 47, /* with keyword */
+ TOK_RETURN = 48, /* return keyword */
+ TOK_NEW = 49, /* new keyword */
+ TOK_DELETE = 50, /* delete keyword */
+ TOK_DEFSHARP = 51, /* #n= for object/array initializers */
+ TOK_USESHARP = 52, /* #n# for object/array initializers */
+ TOK_TRY = 53, /* try keyword */
+ TOK_CATCH = 54, /* catch keyword */
+ TOK_FINALLY = 55, /* finally keyword */
+ TOK_THROW = 56, /* throw keyword */
+ TOK_INSTANCEOF = 57, /* instanceof keyword */
+ TOK_DEBUGGER = 58, /* debugger keyword */
+ TOK_XMLSTAGO = 59, /* XML start tag open (<) */
+ TOK_XMLETAGO = 60, /* XML end tag open (</) */
+ TOK_XMLPTAGC = 61, /* XML point tag close (/>) */
+ TOK_XMLTAGC = 62, /* XML start or end tag close (>) */
+ TOK_XMLNAME = 63, /* XML start-tag non-final fragment */
+ TOK_XMLATTR = 64, /* XML quoted attribute value */
+ TOK_XMLSPACE = 65, /* XML whitespace */
+ TOK_XMLTEXT = 66, /* XML text */
+ TOK_XMLCOMMENT = 67, /* XML comment */
+ TOK_XMLCDATA = 68, /* XML CDATA section */
+ TOK_XMLPI = 69, /* XML processing instruction */
+ TOK_AT = 70, /* XML attribute op (@) */
+ TOK_DBLCOLON = 71, /* namespace qualified name op (::) */
+ TOK_ANYNAME = 72, /* XML AnyName singleton (*) */
+ TOK_DBLDOT = 73, /* XML descendant op (..) */
+ TOK_FILTER = 74, /* XML filtering predicate op (.()) */
+ TOK_XMLELEM = 75, /* XML element node type (no token) */
+ TOK_XMLLIST = 76, /* XML list node type (no token) */
+ TOK_YIELD = 77, /* yield from generator function */
+ TOK_ARRAYCOMP = 78, /* array comprehension initialiser */
+ TOK_ARRAYPUSH = 79, /* array push within comprehension */
+ TOK_LEXICALSCOPE = 80, /* block scope AST node label */
+ TOK_LET = 81, /* let keyword */
+ TOK_SEQ = 82, /* synthetic sequence of statements,
+ not a block */
+ TOK_FORHEAD = 83, /* head of for(;;)-style loop */
+ TOK_RESERVED, /* reserved keywords */
+ TOK_LIMIT /* domain size */
+} JSTokenType;
+
+#define IS_PRIMARY_TOKEN(tt) \
+ ((uintN)((tt) - TOK_NAME) <= (uintN)(TOK_PRIMARY - TOK_NAME))
+
+#define TOKEN_TYPE_IS_XML(tt) \
+ (tt == TOK_AT || tt == TOK_DBLCOLON || tt == TOK_ANYNAME)
+
+#if JS_HAS_BLOCK_SCOPE
+# define TOKEN_TYPE_IS_DECL(tt) ((tt) == TOK_VAR || (tt) == TOK_LET)
+#else
+# define TOKEN_TYPE_IS_DECL(tt) ((tt) == TOK_VAR)
+#endif
+
+struct JSStringBuffer {
+ jschar *base;
+ jschar *limit; /* length limit for quick bounds check */
+ jschar *ptr; /* slot for next non-NUL char to store */
+ void *data;
+ JSBool (*grow)(JSStringBuffer *sb, size_t newlength);
+ void (*free)(JSStringBuffer *sb);
+};
+
+#define STRING_BUFFER_ERROR_BASE ((jschar *) 1)
+#define STRING_BUFFER_OK(sb) ((sb)->base != STRING_BUFFER_ERROR_BASE)
+#define STRING_BUFFER_OFFSET(sb) ((sb)->ptr -(sb)->base)
+
+extern void
+js_InitStringBuffer(JSStringBuffer *sb);
+
+extern void
+js_FinishStringBuffer(JSStringBuffer *sb);
+
+extern void
+js_AppendChar(JSStringBuffer *sb, jschar c);
+
+extern void
+js_RepeatChar(JSStringBuffer *sb, jschar c, uintN count);
+
+extern void
+js_AppendCString(JSStringBuffer *sb, const char *asciiz);
+
+extern void
+js_AppendUCString(JSStringBuffer *sb, const jschar *buf, uintN len);
+
+extern void
+js_AppendJSString(JSStringBuffer *sb, JSString *str);
+
+struct JSTokenPtr {
+ uint16 index; /* index of char in physical line */
+ uint16 lineno; /* physical line number */
+};
+
+struct JSTokenPos {
+ JSTokenPtr begin; /* first character and line of token */
+ JSTokenPtr end; /* index 1 past last char, last line */
+};
+
+struct JSToken {
+ JSTokenType type; /* char value or above enumerator */
+ JSTokenPos pos; /* token position in file */
+ jschar *ptr; /* beginning of token in line buffer */
+ union {
+ struct { /* name or string literal */
+ JSOp op; /* operator, for minimal parser */
+ JSAtom *atom; /* atom table entry */
+ } s;
+ uintN reflags; /* regexp flags, use tokenbuf to access
+ regexp chars */
+ struct { /* atom pair, for XML PIs */
+ JSAtom *atom2; /* auxiliary atom table entry */
+ JSAtom *atom; /* main atom table entry */
+ } p;
+ jsdouble dval; /* floating point number */
+ } u;
+};
+
+#define t_op u.s.op
+#define t_reflags u.reflags
+#define t_atom u.s.atom
+#define t_atom2 u.p.atom2
+#define t_dval u.dval
+
+typedef struct JSTokenBuf {
+ jschar *base; /* base of line or stream buffer */
+ jschar *limit; /* limit for quick bounds check */
+ jschar *ptr; /* next char to get, or slot to use */
+} JSTokenBuf;
+
+#define JS_LINE_LIMIT 256 /* logical line buffer size limit --
+ physical line length is unlimited */
+#define NTOKENS 4 /* 1 current + 2 lookahead, rounded */
+#define NTOKENS_MASK (NTOKENS-1) /* to power of 2 to avoid divmod by 3 */
+
+struct JSTokenStream {
+ JSToken tokens[NTOKENS];/* circular token buffer */
+ uintN cursor; /* index of last parsed token */
+ uintN lookahead; /* count of lookahead tokens */
+ uintN lineno; /* current line number */
+ uintN ungetpos; /* next free char slot in ungetbuf */
+ jschar ungetbuf[6]; /* at most 6, for \uXXXX lookahead */
+ uintN flags; /* flags -- see below */
+ ptrdiff_t linelen; /* physical linebuf segment length */
+ ptrdiff_t linepos; /* linebuf offset in physical line */
+ JSTokenBuf linebuf; /* line buffer for diagnostics */
+ JSTokenBuf userbuf; /* user input buffer if !file */
+ JSStringBuffer tokenbuf; /* current token string buffer */
+ const char *filename; /* input filename or null */
+ FILE *file; /* stdio stream if reading from file */
+ JSSourceHandler listener; /* callback for source; eg debugger */
+ void *listenerData; /* listener 'this' data */
+ void *listenerTSData;/* listener data for this TokenStream */
+ jschar *saveEOL; /* save next end of line in userbuf, to
+ optimize for very long lines */
+};
+
+#define CURRENT_TOKEN(ts) ((ts)->tokens[(ts)->cursor])
+#define ON_CURRENT_LINE(ts,pos) ((uint16)(ts)->lineno == (pos).end.lineno)
+
+/* JSTokenStream flags */
+#define TSF_ERROR 0x01 /* fatal error while compiling */
+#define TSF_EOF 0x02 /* hit end of file */
+#define TSF_NEWLINES 0x04 /* tokenize newlines */
+#define TSF_OPERAND 0x08 /* looking for operand, not operator */
+#define TSF_NLFLAG 0x20 /* last linebuf ended with \n */
+#define TSF_CRFLAG 0x40 /* linebuf would have ended with \r */
+#define TSF_DIRTYLINE 0x80 /* non-whitespace since start of line */
+#define TSF_OWNFILENAME 0x100 /* ts->filename is malloc'd */
+#define TSF_XMLTAGMODE 0x200 /* scanning within an XML tag in E4X */
+#define TSF_XMLTEXTMODE 0x400 /* scanning XMLText terminal from E4X */
+#define TSF_XMLONLYMODE 0x800 /* don't scan {expr} within text/tag */
+
+/* Flag indicating unexpected end of input, i.e. TOK_EOF not at top-level. */
+#define TSF_UNEXPECTED_EOF 0x1000
+
+/*
+ * To handle the hard case of contiguous HTML comments, we want to clear the
+ * TSF_DIRTYINPUT flag at the end of each such comment. But we'd rather not
+ * scan for --> within every //-style comment unless we have to. So we set
+ * TSF_IN_HTML_COMMENT when a <!-- is scanned as an HTML begin-comment, and
+ * clear it (and TSF_DIRTYINPUT) when we scan --> either on a clean line, or
+ * only if (ts->flags & TSF_IN_HTML_COMMENT), in a //-style comment.
+ *
+ * This still works as before given a malformed comment hiding hack such as:
+ *
+ * <script>
+ * <!-- comment hiding hack #1
+ * code goes here
+ * // --> oops, markup for script-unaware browsers goes here!
+ * </script>
+ *
+ * It does not cope with malformed comment hiding hacks where --> is hidden
+ * by C-style comments, or on a dirty line. Such cases are already broken.
+ */
+#define TSF_IN_HTML_COMMENT 0x2000
+
+/* Ignore keywords and return TOK_NAME instead to the parser. */
+#define TSF_KEYWORD_IS_NAME 0x4000
+
+/* Unicode separators that are treated as line terminators, in addition to \n, \r */
+#define LINE_SEPARATOR 0x2028
+#define PARA_SEPARATOR 0x2029
+
+/*
+ * Create a new token stream, either from an input buffer or from a file.
+ * Return null on file-open or memory-allocation failure.
+ *
+ * The function uses JSContext.tempPool to allocate internal buffers. The
+ * caller should release them using JS_ARENA_RELEASE after it has finished
+ * with the token stream and has called js_CloseTokenStream.
+ */
+extern JSBool
+js_InitTokenStream(JSContext *cx, JSTokenStream *ts,
+ const jschar *base, size_t length,
+ FILE *fp, const char *filename, uintN lineno);
+
+extern void
+js_CloseTokenStream(JSContext *cx, JSTokenStream *ts);
+
+extern JS_FRIEND_API(int)
+js_fgets(char *buf, int size, FILE *file);
+
+/*
+ * If the given char array forms JavaScript keyword, return corresponding
+ * token. Otherwise return TOK_EOF.
+ */
+extern JSTokenType
+js_CheckKeyword(const jschar *chars, size_t length);
+
+/*
+ * Friend-exported API entry point to call a mapping function on each reserved
+ * identifier in the scanner's keyword table.
+ */
+extern JS_FRIEND_API(void)
+js_MapKeywords(void (*mapfun)(const char *));
+
+/*
+ * Check that str forms a valid JS identifier name. The function does not
+ * check if str is a JS keyword.
+ */
+extern JSBool
+js_IsIdentifier(JSString *str);
+
+/*
+ * Report a compile-time error by its number. Return true for a warning, false
+ * for an error. When pn is not null, use it to report error's location.
+ * Otherwise use ts, which must not be null.
+ */
+JSBool
+js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, JSParseNode *pn,
+ uintN flags, uintN errorNumber, ...);
+
+/*
+ * Steal one JSREPORT_* bit (see jsapi.h) to tell that arguments to the error
+ * message have const jschar* type, not const char*.
+ */
+#define JSREPORT_UC 0x100
+
+/*
+ * Look ahead one token and return its type.
+ */
+extern JSTokenType
+js_PeekToken(JSContext *cx, JSTokenStream *ts);
+
+extern JSTokenType
+js_PeekTokenSameLine(JSContext *cx, JSTokenStream *ts);
+
+/*
+ * Get the next token from ts.
+ */
+extern JSTokenType
+js_GetToken(JSContext *cx, JSTokenStream *ts);
+
+/*
+ * Push back the last scanned token onto ts.
+ */
+extern void
+js_UngetToken(JSTokenStream *ts);
+
+/*
+ * Get the next token from ts if its type is tt.
+ */
+extern JSBool
+js_MatchToken(JSContext *cx, JSTokenStream *ts, JSTokenType tt);
+
+JS_END_EXTERN_C
+
+#endif /* jsscan_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscope.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsscope.cpp
new file mode 100644
index 0000000..1f9bc0c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscope.cpp
@@ -0,0 +1,1955 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS symbol tables.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h"
+#include "jsbit.h"
+#include "jsclist.h"
+#include "jsdhash.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsdbgapi.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsscope.h"
+#include "jsstr.h"
+
+JSScope *
+js_GetMutableScope(JSContext *cx, JSObject *obj)
+{
+ JSScope *scope, *newscope;
+ JSClass *clasp;
+ uint32 freeslot;
+
+ scope = OBJ_SCOPE(obj);
+ JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
+ if (scope->object == obj)
+ return scope;
+ newscope = js_NewScope(cx, 0, scope->map.ops, LOCKED_OBJ_GET_CLASS(obj),
+ obj);
+ if (!newscope)
+ return NULL;
+ JS_LOCK_SCOPE(cx, newscope);
+ obj->map = js_HoldObjectMap(cx, &newscope->map);
+ JS_ASSERT(newscope->map.freeslot == JSSLOT_FREE(STOBJ_GET_CLASS(obj)));
+ clasp = STOBJ_GET_CLASS(obj);
+ if (clasp->reserveSlots) {
+ freeslot = JSSLOT_FREE(clasp) + clasp->reserveSlots(cx, obj);
+ if (freeslot > STOBJ_NSLOTS(obj))
+ freeslot = STOBJ_NSLOTS(obj);
+ if (newscope->map.freeslot < freeslot)
+ newscope->map.freeslot = freeslot;
+ }
+ scope = (JSScope *) js_DropObjectMap(cx, &scope->map, obj);
+ JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope);
+ return newscope;
+}
+
+/*
+ * JSScope uses multiplicative hashing, _a la_ jsdhash.[ch], but specialized
+ * to minimize footprint. But if a scope has fewer than SCOPE_HASH_THRESHOLD
+ * entries, we use linear search and avoid allocating scope->table.
+ */
+#define SCOPE_HASH_THRESHOLD 6
+#define MIN_SCOPE_SIZE_LOG2 4
+#define MIN_SCOPE_SIZE JS_BIT(MIN_SCOPE_SIZE_LOG2)
+#define SCOPE_TABLE_NBYTES(n) ((n) * sizeof(JSScopeProperty *))
+
+static void
+InitMinimalScope(JSScope *scope)
+{
+ scope->shape = 0;
+ scope->hashShift = JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2;
+ scope->entryCount = scope->removedCount = 0;
+ scope->table = NULL;
+ scope->lastProp = NULL;
+}
+
+static JSBool
+CreateScopeTable(JSContext *cx, JSScope *scope, JSBool report)
+{
+ int sizeLog2;
+ JSScopeProperty *sprop, **spp;
+
+ JS_ASSERT(!scope->table);
+ JS_ASSERT(scope->lastProp);
+
+ if (scope->entryCount > SCOPE_HASH_THRESHOLD) {
+ /*
+ * Either we're creating a table for a large scope that was populated
+ * via property cache hit logic under JSOP_INITPROP, JSOP_SETNAME, or
+ * JSOP_SETPROP; or else calloc failed at least once already. In any
+ * event, let's try to grow, overallocating to hold at least twice the
+ * current population.
+ */
+ sizeLog2 = JS_CeilingLog2(2 * scope->entryCount);
+ scope->hashShift = JS_DHASH_BITS - sizeLog2;
+ } else {
+ JS_ASSERT(scope->hashShift == JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2);
+ sizeLog2 = MIN_SCOPE_SIZE_LOG2;
+ }
+
+ scope->table = (JSScopeProperty **)
+ calloc(JS_BIT(sizeLog2), sizeof(JSScopeProperty *));
+ if (!scope->table) {
+ if (report)
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ js_UpdateMallocCounter(cx, JS_BIT(sizeLog2) * sizeof(JSScopeProperty *));
+
+ scope->hashShift = JS_DHASH_BITS - sizeLog2;
+ for (sprop = scope->lastProp; sprop; sprop = sprop->parent) {
+ spp = js_SearchScope(scope, sprop->id, JS_TRUE);
+ SPROP_STORE_PRESERVING_COLLISION(spp, sprop);
+ }
+ return JS_TRUE;
+}
+
+JSScope *
+js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp,
+ JSObject *obj)
+{
+ JSScope *scope;
+
+ scope = (JSScope *) JS_malloc(cx, sizeof(JSScope));
+ if (!scope)
+ return NULL;
+
+ js_InitObjectMap(&scope->map, nrefs, ops, clasp);
+ scope->object = obj;
+ scope->flags = 0;
+ InitMinimalScope(scope);
+
+#ifdef JS_THREADSAFE
+ js_InitTitle(cx, &scope->title);
+#endif
+ JS_RUNTIME_METER(cx->runtime, liveScopes);
+ JS_RUNTIME_METER(cx->runtime, totalScopes);
+ return scope;
+}
+
+#ifdef DEBUG_SCOPE_COUNT
+extern void
+js_unlog_scope(JSScope *scope);
+#endif
+
+#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS
+# include "jsprf.h"
+# define LIVE_SCOPE_METER(cx,expr) JS_LOCK_RUNTIME_VOID(cx->runtime,expr)
+#else
+# define LIVE_SCOPE_METER(cx,expr) /* nothing */
+#endif
+
+void
+js_DestroyScope(JSContext *cx, JSScope *scope)
+{
+#ifdef DEBUG_SCOPE_COUNT
+ js_unlog_scope(scope);
+#endif
+
+#ifdef JS_THREADSAFE
+ js_FinishTitle(cx, &scope->title);
+#endif
+ if (scope->table)
+ JS_free(cx, scope->table);
+
+ LIVE_SCOPE_METER(cx, cx->runtime->liveScopeProps -= scope->entryCount);
+ JS_RUNTIME_UNMETER(cx->runtime, liveScopes);
+ JS_free(cx, scope);
+}
+
+#ifdef JS_DUMP_PROPTREE_STATS
+typedef struct JSScopeStats {
+ jsrefcount searches;
+ jsrefcount hits;
+ jsrefcount misses;
+ jsrefcount hashes;
+ jsrefcount steps;
+ jsrefcount stepHits;
+ jsrefcount stepMisses;
+ jsrefcount adds;
+ jsrefcount redundantAdds;
+ jsrefcount addFailures;
+ jsrefcount changeFailures;
+ jsrefcount compresses;
+ jsrefcount grows;
+ jsrefcount removes;
+ jsrefcount removeFrees;
+ jsrefcount uselessRemoves;
+ jsrefcount shrinks;
+} JSScopeStats;
+
+JS_FRIEND_DATA(JSScopeStats) js_scope_stats = {0};
+
+# define METER(x) JS_ATOMIC_INCREMENT(&js_scope_stats.x)
+#else
+# define METER(x) /* nothing */
+#endif
+
+JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
+JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
+
+#if JS_BYTES_PER_WORD == 4
+# define HASH_ID(id) ((JSHashNumber)(id))
+#elif JS_BYTES_PER_WORD == 8
+# define HASH_ID(id) ((JSHashNumber)(id) ^ (JSHashNumber)((id) >> 32))
+#else
+# error "Unsupported configuration"
+#endif
+
+/*
+ * Double hashing needs the second hash code to be relatively prime to table
+ * size, so we simply make hash2 odd. The inputs to multiplicative hash are
+ * the golden ratio, expressed as a fixed-point 32 bit fraction, and the id
+ * itself.
+ */
+#define SCOPE_HASH0(id) (HASH_ID(id) * JS_GOLDEN_RATIO)
+#define SCOPE_HASH1(hash0,shift) ((hash0) >> (shift))
+#define SCOPE_HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1)
+
+JS_FRIEND_API(JSScopeProperty **)
+js_SearchScope(JSScope *scope, jsid id, JSBool adding)
+{
+ JSHashNumber hash0, hash1, hash2;
+ int hashShift, sizeLog2;
+ JSScopeProperty *stored, *sprop, **spp, **firstRemoved;
+ uint32 sizeMask;
+
+ METER(searches);
+ if (!scope->table) {
+ /* Not enough properties to justify hashing: search from lastProp. */
+ JS_ASSERT(!SCOPE_HAD_MIDDLE_DELETE(scope));
+ for (spp = &scope->lastProp; (sprop = *spp); spp = &sprop->parent) {
+ if (sprop->id == id) {
+ METER(hits);
+ return spp;
+ }
+ }
+ METER(misses);
+ return spp;
+ }
+
+ /* Compute the primary hash address. */
+ METER(hashes);
+ hash0 = SCOPE_HASH0(id);
+ hashShift = scope->hashShift;
+ hash1 = SCOPE_HASH1(hash0, hashShift);
+ spp = scope->table + hash1;
+
+ /* Miss: return space for a new entry. */
+ stored = *spp;
+ if (SPROP_IS_FREE(stored)) {
+ METER(misses);
+ return spp;
+ }
+
+ /* Hit: return entry. */
+ sprop = SPROP_CLEAR_COLLISION(stored);
+ if (sprop && sprop->id == id) {
+ METER(hits);
+ return spp;
+ }
+
+ /* Collision: double hash. */
+ sizeLog2 = JS_DHASH_BITS - hashShift;
+ hash2 = SCOPE_HASH2(hash0, sizeLog2, hashShift);
+ sizeMask = JS_BITMASK(sizeLog2);
+
+ /* Save the first removed entry pointer so we can recycle it if adding. */
+ if (SPROP_IS_REMOVED(stored)) {
+ firstRemoved = spp;
+ } else {
+ firstRemoved = NULL;
+ if (adding && !SPROP_HAD_COLLISION(stored))
+ SPROP_FLAG_COLLISION(spp, sprop);
+ }
+
+ for (;;) {
+ METER(steps);
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+ spp = scope->table + hash1;
+
+ stored = *spp;
+ if (SPROP_IS_FREE(stored)) {
+ METER(stepMisses);
+ return (adding && firstRemoved) ? firstRemoved : spp;
+ }
+
+ sprop = SPROP_CLEAR_COLLISION(stored);
+ if (sprop && sprop->id == id) {
+ METER(stepHits);
+ return spp;
+ }
+
+ if (SPROP_IS_REMOVED(stored)) {
+ if (!firstRemoved)
+ firstRemoved = spp;
+ } else {
+ if (adding && !SPROP_HAD_COLLISION(stored))
+ SPROP_FLAG_COLLISION(spp, sprop);
+ }
+ }
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+static JSBool
+ChangeScope(JSContext *cx, JSScope *scope, int change)
+{
+ int oldlog2, newlog2;
+ uint32 oldsize, newsize, nbytes;
+ JSScopeProperty **table, **oldtable, **spp, **oldspp, *sprop;
+
+ if (!scope->table)
+ return CreateScopeTable(cx, scope, JS_TRUE);
+
+ /* Grow, shrink, or compress by changing scope->table. */
+ oldlog2 = JS_DHASH_BITS - scope->hashShift;
+ newlog2 = oldlog2 + change;
+ oldsize = JS_BIT(oldlog2);
+ newsize = JS_BIT(newlog2);
+ nbytes = SCOPE_TABLE_NBYTES(newsize);
+ table = (JSScopeProperty **) calloc(nbytes, 1);
+ if (!table) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ /* Now that we have a new table allocated, update scope members. */
+ scope->hashShift = JS_DHASH_BITS - newlog2;
+ scope->removedCount = 0;
+ oldtable = scope->table;
+ scope->table = table;
+
+ /* Treat the above calloc as a JS_malloc, to match CreateScopeTable. */
+ cx->runtime->gcMallocBytes += nbytes;
+
+ /* Copy only live entries, leaving removed and free ones behind. */
+ for (oldspp = oldtable; oldsize != 0; oldspp++) {
+ sprop = SPROP_FETCH(oldspp);
+ if (sprop) {
+ spp = js_SearchScope(scope, sprop->id, JS_TRUE);
+ JS_ASSERT(SPROP_IS_FREE(*spp));
+ *spp = sprop;
+ }
+ oldsize--;
+ }
+
+ /* Finally, free the old table storage. */
+ JS_free(cx, oldtable);
+ return JS_TRUE;
+}
+
+/*
+ * Take care to exclude the mark bits in case we're called from the GC.
+ */
+#define SPROP_FLAGS_NOT_MATCHED (SPROP_MARK | SPROP_FLAG_SHAPE_REGEN)
+
+static JSDHashNumber
+js_HashScopeProperty(JSDHashTable *table, const void *key)
+{
+ const JSScopeProperty *sprop = (const JSScopeProperty *)key;
+ JSDHashNumber hash;
+ JSPropertyOp gsop;
+
+ /* Accumulate from least to most random so the low bits are most random. */
+ hash = 0;
+ gsop = sprop->getter;
+ if (gsop)
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ (jsword)gsop;
+ gsop = sprop->setter;
+ if (gsop)
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ (jsword)gsop;
+
+ hash = JS_ROTATE_LEFT32(hash, 4)
+ ^ (sprop->flags & ~SPROP_FLAGS_NOT_MATCHED);
+
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->attrs;
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->shortid;
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->slot;
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->id;
+ return hash;
+}
+
+#define SPROP_MATCH(sprop, child) \
+ SPROP_MATCH_PARAMS(sprop, (child)->id, (child)->getter, (child)->setter, \
+ (child)->slot, (child)->attrs, (child)->flags, \
+ (child)->shortid)
+
+#define SPROP_MATCH_PARAMS(sprop, aid, agetter, asetter, aslot, aattrs, \
+ aflags, ashortid) \
+ ((sprop)->id == (aid) && \
+ SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs, \
+ aflags, ashortid))
+
+#define SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs, \
+ aflags, ashortid) \
+ ((sprop)->getter == (agetter) && \
+ (sprop)->setter == (asetter) && \
+ (sprop)->slot == (aslot) && \
+ (sprop)->attrs == (aattrs) && \
+ (((sprop)->flags ^ (aflags)) & ~SPROP_FLAGS_NOT_MATCHED) == 0 && \
+ (sprop)->shortid == (ashortid))
+
+static JSBool
+js_MatchScopeProperty(JSDHashTable *table,
+ const JSDHashEntryHdr *hdr,
+ const void *key)
+{
+ const JSPropertyTreeEntry *entry = (const JSPropertyTreeEntry *)hdr;
+ const JSScopeProperty *sprop = entry->child;
+ const JSScopeProperty *kprop = (const JSScopeProperty *)key;
+
+ return SPROP_MATCH(sprop, kprop);
+}
+
+static const JSDHashTableOps PropertyTreeHashOps = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ js_HashScopeProperty,
+ js_MatchScopeProperty,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+/*
+ * A property tree node on rt->propertyFreeList overlays the following prefix
+ * struct on JSScopeProperty.
+ */
+typedef struct FreeNode {
+ jsid id;
+ JSScopeProperty *next;
+ JSScopeProperty **prevp;
+} FreeNode;
+
+#define FREENODE(sprop) ((FreeNode *) (sprop))
+
+#define FREENODE_INSERT(list, sprop) \
+ JS_BEGIN_MACRO \
+ FREENODE(sprop)->next = (list); \
+ FREENODE(sprop)->prevp = &(list); \
+ if (list) \
+ FREENODE(list)->prevp = &FREENODE(sprop)->next; \
+ (list) = (sprop); \
+ JS_END_MACRO
+
+#define FREENODE_REMOVE(sprop) \
+ JS_BEGIN_MACRO \
+ *FREENODE(sprop)->prevp = FREENODE(sprop)->next; \
+ if (FREENODE(sprop)->next) \
+ FREENODE(FREENODE(sprop)->next)->prevp = FREENODE(sprop)->prevp; \
+ JS_END_MACRO
+
+/* NB: Called with rt->gcLock held. */
+static JSScopeProperty *
+NewScopeProperty(JSRuntime *rt)
+{
+ JSScopeProperty *sprop;
+
+ sprop = rt->propertyFreeList;
+ if (sprop) {
+ FREENODE_REMOVE(sprop);
+ } else {
+ JS_ARENA_ALLOCATE_CAST(sprop, JSScopeProperty *,
+ &rt->propertyArenaPool,
+ sizeof(JSScopeProperty));
+ if (!sprop)
+ return NULL;
+ }
+
+ JS_RUNTIME_METER(rt, livePropTreeNodes);
+ JS_RUNTIME_METER(rt, totalPropTreeNodes);
+ return sprop;
+}
+
+#define CHUNKY_KIDS_TAG ((jsuword)1)
+#define KIDS_IS_CHUNKY(kids) ((jsuword)(kids) & CHUNKY_KIDS_TAG)
+#define KIDS_TO_CHUNK(kids) ((PropTreeKidsChunk *) \
+ ((jsuword)(kids) & ~CHUNKY_KIDS_TAG))
+#define CHUNK_TO_KIDS(chunk) ((JSScopeProperty *) \
+ ((jsuword)(chunk) | CHUNKY_KIDS_TAG))
+#define MAX_KIDS_PER_CHUNK 10
+#define CHUNK_HASH_THRESHOLD 30
+
+typedef struct PropTreeKidsChunk PropTreeKidsChunk;
+
+struct PropTreeKidsChunk {
+ JSScopeProperty *kids[MAX_KIDS_PER_CHUNK];
+ JSDHashTable *table;
+ PropTreeKidsChunk *next;
+};
+
+static PropTreeKidsChunk *
+NewPropTreeKidsChunk(JSRuntime *rt)
+{
+ PropTreeKidsChunk *chunk;
+
+ chunk = (PropTreeKidsChunk *) calloc(1, sizeof *chunk);
+ if (!chunk)
+ return NULL;
+ JS_ASSERT(((jsuword)chunk & CHUNKY_KIDS_TAG) == 0);
+ JS_RUNTIME_METER(rt, propTreeKidsChunks);
+ return chunk;
+}
+
+static void
+DestroyPropTreeKidsChunk(JSRuntime *rt, PropTreeKidsChunk *chunk)
+{
+ JS_RUNTIME_UNMETER(rt, propTreeKidsChunks);
+ if (chunk->table)
+ JS_DHashTableDestroy(chunk->table);
+ free(chunk);
+}
+
+/* NB: Called with rt->gcLock held. */
+static JSBool
+InsertPropertyTreeChild(JSRuntime *rt, JSScopeProperty *parent,
+ JSScopeProperty *child, PropTreeKidsChunk *sweptChunk)
+{
+ JSDHashTable *table;
+ JSPropertyTreeEntry *entry;
+ JSScopeProperty **childp, *kids, *sprop;
+ PropTreeKidsChunk *chunk, **chunkp;
+ uintN i;
+
+ JS_ASSERT(!parent || child->parent != parent);
+
+ if (!parent) {
+ table = &rt->propertyTreeHash;
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, child, JS_DHASH_ADD);
+ if (!entry)
+ return JS_FALSE;
+ childp = &entry->child;
+ sprop = *childp;
+ if (!sprop) {
+ *childp = child;
+ } else {
+ /*
+ * A "Duplicate child" case.
+ *
+ * We can't do away with child, as at least one live scope entry
+ * still points at it. What's more, that scope's lastProp chains
+ * through an ancestor line to reach child, and js_Enumerate and
+ * others count on this linkage. We must leave child out of the
+ * hash table, and not require it to be there when we eventually
+ * GC it (see RemovePropertyTreeChild, below).
+ *
+ * It is necessary to leave the duplicate child out of the hash
+ * table to preserve entry uniqueness. It is safe to leave the
+ * child out of the hash table (unlike the duplicate child cases
+ * below), because the child's parent link will be null, which
+ * can't dangle.
+ */
+ JS_ASSERT(sprop != child && SPROP_MATCH(sprop, child));
+ JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
+ }
+ } else {
+ childp = &parent->kids;
+ kids = *childp;
+ if (kids) {
+ if (KIDS_IS_CHUNKY(kids)) {
+ chunk = KIDS_TO_CHUNK(kids);
+
+ table = chunk->table;
+ if (table) {
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, child, JS_DHASH_ADD);
+ if (!entry)
+ return JS_FALSE;
+ if (!entry->child) {
+ entry->child = child;
+ while (chunk->next)
+ chunk = chunk->next;
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ childp = &chunk->kids[i];
+ sprop = *childp;
+ if (!sprop)
+ goto insert;
+ }
+ chunkp = &chunk->next;
+ goto new_chunk;
+ }
+ }
+
+ do {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ childp = &chunk->kids[i];
+ sprop = *childp;
+ if (!sprop)
+ goto insert;
+
+ JS_ASSERT(sprop != child);
+ if (SPROP_MATCH(sprop, child)) {
+ /*
+ * Duplicate child, see comment above. In this
+ * case, we must let the duplicate be inserted at
+ * this level in the tree, so we keep iterating,
+ * looking for an empty slot in which to insert.
+ */
+ JS_ASSERT(sprop != child);
+ JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
+ }
+ }
+ chunkp = &chunk->next;
+ } while ((chunk = *chunkp) != NULL);
+
+ new_chunk:
+ if (sweptChunk) {
+ chunk = sweptChunk;
+ } else {
+ chunk = NewPropTreeKidsChunk(rt);
+ if (!chunk)
+ return JS_FALSE;
+ }
+ *chunkp = chunk;
+ childp = &chunk->kids[0];
+ } else {
+ sprop = kids;
+ JS_ASSERT(sprop != child);
+ if (SPROP_MATCH(sprop, child)) {
+ /*
+ * Duplicate child, see comment above. Once again, we
+ * must let duplicates created by deletion pile up in a
+ * kids-chunk-list, in order to find them when sweeping
+ * and thereby avoid dangling parent pointers.
+ */
+ JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
+ }
+ if (sweptChunk) {
+ chunk = sweptChunk;
+ } else {
+ chunk = NewPropTreeKidsChunk(rt);
+ if (!chunk)
+ return JS_FALSE;
+ }
+ parent->kids = CHUNK_TO_KIDS(chunk);
+ chunk->kids[0] = sprop;
+ childp = &chunk->kids[1];
+ }
+ }
+ insert:
+ *childp = child;
+ }
+
+ child->parent = parent;
+ return JS_TRUE;
+}
+
+/* NB: Called with rt->gcLock held. */
+static PropTreeKidsChunk *
+RemovePropertyTreeChild(JSRuntime *rt, JSScopeProperty *child)
+{
+ PropTreeKidsChunk *freeChunk;
+ JSScopeProperty *parent, *kids, *kid;
+ JSDHashTable *table;
+ PropTreeKidsChunk *list, *chunk, **chunkp, *lastChunk;
+ uintN i, j;
+ JSPropertyTreeEntry *entry;
+
+ freeChunk = NULL;
+ parent = child->parent;
+ if (!parent) {
+ /*
+ * Don't remove child if it is not in rt->propertyTreeHash, but only
+ * matches a root child in the table that has compatible members. See
+ * the "Duplicate child" comments in InsertPropertyTreeChild, above.
+ */
+ table = &rt->propertyTreeHash;
+ } else {
+ kids = parent->kids;
+ if (KIDS_IS_CHUNKY(kids)) {
+ list = chunk = KIDS_TO_CHUNK(kids);
+ chunkp = &list;
+ table = chunk->table;
+
+ do {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ if (chunk->kids[i] == child) {
+ lastChunk = chunk;
+ if (!lastChunk->next) {
+ j = i + 1;
+ } else {
+ j = 0;
+ do {
+ chunkp = &lastChunk->next;
+ lastChunk = *chunkp;
+ } while (lastChunk->next);
+ }
+ for (; j < MAX_KIDS_PER_CHUNK; j++) {
+ if (!lastChunk->kids[j])
+ break;
+ }
+ --j;
+ if (chunk != lastChunk || j > i)
+ chunk->kids[i] = lastChunk->kids[j];
+ lastChunk->kids[j] = NULL;
+ if (j == 0) {
+ *chunkp = NULL;
+ if (!list)
+ parent->kids = NULL;
+ freeChunk = lastChunk;
+ }
+ goto out;
+ }
+ }
+
+ chunkp = &chunk->next;
+ } while ((chunk = *chunkp) != NULL);
+ } else {
+ table = NULL;
+ kid = kids;
+ if (kid == child)
+ parent->kids = NULL;
+ }
+ }
+
+out:
+ if (table) {
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, child, JS_DHASH_LOOKUP);
+
+ if (entry->child == child)
+ JS_DHashTableRawRemove(table, &entry->hdr);
+ }
+ return freeChunk;
+}
+
+static JSDHashTable *
+HashChunks(PropTreeKidsChunk *chunk, uintN n)
+{
+ JSDHashTable *table;
+ uintN i;
+ JSScopeProperty *sprop;
+ JSPropertyTreeEntry *entry;
+
+ table = JS_NewDHashTable(&PropertyTreeHashOps, NULL,
+ sizeof(JSPropertyTreeEntry),
+ JS_DHASH_DEFAULT_CAPACITY(n + 1));
+ if (!table)
+ return NULL;
+ do {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ sprop = chunk->kids[i];
+ if (!sprop)
+ break;
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, sprop, JS_DHASH_ADD);
+ entry->child = sprop;
+ }
+ } while ((chunk = chunk->next) != NULL);
+ return table;
+}
+
+/*
+ * Called without cx->runtime->gcLock held. This function acquires that lock
+ * only when inserting a new child. Thus there may be races to find or add a
+ * node that result in duplicates. We expect such races to be rare!
+ *
+ * We use rt->gcLock, not rt->rtLock, to allow the GC potentially to nest here
+ * under js_GenerateShape.
+ */
+static JSScopeProperty *
+GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent,
+ JSScopeProperty *child)
+{
+ JSRuntime *rt;
+ JSDHashTable *table;
+ JSPropertyTreeEntry *entry;
+ JSScopeProperty *sprop;
+ PropTreeKidsChunk *chunk;
+ uintN i, n;
+ uint32 shape;
+
+ rt = cx->runtime;
+ if (!parent) {
+ JS_LOCK_GC(rt);
+
+ table = &rt->propertyTreeHash;
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, child, JS_DHASH_ADD);
+ if (!entry)
+ goto out_of_memory;
+
+ sprop = entry->child;
+ if (sprop)
+ goto out;
+ } else {
+ /*
+ * Because chunks are appended at the end and never deleted except by
+ * the GC, we can search without taking the runtime's GC lock. We may
+ * miss a matching sprop added by another thread, and make a duplicate
+ * one, but that is an unlikely, therefore small, cost. The property
+ * tree has extremely low fan-out below its root in popular embeddings
+ * with real-world workloads.
+ *
+ * Patterns such as defining closures that capture a constructor's
+ * environment as getters or setters on the new object that is passed
+ * in as |this| can significantly increase fan-out below the property
+ * tree root -- see bug 335700 for details.
+ */
+ entry = NULL;
+ sprop = parent->kids;
+ if (sprop) {
+ if (KIDS_IS_CHUNKY(sprop)) {
+ chunk = KIDS_TO_CHUNK(sprop);
+
+ table = chunk->table;
+ if (table) {
+ JS_LOCK_GC(rt);
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, child, JS_DHASH_LOOKUP);
+ sprop = entry->child;
+ if (sprop) {
+ JS_UNLOCK_GC(rt);
+ return sprop;
+ }
+ goto locked_not_found;
+ }
+
+ n = 0;
+ do {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ sprop = chunk->kids[i];
+ if (!sprop) {
+ n += i;
+ if (n >= CHUNK_HASH_THRESHOLD) {
+ chunk = KIDS_TO_CHUNK(parent->kids);
+ if (!chunk->table) {
+ table = HashChunks(chunk, n);
+ JS_LOCK_GC(rt);
+ if (!table)
+ goto out_of_memory;
+ if (chunk->table)
+ JS_DHashTableDestroy(table);
+ else
+ chunk->table = table;
+ goto locked_not_found;
+ }
+ }
+ goto not_found;
+ }
+
+ if (SPROP_MATCH(sprop, child))
+ return sprop;
+ }
+ n += MAX_KIDS_PER_CHUNK;
+ } while ((chunk = chunk->next) != NULL);
+ } else {
+ if (SPROP_MATCH(sprop, child))
+ return sprop;
+ }
+ }
+
+ not_found:
+ JS_LOCK_GC(rt);
+ }
+
+locked_not_found:
+ /*
+ * Call js_GenerateShape before the allocation to prevent collecting the
+ * new property when the shape generation triggers the GC.
+ */
+ shape = js_GenerateShape(cx, JS_TRUE, NULL);
+
+ sprop = NewScopeProperty(rt);
+ if (!sprop)
+ goto out_of_memory;
+
+ sprop->id = child->id;
+ sprop->getter = child->getter;
+ sprop->setter = child->setter;
+ sprop->slot = child->slot;
+ sprop->attrs = child->attrs;
+ sprop->flags = child->flags;
+ sprop->shortid = child->shortid;
+ sprop->parent = sprop->kids = NULL;
+ sprop->shape = shape;
+
+ if (!parent) {
+ entry->child = sprop;
+ } else {
+ if (!InsertPropertyTreeChild(rt, parent, sprop, NULL))
+ goto out_of_memory;
+ }
+
+out:
+ JS_UNLOCK_GC(rt);
+ return sprop;
+
+out_of_memory:
+ JS_UNLOCK_GC(rt);
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+}
+
+#ifdef DEBUG_notbrendan
+#define CHECK_ANCESTOR_LINE(scope, sparse) \
+ JS_BEGIN_MACRO \
+ if ((scope)->table) CheckAncestorLine(scope, sparse); \
+ JS_END_MACRO
+
+static void
+CheckAncestorLine(JSScope *scope, JSBool sparse)
+{
+ uint32 size;
+ JSScopeProperty **spp, **start, **end, *ancestorLine, *sprop, *aprop;
+ uint32 entryCount, ancestorCount;
+
+ ancestorLine = SCOPE_LAST_PROP(scope);
+ if (ancestorLine)
+ JS_ASSERT(SCOPE_HAS_PROPERTY(scope, ancestorLine));
+
+ entryCount = 0;
+ size = SCOPE_CAPACITY(scope);
+ start = scope->table;
+ for (spp = start, end = start + size; spp < end; spp++) {
+ sprop = SPROP_FETCH(spp);
+ if (sprop) {
+ entryCount++;
+ for (aprop = ancestorLine; aprop; aprop = aprop->parent) {
+ if (aprop == sprop)
+ break;
+ }
+ JS_ASSERT(aprop);
+ }
+ }
+ JS_ASSERT(entryCount == scope->entryCount);
+
+ ancestorCount = 0;
+ for (sprop = ancestorLine; sprop; sprop = sprop->parent) {
+ if (SCOPE_HAD_MIDDLE_DELETE(scope) &&
+ !SCOPE_HAS_PROPERTY(scope, sprop)) {
+ JS_ASSERT(sparse);
+ continue;
+ }
+ ancestorCount++;
+ }
+ JS_ASSERT(ancestorCount == scope->entryCount);
+}
+#else
+#define CHECK_ANCESTOR_LINE(scope, sparse) /* nothing */
+#endif
+
+static void
+ReportReadOnlyScope(JSContext *cx, JSScope *scope)
+{
+ JSString *str;
+ const char *bytes;
+
+ str = js_ValueToString(cx, OBJECT_TO_JSVAL(scope->object));
+ if (!str)
+ return;
+ bytes = js_GetStringBytes(cx, str);
+ if (!bytes)
+ return;
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_READ_ONLY, bytes);
+}
+
+JSScopeProperty *
+js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id,
+ JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
+ uintN attrs, uintN flags, intN shortid)
+{
+ JSScopeProperty **spp, *sprop, *overwriting, **spvec, **spp2, child;
+ uint32 size, splen, i;
+ int change;
+ JSTempValueRooter tvr;
+
+ JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+
+ /*
+ * You can't add properties to a sealed scope. But note well that you can
+ * change property attributes in a sealed scope, even though that replaces
+ * a JSScopeProperty * in the scope's hash table -- but no id is added, so
+ * the scope remains sealed.
+ */
+ if (SCOPE_IS_SEALED(scope)) {
+ ReportReadOnlyScope(cx, scope);
+ return NULL;
+ }
+
+ /*
+ * Normalize stub getter and setter values for faster is-stub testing in
+ * the SPROP_CALL_[GS]ETTER macros.
+ */
+ if (getter == JS_PropertyStub)
+ getter = NULL;
+ if (setter == JS_PropertyStub)
+ setter = NULL;
+
+ /*
+ * Search for id in order to claim its entry, allocating a property tree
+ * node if one doesn't already exist for our parameters.
+ */
+ spp = js_SearchScope(scope, id, JS_TRUE);
+ sprop = overwriting = SPROP_FETCH(spp);
+ if (!sprop) {
+ JS_COUNT_OPERATION(cx, JSOW_NEW_PROPERTY);
+
+ /* Check whether we need to grow, if the load factor is >= .75. */
+ size = SCOPE_CAPACITY(scope);
+ if (scope->entryCount + scope->removedCount >= size - (size >> 2)) {
+ if (scope->removedCount >= size >> 2) {
+ METER(compresses);
+ change = 0;
+ } else {
+ METER(grows);
+ change = 1;
+ }
+ if (!ChangeScope(cx, scope, change) &&
+ scope->entryCount + scope->removedCount == size - 1) {
+ METER(addFailures);
+ return NULL;
+ }
+ spp = js_SearchScope(scope, id, JS_TRUE);
+ JS_ASSERT(!SPROP_FETCH(spp));
+ }
+ } else {
+ /* Property exists: js_SearchScope must have returned a valid entry. */
+ JS_ASSERT(!SPROP_IS_REMOVED(*spp));
+
+ /*
+ * If all property members match, this is a redundant add and we can
+ * return early. If the caller wants to allocate a slot, but doesn't
+ * care which slot, copy sprop->slot into slot so we can match sprop,
+ * if all other members match.
+ */
+ if (!(attrs & JSPROP_SHARED) &&
+ slot == SPROP_INVALID_SLOT &&
+ SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ slot = sprop->slot;
+ }
+ if (SPROP_MATCH_PARAMS_AFTER_ID(sprop, getter, setter, slot, attrs,
+ flags, shortid)) {
+ METER(redundantAdds);
+ return sprop;
+ }
+
+ /*
+ * If we are clearing sprop to force an existing property to be
+ * overwritten (apart from a duplicate formal parameter), we must
+ * unlink it from the ancestor line at scope->lastProp, lazily if
+ * sprop is not lastProp. And we must remove the entry at *spp,
+ * precisely so the lazy "middle delete" fixup code further below
+ * won't find sprop in scope->table, in spite of sprop being on
+ * the ancestor line.
+ *
+ * When we finally succeed in finding or creating a new sprop
+ * and storing its pointer at *spp, we'll use the |overwriting|
+ * local saved when we first looked up id to decide whether we're
+ * indeed creating a new entry, or merely overwriting an existing
+ * property.
+ */
+ if (sprop == SCOPE_LAST_PROP(scope)) {
+ do {
+ SCOPE_REMOVE_LAST_PROP(scope);
+ if (!SCOPE_HAD_MIDDLE_DELETE(scope))
+ break;
+ sprop = SCOPE_LAST_PROP(scope);
+ } while (sprop && !SCOPE_HAS_PROPERTY(scope, sprop));
+ } else if (!SCOPE_HAD_MIDDLE_DELETE(scope)) {
+ /*
+ * If we have no hash table yet, we need one now. The middle
+ * delete code is simple-minded that way!
+ */
+ if (!scope->table) {
+ if (!CreateScopeTable(cx, scope, JS_TRUE))
+ return NULL;
+ spp = js_SearchScope(scope, id, JS_TRUE);
+ sprop = overwriting = SPROP_FETCH(spp);
+ }
+ SCOPE_SET_MIDDLE_DELETE(scope);
+ }
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+
+ /*
+ * If we fail later on trying to find or create a new sprop, we will
+ * goto fail_overwrite and restore *spp from |overwriting|. Note that
+ * we don't bother to keep scope->removedCount in sync, because we'll
+ * fix up *spp and scope->entryCount shortly, no matter how control
+ * flow returns from this function.
+ */
+ if (scope->table)
+ SPROP_STORE_PRESERVING_COLLISION(spp, NULL);
+ scope->entryCount--;
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+ sprop = NULL;
+ }
+
+ if (!sprop) {
+ /*
+ * If properties were deleted from the middle of the list starting at
+ * scope->lastProp, we may need to fork the property tree and squeeze
+ * all deleted properties out of scope's ancestor line. Otherwise we
+ * risk adding a node with the same id as a "middle" node, violating
+ * the rule that properties along an ancestor line have distinct ids.
+ */
+ if (SCOPE_HAD_MIDDLE_DELETE(scope)) {
+ JS_ASSERT(scope->table);
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+
+ splen = scope->entryCount;
+ if (splen == 0) {
+ JS_ASSERT(scope->lastProp == NULL);
+ } else {
+ /*
+ * Enumerate live entries in scope->table using a temporary
+ * vector, by walking the (possibly sparse, due to deletions)
+ * ancestor line from scope->lastProp.
+ */
+ spvec = (JSScopeProperty **)
+ JS_malloc(cx, SCOPE_TABLE_NBYTES(splen));
+ if (!spvec)
+ goto fail_overwrite;
+ i = splen;
+ sprop = SCOPE_LAST_PROP(scope);
+ JS_ASSERT(sprop);
+ do {
+ /*
+ * NB: test SCOPE_GET_PROPERTY, not SCOPE_HAS_PROPERTY --
+ * the latter insists that sprop->id maps to sprop, while
+ * the former simply tests whether sprop->id is bound in
+ * scope. We must allow for duplicate formal parameters
+ * along the ancestor line, and fork them as needed.
+ */
+ if (!SCOPE_GET_PROPERTY(scope, sprop->id))
+ continue;
+
+ JS_ASSERT(sprop != overwriting);
+ if (i == 0) {
+ /*
+ * If our original splen estimate, scope->entryCount,
+ * is less than the ancestor line height, there must
+ * be duplicate formal parameters in this (function
+ * object) scope. Count remaining ancestors in order
+ * to realloc spvec.
+ */
+ JSScopeProperty *tmp = sprop;
+ do {
+ if (SCOPE_GET_PROPERTY(scope, tmp->id))
+ i++;
+ } while ((tmp = tmp->parent) != NULL);
+ spp2 = (JSScopeProperty **)
+ JS_realloc(cx, spvec, SCOPE_TABLE_NBYTES(splen+i));
+ if (!spp2) {
+ JS_free(cx, spvec);
+ goto fail_overwrite;
+ }
+
+ spvec = spp2;
+ memmove(spvec + i, spvec, SCOPE_TABLE_NBYTES(splen));
+ splen += i;
+ }
+
+ spvec[--i] = sprop;
+ } while ((sprop = sprop->parent) != NULL);
+ JS_ASSERT(i == 0);
+
+ /*
+ * Now loop forward through spvec, forking the property tree
+ * whenever we see a "parent gap" due to deletions from scope.
+ * NB: sprop is null on first entry to the loop body.
+ */
+ do {
+ if (spvec[i]->parent == sprop) {
+ sprop = spvec[i];
+ } else {
+ sprop = GetPropertyTreeChild(cx, sprop, spvec[i]);
+ if (!sprop) {
+ JS_free(cx, spvec);
+ goto fail_overwrite;
+ }
+
+ spp2 = js_SearchScope(scope, sprop->id, JS_FALSE);
+ JS_ASSERT(SPROP_FETCH(spp2) == spvec[i]);
+ SPROP_STORE_PRESERVING_COLLISION(spp2, sprop);
+ }
+ } while (++i < splen);
+ JS_free(cx, spvec);
+
+ /*
+ * Now sprop points to the last property in scope, where the
+ * ancestor line from sprop to the root is dense w.r.t. scope:
+ * it contains no nodes not mapped by scope->table, apart from
+ * any stinking ECMA-mandated duplicate formal parameters.
+ */
+ scope->lastProp = sprop;
+ CHECK_ANCESTOR_LINE(scope, JS_FALSE);
+ JS_RUNTIME_METER(cx->runtime, middleDeleteFixups);
+ }
+
+ SCOPE_CLR_MIDDLE_DELETE(scope);
+ }
+
+ /*
+ * Aliases share another property's slot, passed in the |slot| param.
+ * Shared properties have no slot. Unshared properties that do not
+ * alias another property's slot get one here, but may lose it due to
+ * a JS_ClearScope call.
+ */
+ if (!(flags & SPROP_IS_ALIAS)) {
+ if (attrs & JSPROP_SHARED) {
+ slot = SPROP_INVALID_SLOT;
+ } else {
+ /*
+ * We may have set slot from a nearly-matching sprop, above.
+ * If so, we're overwriting that nearly-matching sprop, so we
+ * can reuse its slot -- we don't need to allocate a new one.
+ * Similarly, we use a specific slot if provided by the caller.
+ */
+ if (slot == SPROP_INVALID_SLOT &&
+ !js_AllocSlot(cx, scope->object, &slot)) {
+ goto fail_overwrite;
+ }
+ }
+ }
+
+ /*
+ * Check for a watchpoint on a deleted property; if one exists, change
+ * setter to js_watch_set.
+ * XXXbe this could get expensive with lots of watchpoints...
+ */
+ if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList) &&
+ js_FindWatchPoint(cx->runtime, scope, id)) {
+ JS_PUSH_TEMP_ROOT_SPROP(cx, overwriting, &tvr);
+ setter = js_WrapWatchedSetter(cx, id, attrs, setter);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!setter)
+ goto fail_overwrite;
+ }
+
+ /* Find or create a property tree node labeled by our arguments. */
+ child.id = id;
+ child.getter = getter;
+ child.setter = setter;
+ child.slot = slot;
+ child.attrs = attrs;
+ child.flags = flags;
+ child.shortid = shortid;
+ sprop = GetPropertyTreeChild(cx, scope->lastProp, &child);
+ if (!sprop)
+ goto fail_overwrite;
+
+ /*
+ * The scope's shape defaults to its last property's shape, but may
+ * be regenerated later as the scope diverges (from the property cache
+ * point of view) from the structural type associated with sprop.
+ */
+ SCOPE_EXTEND_SHAPE(cx, scope, sprop);
+
+ /* Store the tree node pointer in the table entry for id. */
+ if (scope->table)
+ SPROP_STORE_PRESERVING_COLLISION(spp, sprop);
+ scope->entryCount++;
+ scope->lastProp = sprop;
+ CHECK_ANCESTOR_LINE(scope, JS_FALSE);
+#ifdef DEBUG
+ if (!overwriting) {
+ LIVE_SCOPE_METER(cx, ++cx->runtime->liveScopeProps);
+ JS_RUNTIME_METER(cx->runtime, totalScopeProps);
+ }
+#endif
+
+ /*
+ * If we reach the hashing threshold, try to allocate scope->table.
+ * If we can't (a rare event, preceded by swapping to death on most
+ * modern OSes), stick with linear search rather than whining about
+ * this little set-back. Therefore we must test !scope->table and
+ * scope->entryCount >= SCOPE_HASH_THRESHOLD, not merely whether the
+ * entry count just reached the threshold.
+ */
+ if (!scope->table && scope->entryCount >= SCOPE_HASH_THRESHOLD)
+ (void) CreateScopeTable(cx, scope, JS_FALSE);
+ }
+
+ METER(adds);
+ return sprop;
+
+fail_overwrite:
+ if (overwriting) {
+ /*
+ * We may or may not have forked overwriting out of scope's ancestor
+ * line, so we must check (the alternative is to set a flag above, but
+ * that hurts the common, non-error case). If we did fork overwriting
+ * out, we'll add it back at scope->lastProp. This means enumeration
+ * order can change due to a failure to overwrite an id.
+ * XXXbe very minor incompatibility
+ */
+ for (sprop = SCOPE_LAST_PROP(scope); ; sprop = sprop->parent) {
+ if (!sprop) {
+ sprop = SCOPE_LAST_PROP(scope);
+ if (overwriting->parent == sprop) {
+ scope->lastProp = overwriting;
+ } else {
+ sprop = GetPropertyTreeChild(cx, sprop, overwriting);
+ if (sprop) {
+ JS_ASSERT(sprop != overwriting);
+ scope->lastProp = sprop;
+ }
+ overwriting = sprop;
+ }
+ break;
+ }
+ if (sprop == overwriting)
+ break;
+ }
+ if (overwriting) {
+ if (scope->table)
+ SPROP_STORE_PRESERVING_COLLISION(spp, overwriting);
+ scope->entryCount++;
+ }
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+ }
+ METER(addFailures);
+ return NULL;
+}
+
+JSScopeProperty *
+js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope,
+ JSScopeProperty *sprop, uintN attrs, uintN mask,
+ JSPropertyOp getter, JSPropertyOp setter)
+{
+ JSScopeProperty child, *newsprop, **spp;
+
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+
+ /* Allow only shared (slot-less) => unshared (slot-full) transition. */
+ attrs |= sprop->attrs & mask;
+ JS_ASSERT(!((attrs ^ sprop->attrs) & JSPROP_SHARED) ||
+ !(attrs & JSPROP_SHARED));
+ if (getter == JS_PropertyStub)
+ getter = NULL;
+ if (setter == JS_PropertyStub)
+ setter = NULL;
+ if (sprop->attrs == attrs &&
+ sprop->getter == getter &&
+ sprop->setter == setter) {
+ return sprop;
+ }
+
+ child.id = sprop->id;
+ child.getter = getter;
+ child.setter = setter;
+ child.slot = sprop->slot;
+ child.attrs = attrs;
+ child.flags = sprop->flags;
+ child.shortid = sprop->shortid;
+
+ if (SCOPE_LAST_PROP(scope) == sprop) {
+ /*
+ * Optimize the case where the last property added to scope is changed
+ * to have a different attrs, getter, or setter. In the last property
+ * case, we need not fork the property tree. But since we do not call
+ * js_AddScopeProperty, we may need to allocate a new slot directly.
+ */
+ if ((sprop->attrs & JSPROP_SHARED) && !(attrs & JSPROP_SHARED)) {
+ JS_ASSERT(child.slot == SPROP_INVALID_SLOT);
+ if (!js_AllocSlot(cx, scope->object, &child.slot))
+ return NULL;
+ }
+
+ newsprop = GetPropertyTreeChild(cx, sprop->parent, &child);
+ if (newsprop) {
+ spp = js_SearchScope(scope, sprop->id, JS_FALSE);
+ JS_ASSERT(SPROP_FETCH(spp) == sprop);
+
+ if (scope->table)
+ SPROP_STORE_PRESERVING_COLLISION(spp, newsprop);
+ scope->lastProp = newsprop;
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+ }
+ } else {
+ /*
+ * Let js_AddScopeProperty handle this |overwriting| case, including
+ * the conservation of sprop->slot (if it's valid). We must not call
+ * js_RemoveScopeProperty here, it will free a valid sprop->slot and
+ * js_AddScopeProperty won't re-allocate it.
+ */
+ newsprop = js_AddScopeProperty(cx, scope, child.id,
+ child.getter, child.setter, child.slot,
+ child.attrs, child.flags, child.shortid);
+ }
+
+ if (newsprop) {
+ if (scope->shape == sprop->shape)
+ scope->shape = newsprop->shape;
+ else
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ }
+#ifdef JS_DUMP_PROPTREE_STATS
+ else
+ METER(changeFailures);
+#endif
+ return newsprop;
+}
+
+JSBool
+js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id)
+{
+ JSScopeProperty **spp, *stored, *sprop;
+ uint32 size;
+
+ JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+ if (SCOPE_IS_SEALED(scope)) {
+ ReportReadOnlyScope(cx, scope);
+ return JS_FALSE;
+ }
+ METER(removes);
+
+ spp = js_SearchScope(scope, id, JS_FALSE);
+ stored = *spp;
+ sprop = SPROP_CLEAR_COLLISION(stored);
+ if (!sprop) {
+ METER(uselessRemoves);
+ return JS_TRUE;
+ }
+
+ /* Convert from a list to a hash so we can handle "middle deletes". */
+ if (!scope->table && sprop != scope->lastProp) {
+ if (!CreateScopeTable(cx, scope, JS_TRUE))
+ return JS_FALSE;
+ spp = js_SearchScope(scope, id, JS_FALSE);
+ stored = *spp;
+ sprop = SPROP_CLEAR_COLLISION(stored);
+ }
+
+ /* First, if sprop is unshared and not cleared, free its slot number. */
+ if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ js_FreeSlot(cx, scope->object, sprop->slot);
+ JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
+ }
+
+ /* Next, remove id by setting its entry to a removed or free sentinel. */
+ if (SPROP_HAD_COLLISION(stored)) {
+ JS_ASSERT(scope->table);
+ *spp = SPROP_REMOVED;
+ scope->removedCount++;
+ } else {
+ METER(removeFrees);
+ if (scope->table)
+ *spp = NULL;
+ }
+ scope->entryCount--;
+ LIVE_SCOPE_METER(cx, --cx->runtime->liveScopeProps);
+
+ /* Update scope->lastProp directly, or set its deferred update flag. */
+ if (sprop == SCOPE_LAST_PROP(scope)) {
+ do {
+ SCOPE_REMOVE_LAST_PROP(scope);
+ if (!SCOPE_HAD_MIDDLE_DELETE(scope))
+ break;
+ sprop = SCOPE_LAST_PROP(scope);
+ } while (sprop && !SCOPE_HAS_PROPERTY(scope, sprop));
+ } else if (!SCOPE_HAD_MIDDLE_DELETE(scope)) {
+ SCOPE_SET_MIDDLE_DELETE(scope);
+ }
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+
+ /* Last, consider shrinking scope's table if its load factor is <= .25. */
+ size = SCOPE_CAPACITY(scope);
+ if (size > MIN_SCOPE_SIZE && scope->entryCount <= size >> 2) {
+ METER(shrinks);
+ (void) ChangeScope(cx, scope, -1);
+ }
+
+ return JS_TRUE;
+}
+
+void
+js_ClearScope(JSContext *cx, JSScope *scope)
+{
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+ LIVE_SCOPE_METER(cx, cx->runtime->liveScopeProps -= scope->entryCount);
+
+ if (scope->table)
+ free(scope->table);
+ SCOPE_CLR_MIDDLE_DELETE(scope);
+ InitMinimalScope(scope);
+ JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
+}
+
+void
+js_TraceId(JSTracer *trc, jsid id)
+{
+ jsval v;
+
+ v = ID_TO_VALUE(id);
+ JS_CALL_VALUE_TRACER(trc, v, "id");
+}
+
+#ifdef DEBUG
+static void
+PrintPropertyGetterOrSetter(JSTracer *trc, char *buf, size_t bufsize)
+{
+ JSScopeProperty *sprop;
+ jsid id;
+ size_t n;
+ const char *name;
+
+ JS_ASSERT(trc->debugPrinter == PrintPropertyGetterOrSetter);
+ sprop = (JSScopeProperty *)trc->debugPrintArg;
+ id = sprop->id;
+ name = trc->debugPrintIndex ? js_setter_str : js_getter_str;
+
+ if (JSID_IS_ATOM(id)) {
+ n = js_PutEscapedString(buf, bufsize - 1,
+ ATOM_TO_STRING(JSID_TO_ATOM(id)), 0);
+ if (n < bufsize - 1)
+ JS_snprintf(buf + n, bufsize - n, " %s", name);
+ } else if (JSID_IS_INT(sprop->id)) {
+ JS_snprintf(buf, bufsize, "%d %s", JSID_TO_INT(id), name);
+ } else {
+ JS_snprintf(buf, bufsize, "<object> %s", name);
+ }
+}
+#endif
+
+
+void
+js_TraceScopeProperty(JSTracer *trc, JSScopeProperty *sprop)
+{
+ if (IS_GC_MARKING_TRACER(trc))
+ sprop->flags |= SPROP_MARK;
+ TRACE_ID(trc, sprop->id);
+
+#if JS_HAS_GETTER_SETTER
+ if (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
+ if (sprop->attrs & JSPROP_GETTER) {
+ JS_ASSERT(JSVAL_IS_OBJECT((jsval) sprop->getter));
+ JS_SET_TRACING_DETAILS(trc, PrintPropertyGetterOrSetter, sprop, 0);
+ JS_CallTracer(trc, JSVAL_TO_OBJECT((jsval) sprop->getter),
+ JSTRACE_OBJECT);
+ }
+ if (sprop->attrs & JSPROP_SETTER) {
+ JS_ASSERT(JSVAL_IS_OBJECT((jsval) sprop->setter));
+ JS_SET_TRACING_DETAILS(trc, PrintPropertyGetterOrSetter, sprop, 1);
+ JS_CallTracer(trc, JSVAL_TO_OBJECT((jsval) sprop->setter),
+ JSTRACE_OBJECT);
+ }
+ }
+#endif /* JS_HAS_GETTER_SETTER */
+}
+
+#ifdef JS_DUMP_PROPTREE_STATS
+
+#include <stdio.h>
+
+static void
+MeterKidCount(JSBasicStats *bs, uintN nkids)
+{
+ JS_BASIC_STATS_ACCUM(bs, nkids);
+ bs->hist[JS_MIN(nkids, 10)]++;
+}
+
+static void
+MeterPropertyTree(JSBasicStats *bs, JSScopeProperty *node)
+{
+ uintN i, nkids;
+ JSScopeProperty *kids, *kid;
+ PropTreeKidsChunk *chunk;
+
+ nkids = 0;
+ kids = node->kids;
+ if (kids) {
+ if (KIDS_IS_CHUNKY(kids)) {
+ for (chunk = KIDS_TO_CHUNK(kids); chunk; chunk = chunk->next) {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ kid = chunk->kids[i];
+ if (!kid)
+ break;
+ MeterPropertyTree(bs, kid);
+ nkids++;
+ }
+ }
+ } else {
+ MeterPropertyTree(bs, kids);
+ nkids = 1;
+ }
+ }
+
+ MeterKidCount(bs, nkids);
+}
+
+static JSDHashOperator
+js_MeterPropertyTree(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
+ void *arg)
+{
+ JSPropertyTreeEntry *entry = (JSPropertyTreeEntry *)hdr;
+ JSBasicStats *bs = (JSBasicStats *)arg;
+
+ MeterPropertyTree(bs, entry->child);
+ return JS_DHASH_NEXT;
+}
+
+static void
+DumpSubtree(JSContext *cx, JSScopeProperty *sprop, int level, FILE *fp)
+{
+ jsval v;
+ JSString *str;
+ JSScopeProperty *kids, *kid;
+ PropTreeKidsChunk *chunk;
+ uintN i;
+
+ fprintf(fp, "%*sid ", level, "");
+ v = ID_TO_VALUE(sprop->id);
+ if (JSID_IS_INT(sprop->id)) {
+ fprintf(fp, "%d", JSVAL_TO_INT(v));
+ } else {
+ if (JSID_IS_ATOM(sprop->id)) {
+ str = JSVAL_TO_STRING(v);
+ } else {
+ JS_ASSERT(JSID_IS_OBJECT(sprop->id));
+ str = js_ValueToString(cx, v);
+ fputs("object ", fp);
+ }
+ if (!str)
+ fputs("<error>", fp);
+ else
+ js_FileEscapedString(fp, str, '"');
+ }
+
+ fprintf(fp, " g/s %p/%p slot %u attrs %x flags %x shortid %d\n",
+ (void *) sprop->getter, (void *) sprop->setter, sprop->slot,
+ sprop->attrs, sprop->flags, sprop->shortid);
+ kids = sprop->kids;
+ if (kids) {
+ ++level;
+ if (KIDS_IS_CHUNKY(kids)) {
+ chunk = KIDS_TO_CHUNK(kids);
+ do {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ kid = chunk->kids[i];
+ if (!kid)
+ break;
+ JS_ASSERT(kid->parent == sprop);
+ DumpSubtree(cx, kid, level, fp);
+ }
+ } while ((chunk = chunk->next) != NULL);
+ } else {
+ kid = kids;
+ DumpSubtree(cx, kid, level, fp);
+ }
+ }
+}
+
+#endif /* JS_DUMP_PROPTREE_STATS */
+
+void
+js_SweepScopeProperties(JSContext *cx)
+{
+ JSRuntime *rt = cx->runtime;
+ JSArena **ap, *a;
+ JSScopeProperty *limit, *sprop, *parent, *kids, *kid;
+ uintN liveCount;
+ PropTreeKidsChunk *chunk, *nextChunk, *freeChunk;
+ uintN i;
+
+#ifdef JS_DUMP_PROPTREE_STATS
+ JSBasicStats bs;
+ uint32 livePropCapacity = 0, totalLiveCount = 0;
+ static FILE *logfp;
+ if (!logfp)
+ logfp = fopen("/tmp/proptree.stats", "w");
+
+ JS_BASIC_STATS_INIT(&bs);
+ MeterKidCount(&bs, rt->propertyTreeHash.entryCount);
+ JS_DHashTableEnumerate(&rt->propertyTreeHash, js_MeterPropertyTree, &bs);
+
+ {
+ double props, nodes, mean, sigma;
+
+ props = rt->liveScopePropsPreSweep;
+ nodes = rt->livePropTreeNodes;
+ JS_ASSERT(nodes == bs.sum);
+ mean = JS_MeanAndStdDevBS(&bs, &sigma);
+
+ fprintf(logfp,
+ "props %g nodes %g beta %g meankids %g sigma %g max %u\n",
+ props, nodes, nodes / props, mean, sigma, bs.max);
+ }
+
+ JS_DumpHistogram(&bs, logfp);
+#endif
+
+ ap = &rt->propertyArenaPool.first.next;
+ while ((a = *ap) != NULL) {
+ limit = (JSScopeProperty *) a->avail;
+ liveCount = 0;
+ for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++) {
+ /* If the id is null, sprop is already on the freelist. */
+ if (sprop->id == JSVAL_NULL)
+ continue;
+
+ /*
+ * If the mark bit is set, sprop is alive, so clear the mark bit
+ * and continue the while loop.
+ *
+ * Regenerate sprop->shape if it hasn't already been refreshed
+ * during the mark phase, when live scopes' lastProp members are
+ * followed to update both scope->shape and lastProp->shape.
+ */
+ if (sprop->flags & SPROP_MARK) {
+ sprop->flags &= ~SPROP_MARK;
+ if (sprop->flags & SPROP_FLAG_SHAPE_REGEN) {
+ sprop->flags &= ~SPROP_FLAG_SHAPE_REGEN;
+ } else {
+ sprop->shape = ++cx->runtime->shapeGen;
+ JS_ASSERT(sprop->shape != 0);
+ }
+ liveCount++;
+ continue;
+ }
+
+ /* Ok, sprop is garbage to collect: unlink it from its parent. */
+ freeChunk = RemovePropertyTreeChild(rt, sprop);
+
+ /*
+ * Take care to reparent all sprop's kids to their grandparent.
+ * InsertPropertyTreeChild can potentially fail for two reasons:
+ *
+ * 1. If parent is null, insertion into the root property hash
+ * table may fail. We are forced to leave the kid out of the
+ * table (as can already happen with duplicates) but ensure
+ * that the kid's parent pointer is set to null.
+ *
+ * 2. If parent is non-null, allocation of a new KidsChunk can
+ * fail. To prevent this from happening, we allow sprops's own
+ * chunks to be reused by the grandparent, which removes the
+ * need for InsertPropertyTreeChild to malloc a new KidsChunk.
+ *
+ * If sprop does not have chunky kids, then we rely on the
+ * RemovePropertyTreeChild call above (which removed sprop from
+ * its parent) either leaving one free entry, or else returning
+ * the now-unused chunk to us so we can reuse it.
+ *
+ * We also require the grandparent to have either no kids or else
+ * chunky kids. A single non-chunky kid would force a new chunk to
+ * be malloced in some cases (if sprop had a single non-chunky
+ * kid, or a multiple of MAX_KIDS_PER_CHUNK kids). Note that
+ * RemovePropertyTreeChild never converts a single-entry chunky
+ * kid back to a non-chunky kid, so we are assured of correct
+ * behaviour.
+ */
+ kids = sprop->kids;
+ if (kids) {
+ sprop->kids = NULL;
+ parent = sprop->parent;
+
+ /* Assert that grandparent has no kids or chunky kids. */
+ JS_ASSERT(!parent || !parent->kids ||
+ KIDS_IS_CHUNKY(parent->kids));
+ if (KIDS_IS_CHUNKY(kids)) {
+ chunk = KIDS_TO_CHUNK(kids);
+ do {
+ nextChunk = chunk->next;
+ chunk->next = NULL;
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ kid = chunk->kids[i];
+ if (!kid)
+ break;
+ JS_ASSERT(kid->parent == sprop);
+
+ /*
+ * Clear a space in the kids array for possible
+ * re-use by InsertPropertyTreeChild.
+ */
+ chunk->kids[i] = NULL;
+ if (!InsertPropertyTreeChild(rt, parent, kid,
+ chunk)) {
+ /*
+ * This can happen only if we failed to add an
+ * entry to the root property hash table.
+ */
+ JS_ASSERT(!parent);
+ kid->parent = NULL;
+ }
+ }
+ if (!chunk->kids[0]) {
+ /* The chunk wasn't reused, so we must free it. */
+ DestroyPropTreeKidsChunk(rt, chunk);
+ }
+ } while ((chunk = nextChunk) != NULL);
+ } else {
+ kid = kids;
+ if (!InsertPropertyTreeChild(rt, parent, kid, freeChunk)) {
+ /*
+ * This can happen only if we failed to add an entry
+ * to the root property hash table.
+ */
+ JS_ASSERT(!parent);
+ kid->parent = NULL;
+ }
+ }
+ }
+
+ if (freeChunk && !freeChunk->kids[0]) {
+ /* The chunk wasn't reused, so we must free it. */
+ DestroyPropTreeKidsChunk(rt, freeChunk);
+ }
+
+ /* Clear id so we know (above) that sprop is on the freelist. */
+ sprop->id = JSVAL_NULL;
+ FREENODE_INSERT(rt->propertyFreeList, sprop);
+ JS_RUNTIME_UNMETER(rt, livePropTreeNodes);
+ }
+
+ /* If a contains no live properties, return it to the malloc heap. */
+ if (liveCount == 0) {
+ for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++)
+ FREENODE_REMOVE(sprop);
+ JS_ARENA_DESTROY(&rt->propertyArenaPool, a, ap);
+ } else {
+#ifdef JS_DUMP_PROPTREE_STATS
+ livePropCapacity += limit - (JSScopeProperty *) a->base;
+ totalLiveCount += liveCount;
+#endif
+ ap = &a->next;
+ }
+ }
+
+#ifdef JS_DUMP_PROPTREE_STATS
+ fprintf(logfp, "arenautil %g%%\n",
+ (totalLiveCount && livePropCapacity)
+ ? (totalLiveCount * 100.0) / livePropCapacity
+ : 0.0);
+
+#define RATE(f1, f2) (((double)js_scope_stats.f1 / js_scope_stats.f2) * 100.0)
+
+ fprintf(logfp, "Scope search stats:\n"
+ " searches: %6u\n"
+ " hits: %6u %5.2f%% of searches\n"
+ " misses: %6u %5.2f%%\n"
+ " hashes: %6u %5.2f%%\n"
+ " steps: %6u %5.2f%% %5.2f%% of hashes\n"
+ " stepHits: %6u %5.2f%% %5.2f%%\n"
+ " stepMisses: %6u %5.2f%% %5.2f%%\n"
+ " adds: %6u\n"
+ " redundantAdds: %6u\n"
+ " addFailures: %6u\n"
+ " changeFailures: %6u\n"
+ " compresses: %6u\n"
+ " grows: %6u\n"
+ " removes: %6u\n"
+ " removeFrees: %6u\n"
+ " uselessRemoves: %6u\n"
+ " shrinks: %6u\n",
+ js_scope_stats.searches,
+ js_scope_stats.hits, RATE(hits, searches),
+ js_scope_stats.misses, RATE(misses, searches),
+ js_scope_stats.hashes, RATE(hashes, searches),
+ js_scope_stats.steps, RATE(steps, searches), RATE(steps, hashes),
+ js_scope_stats.stepHits,
+ RATE(stepHits, searches), RATE(stepHits, hashes),
+ js_scope_stats.stepMisses,
+ RATE(stepMisses, searches), RATE(stepMisses, hashes),
+ js_scope_stats.adds,
+ js_scope_stats.redundantAdds,
+ js_scope_stats.addFailures,
+ js_scope_stats.changeFailures,
+ js_scope_stats.compresses,
+ js_scope_stats.grows,
+ js_scope_stats.removes,
+ js_scope_stats.removeFrees,
+ js_scope_stats.uselessRemoves,
+ js_scope_stats.shrinks);
+
+#undef RATE
+
+ fflush(logfp);
+#endif
+
+#ifdef DUMP_PROPERTY_TREE
+ {
+ FILE *dumpfp = fopen("/tmp/proptree.dump", "w");
+ if (dumpfp) {
+ JSPropertyTreeEntry *pte, *end;
+
+ pte = (JSPropertyTreeEntry *) rt->propertyTreeHash.entryStore;
+ end = pte + JS_DHASH_TABLE_SIZE(&rt->propertyTreeHash);
+ while (pte < end) {
+ if (pte->child)
+ DumpSubtree(cx, pte->child, 0, dumpfp);
+ pte++;
+ }
+ fclose(dumpfp);
+ }
+ }
+#endif
+}
+
+JSBool
+js_InitPropertyTree(JSRuntime *rt)
+{
+ if (!JS_DHashTableInit(&rt->propertyTreeHash, &PropertyTreeHashOps, NULL,
+ sizeof(JSPropertyTreeEntry), JS_DHASH_MIN_SIZE)) {
+ rt->propertyTreeHash.ops = NULL;
+ return JS_FALSE;
+ }
+ JS_INIT_ARENA_POOL(&rt->propertyArenaPool, "properties",
+ 256 * sizeof(JSScopeProperty), sizeof(void *), NULL);
+ return JS_TRUE;
+}
+
+void
+js_FinishPropertyTree(JSRuntime *rt)
+{
+ if (rt->propertyTreeHash.ops) {
+ JS_DHashTableFinish(&rt->propertyTreeHash);
+ rt->propertyTreeHash.ops = NULL;
+ }
+ JS_FinishArenaPool(&rt->propertyArenaPool);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscope.h b/tools/node_modules/expresso/deps/jscoverage/js/jsscope.h
new file mode 100644
index 0000000..b7d8455
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscope.h
@@ -0,0 +1,419 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsscope_h___
+#define jsscope_h___
+/*
+ * JS symbol tables.
+ */
+#include "jstypes.h"
+#include "jslock.h"
+#include "jsobj.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Given P independent, non-unique properties each of size S words mapped by
+ * all scopes in a runtime, construct a property tree of N nodes each of size
+ * S+L words (L for tree linkage). A nominal L value is 2 for leftmost-child
+ * and right-sibling links. We hope that the N < P by enough that the space
+ * overhead of L, and the overhead of scope entries pointing at property tree
+ * nodes, is worth it.
+ *
+ * The tree construction goes as follows. If any empty scope in the runtime
+ * has a property X added to it, find or create a node under the tree root
+ * labeled X, and set scope->lastProp to point at that node. If any non-empty
+ * scope whose most recently added property is labeled Y has another property
+ * labeled Z added, find or create a node for Z under the node that was added
+ * for Y, and set scope->lastProp to point at that node.
+ *
+ * A property is labeled by its members' values: id, getter, setter, slot,
+ * attributes, tiny or short id, and a field telling for..in order. Note that
+ * labels are not unique in the tree, but they are unique among a node's kids
+ * (barring rare and benign multi-threaded race condition outcomes, see below)
+ * and along any ancestor line from the tree root to a given leaf node (except
+ * for the hard case of duplicate formal parameters to a function).
+ *
+ * Thus the root of the tree represents all empty scopes, and the first ply
+ * of the tree represents all scopes containing one property, etc. Each node
+ * in the tree can stand for any number of scopes having the same ordered set
+ * of properties, where that node was the last added to the scope. (We need
+ * not store the root of the tree as a node, and do not -- all we need are
+ * links to its kids.)
+ *
+ * Sidebar on for..in loop order: ECMA requires no particular order, but this
+ * implementation has promised and delivered property definition order, and
+ * compatibility is king. We could use an order number per property, which
+ * would require a sort in js_Enumerate, and an entry order generation number
+ * per scope. An order number beats a list, which should be doubly-linked for
+ * O(1) delete. An even better scheme is to use a parent link in the property
+ * tree, so that the ancestor line can be iterated from scope->lastProp when
+ * filling in a JSIdArray from back to front. This parent link also helps the
+ * GC to sweep properties iteratively.
+ *
+ * What if a property Y is deleted from a scope? If Y is the last property in
+ * the scope, we simply adjust the scope's lastProp member after we remove the
+ * scope's hash-table entry pointing at that property node. The parent link
+ * mentioned in the for..in sidebar above makes this adjustment O(1). But if
+ * Y comes between X and Z in the scope, then we might have to "fork" the tree
+ * at X, leaving X->Y->Z in case other scopes have those properties added in
+ * that order; and to finish the fork, we'd add a node labeled Z with the path
+ * X->Z, if it doesn't exist. This could lead to lots of extra nodes, and to
+ * O(n^2) growth when deleting lots of properties.
+ *
+ * Rather, for O(1) growth all around, we should share the path X->Y->Z among
+ * scopes having those three properties added in that order, and among scopes
+ * having only X->Z where Y was deleted. All such scopes have a lastProp that
+ * points to the Z child of Y. But a scope in which Y was deleted does not
+ * have a table entry for Y, and when iterating that scope by traversing the
+ * ancestor line from Z, we will have to test for a table entry for each node,
+ * skipping nodes that lack entries.
+ *
+ * What if we add Y again? X->Y->Z->Y is wrong and we'll enumerate Y twice.
+ * Therefore we must fork in such a case, if not earlier. Because delete is
+ * "bursty", we should not fork eagerly. Delaying a fork till we are at risk
+ * of adding Y after it was deleted already requires a flag in the JSScope, to
+ * wit, SCOPE_MIDDLE_DELETE.
+ *
+ * What about thread safety? If the property tree operations done by requests
+ * are find-node and insert-node, then the only hazard is duplicate insertion.
+ * This is harmless except for minor bloat. When all requests have ended or
+ * been suspended, the GC is free to sweep the tree after marking all nodes
+ * reachable from scopes, performing remove-node operations as needed.
+ *
+ * Is the property tree worth it compared to property storage in each table's
+ * entries? To decide, we must find the relation <> between the words used
+ * with a property tree and the words required without a tree.
+ *
+ * Model all scopes as one super-scope of capacity T entries (T a power of 2).
+ * Let alpha be the load factor of this double hash-table. With the property
+ * tree, each entry in the table is a word-sized pointer to a node that can be
+ * shared by many scopes. But all such pointers are overhead compared to the
+ * situation without the property tree, where the table stores property nodes
+ * directly, as entries each of size S words. With the property tree, we need
+ * L=2 extra words per node for siblings and kids pointers. Without the tree,
+ * (1-alpha)*S*T words are wasted on free or removed sentinel-entries required
+ * by double hashing.
+ *
+ * Therefore,
+ *
+ * (property tree) <> (no property tree)
+ * N*(S+L) + T <> S*T
+ * N*(S+L) + T <> P*S + (1-alpha)*S*T
+ * N*(S+L) + alpha*T + (1-alpha)*T <> P*S + (1-alpha)*S*T
+ *
+ * Note that P is alpha*T by definition, so
+ *
+ * N*(S+L) + P + (1-alpha)*T <> P*S + (1-alpha)*S*T
+ * N*(S+L) <> P*S - P + (1-alpha)*S*T - (1-alpha)*T
+ * N*(S+L) <> (P + (1-alpha)*T) * (S-1)
+ * N*(S+L) <> (P + (1-alpha)*P/alpha) * (S-1)
+ * N*(S+L) <> P * (1/alpha) * (S-1)
+ *
+ * Let N = P*beta for a compression ratio beta, beta <= 1:
+ *
+ * P*beta*(S+L) <> P * (1/alpha) * (S-1)
+ * beta*(S+L) <> (S-1)/alpha
+ * beta <> (S-1)/((S+L)*alpha)
+ *
+ * For S = 6 (32-bit architectures) and L = 2, the property tree wins iff
+ *
+ * beta < 5/(8*alpha)
+ *
+ * We ensure that alpha <= .75, so the property tree wins if beta < .83_. An
+ * average beta from recent Mozilla browser startups was around .6.
+ *
+ * Can we reduce L? Observe that the property tree degenerates into a list of
+ * lists if at most one property Y follows X in all scopes. In or near such a
+ * case, we waste a word on the right-sibling link outside of the root ply of
+ * the tree. Note also that the root ply tends to be large, so O(n^2) growth
+ * searching it is likely, indicating the need for hashing (but with increased
+ * thread safety costs).
+ *
+ * If only K out of N nodes in the property tree have more than one child, we
+ * could eliminate the sibling link and overlay a children list or hash-table
+ * pointer on the leftmost-child link (which would then be either null or an
+ * only-child link; the overlay could be tagged in the low bit of the pointer,
+ * or flagged elsewhere in the property tree node, although such a flag must
+ * not be considered when comparing node labels during tree search).
+ *
+ * For such a system, L = 1 + (K * averageChildrenTableSize) / N instead of 2.
+ * If K << N, L approaches 1 and the property tree wins if beta < .95.
+ *
+ * We observe that fan-out below the root ply of the property tree appears to
+ * have extremely low degree (see the MeterPropertyTree code that histograms
+ * child-counts in jsscope.c), so instead of a hash-table we use a linked list
+ * of child node pointer arrays ("kid chunks"). The details are isolated in
+ * jsscope.c; others must treat JSScopeProperty.kids as opaque. We leave it
+ * strongly typed for debug-ability of the common (null or one-kid) cases.
+ *
+ * One final twist (can you stand it?): the mean number of entries per scope
+ * in Mozilla is < 5, with a large standard deviation (~8). Instead of always
+ * allocating scope->table, we leave it null while initializing all the other
+ * scope members as if it were non-null and minimal-length. Until a property
+ * is added that crosses the threshold of 6 or more entries for hashing, or
+ * until a "middle delete" occurs, we use linear search from scope->lastProp
+ * to find a given id, and save on the space overhead of a hash table.
+ */
+
+struct JSScope {
+ JSObjectMap map; /* base class state */
+#ifdef JS_THREADSAFE
+ JSTitle title; /* lock state */
+#endif
+ JSObject *object; /* object that owns this scope */
+ uint32 shape; /* property cache shape identifier */
+ uint8 flags; /* flags, see below */
+ int8 hashShift; /* multiplicative hash shift */
+ uint16 spare; /* reserved */
+ uint32 entryCount; /* number of entries in table */
+ uint32 removedCount; /* removed entry sentinels in table */
+ JSScopeProperty **table; /* table of ptrs to shared tree nodes */
+ JSScopeProperty *lastProp; /* pointer to last property added */
+};
+
+#ifdef JS_THREADSAFE
+JS_STATIC_ASSERT(offsetof(JSScope, title) == sizeof(JSObjectMap));
+#endif
+
+#define JS_IS_SCOPE_LOCKED(cx, scope) JS_IS_TITLE_LOCKED(cx, &(scope)->title)
+
+#define OBJ_SCOPE(obj) ((JSScope *)(obj)->map)
+#define OBJ_SHAPE(obj) (OBJ_SCOPE(obj)->shape)
+
+#define SCOPE_MAKE_UNIQUE_SHAPE(cx,scope) \
+ ((scope)->shape = js_GenerateShape((cx), JS_FALSE, NULL))
+
+#define SCOPE_EXTEND_SHAPE(cx,scope,sprop) \
+ JS_BEGIN_MACRO \
+ if (!(scope)->lastProp || \
+ (scope)->shape == (scope)->lastProp->shape) { \
+ (scope)->shape = (sprop)->shape; \
+ } else { \
+ (scope)->shape = js_GenerateShape((cx), JS_FALSE, sprop); \
+ } \
+ JS_END_MACRO
+
+/* By definition, hashShift = JS_DHASH_BITS - log2(capacity). */
+#define SCOPE_CAPACITY(scope) JS_BIT(JS_DHASH_BITS-(scope)->hashShift)
+
+/* Scope flags and some macros to hide them from other files than jsscope.c. */
+#define SCOPE_MIDDLE_DELETE 0x0001
+#define SCOPE_SEALED 0x0002
+#define SCOPE_BRANDED 0x0004
+
+#define SCOPE_HAD_MIDDLE_DELETE(scope) ((scope)->flags & SCOPE_MIDDLE_DELETE)
+#define SCOPE_SET_MIDDLE_DELETE(scope) ((scope)->flags |= SCOPE_MIDDLE_DELETE)
+#define SCOPE_CLR_MIDDLE_DELETE(scope) ((scope)->flags &= ~SCOPE_MIDDLE_DELETE)
+
+#define SCOPE_IS_SEALED(scope) ((scope)->flags & SCOPE_SEALED)
+#define SCOPE_SET_SEALED(scope) ((scope)->flags |= SCOPE_SEALED)
+#if 0
+/*
+ * Don't define this, it can't be done safely because JS_LOCK_OBJ will avoid
+ * taking the lock if the object owns its scope and the scope is sealed.
+ */
+#undef SCOPE_CLR_SEALED(scope) ((scope)->flags &= ~SCOPE_SEALED)
+#endif
+
+/*
+ * A branded scope's object contains plain old methods (function-valued
+ * properties without magic getters and setters), and its scope->shape
+ * evolves whenever a function value changes.
+ */
+#define SCOPE_IS_BRANDED(scope) ((scope)->flags & SCOPE_BRANDED)
+#define SCOPE_SET_BRANDED(scope) ((scope)->flags |= SCOPE_BRANDED)
+#define SCOPE_CLR_BRANDED(scope) ((scope)->flags &= ~SCOPE_BRANDED)
+
+/*
+ * A little information hiding for scope->lastProp, in case it ever becomes
+ * a tagged pointer again.
+ */
+#define SCOPE_LAST_PROP(scope) ((scope)->lastProp)
+#define SCOPE_REMOVE_LAST_PROP(scope) ((scope)->lastProp = \
+ (scope)->lastProp->parent)
+
+struct JSScopeProperty {
+ jsid id; /* int-tagged jsval/untagged JSAtom* */
+ JSPropertyOp getter; /* getter and setter hooks or objects */
+ JSPropertyOp setter;
+ uint32 slot; /* abstract index in object slots */
+ uint8 attrs; /* attributes, see jsapi.h JSPROP_* */
+ uint8 flags; /* flags, see below for defines */
+ int16 shortid; /* tinyid, or local arg/var index */
+ JSScopeProperty *parent; /* parent node, reverse for..in order */
+ JSScopeProperty *kids; /* null, single child, or a tagged ptr
+ to many-kids data structure */
+ uint32 shape; /* property cache shape identifier */
+};
+
+/* JSScopeProperty pointer tag bit indicating a collision. */
+#define SPROP_COLLISION ((jsuword)1)
+#define SPROP_REMOVED ((JSScopeProperty *) SPROP_COLLISION)
+
+/* Macros to get and set sprop pointer values and collision flags. */
+#define SPROP_IS_FREE(sprop) ((sprop) == NULL)
+#define SPROP_IS_REMOVED(sprop) ((sprop) == SPROP_REMOVED)
+#define SPROP_IS_LIVE(sprop) ((sprop) > SPROP_REMOVED)
+#define SPROP_FLAG_COLLISION(spp,sprop) (*(spp) = (JSScopeProperty *) \
+ ((jsuword)(sprop) | SPROP_COLLISION))
+#define SPROP_HAD_COLLISION(sprop) ((jsuword)(sprop) & SPROP_COLLISION)
+#define SPROP_FETCH(spp) SPROP_CLEAR_COLLISION(*(spp))
+
+#define SPROP_CLEAR_COLLISION(sprop) \
+ ((JSScopeProperty *) ((jsuword)(sprop) & ~SPROP_COLLISION))
+
+#define SPROP_STORE_PRESERVING_COLLISION(spp, sprop) \
+ (*(spp) = (JSScopeProperty *) ((jsuword)(sprop) \
+ | SPROP_HAD_COLLISION(*(spp))))
+
+/* Bits stored in sprop->flags. */
+#define SPROP_MARK 0x01
+#define SPROP_IS_ALIAS 0x02
+#define SPROP_HAS_SHORTID 0x04
+#define SPROP_FLAG_SHAPE_REGEN 0x08
+
+/*
+ * If SPROP_HAS_SHORTID is set in sprop->flags, we use sprop->shortid rather
+ * than id when calling sprop's getter or setter.
+ */
+#define SPROP_USERID(sprop) \
+ (((sprop)->flags & SPROP_HAS_SHORTID) ? INT_TO_JSVAL((sprop)->shortid) \
+ : ID_TO_VALUE((sprop)->id))
+
+#define SPROP_INVALID_SLOT 0xffffffff
+
+#define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->map.freeslot)
+#define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope)
+
+#define SPROP_HAS_STUB_GETTER(sprop) (!(sprop)->getter)
+#define SPROP_HAS_STUB_SETTER(sprop) (!(sprop)->setter)
+
+/*
+ * NB: SPROP_GET must not be called if SPROP_HAS_STUB_GETTER(sprop).
+ */
+#define SPROP_GET(cx,sprop,obj,obj2,vp) \
+ (((sprop)->attrs & JSPROP_GETTER) \
+ ? js_InternalGetOrSet(cx, obj, (sprop)->id, \
+ OBJECT_TO_JSVAL((sprop)->getter), JSACC_READ, \
+ 0, 0, vp) \
+ : (sprop)->getter(cx, OBJ_THIS_OBJECT(cx,obj), SPROP_USERID(sprop), vp))
+
+/*
+ * NB: SPROP_SET must not be called if (SPROP_HAS_STUB_SETTER(sprop) &&
+ * !(sprop->attrs & JSPROP_GETTER)).
+ */
+#define SPROP_SET(cx,sprop,obj,obj2,vp) \
+ (((sprop)->attrs & JSPROP_SETTER) \
+ ? js_InternalGetOrSet(cx, obj, (sprop)->id, \
+ OBJECT_TO_JSVAL((sprop)->setter), JSACC_WRITE, \
+ 1, vp, vp) \
+ : ((sprop)->attrs & JSPROP_GETTER) \
+ ? (JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, \
+ JSMSG_GETTER_ONLY, NULL), JS_FALSE) \
+ : (sprop)->setter(cx, OBJ_THIS_OBJECT(cx,obj), SPROP_USERID(sprop), vp))
+
+/* Macro for common expression to test for shared permanent attributes. */
+#define SPROP_IS_SHARED_PERMANENT(sprop) \
+ ((~(sprop)->attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0)
+
+extern JSScope *
+js_GetMutableScope(JSContext *cx, JSObject *obj);
+
+extern JSScope *
+js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp,
+ JSObject *obj);
+
+extern void
+js_DestroyScope(JSContext *cx, JSScope *scope);
+
+extern JS_FRIEND_API(JSScopeProperty **)
+js_SearchScope(JSScope *scope, jsid id, JSBool adding);
+
+#define SCOPE_GET_PROPERTY(scope, id) \
+ SPROP_FETCH(js_SearchScope(scope, id, JS_FALSE))
+
+#define SCOPE_HAS_PROPERTY(scope, sprop) \
+ (SCOPE_GET_PROPERTY(scope, (sprop)->id) == (sprop))
+
+extern JSScopeProperty *
+js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id,
+ JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
+ uintN attrs, uintN flags, intN shortid);
+
+extern JSScopeProperty *
+js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope,
+ JSScopeProperty *sprop, uintN attrs, uintN mask,
+ JSPropertyOp getter, JSPropertyOp setter);
+
+extern JSBool
+js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id);
+
+extern void
+js_ClearScope(JSContext *cx, JSScope *scope);
+
+/*
+ * These macros used to inline short code sequences, but they grew over time.
+ * We retain them for internal backward compatibility, and in case one or both
+ * ever shrink to inline-able size.
+ */
+#define TRACE_ID(trc, id) js_TraceId(trc, id)
+#define TRACE_SCOPE_PROPERTY(trc, sprop) js_TraceScopeProperty(trc, sprop)
+
+extern void
+js_TraceId(JSTracer *trc, jsid id);
+
+extern void
+js_TraceScopeProperty(JSTracer *trc, JSScopeProperty *sprop);
+
+extern void
+js_SweepScopeProperties(JSContext *cx);
+
+extern JSBool
+js_InitPropertyTree(JSRuntime *rt);
+
+extern void
+js_FinishPropertyTree(JSRuntime *rt);
+
+JS_END_EXTERN_C
+
+#endif /* jsscope_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscript.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsscript.cpp
new file mode 100644
index 0000000..fba6a60
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscript.cpp
@@ -0,0 +1,1891 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS script operations.
+ */
+#include "jsstddef.h"
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#if JS_HAS_XDR
+#include "jsxdrapi.h"
+#endif
+
+#if JS_HAS_SCRIPT_OBJECT
+
+static const char js_script_exec_str[] = "Script.prototype.exec";
+static const char js_script_compile_str[] = "Script.prototype.compile";
+
+/*
+ * This routine requires that obj has been locked previously.
+ */
+static jsint
+GetScriptExecDepth(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+
+ JS_ASSERT(JS_IS_OBJ_LOCKED(cx, obj));
+ v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_START(&js_ScriptClass));
+ return JSVAL_TO_INT(v);
+}
+
+static void
+AdjustScriptExecDepth(JSContext *cx, JSObject *obj, jsint delta)
+{
+ jsint execDepth;
+
+ JS_LOCK_OBJ(cx, obj);
+ execDepth = GetScriptExecDepth(cx, obj);
+ LOCKED_OBJ_SET_SLOT(obj, JSSLOT_START(&js_ScriptClass),
+ INT_TO_JSVAL(execDepth + delta));
+ JS_UNLOCK_OBJ(cx, obj);
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+script_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ uint32 indent;
+ JSScript *script;
+ size_t i, j, k, n;
+ char buf[16];
+ jschar *s, *t;
+ JSString *str;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
+ return JS_FALSE;
+
+ indent = 0;
+ if (argc != 0) {
+ indent = js_ValueToECMAUint32(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ }
+
+ script = (JSScript *) JS_GetPrivate(cx, obj);
+
+ /* Let n count the source string length, j the "front porch" length. */
+ j = JS_snprintf(buf, sizeof buf, "(new %s(", js_ScriptClass.name);
+ n = j + 2;
+ if (!script) {
+ /* Let k count the constructor argument string length. */
+ k = 0;
+ s = NULL; /* quell GCC overwarning */
+ } else {
+ str = JS_DecompileScript(cx, script, "Script.prototype.toSource",
+ (uintN)indent);
+ if (!str)
+ return JS_FALSE;
+ str = js_QuoteString(cx, str, '\'');
+ if (!str)
+ return JS_FALSE;
+ JSSTRING_CHARS_AND_LENGTH(str, s, k);
+ n += k;
+ }
+
+ /* Allocate the source string and copy into it. */
+ t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+ if (!t)
+ return JS_FALSE;
+ for (i = 0; i < j; i++)
+ t[i] = buf[i];
+ for (j = 0; j < k; i++, j++)
+ t[i] = s[j];
+ t[i++] = ')';
+ t[i++] = ')';
+ t[i] = 0;
+
+ /* Create and return a JS string for t. */
+ str = JS_NewUCString(cx, t, n);
+ if (!str) {
+ JS_free(cx, t);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif /* JS_HAS_TOSOURCE */
+
+static JSBool
+script_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ uint32 indent;
+ JSObject *obj;
+ JSScript *script;
+ JSString *str;
+
+ indent = 0;
+ if (argc != 0) {
+ indent = js_ValueToECMAUint32(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ }
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
+ return JS_FALSE;
+ script = (JSScript *) JS_GetPrivate(cx, obj);
+ if (!script) {
+ *vp = STRING_TO_JSVAL(cx->runtime->emptyString);
+ return JS_TRUE;
+ }
+
+ str = JS_DecompileScript(cx, script, "Script.prototype.toString",
+ (uintN)indent);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+script_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSString *str;
+ JSObject *scopeobj;
+ jsval v;
+ JSScript *script, *oldscript;
+ JSStackFrame *caller;
+ const char *file;
+ uintN line;
+ JSPrincipals *principals;
+ uint32 tcflags;
+ jsint execDepth;
+
+ /* Make sure obj is a Script object. */
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
+ return JS_FALSE;
+
+ /* If no args, leave private undefined and return early. */
+ if (argc == 0)
+ goto out;
+
+ /* Otherwise, the first arg is the script source to compile. */
+ str = js_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(str);
+
+ scopeobj = NULL;
+ if (argc >= 2) {
+ if (!js_ValueToObject(cx, argv[1], &scopeobj))
+ return JS_FALSE;
+ argv[1] = OBJECT_TO_JSVAL(scopeobj);
+ }
+
+ /* Compile using the caller's scope chain, which js_Invoke passes to fp. */
+ caller = JS_GetScriptedCaller(cx, cx->fp);
+ JS_ASSERT(!caller || cx->fp->scopeChain == caller->scopeChain);
+
+ if (caller) {
+ if (!scopeobj) {
+ scopeobj = js_GetScopeChain(cx, caller);
+ if (!scopeobj)
+ return JS_FALSE;
+ }
+
+ principals = JS_EvalFramePrincipals(cx, cx->fp, caller);
+ file = js_ComputeFilename(cx, caller, principals, &line);
+ } else {
+ file = NULL;
+ line = 0;
+ principals = NULL;
+ }
+
+ /* Ensure we compile this script with the right (inner) principals. */
+ scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_compile_str);
+ if (!scopeobj)
+ return JS_FALSE;
+
+ /*
+ * Compile the new script using the caller's scope chain, a la eval().
+ * Unlike jsobj.c:obj_eval, however, we do not pass TCF_COMPILE_N_GO in
+ * tcflags and use NULL for the callerFrame argument, because compilation
+ * is here separated from execution, and the run-time scope chain may not
+ * match the compile-time. TCF_COMPILE_N_GO is tested in jsemit.c and
+ * jsparse.c to optimize based on identity of run- and compile-time scope.
+ */
+ tcflags = 0;
+ script = js_CompileScript(cx, scopeobj, NULL, principals, tcflags,
+ JSSTRING_CHARS(str), JSSTRING_LENGTH(str),
+ NULL, file, line);
+ if (!script)
+ return JS_FALSE;
+
+ JS_LOCK_OBJ(cx, obj);
+ execDepth = GetScriptExecDepth(cx, obj);
+
+ /*
+ * execDepth must be 0 to allow compilation here, otherwise the JSScript
+ * struct can be released while running.
+ */
+ if (execDepth > 0) {
+ JS_UNLOCK_OBJ(cx, obj);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_COMPILE_EXECED_SCRIPT);
+ return JS_FALSE;
+ }
+
+ /* Swap script for obj's old script, if any. */
+ v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
+ oldscript = (JSScript*) (!JSVAL_IS_VOID(v) ? JSVAL_TO_PRIVATE(v) : NULL);
+ LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(script));
+ JS_UNLOCK_OBJ(cx, obj);
+
+ if (oldscript)
+ js_DestroyScript(cx, oldscript);
+
+ script->u.object = obj;
+ js_CallNewScriptHook(cx, script, NULL);
+
+out:
+ /* Return the object. */
+ *rval = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSBool
+script_compile(JSContext *cx, uintN argc, jsval *vp)
+{
+ return script_compile_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, vp);
+}
+
+static JSBool
+script_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSObject *scopeobj, *parent;
+ JSStackFrame *fp, *caller;
+ JSPrincipals *principals;
+ JSScript *script;
+ JSBool ok;
+
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
+ return JS_FALSE;
+
+ scopeobj = NULL;
+ if (argc != 0) {
+ if (!js_ValueToObject(cx, argv[0], &scopeobj))
+ return JS_FALSE;
+ argv[0] = OBJECT_TO_JSVAL(scopeobj);
+ }
+
+ /*
+ * Emulate eval() by using caller's this, var object, sharp array, etc.,
+ * all propagated by js_Execute via a non-null fourth (down) argument to
+ * js_Execute. If there is no scripted caller, js_Execute uses its second
+ * (chain) argument to set the exec frame's varobj, thisp, and scopeChain.
+ *
+ * Unlike eval, which the compiler detects, Script.prototype.exec may be
+ * called from a lightweight function, or even from native code (in which
+ * case fp->varobj and fp->scopeChain are null). If exec is called from
+ * a lightweight function, we will need to get a Call object representing
+ * its frame, to act as the var object and scope chain head.
+ */
+ fp = cx->fp;
+ caller = JS_GetScriptedCaller(cx, fp);
+ if (caller && !caller->varobj) {
+ /* Called from a lightweight function. */
+ JS_ASSERT(caller->fun && !JSFUN_HEAVYWEIGHT_TEST(caller->fun->flags));
+
+ /* Scope chain links from Call object to callee's parent. */
+ parent = OBJ_GET_PARENT(cx, caller->callee);
+ if (!js_GetCallObject(cx, caller, parent))
+ return JS_FALSE;
+ }
+
+ if (!scopeobj) {
+ /* No scope object passed in: try to use the caller's scope chain. */
+ if (caller) {
+ /*
+ * Load caller->scopeChain after the conditional js_GetCallObject
+ * call above, which resets scopeChain as well as varobj.
+ */
+ scopeobj = js_GetScopeChain(cx, caller);
+ if (!scopeobj)
+ return JS_FALSE;
+ } else {
+ /*
+ * Called from native code, so we don't know what scope object to
+ * use. We could use parent (see above), but Script.prototype.exec
+ * might be a shared/sealed "superglobal" method. A more general
+ * approach would use cx->globalObject, which will be the same as
+ * exec.__parent__ in the non-superglobal case. In the superglobal
+ * case it's the right object: the global, not the superglobal.
+ */
+ scopeobj = cx->globalObject;
+ }
+ }
+
+ scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_exec_str);
+ if (!scopeobj)
+ return JS_FALSE;
+
+ /* Keep track of nesting depth for the script. */
+ AdjustScriptExecDepth(cx, obj, 1);
+
+ /* Must get to out label after this */
+ script = (JSScript *) JS_GetPrivate(cx, obj);
+ if (!script) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ /* Belt-and-braces: check that this script object has access to scopeobj. */
+ principals = script->principals;
+ ok = js_CheckPrincipalsAccess(cx, scopeobj, principals,
+ CLASS_ATOM(cx, Script));
+ if (!ok)
+ goto out;
+
+ ok = js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval);
+
+out:
+ AdjustScriptExecDepth(cx, obj, -1);
+ return ok;
+}
+
+static JSBool
+script_exec(JSContext *cx, uintN argc, jsval *vp)
+{
+ return script_exec_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, vp);
+}
+
+#endif /* JS_HAS_SCRIPT_OBJECT */
+
+#if JS_HAS_XDR
+
+JSBool
+js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
+{
+ JSContext *cx;
+ JSScript *script, *oldscript;
+ JSBool ok;
+ jsbytecode *code;
+ uint32 length, lineno, nslots, magic;
+ uint32 natoms, nsrcnotes, ntrynotes, nobjects, nupvars, nregexps, i;
+ uint32 prologLength, version;
+ JSTempValueRooter tvr;
+ JSPrincipals *principals;
+ uint32 encodeable;
+ JSBool filenameWasSaved;
+ jssrcnote *notes, *sn;
+ JSSecurityCallbacks *callbacks;
+
+ cx = xdr->cx;
+ script = *scriptp;
+ nsrcnotes = ntrynotes = natoms = nobjects = nupvars = nregexps = 0;
+ filenameWasSaved = JS_FALSE;
+ notes = NULL;
+
+ if (xdr->mode == JSXDR_ENCODE)
+ magic = JSXDR_MAGIC_SCRIPT_CURRENT;
+ if (!JS_XDRUint32(xdr, &magic))
+ return JS_FALSE;
+ if (magic != JSXDR_MAGIC_SCRIPT_CURRENT) {
+ /* We do not provide binary compatibility with older scripts. */
+ if (!hasMagic) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_SCRIPT_MAGIC);
+ return JS_FALSE;
+ }
+ *hasMagic = JS_FALSE;
+ return JS_TRUE;
+ }
+ if (hasMagic)
+ *hasMagic = JS_TRUE;
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ length = script->length;
+ prologLength = PTRDIFF(script->main, script->code, jsbytecode);
+ JS_ASSERT((int16)script->version != JSVERSION_UNKNOWN);
+ version = (uint32)script->version | (script->nfixed << 16);
+ lineno = (uint32)script->lineno;
+ nslots = (uint32)script->nslots;
+ nslots = (uint32)((script->staticDepth << 16) | script->nslots);
+ natoms = (uint32)script->atomMap.length;
+
+ /* Count the srcnotes, keeping notes pointing at the first one. */
+ notes = SCRIPT_NOTES(script);
+ for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
+ continue;
+ nsrcnotes = PTRDIFF(sn, notes, jssrcnote);
+ nsrcnotes++; /* room for the terminator */
+
+ if (script->objectsOffset != 0)
+ nobjects = JS_SCRIPT_OBJECTS(script)->length;
+ if (script->upvarsOffset != 0)
+ nupvars = JS_SCRIPT_UPVARS(script)->length;
+ if (script->regexpsOffset != 0)
+ nregexps = JS_SCRIPT_REGEXPS(script)->length;
+ if (script->trynotesOffset != 0)
+ ntrynotes = JS_SCRIPT_TRYNOTES(script)->length;
+ }
+
+ if (!JS_XDRUint32(xdr, &length))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &prologLength))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &version))
+ return JS_FALSE;
+
+ /*
+ * To fuse allocations, we need srcnote, atom, objects, upvar, regexp,
+ * and trynote counts early.
+ */
+ if (!JS_XDRUint32(xdr, &natoms))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &nsrcnotes))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &ntrynotes))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &nobjects))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &nupvars))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &nregexps))
+ return JS_FALSE;
+
+ if (xdr->mode == JSXDR_DECODE) {
+ script = js_NewScript(cx, length, nsrcnotes, natoms, nobjects, nupvars,
+ nregexps, ntrynotes);
+ if (!script)
+ return JS_FALSE;
+
+ script->main += prologLength;
+ script->version = (JSVersion) (version & 0xffff);
+ script->nfixed = (uint16) (version >> 16);
+
+ /* If we know nsrcnotes, we allocated space for notes in script. */
+ notes = SCRIPT_NOTES(script);
+ *scriptp = script;
+ JS_PUSH_TEMP_ROOT_SCRIPT(cx, script, &tvr);
+ }
+
+ /*
+ * Control hereafter must goto error on failure, in order for the
+ * DECODE case to destroy script.
+ */
+ oldscript = xdr->script;
+ code = script->code;
+ if (xdr->mode == JSXDR_ENCODE) {
+ code = js_UntrapScriptCode(cx, script);
+ if (!code)
+ goto error;
+ }
+
+ xdr->script = script;
+ ok = JS_XDRBytes(xdr, (char *) code, length * sizeof(jsbytecode));
+
+ if (code != script->code)
+ JS_free(cx, code);
+
+ if (!ok)
+ goto error;
+
+ if (!JS_XDRBytes(xdr, (char *)notes, nsrcnotes * sizeof(jssrcnote)) ||
+ !JS_XDRCStringOrNull(xdr, (char **)&script->filename) ||
+ !JS_XDRUint32(xdr, &lineno) ||
+ !JS_XDRUint32(xdr, &nslots)) {
+ goto error;
+ }
+
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (xdr->mode == JSXDR_ENCODE) {
+ principals = script->principals;
+ encodeable = callbacks && callbacks->principalsTranscoder;
+ if (!JS_XDRUint32(xdr, &encodeable))
+ goto error;
+ if (encodeable &&
+ !callbacks->principalsTranscoder(xdr, &principals)) {
+ goto error;
+ }
+ } else {
+ if (!JS_XDRUint32(xdr, &encodeable))
+ goto error;
+ if (encodeable) {
+ if (!(callbacks && callbacks->principalsTranscoder)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_DECODE_PRINCIPALS);
+ goto error;
+ }
+ if (!callbacks->principalsTranscoder(xdr, &principals))
+ goto error;
+ script->principals = principals;
+ }
+ }
+
+ if (xdr->mode == JSXDR_DECODE) {
+ const char *filename = script->filename;
+ if (filename) {
+ filename = js_SaveScriptFilename(cx, filename);
+ if (!filename)
+ goto error;
+ JS_free(cx, (void *) script->filename);
+ script->filename = filename;
+ filenameWasSaved = JS_TRUE;
+ }
+ script->lineno = (uintN)lineno;
+ script->nslots = (uint16)nslots;
+ script->staticDepth = nslots >> 16;
+ }
+
+ for (i = 0; i != natoms; ++i) {
+ if (!js_XDRAtom(xdr, &script->atomMap.vector[i]))
+ goto error;
+ }
+
+ /*
+ * Here looping from 0-to-length to xdr objects is essential. It ensures
+ * that block objects from the script->objects array will be written and
+ * restored in the outer-to-inner order. block_xdrObject relies on this to
+ * restore the parent chain.
+ */
+ for (i = 0; i != nobjects; ++i) {
+ if (!js_XDRObject(xdr, &JS_SCRIPT_OBJECTS(script)->vector[i]))
+ goto error;
+ }
+ for (i = 0; i != nupvars; ++i) {
+ if (!JS_XDRUint32(xdr, &JS_SCRIPT_UPVARS(script)->vector[i]))
+ goto error;
+ }
+ for (i = 0; i != nregexps; ++i) {
+ if (!js_XDRObject(xdr, &JS_SCRIPT_REGEXPS(script)->vector[i]))
+ goto error;
+ }
+
+ if (ntrynotes != 0) {
+ /*
+ * We combine tn->kind and tn->stackDepth when serializing as XDR is not
+ * efficient when serializing small integer types.
+ */
+ JSTryNote *tn, *tnfirst;
+ uint32 kindAndDepth;
+ JS_STATIC_ASSERT(sizeof(tn->kind) == sizeof(uint8));
+ JS_STATIC_ASSERT(sizeof(tn->stackDepth) == sizeof(uint16));
+
+ tnfirst = JS_SCRIPT_TRYNOTES(script)->vector;
+ JS_ASSERT(JS_SCRIPT_TRYNOTES(script)->length == ntrynotes);
+ tn = tnfirst + ntrynotes;
+ do {
+ --tn;
+ if (xdr->mode == JSXDR_ENCODE) {
+ kindAndDepth = ((uint32)tn->kind << 16)
+ | (uint32)tn->stackDepth;
+ }
+ if (!JS_XDRUint32(xdr, &kindAndDepth) ||
+ !JS_XDRUint32(xdr, &tn->start) ||
+ !JS_XDRUint32(xdr, &tn->length)) {
+ goto error;
+ }
+ if (xdr->mode == JSXDR_DECODE) {
+ tn->kind = (uint8)(kindAndDepth >> 16);
+ tn->stackDepth = (uint16)kindAndDepth;
+ }
+ } while (tn != tnfirst);
+ }
+
+ xdr->script = oldscript;
+ if (xdr->mode == JSXDR_DECODE)
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return JS_TRUE;
+
+ error:
+ if (xdr->mode == JSXDR_DECODE) {
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (script->filename && !filenameWasSaved) {
+ JS_free(cx, (void *) script->filename);
+ script->filename = NULL;
+ }
+ js_DestroyScript(cx, script);
+ *scriptp = NULL;
+ }
+ xdr->script = oldscript;
+ return JS_FALSE;
+}
+
+#if JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW
+/*
+ * These cannot be exposed to web content, and chrome does not need them, so
+ * we take them out of the Mozilla client altogether. Fortunately, there is
+ * no way to serialize a native function (see fun_xdrObject in jsfun.c).
+ */
+
+static JSBool
+script_freeze(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ JSXDRState *xdr;
+ JSScript *script;
+ JSBool ok, hasMagic;
+ uint32 len;
+ void *buf;
+ JSString *str;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
+ return JS_FALSE;
+ script = (JSScript *) JS_GetPrivate(cx, obj);
+ if (!script)
+ return JS_TRUE;
+
+ /* create new XDR */
+ xdr = JS_XDRNewMem(cx, JSXDR_ENCODE);
+ if (!xdr)
+ return JS_FALSE;
+
+ /* write */
+ ok = js_XDRScript(xdr, &script, &hasMagic);
+ if (!ok)
+ goto out;
+ if (!hasMagic) {
+ *vp = JSVAL_VOID;
+ goto out;
+ }
+
+ buf = JS_XDRMemGetData(xdr, &len);
+ if (!buf) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ JS_ASSERT((jsword)buf % sizeof(jschar) == 0);
+ len /= sizeof(jschar);
+#if IS_BIG_ENDIAN
+ {
+ jschar *chars;
+ uint32 i;
+
+ /* Swap bytes in Unichars to keep frozen strings machine-independent. */
+ chars = (jschar *)buf;
+ for (i = 0; i < len; i++)
+ chars[i] = JSXDR_SWAB16(chars[i]);
+ }
+#endif
+ str = JS_NewUCStringCopyN(cx, (jschar *)buf, len);
+ if (!str) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+
+out:
+ JS_XDRDestroy(xdr);
+ return ok;
+}
+
+static JSBool
+script_thaw(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ JSXDRState *xdr;
+ JSString *str;
+ void *buf;
+ uint32 len;
+ jsval v;
+ JSScript *script, *oldscript;
+ JSBool ok, hasMagic;
+ jsint execDepth;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
+ return JS_FALSE;
+
+ if (argc == 0)
+ return JS_TRUE;
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(str);
+
+ /* create new XDR */
+ xdr = JS_XDRNewMem(cx, JSXDR_DECODE);
+ if (!xdr)
+ return JS_FALSE;
+
+ JSSTRING_CHARS_AND_LENGTH(str, buf, len);
+#if IS_BIG_ENDIAN
+ {
+ jschar *from, *to;
+ uint32 i;
+
+ /* Swap bytes in Unichars to keep frozen strings machine-independent. */
+ from = (jschar *)buf;
+ to = (jschar *) JS_malloc(cx, len * sizeof(jschar));
+ if (!to) {
+ JS_XDRDestroy(xdr);
+ return JS_FALSE;
+ }
+ for (i = 0; i < len; i++)
+ to[i] = JSXDR_SWAB16(from[i]);
+ buf = (char *)to;
+ }
+#endif
+ len *= sizeof(jschar);
+ JS_XDRMemSetData(xdr, buf, len);
+
+ /* XXXbe should magic mismatch be error, or false return value? */
+ ok = js_XDRScript(xdr, &script, &hasMagic);
+ if (!ok)
+ goto out;
+ if (!hasMagic) {
+ *vp = JSVAL_FALSE;
+ goto out;
+ }
+
+ JS_LOCK_OBJ(cx, obj);
+ execDepth = GetScriptExecDepth(cx, obj);
+
+ /*
+ * execDepth must be 0 to allow compilation here, otherwise the JSScript
+ * struct can be released while running.
+ */
+ if (execDepth > 0) {
+ JS_UNLOCK_OBJ(cx, obj);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_COMPILE_EXECED_SCRIPT);
+ goto out;
+ }
+
+ /* Swap script for obj's old script, if any. */
+ v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
+ oldscript = !JSVAL_IS_VOID(v) ? JSVAL_TO_PRIVATE(v) : NULL;
+ LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(script));
+ JS_UNLOCK_OBJ(cx, obj);
+
+ if (oldscript)
+ js_DestroyScript(cx, oldscript);
+
+ script->u.object = obj;
+ js_CallNewScriptHook(cx, script, NULL);
+
+out:
+ /*
+ * We reset the buffer to be NULL so that it doesn't free the chars
+ * memory owned by str (vp[2]).
+ */
+ JS_XDRMemSetData(xdr, NULL, 0);
+ JS_XDRDestroy(xdr);
+#if IS_BIG_ENDIAN
+ JS_free(cx, buf);
+#endif
+ *vp = JSVAL_TRUE;
+ return ok;
+}
+
+static const char js_thaw_str[] = "thaw";
+
+#endif /* JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW */
+#endif /* JS_HAS_XDR */
+
+#if JS_HAS_SCRIPT_OBJECT
+
+static JSFunctionSpec script_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, script_toSource, 0,0),
+#endif
+ JS_FN(js_toString_str, script_toString, 0,0),
+ JS_FN("compile", script_compile, 2,0),
+ JS_FN("exec", script_exec, 1,0),
+#if JS_HAS_XDR_FREEZE_THAW
+ JS_FN("freeze", script_freeze, 0,0),
+ JS_FN(js_thaw_str, script_thaw, 1,0),
+#endif /* JS_HAS_XDR_FREEZE_THAW */
+ JS_FS_END
+};
+
+#endif /* JS_HAS_SCRIPT_OBJECT */
+
+static void
+script_finalize(JSContext *cx, JSObject *obj)
+{
+ JSScript *script;
+
+ script = (JSScript *) JS_GetPrivate(cx, obj);
+ if (script)
+ js_DestroyScript(cx, script);
+}
+
+static JSBool
+script_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+#if JS_HAS_SCRIPT_OBJECT
+ return script_exec_sub(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval);
+#else
+ return JS_FALSE;
+#endif
+}
+
+static void
+script_trace(JSTracer *trc, JSObject *obj)
+{
+ JSScript *script;
+
+ script = (JSScript *) JS_GetPrivate(trc->context, obj);
+ if (script)
+ js_TraceScript(trc, script);
+}
+
+#if !JS_HAS_SCRIPT_OBJECT
+#define JSProto_Script JSProto_Object
+#endif
+
+JS_FRIEND_DATA(JSClass) js_ScriptClass = {
+ js_Script_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Script),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, script_finalize,
+ NULL, NULL, script_call, NULL,/*XXXbe xdr*/
+ NULL, NULL, JS_CLASS_TRACE(script_trace), NULL
+};
+
+#if JS_HAS_SCRIPT_OBJECT
+
+static JSBool
+Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ /* If not constructing, replace obj with a new Script object. */
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+
+ /*
+ * script_compile_sub does not use rval to root its temporaries so we
+ * can use it to root obj.
+ */
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+
+ if (!JS_SetReservedSlot(cx, obj, 0, INT_TO_JSVAL(0)))
+ return JS_FALSE;
+
+ return script_compile_sub(cx, obj, argc, argv, rval);
+}
+
+#if JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW
+
+static JSBool
+script_static_thaw(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
+ if (!obj)
+ return JS_FALSE;
+ vp[1] = OBJECT_TO_JSVAL(obj);
+ if (!script_thaw(cx, argc, vp))
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSFunctionSpec script_static_methods[] = {
+ JS_FN(js_thaw_str, script_static_thaw, 1,0),
+ JS_FS_END
+};
+
+#else /* !JS_HAS_SCRIPT_OBJECT || !JS_HAS_XDR_FREEZE_THAW */
+
+#define script_static_methods NULL
+
+#endif /* !JS_HAS_SCRIPT_OBJECT || !JS_HAS_XDR_FREEZE_THAW */
+
+JSObject *
+js_InitScriptClass(JSContext *cx, JSObject *obj)
+{
+ return JS_InitClass(cx, obj, NULL, &js_ScriptClass, Script, 1,
+ NULL, script_methods, NULL, script_static_methods);
+}
+
+#endif /* JS_HAS_SCRIPT_OBJECT */
+
+/*
+ * Shared script filename management.
+ */
+static int
+js_compare_strings(const void *k1, const void *k2)
+{
+ return strcmp((const char *) k1, (const char *) k2) == 0;
+}
+
+/* NB: This struct overlays JSHashEntry -- see jshash.h, do not reorganize. */
+typedef struct ScriptFilenameEntry {
+ JSHashEntry *next; /* hash chain linkage */
+ JSHashNumber keyHash; /* key hash function result */
+ const void *key; /* ptr to filename, below */
+ uint32 flags; /* user-defined filename prefix flags */
+ JSPackedBool mark; /* GC mark flag */
+ char filename[3]; /* two or more bytes, NUL-terminated */
+} ScriptFilenameEntry;
+
+static void *
+js_alloc_table_space(void *priv, size_t size)
+{
+ return malloc(size);
+}
+
+static void
+js_free_table_space(void *priv, void *item)
+{
+ free(item);
+}
+
+static JSHashEntry *
+js_alloc_sftbl_entry(void *priv, const void *key)
+{
+ size_t nbytes = offsetof(ScriptFilenameEntry, filename) +
+ strlen((const char *) key) + 1;
+
+ return (JSHashEntry *) malloc(JS_MAX(nbytes, sizeof(JSHashEntry)));
+}
+
+static void
+js_free_sftbl_entry(void *priv, JSHashEntry *he, uintN flag)
+{
+ if (flag != HT_FREE_ENTRY)
+ return;
+ free(he);
+}
+
+static JSHashAllocOps sftbl_alloc_ops = {
+ js_alloc_table_space, js_free_table_space,
+ js_alloc_sftbl_entry, js_free_sftbl_entry
+};
+
+JSBool
+js_InitRuntimeScriptState(JSRuntime *rt)
+{
+#ifdef JS_THREADSAFE
+ JS_ASSERT(!rt->scriptFilenameTableLock);
+ rt->scriptFilenameTableLock = JS_NEW_LOCK();
+ if (!rt->scriptFilenameTableLock)
+ return JS_FALSE;
+#endif
+ JS_ASSERT(!rt->scriptFilenameTable);
+ rt->scriptFilenameTable =
+ JS_NewHashTable(16, JS_HashString, js_compare_strings, NULL,
+ &sftbl_alloc_ops, NULL);
+ if (!rt->scriptFilenameTable) {
+ js_FinishRuntimeScriptState(rt); /* free lock if threadsafe */
+ return JS_FALSE;
+ }
+ JS_INIT_CLIST(&rt->scriptFilenamePrefixes);
+ return JS_TRUE;
+}
+
+typedef struct ScriptFilenamePrefix {
+ JSCList links; /* circular list linkage for easy deletion */
+ const char *name; /* pointer to pinned ScriptFilenameEntry string */
+ size_t length; /* prefix string length, precomputed */
+ uint32 flags; /* user-defined flags to inherit from this prefix */
+} ScriptFilenamePrefix;
+
+void
+js_FinishRuntimeScriptState(JSRuntime *rt)
+{
+ if (rt->scriptFilenameTable) {
+ JS_HashTableDestroy(rt->scriptFilenameTable);
+ rt->scriptFilenameTable = NULL;
+ }
+#ifdef JS_THREADSAFE
+ if (rt->scriptFilenameTableLock) {
+ JS_DESTROY_LOCK(rt->scriptFilenameTableLock);
+ rt->scriptFilenameTableLock = NULL;
+ }
+#endif
+}
+
+void
+js_FreeRuntimeScriptState(JSRuntime *rt)
+{
+ ScriptFilenamePrefix *sfp;
+
+ if (!rt->scriptFilenameTable)
+ return;
+
+ while (!JS_CLIST_IS_EMPTY(&rt->scriptFilenamePrefixes)) {
+ sfp = (ScriptFilenamePrefix *) rt->scriptFilenamePrefixes.next;
+ JS_REMOVE_LINK(&sfp->links);
+ free(sfp);
+ }
+ js_FinishRuntimeScriptState(rt);
+}
+
+#ifdef DEBUG_brendan
+#define DEBUG_SFTBL
+#endif
+#ifdef DEBUG_SFTBL
+size_t sftbl_savings = 0;
+#endif
+
+static ScriptFilenameEntry *
+SaveScriptFilename(JSRuntime *rt, const char *filename, uint32 flags)
+{
+ JSHashTable *table;
+ JSHashNumber hash;
+ JSHashEntry **hep;
+ ScriptFilenameEntry *sfe;
+ size_t length;
+ JSCList *head, *link;
+ ScriptFilenamePrefix *sfp;
+
+ table = rt->scriptFilenameTable;
+ hash = JS_HashString(filename);
+ hep = JS_HashTableRawLookup(table, hash, filename);
+ sfe = (ScriptFilenameEntry *) *hep;
+#ifdef DEBUG_SFTBL
+ if (sfe)
+ sftbl_savings += strlen(sfe->filename);
+#endif
+
+ if (!sfe) {
+ sfe = (ScriptFilenameEntry *)
+ JS_HashTableRawAdd(table, hep, hash, filename, NULL);
+ if (!sfe)
+ return NULL;
+ sfe->key = strcpy(sfe->filename, filename);
+ sfe->flags = 0;
+ sfe->mark = JS_FALSE;
+ }
+
+ /* If saving a prefix, add it to the set in rt->scriptFilenamePrefixes. */
+ if (flags != 0) {
+ /* Search in case filename was saved already; we must be idempotent. */
+ sfp = NULL;
+ length = strlen(filename);
+ for (head = link = &rt->scriptFilenamePrefixes;
+ link->next != head;
+ link = link->next) {
+ /* Lag link behind sfp to insert in non-increasing length order. */
+ sfp = (ScriptFilenamePrefix *) link->next;
+ if (!strcmp(sfp->name, filename))
+ break;
+ if (sfp->length <= length) {
+ sfp = NULL;
+ break;
+ }
+ sfp = NULL;
+ }
+
+ if (!sfp) {
+ /* No such prefix: add one now. */
+ sfp = (ScriptFilenamePrefix *) malloc(sizeof(ScriptFilenamePrefix));
+ if (!sfp)
+ return NULL;
+ JS_INSERT_AFTER(&sfp->links, link);
+ sfp->name = sfe->filename;
+ sfp->length = length;
+ sfp->flags = 0;
+ }
+
+ /*
+ * Accumulate flags in both sfe and sfp: sfe for later access from the
+ * JS_GetScriptedCallerFilenameFlags debug-API, and sfp so that longer
+ * filename entries can inherit by prefix.
+ */
+ sfe->flags |= flags;
+ sfp->flags |= flags;
+ }
+
+ return sfe;
+}
+
+const char *
+js_SaveScriptFilename(JSContext *cx, const char *filename)
+{
+ JSRuntime *rt;
+ ScriptFilenameEntry *sfe;
+ JSCList *head, *link;
+ ScriptFilenamePrefix *sfp;
+
+ rt = cx->runtime;
+ JS_ACQUIRE_LOCK(rt->scriptFilenameTableLock);
+ sfe = SaveScriptFilename(rt, filename, 0);
+ if (!sfe) {
+ JS_RELEASE_LOCK(rt->scriptFilenameTableLock);
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+
+ /*
+ * Try to inherit flags by prefix. We assume there won't be more than a
+ * few (dozen! ;-) prefixes, so linear search is tolerable.
+ * XXXbe every time I've assumed that in the JS engine, I've been wrong!
+ */
+ for (head = &rt->scriptFilenamePrefixes, link = head->next;
+ link != head;
+ link = link->next) {
+ sfp = (ScriptFilenamePrefix *) link;
+ if (!strncmp(sfp->name, filename, sfp->length)) {
+ sfe->flags |= sfp->flags;
+ break;
+ }
+ }
+ JS_RELEASE_LOCK(rt->scriptFilenameTableLock);
+ return sfe->filename;
+}
+
+const char *
+js_SaveScriptFilenameRT(JSRuntime *rt, const char *filename, uint32 flags)
+{
+ ScriptFilenameEntry *sfe;
+
+ /* This may be called very early, via the jsdbgapi.h entry point. */
+ if (!rt->scriptFilenameTable && !js_InitRuntimeScriptState(rt))
+ return NULL;
+
+ JS_ACQUIRE_LOCK(rt->scriptFilenameTableLock);
+ sfe = SaveScriptFilename(rt, filename, flags);
+ JS_RELEASE_LOCK(rt->scriptFilenameTableLock);
+ if (!sfe)
+ return NULL;
+
+ return sfe->filename;
+}
+
+/*
+ * Back up from a saved filename by its offset within its hash table entry.
+ */
+#define FILENAME_TO_SFE(fn) \
+ ((ScriptFilenameEntry *) ((fn) - offsetof(ScriptFilenameEntry, filename)))
+
+/*
+ * The sfe->key member, redundant given sfe->filename but required by the old
+ * jshash.c code, here gives us a useful sanity check. This assertion will
+ * very likely botch if someone tries to mark a string that wasn't allocated
+ * as an sfe->filename.
+ */
+#define ASSERT_VALID_SFE(sfe) JS_ASSERT((sfe)->key == (sfe)->filename)
+
+uint32
+js_GetScriptFilenameFlags(const char *filename)
+{
+ ScriptFilenameEntry *sfe;
+
+ sfe = FILENAME_TO_SFE(filename);
+ ASSERT_VALID_SFE(sfe);
+ return sfe->flags;
+}
+
+void
+js_MarkScriptFilename(const char *filename)
+{
+ ScriptFilenameEntry *sfe;
+
+ sfe = FILENAME_TO_SFE(filename);
+ ASSERT_VALID_SFE(sfe);
+ sfe->mark = JS_TRUE;
+}
+
+static intN
+js_script_filename_marker(JSHashEntry *he, intN i, void *arg)
+{
+ ScriptFilenameEntry *sfe = (ScriptFilenameEntry *) he;
+
+ sfe->mark = JS_TRUE;
+ return HT_ENUMERATE_NEXT;
+}
+
+void
+js_MarkScriptFilenames(JSRuntime *rt, JSBool keepAtoms)
+{
+ JSCList *head, *link;
+ ScriptFilenamePrefix *sfp;
+
+ if (!rt->scriptFilenameTable)
+ return;
+
+ if (keepAtoms) {
+ JS_HashTableEnumerateEntries(rt->scriptFilenameTable,
+ js_script_filename_marker,
+ rt);
+ }
+ for (head = &rt->scriptFilenamePrefixes, link = head->next;
+ link != head;
+ link = link->next) {
+ sfp = (ScriptFilenamePrefix *) link;
+ js_MarkScriptFilename(sfp->name);
+ }
+}
+
+static intN
+js_script_filename_sweeper(JSHashEntry *he, intN i, void *arg)
+{
+ ScriptFilenameEntry *sfe = (ScriptFilenameEntry *) he;
+
+ if (!sfe->mark)
+ return HT_ENUMERATE_REMOVE;
+ sfe->mark = JS_FALSE;
+ return HT_ENUMERATE_NEXT;
+}
+
+void
+js_SweepScriptFilenames(JSRuntime *rt)
+{
+ if (!rt->scriptFilenameTable)
+ return;
+
+ JS_HashTableEnumerateEntries(rt->scriptFilenameTable,
+ js_script_filename_sweeper,
+ rt);
+#ifdef DEBUG_notme
+#ifdef DEBUG_SFTBL
+ printf("script filename table savings so far: %u\n", sftbl_savings);
+#endif
+#endif
+}
+
+/*
+ * JSScript data structures memory alignment:
+ *
+ * JSScript
+ * JSObjectArray script objects' descriptor if JSScript.objectsOffset != 0,
+ * use JS_SCRIPT_OBJECTS(script) macro to access it.
+ * JSObjectArray script regexps' descriptor if JSScript.regexpsOffset != 0,
+ * use JS_SCRIPT_REGEXPS(script) macro to access it.
+ * JSTryNoteArray script try notes' descriptor if JSScript.tryNotesOffset
+ * != 0, use JS_SCRIPT_TRYNOTES(script) macro to access it.
+ * JSAtom *a[] array of JSScript.atomMap.length atoms pointed by
+ * JSScript.atomMap.vector if any.
+ * JSObject *o[] array of JS_SCRIPT_OBJECTS(script)->length objects if any
+ * pointed by JS_SCRIPT_OBJECTS(script)->vector.
+ * JSObject *r[] array of JS_SCRIPT_REGEXPS(script)->length regexps if any
+ * pointed by JS_SCRIPT_REGEXPS(script)->vector.
+ * JSTryNote t[] array of JS_SCRIPT_TRYNOTES(script)->length try notes if any
+ * pointed by JS_SCRIPT_TRYNOTES(script)->vector.
+ * jsbytecode b[] script bytecode pointed by JSScript.code.
+ * jssrcnote s[] script source notes, use SCRIPT_NOTES(script) to access it
+ *
+ * The alignment avoids gaps between entries as alignment requirement for each
+ * subsequent structure or array is the same or divides the alignment
+ * requirement for the previous one.
+ *
+ * The followings asserts checks that assuming that the alignment requirement
+ * for JSObjectArray and JSTryNoteArray are sizeof(void *) and for JSTryNote
+ * it is sizeof(uint32) as the structure consists of 3 uint32 fields.
+ */
+JS_STATIC_ASSERT(sizeof(JSScript) % sizeof(void *) == 0);
+JS_STATIC_ASSERT(sizeof(JSObjectArray) % sizeof(void *) == 0);
+JS_STATIC_ASSERT(sizeof(JSTryNoteArray) == sizeof(JSObjectArray));
+JS_STATIC_ASSERT(sizeof(JSAtom *) == sizeof(JSObject *));
+JS_STATIC_ASSERT(sizeof(JSObject *) % sizeof(uint32) == 0);
+JS_STATIC_ASSERT(sizeof(JSTryNote) == 3 * sizeof(uint32));
+JS_STATIC_ASSERT(sizeof(uint32) % sizeof(jsbytecode) == 0);
+JS_STATIC_ASSERT(sizeof(jsbytecode) % sizeof(jssrcnote) == 0);
+
+/*
+ * Check that uint8 offset for object, upvar, regexp, and try note arrays is
+ * sufficient.
+ */
+JS_STATIC_ASSERT(sizeof(JSScript) + 2 * sizeof(JSObjectArray) +
+ sizeof(JSUpvarArray) < JS_BIT(8));
+
+JSScript *
+js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
+ uint32 nobjects, uint32 nupvars, uint32 nregexps,
+ uint32 ntrynotes)
+{
+ size_t size, vectorSize;
+ JSScript *script;
+ uint8 *cursor;
+
+ size = sizeof(JSScript) +
+ sizeof(JSAtom *) * natoms +
+ length * sizeof(jsbytecode) +
+ nsrcnotes * sizeof(jssrcnote);
+ if (nobjects != 0)
+ size += sizeof(JSObjectArray) + nobjects * sizeof(JSObject *);
+ if (nupvars != 0)
+ size += sizeof(JSUpvarArray) + nupvars * sizeof(uint32);
+ if (nregexps != 0)
+ size += sizeof(JSObjectArray) + nregexps * sizeof(JSObject *);
+ if (ntrynotes != 0)
+ size += sizeof(JSTryNoteArray) + ntrynotes * sizeof(JSTryNote);
+
+ script = (JSScript *) JS_malloc(cx, size);
+ if (!script)
+ return NULL;
+ memset(script, 0, sizeof(JSScript));
+ script->length = length;
+ script->version = cx->version;
+
+ cursor = (uint8 *)script + sizeof(JSScript);
+ if (nobjects != 0) {
+ script->objectsOffset = (uint8)(cursor - (uint8 *)script);
+ cursor += sizeof(JSObjectArray);
+ }
+ if (nupvars != 0) {
+ script->upvarsOffset = (uint8)(cursor - (uint8 *)script);
+ cursor += sizeof(JSUpvarArray);
+ }
+ if (nregexps != 0) {
+ script->regexpsOffset = (uint8)(cursor - (uint8 *)script);
+ cursor += sizeof(JSObjectArray);
+ }
+ if (ntrynotes != 0) {
+ script->trynotesOffset = (uint8)(cursor - (uint8 *)script);
+ cursor += sizeof(JSTryNoteArray);
+ }
+
+ if (natoms != 0) {
+ script->atomMap.length = natoms;
+ script->atomMap.vector = (JSAtom **)cursor;
+ vectorSize = natoms * sizeof(script->atomMap.vector[0]);
+
+ /*
+ * Clear object map's vector so the GC tracing can run when not yet
+ * all atoms are copied to the array.
+ */
+ memset(cursor, 0, vectorSize);
+ cursor += vectorSize;
+ }
+
+ if (nobjects != 0) {
+ JS_SCRIPT_OBJECTS(script)->length = nobjects;
+ JS_SCRIPT_OBJECTS(script)->vector = (JSObject **)cursor;
+ vectorSize = nobjects * sizeof(JS_SCRIPT_OBJECTS(script)->vector[0]);
+ memset(cursor, 0, vectorSize);
+ cursor += vectorSize;
+ }
+
+ if (nupvars != 0) {
+ JS_SCRIPT_UPVARS(script)->length = nupvars;
+ JS_SCRIPT_UPVARS(script)->vector = (uint32 *)cursor;
+ vectorSize = nupvars * sizeof(JS_SCRIPT_UPVARS(script)->vector[0]);
+ memset(cursor, 0, vectorSize);
+ cursor += vectorSize;
+ }
+
+ if (nregexps != 0) {
+ JS_SCRIPT_REGEXPS(script)->length = nregexps;
+ JS_SCRIPT_REGEXPS(script)->vector = (JSObject **)cursor;
+ vectorSize = nregexps * sizeof(JS_SCRIPT_REGEXPS(script)->vector[0]);
+ memset(cursor, 0, vectorSize);
+ cursor += vectorSize;
+ }
+
+ if (ntrynotes != 0) {
+ JS_SCRIPT_TRYNOTES(script)->length = ntrynotes;
+ JS_SCRIPT_TRYNOTES(script)->vector = (JSTryNote *)cursor;
+ vectorSize = ntrynotes * sizeof(JS_SCRIPT_TRYNOTES(script)->vector[0]);
+#ifdef DEBUG
+ memset(cursor, 0, vectorSize);
+#endif
+ cursor += vectorSize;
+ }
+
+ script->code = script->main = (jsbytecode *)cursor;
+ JS_ASSERT(cursor +
+ length * sizeof(jsbytecode) +
+ nsrcnotes * sizeof(jssrcnote) ==
+ (uint8 *)script + size);
+
+#ifdef CHECK_SCRIPT_OWNER
+ script->owner = cx->thread;
+#endif
+ return script;
+}
+
+JSScript *
+js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
+{
+ uint32 mainLength, prologLength, nsrcnotes, nfixed;
+ JSScript *script;
+ const char *filename;
+ JSFunction *fun;
+
+ /* The counts of indexed things must be checked during code generation. */
+ JS_ASSERT(cg->atomList.count <= INDEX_LIMIT);
+ JS_ASSERT(cg->objectList.length <= INDEX_LIMIT);
+ JS_ASSERT(cg->regexpList.length <= INDEX_LIMIT);
+
+ mainLength = CG_OFFSET(cg);
+ prologLength = CG_PROLOG_OFFSET(cg);
+ CG_COUNT_FINAL_SRCNOTES(cg, nsrcnotes);
+ script = js_NewScript(cx, prologLength + mainLength, nsrcnotes,
+ cg->atomList.count, cg->objectList.length,
+ cg->upvarList.count, cg->regexpList.length,
+ cg->ntrynotes);
+ if (!script)
+ return NULL;
+
+ /* Now that we have script, error control flow must go to label bad. */
+ script->main += prologLength;
+ memcpy(script->code, CG_PROLOG_BASE(cg), prologLength * sizeof(jsbytecode));
+ memcpy(script->main, CG_BASE(cg), mainLength * sizeof(jsbytecode));
+ nfixed = (cg->treeContext.flags & TCF_IN_FUNCTION)
+ ? cg->treeContext.u.fun->u.i.nvars
+ : cg->treeContext.ngvars + cg->regexpList.length;
+ JS_ASSERT(nfixed < SLOTNO_LIMIT);
+ script->nfixed = (uint16) nfixed;
+ js_InitAtomMap(cx, &script->atomMap, &cg->atomList);
+
+ filename = cg->treeContext.parseContext->tokenStream.filename;
+ if (filename) {
+ script->filename = js_SaveScriptFilename(cx, filename);
+ if (!script->filename)
+ goto bad;
+ }
+ script->lineno = cg->firstLine;
+ if (script->nfixed + cg->maxStackDepth >= JS_BIT(16)) {
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), NULL, JSREPORT_ERROR,
+ JSMSG_NEED_DIET, "script");
+ goto bad;
+ }
+ script->nslots = script->nfixed + cg->maxStackDepth;
+ script->staticDepth = cg->staticDepth;
+ script->principals = cg->treeContext.parseContext->principals;
+ if (script->principals)
+ JSPRINCIPALS_HOLD(cx, script->principals);
+
+ if (!js_FinishTakingSrcNotes(cx, cg, SCRIPT_NOTES(script)))
+ goto bad;
+ if (cg->ntrynotes != 0)
+ js_FinishTakingTryNotes(cg, JS_SCRIPT_TRYNOTES(script));
+ if (cg->objectList.length != 0)
+ FinishParsedObjects(&cg->objectList, JS_SCRIPT_OBJECTS(script));
+ if (cg->regexpList.length != 0)
+ FinishParsedObjects(&cg->regexpList, JS_SCRIPT_REGEXPS(script));
+ if (cg->treeContext.flags & TCF_NO_SCRIPT_RVAL)
+ script->flags |= JSSF_NO_SCRIPT_RVAL;
+
+ if (cg->upvarList.count != 0) {
+ JS_ASSERT(cg->upvarList.count <= cg->upvarMap.length);
+ memcpy(JS_SCRIPT_UPVARS(script)->vector, cg->upvarMap.vector,
+ cg->upvarList.count * sizeof(uint32));
+ ATOM_LIST_INIT(&cg->upvarList);
+ JS_free(cx, cg->upvarMap.vector);
+ cg->upvarMap.vector = NULL;
+ }
+
+ /*
+ * We initialize fun->u.script to be the script constructed above
+ * so that the debugger has a valid FUN_SCRIPT(fun).
+ */
+ fun = NULL;
+ if (cg->treeContext.flags & TCF_IN_FUNCTION) {
+ fun = cg->treeContext.u.fun;
+ JS_ASSERT(FUN_INTERPRETED(fun) && !FUN_SCRIPT(fun));
+ JS_ASSERT_IF(script->upvarsOffset != 0,
+ JS_SCRIPT_UPVARS(script)->length == fun->u.i.nupvars);
+
+ js_FreezeLocalNames(cx, fun);
+ fun->u.i.script = script;
+#ifdef CHECK_SCRIPT_OWNER
+ script->owner = NULL;
+#endif
+ if (cg->treeContext.flags & TCF_FUN_HEAVYWEIGHT)
+ fun->flags |= JSFUN_HEAVYWEIGHT;
+ }
+
+ /* Tell the debugger about this compiled script. */
+ js_CallNewScriptHook(cx, script, fun);
+ return script;
+
+bad:
+ js_DestroyScript(cx, script);
+ return NULL;
+}
+
+JS_FRIEND_API(void)
+js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun)
+{
+ JSNewScriptHook hook;
+
+ hook = cx->debugHooks->newScriptHook;
+ if (hook) {
+ JS_KEEP_ATOMS(cx->runtime);
+ hook(cx, script->filename, script->lineno, script, fun,
+ cx->debugHooks->newScriptHookData);
+ JS_UNKEEP_ATOMS(cx->runtime);
+ }
+}
+
+JS_FRIEND_API(void)
+js_CallDestroyScriptHook(JSContext *cx, JSScript *script)
+{
+ JSDestroyScriptHook hook;
+
+ hook = cx->debugHooks->destroyScriptHook;
+ if (hook)
+ hook(cx, script, cx->debugHooks->destroyScriptHookData);
+}
+
+void
+js_DestroyScript(JSContext *cx, JSScript *script)
+{
+ js_CallDestroyScriptHook(cx, script);
+ JS_ClearScriptTraps(cx, script);
+
+ if (script->principals)
+ JSPRINCIPALS_DROP(cx, script->principals);
+
+ if (JS_GSN_CACHE(cx).code == script->code)
+ JS_CLEAR_GSN_CACHE(cx);
+
+ /*
+ * The GC flushes all property caches, so no need to purge just the
+ * entries for this script.
+ *
+ * JS_THREADSAFE note: js_FlushPropertyCacheForScript flushes only the
+ * current thread's property cache, so a script not owned by a function
+ * or object, which hands off lifetime management for that script to the
+ * GC, must be used by only one thread over its lifetime.
+ *
+ * This should be an API-compatible change, since a script is never safe
+ * against premature GC if shared among threads without a rooted object
+ * wrapping it to protect the script's mapped atoms against GC. We use
+ * script->owner to enforce this requirement via assertions.
+ */
+#ifdef CHECK_SCRIPT_OWNER
+ JS_ASSERT_IF(cx->runtime->gcRunning, !script->owner);
+#endif
+
+ if (!cx->runtime->gcRunning) {
+ if (!(cx->fp && (cx->fp->flags & JSFRAME_EVAL))) {
+#ifdef CHECK_SCRIPT_OWNER
+ JS_ASSERT(script->owner == cx->thread);
+#endif
+ js_FlushPropertyCacheForScript(cx, script);
+ }
+ }
+
+ JS_free(cx, script);
+}
+
+void
+js_TraceScript(JSTracer *trc, JSScript *script)
+{
+ JSAtomMap *map;
+ uintN i, length;
+ JSAtom **vector;
+ jsval v;
+ JSObjectArray *objarray;
+
+ map = &script->atomMap;
+ length = map->length;
+ vector = map->vector;
+ for (i = 0; i < length; i++) {
+ v = ATOM_KEY(vector[i]);
+ if (JSVAL_IS_TRACEABLE(v)) {
+ JS_SET_TRACING_INDEX(trc, "atomMap", i);
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
+ }
+ }
+
+ if (script->objectsOffset != 0) {
+ objarray = JS_SCRIPT_OBJECTS(script);
+ i = objarray->length;
+ do {
+ --i;
+ if (objarray->vector[i]) {
+ JS_SET_TRACING_INDEX(trc, "objects", i);
+ JS_CallTracer(trc, objarray->vector[i], JSTRACE_OBJECT);
+ }
+ } while (i != 0);
+ }
+
+ if (script->regexpsOffset != 0) {
+ objarray = JS_SCRIPT_REGEXPS(script);
+ i = objarray->length;
+ do {
+ --i;
+ if (objarray->vector[i]) {
+ JS_SET_TRACING_INDEX(trc, "regexps", i);
+ JS_CallTracer(trc, objarray->vector[i], JSTRACE_OBJECT);
+ }
+ } while (i != 0);
+ }
+
+ if (script->u.object) {
+ JS_SET_TRACING_NAME(trc, "object");
+ JS_CallTracer(trc, script->u.object, JSTRACE_OBJECT);
+ }
+
+ if (IS_GC_MARKING_TRACER(trc) && script->filename)
+ js_MarkScriptFilename(script->filename);
+}
+
+typedef struct GSNCacheEntry {
+ JSDHashEntryHdr hdr;
+ jsbytecode *pc;
+ jssrcnote *sn;
+} GSNCacheEntry;
+
+#define GSN_CACHE_THRESHOLD 100
+
+jssrcnote *
+js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc)
+{
+ ptrdiff_t target, offset;
+ GSNCacheEntry *entry;
+ jssrcnote *sn, *result;
+ uintN nsrcnotes;
+
+
+ target = PTRDIFF(pc, script->code, jsbytecode);
+ if ((uint32)target >= script->length)
+ return NULL;
+
+ if (JS_GSN_CACHE(cx).code == script->code) {
+ JS_METER_GSN_CACHE(cx, hits);
+ entry = (GSNCacheEntry *)
+ JS_DHashTableOperate(&JS_GSN_CACHE(cx).table, pc,
+ JS_DHASH_LOOKUP);
+ return entry->sn;
+ }
+
+ JS_METER_GSN_CACHE(cx, misses);
+ offset = 0;
+ for (sn = SCRIPT_NOTES(script); ; sn = SN_NEXT(sn)) {
+ if (SN_IS_TERMINATOR(sn)) {
+ result = NULL;
+ break;
+ }
+ offset += SN_DELTA(sn);
+ if (offset == target && SN_IS_GETTABLE(sn)) {
+ result = sn;
+ break;
+ }
+ }
+
+ if (JS_GSN_CACHE(cx).code != script->code &&
+ script->length >= GSN_CACHE_THRESHOLD) {
+ JS_CLEAR_GSN_CACHE(cx);
+ nsrcnotes = 0;
+ for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn);
+ sn = SN_NEXT(sn)) {
+ if (SN_IS_GETTABLE(sn))
+ ++nsrcnotes;
+ }
+ if (!JS_DHashTableInit(&JS_GSN_CACHE(cx).table, JS_DHashGetStubOps(),
+ NULL, sizeof(GSNCacheEntry),
+ JS_DHASH_DEFAULT_CAPACITY(nsrcnotes))) {
+ JS_GSN_CACHE(cx).table.ops = NULL;
+ } else {
+ pc = script->code;
+ for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn);
+ sn = SN_NEXT(sn)) {
+ pc += SN_DELTA(sn);
+ if (SN_IS_GETTABLE(sn)) {
+ entry = (GSNCacheEntry *)
+ JS_DHashTableOperate(&JS_GSN_CACHE(cx).table, pc,
+ JS_DHASH_ADD);
+ entry->pc = pc;
+ entry->sn = sn;
+ }
+ }
+ JS_GSN_CACHE(cx).code = script->code;
+ JS_METER_GSN_CACHE(cx, fills);
+ }
+ }
+
+ return result;
+}
+
+uintN
+js_FramePCToLineNumber(JSContext *cx, JSStackFrame *fp)
+{
+ return js_PCToLineNumber(cx, fp->script, fp->imacpc ? fp->imacpc : fp->regs->pc);
+}
+
+uintN
+js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
+{
+ JSFunction *fun;
+ uintN lineno;
+ ptrdiff_t offset, target;
+ jssrcnote *sn;
+ JSSrcNoteType type;
+
+ /* Cope with JSStackFrame.pc value prior to entering js_Interpret. */
+ if (!pc)
+ return 0;
+
+ /*
+ * Special case: function definition needs no line number note because
+ * the function's script contains its starting line number.
+ */
+ if (js_CodeSpec[*pc].format & JOF_INDEXBASE)
+ pc += js_CodeSpec[*pc].length;
+ if (*pc == JSOP_DEFFUN) {
+ GET_FUNCTION_FROM_BYTECODE(script, pc, 0, fun);
+ return fun->u.i.script->lineno;
+ }
+
+ /*
+ * General case: walk through source notes accumulating their deltas,
+ * keeping track of line-number notes, until we pass the note for pc's
+ * offset within script->code.
+ */
+ lineno = script->lineno;
+ offset = 0;
+ target = PTRDIFF(pc, script->code, jsbytecode);
+ for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
+ offset += SN_DELTA(sn);
+ type = (JSSrcNoteType) SN_TYPE(sn);
+ if (type == SRC_SETLINE) {
+ if (offset <= target)
+ lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
+ } else if (type == SRC_NEWLINE) {
+ if (offset <= target)
+ lineno++;
+ }
+ if (offset > target)
+ break;
+ }
+ return lineno;
+}
+
+/* The line number limit is the same as the jssrcnote offset limit. */
+#define SN_LINE_LIMIT (SN_3BYTE_OFFSET_FLAG << 16)
+
+jsbytecode *
+js_LineNumberToPC(JSScript *script, uintN target)
+{
+ ptrdiff_t offset, best;
+ uintN lineno, bestdiff, diff;
+ jssrcnote *sn;
+ JSSrcNoteType type;
+
+ offset = 0;
+ best = -1;
+ lineno = script->lineno;
+ bestdiff = SN_LINE_LIMIT;
+ for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
+ /*
+ * Exact-match only if offset is not in the prolog; otherwise use
+ * nearest greater-or-equal line number match.
+ */
+ if (lineno == target && script->code + offset >= script->main)
+ goto out;
+ if (lineno >= target) {
+ diff = lineno - target;
+ if (diff < bestdiff) {
+ bestdiff = diff;
+ best = offset;
+ }
+ }
+ offset += SN_DELTA(sn);
+ type = (JSSrcNoteType) SN_TYPE(sn);
+ if (type == SRC_SETLINE) {
+ lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
+ } else if (type == SRC_NEWLINE) {
+ lineno++;
+ }
+ }
+ if (best >= 0)
+ offset = best;
+out:
+ return script->code + offset;
+}
+
+JS_FRIEND_API(uintN)
+js_GetScriptLineExtent(JSScript *script)
+{
+ uintN lineno;
+ jssrcnote *sn;
+ JSSrcNoteType type;
+
+ lineno = script->lineno;
+ for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
+ type = (JSSrcNoteType) SN_TYPE(sn);
+ if (type == SRC_SETLINE) {
+ lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
+ } else if (type == SRC_NEWLINE) {
+ lineno++;
+ }
+ }
+ return 1 + lineno - script->lineno;
+}
+
+#if JS_HAS_GENERATORS
+
+JSBool
+js_IsInsideTryWithFinally(JSScript *script, jsbytecode *pc)
+{
+ JSTryNoteArray *tarray;
+ JSTryNote *tn, *tnlimit;
+ uint32 off;
+
+ JS_ASSERT(script->code <= pc);
+ JS_ASSERT(pc < script->code + script->length);
+
+ if (!script->trynotesOffset != 0)
+ return JS_FALSE;
+ tarray = JS_SCRIPT_TRYNOTES(script);
+ JS_ASSERT(tarray->length != 0);
+
+ tn = tarray->vector;
+ tnlimit = tn + tarray->length;
+ off = (uint32)(pc - script->main);
+ do {
+ if (off - tn->start < tn->length) {
+ if (tn->kind == JSTRY_FINALLY)
+ return JS_TRUE;
+ JS_ASSERT(tn->kind == JSTRY_CATCH);
+ }
+ } while (++tn != tnlimit);
+ return JS_FALSE;
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscript.h b/tools/node_modules/expresso/deps/jscoverage/js/jsscript.h
new file mode 100644
index 0000000..00f7ca7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscript.h
@@ -0,0 +1,330 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsscript_h___
+#define jsscript_h___
+/*
+ * JS script descriptor.
+ */
+#include "jsatom.h"
+#include "jsprvtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Type of try note associated with each catch or finally block, and also with
+ * for-in loops.
+ */
+typedef enum JSTryNoteKind {
+ JSTRY_CATCH,
+ JSTRY_FINALLY,
+ JSTRY_ITER
+} JSTryNoteKind;
+
+/*
+ * Exception handling record.
+ */
+struct JSTryNote {
+ uint8 kind; /* one of JSTryNoteKind */
+ uint8 padding; /* explicit padding on uint16 boundary */
+ uint16 stackDepth; /* stack depth upon exception handler entry */
+ uint32 start; /* start of the try statement or for-in loop
+ relative to script->main */
+ uint32 length; /* length of the try statement or for-in loop */
+};
+
+typedef struct JSTryNoteArray {
+ JSTryNote *vector; /* array of indexed try notes */
+ uint32 length; /* count of indexed try notes */
+} JSTryNoteArray;
+
+typedef struct JSObjectArray {
+ JSObject **vector; /* array of indexed objects */
+ uint32 length; /* count of indexed objects */
+} JSObjectArray;
+
+typedef struct JSUpvarArray {
+ uint32 *vector; /* array of indexed upvar cookies */
+ uint32 length; /* count of indexed upvar cookies */
+} JSUpvarArray;
+
+#define MAKE_UPVAR_COOKIE(skip,slot) ((skip) << 16 | (slot))
+#define UPVAR_FRAME_SKIP(cookie) ((uint32)(cookie) >> 16)
+#define UPVAR_FRAME_SLOT(cookie) ((uint16)(cookie))
+
+#define JS_OBJECT_ARRAY_SIZE(length) \
+ (offsetof(JSObjectArray, vector) + sizeof(JSObject *) * (length))
+
+#if defined DEBUG && defined JS_THREADSAFE
+# define CHECK_SCRIPT_OWNER 1
+#endif
+
+struct JSScript {
+ jsbytecode *code; /* bytecodes and their immediate operands */
+ uint32 length; /* length of code vector */
+ uint16 version; /* JS version under which script was compiled */
+ uint16 nfixed; /* number of slots besides stack operands in
+ slot array */
+ uint8 objectsOffset; /* offset to the array of nested function,
+ block, scope, xml and one-time regexps
+ objects or 0 if none */
+ uint8 upvarsOffset; /* offset of the array of display ("up")
+ closure vars or 0 if none */
+ uint8 regexpsOffset; /* offset to the array of to-be-cloned
+ regexps or 0 if none. */
+ uint8 trynotesOffset; /* offset to the array of try notes or
+ 0 if none */
+ uint8 flags; /* see below */
+ jsbytecode *main; /* main entry point, after predef'ing prolog */
+ JSAtomMap atomMap; /* maps immediate index to literal struct */
+ const char *filename; /* source filename or null */
+ uint32 lineno; /* base line number of script */
+ uint16 nslots; /* vars plus maximum stack depth */
+ uint16 staticDepth;/* static depth for display maintenance */
+ JSPrincipals *principals;/* principals for this script */
+ union {
+ JSObject *object; /* optional Script-class object wrapper */
+ JSScript *nextToGC; /* next to GC in rt->scriptsToGC list */
+ } u;
+#ifdef CHECK_SCRIPT_OWNER
+ JSThread *owner; /* for thread-safe life-cycle assertions */
+#endif
+};
+
+#define JSSF_NO_SCRIPT_RVAL 0x01 /* no need for result value of last
+ expression statement */
+
+static JS_INLINE uintN
+StackDepth(JSScript *script)
+{
+ return script->nslots - script->nfixed;
+}
+
+/* No need to store script->notes now that it is allocated right after code. */
+#define SCRIPT_NOTES(script) ((jssrcnote*)((script)->code+(script)->length))
+
+#define JS_SCRIPT_OBJECTS(script) \
+ (JS_ASSERT((script)->objectsOffset != 0), \
+ (JSObjectArray *)((uint8 *)(script) + (script)->objectsOffset))
+
+#define JS_SCRIPT_UPVARS(script) \
+ (JS_ASSERT((script)->upvarsOffset != 0), \
+ (JSUpvarArray *)((uint8 *)(script) + (script)->upvarsOffset))
+
+#define JS_SCRIPT_REGEXPS(script) \
+ (JS_ASSERT((script)->regexpsOffset != 0), \
+ (JSObjectArray *)((uint8 *)(script) + (script)->regexpsOffset))
+
+#define JS_SCRIPT_TRYNOTES(script) \
+ (JS_ASSERT((script)->trynotesOffset != 0), \
+ (JSTryNoteArray *)((uint8 *)(script) + (script)->trynotesOffset))
+
+#define JS_GET_SCRIPT_ATOM(script_, index, atom) \
+ JS_BEGIN_MACRO \
+ if (cx->fp && cx->fp->imacpc && cx->fp->script == script_) { \
+ JS_ASSERT((size_t)(index) < js_common_atom_count); \
+ (atom) = COMMON_ATOMS_START(&cx->runtime->atomState)[index]; \
+ } else { \
+ JSAtomMap *atoms_ = &(script_)->atomMap; \
+ JS_ASSERT((uint32)(index) < atoms_->length); \
+ (atom) = atoms_->vector[index]; \
+ } \
+ JS_END_MACRO
+
+#define JS_GET_SCRIPT_OBJECT(script, index, obj) \
+ JS_BEGIN_MACRO \
+ JSObjectArray *objects_ = JS_SCRIPT_OBJECTS(script); \
+ JS_ASSERT((uint32)(index) < objects_->length); \
+ (obj) = objects_->vector[index]; \
+ JS_END_MACRO
+
+#define JS_GET_SCRIPT_FUNCTION(script, index, fun) \
+ JS_BEGIN_MACRO \
+ JSObject *funobj_; \
+ \
+ JS_GET_SCRIPT_OBJECT(script, index, funobj_); \
+ JS_ASSERT(HAS_FUNCTION_CLASS(funobj_)); \
+ JS_ASSERT(funobj_ == (JSObject *) STOBJ_GET_PRIVATE(funobj_)); \
+ (fun) = (JSFunction *) funobj_; \
+ JS_ASSERT(FUN_INTERPRETED(fun)); \
+ JS_END_MACRO
+
+#define JS_GET_SCRIPT_REGEXP(script, index, obj) \
+ JS_BEGIN_MACRO \
+ JSObjectArray *regexps_ = JS_SCRIPT_REGEXPS(script); \
+ JS_ASSERT((uint32)(index) < regexps_->length); \
+ (obj) = regexps_->vector[index]; \
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_RegExpClass); \
+ JS_END_MACRO
+
+/*
+ * Check if pc is inside a try block that has finally code. GC calls this to
+ * check if it is necessary to schedule generator.close() invocation for an
+ * unreachable generator.
+ */
+JSBool
+js_IsInsideTryWithFinally(JSScript *script, jsbytecode *pc);
+
+extern JS_FRIEND_DATA(JSClass) js_ScriptClass;
+
+extern JSObject *
+js_InitScriptClass(JSContext *cx, JSObject *obj);
+
+/*
+ * On first new context in rt, initialize script runtime state, specifically
+ * the script filename table and its lock.
+ */
+extern JSBool
+js_InitRuntimeScriptState(JSRuntime *rt);
+
+/*
+ * On last context destroy for rt, if script filenames are all GC'd, free the
+ * script filename table and its lock.
+ */
+extern void
+js_FinishRuntimeScriptState(JSRuntime *rt);
+
+/*
+ * On JS_DestroyRuntime(rt), forcibly free script filename prefixes and any
+ * script filename table entries that have not been GC'd, the latter using
+ * js_FinishRuntimeScriptState.
+ *
+ * This allows script filename prefixes to outlive any context in rt.
+ */
+extern void
+js_FreeRuntimeScriptState(JSRuntime *rt);
+
+extern const char *
+js_SaveScriptFilename(JSContext *cx, const char *filename);
+
+extern const char *
+js_SaveScriptFilenameRT(JSRuntime *rt, const char *filename, uint32 flags);
+
+extern uint32
+js_GetScriptFilenameFlags(const char *filename);
+
+extern void
+js_MarkScriptFilename(const char *filename);
+
+extern void
+js_MarkScriptFilenames(JSRuntime *rt, JSBool keepAtoms);
+
+extern void
+js_SweepScriptFilenames(JSRuntime *rt);
+
+/*
+ * Two successively less primitive ways to make a new JSScript. The first
+ * does *not* call a non-null cx->runtime->newScriptHook -- only the second,
+ * js_NewScriptFromCG, calls this optional debugger hook.
+ *
+ * The js_NewScript function can't know whether the script it creates belongs
+ * to a function, or is top-level or eval code, but the debugger wants access
+ * to the newly made script's function, if any -- so callers of js_NewScript
+ * are responsible for notifying the debugger after successfully creating any
+ * kind (function or other) of new JSScript.
+ */
+extern JSScript *
+js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
+ uint32 nobjects, uint32 nupvars, uint32 nregexps,
+ uint32 ntrynotes);
+
+extern JSScript *
+js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg);
+
+/*
+ * New-script-hook calling is factored from js_NewScriptFromCG so that it
+ * and callers of js_XDRScript can share this code. In the case of callers
+ * of js_XDRScript, the hook should be invoked only after successful decode
+ * of any owning function (the fun parameter) or script object (null fun).
+ */
+extern JS_FRIEND_API(void)
+js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun);
+
+extern JS_FRIEND_API(void)
+js_CallDestroyScriptHook(JSContext *cx, JSScript *script);
+
+extern void
+js_DestroyScript(JSContext *cx, JSScript *script);
+
+extern void
+js_TraceScript(JSTracer *trc, JSScript *script);
+
+/*
+ * To perturb as little code as possible, we introduce a js_GetSrcNote lookup
+ * cache without adding an explicit cx parameter. Thus js_GetSrcNote becomes
+ * a macro that uses cx from its calls' lexical environments.
+ */
+#define js_GetSrcNote(script,pc) js_GetSrcNoteCached(cx, script, pc)
+
+extern jssrcnote *
+js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc);
+
+/*
+ * NOTE: use js_FramePCToLineNumber(cx, fp) when you have an active fp, in
+ * preference to js_PCToLineNumber (cx, fp->script fp->regs->pc), because
+ * fp->imacpc may be non-null, indicating an active imacro.
+ */
+extern uintN
+js_FramePCToLineNumber(JSContext *cx, JSStackFrame *fp);
+
+extern uintN
+js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
+
+extern jsbytecode *
+js_LineNumberToPC(JSScript *script, uintN lineno);
+
+extern JS_FRIEND_API(uintN)
+js_GetScriptLineExtent(JSScript *script);
+
+/*
+ * If magic is non-null, js_XDRScript succeeds on magic number mismatch but
+ * returns false in *magic; it reflects a match via a true *magic out param.
+ * If magic is null, js_XDRScript returns false on bad magic number errors,
+ * which it reports.
+ *
+ * NB: callers must call js_CallNewScriptHook after successful JSXDR_DECODE
+ * and subsequent set-up of owning function or script object, if any.
+ */
+extern JSBool
+js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *magic);
+
+JS_END_EXTERN_C
+
+#endif /* jsscript_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsshell.msg b/tools/node_modules/expresso/deps/jscoverage/js/jsshell.msg
new file mode 100644
index 0000000..7074fe9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsshell.msg
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ Error messages for JSShell. See js.msg for format.
+*/
+
+MSG_DEF(JSSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
+MSG_DEF(JSSMSG_CANT_OPEN, 1, 2, JSEXN_NONE, "can't open {0}: {1}")
+MSG_DEF(JSSMSG_TRAP_USAGE, 2, 0, JSEXN_NONE, "usage: trap [fun] [pc] expr")
+MSG_DEF(JSSMSG_LINE2PC_USAGE, 3, 0, JSEXN_NONE, "usage: line2pc [fun] line")
+MSG_DEF(JSSMSG_FILE_SCRIPTS_ONLY, 4, 0, JSEXN_NONE, "only works on JS scripts read from files")
+MSG_DEF(JSSMSG_UNEXPECTED_EOF, 5, 1, JSEXN_NONE, "unexpected EOF in {0}")
+MSG_DEF(JSSMSG_DOEXP_USAGE, 6, 0, JSEXN_NONE, "usage: doexp obj id")
+MSG_DEF(JSSMSG_SCRIPTS_ONLY, 7, 0, JSEXN_NONE, "only works on scripts")
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsstaticcheck.h b/tools/node_modules/expresso/deps/jscoverage/js/jsstaticcheck.h
new file mode 100644
index 0000000..2614659
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsstaticcheck.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsstaticcheck_h___
+#define jsstaticcheck_h___
+
+#ifdef NS_STATIC_CHECKING
+/*
+ * Trigger a control flow check to make sure that code flows through label
+ */
+inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {
+}
+
+/* avoid unused goto-label warnings */
+#define MUST_FLOW_LABEL(label) goto label; label:
+#else
+#define MUST_FLOW_THROUGH(label) ((void)0)
+#define MUST_FLOW_LABEL(label)
+#endif
+
+#endif /* jsstaticcheck_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsstddef.h b/tools/node_modules/expresso/deps/jscoverage/js/jsstddef.h
new file mode 100644
index 0000000..45b417f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsstddef.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * stddef inclusion here to first declare ptrdif as a signed long instead of a
+ * signed int.
+ */
+
+#ifdef _WINDOWS
+# ifndef XP_WIN
+# define XP_WIN
+# endif
+#if defined(_WIN32) || defined(WIN32)
+# ifndef XP_WIN32
+# define XP_WIN32
+# endif
+#else
+# ifndef XP_WIN16
+# define XP_WIN16
+# endif
+#endif
+#endif
+
+#ifdef XP_WIN16
+#ifndef _PTRDIFF_T_DEFINED
+typedef long ptrdiff_t;
+
+/*
+ * The Win16 compiler treats pointer differences as 16-bit signed values.
+ * This macro allows us to treat them as 17-bit signed values, stored in
+ * a 32-bit type.
+ */
+#define PTRDIFF(p1, p2, type) \
+ ((((unsigned long)(p1)) - ((unsigned long)(p2))) / sizeof(type))
+
+#define _PTRDIFF_T_DEFINED
+#endif /*_PTRDIFF_T_DEFINED*/
+#else /*WIN16*/
+
+#define PTRDIFF(p1, p2, type) \
+ ((p1) - (p2))
+
+#endif
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+# define __cplusplus_only(x) x
+#else
+# define __cplusplus_only(x) /* nothing */
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsstr.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsstr.cpp
new file mode 100644
index 0000000..eeb505d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsstr.cpp
@@ -0,0 +1,5347 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS string type implementation.
+ *
+ * In order to avoid unnecessary js_LockGCThing/js_UnlockGCThing calls, these
+ * native methods store strings (possibly newborn) converted from their 'this'
+ * parameter and arguments on the stack: 'this' conversions at argv[-1], arg
+ * conversions at their index (argv[0], argv[1]). This is a legitimate method
+ * of rooting things that might lose their newborn root due to subsequent GC
+ * allocations in the same native method.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jshash.h" /* Added by JSIFY */
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsregexp.h"
+#include "jsscope.h"
+#include "jsstr.h"
+#include "jsbit.h"
+
+#define JSSTRDEP_RECURSION_LIMIT 100
+
+size_t
+js_MinimizeDependentStrings(JSString *str, int level, JSString **basep)
+{
+ JSString *base;
+ size_t start, length;
+
+ JS_ASSERT(JSSTRING_IS_DEPENDENT(str));
+ base = JSSTRDEP_BASE(str);
+ start = JSSTRDEP_START(str);
+ if (JSSTRING_IS_DEPENDENT(base)) {
+ if (level < JSSTRDEP_RECURSION_LIMIT) {
+ start += js_MinimizeDependentStrings(base, level + 1, &base);
+ } else {
+ do {
+ start += JSSTRDEP_START(base);
+ base = JSSTRDEP_BASE(base);
+ } while (JSSTRING_IS_DEPENDENT(base));
+ }
+ if (start == 0) {
+ JS_ASSERT(JSSTRDEP_IS_PREFIX(str));
+ JSPREFIX_SET_BASE(str, base);
+ } else if (start <= JSSTRDEP_START_MASK) {
+ length = JSSTRDEP_LENGTH(str);
+ JSSTRDEP_INIT(str, base, start, length);
+ }
+ }
+ *basep = base;
+ return start;
+}
+
+jschar *
+js_GetDependentStringChars(JSString *str)
+{
+ size_t start;
+ JSString *base;
+
+ start = js_MinimizeDependentStrings(str, 0, &base);
+ JS_ASSERT(start < JSFLATSTR_LENGTH(base));
+ return JSFLATSTR_CHARS(base) + start;
+}
+
+const jschar *
+js_GetStringChars(JSContext *cx, JSString *str)
+{
+ if (!js_MakeStringImmutable(cx, str))
+ return NULL;
+ return JSFLATSTR_CHARS(str);
+}
+
+JSString * JS_FASTCALL
+js_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
+{
+ size_t rn, ln, lrdist, n;
+ jschar *rs, *ls, *s;
+ JSString *ldep; /* non-null if left should become dependent */
+ JSString *str;
+
+ JSSTRING_CHARS_AND_LENGTH(right, rs, rn);
+ if (rn == 0)
+ return left;
+
+ JSSTRING_CHARS_AND_LENGTH(left, ls, ln);
+ if (ln == 0)
+ return right;
+
+ if (!JSSTRING_IS_MUTABLE(left)) {
+ /* We must copy if left does not own a buffer to realloc. */
+ s = (jschar *) JS_malloc(cx, (ln + rn + 1) * sizeof(jschar));
+ if (!s)
+ return NULL;
+ js_strncpy(s, ls, ln);
+ ldep = NULL;
+ } else {
+ /* We can realloc left's space and make it depend on our result. */
+ JS_ASSERT(JSSTRING_IS_FLAT(left));
+ s = (jschar *) JS_realloc(cx, ls, (ln + rn + 1) * sizeof(jschar));
+ if (!s)
+ return NULL;
+
+ /* Take care: right could depend on left! */
+ lrdist = (size_t)(rs - ls);
+ if (lrdist < ln)
+ rs = s + lrdist;
+ left->u.chars = ls = s;
+ ldep = left;
+ }
+
+ js_strncpy(s + ln, rs, rn);
+ n = ln + rn;
+ s[n] = 0;
+ str = js_NewString(cx, s, n);
+ if (!str) {
+ /* Out of memory: clean up any space we (re-)allocated. */
+ if (!ldep) {
+ JS_free(cx, s);
+ } else {
+ s = (jschar *) JS_realloc(cx, ls, (ln + 1) * sizeof(jschar));
+ if (s)
+ left->u.chars = s;
+ }
+ } else {
+ JSFLATSTR_SET_MUTABLE(str);
+
+ /* Morph left into a dependent prefix if we realloc'd its buffer. */
+ if (ldep) {
+ JSPREFIX_INIT(ldep, str, ln);
+#ifdef DEBUG
+ {
+ JSRuntime *rt = cx->runtime;
+ JS_RUNTIME_METER(rt, liveDependentStrings);
+ JS_RUNTIME_METER(rt, totalDependentStrings);
+ JS_LOCK_RUNTIME_VOID(rt,
+ (rt->strdepLengthSum += (double)ln,
+ rt->strdepLengthSquaredSum += (double)ln * (double)ln));
+ }
+#endif
+ }
+ }
+
+ return str;
+}
+
+const jschar *
+js_UndependString(JSContext *cx, JSString *str)
+{
+ size_t n, size;
+ jschar *s;
+
+ if (JSSTRING_IS_DEPENDENT(str)) {
+ n = JSSTRDEP_LENGTH(str);
+ size = (n + 1) * sizeof(jschar);
+ s = (jschar *) JS_malloc(cx, size);
+ if (!s)
+ return NULL;
+
+ js_strncpy(s, JSSTRDEP_CHARS(str), n);
+ s[n] = 0;
+ JSFLATSTR_INIT(str, s, n);
+
+#ifdef DEBUG
+ {
+ JSRuntime *rt = cx->runtime;
+ JS_RUNTIME_UNMETER(rt, liveDependentStrings);
+ JS_RUNTIME_UNMETER(rt, totalDependentStrings);
+ JS_LOCK_RUNTIME_VOID(rt,
+ (rt->strdepLengthSum -= (double)n,
+ rt->strdepLengthSquaredSum -= (double)n * (double)n));
+ }
+#endif
+ }
+
+ return JSFLATSTR_CHARS(str);
+}
+
+JSBool
+js_MakeStringImmutable(JSContext *cx, JSString *str)
+{
+ if (JSSTRING_IS_DEPENDENT(str) && !js_UndependString(cx, str)) {
+ JS_RUNTIME_METER(cx->runtime, badUndependStrings);
+ return JS_FALSE;
+ }
+ JSFLATSTR_CLEAR_MUTABLE(str);
+ return JS_TRUE;
+}
+
+static JSString *
+ArgToRootedString(JSContext *cx, uintN argc, jsval *vp, uintN arg)
+{
+ JSObject *obj;
+ JSString *str;
+
+ if (arg >= argc)
+ return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
+ vp += 2 + arg;
+
+ if (JSVAL_IS_OBJECT(*vp)) {
+ obj = JSVAL_TO_OBJECT(*vp);
+ if (!obj)
+ return ATOM_TO_STRING(cx->runtime->atomState.nullAtom);
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, vp))
+ return NULL;
+ }
+ if (JSVAL_IS_STRING(*vp))
+ return JSVAL_TO_STRING(*vp);
+ if (JSVAL_IS_INT(*vp)) {
+ str = js_NumberToString(cx, JSVAL_TO_INT(*vp));
+ } else if (JSVAL_IS_DOUBLE(*vp)) {
+ str = js_NumberToString(cx, *JSVAL_TO_DOUBLE(*vp));
+ } else if (JSVAL_IS_BOOLEAN(*vp)) {
+ return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[
+ JSVAL_TO_BOOLEAN(*vp)? 1 : 0]);
+ } else {
+ JS_ASSERT(JSVAL_IS_VOID(*vp));
+ return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
+ }
+ if (str)
+ *vp = STRING_TO_JSVAL(str);
+ return str;
+}
+
+/*
+ * Forward declarations for URI encode/decode and helper routines
+ */
+static JSBool
+str_decodeURI(JSContext *cx, uintN argc, jsval *vp);
+
+static JSBool
+str_decodeURI_Component(JSContext *cx, uintN argc, jsval *vp);
+
+static JSBool
+str_encodeURI(JSContext *cx, uintN argc, jsval *vp);
+
+static JSBool
+str_encodeURI_Component(JSContext *cx, uintN argc, jsval *vp);
+
+static uint32
+Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length);
+
+/*
+ * Contributions from the String class to the set of methods defined for the
+ * global object. escape and unescape used to be defined in the Mocha library,
+ * but as ECMA decided to spec them, they've been moved to the core engine
+ * and made ECMA-compliant. (Incomplete escapes are interpreted as literal
+ * characters by unescape.)
+ */
+
+/*
+ * Stuff to emulate the old libmocha escape, which took a second argument
+ * giving the type of escape to perform. Retained for compatibility, and
+ * copied here to avoid reliance on net.h, mkparse.c/NET_EscapeBytes.
+ */
+
+#define URL_XALPHAS ((uint8) 1)
+#define URL_XPALPHAS ((uint8) 2)
+#define URL_PATH ((uint8) 4)
+
+static const uint8 urlCharType[256] =
+/* Bit 0 xalpha -- the alphas
+ * Bit 1 xpalpha -- as xalpha but
+ * converts spaces to plus and plus to %20
+ * Bit 2 ... path -- as xalphas but doesn't escape '/'
+ */
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1x */
+ 0,0,0,0,0,0,0,0,0,0,7,4,0,7,7,4, /* 2x !"#$%&'()*+,-./ */
+ 7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 4x @ABCDEFGHIJKLMNO */
+ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7, /* 5X PQRSTUVWXYZ[\]^_ */
+ 0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 6x `abcdefghijklmno */
+ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0, /* 7X pqrstuvwxyz{\}~ DEL */
+ 0, };
+
+/* This matches the ECMA escape set when mask is 7 (default.) */
+
+#define IS_OK(C, mask) (urlCharType[((uint8) (C))] & (mask))
+
+/* See ECMA-262 Edition 3 B.2.1 */
+JSBool
+js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+ size_t i, ni, length, newlength;
+ const jschar *chars;
+ jschar *newchars;
+ jschar ch;
+ jsint mask;
+ jsdouble d;
+ const char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;
+ if (argc > 1) {
+ d = js_ValueToNumber(cx, &argv[1]);
+ if (JSVAL_IS_NULL(argv[1]))
+ return JS_FALSE;
+ if (!JSDOUBLE_IS_FINITE(d) ||
+ (mask = (jsint)d) != d ||
+ mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH))
+ {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) mask);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_STRING_MASK, numBuf);
+ return JS_FALSE;
+ }
+ }
+
+ str = ArgToRootedString(cx, argc, argv - 2, 0);
+ if (!str)
+ return JS_FALSE;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ newlength = length;
+
+ /* Take a first pass and see how big the result string will need to be. */
+ for (i = 0; i < length; i++) {
+ if ((ch = chars[i]) < 128 && IS_OK(ch, mask))
+ continue;
+ if (ch < 256) {
+ if (mask == URL_XPALPHAS && ch == ' ')
+ continue; /* The character will be encoded as '+' */
+ newlength += 2; /* The character will be encoded as %XX */
+ } else {
+ newlength += 5; /* The character will be encoded as %uXXXX */
+ }
+
+ /*
+ * This overflow test works because newlength is incremented by at
+ * most 5 on each iteration.
+ */
+ if (newlength < length) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+ }
+
+ if (newlength >= ~(size_t)0 / sizeof(jschar)) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+
+ newchars = (jschar *) JS_malloc(cx, (newlength + 1) * sizeof(jschar));
+ if (!newchars)
+ return JS_FALSE;
+ for (i = 0, ni = 0; i < length; i++) {
+ if ((ch = chars[i]) < 128 && IS_OK(ch, mask)) {
+ newchars[ni++] = ch;
+ } else if (ch < 256) {
+ if (mask == URL_XPALPHAS && ch == ' ') {
+ newchars[ni++] = '+'; /* convert spaces to pluses */
+ } else {
+ newchars[ni++] = '%';
+ newchars[ni++] = digits[ch >> 4];
+ newchars[ni++] = digits[ch & 0xF];
+ }
+ } else {
+ newchars[ni++] = '%';
+ newchars[ni++] = 'u';
+ newchars[ni++] = digits[ch >> 12];
+ newchars[ni++] = digits[(ch & 0xF00) >> 8];
+ newchars[ni++] = digits[(ch & 0xF0) >> 4];
+ newchars[ni++] = digits[ch & 0xF];
+ }
+ }
+ JS_ASSERT(ni == newlength);
+ newchars[newlength] = 0;
+
+ str = js_NewString(cx, newchars, newlength);
+ if (!str) {
+ JS_free(cx, newchars);
+ return JS_FALSE;
+ }
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#undef IS_OK
+
+static JSBool
+str_escape(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && js_str_escape(cx, obj, argc, vp + 2, vp);
+}
+
+/* See ECMA-262 Edition 3 B.2.2 */
+static JSBool
+str_unescape(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ size_t i, ni, length;
+ const jschar *chars;
+ jschar *newchars;
+ jschar ch;
+
+ str = ArgToRootedString(cx, argc, vp, 0);
+ if (!str)
+ return JS_FALSE;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+
+ /* Don't bother allocating less space for the new string. */
+ newchars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!newchars)
+ return JS_FALSE;
+ ni = i = 0;
+ while (i < length) {
+ ch = chars[i++];
+ if (ch == '%') {
+ if (i + 1 < length &&
+ JS7_ISHEX(chars[i]) && JS7_ISHEX(chars[i + 1]))
+ {
+ ch = JS7_UNHEX(chars[i]) * 16 + JS7_UNHEX(chars[i + 1]);
+ i += 2;
+ } else if (i + 4 < length && chars[i] == 'u' &&
+ JS7_ISHEX(chars[i + 1]) && JS7_ISHEX(chars[i + 2]) &&
+ JS7_ISHEX(chars[i + 3]) && JS7_ISHEX(chars[i + 4]))
+ {
+ ch = (((((JS7_UNHEX(chars[i + 1]) << 4)
+ + JS7_UNHEX(chars[i + 2])) << 4)
+ + JS7_UNHEX(chars[i + 3])) << 4)
+ + JS7_UNHEX(chars[i + 4]);
+ i += 5;
+ }
+ }
+ newchars[ni++] = ch;
+ }
+ newchars[ni] = 0;
+
+ str = js_NewString(cx, newchars, ni);
+ if (!str) {
+ JS_free(cx, newchars);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#if JS_HAS_UNEVAL
+static JSBool
+str_uneval(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = js_ValueToSource(cx, argc != 0 ? vp[2] : JSVAL_VOID);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif
+
+const char js_escape_str[] = "escape";
+const char js_unescape_str[] = "unescape";
+#if JS_HAS_UNEVAL
+const char js_uneval_str[] = "uneval";
+#endif
+const char js_decodeURI_str[] = "decodeURI";
+const char js_encodeURI_str[] = "encodeURI";
+const char js_decodeURIComponent_str[] = "decodeURIComponent";
+const char js_encodeURIComponent_str[] = "encodeURIComponent";
+
+static JSFunctionSpec string_functions[] = {
+ JS_FN(js_escape_str, str_escape, 1,0),
+ JS_FN(js_unescape_str, str_unescape, 1,0),
+#if JS_HAS_UNEVAL
+ JS_FN(js_uneval_str, str_uneval, 1,0),
+#endif
+ JS_FN(js_decodeURI_str, str_decodeURI, 1,0),
+ JS_FN(js_encodeURI_str, str_encodeURI, 1,0),
+ JS_FN(js_decodeURIComponent_str, str_decodeURI_Component, 1,0),
+ JS_FN(js_encodeURIComponent_str, str_encodeURI_Component, 1,0),
+
+ JS_FS_END
+};
+
+jschar js_empty_ucstr[] = {0};
+JSSubString js_EmptySubString = {0, js_empty_ucstr};
+
+enum string_tinyid {
+ STRING_LENGTH = -1
+};
+
+static JSPropertySpec string_props[] = {
+ {js_length_str, STRING_LENGTH,
+ JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED, 0,0},
+ {0,0,0,0,0}
+};
+
+static JSBool
+str_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsval v;
+ JSString *str;
+ jsint slot;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+
+ slot = JSVAL_TO_INT(id);
+ if (slot == STRING_LENGTH) {
+ if (OBJ_GET_CLASS(cx, obj) == &js_StringClass) {
+ /* Follow ECMA-262 by fetching intrinsic length of our string. */
+ v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ str = JSVAL_TO_STRING(v);
+ } else {
+ /* Preserve compatibility: convert obj to a string primitive. */
+ str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
+ if (!str)
+ return JS_FALSE;
+ }
+
+ *vp = INT_TO_JSVAL((jsint) JSSTRING_LENGTH(str));
+ }
+ return JS_TRUE;
+}
+
+#define STRING_ELEMENT_ATTRS (JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
+
+static JSBool
+str_enumerate(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+ JSString *str, *str1;
+ size_t i, length;
+
+ v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ str = JSVAL_TO_STRING(v);
+
+ length = JSSTRING_LENGTH(str);
+ for (i = 0; i < length; i++) {
+ str1 = js_NewDependentString(cx, str, i, 1);
+ if (!str1)
+ return JS_FALSE;
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(i),
+ STRING_TO_JSVAL(str1), NULL, NULL,
+ STRING_ELEMENT_ATTRS, NULL)) {
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+str_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ jsval v;
+ JSString *str, *str1;
+ jsint slot;
+
+ if (!JSVAL_IS_INT(id) || (flags & JSRESOLVE_ASSIGNING))
+ return JS_TRUE;
+
+ v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ str = JSVAL_TO_STRING(v);
+
+ slot = JSVAL_TO_INT(id);
+ if ((size_t)slot < JSSTRING_LENGTH(str)) {
+ str1 = js_GetUnitString(cx, str, (size_t)slot);
+ if (!str1)
+ return JS_FALSE;
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(slot),
+ STRING_TO_JSVAL(str1), NULL, NULL,
+ STRING_ELEMENT_ATTRS, NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ }
+ return JS_TRUE;
+}
+
+JSClass js_StringClass = {
+ js_String_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_String),
+ JS_PropertyStub, JS_PropertyStub, str_getProperty, JS_PropertyStub,
+ str_enumerate, (JSResolveOp)str_resolve, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+#define NORMALIZE_THIS(cx,vp,str) \
+ JS_BEGIN_MACRO \
+ if (JSVAL_IS_STRING(vp[1])) { \
+ str = JSVAL_TO_STRING(vp[1]); \
+ } else { \
+ str = NormalizeThis(cx, vp); \
+ if (!str) \
+ return JS_FALSE; \
+ } \
+ JS_END_MACRO
+
+static JSString *
+NormalizeThis(JSContext *cx, jsval *vp)
+{
+ JSString *str;
+
+ if (JSVAL_IS_NULL(vp[1]) && JSVAL_IS_NULL(JS_THIS(cx, vp)))
+ return NULL;
+ str = js_ValueToString(cx, vp[1]);
+ if (!str)
+ return NULL;
+ vp[1] = STRING_TO_JSVAL(str);
+ return str;
+}
+
+#if JS_HAS_TOSOURCE
+
+/*
+ * String.prototype.quote is generic (as are most string methods), unlike
+ * toSource, toString, and valueOf.
+ */
+static JSBool
+str_quote(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ NORMALIZE_THIS(cx, vp, str);
+ str = js_QuoteString(cx, str, '"');
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+str_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ JSString *str;
+ size_t i, j, k, n;
+ char buf[16];
+ jschar *s, *t;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_StringClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ str = js_QuoteString(cx, JSVAL_TO_STRING(v), '"');
+ if (!str)
+ return JS_FALSE;
+ j = JS_snprintf(buf, sizeof buf, "(new %s(", js_StringClass.name);
+ JSSTRING_CHARS_AND_LENGTH(str, s, k);
+ n = j + k + 2;
+ t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+ if (!t)
+ return JS_FALSE;
+ for (i = 0; i < j; i++)
+ t[i] = buf[i];
+ for (j = 0; j < k; i++, j++)
+ t[i] = s[j];
+ t[i++] = ')';
+ t[i++] = ')';
+ t[i] = 0;
+ str = js_NewString(cx, t, n);
+ if (!str) {
+ JS_free(cx, t);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#endif /* JS_HAS_TOSOURCE */
+
+static JSBool
+str_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_GetPrimitiveThis(cx, vp, &js_StringClass, vp);
+}
+
+/*
+ * Java-like string native methods.
+ */
+
+static JSString *
+SubstringTail(JSContext *cx, JSString *str, jsdouble length, jsdouble begin, jsdouble end)
+{
+ if (begin < 0)
+ begin = 0;
+ else if (begin > length)
+ begin = length;
+
+ if (end < 0)
+ end = 0;
+ else if (end > length)
+ end = length;
+ if (end < begin) {
+ /* ECMA emulates old JDK1.0 java.lang.String.substring. */
+ jsdouble tmp = begin;
+ begin = end;
+ end = tmp;
+ }
+
+ return js_NewDependentString(cx, str, (size_t)begin, (size_t)(end - begin));
+}
+
+static JSBool
+str_substring(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ jsdouble d;
+ jsdouble length, begin, end;
+
+ NORMALIZE_THIS(cx, vp, str);
+ if (argc != 0) {
+ d = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ length = JSSTRING_LENGTH(str);
+ begin = js_DoubleToInteger(d);
+ if (argc == 1) {
+ end = length;
+ } else {
+ d = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ end = js_DoubleToInteger(d);
+ }
+
+ str = SubstringTail(cx, str, length, begin, end);
+ if (!str)
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static JSString* FASTCALL
+String_p_toString(JSContext* cx, JSObject* obj)
+{
+ if (!JS_InstanceOf(cx, obj, &js_StringClass, NULL))
+ return NULL;
+ jsval v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ return JSVAL_TO_STRING(v);
+}
+
+static JSString* FASTCALL
+String_p_substring(JSContext* cx, JSString* str, int32 begin, int32 end)
+{
+ JS_ASSERT(JS_ON_TRACE(cx));
+
+ size_t length = JSSTRING_LENGTH(str);
+ return SubstringTail(cx, str, length, begin, end);
+}
+
+static JSString* FASTCALL
+String_p_substring_1(JSContext* cx, JSString* str, int32 begin)
+{
+ JS_ASSERT(JS_ON_TRACE(cx));
+
+ size_t length = JSSTRING_LENGTH(str);
+ return SubstringTail(cx, str, length, begin, length);
+}
+#endif
+
+JSString* JS_FASTCALL
+js_toLowerCase(JSContext *cx, JSString *str)
+{
+ size_t i, n;
+ jschar *s, *news;
+
+ JSSTRING_CHARS_AND_LENGTH(str, s, n);
+ news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+ if (!news)
+ return NULL;
+ for (i = 0; i < n; i++)
+ news[i] = JS_TOLOWER(s[i]);
+ news[n] = 0;
+ str = js_NewString(cx, news, n);
+ if (!str) {
+ JS_free(cx, news);
+ return NULL;
+ }
+ return str;
+}
+
+static JSBool
+str_toLowerCase(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ NORMALIZE_THIS(cx, vp, str);
+ str = js_toLowerCase(cx, str);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+str_toLocaleLowerCase(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ /*
+ * Forcefully ignore the first (or any) argument and return toLowerCase(),
+ * ECMA has reserved that argument, presumably for defining the locale.
+ */
+ if (cx->localeCallbacks && cx->localeCallbacks->localeToLowerCase) {
+ NORMALIZE_THIS(cx, vp, str);
+ return cx->localeCallbacks->localeToLowerCase(cx, str, vp);
+ }
+ return str_toLowerCase(cx, 0, vp);
+}
+
+JSString* JS_FASTCALL
+js_toUpperCase(JSContext *cx, JSString *str)
+{
+ size_t i, n;
+ jschar *s, *news;
+
+ JSSTRING_CHARS_AND_LENGTH(str, s, n);
+ news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+ if (!news)
+ return NULL;
+ for (i = 0; i < n; i++)
+ news[i] = JS_TOUPPER(s[i]);
+ news[n] = 0;
+ str = js_NewString(cx, news, n);
+ if (!str) {
+ JS_free(cx, news);
+ return NULL;
+ }
+ return str;
+}
+
+static JSBool
+str_toUpperCase(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ NORMALIZE_THIS(cx, vp, str);
+ str = js_toUpperCase(cx, str);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+str_toLocaleUpperCase(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ /*
+ * Forcefully ignore the first (or any) argument and return toUpperCase(),
+ * ECMA has reserved that argument, presumably for defining the locale.
+ */
+ if (cx->localeCallbacks && cx->localeCallbacks->localeToUpperCase) {
+ NORMALIZE_THIS(cx, vp, str);
+ return cx->localeCallbacks->localeToUpperCase(cx, str, vp);
+ }
+ return str_toUpperCase(cx, 0, vp);
+}
+
+static JSBool
+str_localeCompare(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str, *thatStr;
+
+ NORMALIZE_THIS(cx, vp, str);
+ if (argc == 0) {
+ *vp = JSVAL_ZERO;
+ } else {
+ thatStr = js_ValueToString(cx, vp[2]);
+ if (!thatStr)
+ return JS_FALSE;
+ if (cx->localeCallbacks && cx->localeCallbacks->localeCompare) {
+ vp[2] = STRING_TO_JSVAL(thatStr);
+ return cx->localeCallbacks->localeCompare(cx, str, thatStr, vp);
+ }
+ *vp = INT_TO_JSVAL(js_CompareStrings(str, thatStr));
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+str_charAt(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval t;
+ JSString *str;
+ jsint i;
+ jsdouble d;
+
+ t = vp[1];
+ if (JSVAL_IS_STRING(t) && argc != 0 && JSVAL_IS_INT(vp[2])) {
+ str = JSVAL_TO_STRING(t);
+ i = JSVAL_TO_INT(vp[2]);
+ if ((size_t)i >= JSSTRING_LENGTH(str))
+ goto out_of_range;
+ } else {
+ str = NormalizeThis(cx, vp);
+ if (!str)
+ return JS_FALSE;
+
+ if (argc == 0) {
+ d = 0.0;
+ } else {
+ d = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ }
+
+ if (d < 0 || JSSTRING_LENGTH(str) <= d)
+ goto out_of_range;
+ i = (jsint) d;
+ }
+
+ str = js_GetUnitString(cx, str, (size_t)i);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+
+out_of_range:
+ *vp = JS_GetEmptyStringValue(cx);
+ return JS_TRUE;
+}
+
+static JSBool
+str_charCodeAt(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval t;
+ JSString *str;
+ jsint i;
+ jsdouble d;
+
+ t = vp[1];
+ if (JSVAL_IS_STRING(t) && argc != 0 && JSVAL_IS_INT(vp[2])) {
+ str = JSVAL_TO_STRING(t);
+ i = JSVAL_TO_INT(vp[2]);
+ if ((size_t)i >= JSSTRING_LENGTH(str))
+ goto out_of_range;
+ } else {
+ str = NormalizeThis(cx, vp);
+ if (!str)
+ return JS_FALSE;
+
+ if (argc == 0) {
+ d = 0.0;
+ } else {
+ d = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ }
+
+ if (d < 0 || JSSTRING_LENGTH(str) <= d)
+ goto out_of_range;
+ i = (jsint) d;
+ }
+
+ *vp = INT_TO_JSVAL(JSSTRING_CHARS(str)[i]);
+ return JS_TRUE;
+
+out_of_range:
+ *vp = JS_GetNaNValue(cx);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+int32 FASTCALL
+js_String_p_charCodeAt(JSString* str, int32 i)
+{
+ if (i < 0 || (int32)JSSTRING_LENGTH(str) <= i)
+ return -1;
+ return JSSTRING_CHARS(str)[i];
+}
+#endif
+
+jsint
+js_BoyerMooreHorspool(const jschar *text, jsint textlen,
+ const jschar *pat, jsint patlen,
+ jsint start)
+{
+ jsint i, j, k, m;
+ uint8 skip[BMH_CHARSET_SIZE];
+ jschar c;
+
+ JS_ASSERT(0 < patlen && patlen <= BMH_PATLEN_MAX);
+ for (i = 0; i < BMH_CHARSET_SIZE; i++)
+ skip[i] = (uint8)patlen;
+ m = patlen - 1;
+ for (i = 0; i < m; i++) {
+ c = pat[i];
+ if (c >= BMH_CHARSET_SIZE)
+ return BMH_BAD_PATTERN;
+ skip[c] = (uint8)(m - i);
+ }
+ for (k = start + m;
+ k < textlen;
+ k += ((c = text[k]) >= BMH_CHARSET_SIZE) ? patlen : skip[c]) {
+ for (i = k, j = m; ; i--, j--) {
+ if (j < 0)
+ return i + 1;
+ if (text[i] != pat[j])
+ break;
+ }
+ }
+ return -1;
+}
+
+static JSBool
+str_indexOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval t;
+ JSString *str, *str2;
+ const jschar *text, *pat;
+ jsint i, j, index, textlen, patlen;
+ jsdouble d;
+
+ t = vp[1];
+ if (JSVAL_IS_STRING(t) && argc != 0 && JSVAL_IS_STRING(vp[2])) {
+ str = JSVAL_TO_STRING(t);
+ str2 = JSVAL_TO_STRING(vp[2]);
+ } else {
+ str = NormalizeThis(cx, vp);
+ if (!str)
+ return JS_FALSE;
+
+ str2 = ArgToRootedString(cx, argc, vp, 0);
+ if (!str2)
+ return JS_FALSE;
+ }
+
+ text = JSSTRING_CHARS(str);
+ textlen = (jsint) JSSTRING_LENGTH(str);
+ pat = JSSTRING_CHARS(str2);
+ patlen = (jsint) JSSTRING_LENGTH(str2);
+
+ if (argc > 1) {
+ d = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ if (d < 0)
+ i = 0;
+ else if (d > textlen)
+ i = textlen;
+ else
+ i = (jsint)d;
+ } else {
+ i = 0;
+ }
+ if (patlen == 0) {
+ *vp = INT_TO_JSVAL(i);
+ return JS_TRUE;
+ }
+
+ /* XXX tune the BMH threshold (512) */
+ if (textlen - i >= 512 && (jsuint)(patlen - 2) <= BMH_PATLEN_MAX - 2) {
+ index = js_BoyerMooreHorspool(text, textlen, pat, patlen, i);
+ if (index != BMH_BAD_PATTERN)
+ goto out;
+ }
+
+ index = -1;
+ j = 0;
+ while (i + j < textlen) {
+ if (text[i + j] == pat[j]) {
+ if (++j == patlen) {
+ index = i;
+ break;
+ }
+ } else {
+ i++;
+ j = 0;
+ }
+ }
+
+out:
+ *vp = INT_TO_JSVAL(index);
+ return JS_TRUE;
+}
+
+static JSBool
+str_lastIndexOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str, *str2;
+ const jschar *text, *pat;
+ jsint i, j, textlen, patlen;
+ jsdouble d;
+
+ NORMALIZE_THIS(cx, vp, str);
+ text = JSSTRING_CHARS(str);
+ textlen = (jsint) JSSTRING_LENGTH(str);
+
+ str2 = ArgToRootedString(cx, argc, vp, 0);
+ if (!str2)
+ return JS_FALSE;
+ pat = JSSTRING_CHARS(str2);
+ patlen = (jsint) JSSTRING_LENGTH(str2);
+
+ if (argc > 1) {
+ d = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ if (JSDOUBLE_IS_NaN(d)) {
+ i = textlen;
+ } else {
+ d = js_DoubleToInteger(d);
+ if (d < 0)
+ i = 0;
+ else if (d > textlen)
+ i = textlen;
+ else
+ i = (jsint)d;
+ }
+ } else {
+ i = textlen;
+ }
+
+ if (patlen == 0) {
+ *vp = INT_TO_JSVAL(i);
+ return JS_TRUE;
+ }
+
+ j = 0;
+ while (i >= 0) {
+ /* Don't assume that text is NUL-terminated: it could be dependent. */
+ if (i + j < textlen && text[i + j] == pat[j]) {
+ if (++j == patlen)
+ break;
+ } else {
+ i--;
+ j = 0;
+ }
+ }
+ *vp = INT_TO_JSVAL(i);
+ return JS_TRUE;
+}
+
+static JSBool
+js_TrimString(JSContext *cx, jsval *vp, JSBool trimLeft, JSBool trimRight)
+{
+ JSString *str;
+ const jschar *chars;
+ size_t length, begin, end;
+
+ NORMALIZE_THIS(cx, vp, str);
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ begin = 0;
+ end = length;
+
+ if (trimLeft) {
+ while (begin < length && JS_ISSPACE(chars[begin]))
+ ++begin;
+ }
+
+ if (trimRight) {
+ while (end > begin && JS_ISSPACE(chars[end-1]))
+ --end;
+ }
+
+ str = js_NewDependentString(cx, str, begin, end - begin);
+ if (!str)
+ return JS_FALSE;
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+str_trim(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_TrimString(cx, vp, JS_TRUE, JS_TRUE);
+}
+
+static JSBool
+str_trimLeft(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_TrimString(cx, vp, JS_TRUE, JS_FALSE);
+}
+
+static JSBool
+str_trimRight(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_TrimString(cx, vp, JS_FALSE, JS_TRUE);
+}
+
+/*
+ * Perl-inspired string functions.
+ */
+typedef struct GlobData {
+ jsbytecode *pc; /* in: program counter resulting in us matching */
+ uintN flags; /* inout: mode and flag bits, see below */
+ uintN optarg; /* in: index of optional flags argument */
+ JSString *str; /* out: 'this' parameter object as string */
+ JSRegExp *regexp; /* out: regexp parameter object private data */
+} GlobData;
+
+/*
+ * Mode and flag bit definitions for match_or_replace's GlobData.flags field.
+ */
+#define MODE_MATCH 0x00 /* in: return match array on success */
+#define MODE_REPLACE 0x01 /* in: match and replace */
+#define MODE_SEARCH 0x02 /* in: search only, return match index or -1 */
+#define GET_MODE(f) ((f) & 0x03)
+#define FORCE_FLAT 0x04 /* in: force flat (non-regexp) string match */
+#define KEEP_REGEXP 0x08 /* inout: keep GlobData.regexp alive for caller
+ of match_or_replace; if set on input
+ but clear on output, regexp ownership
+ does not pass to caller */
+#define GLOBAL_REGEXP 0x10 /* out: regexp had the 'g' flag */
+
+static JSBool
+match_or_replace(JSContext *cx,
+ JSBool (*glob)(JSContext *cx, jsint count, GlobData *data),
+ void (*destroy)(JSContext *cx, GlobData *data),
+ GlobData *data, uintN argc, jsval *vp)
+{
+ JSString *str, *src, *opt;
+ JSObject *reobj;
+ JSRegExp *re;
+ size_t index, length;
+ JSBool ok, test;
+ jsint count;
+
+ NORMALIZE_THIS(cx, vp, str);
+ data->str = str;
+
+ if (argc != 0 && VALUE_IS_REGEXP(cx, vp[2])) {
+ reobj = JSVAL_TO_OBJECT(vp[2]);
+ re = (JSRegExp *) JS_GetPrivate(cx, reobj);
+ } else {
+ src = ArgToRootedString(cx, argc, vp, 0);
+ if (!src)
+ return JS_FALSE;
+ if (data->optarg < argc) {
+ opt = js_ValueToString(cx, vp[2 + data->optarg]);
+ if (!opt)
+ return JS_FALSE;
+ } else {
+ opt = NULL;
+ }
+ re = js_NewRegExpOpt(cx, src, opt, (data->flags & FORCE_FLAT) != 0);
+ if (!re)
+ return JS_FALSE;
+ reobj = NULL;
+ }
+ /* From here on, all control flow must reach the matching DROP. */
+ data->regexp = re;
+ HOLD_REGEXP(cx, re);
+
+ if (re->flags & JSREG_GLOB)
+ data->flags |= GLOBAL_REGEXP;
+ index = 0;
+ if (GET_MODE(data->flags) == MODE_SEARCH) {
+ ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, vp);
+ if (ok) {
+ *vp = (*vp == JSVAL_TRUE)
+ ? INT_TO_JSVAL(cx->regExpStatics.leftContext.length)
+ : INT_TO_JSVAL(-1);
+ }
+ } else if (data->flags & GLOBAL_REGEXP) {
+ if (reobj) {
+ /* Set the lastIndex property's reserved slot to 0. */
+ ok = js_SetLastIndex(cx, reobj, 0);
+ } else {
+ ok = JS_TRUE;
+ }
+ if (ok) {
+ length = JSSTRING_LENGTH(str);
+ for (count = 0; index <= length; count++) {
+ ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, vp);
+ if (!ok || *vp != JSVAL_TRUE)
+ break;
+ ok = glob(cx, count, data);
+ if (!ok)
+ break;
+ if (cx->regExpStatics.lastMatch.length == 0) {
+ if (index == length)
+ break;
+ index++;
+ }
+ }
+ if (!ok && destroy)
+ destroy(cx, data);
+ }
+ } else {
+ if (GET_MODE(data->flags) == MODE_REPLACE) {
+ test = JS_TRUE;
+ } else {
+ /*
+ * MODE_MATCH implies str_match is being called from a script or a
+ * scripted function. If the caller cares only about testing null
+ * vs. non-null return value, optimize away the array object that
+ * would normally be returned in *vp.
+ *
+ * Assume a full array result is required, then prove otherwise.
+ */
+ test = JS_FALSE;
+ if (data->pc && (*data->pc == JSOP_CALL || *data->pc == JSOP_NEW)) {
+ JS_ASSERT(js_CodeSpec[*data->pc].length == 3);
+ switch (data->pc[3]) {
+ case JSOP_POP:
+ case JSOP_IFEQ:
+ case JSOP_IFNE:
+ case JSOP_IFEQX:
+ case JSOP_IFNEX:
+ test = JS_TRUE;
+ break;
+ default:;
+ }
+ }
+ }
+ ok = js_ExecuteRegExp(cx, re, str, &index, test, vp);
+ }
+
+ DROP_REGEXP(cx, re);
+ if (reobj) {
+ /* Tell our caller that it doesn't need to destroy data->regexp. */
+ data->flags &= ~KEEP_REGEXP;
+ } else if (!ok || !(data->flags & KEEP_REGEXP)) {
+ /* Caller didn't want to keep data->regexp, so null and destroy it. */
+ data->regexp = NULL;
+ js_DestroyRegExp(cx, re);
+ }
+
+ return ok;
+}
+
+typedef struct MatchData {
+ GlobData base;
+ jsval *arrayval; /* NB: local root pointer */
+} MatchData;
+
+static JSBool
+match_glob(JSContext *cx, jsint count, GlobData *data)
+{
+ MatchData *mdata;
+ JSObject *arrayobj;
+ JSSubString *matchsub;
+ JSString *matchstr;
+ jsval v;
+
+ mdata = (MatchData *)data;
+ arrayobj = JSVAL_TO_OBJECT(*mdata->arrayval);
+ if (!arrayobj) {
+ arrayobj = js_ConstructObject(cx, &js_ArrayClass, NULL, NULL, 0, NULL);
+ if (!arrayobj)
+ return JS_FALSE;
+ *mdata->arrayval = OBJECT_TO_JSVAL(arrayobj);
+ }
+ matchsub = &cx->regExpStatics.lastMatch;
+ matchstr = js_NewStringCopyN(cx, matchsub->chars, matchsub->length);
+ if (!matchstr)
+ return JS_FALSE;
+ v = STRING_TO_JSVAL(matchstr);
+ JS_ASSERT(count <= JSVAL_INT_MAX);
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
+ return OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(count), &v);
+}
+
+JSBool
+js_StringMatchHelper(JSContext *cx, uintN argc, jsval *vp, jsbytecode *pc)
+{
+ JSTempValueRooter tvr;
+ MatchData mdata;
+ JSBool ok;
+
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ mdata.base.pc = pc;
+ mdata.base.flags = MODE_MATCH;
+ mdata.base.optarg = 1;
+ mdata.arrayval = &tvr.u.value;
+ ok = match_or_replace(cx, match_glob, NULL, &mdata.base, argc, vp);
+ if (ok && !JSVAL_IS_NULL(*mdata.arrayval))
+ *vp = *mdata.arrayval;
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSBool
+str_match(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSStackFrame *fp;
+
+ for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
+ JS_ASSERT(!fp->script);
+ return js_StringMatchHelper(cx, argc, vp, fp ? fp->regs->pc : NULL);
+}
+
+#ifdef JS_TRACER
+static JSObject* FASTCALL
+String_p_match(JSContext* cx, JSString* str, jsbytecode *pc, JSObject* regexp)
+{
+ jsval vp[3] = { JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
+ if (!js_StringMatchHelper(cx, 1, vp, pc))
+ return (JSObject*) JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ JS_ASSERT(JSVAL_IS_NULL(vp[0]) ||
+ (!JSVAL_IS_PRIMITIVE(vp[0]) && OBJ_IS_ARRAY(cx, JSVAL_TO_OBJECT(vp[0]))));
+ return JSVAL_TO_OBJECT(vp[0]);
+}
+
+static JSObject* FASTCALL
+String_p_match_obj(JSContext* cx, JSObject* str, jsbytecode *pc, JSObject* regexp)
+{
+ jsval vp[3] = { JSVAL_NULL, OBJECT_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
+ if (!js_StringMatchHelper(cx, 1, vp, pc))
+ return (JSObject*) JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ JS_ASSERT(JSVAL_IS_NULL(vp[0]) ||
+ (!JSVAL_IS_PRIMITIVE(vp[0]) && OBJ_IS_ARRAY(cx, JSVAL_TO_OBJECT(vp[0]))));
+ return JSVAL_TO_OBJECT(vp[0]);
+}
+#endif
+
+static JSBool
+str_search(JSContext *cx, uintN argc, jsval *vp)
+{
+ GlobData data;
+
+ data.flags = MODE_SEARCH;
+ data.optarg = 1;
+ return match_or_replace(cx, NULL, NULL, &data, argc, vp);
+}
+
+typedef struct ReplaceData {
+ GlobData base; /* base struct state */
+ JSObject *lambda; /* replacement function object or null */
+ JSString *repstr; /* replacement string */
+ jschar *dollar; /* null or pointer to first $ in repstr */
+ jschar *dollarEnd; /* limit pointer for js_strchr_limit */
+ jschar *chars; /* result chars, null initially */
+ size_t length; /* result length, 0 initially */
+ jsint index; /* index in result of next replacement */
+ jsint leftIndex; /* left context index in base.str->chars */
+ JSSubString dollarStr; /* for "$$" interpret_dollar result */
+} ReplaceData;
+
+static JSSubString *
+interpret_dollar(JSContext *cx, jschar *dp, jschar *ep, ReplaceData *rdata,
+ size_t *skip)
+{
+ JSRegExpStatics *res;
+ jschar dc, *cp;
+ uintN num, tmp;
+
+ JS_ASSERT(*dp == '$');
+
+ /* If there is only a dollar, bail now */
+ if (dp + 1 >= ep)
+ return NULL;
+
+ /* Interpret all Perl match-induced dollar variables. */
+ res = &cx->regExpStatics;
+ dc = dp[1];
+ if (JS7_ISDEC(dc)) {
+ /* ECMA-262 Edition 3: 1-9 or 01-99 */
+ num = JS7_UNDEC(dc);
+ if (num > res->parenCount)
+ return NULL;
+
+ cp = dp + 2;
+ if (cp < ep && (dc = *cp, JS7_ISDEC(dc))) {
+ tmp = 10 * num + JS7_UNDEC(dc);
+ if (tmp <= res->parenCount) {
+ cp++;
+ num = tmp;
+ }
+ }
+ if (num == 0)
+ return NULL;
+
+ /* Adjust num from 1 $n-origin to 0 array-index-origin. */
+ num--;
+ *skip = cp - dp;
+ return REGEXP_PAREN_SUBSTRING(res, num);
+ }
+
+ *skip = 2;
+ switch (dc) {
+ case '$':
+ rdata->dollarStr.chars = dp;
+ rdata->dollarStr.length = 1;
+ return &rdata->dollarStr;
+ case '&':
+ return &res->lastMatch;
+ case '+':
+ return &res->lastParen;
+ case '`':
+ return &res->leftContext;
+ case '\'':
+ return &res->rightContext;
+ }
+ return NULL;
+}
+
+static JSBool
+find_replen(JSContext *cx, ReplaceData *rdata, size_t *sizep)
+{
+ JSString *repstr;
+ size_t replen, skip;
+ jschar *dp, *ep;
+ JSSubString *sub;
+ JSObject *lambda;
+
+ lambda = rdata->lambda;
+ if (lambda) {
+ uintN argc, i, j, m, n, p;
+ jsval *invokevp, *sp;
+ void *mark;
+ JSBool ok;
+
+ /*
+ * Save the regExpStatics from the current regexp, since they may be
+ * clobbered by a RegExp usage in the lambda function. Note that all
+ * members of JSRegExpStatics are JSSubStrings, so not GC roots, save
+ * input, which is rooted otherwise via vp[1] in str_replace.
+ */
+ JSRegExpStatics save = cx->regExpStatics;
+ JSBool freeMoreParens = JS_FALSE;
+
+ /*
+ * In the lambda case, not only do we find the replacement string's
+ * length, we compute repstr and return it via rdata for use within
+ * do_replace. The lambda is called with arguments ($&, $1, $2, ...,
+ * index, input), i.e., all the properties of a regexp match array.
+ * For $&, etc., we must create string jsvals from cx->regExpStatics.
+ * We grab up stack space to keep the newborn strings GC-rooted.
+ */
+ p = rdata->base.regexp->parenCount;
+ argc = 1 + p + 2;
+ invokevp = js_AllocStack(cx, 2 + argc, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ /* Push lambda and its 'this' parameter. */
+ sp = invokevp;
+ *sp++ = OBJECT_TO_JSVAL(lambda);
+ *sp++ = OBJECT_TO_JSVAL(OBJ_GET_PARENT(cx, lambda));
+
+#define PUSH_REGEXP_STATIC(sub) \
+ JS_BEGIN_MACRO \
+ JSString *str = js_NewStringCopyN(cx, \
+ cx->regExpStatics.sub.chars, \
+ cx->regExpStatics.sub.length); \
+ if (!str) { \
+ ok = JS_FALSE; \
+ goto lambda_out; \
+ } \
+ *sp++ = STRING_TO_JSVAL(str); \
+ JS_END_MACRO
+
+ /* Push $&, $1, $2, ... */
+ PUSH_REGEXP_STATIC(lastMatch);
+ i = 0;
+ m = cx->regExpStatics.parenCount;
+ n = JS_MIN(m, 9);
+ for (j = 0; i < n; i++, j++)
+ PUSH_REGEXP_STATIC(parens[j]);
+ for (j = 0; i < m; i++, j++)
+ PUSH_REGEXP_STATIC(moreParens[j]);
+
+ /*
+ * We need to clear moreParens in the top-of-stack cx->regExpStatics
+ * to it won't be possibly realloc'ed, leaving the bottom-of-stack
+ * moreParens pointing to freed memory.
+ */
+ cx->regExpStatics.moreParens = NULL;
+ freeMoreParens = JS_TRUE;
+
+#undef PUSH_REGEXP_STATIC
+
+ /* Make sure to push undefined for any unmatched parens. */
+ for (; i < p; i++)
+ *sp++ = JSVAL_VOID;
+
+ /* Push match index and input string. */
+ *sp++ = INT_TO_JSVAL((jsint)cx->regExpStatics.leftContext.length);
+ *sp++ = STRING_TO_JSVAL(rdata->base.str);
+
+ ok = js_Invoke(cx, argc, invokevp, 0);
+ if (ok) {
+ /*
+ * NB: we count on the newborn string root to hold any string
+ * created by this js_ValueToString that would otherwise be GC-
+ * able, until we use rdata->repstr in do_replace.
+ */
+ repstr = js_ValueToString(cx, *invokevp);
+ if (!repstr) {
+ ok = JS_FALSE;
+ } else {
+ rdata->repstr = repstr;
+ *sizep = JSSTRING_LENGTH(repstr);
+ }
+ }
+
+ lambda_out:
+ js_FreeStack(cx, mark);
+ if (freeMoreParens)
+ JS_free(cx, cx->regExpStatics.moreParens);
+ cx->regExpStatics = save;
+ return ok;
+ }
+
+ repstr = rdata->repstr;
+ replen = JSSTRING_LENGTH(repstr);
+ for (dp = rdata->dollar, ep = rdata->dollarEnd; dp;
+ dp = js_strchr_limit(dp, '$', ep)) {
+ sub = interpret_dollar(cx, dp, ep, rdata, &skip);
+ if (sub) {
+ replen += sub->length - skip;
+ dp += skip;
+ }
+ else
+ dp++;
+ }
+ *sizep = replen;
+ return JS_TRUE;
+}
+
+static void
+do_replace(JSContext *cx, ReplaceData *rdata, jschar *chars)
+{
+ JSString *repstr;
+ jschar *bp, *cp, *dp, *ep;
+ size_t len, skip;
+ JSSubString *sub;
+
+ repstr = rdata->repstr;
+ bp = cp = JSSTRING_CHARS(repstr);
+ for (dp = rdata->dollar, ep = rdata->dollarEnd; dp;
+ dp = js_strchr_limit(dp, '$', ep)) {
+ len = dp - cp;
+ js_strncpy(chars, cp, len);
+ chars += len;
+ cp = dp;
+ sub = interpret_dollar(cx, dp, ep, rdata, &skip);
+ if (sub) {
+ len = sub->length;
+ js_strncpy(chars, sub->chars, len);
+ chars += len;
+ cp += skip;
+ dp += skip;
+ } else {
+ dp++;
+ }
+ }
+ js_strncpy(chars, cp, JSSTRING_LENGTH(repstr) - (cp - bp));
+}
+
+static void
+replace_destroy(JSContext *cx, GlobData *data)
+{
+ ReplaceData *rdata;
+
+ rdata = (ReplaceData *)data;
+ JS_free(cx, rdata->chars);
+ rdata->chars = NULL;
+}
+
+static JSBool
+replace_glob(JSContext *cx, jsint count, GlobData *data)
+{
+ ReplaceData *rdata;
+ JSString *str;
+ size_t leftoff, leftlen, replen, growth;
+ const jschar *left;
+ jschar *chars;
+
+ rdata = (ReplaceData *)data;
+ str = data->str;
+ leftoff = rdata->leftIndex;
+ left = JSSTRING_CHARS(str) + leftoff;
+ leftlen = cx->regExpStatics.lastMatch.chars - left;
+ rdata->leftIndex = cx->regExpStatics.lastMatch.chars - JSSTRING_CHARS(str);
+ rdata->leftIndex += cx->regExpStatics.lastMatch.length;
+ if (!find_replen(cx, rdata, &replen))
+ return JS_FALSE;
+ growth = leftlen + replen;
+ chars = (jschar *)
+ (rdata->chars
+ ? JS_realloc(cx, rdata->chars, (rdata->length + growth + 1)
+ * sizeof(jschar))
+ : JS_malloc(cx, (growth + 1) * sizeof(jschar)));
+ if (!chars)
+ return JS_FALSE;
+ rdata->chars = chars;
+ rdata->length += growth;
+ chars += rdata->index;
+ rdata->index += growth;
+ js_strncpy(chars, left, leftlen);
+ chars += leftlen;
+ do_replace(cx, rdata, chars);
+ return JS_TRUE;
+}
+
+static JSBool
+str_replace(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *lambda;
+ JSString *repstr;
+
+ if (argc >= 2 && JS_TypeOfValue(cx, vp[3]) == JSTYPE_FUNCTION) {
+ lambda = JSVAL_TO_OBJECT(vp[3]);
+ repstr = NULL;
+ } else {
+ lambda = NULL;
+ repstr = ArgToRootedString(cx, argc, vp, 1);
+ if (!repstr)
+ return JS_FALSE;
+ }
+
+ return js_StringReplaceHelper(cx, argc, lambda, repstr, vp);
+}
+
+#ifdef JS_TRACER
+static JSString* FASTCALL
+String_p_replace_str(JSContext* cx, JSString* str, JSObject* regexp, JSString* repstr)
+{
+ jsval vp[4] = {
+ JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp), STRING_TO_JSVAL(repstr)
+ };
+ if (!js_StringReplaceHelper(cx, 2, NULL, repstr, vp))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(vp[0]));
+ return JSVAL_TO_STRING(vp[0]);
+}
+
+static JSString* FASTCALL
+String_p_replace_str2(JSContext* cx, JSString* str, JSString* patstr, JSString* repstr)
+{
+ jsval vp[4] = {
+ JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(patstr), STRING_TO_JSVAL(repstr)
+ };
+ if (!js_StringReplaceHelper(cx, 2, NULL, repstr, vp))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(vp[0]));
+ return JSVAL_TO_STRING(vp[0]);
+}
+
+static JSString* FASTCALL
+String_p_replace_str3(JSContext* cx, JSString* str, JSString* patstr, JSString* repstr,
+ JSString* flagstr)
+{
+ jsval vp[5] = {
+ JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(patstr), STRING_TO_JSVAL(repstr),
+ STRING_TO_JSVAL(flagstr)
+ };
+ if (!js_StringReplaceHelper(cx, 3, NULL, repstr, vp))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(vp[0]));
+ return JSVAL_TO_STRING(vp[0]);
+}
+#endif
+
+JSBool
+js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda,
+ JSString *repstr, jsval *vp)
+{
+ ReplaceData rdata;
+ JSBool ok;
+ size_t leftlen, rightlen, length;
+ jschar *chars;
+ JSString *str;
+
+ /*
+ * For ECMA Edition 3, the first argument is to be converted to a string
+ * to match in a "flat" sense (without regular expression metachars having
+ * special meanings) UNLESS the first arg is a RegExp object.
+ */
+ rdata.base.flags = MODE_REPLACE | KEEP_REGEXP | FORCE_FLAT;
+ rdata.base.optarg = 2;
+
+ rdata.lambda = lambda;
+ rdata.repstr = repstr;
+ if (repstr) {
+ rdata.dollarEnd = JSSTRING_CHARS(repstr) + JSSTRING_LENGTH(repstr);
+ rdata.dollar = js_strchr_limit(JSSTRING_CHARS(repstr), '$',
+ rdata.dollarEnd);
+ } else {
+ rdata.dollar = rdata.dollarEnd = NULL;
+ }
+ rdata.chars = NULL;
+ rdata.length = 0;
+ rdata.index = 0;
+ rdata.leftIndex = 0;
+
+ ok = match_or_replace(cx, replace_glob, replace_destroy, &rdata.base,
+ argc, vp);
+ if (!ok)
+ return JS_FALSE;
+
+ if (!rdata.chars) {
+ if ((rdata.base.flags & GLOBAL_REGEXP) || *vp != JSVAL_TRUE) {
+ /* Didn't match even once. */
+ *vp = STRING_TO_JSVAL(rdata.base.str);
+ goto out;
+ }
+ leftlen = cx->regExpStatics.leftContext.length;
+ ok = find_replen(cx, &rdata, &length);
+ if (!ok)
+ goto out;
+ length += leftlen;
+ chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!chars) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ js_strncpy(chars, cx->regExpStatics.leftContext.chars, leftlen);
+ do_replace(cx, &rdata, chars + leftlen);
+ rdata.chars = chars;
+ rdata.length = length;
+ }
+
+ rightlen = cx->regExpStatics.rightContext.length;
+ length = rdata.length + rightlen;
+ chars = (jschar *)
+ JS_realloc(cx, rdata.chars, (length + 1) * sizeof(jschar));
+ if (!chars) {
+ JS_free(cx, rdata.chars);
+ ok = JS_FALSE;
+ goto out;
+ }
+ js_strncpy(chars + rdata.length, cx->regExpStatics.rightContext.chars,
+ rightlen);
+ chars[length] = 0;
+
+ str = js_NewString(cx, chars, length);
+ if (!str) {
+ JS_free(cx, chars);
+ ok = JS_FALSE;
+ goto out;
+ }
+ *vp = STRING_TO_JSVAL(str);
+
+out:
+ /* If KEEP_REGEXP is still set, it's our job to destroy regexp now. */
+ if (rdata.base.flags & KEEP_REGEXP)
+ js_DestroyRegExp(cx, rdata.base.regexp);
+ return ok;
+}
+
+/*
+ * Subroutine used by str_split to find the next split point in str, starting
+ * at offset *ip and looking either for the separator substring given by sep, or
+ * for the next re match. In the re case, return the matched separator in *sep,
+ * and the possibly updated offset in *ip.
+ *
+ * Return -2 on error, -1 on end of string, >= 0 for a valid index of the next
+ * separator occurrence if found, or str->length if no separator is found.
+ */
+static jsint
+find_split(JSContext *cx, JSString *str, JSRegExp *re, jsint *ip,
+ JSSubString *sep)
+{
+ jsint i, j, k;
+ size_t length;
+ jschar *chars;
+
+ /*
+ * Stop if past end of string. If at end of string, we will compare the
+ * null char stored there (by js_NewString*) to sep->chars[j] in the while
+ * loop at the end of this function, so that
+ *
+ * "ab,".split(',') => ["ab", ""]
+ *
+ * and the resulting array converts back to the string "ab," for symmetry.
+ * However, we ape Perl and do this only if there is a sufficiently large
+ * limit argument (see str_split).
+ */
+ i = *ip;
+ length = JSSTRING_LENGTH(str);
+ if ((size_t)i > length)
+ return -1;
+
+ chars = JSSTRING_CHARS(str);
+
+ /*
+ * Match a regular expression against the separator at or above index i.
+ * Call js_ExecuteRegExp with true for the test argument. On successful
+ * match, get the separator from cx->regExpStatics.lastMatch.
+ */
+ if (re) {
+ size_t index;
+ jsval rval;
+
+ again:
+ /* JS1.2 deviated from Perl by never matching at end of string. */
+ index = (size_t)i;
+ if (!js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, &rval))
+ return -2;
+ if (rval != JSVAL_TRUE) {
+ /* Mismatch: ensure our caller advances i past end of string. */
+ sep->length = 1;
+ return length;
+ }
+ i = (jsint)index;
+ *sep = cx->regExpStatics.lastMatch;
+ if (sep->length == 0) {
+ /*
+ * Empty string match: never split on an empty match at the start
+ * of a find_split cycle. Same rule as for an empty global match
+ * in match_or_replace.
+ */
+ if (i == *ip) {
+ /*
+ * "Bump-along" to avoid sticking at an empty match, but don't
+ * bump past end of string -- our caller must do that by adding
+ * sep->length to our return value.
+ */
+ if ((size_t)i == length)
+ return -1;
+ i++;
+ goto again;
+ }
+ if ((size_t)i == length) {
+ /*
+ * If there was a trivial zero-length match at the end of the
+ * split, then we shouldn't output the matched string at the end
+ * of the split array. See ECMA-262 Ed. 3, 15.5.4.14, Step 15.
+ */
+ sep->chars = NULL;
+ }
+ }
+ JS_ASSERT((size_t)i >= sep->length);
+ return i - sep->length;
+ }
+
+ /*
+ * Special case: if sep is the empty string, split str into one character
+ * substrings. Let our caller worry about whether to split once at end of
+ * string into an empty substring.
+ */
+ if (sep->length == 0)
+ return ((size_t)i == length) ? -1 : i + 1;
+
+ /*
+ * Now that we know sep is non-empty, search starting at i in str for an
+ * occurrence of all of sep's chars. If we find them, return the index of
+ * the first separator char. Otherwise, return length.
+ */
+ j = 0;
+ while ((size_t)(k = i + j) < length) {
+ if (chars[k] == sep->chars[j]) {
+ if ((size_t)++j == sep->length)
+ return i;
+ } else {
+ i++;
+ j = 0;
+ }
+ }
+ return k;
+}
+
+static JSBool
+str_split(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str, *sub;
+ JSObject *arrayobj;
+ jsval v;
+ JSBool ok, limited;
+ JSRegExp *re;
+ JSSubString *sep, tmp;
+ jsdouble d;
+ jsint i, j;
+ uint32 len, limit;
+
+ NORMALIZE_THIS(cx, vp, str);
+
+ arrayobj = js_ConstructObject(cx, &js_ArrayClass, NULL, NULL, 0, NULL);
+ if (!arrayobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(arrayobj);
+
+ if (argc == 0) {
+ v = STRING_TO_JSVAL(str);
+ ok = OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(0), &v);
+ } else {
+ if (VALUE_IS_REGEXP(cx, vp[2])) {
+ re = (JSRegExp *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(vp[2]));
+ sep = &tmp;
+
+ /* Set a magic value so we can detect a successful re match. */
+ sep->chars = NULL;
+ sep->length = 0;
+ } else {
+ JSString *str2 = js_ValueToString(cx, vp[2]);
+ if (!str2)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(str2);
+
+ /*
+ * Point sep at a local copy of str2's header because find_split
+ * will modify sep->length.
+ */
+ JSSTRING_CHARS_AND_LENGTH(str2, tmp.chars, tmp.length);
+ sep = &tmp;
+ re = NULL;
+ }
+
+ /* Use the second argument as the split limit, if given. */
+ limited = (argc > 1) && !JSVAL_IS_VOID(vp[3]);
+ limit = 0; /* Avoid warning. */
+ if (limited) {
+ d = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+
+ /* Clamp limit between 0 and 1 + string length. */
+ limit = js_DoubleToECMAUint32(d);
+ if (limit > JSSTRING_LENGTH(str))
+ limit = 1 + JSSTRING_LENGTH(str);
+ }
+
+ len = i = 0;
+ while ((j = find_split(cx, str, re, &i, sep)) >= 0) {
+ if (limited && len >= limit)
+ break;
+ sub = js_NewDependentString(cx, str, i, (size_t)(j - i));
+ if (!sub)
+ return JS_FALSE;
+ v = STRING_TO_JSVAL(sub);
+ if (!JS_SetElement(cx, arrayobj, len, &v))
+ return JS_FALSE;
+ len++;
+
+ /*
+ * Imitate perl's feature of including parenthesized substrings
+ * that matched part of the delimiter in the new array, after the
+ * split substring that was delimited.
+ */
+ if (re && sep->chars) {
+ uintN num;
+ JSSubString *parsub;
+
+ for (num = 0; num < cx->regExpStatics.parenCount; num++) {
+ if (limited && len >= limit)
+ break;
+ parsub = REGEXP_PAREN_SUBSTRING(&cx->regExpStatics, num);
+ sub = js_NewStringCopyN(cx, parsub->chars, parsub->length);
+ if (!sub)
+ return JS_FALSE;
+ v = STRING_TO_JSVAL(sub);
+ if (!JS_SetElement(cx, arrayobj, len, &v))
+ return JS_FALSE;
+ len++;
+ }
+ sep->chars = NULL;
+ }
+ i = j + sep->length;
+ }
+ ok = (j != -2);
+ }
+ return ok;
+}
+
+#ifdef JS_TRACER
+static JSObject* FASTCALL
+String_p_split(JSContext* cx, JSString* str, JSString* sepstr)
+{
+ // FIXME: Avoid building and then parsing this array.
+ jsval vp[4] = { JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(sepstr), JSVAL_VOID };
+ if (!str_split(cx, 2, vp))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_OBJECT(vp[0]));
+ return JSVAL_TO_OBJECT(vp[0]);
+}
+#endif
+
+#if JS_HAS_PERL_SUBSTR
+static JSBool
+str_substr(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ jsdouble d;
+ jsdouble length, begin, end;
+
+ NORMALIZE_THIS(cx, vp, str);
+ if (argc != 0) {
+ d = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ length = JSSTRING_LENGTH(str);
+ begin = js_DoubleToInteger(d);
+ if (begin < 0) {
+ begin += length;
+ if (begin < 0)
+ begin = 0;
+ } else if (begin > length) {
+ begin = length;
+ }
+
+ if (argc == 1) {
+ end = length;
+ } else {
+ d = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ end = js_DoubleToInteger(d);
+ if (end < 0)
+ end = 0;
+ end += begin;
+ if (end > length)
+ end = length;
+ }
+
+ str = js_NewDependentString(cx, str,
+ (size_t)begin,
+ (size_t)(end - begin));
+ if (!str)
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif /* JS_HAS_PERL_SUBSTR */
+
+/*
+ * Python-esque sequence operations.
+ */
+static JSBool
+str_concat(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str, *str2;
+ jsval *argv;
+ uintN i;
+
+ NORMALIZE_THIS(cx, vp, str);
+
+ for (i = 0, argv = vp + 2; i < argc; i++) {
+ str2 = js_ValueToString(cx, argv[i]);
+ if (!str2)
+ return JS_FALSE;
+ argv[i] = STRING_TO_JSVAL(str2);
+
+ str = js_ConcatStrings(cx, str, str2);
+ if (!str)
+ return JS_FALSE;
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static JSString* FASTCALL
+String_p_concat_1int(JSContext* cx, JSString* str, int32 i)
+{
+ // FIXME: should be able to use stack buffer and avoid istr...
+ JSString* istr = js_NumberToString(cx, i);
+ if (!istr)
+ return NULL;
+ return js_ConcatStrings(cx, str, istr);
+}
+
+static JSString* FASTCALL
+String_p_concat_2str(JSContext* cx, JSString* str, JSString* a, JSString* b)
+{
+ str = js_ConcatStrings(cx, str, a);
+ if (str)
+ return js_ConcatStrings(cx, str, b);
+ return NULL;
+}
+
+static JSString* FASTCALL
+String_p_concat_3str(JSContext* cx, JSString* str, JSString* a, JSString* b, JSString* c)
+{
+ str = js_ConcatStrings(cx, str, a);
+ if (str) {
+ str = js_ConcatStrings(cx, str, b);
+ if (str)
+ return js_ConcatStrings(cx, str, c);
+ }
+ return NULL;
+}
+#endif
+
+static JSBool
+str_slice(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval t, v;
+ JSString *str;
+
+ t = vp[1];
+ v = vp[2];
+ if (argc == 1 && JSVAL_IS_STRING(t) && JSVAL_IS_INT(v)) {
+ size_t begin, end, length;
+
+ str = JSVAL_TO_STRING(t);
+ begin = JSVAL_TO_INT(v);
+ end = JSSTRING_LENGTH(str);
+ if (begin <= end) {
+ length = end - begin;
+ if (length == 0) {
+ str = cx->runtime->emptyString;
+ } else {
+ str = (length == 1)
+ ? js_GetUnitString(cx, str, begin)
+ : js_NewDependentString(cx, str, begin, length);
+ if (!str)
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+ }
+ }
+
+ NORMALIZE_THIS(cx, vp, str);
+
+ if (argc != 0) {
+ double begin, end, length;
+
+ begin = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ begin = js_DoubleToInteger(begin);
+ length = JSSTRING_LENGTH(str);
+ if (begin < 0) {
+ begin += length;
+ if (begin < 0)
+ begin = 0;
+ } else if (begin > length) {
+ begin = length;
+ }
+
+ if (argc == 1) {
+ end = length;
+ } else {
+ end = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ end = js_DoubleToInteger(end);
+ if (end < 0) {
+ end += length;
+ if (end < 0)
+ end = 0;
+ } else if (end > length) {
+ end = length;
+ }
+ if (end < begin)
+ end = begin;
+ }
+
+ str = js_NewDependentString(cx, str,
+ (size_t)begin,
+ (size_t)(end - begin));
+ if (!str)
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#if JS_HAS_STR_HTML_HELPERS
+/*
+ * HTML composition aids.
+ */
+static JSBool
+tagify(JSContext *cx, const char *begin, JSString *param, const char *end,
+ jsval *vp)
+{
+ JSString *str;
+ jschar *tagbuf;
+ size_t beglen, endlen, parlen, taglen;
+ size_t i, j;
+
+ NORMALIZE_THIS(cx, vp, str);
+
+ if (!end)
+ end = begin;
+
+ beglen = strlen(begin);
+ taglen = 1 + beglen + 1; /* '<begin' + '>' */
+ parlen = 0; /* Avoid warning. */
+ if (param) {
+ parlen = JSSTRING_LENGTH(param);
+ taglen += 2 + parlen + 1; /* '="param"' */
+ }
+ endlen = strlen(end);
+ taglen += JSSTRING_LENGTH(str) + 2 + endlen + 1; /* 'str</end>' */
+
+ if (taglen >= ~(size_t)0 / sizeof(jschar)) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+
+ tagbuf = (jschar *) JS_malloc(cx, (taglen + 1) * sizeof(jschar));
+ if (!tagbuf)
+ return JS_FALSE;
+
+ j = 0;
+ tagbuf[j++] = '<';
+ for (i = 0; i < beglen; i++)
+ tagbuf[j++] = (jschar)begin[i];
+ if (param) {
+ tagbuf[j++] = '=';
+ tagbuf[j++] = '"';
+ js_strncpy(&tagbuf[j], JSSTRING_CHARS(param), parlen);
+ j += parlen;
+ tagbuf[j++] = '"';
+ }
+ tagbuf[j++] = '>';
+ js_strncpy(&tagbuf[j], JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
+ j += JSSTRING_LENGTH(str);
+ tagbuf[j++] = '<';
+ tagbuf[j++] = '/';
+ for (i = 0; i < endlen; i++)
+ tagbuf[j++] = (jschar)end[i];
+ tagbuf[j++] = '>';
+ JS_ASSERT(j == taglen);
+ tagbuf[j] = 0;
+
+ str = js_NewString(cx, tagbuf, taglen);
+ if (!str) {
+ free((char *)tagbuf);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+tagify_value(JSContext *cx, uintN argc, jsval *vp,
+ const char *begin, const char *end)
+{
+ JSString *param;
+
+ param = ArgToRootedString(cx, argc, vp, 0);
+ if (!param)
+ return JS_FALSE;
+ return tagify(cx, begin, param, end, vp);
+}
+
+static JSBool
+str_bold(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "b", NULL, NULL, vp);
+}
+
+static JSBool
+str_italics(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "i", NULL, NULL, vp);
+}
+
+static JSBool
+str_fixed(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "tt", NULL, NULL, vp);
+}
+
+static JSBool
+str_fontsize(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify_value(cx, argc, vp, "font size", "font");
+}
+
+static JSBool
+str_fontcolor(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify_value(cx, argc, vp, "font color", "font");
+}
+
+static JSBool
+str_link(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify_value(cx, argc, vp, "a href", "a");
+}
+
+static JSBool
+str_anchor(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify_value(cx, argc, vp, "a name", "a");
+}
+
+static JSBool
+str_strike(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "strike", NULL, NULL, vp);
+}
+
+static JSBool
+str_small(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "small", NULL, NULL, vp);
+}
+
+static JSBool
+str_big(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "big", NULL, NULL, vp);
+}
+
+static JSBool
+str_blink(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "blink", NULL, NULL, vp);
+}
+
+static JSBool
+str_sup(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "sup", NULL, NULL, vp);
+}
+
+static JSBool
+str_sub(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "sub", NULL, NULL, vp);
+}
+#endif /* JS_HAS_STR_HTML_HELPERS */
+
+#ifdef JS_TRACER
+JSString* FASTCALL
+js_String_getelem(JSContext* cx, JSString* str, int32 i)
+{
+ if ((size_t)i >= JSSTRING_LENGTH(str))
+ return NULL;
+ return js_GetUnitString(cx, str, (size_t)i);
+}
+#endif
+
+JS_DEFINE_CALLINFO_2(extern, BOOL, js_EqualStrings, STRING, STRING, 1, 1)
+JS_DEFINE_CALLINFO_2(extern, INT32, js_CompareStrings, STRING, STRING, 1, 1)
+
+JS_DEFINE_TRCINFO_1(str_toString,
+ (2, (extern, STRING_FAIL, String_p_toString, CONTEXT, THIS, 1, 1)))
+JS_DEFINE_TRCINFO_2(str_substring,
+ (4, (static, STRING_FAIL, String_p_substring, CONTEXT, THIS_STRING, INT32, INT32, 1, 1)),
+ (3, (static, STRING_FAIL, String_p_substring_1, CONTEXT, THIS_STRING, INT32, 1, 1)))
+JS_DEFINE_TRCINFO_1(str_charAt,
+ (3, (extern, STRING_FAIL, js_String_getelem, CONTEXT, THIS_STRING, INT32, 1, 1)))
+JS_DEFINE_TRCINFO_1(str_charCodeAt,
+ (2, (extern, INT32_FAIL, js_String_p_charCodeAt, THIS_STRING, INT32, 1, 1)))
+JS_DEFINE_TRCINFO_4(str_concat,
+ (3, (static, STRING_FAIL, String_p_concat_1int, CONTEXT, THIS_STRING, INT32, 1, 1)),
+ (3, (extern, STRING_FAIL, js_ConcatStrings, CONTEXT, THIS_STRING, STRING, 1, 1)),
+ (4, (static, STRING_FAIL, String_p_concat_2str, CONTEXT, THIS_STRING, STRING, STRING, 1, 1)),
+ (5, (static, STRING_FAIL, String_p_concat_3str, CONTEXT, THIS_STRING, STRING, STRING, STRING, 1, 1)))
+JS_DEFINE_TRCINFO_2(str_match,
+ (4, (static, OBJECT_FAIL_VOID, String_p_match, CONTEXT, THIS_STRING, PC, REGEXP, 1, 1)),
+ (4, (static, OBJECT_FAIL_VOID, String_p_match_obj, CONTEXT, THIS, PC, REGEXP, 1, 1)))
+JS_DEFINE_TRCINFO_3(str_replace,
+ (4, (static, STRING_FAIL, String_p_replace_str, CONTEXT, THIS_STRING, REGEXP, STRING, 1, 1)),
+ (4, (static, STRING_FAIL, String_p_replace_str2, CONTEXT, THIS_STRING, STRING, STRING, 1, 1)),
+ (5, (static, STRING_FAIL, String_p_replace_str3, CONTEXT, THIS_STRING, STRING, STRING, STRING, 1, 1)))
+JS_DEFINE_TRCINFO_1(str_split,
+ (3, (static, OBJECT_FAIL_NULL, String_p_split, CONTEXT, THIS_STRING, STRING, 0, 0)))
+JS_DEFINE_TRCINFO_1(str_toLowerCase,
+ (2, (extern, STRING_FAIL, js_toLowerCase, CONTEXT, THIS_STRING, 1, 1)))
+JS_DEFINE_TRCINFO_1(str_toUpperCase,
+ (2, (extern, STRING_FAIL, js_toUpperCase, CONTEXT, THIS_STRING, 1, 1)))
+
+#define GENERIC JSFUN_GENERIC_NATIVE
+#define PRIMITIVE JSFUN_THISP_PRIMITIVE
+#define GENERIC_PRIMITIVE (GENERIC | PRIMITIVE)
+
+static JSFunctionSpec string_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN("quote", str_quote, 0,GENERIC_PRIMITIVE),
+ JS_FN(js_toSource_str, str_toSource, 0,JSFUN_THISP_STRING),
+#endif
+
+ /* Java-like methods. */
+ JS_TN(js_toString_str, str_toString, 0,JSFUN_THISP_STRING, str_toString_trcinfo),
+ JS_FN(js_valueOf_str, str_toString, 0,JSFUN_THISP_STRING),
+ JS_FN(js_toJSON_str, str_toString, 0,JSFUN_THISP_STRING),
+ JS_TN("substring", str_substring, 2,GENERIC_PRIMITIVE, str_substring_trcinfo),
+ JS_TN("toLowerCase", str_toLowerCase, 0,GENERIC_PRIMITIVE, str_toLowerCase_trcinfo),
+ JS_TN("toUpperCase", str_toUpperCase, 0,GENERIC_PRIMITIVE, str_toUpperCase_trcinfo),
+ JS_TN("charAt", str_charAt, 1,GENERIC_PRIMITIVE, str_charAt_trcinfo),
+ JS_TN("charCodeAt", str_charCodeAt, 1,GENERIC_PRIMITIVE, str_charCodeAt_trcinfo),
+ JS_FN("indexOf", str_indexOf, 1,GENERIC_PRIMITIVE),
+ JS_FN("lastIndexOf", str_lastIndexOf, 1,GENERIC_PRIMITIVE),
+ JS_FN("trim", str_trim, 0,GENERIC_PRIMITIVE),
+ JS_FN("trimLeft", str_trimLeft, 0,GENERIC_PRIMITIVE),
+ JS_FN("trimRight", str_trimRight, 0,GENERIC_PRIMITIVE),
+ JS_FN("toLocaleLowerCase", str_toLocaleLowerCase, 0,GENERIC_PRIMITIVE),
+ JS_FN("toLocaleUpperCase", str_toLocaleUpperCase, 0,GENERIC_PRIMITIVE),
+ JS_FN("localeCompare", str_localeCompare, 1,GENERIC_PRIMITIVE),
+
+ /* Perl-ish methods (search is actually Python-esque). */
+ JS_TN("match", str_match, 1,GENERIC_PRIMITIVE, str_match_trcinfo),
+ JS_FN("search", str_search, 1,GENERIC_PRIMITIVE),
+ JS_TN("replace", str_replace, 2,GENERIC_PRIMITIVE, str_replace_trcinfo),
+ JS_TN("split", str_split, 2,GENERIC_PRIMITIVE, str_split_trcinfo),
+#if JS_HAS_PERL_SUBSTR
+ JS_FN("substr", str_substr, 2,GENERIC_PRIMITIVE),
+#endif
+
+ /* Python-esque sequence methods. */
+ JS_TN("concat", str_concat, 1,GENERIC_PRIMITIVE, str_concat_trcinfo),
+ JS_FN("slice", str_slice, 2,GENERIC_PRIMITIVE),
+
+ /* HTML string methods. */
+#if JS_HAS_STR_HTML_HELPERS
+ JS_FN("bold", str_bold, 0,PRIMITIVE),
+ JS_FN("italics", str_italics, 0,PRIMITIVE),
+ JS_FN("fixed", str_fixed, 0,PRIMITIVE),
+ JS_FN("fontsize", str_fontsize, 1,PRIMITIVE),
+ JS_FN("fontcolor", str_fontcolor, 1,PRIMITIVE),
+ JS_FN("link", str_link, 1,PRIMITIVE),
+ JS_FN("anchor", str_anchor, 1,PRIMITIVE),
+ JS_FN("strike", str_strike, 0,PRIMITIVE),
+ JS_FN("small", str_small, 0,PRIMITIVE),
+ JS_FN("big", str_big, 0,PRIMITIVE),
+ JS_FN("blink", str_blink, 0,PRIMITIVE),
+ JS_FN("sup", str_sup, 0,PRIMITIVE),
+ JS_FN("sub", str_sub, 0,PRIMITIVE),
+#endif
+
+ JS_FS_END
+};
+
+static JSBool
+String(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+
+ if (argc > 0) {
+ str = js_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(str);
+ } else {
+ str = cx->runtime->emptyString;
+ }
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+ }
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, STRING_TO_JSVAL(str));
+ return JS_TRUE;
+}
+
+static JSBool
+str_fromCharCode(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv;
+ uintN i;
+ uint16 code;
+ jschar *chars;
+ JSString *str;
+
+ argv = vp + 2;
+ JS_ASSERT(argc < ARRAY_INIT_LIMIT);
+ if (argc == 1 &&
+ (code = js_ValueToUint16(cx, &argv[0])) < UNIT_STRING_LIMIT) {
+ str = js_GetUnitStringForChar(cx, code);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+ }
+ chars = (jschar *) JS_malloc(cx, (argc + 1) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+ for (i = 0; i < argc; i++) {
+ code = js_ValueToUint16(cx, &argv[i]);
+ if (JSVAL_IS_NULL(argv[i])) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ chars[i] = (jschar)code;
+ }
+ chars[i] = 0;
+ str = js_NewString(cx, chars, argc);
+ if (!str) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static JSString* FASTCALL
+String_fromCharCode(JSContext* cx, int32 i)
+{
+ JS_ASSERT(JS_ON_TRACE(cx));
+ jschar c = (jschar)i;
+ if (c < UNIT_STRING_LIMIT)
+ return js_GetUnitStringForChar(cx, c);
+ return js_NewStringCopyN(cx, &c, 1);
+}
+#endif
+
+JS_DEFINE_TRCINFO_1(str_fromCharCode,
+ (2, (static, STRING_FAIL, String_fromCharCode, CONTEXT, INT32, 1, 1)))
+
+static JSFunctionSpec string_static_methods[] = {
+ JS_TN("fromCharCode", str_fromCharCode, 1, 0, str_fromCharCode_trcinfo),
+ JS_FS_END
+};
+
+static JSHashNumber
+js_hash_string_pointer(const void *key)
+{
+ return (JSHashNumber)JS_PTR_TO_UINT32(key) >> JSVAL_TAGBITS;
+}
+
+JSBool
+js_InitRuntimeStringState(JSContext *cx)
+{
+ JSRuntime *rt;
+
+ rt = cx->runtime;
+ rt->emptyString = ATOM_TO_STRING(rt->atomState.emptyAtom);
+ return JS_TRUE;
+}
+
+JSBool
+js_InitDeflatedStringCache(JSRuntime *rt)
+{
+ JSHashTable *cache;
+
+ /* Initialize string cache */
+ JS_ASSERT(!rt->deflatedStringCache);
+ cache = JS_NewHashTable(8, js_hash_string_pointer,
+ JS_CompareValues, JS_CompareValues,
+ NULL, NULL);
+ if (!cache)
+ return JS_FALSE;
+ rt->deflatedStringCache = cache;
+
+#ifdef JS_THREADSAFE
+ JS_ASSERT(!rt->deflatedStringCacheLock);
+ rt->deflatedStringCacheLock = JS_NEW_LOCK();
+ if (!rt->deflatedStringCacheLock)
+ return JS_FALSE;
+#endif
+ return JS_TRUE;
+}
+
+#define UNIT_STRING_SPACE(sp) ((jschar *) ((sp) + UNIT_STRING_LIMIT))
+#define UNIT_STRING_SPACE_RT(rt) UNIT_STRING_SPACE((rt)->unitStrings)
+
+#define IN_UNIT_STRING_SPACE(sp,cp) \
+ ((size_t)((cp) - UNIT_STRING_SPACE(sp)) < 2 * UNIT_STRING_LIMIT)
+#define IN_UNIT_STRING_SPACE_RT(rt,cp) \
+ IN_UNIT_STRING_SPACE((rt)->unitStrings, cp)
+
+JSString *
+js_GetUnitStringForChar(JSContext *cx, jschar c)
+{
+ jschar *cp, i;
+ JSRuntime *rt;
+ JSString **sp;
+
+ JS_ASSERT(c < UNIT_STRING_LIMIT);
+ rt = cx->runtime;
+ if (!rt->unitStrings) {
+ sp = (JSString **) calloc(UNIT_STRING_LIMIT * sizeof(JSString *) +
+ UNIT_STRING_LIMIT * 2 * sizeof(jschar),
+ 1);
+ if (!sp) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ cp = UNIT_STRING_SPACE(sp);
+ for (i = 0; i < UNIT_STRING_LIMIT; i++) {
+ *cp = i;
+ cp += 2;
+ }
+ JS_LOCK_GC(rt);
+ if (!rt->unitStrings) {
+ rt->unitStrings = sp;
+ JS_UNLOCK_GC(rt);
+ } else {
+ JS_UNLOCK_GC(rt);
+ free(sp);
+ }
+ }
+ if (!rt->unitStrings[c]) {
+ JSString *str;
+
+ cp = UNIT_STRING_SPACE_RT(rt);
+ str = js_NewString(cx, cp + 2 * c, 1);
+ if (!str)
+ return NULL;
+ JS_LOCK_GC(rt);
+ if (!rt->unitStrings[c])
+ rt->unitStrings[c] = str;
+ JS_UNLOCK_GC(rt);
+ }
+ return rt->unitStrings[c];
+}
+
+JSString *
+js_GetUnitString(JSContext *cx, JSString *str, size_t index)
+{
+ jschar c;
+
+ JS_ASSERT(index < JSSTRING_LENGTH(str));
+ c = JSSTRING_CHARS(str)[index];
+ if (c >= UNIT_STRING_LIMIT)
+ return js_NewDependentString(cx, str, index, 1);
+ return js_GetUnitStringForChar(cx, c);
+}
+
+void
+js_FinishUnitStrings(JSRuntime *rt)
+{
+ free(rt->unitStrings);
+ rt->unitStrings = NULL;
+}
+
+void
+js_FinishRuntimeStringState(JSContext *cx)
+{
+ cx->runtime->emptyString = NULL;
+}
+
+void
+js_FinishDeflatedStringCache(JSRuntime *rt)
+{
+ if (rt->deflatedStringCache) {
+ JS_HashTableDestroy(rt->deflatedStringCache);
+ rt->deflatedStringCache = NULL;
+ }
+#ifdef JS_THREADSAFE
+ if (rt->deflatedStringCacheLock) {
+ JS_DESTROY_LOCK(rt->deflatedStringCacheLock);
+ rt->deflatedStringCacheLock = NULL;
+ }
+#endif
+}
+
+JSObject *
+js_InitStringClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ /* Define the escape, unescape functions in the global object. */
+ if (!JS_DefineFunctions(cx, obj, string_functions))
+ return NULL;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_StringClass, String, 1,
+ string_props, string_methods,
+ NULL, string_static_methods);
+ if (!proto)
+ return NULL;
+ STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE,
+ STRING_TO_JSVAL(cx->runtime->emptyString));
+ return proto;
+}
+
+JSString *
+js_NewString(JSContext *cx, jschar *chars, size_t length)
+{
+ JSString *str;
+
+ if (length > JSSTRING_LENGTH_MASK) {
+ js_ReportAllocationOverflow(cx);
+ return NULL;
+ }
+
+ str = (JSString *) js_NewGCThing(cx, GCX_STRING, sizeof(JSString));
+ if (!str)
+ return NULL;
+ JSFLATSTR_INIT(str, chars, length);
+#ifdef DEBUG
+ {
+ JSRuntime *rt = cx->runtime;
+ JS_RUNTIME_METER(rt, liveStrings);
+ JS_RUNTIME_METER(rt, totalStrings);
+ JS_LOCK_RUNTIME_VOID(rt,
+ (rt->lengthSum += (double)length,
+ rt->lengthSquaredSum += (double)length * (double)length));
+ }
+#endif
+ return str;
+}
+
+JSString *
+js_NewDependentString(JSContext *cx, JSString *base, size_t start,
+ size_t length)
+{
+ JSString *ds;
+
+ if (length == 0)
+ return cx->runtime->emptyString;
+
+ if (start == 0 && length == JSSTRING_LENGTH(base))
+ return base;
+
+ if (start > JSSTRDEP_START_MASK ||
+ (start != 0 && length > JSSTRDEP_LENGTH_MASK)) {
+ return js_NewStringCopyN(cx, JSSTRING_CHARS(base) + start, length);
+ }
+
+ ds = (JSString *)js_NewGCThing(cx, GCX_STRING, sizeof(JSString));
+ if (!ds)
+ return NULL;
+ if (start == 0)
+ JSPREFIX_INIT(ds, base, length);
+ else
+ JSSTRDEP_INIT(ds, base, start, length);
+#ifdef DEBUG
+ {
+ JSRuntime *rt = cx->runtime;
+ JS_RUNTIME_METER(rt, liveDependentStrings);
+ JS_RUNTIME_METER(rt, totalDependentStrings);
+ JS_RUNTIME_METER(rt, liveStrings);
+ JS_RUNTIME_METER(rt, totalStrings);
+ JS_LOCK_RUNTIME_VOID(rt,
+ (rt->strdepLengthSum += (double)length,
+ rt->strdepLengthSquaredSum += (double)length * (double)length));
+ JS_LOCK_RUNTIME_VOID(rt,
+ (rt->lengthSum += (double)length,
+ rt->lengthSquaredSum += (double)length * (double)length));
+ }
+#endif
+ return ds;
+}
+
+#ifdef DEBUG
+#include <math.h>
+
+void printJSStringStats(JSRuntime *rt)
+{
+ double mean, sigma;
+
+ mean = JS_MeanAndStdDev(rt->totalStrings, rt->lengthSum,
+ rt->lengthSquaredSum, &sigma);
+
+ fprintf(stderr, "%lu total strings, mean length %g (sigma %g)\n",
+ (unsigned long)rt->totalStrings, mean, sigma);
+
+ mean = JS_MeanAndStdDev(rt->totalDependentStrings, rt->strdepLengthSum,
+ rt->strdepLengthSquaredSum, &sigma);
+
+ fprintf(stderr, "%lu total dependent strings, mean length %g (sigma %g)\n",
+ (unsigned long)rt->totalDependentStrings, mean, sigma);
+}
+#endif
+
+JSString *
+js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n)
+{
+ jschar *news;
+ JSString *str;
+
+ news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+ if (!news)
+ return NULL;
+ js_strncpy(news, s, n);
+ news[n] = 0;
+ str = js_NewString(cx, news, n);
+ if (!str)
+ JS_free(cx, news);
+ return str;
+}
+
+JSString *
+js_NewStringCopyZ(JSContext *cx, const jschar *s)
+{
+ size_t n, m;
+ jschar *news;
+ JSString *str;
+
+ n = js_strlen(s);
+ m = (n + 1) * sizeof(jschar);
+ news = (jschar *) JS_malloc(cx, m);
+ if (!news)
+ return NULL;
+ memcpy(news, s, m);
+ str = js_NewString(cx, news, n);
+ if (!str)
+ JS_free(cx, news);
+ return str;
+}
+
+void
+js_PurgeDeflatedStringCache(JSRuntime *rt, JSString *str)
+{
+ JSHashNumber hash;
+ JSHashEntry *he, **hep;
+
+ hash = js_hash_string_pointer(str);
+ JS_ACQUIRE_LOCK(rt->deflatedStringCacheLock);
+ hep = JS_HashTableRawLookup(rt->deflatedStringCache, hash, str);
+ he = *hep;
+ if (he) {
+#ifdef DEBUG
+ rt->deflatedStringCacheBytes -= JSSTRING_LENGTH(str);
+#endif
+ free(he->value);
+ JS_HashTableRawRemove(rt->deflatedStringCache, hep, he);
+ }
+ JS_RELEASE_LOCK(rt->deflatedStringCacheLock);
+}
+
+static JSStringFinalizeOp str_finalizers[GCX_NTYPES - GCX_EXTERNAL_STRING] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+intN
+js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
+ JSStringFinalizeOp newop)
+{
+ uintN i;
+
+ for (i = 0; i != JS_ARRAY_LENGTH(str_finalizers); i++) {
+ if (str_finalizers[i] == oldop) {
+ str_finalizers[i] = newop;
+ return (intN) i;
+ }
+ }
+ return -1;
+}
+
+/*
+ * cx is NULL when we are called from js_FinishAtomState to force the
+ * finalization of the permanently interned strings.
+ */
+void
+js_FinalizeStringRT(JSRuntime *rt, JSString *str, intN type, JSContext *cx)
+{
+ jschar *chars;
+ JSBool valid;
+ JSStringFinalizeOp finalizer;
+
+ JS_RUNTIME_UNMETER(rt, liveStrings);
+ if (JSSTRING_IS_DEPENDENT(str)) {
+ /* A dependent string can not be external and must be valid. */
+ JS_ASSERT(type < 0);
+ JS_ASSERT(JSSTRDEP_BASE(str));
+ JS_RUNTIME_UNMETER(rt, liveDependentStrings);
+ valid = JS_TRUE;
+ } else {
+ /* A stillborn string has null chars, so is not valid. */
+ chars = JSFLATSTR_CHARS(str);
+ valid = (chars != NULL);
+ if (valid) {
+ if (IN_UNIT_STRING_SPACE_RT(rt, chars)) {
+ JS_ASSERT(rt->unitStrings[*chars] == str);
+ JS_ASSERT(type < 0);
+ rt->unitStrings[*chars] = NULL;
+ } else if (type < 0) {
+ free(chars);
+ } else {
+ JS_ASSERT((uintN) type < JS_ARRAY_LENGTH(str_finalizers));
+ finalizer = str_finalizers[type];
+ if (finalizer) {
+ /*
+ * Assume that the finalizer for the permanently interned
+ * string knows how to deal with null context.
+ */
+ finalizer(cx, str);
+ }
+ }
+ }
+ }
+ if (valid)
+ js_PurgeDeflatedStringCache(rt, str);
+}
+
+JS_FRIEND_API(const char *)
+js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun)
+{
+ JSString *str;
+
+ str = v2sfun(cx, v);
+ if (!str)
+ return NULL;
+ str = js_QuoteString(cx, str, 0);
+ if (!str)
+ return NULL;
+ return js_GetStringBytes(cx, str);
+}
+
+JS_FRIEND_API(JSString *)
+js_ValueToString(JSContext *cx, jsval v)
+{
+ JSObject *obj;
+ JSString *str;
+
+ if (JSVAL_IS_OBJECT(v)) {
+ obj = JSVAL_TO_OBJECT(v);
+ if (!obj)
+ return ATOM_TO_STRING(cx->runtime->atomState.nullAtom);
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v))
+ return NULL;
+ }
+ if (JSVAL_IS_STRING(v)) {
+ str = JSVAL_TO_STRING(v);
+ } else if (JSVAL_IS_INT(v)) {
+ str = js_NumberToString(cx, JSVAL_TO_INT(v));
+ } else if (JSVAL_IS_DOUBLE(v)) {
+ str = js_NumberToString(cx, *JSVAL_TO_DOUBLE(v));
+ } else if (JSVAL_IS_BOOLEAN(v)) {
+ str = js_BooleanToString(cx, JSVAL_TO_BOOLEAN(v));
+ } else {
+ str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
+ }
+ return str;
+}
+
+JS_FRIEND_API(JSString *)
+js_ValueToSource(JSContext *cx, jsval v)
+{
+ JSTempValueRooter tvr;
+ JSString *str;
+
+ if (JSVAL_IS_VOID(v))
+ return ATOM_TO_STRING(cx->runtime->atomState.void0Atom);
+ if (JSVAL_IS_STRING(v))
+ return js_QuoteString(cx, JSVAL_TO_STRING(v), '"');
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ /* Special case to preserve negative zero, _contra_ toString. */
+ if (JSVAL_IS_DOUBLE(v) && JSDOUBLE_IS_NEGZERO(*JSVAL_TO_DOUBLE(v))) {
+ /* NB: _ucNstr rather than _ucstr to indicate non-terminated. */
+ static const jschar js_negzero_ucNstr[] = {'-', '0'};
+
+ return js_NewStringCopyN(cx, js_negzero_ucNstr, 2);
+ }
+ return js_ValueToString(cx, v);
+ }
+
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ if (!js_TryMethod(cx, JSVAL_TO_OBJECT(v),
+ cx->runtime->atomState.toSourceAtom,
+ 0, NULL, &tvr.u.value)) {
+ str = NULL;
+ } else {
+ str = js_ValueToString(cx, tvr.u.value);
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return str;
+}
+
+/*
+ * str is not necessarily a GC thing here.
+ */
+uint32
+js_HashString(JSString *str)
+{
+ const jschar *s;
+ size_t n;
+ uint32 h;
+
+ JSSTRING_CHARS_AND_LENGTH(str, s, n);
+ for (h = 0; n; s++, n--)
+ h = JS_ROTATE_LEFT32(h, 4) ^ *s;
+ return h;
+}
+
+/*
+ * str is not necessarily a GC thing here.
+ */
+JSBool JS_FASTCALL
+js_EqualStrings(JSString *str1, JSString *str2)
+{
+ size_t n;
+ const jschar *s1, *s2;
+
+ JS_ASSERT(str1);
+ JS_ASSERT(str2);
+
+ /* Fast case: pointer equality could be a quick win. */
+ if (str1 == str2)
+ return JS_TRUE;
+
+ n = JSSTRING_LENGTH(str1);
+ if (n != JSSTRING_LENGTH(str2))
+ return JS_FALSE;
+
+ if (n == 0)
+ return JS_TRUE;
+
+ s1 = JSSTRING_CHARS(str1), s2 = JSSTRING_CHARS(str2);
+ do {
+ if (*s1 != *s2)
+ return JS_FALSE;
+ ++s1, ++s2;
+ } while (--n != 0);
+
+ return JS_TRUE;
+}
+
+int32 JS_FASTCALL
+js_CompareStrings(JSString *str1, JSString *str2)
+{
+ size_t l1, l2, n, i;
+ const jschar *s1, *s2;
+ intN cmp;
+
+ JS_ASSERT(str1);
+ JS_ASSERT(str2);
+
+ /* Fast case: pointer equality could be a quick win. */
+ if (str1 == str2)
+ return 0;
+
+ JSSTRING_CHARS_AND_LENGTH(str1, s1, l1);
+ JSSTRING_CHARS_AND_LENGTH(str2, s2, l2);
+ n = JS_MIN(l1, l2);
+ for (i = 0; i < n; i++) {
+ cmp = s1[i] - s2[i];
+ if (cmp != 0)
+ return cmp;
+ }
+ return (intN)(l1 - l2);
+}
+
+size_t
+js_strlen(const jschar *s)
+{
+ const jschar *t;
+
+ for (t = s; *t != 0; t++)
+ continue;
+ return (size_t)(t - s);
+}
+
+jschar *
+js_strchr(const jschar *s, jschar c)
+{
+ while (*s != 0) {
+ if (*s == c)
+ return (jschar *)s;
+ s++;
+ }
+ return NULL;
+}
+
+jschar *
+js_strchr_limit(const jschar *s, jschar c, const jschar *limit)
+{
+ while (s < limit) {
+ if (*s == c)
+ return (jschar *)s;
+ s++;
+ }
+ return NULL;
+}
+
+const jschar *
+js_SkipWhiteSpace(const jschar *s, const jschar *end)
+{
+ JS_ASSERT(s <= end);
+ while (s != end && JS_ISSPACE(*s))
+ s++;
+ return s;
+}
+
+jschar *
+js_InflateString(JSContext *cx, const char *bytes, size_t *lengthp)
+{
+ size_t nbytes, nchars, i;
+ jschar *chars;
+#ifdef DEBUG
+ JSBool ok;
+#endif
+
+ nbytes = *lengthp;
+ if (js_CStringsAreUTF8) {
+ if (!js_InflateStringToBuffer(cx, bytes, nbytes, NULL, &nchars))
+ goto bad;
+ chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof (jschar));
+ if (!chars)
+ goto bad;
+#ifdef DEBUG
+ ok =
+#endif
+ js_InflateStringToBuffer(cx, bytes, nbytes, chars, &nchars);
+ JS_ASSERT(ok);
+ } else {
+ nchars = nbytes;
+ chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar));
+ if (!chars)
+ goto bad;
+ for (i = 0; i < nchars; i++)
+ chars[i] = (unsigned char) bytes[i];
+ }
+ *lengthp = nchars;
+ chars[nchars] = 0;
+ return chars;
+
+ bad:
+ /*
+ * For compatibility with callers of JS_DecodeBytes we must zero lengthp
+ * on errors.
+ */
+ *lengthp = 0;
+ return NULL;
+}
+
+/*
+ * May be called with null cx by js_GetStringBytes, see below.
+ */
+char *
+js_DeflateString(JSContext *cx, const jschar *chars, size_t nchars)
+{
+ size_t nbytes, i;
+ char *bytes;
+#ifdef DEBUG
+ JSBool ok;
+#endif
+
+ if (js_CStringsAreUTF8) {
+ nbytes = js_GetDeflatedStringLength(cx, chars, nchars);
+ if (nbytes == (size_t) -1)
+ return NULL;
+ bytes = (char *) (cx ? JS_malloc(cx, nbytes + 1) : malloc(nbytes + 1));
+ if (!bytes)
+ return NULL;
+#ifdef DEBUG
+ ok =
+#endif
+ js_DeflateStringToBuffer(cx, chars, nchars, bytes, &nbytes);
+ JS_ASSERT(ok);
+ } else {
+ nbytes = nchars;
+ bytes = (char *) (cx ? JS_malloc(cx, nbytes + 1) : malloc(nbytes + 1));
+ if (!bytes)
+ return NULL;
+ for (i = 0; i < nbytes; i++)
+ bytes[i] = (char) chars[i];
+ }
+ bytes[nbytes] = 0;
+ return bytes;
+}
+
+/*
+ * May be called with null cx through js_GetStringBytes, see below.
+ */
+size_t
+js_GetDeflatedStringLength(JSContext *cx, const jschar *chars, size_t nchars)
+{
+ size_t nbytes;
+ const jschar *end;
+ uintN c, c2;
+ char buffer[10];
+
+ if (!js_CStringsAreUTF8)
+ return nchars;
+
+ nbytes = nchars;
+ for (end = chars + nchars; chars != end; chars++) {
+ c = *chars;
+ if (c < 0x80)
+ continue;
+ if (0xD800 <= c && c <= 0xDFFF) {
+ /* Surrogate pair. */
+ chars++;
+ if (c >= 0xDC00 || chars == end)
+ goto bad_surrogate;
+ c2 = *chars;
+ if (c2 < 0xDC00 || c2 > 0xDFFF)
+ goto bad_surrogate;
+ c = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
+ }
+ c >>= 11;
+ nbytes++;
+ while (c) {
+ c >>= 5;
+ nbytes++;
+ }
+ }
+ return nbytes;
+
+ bad_surrogate:
+ if (cx) {
+ JS_snprintf(buffer, 10, "0x%x", c);
+ JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
+ NULL, JSMSG_BAD_SURROGATE_CHAR, buffer);
+ }
+ return (size_t) -1;
+}
+
+JSBool
+js_DeflateStringToBuffer(JSContext *cx, const jschar *src, size_t srclen,
+ char *dst, size_t *dstlenp)
+{
+ size_t dstlen, i, origDstlen, utf8Len;
+ jschar c, c2;
+ uint32 v;
+ uint8 utf8buf[6];
+
+ dstlen = *dstlenp;
+ if (!js_CStringsAreUTF8) {
+ if (srclen > dstlen) {
+ for (i = 0; i < dstlen; i++)
+ dst[i] = (char) src[i];
+ if (cx) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BUFFER_TOO_SMALL);
+ }
+ return JS_FALSE;
+ }
+ for (i = 0; i < srclen; i++)
+ dst[i] = (char) src[i];
+ *dstlenp = srclen;
+ return JS_TRUE;
+ }
+
+ origDstlen = dstlen;
+ while (srclen) {
+ c = *src++;
+ srclen--;
+ if ((c >= 0xDC00) && (c <= 0xDFFF))
+ goto badSurrogate;
+ if (c < 0xD800 || c > 0xDBFF) {
+ v = c;
+ } else {
+ if (srclen < 1)
+ goto badSurrogate;
+ c2 = *src;
+ if ((c2 < 0xDC00) || (c2 > 0xDFFF))
+ goto badSurrogate;
+ src++;
+ srclen--;
+ v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
+ }
+ if (v < 0x0080) {
+ /* no encoding necessary - performance hack */
+ if (dstlen == 0)
+ goto bufferTooSmall;
+ *dst++ = (char) v;
+ utf8Len = 1;
+ } else {
+ utf8Len = js_OneUcs4ToUtf8Char(utf8buf, v);
+ if (utf8Len > dstlen)
+ goto bufferTooSmall;
+ for (i = 0; i < utf8Len; i++)
+ *dst++ = (char) utf8buf[i];
+ }
+ dstlen -= utf8Len;
+ }
+ *dstlenp = (origDstlen - dstlen);
+ return JS_TRUE;
+
+badSurrogate:
+ *dstlenp = (origDstlen - dstlen);
+ /* Delegate error reporting to the measurement function. */
+ if (cx)
+ js_GetDeflatedStringLength(cx, src - 1, srclen + 1);
+ return JS_FALSE;
+
+bufferTooSmall:
+ *dstlenp = (origDstlen - dstlen);
+ if (cx) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BUFFER_TOO_SMALL);
+ }
+ return JS_FALSE;
+}
+
+JSBool
+js_InflateStringToBuffer(JSContext *cx, const char *src, size_t srclen,
+ jschar *dst, size_t *dstlenp)
+{
+ size_t dstlen, i, origDstlen, offset, j, n;
+ uint32 v;
+
+ if (!js_CStringsAreUTF8) {
+ if (dst) {
+ dstlen = *dstlenp;
+ if (srclen > dstlen) {
+ for (i = 0; i < dstlen; i++)
+ dst[i] = (unsigned char) src[i];
+ if (cx) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BUFFER_TOO_SMALL);
+ }
+ return JS_FALSE;
+ }
+ for (i = 0; i < srclen; i++)
+ dst[i] = (unsigned char) src[i];
+ }
+ *dstlenp = srclen;
+ return JS_TRUE;
+ }
+
+ dstlen = dst ? *dstlenp : (size_t) -1;
+ origDstlen = dstlen;
+ offset = 0;
+
+ while (srclen) {
+ v = (uint8) *src;
+ n = 1;
+ if (v & 0x80) {
+ while (v & (0x80 >> n))
+ n++;
+ if (n > srclen)
+ goto bufferTooSmall;
+ if (n == 1 || n > 6)
+ goto badCharacter;
+ for (j = 1; j < n; j++) {
+ if ((src[j] & 0xC0) != 0x80)
+ goto badCharacter;
+ }
+ v = Utf8ToOneUcs4Char((uint8 *)src, n);
+ if (v >= 0x10000) {
+ v -= 0x10000;
+ if (v > 0xFFFFF || dstlen < 2) {
+ *dstlenp = (origDstlen - dstlen);
+ if (cx) {
+ char buffer[10];
+ JS_snprintf(buffer, 10, "0x%x", v + 0x10000);
+ JS_ReportErrorFlagsAndNumber(cx,
+ JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_UTF8_CHAR_TOO_LARGE,
+ buffer);
+ }
+ return JS_FALSE;
+ }
+ if (dstlen < 2)
+ goto bufferTooSmall;
+ if (dst) {
+ *dst++ = (jschar)((v >> 10) + 0xD800);
+ v = (jschar)((v & 0x3FF) + 0xDC00);
+ }
+ dstlen--;
+ }
+ }
+ if (!dstlen)
+ goto bufferTooSmall;
+ if (dst)
+ *dst++ = (jschar) v;
+ dstlen--;
+ offset += n;
+ src += n;
+ srclen -= n;
+ }
+ *dstlenp = (origDstlen - dstlen);
+ return JS_TRUE;
+
+badCharacter:
+ *dstlenp = (origDstlen - dstlen);
+ if (cx) {
+ char buffer[10];
+ JS_snprintf(buffer, 10, "%d", offset);
+ JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_MALFORMED_UTF8_CHAR,
+ buffer);
+ }
+ return JS_FALSE;
+
+bufferTooSmall:
+ *dstlenp = (origDstlen - dstlen);
+ if (cx) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BUFFER_TOO_SMALL);
+ }
+ return JS_FALSE;
+}
+
+JSBool
+js_SetStringBytes(JSContext *cx, JSString *str, char *bytes, size_t length)
+{
+ JSRuntime *rt;
+ JSHashTable *cache;
+ JSBool ok;
+ JSHashNumber hash;
+ JSHashEntry **hep;
+
+ rt = cx->runtime;
+ JS_ACQUIRE_LOCK(rt->deflatedStringCacheLock);
+
+ cache = rt->deflatedStringCache;
+ hash = js_hash_string_pointer(str);
+ hep = JS_HashTableRawLookup(cache, hash, str);
+ JS_ASSERT(*hep == NULL);
+ ok = JS_HashTableRawAdd(cache, hep, hash, str, bytes) != NULL;
+#ifdef DEBUG
+ if (ok)
+ rt->deflatedStringCacheBytes += length;
+#endif
+
+ JS_RELEASE_LOCK(rt->deflatedStringCacheLock);
+ return ok;
+}
+
+const char *
+js_GetStringBytes(JSContext *cx, JSString *str)
+{
+ JSRuntime *rt;
+ JSHashTable *cache;
+ char *bytes;
+ JSHashNumber hash;
+ JSHashEntry *he, **hep;
+
+ if (cx) {
+ rt = cx->runtime;
+ } else {
+ /* JS_GetStringBytes calls us with null cx. */
+ rt = js_GetGCStringRuntime(str);
+ }
+
+#ifdef JS_THREADSAFE
+ if (!rt->deflatedStringCacheLock) {
+ /*
+ * Called from last GC (see js_DestroyContext), after runtime string
+ * state has been finalized. We have no choice but to leak here.
+ */
+ return js_DeflateString(NULL, JSSTRING_CHARS(str),
+ JSSTRING_LENGTH(str));
+ }
+#endif
+
+ JS_ACQUIRE_LOCK(rt->deflatedStringCacheLock);
+
+ cache = rt->deflatedStringCache;
+ hash = js_hash_string_pointer(str);
+ hep = JS_HashTableRawLookup(cache, hash, str);
+ he = *hep;
+ if (he) {
+ bytes = (char *) he->value;
+
+ /* Try to catch failure to JS_ShutDown between runtime epochs. */
+ if (!js_CStringsAreUTF8) {
+ JS_ASSERT_IF(*bytes != (char) JSSTRING_CHARS(str)[0],
+ *bytes == '\0' && JSSTRING_LENGTH(str) == 0);
+ }
+ } else {
+ bytes = js_DeflateString(cx, JSSTRING_CHARS(str),
+ JSSTRING_LENGTH(str));
+ if (bytes) {
+ if (JS_HashTableRawAdd(cache, hep, hash, str, bytes)) {
+#ifdef DEBUG
+ rt->deflatedStringCacheBytes += JSSTRING_LENGTH(str);
+#endif
+ } else {
+ if (cx)
+ JS_free(cx, bytes);
+ else
+ free(bytes);
+ bytes = NULL;
+ }
+ }
+ }
+
+ JS_RELEASE_LOCK(rt->deflatedStringCacheLock);
+ return bytes;
+}
+
+/*
+ * From java.lang.Character.java:
+ *
+ * The character properties are currently encoded into 32 bits in the
+ * following manner:
+ *
+ * 10 bits signed offset used for converting case
+ * 1 bit if 1, adding the signed offset converts the character to
+ * lowercase
+ * 1 bit if 1, subtracting the signed offset converts the character to
+ * uppercase
+ * 1 bit if 1, character has a titlecase equivalent (possibly itself)
+ * 3 bits 0 may not be part of an identifier
+ * 1 ignorable control; may continue a Unicode identifier or JS
+ * identifier
+ * 2 may continue a JS identifier but not a Unicode identifier
+ * (unused)
+ * 3 may continue a Unicode identifier or JS identifier
+ * 4 is a JS whitespace character
+ * 5 may start or continue a JS identifier;
+ * may continue but not start a Unicode identifier (_)
+ * 6 may start or continue a JS identifier but not a Unicode
+ * identifier ($)
+ * 7 may start or continue a Unicode identifier or JS identifier
+ * Thus:
+ * 5, 6, 7 may start a JS identifier
+ * 1, 2, 3, 5, 6, 7 may continue a JS identifier
+ * 7 may start a Unicode identifier
+ * 1, 3, 5, 7 may continue a Unicode identifier
+ * 1 is ignorable within an identifier
+ * 4 is JS whitespace
+ * 2 bits 0 this character has no numeric property
+ * 1 adding the digit offset to the character code and then
+ * masking with 0x1F will produce the desired numeric value
+ * 2 this character has a "strange" numeric value
+ * 3 a JS supradecimal digit: adding the digit offset to the
+ * character code, then masking with 0x1F, then adding 10
+ * will produce the desired numeric value
+ * 5 bits digit offset
+ * 1 bit XML 1.0 name start character
+ * 1 bit XML 1.0 name character
+ * 2 bits reserved for future use
+ * 5 bits character type
+ */
+
+/* The X table has 1024 entries for a total of 1024 bytes. */
+
+const uint8 js_X[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, /* 0x0000 */
+ 8, 9, 10, 11, 12, 13, 14, 15, /* 0x0200 */
+ 16, 17, 18, 19, 20, 21, 22, 23, /* 0x0400 */
+ 24, 25, 26, 27, 28, 28, 28, 28, /* 0x0600 */
+ 28, 28, 28, 28, 29, 30, 31, 32, /* 0x0800 */
+ 33, 34, 35, 36, 37, 38, 39, 40, /* 0x0A00 */
+ 41, 42, 43, 44, 45, 46, 28, 28, /* 0x0C00 */
+ 47, 48, 49, 50, 51, 52, 53, 28, /* 0x0E00 */
+ 28, 28, 54, 55, 56, 57, 58, 59, /* 0x1000 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1200 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1400 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1600 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1800 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1A00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1C00 */
+ 60, 60, 61, 62, 63, 64, 65, 66, /* 0x1E00 */
+ 67, 68, 69, 70, 71, 72, 73, 74, /* 0x2000 */
+ 75, 75, 75, 76, 77, 78, 28, 28, /* 0x2200 */
+ 79, 80, 81, 82, 83, 83, 84, 85, /* 0x2400 */
+ 86, 85, 28, 28, 87, 88, 89, 28, /* 0x2600 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2800 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2A00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2C00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2E00 */
+ 90, 91, 92, 93, 94, 56, 95, 28, /* 0x3000 */
+ 96, 97, 98, 99, 83, 100, 83, 101, /* 0x3200 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3400 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3600 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3800 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3A00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3C00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3E00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4000 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4200 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4400 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4600 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4800 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4A00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4C00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x4E00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5A00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5C00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5E00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6A00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6C00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6E00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7A00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7C00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7E00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8A00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8C00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8E00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9A00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9C00 */
+ 56, 56, 56, 56, 56, 56, 102, 28, /* 0x9E00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA000 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA200 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA400 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA600 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA800 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xAA00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xAC00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xAE00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBA00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBC00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBE00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCA00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCC00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCE00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD400 */
+ 56, 56, 56, 56, 56, 56, 103, 28, /* 0xD600 */
+104, 104, 104, 104, 104, 104, 104, 104, /* 0xD800 */
+104, 104, 104, 104, 104, 104, 104, 104, /* 0xDA00 */
+104, 104, 104, 104, 104, 104, 104, 104, /* 0xDC00 */
+104, 104, 104, 104, 104, 104, 104, 104, /* 0xDE00 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xE000 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xE200 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xE400 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xE600 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xE800 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xEA00 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xEC00 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xEE00 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xF000 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xF200 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xF400 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xF600 */
+105, 105, 105, 105, 56, 56, 56, 56, /* 0xF800 */
+106, 28, 28, 28, 107, 108, 109, 110, /* 0xFA00 */
+ 56, 56, 56, 56, 111, 112, 113, 114, /* 0xFC00 */
+115, 116, 56, 117, 118, 119, 120, 121 /* 0xFE00 */
+};
+
+/* The Y table has 7808 entries for a total of 7808 bytes. */
+
+const uint8 js_Y[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
+ 0, 1, 1, 1, 1, 1, 0, 0, /* 0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
+ 2, 3, 3, 3, 4, 3, 3, 3, /* 0 */
+ 5, 6, 3, 7, 3, 8, 3, 3, /* 0 */
+ 9, 9, 9, 9, 9, 9, 9, 9, /* 0 */
+ 9, 9, 3, 3, 7, 7, 7, 3, /* 0 */
+ 3, 10, 10, 10, 10, 10, 10, 10, /* 1 */
+ 10, 10, 10, 10, 10, 10, 10, 10, /* 1 */
+ 10, 10, 10, 10, 10, 10, 10, 10, /* 1 */
+ 10, 10, 10, 5, 3, 6, 11, 12, /* 1 */
+ 11, 13, 13, 13, 13, 13, 13, 13, /* 1 */
+ 13, 13, 13, 13, 13, 13, 13, 13, /* 1 */
+ 13, 13, 13, 13, 13, 13, 13, 13, /* 1 */
+ 13, 13, 13, 5, 7, 6, 7, 0, /* 1 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
+ 2, 3, 4, 4, 4, 4, 15, 15, /* 2 */
+ 11, 15, 16, 5, 7, 8, 15, 11, /* 2 */
+ 15, 7, 17, 17, 11, 16, 15, 3, /* 2 */
+ 11, 18, 16, 6, 19, 19, 19, 3, /* 2 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 3 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 3 */
+ 20, 20, 20, 20, 20, 20, 20, 7, /* 3 */
+ 20, 20, 20, 20, 20, 20, 20, 16, /* 3 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 3 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 3 */
+ 21, 21, 21, 21, 21, 21, 21, 7, /* 3 */
+ 21, 21, 21, 21, 21, 21, 21, 22, /* 3 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 25, 26, 23, 24, 23, 24, 23, 24, /* 4 */
+ 16, 23, 24, 23, 24, 23, 24, 23, /* 4 */
+ 24, 23, 24, 23, 24, 23, 24, 23, /* 5 */
+ 24, 16, 23, 24, 23, 24, 23, 24, /* 5 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
+ 27, 23, 24, 23, 24, 23, 24, 28, /* 5 */
+ 16, 29, 23, 24, 23, 24, 30, 23, /* 6 */
+ 24, 31, 31, 23, 24, 16, 32, 32, /* 6 */
+ 33, 23, 24, 31, 34, 16, 35, 36, /* 6 */
+ 23, 24, 16, 16, 35, 37, 16, 38, /* 6 */
+ 23, 24, 23, 24, 23, 24, 38, 23, /* 6 */
+ 24, 39, 40, 16, 23, 24, 39, 23, /* 6 */
+ 24, 41, 41, 23, 24, 23, 24, 42, /* 6 */
+ 23, 24, 16, 40, 23, 24, 40, 40, /* 6 */
+ 40, 40, 40, 40, 43, 44, 45, 43, /* 7 */
+ 44, 45, 43, 44, 45, 23, 24, 23, /* 7 */
+ 24, 23, 24, 23, 24, 23, 24, 23, /* 7 */
+ 24, 23, 24, 23, 24, 16, 23, 24, /* 7 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 7 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 7 */
+ 16, 43, 44, 45, 23, 24, 46, 46, /* 7 */
+ 46, 46, 23, 24, 23, 24, 23, 24, /* 7 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 9 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 9 */
+ 16, 16, 16, 47, 48, 16, 49, 49, /* 9 */
+ 50, 50, 16, 51, 16, 16, 16, 16, /* 9 */
+ 49, 16, 16, 52, 16, 16, 16, 16, /* 9 */
+ 53, 54, 16, 16, 16, 16, 16, 54, /* 9 */
+ 16, 16, 55, 16, 16, 16, 16, 16, /* 9 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 9 */
+ 16, 16, 16, 56, 16, 16, 16, 16, /* 10 */
+ 56, 16, 57, 57, 16, 16, 16, 16, /* 10 */
+ 16, 16, 58, 16, 16, 16, 16, 16, /* 10 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 10 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 10 */
+ 16, 46, 46, 46, 46, 46, 46, 46, /* 10 */
+ 59, 59, 59, 59, 59, 59, 59, 59, /* 10 */
+ 59, 11, 11, 59, 59, 59, 59, 59, /* 10 */
+ 59, 59, 11, 11, 11, 11, 11, 11, /* 11 */
+ 11, 11, 11, 11, 11, 11, 11, 11, /* 11 */
+ 59, 59, 11, 11, 11, 11, 11, 11, /* 11 */
+ 11, 11, 11, 11, 11, 11, 11, 46, /* 11 */
+ 59, 59, 59, 59, 59, 11, 11, 11, /* 11 */
+ 11, 11, 46, 46, 46, 46, 46, 46, /* 11 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 11 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 11 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 46, 46, /* 13 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
+ 60, 60, 46, 46, 46, 46, 46, 46, /* 13 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
+ 46, 46, 46, 46, 3, 3, 46, 46, /* 13 */
+ 46, 46, 59, 46, 46, 46, 3, 46, /* 13 */
+ 46, 46, 46, 46, 11, 11, 61, 3, /* 14 */
+ 62, 62, 62, 46, 63, 46, 64, 64, /* 14 */
+ 16, 20, 20, 20, 20, 20, 20, 20, /* 14 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 14 */
+ 20, 20, 46, 20, 20, 20, 20, 20, /* 14 */
+ 20, 20, 20, 20, 65, 66, 66, 66, /* 14 */
+ 16, 21, 21, 21, 21, 21, 21, 21, /* 14 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 14 */
+ 21, 21, 16, 21, 21, 21, 21, 21, /* 15 */
+ 21, 21, 21, 21, 67, 68, 68, 46, /* 15 */
+ 69, 70, 38, 38, 38, 71, 72, 46, /* 15 */
+ 46, 46, 38, 46, 38, 46, 38, 46, /* 15 */
+ 38, 46, 23, 24, 23, 24, 23, 24, /* 15 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 15 */
+ 73, 74, 16, 40, 46, 46, 46, 46, /* 15 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 15 */
+ 46, 75, 75, 75, 75, 75, 75, 75, /* 16 */
+ 75, 75, 75, 75, 75, 46, 75, 75, /* 16 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 16 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 16 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 17 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 17 */
+ 46, 74, 74, 74, 74, 74, 74, 74, /* 17 */
+ 74, 74, 74, 74, 74, 46, 74, 74, /* 17 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
+ 23, 24, 15, 60, 60, 60, 60, 46, /* 18 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 40, 23, 24, 23, 24, 46, 46, 23, /* 19 */
+ 24, 46, 46, 23, 24, 46, 46, 46, /* 19 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */
+ 23, 24, 23, 24, 46, 46, 23, 24, /* 19 */
+ 23, 24, 23, 24, 23, 24, 46, 46, /* 19 */
+ 23, 24, 46, 46, 46, 46, 46, 46, /* 19 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 76, 76, 76, 76, 76, 76, 76, /* 20 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 20 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 21 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 21 */
+ 76, 76, 76, 76, 76, 76, 76, 46, /* 21 */
+ 46, 59, 3, 3, 3, 3, 3, 3, /* 21 */
+ 46, 77, 77, 77, 77, 77, 77, 77, /* 21 */
+ 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */
+ 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */
+ 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */
+ 77, 77, 77, 77, 77, 77, 77, 16, /* 22 */
+ 46, 3, 46, 46, 46, 46, 46, 46, /* 22 */
+ 46, 60, 60, 60, 60, 60, 60, 60, /* 22 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */
+ 60, 60, 46, 60, 60, 60, 60, 60, /* 22 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */
+ 60, 60, 46, 60, 60, 60, 3, 60, /* 22 */
+ 3, 60, 60, 3, 60, 46, 46, 46, /* 23 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 23 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */
+ 40, 40, 40, 46, 46, 46, 46, 46, /* 23 */
+ 40, 40, 40, 3, 3, 46, 46, 46, /* 23 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 23 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 24 */
+ 46, 46, 46, 46, 3, 46, 46, 46, /* 24 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 24 */
+ 46, 46, 46, 3, 46, 46, 46, 3, /* 24 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 24 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 24 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 24 */
+ 40, 40, 40, 46, 46, 46, 46, 46, /* 24 */
+ 59, 40, 40, 40, 40, 40, 40, 40, /* 25 */
+ 40, 40, 40, 60, 60, 60, 60, 60, /* 25 */
+ 60, 60, 60, 46, 46, 46, 46, 46, /* 25 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 25 */
+ 78, 78, 78, 78, 78, 78, 78, 78, /* 25 */
+ 78, 78, 3, 3, 3, 3, 46, 46, /* 25 */
+ 60, 40, 40, 40, 40, 40, 40, 40, /* 25 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 25 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 46, 46, 40, 40, 40, 40, 40, 46, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 27 */
+ 40, 40, 40, 40, 40, 40, 40, 46, /* 27 */
+ 40, 40, 40, 40, 3, 40, 60, 60, /* 27 */
+ 60, 60, 60, 60, 60, 79, 79, 60, /* 27 */
+ 60, 60, 60, 60, 60, 59, 59, 60, /* 27 */
+ 60, 15, 60, 60, 60, 60, 46, 46, /* 27 */
+ 9, 9, 9, 9, 9, 9, 9, 9, /* 27 */
+ 9, 9, 46, 46, 46, 46, 46, 46, /* 27 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 60, 60, 80, 46, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 46, 46, 60, 40, 80, 80, /* 29 */
+ 80, 60, 60, 60, 60, 60, 60, 60, /* 30 */
+ 60, 80, 80, 80, 80, 60, 46, 46, /* 30 */
+ 15, 60, 60, 60, 60, 46, 46, 46, /* 30 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 30 */
+ 40, 40, 60, 60, 3, 3, 81, 81, /* 30 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 30 */
+ 3, 46, 46, 46, 46, 46, 46, 46, /* 30 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 30 */
+ 46, 60, 80, 80, 46, 40, 40, 40, /* 31 */
+ 40, 40, 40, 40, 40, 46, 46, 40, /* 31 */
+ 40, 46, 46, 40, 40, 40, 40, 40, /* 31 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 31 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 31 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 31 */
+ 40, 46, 40, 46, 46, 46, 40, 40, /* 31 */
+ 40, 40, 46, 46, 60, 46, 80, 80, /* 31 */
+ 80, 60, 60, 60, 60, 46, 46, 80, /* 32 */
+ 80, 46, 46, 80, 80, 60, 46, 46, /* 32 */
+ 46, 46, 46, 46, 46, 46, 46, 80, /* 32 */
+ 46, 46, 46, 46, 40, 40, 46, 40, /* 32 */
+ 40, 40, 60, 60, 46, 46, 81, 81, /* 32 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 32 */
+ 40, 40, 4, 4, 82, 82, 82, 82, /* 32 */
+ 19, 83, 15, 46, 46, 46, 46, 46, /* 32 */
+ 46, 46, 60, 46, 46, 40, 40, 40, /* 33 */
+ 40, 40, 40, 46, 46, 46, 46, 40, /* 33 */
+ 40, 46, 46, 40, 40, 40, 40, 40, /* 33 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 33 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 33 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 33 */
+ 40, 46, 40, 40, 46, 40, 40, 46, /* 33 */
+ 40, 40, 46, 46, 60, 46, 80, 80, /* 33 */
+ 80, 60, 60, 46, 46, 46, 46, 60, /* 34 */
+ 60, 46, 46, 60, 60, 60, 46, 46, /* 34 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 34 */
+ 46, 40, 40, 40, 40, 46, 40, 46, /* 34 */
+ 46, 46, 46, 46, 46, 46, 81, 81, /* 34 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 34 */
+ 60, 60, 40, 40, 40, 46, 46, 46, /* 34 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 34 */
+ 46, 60, 60, 80, 46, 40, 40, 40, /* 35 */
+ 40, 40, 40, 40, 46, 40, 46, 40, /* 35 */
+ 40, 40, 46, 40, 40, 40, 40, 40, /* 35 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 35 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 35 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 35 */
+ 40, 46, 40, 40, 46, 40, 40, 40, /* 35 */
+ 40, 40, 46, 46, 60, 40, 80, 80, /* 35 */
+ 80, 60, 60, 60, 60, 60, 46, 60, /* 36 */
+ 60, 80, 46, 80, 80, 60, 46, 46, /* 36 */
+ 15, 46, 46, 46, 46, 46, 46, 46, /* 36 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */
+ 40, 46, 46, 46, 46, 46, 81, 81, /* 36 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 36 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */
+ 46, 60, 80, 80, 46, 40, 40, 40, /* 37 */
+ 40, 40, 40, 40, 40, 46, 46, 40, /* 37 */
+ 40, 46, 46, 40, 40, 40, 40, 40, /* 37 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 37 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 37 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 37 */
+ 40, 46, 40, 40, 46, 46, 40, 40, /* 37 */
+ 40, 40, 46, 46, 60, 40, 80, 60, /* 37 */
+ 80, 60, 60, 60, 46, 46, 46, 80, /* 38 */
+ 80, 46, 46, 80, 80, 60, 46, 46, /* 38 */
+ 46, 46, 46, 46, 46, 46, 60, 80, /* 38 */
+ 46, 46, 46, 46, 40, 40, 46, 40, /* 38 */
+ 40, 40, 46, 46, 46, 46, 81, 81, /* 38 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 38 */
+ 15, 46, 46, 46, 46, 46, 46, 46, /* 38 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 38 */
+ 46, 46, 60, 80, 46, 40, 40, 40, /* 39 */
+ 40, 40, 40, 46, 46, 46, 40, 40, /* 39 */
+ 40, 46, 40, 40, 40, 40, 46, 46, /* 39 */
+ 46, 40, 40, 46, 40, 46, 40, 40, /* 39 */
+ 46, 46, 46, 40, 40, 46, 46, 46, /* 39 */
+ 40, 40, 40, 46, 46, 46, 40, 40, /* 39 */
+ 40, 40, 40, 40, 40, 40, 46, 40, /* 39 */
+ 40, 40, 46, 46, 46, 46, 80, 80, /* 39 */
+ 60, 80, 80, 46, 46, 46, 80, 80, /* 40 */
+ 80, 46, 80, 80, 80, 60, 46, 46, /* 40 */
+ 46, 46, 46, 46, 46, 46, 46, 80, /* 40 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 40 */
+ 46, 46, 46, 46, 46, 46, 46, 81, /* 40 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 40 */
+ 84, 19, 19, 46, 46, 46, 46, 46, /* 40 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 40 */
+ 46, 80, 80, 80, 46, 40, 40, 40, /* 41 */
+ 40, 40, 40, 40, 40, 46, 40, 40, /* 41 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 41 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 41 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 41 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 41 */
+ 40, 40, 40, 40, 46, 40, 40, 40, /* 41 */
+ 40, 40, 46, 46, 46, 46, 60, 60, /* 41 */
+ 60, 80, 80, 80, 80, 46, 60, 60, /* 42 */
+ 60, 46, 60, 60, 60, 60, 46, 46, /* 42 */
+ 46, 46, 46, 46, 46, 60, 60, 46, /* 42 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */
+ 40, 40, 46, 46, 46, 46, 81, 81, /* 42 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 42 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */
+ 46, 46, 80, 80, 46, 40, 40, 40, /* 43 */
+ 40, 40, 40, 40, 40, 46, 40, 40, /* 43 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 43 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 43 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 43 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 43 */
+ 40, 40, 40, 40, 46, 40, 40, 40, /* 43 */
+ 40, 40, 46, 46, 46, 46, 80, 60, /* 43 */
+ 80, 80, 80, 80, 80, 46, 60, 80, /* 44 */
+ 80, 46, 80, 80, 60, 60, 46, 46, /* 44 */
+ 46, 46, 46, 46, 46, 80, 80, 46, /* 44 */
+ 46, 46, 46, 46, 46, 46, 40, 46, /* 44 */
+ 40, 40, 46, 46, 46, 46, 81, 81, /* 44 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 44 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 44 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 44 */
+ 46, 46, 80, 80, 46, 40, 40, 40, /* 45 */
+ 40, 40, 40, 40, 40, 46, 40, 40, /* 45 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 45 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 45 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */
+ 40, 40, 46, 46, 46, 46, 80, 80, /* 45 */
+ 80, 60, 60, 60, 46, 46, 80, 80, /* 46 */
+ 80, 46, 80, 80, 80, 60, 46, 46, /* 46 */
+ 46, 46, 46, 46, 46, 46, 46, 80, /* 46 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */
+ 40, 40, 46, 46, 46, 46, 81, 81, /* 46 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 46 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 47 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
+ 40, 40, 40, 40, 40, 40, 40, 3, /* 47 */
+ 40, 60, 40, 40, 60, 60, 60, 60, /* 47 */
+ 60, 60, 60, 46, 46, 46, 46, 4, /* 47 */
+ 40, 40, 40, 40, 40, 40, 59, 60, /* 48 */
+ 60, 60, 60, 60, 60, 60, 60, 15, /* 48 */
+ 9, 9, 9, 9, 9, 9, 9, 9, /* 48 */
+ 9, 9, 3, 3, 46, 46, 46, 46, /* 48 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
+ 46, 40, 40, 46, 40, 46, 46, 40, /* 49 */
+ 40, 46, 40, 46, 46, 40, 46, 46, /* 49 */
+ 46, 46, 46, 46, 40, 40, 40, 40, /* 49 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 49 */
+ 46, 40, 40, 40, 46, 40, 46, 40, /* 49 */
+ 46, 46, 40, 40, 46, 40, 40, 3, /* 49 */
+ 40, 60, 40, 40, 60, 60, 60, 60, /* 49 */
+ 60, 60, 46, 60, 60, 40, 46, 46, /* 49 */
+ 40, 40, 40, 40, 40, 46, 59, 46, /* 50 */
+ 60, 60, 60, 60, 60, 60, 46, 46, /* 50 */
+ 9, 9, 9, 9, 9, 9, 9, 9, /* 50 */
+ 9, 9, 46, 46, 40, 40, 46, 46, /* 50 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
+ 15, 15, 15, 15, 3, 3, 3, 3, /* 51 */
+ 3, 3, 3, 3, 3, 3, 3, 3, /* 51 */
+ 3, 3, 3, 15, 15, 15, 15, 15, /* 51 */
+ 60, 60, 15, 15, 15, 15, 15, 15, /* 51 */
+ 78, 78, 78, 78, 78, 78, 78, 78, /* 51 */
+ 78, 78, 85, 85, 85, 85, 85, 85, /* 51 */
+ 85, 85, 85, 85, 15, 60, 15, 60, /* 51 */
+ 15, 60, 5, 6, 5, 6, 80, 80, /* 51 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 52 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
+ 40, 40, 46, 46, 46, 46, 46, 46, /* 52 */
+ 46, 60, 60, 60, 60, 60, 60, 60, /* 52 */
+ 60, 60, 60, 60, 60, 60, 60, 80, /* 52 */
+ 60, 60, 60, 60, 60, 3, 60, 60, /* 53 */
+ 60, 60, 60, 60, 46, 46, 46, 46, /* 53 */
+ 60, 60, 60, 60, 60, 60, 46, 60, /* 53 */
+ 46, 60, 60, 60, 60, 60, 60, 60, /* 53 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 53 */
+ 60, 60, 60, 60, 60, 60, 46, 46, /* 53 */
+ 46, 60, 60, 60, 60, 60, 60, 60, /* 53 */
+ 46, 60, 46, 46, 46, 46, 46, 46, /* 53 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
+ 76, 76, 76, 76, 76, 76, 46, 46, /* 55 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 55 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
+ 16, 16, 16, 16, 16, 16, 16, 46, /* 55 */
+ 46, 46, 46, 3, 46, 46, 46, 46, /* 55 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 46, 46, 46, 46, 46, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 46, 46, 46, 46, 46, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 46, 46, 46, 46, 46, 46, /* 59 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 16, 16, /* 61 */
+ 16, 16, 16, 16, 46, 46, 46, 46, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 46, 46, 46, 46, 46, 46, /* 62 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */
+ 86, 86, 86, 86, 86, 86, 46, 46, /* 63 */
+ 87, 87, 87, 87, 87, 87, 46, 46, /* 63 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */
+ 86, 86, 86, 86, 86, 86, 46, 46, /* 64 */
+ 87, 87, 87, 87, 87, 87, 46, 46, /* 64 */
+ 16, 86, 16, 86, 16, 86, 16, 86, /* 64 */
+ 46, 87, 46, 87, 46, 87, 46, 87, /* 64 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 64 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 64 */
+ 88, 88, 89, 89, 89, 89, 90, 90, /* 64 */
+ 91, 91, 92, 92, 93, 93, 46, 46, /* 64 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */
+ 86, 86, 16, 94, 16, 46, 16, 16, /* 65 */
+ 87, 87, 95, 95, 96, 11, 38, 11, /* 65 */
+ 11, 11, 16, 94, 16, 46, 16, 16, /* 66 */
+ 97, 97, 97, 97, 96, 11, 11, 11, /* 66 */
+ 86, 86, 16, 16, 46, 46, 16, 16, /* 66 */
+ 87, 87, 98, 98, 46, 11, 11, 11, /* 66 */
+ 86, 86, 16, 16, 16, 99, 16, 16, /* 66 */
+ 87, 87, 100, 100, 101, 11, 11, 11, /* 66 */
+ 46, 46, 16, 94, 16, 46, 16, 16, /* 66 */
+102, 102, 103, 103, 96, 11, 11, 46, /* 66 */
+ 2, 2, 2, 2, 2, 2, 2, 2, /* 67 */
+ 2, 2, 2, 2, 104, 104, 104, 104, /* 67 */
+ 8, 8, 8, 8, 8, 8, 3, 3, /* 67 */
+ 5, 6, 5, 5, 5, 6, 5, 5, /* 67 */
+ 3, 3, 3, 3, 3, 3, 3, 3, /* 67 */
+105, 106, 104, 104, 104, 104, 104, 46, /* 67 */
+ 3, 3, 3, 3, 3, 3, 3, 3, /* 67 */
+ 3, 5, 6, 3, 3, 3, 3, 12, /* 67 */
+ 12, 3, 3, 3, 7, 5, 6, 46, /* 68 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
+ 46, 46, 104, 104, 104, 104, 104, 104, /* 68 */
+ 17, 46, 46, 46, 17, 17, 17, 17, /* 68 */
+ 17, 17, 7, 7, 7, 5, 6, 16, /* 68 */
+107, 107, 107, 107, 107, 107, 107, 107, /* 69 */
+107, 107, 7, 7, 7, 5, 6, 46, /* 69 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
+ 4, 4, 4, 4, 4, 4, 4, 4, /* 69 */
+ 4, 4, 4, 4, 46, 46, 46, 46, /* 69 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 70 */
+ 60, 60, 60, 60, 60, 79, 79, 79, /* 70 */
+ 79, 60, 46, 46, 46, 46, 46, 46, /* 70 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
+ 15, 15, 38, 15, 15, 15, 15, 38, /* 71 */
+ 15, 15, 16, 38, 38, 38, 16, 16, /* 71 */
+ 38, 38, 38, 16, 15, 38, 15, 15, /* 71 */
+ 38, 38, 38, 38, 38, 38, 15, 15, /* 71 */
+ 15, 15, 15, 15, 38, 15, 38, 15, /* 71 */
+ 38, 15, 38, 38, 38, 38, 16, 16, /* 71 */
+ 38, 38, 15, 38, 16, 40, 40, 40, /* 71 */
+ 40, 46, 46, 46, 46, 46, 46, 46, /* 71 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 72 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 72 */
+ 46, 46, 46, 19, 19, 19, 19, 19, /* 72 */
+ 19, 19, 19, 19, 19, 19, 19, 108, /* 72 */
+109, 109, 109, 109, 109, 109, 109, 109, /* 72 */
+109, 109, 109, 109, 110, 110, 110, 110, /* 72 */
+111, 111, 111, 111, 111, 111, 111, 111, /* 72 */
+111, 111, 111, 111, 112, 112, 112, 112, /* 72 */
+113, 113, 113, 46, 46, 46, 46, 46, /* 73 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 73 */
+ 7, 7, 7, 7, 7, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
+ 15, 15, 7, 15, 7, 15, 15, 15, /* 74 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
+ 15, 15, 15, 46, 46, 46, 46, 46, /* 74 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 74 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 74 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 46, 46, 46, 46, 46, 46, /* 76 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 76 */
+ 15, 46, 15, 15, 15, 15, 15, 15, /* 77 */
+ 7, 7, 7, 7, 15, 15, 15, 15, /* 77 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
+ 7, 7, 15, 15, 15, 15, 15, 15, /* 77 */
+ 15, 5, 6, 15, 15, 15, 15, 15, /* 77 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 46, 46, 46, 46, 46, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
+ 15, 15, 15, 15, 15, 46, 46, 46, /* 79 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 80 */
+ 15, 15, 15, 46, 46, 46, 46, 46, /* 80 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 80 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 80 */
+114, 114, 114, 114, 114, 114, 114, 114, /* 80 */
+114, 114, 114, 114, 114, 114, 114, 114, /* 80 */
+114, 114, 114, 114, 82, 82, 82, 82, /* 80 */
+ 82, 82, 82, 82, 82, 82, 82, 82, /* 80 */
+ 82, 82, 82, 82, 82, 82, 82, 82, /* 81 */
+115, 115, 115, 115, 115, 115, 115, 115, /* 81 */
+115, 115, 115, 115, 115, 115, 115, 115, /* 81 */
+115, 115, 115, 115, 15, 15, 15, 15, /* 81 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 81 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 81 */
+ 15, 15, 15, 15, 15, 15, 116, 116, /* 81 */
+116, 116, 116, 116, 116, 116, 116, 116, /* 81 */
+116, 116, 116, 116, 116, 116, 116, 116, /* 82 */
+116, 116, 116, 116, 116, 116, 116, 116, /* 82 */
+117, 117, 117, 117, 117, 117, 117, 117, /* 82 */
+117, 117, 117, 117, 117, 117, 117, 117, /* 82 */
+117, 117, 117, 117, 117, 117, 117, 117, /* 82 */
+117, 117, 118, 46, 46, 46, 46, 46, /* 82 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 82 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 82 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 46, 46, /* 84 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 85 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 46, 46, 46, 46, /* 86 */
+ 46, 46, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 46, 15, 15, 15, 15, 46, 15, 15, /* 87 */
+ 15, 15, 46, 46, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 46, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 88 */
+ 15, 15, 15, 15, 46, 15, 46, 15, /* 88 */
+ 15, 15, 15, 46, 46, 46, 15, 46, /* 88 */
+ 15, 15, 15, 15, 15, 15, 15, 46, /* 88 */
+ 46, 15, 15, 15, 15, 15, 15, 15, /* 88 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 88 */
+ 46, 46, 46, 46, 46, 46, 119, 119, /* 88 */
+119, 119, 119, 119, 119, 119, 119, 119, /* 88 */
+114, 114, 114, 114, 114, 114, 114, 114, /* 89 */
+114, 114, 83, 83, 83, 83, 83, 83, /* 89 */
+ 83, 83, 83, 83, 15, 46, 46, 46, /* 89 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */
+ 46, 15, 15, 15, 15, 15, 15, 15, /* 89 */
+ 15, 15, 15, 15, 15, 15, 15, 46, /* 89 */
+ 2, 3, 3, 3, 15, 59, 3, 120, /* 90 */
+ 5, 6, 5, 6, 5, 6, 5, 6, /* 90 */
+ 5, 6, 15, 15, 5, 6, 5, 6, /* 90 */
+ 5, 6, 5, 6, 8, 5, 6, 5, /* 90 */
+ 15, 121, 121, 121, 121, 121, 121, 121, /* 90 */
+121, 121, 60, 60, 60, 60, 60, 60, /* 90 */
+ 8, 59, 59, 59, 59, 59, 15, 15, /* 90 */
+ 46, 46, 46, 46, 46, 46, 46, 15, /* 90 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 46, 46, 46, /* 92 */
+ 46, 60, 60, 59, 59, 59, 59, 46, /* 92 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 3, 59, 59, 59, 46, /* 93 */
+ 46, 46, 46, 46, 46, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 46, 46, 46, /* 94 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 95 */
+ 40, 40, 40, 40, 40, 40, 40, 46, /* 95 */
+ 15, 15, 85, 85, 85, 85, 15, 15, /* 95 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 95 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 15, 46, 46, 46, /* 96 */
+ 85, 85, 85, 85, 85, 85, 85, 85, /* 96 */
+ 85, 85, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 46, 46, 46, 46, /* 97 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */
+ 15, 15, 15, 15, 46, 46, 46, 15, /* 97 */
+114, 114, 114, 114, 114, 114, 114, 114, /* 98 */
+114, 114, 15, 15, 15, 15, 15, 15, /* 98 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
+ 15, 46, 46, 46, 46, 46, 46, 46, /* 98 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 98 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 46, 46, 46, 46, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 46, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 46, /* 100 */
+ 46, 46, 46, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 46, 46, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 46, /* 101 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
+ 40, 40, 40, 40, 40, 40, 46, 46, /* 102 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
+ 40, 40, 40, 40, 46, 46, 46, 46, /* 103 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
+ 40, 40, 40, 40, 40, 40, 46, 46, /* 106 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 106 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 106 */
+ 16, 16, 16, 16, 16, 16, 16, 46, /* 107 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 107 */
+ 46, 46, 46, 16, 16, 16, 16, 16, /* 107 */
+ 46, 46, 46, 46, 46, 46, 60, 40, /* 107 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 107 */
+ 40, 7, 40, 40, 40, 40, 40, 40, /* 107 */
+ 40, 40, 40, 40, 40, 40, 40, 46, /* 107 */
+ 40, 40, 40, 40, 40, 46, 40, 46, /* 107 */
+ 40, 40, 46, 40, 40, 46, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 46, 46, 46, 46, 46, 46, /* 109 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 109 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 110 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 110 */
+ 46, 46, 46, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 5, 6, /* 111 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 112 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 46, 46, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 114 */
+ 40, 40, 40, 40, 46, 46, 46, 46, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
+ 60, 60, 60, 60, 46, 46, 46, 46, /* 115 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
+ 3, 8, 8, 12, 12, 5, 6, 5, /* 115 */
+ 6, 5, 6, 5, 6, 5, 6, 5, /* 115 */
+ 6, 5, 6, 5, 6, 46, 46, 46, /* 116 */
+ 46, 3, 3, 3, 3, 12, 12, 12, /* 116 */
+ 3, 3, 3, 46, 3, 3, 3, 3, /* 116 */
+ 8, 5, 6, 5, 6, 5, 6, 3, /* 116 */
+ 3, 3, 7, 8, 7, 7, 7, 46, /* 116 */
+ 3, 4, 3, 3, 46, 46, 46, 46, /* 116 */
+ 40, 40, 40, 46, 40, 46, 40, 40, /* 116 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 116 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 46, 46, 104, /* 117 */
+ 46, 3, 3, 3, 4, 3, 3, 3, /* 118 */
+ 5, 6, 3, 7, 3, 8, 3, 3, /* 118 */
+ 9, 9, 9, 9, 9, 9, 9, 9, /* 118 */
+ 9, 9, 3, 3, 7, 7, 7, 3, /* 118 */
+ 3, 10, 10, 10, 10, 10, 10, 10, /* 118 */
+ 10, 10, 10, 10, 10, 10, 10, 10, /* 118 */
+ 10, 10, 10, 10, 10, 10, 10, 10, /* 118 */
+ 10, 10, 10, 5, 3, 6, 11, 12, /* 118 */
+ 11, 13, 13, 13, 13, 13, 13, 13, /* 119 */
+ 13, 13, 13, 13, 13, 13, 13, 13, /* 119 */
+ 13, 13, 13, 13, 13, 13, 13, 13, /* 119 */
+ 13, 13, 13, 5, 7, 6, 7, 46, /* 119 */
+ 46, 3, 5, 6, 3, 3, 40, 40, /* 119 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 119 */
+ 59, 40, 40, 40, 40, 40, 40, 40, /* 119 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 119 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 59, 59, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 46, /* 120 */
+ 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */
+ 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */
+ 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */
+ 46, 46, 40, 40, 40, 46, 46, 46, /* 121 */
+ 4, 4, 7, 11, 15, 4, 4, 46, /* 121 */
+ 7, 7, 7, 7, 7, 15, 15, 46, /* 121 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 121 */
+ 46, 46, 46, 46, 46, 15, 46, 46 /* 121 */
+};
+
+/* The A table has 124 entries for a total of 496 bytes. */
+
+const uint32 js_A[] = {
+0x0001000F, /* 0 Cc, ignorable */
+0x0004000F, /* 1 Cc, whitespace */
+0x0004000C, /* 2 Zs, whitespace */
+0x00000018, /* 3 Po */
+0x0006001A, /* 4 Sc, currency */
+0x00000015, /* 5 Ps */
+0x00000016, /* 6 Pe */
+0x00000019, /* 7 Sm */
+0x00000014, /* 8 Pd */
+0x00036089, /* 9 Nd, identifier part, decimal 16 */
+0x0827FF81, /* 10 Lu, hasLower (add 32), identifier start, supradecimal 31 */
+0x0000001B, /* 11 Sk */
+0x00050017, /* 12 Pc, underscore */
+0x0817FF82, /* 13 Ll, hasUpper (subtract 32), identifier start, supradecimal 31 */
+0x0000000C, /* 14 Zs */
+0x0000001C, /* 15 So */
+0x00070182, /* 16 Ll, identifier start */
+0x0000600B, /* 17 No, decimal 16 */
+0x0000500B, /* 18 No, decimal 8 */
+0x0000800B, /* 19 No, strange */
+0x08270181, /* 20 Lu, hasLower (add 32), identifier start */
+0x08170182, /* 21 Ll, hasUpper (subtract 32), identifier start */
+0xE1D70182, /* 22 Ll, hasUpper (subtract -121), identifier start */
+0x00670181, /* 23 Lu, hasLower (add 1), identifier start */
+0x00570182, /* 24 Ll, hasUpper (subtract 1), identifier start */
+0xCE670181, /* 25 Lu, hasLower (add -199), identifier start */
+0x3A170182, /* 26 Ll, hasUpper (subtract 232), identifier start */
+0xE1E70181, /* 27 Lu, hasLower (add -121), identifier start */
+0x4B170182, /* 28 Ll, hasUpper (subtract 300), identifier start */
+0x34A70181, /* 29 Lu, hasLower (add 210), identifier start */
+0x33A70181, /* 30 Lu, hasLower (add 206), identifier start */
+0x33670181, /* 31 Lu, hasLower (add 205), identifier start */
+0x32A70181, /* 32 Lu, hasLower (add 202), identifier start */
+0x32E70181, /* 33 Lu, hasLower (add 203), identifier start */
+0x33E70181, /* 34 Lu, hasLower (add 207), identifier start */
+0x34E70181, /* 35 Lu, hasLower (add 211), identifier start */
+0x34670181, /* 36 Lu, hasLower (add 209), identifier start */
+0x35670181, /* 37 Lu, hasLower (add 213), identifier start */
+0x00070181, /* 38 Lu, identifier start */
+0x36A70181, /* 39 Lu, hasLower (add 218), identifier start */
+0x00070185, /* 40 Lo, identifier start */
+0x36670181, /* 41 Lu, hasLower (add 217), identifier start */
+0x36E70181, /* 42 Lu, hasLower (add 219), identifier start */
+0x00AF0181, /* 43 Lu, hasLower (add 2), hasTitle, identifier start */
+0x007F0183, /* 44 Lt, hasUpper (subtract 1), hasLower (add 1), hasTitle, identifier start */
+0x009F0182, /* 45 Ll, hasUpper (subtract 2), hasTitle, identifier start */
+0x00000000, /* 46 unassigned */
+0x34970182, /* 47 Ll, hasUpper (subtract 210), identifier start */
+0x33970182, /* 48 Ll, hasUpper (subtract 206), identifier start */
+0x33570182, /* 49 Ll, hasUpper (subtract 205), identifier start */
+0x32970182, /* 50 Ll, hasUpper (subtract 202), identifier start */
+0x32D70182, /* 51 Ll, hasUpper (subtract 203), identifier start */
+0x33D70182, /* 52 Ll, hasUpper (subtract 207), identifier start */
+0x34570182, /* 53 Ll, hasUpper (subtract 209), identifier start */
+0x34D70182, /* 54 Ll, hasUpper (subtract 211), identifier start */
+0x35570182, /* 55 Ll, hasUpper (subtract 213), identifier start */
+0x36970182, /* 56 Ll, hasUpper (subtract 218), identifier start */
+0x36570182, /* 57 Ll, hasUpper (subtract 217), identifier start */
+0x36D70182, /* 58 Ll, hasUpper (subtract 219), identifier start */
+0x00070084, /* 59 Lm, identifier start */
+0x00030086, /* 60 Mn, identifier part */
+0x09A70181, /* 61 Lu, hasLower (add 38), identifier start */
+0x09670181, /* 62 Lu, hasLower (add 37), identifier start */
+0x10270181, /* 63 Lu, hasLower (add 64), identifier start */
+0x0FE70181, /* 64 Lu, hasLower (add 63), identifier start */
+0x09970182, /* 65 Ll, hasUpper (subtract 38), identifier start */
+0x09570182, /* 66 Ll, hasUpper (subtract 37), identifier start */
+0x10170182, /* 67 Ll, hasUpper (subtract 64), identifier start */
+0x0FD70182, /* 68 Ll, hasUpper (subtract 63), identifier start */
+0x0F970182, /* 69 Ll, hasUpper (subtract 62), identifier start */
+0x0E570182, /* 70 Ll, hasUpper (subtract 57), identifier start */
+0x0BD70182, /* 71 Ll, hasUpper (subtract 47), identifier start */
+0x0D970182, /* 72 Ll, hasUpper (subtract 54), identifier start */
+0x15970182, /* 73 Ll, hasUpper (subtract 86), identifier start */
+0x14170182, /* 74 Ll, hasUpper (subtract 80), identifier start */
+0x14270181, /* 75 Lu, hasLower (add 80), identifier start */
+0x0C270181, /* 76 Lu, hasLower (add 48), identifier start */
+0x0C170182, /* 77 Ll, hasUpper (subtract 48), identifier start */
+0x00034089, /* 78 Nd, identifier part, decimal 0 */
+0x00000087, /* 79 Me */
+0x00030088, /* 80 Mc, identifier part */
+0x00037489, /* 81 Nd, identifier part, decimal 26 */
+0x00005A0B, /* 82 No, decimal 13 */
+0x00006E0B, /* 83 No, decimal 23 */
+0x0000740B, /* 84 No, decimal 26 */
+0x0000000B, /* 85 No */
+0xFE170182, /* 86 Ll, hasUpper (subtract -8), identifier start */
+0xFE270181, /* 87 Lu, hasLower (add -8), identifier start */
+0xED970182, /* 88 Ll, hasUpper (subtract -74), identifier start */
+0xEA970182, /* 89 Ll, hasUpper (subtract -86), identifier start */
+0xE7170182, /* 90 Ll, hasUpper (subtract -100), identifier start */
+0xE0170182, /* 91 Ll, hasUpper (subtract -128), identifier start */
+0xE4170182, /* 92 Ll, hasUpper (subtract -112), identifier start */
+0xE0970182, /* 93 Ll, hasUpper (subtract -126), identifier start */
+0xFDD70182, /* 94 Ll, hasUpper (subtract -9), identifier start */
+0xEDA70181, /* 95 Lu, hasLower (add -74), identifier start */
+0xFDE70181, /* 96 Lu, hasLower (add -9), identifier start */
+0xEAA70181, /* 97 Lu, hasLower (add -86), identifier start */
+0xE7270181, /* 98 Lu, hasLower (add -100), identifier start */
+0xFE570182, /* 99 Ll, hasUpper (subtract -7), identifier start */
+0xE4270181, /* 100 Lu, hasLower (add -112), identifier start */
+0xFE670181, /* 101 Lu, hasLower (add -7), identifier start */
+0xE0270181, /* 102 Lu, hasLower (add -128), identifier start */
+0xE0A70181, /* 103 Lu, hasLower (add -126), identifier start */
+0x00010010, /* 104 Cf, ignorable */
+0x0004000D, /* 105 Zl, whitespace */
+0x0004000E, /* 106 Zp, whitespace */
+0x0000400B, /* 107 No, decimal 0 */
+0x0000440B, /* 108 No, decimal 2 */
+0x0427438A, /* 109 Nl, hasLower (add 16), identifier start, decimal 1 */
+0x0427818A, /* 110 Nl, hasLower (add 16), identifier start, strange */
+0x0417638A, /* 111 Nl, hasUpper (subtract 16), identifier start, decimal 17 */
+0x0417818A, /* 112 Nl, hasUpper (subtract 16), identifier start, strange */
+0x0007818A, /* 113 Nl, identifier start, strange */
+0x0000420B, /* 114 No, decimal 1 */
+0x0000720B, /* 115 No, decimal 25 */
+0x06A0001C, /* 116 So, hasLower (add 26) */
+0x0690001C, /* 117 So, hasUpper (subtract 26) */
+0x00006C0B, /* 118 No, decimal 22 */
+0x0000560B, /* 119 No, decimal 11 */
+0x0007738A, /* 120 Nl, identifier start, decimal 25 */
+0x0007418A, /* 121 Nl, identifier start, decimal 0 */
+0x00000013, /* 122 Cs */
+0x00000012 /* 123 Co */
+};
+
+const jschar js_uriReservedPlusPound_ucstr[] =
+ {';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#', 0};
+const jschar js_uriUnescaped_ucstr[] =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '-', '_', '.', '!', '~', '*', '\'', '(', ')', 0};
+
+#define URI_CHUNK 64U
+
+/* Concatenate jschars onto the buffer */
+static JSBool
+AddCharsToURI(JSContext *cx, JSCharBuffer *buf,
+ const jschar *chars, size_t length)
+{
+ size_t total;
+ jschar *newchars;
+
+ total = buf->length + length + 1;
+ if (!buf->chars ||
+ JS_HOWMANY(total, URI_CHUNK) > JS_HOWMANY(buf->length + 1, URI_CHUNK)) {
+ total = JS_ROUNDUP(total, URI_CHUNK);
+ newchars = (jschar *) JS_realloc(cx, buf->chars,
+ total * sizeof(jschar));
+ if (!newchars)
+ return JS_FALSE;
+ buf->chars = newchars;
+ }
+ js_strncpy(buf->chars + buf->length, chars, length);
+ buf->length += length;
+ buf->chars[buf->length] = 0;
+ return JS_TRUE;
+}
+
+static JSBool
+TransferBufferToString(JSContext *cx, JSCharBuffer *cb, jsval *rval)
+{
+ jschar *chars;
+ size_t n;
+ JSString *str;
+
+ /*
+ * Shrinking realloc can fail (e.g., with a BSD-style allocator), but we
+ * don't worry about that case here.
+ */
+ n = cb->length;
+ chars = (jschar *) JS_realloc(cx, cb->chars, (n + 1) * sizeof(jschar));
+ if (!chars)
+ chars = cb->chars;
+ str = js_NewString(cx, chars, n);
+ if (!str)
+ return JS_FALSE;
+
+ /* Successful allocation transfer ownership of cb->chars to the string. */
+#ifdef DEBUG
+ memset(cb, JS_FREE_PATTERN, sizeof *cb);
+#endif
+
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+/*
+ * ECMA 3, 15.1.3 URI Handling Function Properties
+ *
+ * The following are implementations of the algorithms
+ * given in the ECMA specification for the hidden functions
+ * 'Encode' and 'Decode'.
+ */
+static JSBool
+Encode(JSContext *cx, JSString *str, const jschar *unescapedSet,
+ const jschar *unescapedSet2, jsval *rval)
+{
+ size_t length, j, k, L;
+ JSCharBuffer cb;
+ jschar *chars, c, c2;
+ uint32 v;
+ uint8 utf8buf[6];
+ jschar hexBuf[4];
+ static const char HexDigits[] = "0123456789ABCDEF"; /* NB: uppercase */
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ if (length == 0) {
+ *rval = STRING_TO_JSVAL(cx->runtime->emptyString);
+ return JS_TRUE;
+ }
+
+ cb.length = 0;
+ cb.chars = NULL;
+
+ /* From this point the control must goto bad on failures. */
+ hexBuf[0] = '%';
+ hexBuf[3] = 0;
+ for (k = 0; k < length; k++) {
+ c = chars[k];
+ if (js_strchr(unescapedSet, c) ||
+ (unescapedSet2 && js_strchr(unescapedSet2, c))) {
+ if (!AddCharsToURI(cx, &cb, &c, 1))
+ goto bad;
+ } else {
+ if ((c >= 0xDC00) && (c <= 0xDFFF)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_URI, NULL);
+ goto bad;
+ }
+ if (c < 0xD800 || c > 0xDBFF) {
+ v = c;
+ } else {
+ k++;
+ if (k == length) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_URI, NULL);
+ goto bad;
+ }
+ c2 = chars[k];
+ if ((c2 < 0xDC00) || (c2 > 0xDFFF)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_URI, NULL);
+ goto bad;
+ }
+ v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
+ }
+ L = js_OneUcs4ToUtf8Char(utf8buf, v);
+ for (j = 0; j < L; j++) {
+ hexBuf[1] = HexDigits[utf8buf[j] >> 4];
+ hexBuf[2] = HexDigits[utf8buf[j] & 0xf];
+ if (!AddCharsToURI(cx, &cb, hexBuf, 3))
+ goto bad;
+ }
+ }
+ }
+
+ if (!TransferBufferToString(cx, &cb, rval))
+ goto bad;
+
+ return JS_TRUE;
+
+ bad:
+ JS_free(cx, cb.chars);
+ return JS_FALSE;
+}
+
+static JSBool
+Decode(JSContext *cx, JSString *str, const jschar *reservedSet, jsval *rval)
+{
+ size_t length, start, k;
+ JSCharBuffer cb;
+ jschar *chars, c, H;
+ uint32 v;
+ jsuint B;
+ uint8 octets[6];
+ intN j, n;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ if (length == 0) {
+ *rval = STRING_TO_JSVAL(cx->runtime->emptyString);
+ return JS_TRUE;
+ }
+
+ cb.length = 0;
+ cb.chars = NULL;
+
+ /* From this point the control must goto bad on failures. */
+ for (k = 0; k < length; k++) {
+ c = chars[k];
+ if (c == '%') {
+ start = k;
+ if ((k + 2) >= length)
+ goto report_bad_uri;
+ if (!JS7_ISHEX(chars[k+1]) || !JS7_ISHEX(chars[k+2]))
+ goto report_bad_uri;
+ B = JS7_UNHEX(chars[k+1]) * 16 + JS7_UNHEX(chars[k+2]);
+ k += 2;
+ if (!(B & 0x80)) {
+ c = (jschar)B;
+ } else {
+ n = 1;
+ while (B & (0x80 >> n))
+ n++;
+ if (n == 1 || n > 6)
+ goto report_bad_uri;
+ octets[0] = (uint8)B;
+ if (k + 3 * (n - 1) >= length)
+ goto report_bad_uri;
+ for (j = 1; j < n; j++) {
+ k++;
+ if (chars[k] != '%')
+ goto report_bad_uri;
+ if (!JS7_ISHEX(chars[k+1]) || !JS7_ISHEX(chars[k+2]))
+ goto report_bad_uri;
+ B = JS7_UNHEX(chars[k+1]) * 16 + JS7_UNHEX(chars[k+2]);
+ if ((B & 0xC0) != 0x80)
+ goto report_bad_uri;
+ k += 2;
+ octets[j] = (char)B;
+ }
+ v = Utf8ToOneUcs4Char(octets, n);
+ if (v >= 0x10000) {
+ v -= 0x10000;
+ if (v > 0xFFFFF)
+ goto report_bad_uri;
+ c = (jschar)((v & 0x3FF) + 0xDC00);
+ H = (jschar)((v >> 10) + 0xD800);
+ if (!AddCharsToURI(cx, &cb, &H, 1))
+ goto bad;
+ } else {
+ c = (jschar)v;
+ }
+ }
+ if (js_strchr(reservedSet, c)) {
+ if (!AddCharsToURI(cx, &cb, &chars[start], (k - start + 1)))
+ goto bad;
+ } else {
+ if (!AddCharsToURI(cx, &cb, &c, 1))
+ goto bad;
+ }
+ } else {
+ if (!AddCharsToURI(cx, &cb, &c, 1))
+ return JS_FALSE;
+ }
+ }
+
+ if (!TransferBufferToString(cx, &cb, rval))
+ goto bad;
+
+ return JS_TRUE;
+
+ report_bad_uri:
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_URI);
+ /* FALL THROUGH */
+
+ bad:
+ JS_free(cx, cb.chars);
+ return JS_FALSE;
+}
+
+static JSBool
+str_decodeURI(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = ArgToRootedString(cx, argc, vp, 0);
+ if (!str)
+ return JS_FALSE;
+ return Decode(cx, str, js_uriReservedPlusPound_ucstr, vp);
+}
+
+static JSBool
+str_decodeURI_Component(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = ArgToRootedString(cx, argc, vp, 0);
+ if (!str)
+ return JS_FALSE;
+ return Decode(cx, str, js_empty_ucstr, vp);
+}
+
+static JSBool
+str_encodeURI(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = ArgToRootedString(cx, argc, vp, 0);
+ if (!str)
+ return JS_FALSE;
+ return Encode(cx, str, js_uriReservedPlusPound_ucstr, js_uriUnescaped_ucstr,
+ vp);
+}
+
+static JSBool
+str_encodeURI_Component(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = ArgToRootedString(cx, argc, vp, 0);
+ if (!str)
+ return JS_FALSE;
+ return Encode(cx, str, js_uriUnescaped_ucstr, NULL, vp);
+}
+
+/*
+ * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
+ * least 6 bytes long. Return the number of UTF-8 bytes of data written.
+ */
+int
+js_OneUcs4ToUtf8Char(uint8 *utf8Buffer, uint32 ucs4Char)
+{
+ int utf8Length = 1;
+
+ JS_ASSERT(ucs4Char <= 0x7FFFFFFF);
+ if (ucs4Char < 0x80) {
+ *utf8Buffer = (uint8)ucs4Char;
+ } else {
+ int i;
+ uint32 a = ucs4Char >> 11;
+ utf8Length = 2;
+ while (a) {
+ a >>= 5;
+ utf8Length++;
+ }
+ i = utf8Length;
+ while (--i) {
+ utf8Buffer[i] = (uint8)((ucs4Char & 0x3F) | 0x80);
+ ucs4Char >>= 6;
+ }
+ *utf8Buffer = (uint8)(0x100 - (1 << (8-utf8Length)) + ucs4Char);
+ }
+ return utf8Length;
+}
+
+/*
+ * Convert a utf8 character sequence into a UCS-4 character and return that
+ * character. It is assumed that the caller already checked that the sequence
+ * is valid.
+ */
+static uint32
+Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length)
+{
+ uint32 ucs4Char;
+ uint32 minucs4Char;
+ /* from Unicode 3.1, non-shortest form is illegal */
+ static const uint32 minucs4Table[] = {
+ 0x00000080, 0x00000800, 0x0001000, 0x0020000, 0x0400000
+ };
+
+ JS_ASSERT(utf8Length >= 1 && utf8Length <= 6);
+ if (utf8Length == 1) {
+ ucs4Char = *utf8Buffer;
+ JS_ASSERT(!(ucs4Char & 0x80));
+ } else {
+ JS_ASSERT((*utf8Buffer & (0x100 - (1 << (7-utf8Length)))) ==
+ (0x100 - (1 << (8-utf8Length))));
+ ucs4Char = *utf8Buffer++ & ((1<<(7-utf8Length))-1);
+ minucs4Char = minucs4Table[utf8Length-2];
+ while (--utf8Length) {
+ JS_ASSERT((*utf8Buffer & 0xC0) == 0x80);
+ ucs4Char = ucs4Char<<6 | (*utf8Buffer++ & 0x3F);
+ }
+ if (ucs4Char < minucs4Char ||
+ ucs4Char == 0xFFFE || ucs4Char == 0xFFFF) {
+ ucs4Char = 0xFFFD;
+ }
+ }
+ return ucs4Char;
+}
+
+#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS
+
+JS_FRIEND_API(size_t)
+js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp,
+ JSString *str, uint32 quote)
+{
+ jschar *chars, *charsEnd;
+ size_t n;
+ const char *escape;
+ char c;
+ uintN u, hex, shift;
+ enum {
+ STOP, FIRST_QUOTE, LAST_QUOTE, CHARS, ESCAPE_START, ESCAPE_MORE
+ } state;
+
+ JS_ASSERT(quote == 0 || quote == '\'' || quote == '"');
+ JS_ASSERT_IF(buffer, bufferSize != 0);
+ JS_ASSERT_IF(!buffer, bufferSize == 0);
+ JS_ASSERT_IF(fp, !buffer);
+
+ JSSTRING_CHARS_AND_END(str, chars, charsEnd);
+ n = 0;
+ --bufferSize;
+ state = FIRST_QUOTE;
+ shift = 0;
+ hex = 0;
+ u = 0;
+ c = 0; /* to quell GCC warnings */
+
+ for (;;) {
+ switch (state) {
+ case STOP:
+ goto stop;
+ case FIRST_QUOTE:
+ state = CHARS;
+ goto do_quote;
+ case LAST_QUOTE:
+ state = STOP;
+ do_quote:
+ if (quote == 0)
+ continue;
+ c = (char)quote;
+ break;
+ case CHARS:
+ if (chars == charsEnd) {
+ state = LAST_QUOTE;
+ continue;
+ }
+ u = *chars++;
+ if (u < ' ') {
+ if (u != 0) {
+ escape = strchr(js_EscapeMap, (int)u);
+ if (escape) {
+ u = escape[1];
+ goto do_escape;
+ }
+ }
+ goto do_hex_escape;
+ }
+ if (u < 127) {
+ if (u == quote || u == '\\')
+ goto do_escape;
+ c = (char)u;
+ } else if (u < 0x100) {
+ goto do_hex_escape;
+ } else {
+ shift = 16;
+ hex = u;
+ u = 'u';
+ goto do_escape;
+ }
+ break;
+ do_hex_escape:
+ shift = 8;
+ hex = u;
+ u = 'x';
+ do_escape:
+ c = '\\';
+ state = ESCAPE_START;
+ break;
+ case ESCAPE_START:
+ JS_ASSERT(' ' <= u && u < 127);
+ c = (char)u;
+ state = ESCAPE_MORE;
+ break;
+ case ESCAPE_MORE:
+ if (shift == 0) {
+ state = CHARS;
+ continue;
+ }
+ shift -= 4;
+ u = 0xF & (hex >> shift);
+ c = (char)(u + (u < 10 ? '0' : 'A' - 10));
+ break;
+ }
+ if (buffer) {
+ if (n == bufferSize)
+ break;
+ buffer[n] = c;
+ } else if (fp) {
+ fputc(c, fp);
+ }
+ n++;
+ }
+ stop:
+ if (buffer)
+ buffer[n] = '\0';
+ return n;
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsstr.h b/tools/node_modules/expresso/deps/jscoverage/js/jsstr.h
new file mode 100644
index 0000000..349754e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsstr.h
@@ -0,0 +1,662 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsstr_h___
+#define jsstr_h___
+/*
+ * JS string type implementation.
+ *
+ * A JS string is a counted array of unicode characters. To support handoff
+ * of API client memory, the chars are allocated separately from the length,
+ * necessitating a pointer after the count, to form a separately allocated
+ * string descriptor. String descriptors are GC'ed, while their chars are
+ * allocated from the malloc heap.
+ */
+#include <ctype.h>
+#include "jspubtd.h"
+#include "jsprvtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * The GC-thing "string" type.
+ *
+ * When the JSSTRFLAG_DEPENDENT bit of the length field is unset, the u.chars
+ * field points to a flat character array owned by its GC-thing descriptor.
+ * The array is terminated at index length by a zero character and the size of
+ * the array in bytes is (length + 1) * sizeof(jschar). The terminator is
+ * purely a backstop, in case the chars pointer flows out to native code that
+ * requires \u0000 termination.
+ *
+ * A flat string with JSSTRFLAG_MUTABLE set means that the string is accessible
+ * only from one thread and it is possible to turn it into a dependent string
+ * of the same length to optimize js_ConcatStrings. It is also possible to grow
+ * such a string, but extreme care must be taken to ensure that no other code
+ * relies on the original length of the string.
+ *
+ * A flat string with JSSTRFLAG_ATOMIZED set means that the string is hashed as
+ * an atom. This flag is used to avoid re-hashing the already-atomized string.
+ *
+ * When JSSTRFLAG_DEPENDENT is set, the string depends on characters of another
+ * string strongly referenced by the u.base field. The base member may point to
+ * another dependent string if JSSTRING_CHARS has not been called yet.
+ *
+ * JSSTRFLAG_PREFIX determines the kind of the dependent string. When the flag
+ * is unset, the length field encodes both starting position relative to the
+ * base string and the number of characters in the dependent string, see
+ * JSSTRDEP_START_MASK and JSSTRDEP_LENGTH_MASK macros below for details.
+ *
+ * When JSSTRFLAG_PREFIX is set, the dependent string is a prefix of the base
+ * string. The number of characters in the prefix is encoded using all non-flag
+ * bits of the length field and spans the same 0 .. SIZE_T_MAX/4 range as the
+ * length of the flat string.
+ *
+ * NB: Always use the JSSTRING_LENGTH and JSSTRING_CHARS accessor macros.
+ */
+struct JSString {
+ size_t length;
+ union {
+ jschar *chars;
+ JSString *base;
+ } u;
+};
+
+/*
+ * Definitions for flags stored in the high order bits of JSString.length.
+ * JSSTRFLAG_PREFIX and JSSTRFLAG_MUTABLE are two aliases for the same value.
+ * JSSTRFLAG_PREFIX should be used only if JSSTRFLAG_DEPENDENT is set and
+ * JSSTRFLAG_MUTABLE should be used only if the string is flat.
+ * JSSTRFLAG_ATOMIZED is used only with the flat immutable strings.
+ */
+#define JSSTRFLAG_DEPENDENT JSSTRING_BIT(JS_BITS_PER_WORD - 1)
+#define JSSTRFLAG_PREFIX JSSTRING_BIT(JS_BITS_PER_WORD - 2)
+#define JSSTRFLAG_MUTABLE JSSTRFLAG_PREFIX
+#define JSSTRFLAG_ATOMIZED JSSTRING_BIT(JS_BITS_PER_WORD - 3)
+
+#define JSSTRING_LENGTH_BITS (JS_BITS_PER_WORD - 3)
+#define JSSTRING_LENGTH_MASK JSSTRING_BITMASK(JSSTRING_LENGTH_BITS)
+
+/* Universal JSString type inquiry and accessor macros. */
+#define JSSTRING_BIT(n) ((size_t)1 << (n))
+#define JSSTRING_BITMASK(n) (JSSTRING_BIT(n) - 1)
+#define JSSTRING_HAS_FLAG(str,flg) ((str)->length & (flg))
+#define JSSTRING_IS_DEPENDENT(str) JSSTRING_HAS_FLAG(str, JSSTRFLAG_DEPENDENT)
+#define JSSTRING_IS_FLAT(str) (!JSSTRING_IS_DEPENDENT(str))
+#define JSSTRING_IS_MUTABLE(str) (((str)->length & (JSSTRFLAG_DEPENDENT | \
+ JSSTRFLAG_MUTABLE)) == \
+ JSSTRFLAG_MUTABLE)
+#define JSSTRING_IS_ATOMIZED(str) (((str)->length & (JSSTRFLAG_DEPENDENT | \
+ JSSTRFLAG_ATOMIZED)) ==\
+ JSSTRFLAG_ATOMIZED)
+
+#define JSSTRING_CHARS(str) (JSSTRING_IS_DEPENDENT(str) \
+ ? JSSTRDEP_CHARS(str) \
+ : JSFLATSTR_CHARS(str))
+#define JSSTRING_LENGTH(str) (JSSTRING_IS_DEPENDENT(str) \
+ ? JSSTRDEP_LENGTH(str) \
+ : JSFLATSTR_LENGTH(str))
+
+#define JSSTRING_CHARS_AND_LENGTH(str, chars_, length_) \
+ ((void)(JSSTRING_IS_DEPENDENT(str) \
+ ? ((length_) = JSSTRDEP_LENGTH(str), \
+ (chars_) = JSSTRDEP_CHARS(str)) \
+ : ((length_) = JSFLATSTR_LENGTH(str), \
+ (chars_) = JSFLATSTR_CHARS(str))))
+
+#define JSSTRING_CHARS_AND_END(str, chars_, end) \
+ ((void)((end) = JSSTRING_IS_DEPENDENT(str) \
+ ? JSSTRDEP_LENGTH(str) + ((chars_) = JSSTRDEP_CHARS(str)) \
+ : JSFLATSTR_LENGTH(str) + ((chars_) = JSFLATSTR_CHARS(str))))
+
+/* Specific flat string initializer and accessor macros. */
+#define JSFLATSTR_INIT(str, chars_, length_) \
+ ((void)(JS_ASSERT(((length_) & ~JSSTRING_LENGTH_MASK) == 0), \
+ (str)->length = (length_), (str)->u.chars = (chars_)))
+
+#define JSFLATSTR_LENGTH(str) \
+ (JS_ASSERT(JSSTRING_IS_FLAT(str)), (str)->length & JSSTRING_LENGTH_MASK)
+
+#define JSFLATSTR_CHARS(str) \
+ (JS_ASSERT(JSSTRING_IS_FLAT(str)), (str)->u.chars)
+
+/*
+ * Macros to manipulate atomized and mutable flags of flat strings. It is safe
+ * to use these without extra locking due to the following properties:
+ *
+ * * We do not have a macro like JSFLATSTR_CLEAR_ATOMIZED as a string
+ * remains atomized until the GC collects it.
+ *
+ * * A thread may call JSFLATSTR_SET_MUTABLE only when it is the only thread
+ * accessing the string until a later call to JSFLATSTR_CLEAR_MUTABLE.
+ *
+ * * Multiple threads can call JSFLATSTR_CLEAR_MUTABLE but the macro
+ * actually clears the mutable flag only when the flag is set -- in which
+ * case only one thread can access the string (see previous property).
+ *
+ * Thus, when multiple threads access the string, JSFLATSTR_SET_ATOMIZED is
+ * the only macro that can update the length field of the string by changing
+ * the mutable bit from 0 to 1. We call the macro only after the string has
+ * been hashed. When some threads in js_ValueToStringId see that the flag is
+ * set, it knows that the string was atomized.
+ *
+ * On the other hand, if the thread sees that the flag is unset, it could be
+ * seeing a stale value when another thread has just atomized the string and
+ * set the flag. But this can lead only to an extra call to js_AtomizeString.
+ * This function would find that the string was already hashed and return it
+ * with the atomized bit set.
+ */
+#define JSFLATSTR_SET_ATOMIZED(str) \
+ ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str) && !JSSTRING_IS_MUTABLE(str)), \
+ (str)->length |= JSSTRFLAG_ATOMIZED))
+
+#define JSFLATSTR_SET_MUTABLE(str) \
+ ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str) && !JSSTRING_IS_ATOMIZED(str)), \
+ (str)->length |= JSSTRFLAG_MUTABLE))
+
+#define JSFLATSTR_CLEAR_MUTABLE(str) \
+ ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str)), \
+ JSSTRING_HAS_FLAG(str, JSSTRFLAG_MUTABLE) && \
+ ((str)->length &= ~JSSTRFLAG_MUTABLE)))
+
+/* Specific dependent string shift/mask accessor and mutator macros. */
+#define JSSTRDEP_START_BITS (JSSTRING_LENGTH_BITS-JSSTRDEP_LENGTH_BITS)
+#define JSSTRDEP_START_SHIFT JSSTRDEP_LENGTH_BITS
+#define JSSTRDEP_START_MASK JSSTRING_BITMASK(JSSTRDEP_START_BITS)
+#define JSSTRDEP_LENGTH_BITS (JSSTRING_LENGTH_BITS / 2)
+#define JSSTRDEP_LENGTH_MASK JSSTRING_BITMASK(JSSTRDEP_LENGTH_BITS)
+
+#define JSSTRDEP_IS_PREFIX(str) JSSTRING_HAS_FLAG(str, JSSTRFLAG_PREFIX)
+
+#define JSSTRDEP_START(str) (JSSTRDEP_IS_PREFIX(str) ? 0 \
+ : (((str)->length \
+ >> JSSTRDEP_START_SHIFT) \
+ & JSSTRDEP_START_MASK))
+#define JSSTRDEP_LENGTH(str) ((str)->length \
+ & (JSSTRDEP_IS_PREFIX(str) \
+ ? JSSTRING_LENGTH_MASK \
+ : JSSTRDEP_LENGTH_MASK))
+
+#define JSSTRDEP_INIT(str,bstr,off,len) \
+ ((str)->length = JSSTRFLAG_DEPENDENT \
+ | ((off) << JSSTRDEP_START_SHIFT) \
+ | (len), \
+ (str)->u.base = (bstr))
+
+#define JSPREFIX_INIT(str,bstr,len) \
+ ((str)->length = JSSTRFLAG_DEPENDENT | JSSTRFLAG_PREFIX | (len), \
+ (str)->u.base = (bstr))
+
+#define JSSTRDEP_BASE(str) ((str)->u.base)
+#define JSPREFIX_BASE(str) JSSTRDEP_BASE(str)
+#define JSPREFIX_SET_BASE(str,bstr) ((str)->u.base = (bstr))
+
+#define JSSTRDEP_CHARS(str) \
+ (JSSTRING_IS_DEPENDENT(JSSTRDEP_BASE(str)) \
+ ? js_GetDependentStringChars(str) \
+ : JSFLATSTR_CHARS(JSSTRDEP_BASE(str)) + JSSTRDEP_START(str))
+
+extern size_t
+js_MinimizeDependentStrings(JSString *str, int level, JSString **basep);
+
+extern jschar *
+js_GetDependentStringChars(JSString *str);
+
+extern const jschar *
+js_GetStringChars(JSContext *cx, JSString *str);
+
+extern JSString * JS_FASTCALL
+js_ConcatStrings(JSContext *cx, JSString *left, JSString *right);
+
+extern const jschar *
+js_UndependString(JSContext *cx, JSString *str);
+
+extern JSBool
+js_MakeStringImmutable(JSContext *cx, JSString *str);
+
+extern JSString* JS_FASTCALL
+js_toLowerCase(JSContext *cx, JSString *str);
+
+extern JSString* JS_FASTCALL
+js_toUpperCase(JSContext *cx, JSString *str);
+
+typedef struct JSCharBuffer {
+ size_t length;
+ jschar *chars;
+} JSCharBuffer;
+
+struct JSSubString {
+ size_t length;
+ const jschar *chars;
+};
+
+extern jschar js_empty_ucstr[];
+extern JSSubString js_EmptySubString;
+
+/* Unicode character attribute lookup tables. */
+extern const uint8 js_X[];
+extern const uint8 js_Y[];
+extern const uint32 js_A[];
+
+/* Enumerated Unicode general category types. */
+typedef enum JSCharType {
+ JSCT_UNASSIGNED = 0,
+ JSCT_UPPERCASE_LETTER = 1,
+ JSCT_LOWERCASE_LETTER = 2,
+ JSCT_TITLECASE_LETTER = 3,
+ JSCT_MODIFIER_LETTER = 4,
+ JSCT_OTHER_LETTER = 5,
+ JSCT_NON_SPACING_MARK = 6,
+ JSCT_ENCLOSING_MARK = 7,
+ JSCT_COMBINING_SPACING_MARK = 8,
+ JSCT_DECIMAL_DIGIT_NUMBER = 9,
+ JSCT_LETTER_NUMBER = 10,
+ JSCT_OTHER_NUMBER = 11,
+ JSCT_SPACE_SEPARATOR = 12,
+ JSCT_LINE_SEPARATOR = 13,
+ JSCT_PARAGRAPH_SEPARATOR = 14,
+ JSCT_CONTROL = 15,
+ JSCT_FORMAT = 16,
+ JSCT_PRIVATE_USE = 18,
+ JSCT_SURROGATE = 19,
+ JSCT_DASH_PUNCTUATION = 20,
+ JSCT_START_PUNCTUATION = 21,
+ JSCT_END_PUNCTUATION = 22,
+ JSCT_CONNECTOR_PUNCTUATION = 23,
+ JSCT_OTHER_PUNCTUATION = 24,
+ JSCT_MATH_SYMBOL = 25,
+ JSCT_CURRENCY_SYMBOL = 26,
+ JSCT_MODIFIER_SYMBOL = 27,
+ JSCT_OTHER_SYMBOL = 28
+} JSCharType;
+
+/* Character classifying and mapping macros, based on java.lang.Character. */
+#define JS_CCODE(c) (js_A[js_Y[(js_X[(uint16)(c)>>6]<<6)|((c)&0x3F)]])
+#define JS_CTYPE(c) (JS_CCODE(c) & 0x1F)
+
+#define JS_ISALPHA(c) ((((1 << JSCT_UPPERCASE_LETTER) | \
+ (1 << JSCT_LOWERCASE_LETTER) | \
+ (1 << JSCT_TITLECASE_LETTER) | \
+ (1 << JSCT_MODIFIER_LETTER) | \
+ (1 << JSCT_OTHER_LETTER)) \
+ >> JS_CTYPE(c)) & 1)
+
+#define JS_ISALNUM(c) ((((1 << JSCT_UPPERCASE_LETTER) | \
+ (1 << JSCT_LOWERCASE_LETTER) | \
+ (1 << JSCT_TITLECASE_LETTER) | \
+ (1 << JSCT_MODIFIER_LETTER) | \
+ (1 << JSCT_OTHER_LETTER) | \
+ (1 << JSCT_DECIMAL_DIGIT_NUMBER)) \
+ >> JS_CTYPE(c)) & 1)
+
+/* A unicode letter, suitable for use in an identifier. */
+#define JS_ISLETTER(c) ((((1 << JSCT_UPPERCASE_LETTER) | \
+ (1 << JSCT_LOWERCASE_LETTER) | \
+ (1 << JSCT_TITLECASE_LETTER) | \
+ (1 << JSCT_MODIFIER_LETTER) | \
+ (1 << JSCT_OTHER_LETTER) | \
+ (1 << JSCT_LETTER_NUMBER)) \
+ >> JS_CTYPE(c)) & 1)
+
+/*
+ * 'IdentifierPart' from ECMA grammar, is Unicode letter or combining mark or
+ * digit or connector punctuation.
+ */
+#define JS_ISIDPART(c) ((((1 << JSCT_UPPERCASE_LETTER) | \
+ (1 << JSCT_LOWERCASE_LETTER) | \
+ (1 << JSCT_TITLECASE_LETTER) | \
+ (1 << JSCT_MODIFIER_LETTER) | \
+ (1 << JSCT_OTHER_LETTER) | \
+ (1 << JSCT_LETTER_NUMBER) | \
+ (1 << JSCT_NON_SPACING_MARK) | \
+ (1 << JSCT_COMBINING_SPACING_MARK) | \
+ (1 << JSCT_DECIMAL_DIGIT_NUMBER) | \
+ (1 << JSCT_CONNECTOR_PUNCTUATION)) \
+ >> JS_CTYPE(c)) & 1)
+
+/* Unicode control-format characters, ignored in input */
+#define JS_ISFORMAT(c) (((1 << JSCT_FORMAT) >> JS_CTYPE(c)) & 1)
+
+/*
+ * Per ECMA-262 15.10.2.6, these characters are the only ones that make up a
+ * "word", as far as a RegExp is concerned. If we want a Unicode-friendlier
+ * definition of "word", we should rename this macro to something regexp-y.
+ */
+#define JS_ISWORD(c) ((c) < 128 && (isalnum(c) || (c) == '_'))
+
+#define JS_ISIDSTART(c) (JS_ISLETTER(c) || (c) == '_' || (c) == '$')
+#define JS_ISIDENT(c) (JS_ISIDPART(c) || (c) == '_' || (c) == '$')
+
+#define JS_ISXMLSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || \
+ (c) == '\n')
+#define JS_ISXMLNSSTART(c) ((JS_CCODE(c) & 0x00000100) || (c) == '_')
+#define JS_ISXMLNS(c) ((JS_CCODE(c) & 0x00000080) || (c) == '.' || \
+ (c) == '-' || (c) == '_')
+#define JS_ISXMLNAMESTART(c) (JS_ISXMLNSSTART(c) || (c) == ':')
+#define JS_ISXMLNAME(c) (JS_ISXMLNS(c) || (c) == ':')
+
+#define JS_ISDIGIT(c) (JS_CTYPE(c) == JSCT_DECIMAL_DIGIT_NUMBER)
+
+/* XXXbe unify on A/X/Y tbls, avoid ctype.h? */
+/* XXXbe fs, etc. ? */
+#define JS_ISSPACE(c) ((JS_CCODE(c) & 0x00070000) == 0x00040000)
+#define JS_ISPRINT(c) ((c) < 128 && isprint(c))
+
+#define JS_ISUPPER(c) (JS_CTYPE(c) == JSCT_UPPERCASE_LETTER)
+#define JS_ISLOWER(c) (JS_CTYPE(c) == JSCT_LOWERCASE_LETTER)
+
+#define JS_TOUPPER(c) ((jschar) ((JS_CCODE(c) & 0x00100000) \
+ ? (c) - ((int32)JS_CCODE(c) >> 22) \
+ : (c)))
+#define JS_TOLOWER(c) ((jschar) ((JS_CCODE(c) & 0x00200000) \
+ ? (c) + ((int32)JS_CCODE(c) >> 22) \
+ : (c)))
+
+/*
+ * Shorthands for ASCII (7-bit) decimal and hex conversion.
+ * Manually inline isdigit for performance; MSVC doesn't do this for us.
+ */
+#define JS7_ISDEC(c) ((((unsigned)(c)) - '0') <= 9)
+#define JS7_UNDEC(c) ((c) - '0')
+#define JS7_ISHEX(c) ((c) < 128 && isxdigit(c))
+#define JS7_UNHEX(c) (uintN)(JS7_ISDEC(c) ? (c) - '0' : 10 + tolower(c) - 'a')
+#define JS7_ISLET(c) ((c) < 128 && isalpha(c))
+
+/* Initialize per-runtime string state for the first context in the runtime. */
+extern JSBool
+js_InitRuntimeStringState(JSContext *cx);
+
+extern JSBool
+js_InitDeflatedStringCache(JSRuntime *rt);
+
+/*
+ * Maximum character code for which we will create a pinned unit string on
+ * demand -- see JSRuntime.unitStrings in jscntxt.h.
+ */
+#define UNIT_STRING_LIMIT 256U
+
+/*
+ * Get the independent string containing only character code at index in str
+ * (backstopped with a zero character as usual for independent strings).
+ */
+extern JSString *
+js_GetUnitString(JSContext *cx, JSString *str, size_t index);
+
+/*
+ * Get the independent string containing only the character code c, which must
+ * be less than UNIT_STRING_LIMIT.
+ */
+extern JSString *
+js_GetUnitStringForChar(JSContext *cx, jschar c);
+
+extern void
+js_FinishUnitStrings(JSRuntime *rt);
+
+extern void
+js_FinishRuntimeStringState(JSContext *cx);
+
+extern void
+js_FinishDeflatedStringCache(JSRuntime *rt);
+
+/* Initialize the String class, returning its prototype object. */
+extern JSClass js_StringClass;
+
+extern JSObject *
+js_InitStringClass(JSContext *cx, JSObject *obj);
+
+extern const char js_escape_str[];
+extern const char js_unescape_str[];
+extern const char js_uneval_str[];
+extern const char js_decodeURI_str[];
+extern const char js_encodeURI_str[];
+extern const char js_decodeURIComponent_str[];
+extern const char js_encodeURIComponent_str[];
+
+/* GC-allocate a string descriptor for the given malloc-allocated chars. */
+extern JSString *
+js_NewString(JSContext *cx, jschar *chars, size_t length);
+
+extern JSString *
+js_NewDependentString(JSContext *cx, JSString *base, size_t start,
+ size_t length);
+
+/* Copy a counted string and GC-allocate a descriptor for it. */
+extern JSString *
+js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n);
+
+/* Copy a C string and GC-allocate a descriptor for it. */
+extern JSString *
+js_NewStringCopyZ(JSContext *cx, const jschar *s);
+
+/*
+ * Free the chars held by str when it is finalized by the GC. When type is
+ * less then zero, it denotes an internal string. Otherwise it denotes the
+ * type of the external string allocated with JS_NewExternalString.
+ *
+ * This function always needs rt but can live with null cx.
+ */
+extern void
+js_FinalizeStringRT(JSRuntime *rt, JSString *str, intN type, JSContext *cx);
+
+/*
+ * Convert a value to a printable C string.
+ */
+typedef JSString *(*JSValueToStringFun)(JSContext *cx, jsval v);
+
+extern JS_FRIEND_API(const char *)
+js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun);
+
+#define js_ValueToPrintableString(cx,v) \
+ js_ValueToPrintable(cx, v, js_ValueToString)
+
+#define js_ValueToPrintableSource(cx,v) \
+ js_ValueToPrintable(cx, v, js_ValueToSource)
+
+/*
+ * Convert a value to a string, returning null after reporting an error,
+ * otherwise returning a new string reference.
+ */
+extern JS_FRIEND_API(JSString *)
+js_ValueToString(JSContext *cx, jsval v);
+
+/*
+ * Convert a value to its source expression, returning null after reporting
+ * an error, otherwise returning a new string reference.
+ */
+extern JS_FRIEND_API(JSString *)
+js_ValueToSource(JSContext *cx, jsval v);
+
+/*
+ * Compute a hash function from str. The caller can call this function even if
+ * str is not a GC-allocated thing.
+ */
+extern uint32
+js_HashString(JSString *str);
+
+/*
+ * Test if strings are equal. The caller can call the function even if str1
+ * or str2 are not GC-allocated things.
+ */
+extern JSBool JS_FASTCALL
+js_EqualStrings(JSString *str1, JSString *str2);
+
+/*
+ * Return less than, equal to, or greater than zero depending on whether
+ * str1 is less than, equal to, or greater than str2.
+ */
+extern int32 JS_FASTCALL
+js_CompareStrings(JSString *str1, JSString *str2);
+
+/*
+ * Boyer-Moore-Horspool superlinear search for pat:patlen in text:textlen.
+ * The patlen argument must be positive and no greater than BMH_PATLEN_MAX.
+ * The start argument tells where in text to begin the search.
+ *
+ * Return the index of pat in text, or -1 if not found.
+ */
+#define BMH_CHARSET_SIZE 256 /* ISO-Latin-1 */
+#define BMH_PATLEN_MAX 255 /* skip table element is uint8 */
+
+#define BMH_BAD_PATTERN (-2) /* return value if pat is not ISO-Latin-1 */
+
+extern jsint
+js_BoyerMooreHorspool(const jschar *text, jsint textlen,
+ const jschar *pat, jsint patlen,
+ jsint start);
+
+extern size_t
+js_strlen(const jschar *s);
+
+extern jschar *
+js_strchr(const jschar *s, jschar c);
+
+extern jschar *
+js_strchr_limit(const jschar *s, jschar c, const jschar *limit);
+
+#define js_strncpy(t, s, n) memcpy((t), (s), (n) * sizeof(jschar))
+
+/*
+ * Return s advanced past any Unicode white space characters.
+ */
+extern const jschar *
+js_SkipWhiteSpace(const jschar *s, const jschar *end);
+
+/*
+ * Inflate bytes to JS chars and vice versa. Report out of memory via cx
+ * and return null on error, otherwise return the jschar or byte vector that
+ * was JS_malloc'ed. length is updated with the length of the new string in jschars.
+ */
+extern jschar *
+js_InflateString(JSContext *cx, const char *bytes, size_t *length);
+
+extern char *
+js_DeflateString(JSContext *cx, const jschar *chars, size_t length);
+
+/*
+ * Inflate bytes to JS chars into a buffer. 'chars' must be large enough for
+ * 'length' jschars. The buffer is NOT null-terminated. The destination length
+ * must be be initialized with the buffer size and will contain on return the
+ * number of copied chars.
+ */
+extern JSBool
+js_InflateStringToBuffer(JSContext* cx, const char *bytes, size_t length,
+ jschar *chars, size_t* charsLength);
+
+/*
+ * Get number of bytes in the deflated sequence of characters.
+ */
+extern size_t
+js_GetDeflatedStringLength(JSContext *cx, const jschar *chars,
+ size_t charsLength);
+
+/*
+ * Deflate JS chars to bytes into a buffer. 'bytes' must be large enough for
+ * 'length chars. The buffer is NOT null-terminated. The destination length
+ * must to be initialized with the buffer size and will contain on return the
+ * number of copied bytes.
+ */
+extern JSBool
+js_DeflateStringToBuffer(JSContext* cx, const jschar *chars,
+ size_t charsLength, char *bytes, size_t* length);
+
+/*
+ * Associate bytes with str in the deflated string cache, returning true on
+ * successful association, false on out of memory.
+ */
+extern JSBool
+js_SetStringBytes(JSContext *cx, JSString *str, char *bytes, size_t length);
+
+/*
+ * Find or create a deflated string cache entry for str that contains its
+ * characters chopped from Unicode code points into bytes.
+ */
+extern const char *
+js_GetStringBytes(JSContext *cx, JSString *str);
+
+/* Remove a deflated string cache entry associated with str if any. */
+extern void
+js_PurgeDeflatedStringCache(JSRuntime *rt, JSString *str);
+
+/* Export a few natives and a helper to other files in SpiderMonkey. */
+extern JSBool
+js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JSBool
+js_StringMatchHelper(JSContext *cx, uintN argc, jsval *vp, jsbytecode *pc);
+
+extern JSBool
+js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda,
+ JSString *repstr, jsval *vp);
+
+/*
+ * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
+ * least 6 bytes long. Return the number of UTF-8 bytes of data written.
+ */
+extern int
+js_OneUcs4ToUtf8Char(uint8 *utf8Buffer, uint32 ucs4Char);
+
+/*
+ * Write str into buffer escaping any non-printable or non-ASCII character.
+ * Guarantees that a NUL is at the end of the buffer. Returns the length of
+ * the written output, NOT including the NUL. If buffer is null, just returns
+ * the length of the output. If quote is not 0, it must be a single or double
+ * quote character that will quote the output.
+ *
+ * The function is only defined for debug builds.
+*/
+#define js_PutEscapedString(buffer, bufferSize, str, quote) \
+ js_PutEscapedStringImpl(buffer, bufferSize, NULL, str, quote)
+
+/*
+ * Write str into file escaping any non-printable or non-ASCII character.
+ * Returns the number of bytes written to file. If quote is not 0, it must
+ * be a single or double quote character that will quote the output.
+ *
+ * The function is only defined for debug builds.
+*/
+#define js_FileEscapedString(file, str, quote) \
+ (JS_ASSERT(file), js_PutEscapedStringImpl(NULL, 0, file, str, quote))
+
+extern JS_FRIEND_API(size_t)
+js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp,
+ JSString *str, uint32 quote);
+
+JS_END_EXTERN_C
+
+#endif /* jsstr_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jstracer.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jstracer.cpp
new file mode 100644
index 0000000..7cfb474
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jstracer.cpp
@@ -0,0 +1,8276 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=4 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * May 28, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Brendan Eich <brendan@mozilla.org>
+ *
+ * Contributor(s):
+ * Andreas Gal <gal@mozilla.com>
+ * Mike Shaver <shaver@mozilla.org>
+ * David Anderson <danderson@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h" // always first
+#include "jsbit.h" // low-level (NSPR-based) headers next
+#include "jsprf.h"
+#include <math.h> // standard headers next
+#ifdef _MSC_VER
+#include <malloc.h>
+#define alloca _alloca
+#endif
+#ifdef SOLARIS
+#include <alloca.h>
+#endif
+
+#include "nanojit/nanojit.h"
+#include "jsarray.h" // higher-level library and API headers
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsregexp.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsdate.h"
+#include "jsstaticcheck.h"
+#include "jstracer.h"
+
+#include "jsautooplen.h" // generated headers last
+
+/* Never use JSVAL_IS_BOOLEAN because it restricts the value (true, false) and
+ the type. What you want to use is JSVAL_TAG(x) == JSVAL_BOOLEAN and then
+ handle the undefined case properly (bug 457363). */
+#undef JSVAL_IS_BOOLEAN
+#define JSVAL_IS_BOOLEAN(x) JS_STATIC_ASSERT(0)
+
+/* Use a fake tag to represent boxed values, borrowing from the integer tag
+ range since we only use JSVAL_INT to indicate integers. */
+#define JSVAL_BOXED 3
+
+/* Map to translate a type tag into a printable representation. */
+static const char typeChar[] = "OIDVS?B?";
+
+/* Number of iterations of a loop where we start tracing. That is, we don't
+ start tracing until the beginning of the HOTLOOP-th iteration. */
+#define HOTLOOP 2
+
+/* Number of times we wait to exit on a side exit before we try to extend the tree. */
+#define HOTEXIT 1
+
+/* Max call depths for inlining. */
+#define MAX_CALLDEPTH 10
+
+/* Max number of type mismatchs before we trash the tree. */
+#define MAX_MISMATCH 20
+
+/* Max blacklist level of inner tree immediate recompiling */
+#define MAX_INNER_RECORD_BLACKLIST -16
+
+/* Max native stack size. */
+#define MAX_NATIVE_STACK_SLOTS 1024
+
+/* Max call stack size. */
+#define MAX_CALL_STACK_ENTRIES 64
+
+/* Max number of branches per tree. */
+#define MAX_BRANCHES 16
+
+/* Macros for demote slot lists */
+#define ALLOCA_UNDEMOTE_SLOTLIST(num) (unsigned*)alloca(((num) + 1) * sizeof(unsigned))
+#define ADD_UNDEMOTE_SLOT(list, slot) list[++list[0]] = slot
+#define NUM_UNDEMOTE_SLOTS(list) list[0]
+#define CLEAR_UNDEMOTE_SLOTLIST(list) list[0] = 0
+
+#ifdef JS_JIT_SPEW
+#define ABORT_TRACE(msg) do { debug_only_v(fprintf(stdout, "abort: %d: %s\n", __LINE__, msg);) return false; } while (0)
+#else
+#define ABORT_TRACE(msg) return false
+#endif
+
+#ifdef JS_JIT_SPEW
+struct __jitstats {
+#define JITSTAT(x) uint64 x;
+#include "jitstats.tbl"
+#undef JITSTAT
+} jitstats = { 0LL, };
+
+JS_STATIC_ASSERT(sizeof(jitstats) % sizeof(uint64) == 0);
+
+enum jitstat_ids {
+#define JITSTAT(x) STAT ## x ## ID,
+#include "jitstats.tbl"
+#undef JITSTAT
+ STAT_IDS_TOTAL
+};
+
+static JSPropertySpec jitstats_props[] = {
+#define JITSTAT(x) { #x, STAT ## x ## ID, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT },
+#include "jitstats.tbl"
+#undef JITSTAT
+ { 0 }
+};
+
+static JSBool
+jitstats_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ int index = -1;
+
+ if (JSVAL_IS_STRING(id)) {
+ JSString* str = JSVAL_TO_STRING(id);
+ if (strcmp(JS_GetStringBytes(str), "HOTLOOP") == 0) {
+ *vp = INT_TO_JSVAL(HOTLOOP);
+ return JS_TRUE;
+ }
+ }
+
+ if (JSVAL_IS_INT(id))
+ index = JSVAL_TO_INT(id);
+
+ uint64 result = 0;
+ switch (index) {
+#define JITSTAT(x) case STAT ## x ## ID: result = jitstats.x; break;
+#include "jitstats.tbl"
+#undef JITSTAT
+ default:
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ if (result < JSVAL_INT_MAX) {
+ *vp = INT_TO_JSVAL(result);
+ return JS_TRUE;
+ }
+ char retstr[64];
+ JS_snprintf(retstr, sizeof retstr, "%llu", result);
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, retstr));
+ return JS_TRUE;
+}
+
+JSClass jitstats_class = {
+ "jitstats",
+ JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub,
+ jitstats_getProperty, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub,
+ JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+void
+js_InitJITStatsClass(JSContext *cx, JSObject *glob)
+{
+ JS_InitClass(cx, glob, NULL, &jitstats_class, NULL, 0, jitstats_props, NULL, NULL, NULL);
+}
+
+#define AUDIT(x) (jitstats.x++)
+#else
+#define AUDIT(x) ((void)0)
+#endif /* JS_JIT_SPEW */
+
+#define INS_CONST(c) addName(lir->insImm(c), #c)
+#define INS_CONSTPTR(p) addName(lir->insImmPtr((void*) (p)), #p)
+
+using namespace avmplus;
+using namespace nanojit;
+
+static GC gc = GC();
+static avmplus::AvmCore s_core = avmplus::AvmCore();
+static avmplus::AvmCore* core = &s_core;
+
+#ifdef JS_JIT_SPEW
+void
+js_DumpPeerStability(Fragmento* frago, const void* ip);
+#endif
+
+/* We really need a better way to configure the JIT. Shaver, where is my fancy JIT object? */
+static bool nesting_enabled = true;
+#if defined(NANOJIT_IA32)
+static bool did_we_check_sse2 = false;
+#endif
+
+#ifdef JS_JIT_SPEW
+static bool verbose_debug = getenv("TRACEMONKEY") && strstr(getenv("TRACEMONKEY"), "verbose");
+#define debug_only_v(x) if (verbose_debug) { x; }
+#else
+#define debug_only_v(x)
+#endif
+
+/* The entire VM shares one oracle. Collisions and concurrent updates are tolerated and worst
+ case cause performance regressions. */
+static Oracle oracle;
+
+/* Blacklists the root peer fragment at a fragment's PC. This is so blacklisting stays at the
+ top of the peer list and not scattered around. */
+void
+js_BlacklistPC(Fragmento* frago, Fragment* frag);
+
+Tracker::Tracker()
+{
+ pagelist = 0;
+}
+
+Tracker::~Tracker()
+{
+ clear();
+}
+
+jsuword
+Tracker::getPageBase(const void* v) const
+{
+ return jsuword(v) & ~jsuword(NJ_PAGE_SIZE-1);
+}
+
+struct Tracker::Page*
+Tracker::findPage(const void* v) const
+{
+ jsuword base = getPageBase(v);
+ struct Tracker::Page* p = pagelist;
+ while (p) {
+ if (p->base == base) {
+ return p;
+ }
+ p = p->next;
+ }
+ return 0;
+}
+
+struct Tracker::Page*
+Tracker::addPage(const void* v) {
+ jsuword base = getPageBase(v);
+ struct Tracker::Page* p = (struct Tracker::Page*)
+ GC::Alloc(sizeof(*p) - sizeof(p->map) + (NJ_PAGE_SIZE >> 2) * sizeof(LIns*));
+ p->base = base;
+ p->next = pagelist;
+ pagelist = p;
+ return p;
+}
+
+void
+Tracker::clear()
+{
+ while (pagelist) {
+ Page* p = pagelist;
+ pagelist = pagelist->next;
+ GC::Free(p);
+ }
+}
+
+bool
+Tracker::has(const void *v) const
+{
+ return get(v) != NULL;
+}
+
+#if defined NANOJIT_64BIT
+#define PAGEMASK 0x7ff
+#else
+#define PAGEMASK 0xfff
+#endif
+
+LIns*
+Tracker::get(const void* v) const
+{
+ struct Tracker::Page* p = findPage(v);
+ if (!p)
+ return NULL;
+ return p->map[(jsuword(v) & PAGEMASK) >> 2];
+}
+
+void
+Tracker::set(const void* v, LIns* i)
+{
+ struct Tracker::Page* p = findPage(v);
+ if (!p)
+ p = addPage(v);
+ p->map[(jsuword(v) & PAGEMASK) >> 2] = i;
+}
+
+static inline bool isNumber(jsval v)
+{
+ return JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v);
+}
+
+static inline jsdouble asNumber(jsval v)
+{
+ JS_ASSERT(isNumber(v));
+ if (JSVAL_IS_DOUBLE(v))
+ return *JSVAL_TO_DOUBLE(v);
+ return (jsdouble)JSVAL_TO_INT(v);
+}
+
+static inline bool isInt32(jsval v)
+{
+ if (!isNumber(v))
+ return false;
+ jsdouble d = asNumber(v);
+ jsint i;
+ return JSDOUBLE_IS_INT(d, i);
+}
+
+/* Return JSVAL_DOUBLE for all numbers (int and double) and the tag otherwise. */
+static inline uint8 getPromotedType(jsval v)
+{
+ return JSVAL_IS_INT(v) ? JSVAL_DOUBLE : uint8(JSVAL_TAG(v));
+}
+
+/* Return JSVAL_INT for all whole numbers that fit into signed 32-bit and the tag otherwise. */
+static inline uint8 getCoercedType(jsval v)
+{
+ return isInt32(v) ? JSVAL_INT : (uint8) JSVAL_TAG(v);
+}
+
+/* Tell the oracle that a certain global variable should not be demoted. */
+void
+Oracle::markGlobalSlotUndemotable(JSScript* script, unsigned slot)
+{
+ _dontDemote.set(&gc, (slot % ORACLE_SIZE));
+}
+
+/* Consult with the oracle whether we shouldn't demote a certain global variable. */
+bool
+Oracle::isGlobalSlotUndemotable(JSScript* script, unsigned slot) const
+{
+ return _dontDemote.get(slot % ORACLE_SIZE);
+}
+
+/* Tell the oracle that a certain slot at a certain bytecode location should not be demoted. */
+void
+Oracle::markStackSlotUndemotable(JSScript* script, jsbytecode* ip, unsigned slot)
+{
+ uint32 hash = uint32(intptr_t(ip)) + (slot << 5);
+ hash %= ORACLE_SIZE;
+ _dontDemote.set(&gc, hash);
+}
+
+/* Consult with the oracle whether we shouldn't demote a certain slot. */
+bool
+Oracle::isStackSlotUndemotable(JSScript* script, jsbytecode* ip, unsigned slot) const
+{
+ uint32 hash = uint32(intptr_t(ip)) + (slot << 5);
+ hash %= ORACLE_SIZE;
+ return _dontDemote.get(hash);
+}
+
+/* Clear the oracle. */
+void
+Oracle::clear()
+{
+ _dontDemote.reset();
+}
+
+#if defined(NJ_SOFTFLOAT)
+JS_DEFINE_CALLINFO_1(static, DOUBLE, i2f, INT32, 1, 1)
+JS_DEFINE_CALLINFO_1(static, DOUBLE, u2f, UINT32, 1, 1)
+#endif
+
+static bool isi2f(LInsp i)
+{
+ if (i->isop(LIR_i2f))
+ return true;
+
+#if defined(NJ_SOFTFLOAT)
+ if (i->isop(LIR_qjoin) &&
+ i->oprnd1()->isop(LIR_call) &&
+ i->oprnd2()->isop(LIR_callh))
+ {
+ if (i->oprnd1()->callInfo() == &i2f_ci)
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+static bool isu2f(LInsp i)
+{
+ if (i->isop(LIR_u2f))
+ return true;
+
+#if defined(NJ_SOFTFLOAT)
+ if (i->isop(LIR_qjoin) &&
+ i->oprnd1()->isop(LIR_call) &&
+ i->oprnd2()->isop(LIR_callh))
+ {
+ if (i->oprnd1()->callInfo() == &u2f_ci)
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+static LInsp iu2fArg(LInsp i)
+{
+#if defined(NJ_SOFTFLOAT)
+ if (i->isop(LIR_qjoin))
+ return i->oprnd1()->arg(0);
+#endif
+
+ return i->oprnd1();
+}
+
+
+static LIns* demote(LirWriter *out, LInsp i)
+{
+ if (i->isCall())
+ return callArgN(i, 0);
+ if (isi2f(i) || isu2f(i))
+ return iu2fArg(i);
+ if (i->isconst())
+ return i;
+ AvmAssert(i->isconstq());
+ double cf = i->constvalf();
+ int32_t ci = cf > 0x7fffffff ? uint32_t(cf) : int32_t(cf);
+ return out->insImm(ci);
+}
+
+static bool isPromoteInt(LIns* i)
+{
+ jsdouble d;
+ return isi2f(i) || i->isconst() ||
+ (i->isconstq() && (d = i->constvalf()) == jsdouble(jsint(d)) && !JSDOUBLE_IS_NEGZERO(d));
+}
+
+static bool isPromoteUint(LIns* i)
+{
+ jsdouble d;
+ return isu2f(i) || i->isconst() ||
+ (i->isconstq() && (d = i->constvalf()) == (jsdouble)(jsuint)d && !JSDOUBLE_IS_NEGZERO(d));
+}
+
+static bool isPromote(LIns* i)
+{
+ return isPromoteInt(i) || isPromoteUint(i);
+}
+
+static bool isconst(LIns* i, int32_t c)
+{
+ return i->isconst() && i->constval() == c;
+}
+
+static bool overflowSafe(LIns* i)
+{
+ LIns* c;
+ return (i->isop(LIR_and) && ((c = i->oprnd2())->isconst()) &&
+ ((c->constval() & 0xc0000000) == 0)) ||
+ (i->isop(LIR_rsh) && ((c = i->oprnd2())->isconst()) &&
+ ((c->constval() > 0)));
+}
+
+#if defined(NJ_SOFTFLOAT)
+/* soft float */
+
+JS_DEFINE_CALLINFO_1(static, DOUBLE, fneg, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, INT32, fcmpeq, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, INT32, fcmplt, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, INT32, fcmple, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, INT32, fcmpgt, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, INT32, fcmpge, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, DOUBLE, fmul, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, DOUBLE, fadd, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, DOUBLE, fdiv, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, DOUBLE, fsub, DOUBLE, DOUBLE, 1, 1)
+
+jsdouble FASTCALL
+fneg(jsdouble x)
+{
+ return -x;
+}
+
+jsdouble FASTCALL
+i2f(int32 i)
+{
+ return i;
+}
+
+jsdouble FASTCALL
+u2f(jsuint u)
+{
+ return u;
+}
+
+int32 FASTCALL
+fcmpeq(jsdouble x, jsdouble y)
+{
+ return x==y;
+}
+
+int32 FASTCALL
+fcmplt(jsdouble x, jsdouble y)
+{
+ return x < y;
+}
+
+int32 FASTCALL
+fcmple(jsdouble x, jsdouble y)
+{
+ return x <= y;
+}
+
+int32 FASTCALL
+fcmpgt(jsdouble x, jsdouble y)
+{
+ return x > y;
+}
+
+int32 FASTCALL
+fcmpge(jsdouble x, jsdouble y)
+{
+ return x >= y;
+}
+
+jsdouble FASTCALL
+fmul(jsdouble x, jsdouble y)
+{
+ return x * y;
+}
+
+jsdouble FASTCALL
+fadd(jsdouble x, jsdouble y)
+{
+ return x + y;
+}
+
+jsdouble FASTCALL
+fdiv(jsdouble x, jsdouble y)
+{
+ return x / y;
+}
+
+jsdouble FASTCALL
+fsub(jsdouble x, jsdouble y)
+{
+ return x - y;
+}
+
+class SoftFloatFilter: public LirWriter
+{
+public:
+ SoftFloatFilter(LirWriter* out):
+ LirWriter(out)
+ {
+ }
+
+ LInsp quadCall(const CallInfo *ci, LInsp args[]) {
+ LInsp qlo, qhi;
+
+ qlo = out->insCall(ci, args);
+ qhi = out->ins1(LIR_callh, qlo);
+ return out->qjoin(qlo, qhi);
+ }
+
+ LInsp ins1(LOpcode v, LInsp s0)
+ {
+ if (v == LIR_fneg)
+ return quadCall(&fneg_ci, &s0);
+
+ if (v == LIR_i2f)
+ return quadCall(&i2f_ci, &s0);
+
+ if (v == LIR_u2f)
+ return quadCall(&u2f_ci, &s0);
+
+ return out->ins1(v, s0);
+ }
+
+ LInsp ins2(LOpcode v, LInsp s0, LInsp s1)
+ {
+ LInsp args[2];
+ LInsp bv;
+
+ // change the numeric value and order of these LIR opcodes and die
+ if (LIR_fadd <= v && v <= LIR_fdiv) {
+ static const CallInfo *fmap[] = { &fadd_ci, &fsub_ci, &fmul_ci, &fdiv_ci };
+
+ args[0] = s1;
+ args[1] = s0;
+
+ return quadCall(fmap[v - LIR_fadd], args);
+ }
+
+ if (LIR_feq <= v && v <= LIR_fge) {
+ static const CallInfo *fmap[] = { &fcmpeq_ci, &fcmplt_ci, &fcmpgt_ci, &fcmple_ci, &fcmpge_ci };
+
+ args[0] = s1;
+ args[1] = s0;
+
+ bv = out->insCall(fmap[v - LIR_feq], args);
+ return out->ins2(LIR_eq, bv, out->insImm(1));
+ }
+
+ return out->ins2(v, s0, s1);
+ }
+
+ LInsp insCall(const CallInfo *ci, LInsp args[])
+ {
+ // if the return type is ARGSIZE_F, we have
+ // to do a quadCall ( qjoin(call,callh) )
+ if ((ci->_argtypes & 3) == ARGSIZE_F)
+ return quadCall(ci, args);
+
+ return out->insCall(ci, args);
+ }
+};
+
+#endif // NJ_SOFTFLOAT
+
+class FuncFilter: public LirWriter
+{
+public:
+ FuncFilter(LirWriter* out):
+ LirWriter(out)
+ {
+ }
+
+ LInsp ins2(LOpcode v, LInsp s0, LInsp s1)
+ {
+ if (s0 == s1 && v == LIR_feq) {
+ if (isPromote(s0)) {
+ // double(int) and double(uint) cannot be nan
+ return insImm(1);
+ }
+ if (s0->isop(LIR_fmul) || s0->isop(LIR_fsub) || s0->isop(LIR_fadd)) {
+ LInsp lhs = s0->oprnd1();
+ LInsp rhs = s0->oprnd2();
+ if (isPromote(lhs) && isPromote(rhs)) {
+ // add/sub/mul promoted ints can't be nan
+ return insImm(1);
+ }
+ }
+ } else if (LIR_feq <= v && v <= LIR_fge) {
+ if (isPromoteInt(s0) && isPromoteInt(s1)) {
+ // demote fcmp to cmp
+ v = LOpcode(v + (LIR_eq - LIR_feq));
+ return out->ins2(v, demote(out, s0), demote(out, s1));
+ } else if (isPromoteUint(s0) && isPromoteUint(s1)) {
+ // uint compare
+ v = LOpcode(v + (LIR_eq - LIR_feq));
+ if (v != LIR_eq)
+ v = LOpcode(v + (LIR_ult - LIR_lt)); // cmp -> ucmp
+ return out->ins2(v, demote(out, s0), demote(out, s1));
+ }
+ } else if (v == LIR_or &&
+ s0->isop(LIR_lsh) && isconst(s0->oprnd2(), 16) &&
+ s1->isop(LIR_and) && isconst(s1->oprnd2(), 0xffff)) {
+ LIns* msw = s0->oprnd1();
+ LIns* lsw = s1->oprnd1();
+ LIns* x;
+ LIns* y;
+ if (lsw->isop(LIR_add) &&
+ lsw->oprnd1()->isop(LIR_and) &&
+ lsw->oprnd2()->isop(LIR_and) &&
+ isconst(lsw->oprnd1()->oprnd2(), 0xffff) &&
+ isconst(lsw->oprnd2()->oprnd2(), 0xffff) &&
+ msw->isop(LIR_add) &&
+ msw->oprnd1()->isop(LIR_add) &&
+ msw->oprnd2()->isop(LIR_rsh) &&
+ msw->oprnd1()->oprnd1()->isop(LIR_rsh) &&
+ msw->oprnd1()->oprnd2()->isop(LIR_rsh) &&
+ isconst(msw->oprnd2()->oprnd2(), 16) &&
+ isconst(msw->oprnd1()->oprnd1()->oprnd2(), 16) &&
+ isconst(msw->oprnd1()->oprnd2()->oprnd2(), 16) &&
+ (x = lsw->oprnd1()->oprnd1()) == msw->oprnd1()->oprnd1()->oprnd1() &&
+ (y = lsw->oprnd2()->oprnd1()) == msw->oprnd1()->oprnd2()->oprnd1() &&
+ lsw == msw->oprnd2()->oprnd1()) {
+ return out->ins2(LIR_add, x, y);
+ }
+ }
+#ifdef NANOJIT_ARM
+ else if (v == LIR_lsh ||
+ v == LIR_rsh ||
+ v == LIR_ush)
+ {
+ // needed on ARM -- arm doesn't mask shifts to 31 like x86 does
+ if (s1->isconst())
+ s1->setimm16(s1->constval() & 31);
+ else
+ s1 = out->ins2(LIR_and, s1, out->insImm(31));
+ return out->ins2(v, s0, s1);
+ }
+#endif
+
+ return out->ins2(v, s0, s1);
+ }
+
+ LInsp insCall(const CallInfo *ci, LInsp args[])
+ {
+ LInsp s0 = args[0];
+ if (ci == &js_DoubleToUint32_ci) {
+ if (s0->isconstq())
+ return out->insImm(js_DoubleToECMAUint32(s0->constvalf()));
+ if (isi2f(s0) || isu2f(s0))
+ return iu2fArg(s0);
+ } else if (ci == &js_DoubleToInt32_ci) {
+ if (s0->isconstq())
+ return out->insImm(js_DoubleToECMAInt32(s0->constvalf()));
+ if (s0->isop(LIR_fadd) || s0->isop(LIR_fsub)) {
+ LInsp lhs = s0->oprnd1();
+ LInsp rhs = s0->oprnd2();
+ if (isPromote(lhs) && isPromote(rhs)) {
+ LOpcode op = LOpcode(s0->opcode() & ~LIR64);
+ return out->ins2(op, demote(out, lhs), demote(out, rhs));
+ }
+ }
+ if (isi2f(s0) || isu2f(s0))
+ return iu2fArg(s0);
+ // XXX ARM -- check for qjoin(call(UnboxDouble),call(UnboxDouble))
+ if (s0->isCall() && s0->callInfo() == &js_UnboxDouble_ci) {
+ LIns* args2[] = { callArgN(s0, 0) };
+ return out->insCall(&js_UnboxInt32_ci, args2);
+ }
+ if (s0->isCall() && s0->callInfo() == &js_StringToNumber_ci) {
+ // callArgN's ordering is that as seen by the builtin, not as stored in args here.
+ // True story!
+ LIns* args2[] = { callArgN(s0, 1), callArgN(s0, 0) };
+ return out->insCall(&js_StringToInt32_ci, args2);
+ }
+ } else if (ci == &js_BoxDouble_ci) {
+ JS_ASSERT(s0->isQuad());
+ if (s0->isop(LIR_i2f)) {
+ LIns* args2[] = { s0->oprnd1(), args[1] };
+ return out->insCall(&js_BoxInt32_ci, args2);
+ }
+ if (s0->isCall() && s0->callInfo() == &js_UnboxDouble_ci)
+ return callArgN(s0, 0);
+ }
+ return out->insCall(ci, args);
+ }
+};
+
+/* In debug mode vpname contains a textual description of the type of the
+ slot during the forall iteration over al slots. */
+#ifdef JS_JIT_SPEW
+#define DEF_VPNAME const char* vpname; unsigned vpnum
+#define SET_VPNAME(name) do { vpname = name; vpnum = 0; } while(0)
+#define INC_VPNUM() do { ++vpnum; } while(0)
+#else
+#define DEF_VPNAME do {} while (0)
+#define vpname ""
+#define vpnum 0
+#define SET_VPNAME(name) ((void)0)
+#define INC_VPNUM() ((void)0)
+#endif
+
+/* Iterate over all interned global variables. */
+#define FORALL_GLOBAL_SLOTS(cx, ngslots, gslots, code) \
+ JS_BEGIN_MACRO \
+ DEF_VPNAME; \
+ JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain); \
+ unsigned n; \
+ jsval* vp; \
+ SET_VPNAME("global"); \
+ for (n = 0; n < ngslots; ++n) { \
+ vp = &STOBJ_GET_SLOT(globalObj, gslots[n]); \
+ { code; } \
+ INC_VPNUM(); \
+ } \
+ JS_END_MACRO
+
+/* Iterate over all slots in the frame, consisting of args, vars, and stack
+ (except for the top-level frame which does not have args or vars. */
+#define FORALL_FRAME_SLOTS(fp, depth, code) \
+ JS_BEGIN_MACRO \
+ jsval* vp; \
+ jsval* vpstop; \
+ if (fp->callee) { \
+ if (depth == 0) { \
+ SET_VPNAME("callee"); \
+ vp = &fp->argv[-2]; \
+ { code; } \
+ SET_VPNAME("this"); \
+ vp = &fp->argv[-1]; \
+ { code; } \
+ SET_VPNAME("argv"); \
+ vp = &fp->argv[0]; vpstop = &fp->argv[fp->fun->nargs]; \
+ while (vp < vpstop) { code; ++vp; INC_VPNUM(); } \
+ } \
+ SET_VPNAME("vars"); \
+ vp = fp->slots; vpstop = &fp->slots[fp->script->nfixed]; \
+ while (vp < vpstop) { code; ++vp; INC_VPNUM(); } \
+ } \
+ SET_VPNAME("stack"); \
+ vp = StackBase(fp); vpstop = fp->regs->sp; \
+ while (vp < vpstop) { code; ++vp; INC_VPNUM(); } \
+ if (fsp < fspstop - 1) { \
+ JSStackFrame* fp2 = fsp[1]; \
+ int missing = fp2->fun->nargs - fp2->argc; \
+ if (missing > 0) { \
+ SET_VPNAME("missing"); \
+ vp = fp->regs->sp; \
+ vpstop = vp + missing; \
+ while (vp < vpstop) { code; ++vp; INC_VPNUM(); } \
+ } \
+ } \
+ JS_END_MACRO
+
+/* Iterate over all slots in each pending frame. */
+#define FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth, code) \
+ JS_BEGIN_MACRO \
+ DEF_VPNAME; \
+ unsigned n; \
+ JSStackFrame* currentFrame = cx->fp; \
+ JSStackFrame* entryFrame; \
+ JSStackFrame* fp = currentFrame; \
+ for (n = 0; n < callDepth; ++n) { fp = fp->down; } \
+ entryFrame = fp; \
+ unsigned frames = callDepth+1; \
+ JSStackFrame** fstack = \
+ (JSStackFrame**) alloca(frames * sizeof (JSStackFrame*)); \
+ JSStackFrame** fspstop = &fstack[frames]; \
+ JSStackFrame** fsp = fspstop-1; \
+ fp = currentFrame; \
+ for (;; fp = fp->down) { *fsp-- = fp; if (fp == entryFrame) break; } \
+ unsigned depth; \
+ for (depth = 0, fsp = fstack; fsp < fspstop; ++fsp, ++depth) { \
+ fp = *fsp; \
+ FORALL_FRAME_SLOTS(fp, depth, code); \
+ } \
+ JS_END_MACRO
+
+#define FORALL_SLOTS(cx, ngslots, gslots, callDepth, code) \
+ JS_BEGIN_MACRO \
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots, code); \
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth, code); \
+ JS_END_MACRO
+
+/* Calculate the total number of native frame slots we need from this frame
+ all the way back to the entry frame, including the current stack usage. */
+unsigned
+js_NativeStackSlots(JSContext *cx, unsigned callDepth)
+{
+ JSStackFrame* fp = cx->fp;
+ unsigned slots = 0;
+#if defined _DEBUG
+ unsigned int origCallDepth = callDepth;
+#endif
+ for (;;) {
+ unsigned operands = fp->regs->sp - StackBase(fp);
+ slots += operands;
+ if (fp->callee)
+ slots += fp->script->nfixed;
+ if (callDepth-- == 0) {
+ if (fp->callee)
+ slots += 2/*callee,this*/ + fp->fun->nargs;
+#if defined _DEBUG
+ unsigned int m = 0;
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, origCallDepth, m++);
+ JS_ASSERT(m == slots);
+#endif
+ return slots;
+ }
+ JSStackFrame* fp2 = fp;
+ fp = fp->down;
+ int missing = fp2->fun->nargs - fp2->argc;
+ if (missing > 0)
+ slots += missing;
+ }
+ JS_NOT_REACHED("js_NativeStackSlots");
+}
+
+/* Capture the type map for the selected slots of the global object. */
+void
+TypeMap::captureGlobalTypes(JSContext* cx, SlotList& slots)
+{
+ unsigned ngslots = slots.length();
+ uint16* gslots = slots.data();
+ setLength(ngslots);
+ uint8* map = data();
+ uint8* m = map;
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ uint8 type = getCoercedType(*vp);
+ if ((type == JSVAL_INT) && oracle.isGlobalSlotUndemotable(cx->fp->script, gslots[n]))
+ type = JSVAL_DOUBLE;
+ JS_ASSERT(type != JSVAL_BOXED);
+ *m++ = type;
+ );
+}
+
+/* Capture the type map for the currently pending stack frames. */
+void
+TypeMap::captureStackTypes(JSContext* cx, unsigned callDepth)
+{
+ setLength(js_NativeStackSlots(cx, callDepth));
+ uint8* map = data();
+ uint8* m = map;
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
+ uint8 type = getCoercedType(*vp);
+ if ((type == JSVAL_INT) &&
+ oracle.isStackSlotUndemotable(cx->fp->script, cx->fp->regs->pc, unsigned(m - map))) {
+ type = JSVAL_DOUBLE;
+ }
+ debug_only_v(printf("capture %s%d: %d\n", vpname, vpnum, type);)
+ *m++ = type;
+ );
+}
+
+/* Compare this type map to another one and see whether they match. */
+bool
+TypeMap::matches(TypeMap& other) const
+{
+ if (length() != other.length())
+ return false;
+ return !memcmp(data(), other.data(), length());
+}
+
+/* Use the provided storage area to create a new type map that contains the partial type map
+ with the rest of it filled up from the complete type map. */
+static void
+mergeTypeMaps(uint8** partial, unsigned* plength, uint8* complete, unsigned clength, uint8* mem)
+{
+ unsigned l = *plength;
+ JS_ASSERT(l < clength);
+ memcpy(mem, *partial, l * sizeof(uint8));
+ memcpy(mem + l, complete + l, (clength - l) * sizeof(uint8));
+ *partial = mem;
+ *plength = clength;
+}
+
+static void
+js_TrashTree(JSContext* cx, Fragment* f);
+
+TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* _anchor, Fragment* _fragment,
+ TreeInfo* ti, unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap,
+ VMSideExit* innermostNestedGuard, Fragment* outerToBlacklist)
+{
+ JS_ASSERT(!_fragment->vmprivate && ti);
+
+ this->cx = cx;
+ this->traceMonitor = &JS_TRACE_MONITOR(cx);
+ this->globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
+ this->anchor = _anchor;
+ this->fragment = _fragment;
+ this->lirbuf = _fragment->lirbuf;
+ this->treeInfo = ti;
+ this->callDepth = _anchor ? _anchor->calldepth : 0;
+ this->atoms = cx->fp->script->atomMap.vector;
+ this->deepAborted = false;
+ this->applyingArguments = false;
+ this->trashTree = false;
+ this->whichTreeToTrash = _fragment->root;
+ this->global_dslots = this->globalObj->dslots;
+ this->terminate = false;
+ this->outerToBlacklist = outerToBlacklist;
+ this->wasRootFragment = _fragment == _fragment->root;
+
+ debug_only_v(printf("recording starting from %s:%u@%u\n",
+ cx->fp->script->filename,
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp));)
+ debug_only_v(printf("globalObj=%p, shape=%d\n", this->globalObj, OBJ_SHAPE(this->globalObj));)
+
+ lir = lir_buf_writer = new (&gc) LirBufWriter(lirbuf);
+#ifdef DEBUG
+ if (verbose_debug)
+ lir = verbose_filter = new (&gc) VerboseWriter(&gc, lir, lirbuf->names);
+#endif
+#ifdef NJ_SOFTFLOAT
+ lir = float_filter = new (&gc) SoftFloatFilter(lir);
+#endif
+ lir = cse_filter = new (&gc) CseFilter(lir, &gc);
+ lir = expr_filter = new (&gc) ExprFilter(lir);
+ lir = func_filter = new (&gc) FuncFilter(lir);
+ lir->ins0(LIR_start);
+
+ if (!nanojit::AvmCore::config.tree_opt || fragment->root == fragment)
+ lirbuf->state = addName(lir->insParam(0, 0), "state");
+
+ lirbuf->sp = addName(lir->insLoad(LIR_ldp, lirbuf->state, (int)offsetof(InterpState, sp)), "sp");
+ lirbuf->rp = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, rp)), "rp");
+ cx_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, cx)), "cx");
+ gp_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, gp)), "gp");
+ eos_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, eos)), "eos");
+ eor_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, eor)), "eor");
+
+ /* read into registers all values on the stack and all globals we know so far */
+ import(treeInfo, lirbuf->sp, ngslots, callDepth, globalTypeMap, stackTypeMap);
+
+ /* If we are attached to a tree call guard, make sure the guard the inner tree exited from
+ is what we expect it to be. */
+ if (_anchor && _anchor->exitType == NESTED_EXIT) {
+ LIns* nested_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state,
+ offsetof(InterpState, lastTreeExitGuard)),
+ "lastTreeExitGuard");
+ guard(true, lir->ins2(LIR_eq, nested_ins, INS_CONSTPTR(innermostNestedGuard)), NESTED_EXIT);
+ }
+}
+
+TreeInfo::~TreeInfo()
+{
+ UnstableExit* temp;
+
+ while (unstableExits) {
+ temp = unstableExits->next;
+ delete unstableExits;
+ unstableExits = temp;
+ }
+}
+
+TraceRecorder::~TraceRecorder()
+{
+ JS_ASSERT(nextRecorderToAbort == NULL);
+ JS_ASSERT(treeInfo && (fragment || wasDeepAborted()));
+#ifdef DEBUG
+ TraceRecorder* tr = JS_TRACE_MONITOR(cx).abortStack;
+ while (tr != NULL)
+ {
+ JS_ASSERT(this != tr);
+ tr = tr->nextRecorderToAbort;
+ }
+#endif
+ if (fragment) {
+ if (wasRootFragment && !fragment->root->code()) {
+ JS_ASSERT(!fragment->root->vmprivate);
+ delete treeInfo;
+ }
+ if (trashTree)
+ js_TrashTree(cx, whichTreeToTrash);
+ } else if (wasRootFragment) {
+ delete treeInfo;
+ }
+#ifdef DEBUG
+ delete verbose_filter;
+#endif
+ delete cse_filter;
+ delete expr_filter;
+ delete func_filter;
+#ifdef NJ_SOFTFLOAT
+ delete float_filter;
+#endif
+ delete lir_buf_writer;
+}
+
+void TraceRecorder::removeFragmentoReferences()
+{
+ fragment = NULL;
+}
+
+/* Add debug information to a LIR instruction as we emit it. */
+inline LIns*
+TraceRecorder::addName(LIns* ins, const char* name)
+{
+#ifdef DEBUG
+ lirbuf->names->addName(ins, name);
+#endif
+ return ins;
+}
+
+/* Determine the current call depth (starting with the entry frame.) */
+unsigned
+TraceRecorder::getCallDepth() const
+{
+ return callDepth;
+}
+
+/* Determine the offset in the native global frame for a jsval we track */
+ptrdiff_t
+TraceRecorder::nativeGlobalOffset(jsval* p) const
+{
+ JS_ASSERT(isGlobal(p));
+ if (size_t(p - globalObj->fslots) < JS_INITIAL_NSLOTS)
+ return size_t(p - globalObj->fslots) * sizeof(double);
+ return ((p - globalObj->dslots) + JS_INITIAL_NSLOTS) * sizeof(double);
+}
+
+/* Determine whether a value is a global stack slot */
+bool
+TraceRecorder::isGlobal(jsval* p) const
+{
+ return ((size_t(p - globalObj->fslots) < JS_INITIAL_NSLOTS) ||
+ (size_t(p - globalObj->dslots) < (STOBJ_NSLOTS(globalObj) - JS_INITIAL_NSLOTS)));
+}
+
+/* Determine the offset in the native stack for a jsval we track */
+ptrdiff_t
+TraceRecorder::nativeStackOffset(jsval* p) const
+{
+#ifdef DEBUG
+ size_t slow_offset = 0;
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
+ if (vp == p) goto done;
+ slow_offset += sizeof(double)
+ );
+
+ /*
+ * If it's not in a pending frame, it must be on the stack of the current frame above
+ * sp but below fp->slots + script->nslots.
+ */
+ JS_ASSERT(size_t(p - cx->fp->slots) < cx->fp->script->nslots);
+ slow_offset += size_t(p - cx->fp->regs->sp) * sizeof(double);
+
+done:
+#define RETURN(offset) { JS_ASSERT((offset) == slow_offset); return offset; }
+#else
+#define RETURN(offset) { return offset; }
+#endif
+ size_t offset = 0;
+ JSStackFrame* currentFrame = cx->fp;
+ JSStackFrame* entryFrame;
+ JSStackFrame* fp = currentFrame;
+ for (unsigned n = 0; n < callDepth; ++n) { fp = fp->down; }
+ entryFrame = fp;
+ unsigned frames = callDepth+1;
+ JSStackFrame** fstack = (JSStackFrame **)alloca(frames * sizeof (JSStackFrame *));
+ JSStackFrame** fspstop = &fstack[frames];
+ JSStackFrame** fsp = fspstop-1;
+ fp = currentFrame;
+ for (;; fp = fp->down) { *fsp-- = fp; if (fp == entryFrame) break; }
+ for (fsp = fstack; fsp < fspstop; ++fsp) {
+ fp = *fsp;
+ if (fp->callee) {
+ if (fsp == fstack) {
+ if (size_t(p - &fp->argv[-2]) < size_t(2/*callee,this*/ + fp->fun->nargs))
+ RETURN(offset + size_t(p - &fp->argv[-2]) * sizeof(double));
+ offset += (2/*callee,this*/ + fp->fun->nargs) * sizeof(double);
+ }
+ if (size_t(p - &fp->slots[0]) < fp->script->nfixed)
+ RETURN(offset + size_t(p - &fp->slots[0]) * sizeof(double));
+ offset += fp->script->nfixed * sizeof(double);
+ }
+ jsval* spbase = StackBase(fp);
+ if (size_t(p - spbase) < size_t(fp->regs->sp - spbase))
+ RETURN(offset + size_t(p - spbase) * sizeof(double));
+ offset += size_t(fp->regs->sp - spbase) * sizeof(double);
+ if (fsp < fspstop - 1) {
+ JSStackFrame* fp2 = fsp[1];
+ int missing = fp2->fun->nargs - fp2->argc;
+ if (missing > 0) {
+ if (size_t(p - fp->regs->sp) < size_t(missing))
+ RETURN(offset + size_t(p - fp->regs->sp) * sizeof(double));
+ offset += size_t(missing) * sizeof(double);
+ }
+ }
+ }
+
+ /*
+ * If it's not in a pending frame, it must be on the stack of the current frame above
+ * sp but below fp->slots + script->nslots.
+ */
+ JS_ASSERT(size_t(p - currentFrame->slots) < currentFrame->script->nslots);
+ offset += size_t(p - currentFrame->regs->sp) * sizeof(double);
+ RETURN(offset);
+#undef RETURN
+}
+
+/* Track the maximum number of native frame slots we need during
+ execution. */
+void
+TraceRecorder::trackNativeStackUse(unsigned slots)
+{
+ if (slots > treeInfo->maxNativeStackSlots)
+ treeInfo->maxNativeStackSlots = slots;
+}
+
+/* Unbox a jsval into a slot. Slots are wide enough to hold double values directly (instead of
+ storing a pointer to them). We now assert instead of type checking, the caller must ensure the
+ types are compatible. */
+static void
+ValueToNative(JSContext* cx, jsval v, uint8 type, double* slot)
+{
+ unsigned tag = JSVAL_TAG(v);
+ switch (type) {
+ case JSVAL_INT:
+ jsint i;
+ if (JSVAL_IS_INT(v))
+ *(jsint*)slot = JSVAL_TO_INT(v);
+ else if ((tag == JSVAL_DOUBLE) && JSDOUBLE_IS_INT(*JSVAL_TO_DOUBLE(v), i))
+ *(jsint*)slot = i;
+ else
+ JS_ASSERT(JSVAL_IS_INT(v));
+ debug_only_v(printf("int<%d> ", *(jsint*)slot);)
+ return;
+ case JSVAL_DOUBLE:
+ jsdouble d;
+ if (JSVAL_IS_INT(v))
+ d = JSVAL_TO_INT(v);
+ else
+ d = *JSVAL_TO_DOUBLE(v);
+ JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v));
+ *(jsdouble*)slot = d;
+ debug_only_v(printf("double<%g> ", d);)
+ return;
+ case JSVAL_BOOLEAN:
+ JS_ASSERT(tag == JSVAL_BOOLEAN);
+ *(JSBool*)slot = JSVAL_TO_BOOLEAN(v);
+ debug_only_v(printf("boolean<%d> ", *(JSBool*)slot);)
+ return;
+ case JSVAL_STRING:
+ JS_ASSERT(tag == JSVAL_STRING);
+ *(JSString**)slot = JSVAL_TO_STRING(v);
+ debug_only_v(printf("string<%p> ", *(JSString**)slot);)
+ return;
+ default:
+ /* Note: we should never see JSVAL_BOXED in an entry type map. */
+ JS_ASSERT(type == JSVAL_OBJECT);
+ JS_ASSERT(tag == JSVAL_OBJECT);
+ *(JSObject**)slot = JSVAL_TO_OBJECT(v);
+ debug_only_v(printf("object<%p:%s> ", JSVAL_TO_OBJECT(v),
+ JSVAL_IS_NULL(v)
+ ? "null"
+ : STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name);)
+ return;
+ }
+}
+
+/* We maintain an emergency recovery pool of doubles so we can recover safely if a trace runs
+ out of memory (doubles or objects). */
+static jsval
+AllocateDoubleFromRecoveryPool(JSContext* cx)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ JS_ASSERT(tm->recoveryDoublePoolPtr > tm->recoveryDoublePool);
+ return *--tm->recoveryDoublePoolPtr;
+}
+
+static bool
+js_ReplenishRecoveryPool(JSContext* cx, JSTraceMonitor* tm)
+{
+ /* We should not be called with a full pool. */
+ JS_ASSERT((size_t) (tm->recoveryDoublePoolPtr - tm->recoveryDoublePool) <
+ MAX_NATIVE_STACK_SLOTS);
+
+ /*
+ * When the GC runs in js_NewDoubleInRootedValue, it resets
+ * tm->recoveryDoublePoolPtr back to tm->recoveryDoublePool.
+ */
+ JSRuntime* rt = cx->runtime;
+ uintN gcNumber = rt->gcNumber;
+ jsval* ptr = tm->recoveryDoublePoolPtr;
+ while (ptr < tm->recoveryDoublePool + MAX_NATIVE_STACK_SLOTS) {
+ if (!js_NewDoubleInRootedValue(cx, 0.0, ptr))
+ goto oom;
+ if (rt->gcNumber != gcNumber) {
+ JS_ASSERT(tm->recoveryDoublePoolPtr == tm->recoveryDoublePool);
+ ptr = tm->recoveryDoublePool;
+ if (uintN(rt->gcNumber - gcNumber) > uintN(1))
+ goto oom;
+ continue;
+ }
+ ++ptr;
+ }
+ tm->recoveryDoublePoolPtr = ptr;
+ return true;
+
+oom:
+ /*
+ * Already massive GC pressure, no need to hold doubles back.
+ * We won't run any native code anyway.
+ */
+ tm->recoveryDoublePoolPtr = tm->recoveryDoublePool;
+ return false;
+}
+
+/* Box a value from the native stack back into the jsval format. Integers
+ that are too large to fit into a jsval are automatically boxed into
+ heap-allocated doubles. */
+static bool
+NativeToValue(JSContext* cx, jsval& v, uint8 type, double* slot)
+{
+ jsint i;
+ jsdouble d;
+ switch (type) {
+ case JSVAL_BOOLEAN:
+ v = BOOLEAN_TO_JSVAL(*(JSBool*)slot);
+ debug_only_v(printf("boolean<%d> ", *(JSBool*)slot);)
+ break;
+ case JSVAL_INT:
+ i = *(jsint*)slot;
+ debug_only_v(printf("int<%d> ", i);)
+ store_int:
+ if (INT_FITS_IN_JSVAL(i)) {
+ v = INT_TO_JSVAL(i);
+ break;
+ }
+ d = (jsdouble)i;
+ goto store_double;
+ case JSVAL_DOUBLE:
+ d = *slot;
+ debug_only_v(printf("double<%g> ", d);)
+ if (JSDOUBLE_IS_INT(d, i))
+ goto store_int;
+ store_double: {
+ /* Its not safe to trigger the GC here, so use an emergency heap if we are out of
+ double boxes. */
+ if (cx->doubleFreeList) {
+#ifdef DEBUG
+ bool ok =
+#endif
+ js_NewDoubleInRootedValue(cx, d, &v);
+ JS_ASSERT(ok);
+ return true;
+ }
+ v = AllocateDoubleFromRecoveryPool(cx);
+ JS_ASSERT(JSVAL_IS_DOUBLE(v) && *JSVAL_TO_DOUBLE(v) == 0.0);
+ *JSVAL_TO_DOUBLE(v) = d;
+ return true;
+ }
+ case JSVAL_STRING:
+ v = STRING_TO_JSVAL(*(JSString**)slot);
+ JS_ASSERT(JSVAL_TAG(v) == JSVAL_STRING); /* if this fails the pointer was not aligned */
+ debug_only_v(printf("string<%p> ", *(JSString**)slot);)
+ break;
+ case JSVAL_BOXED:
+ v = *(jsval*)slot;
+ debug_only_v(printf("box<%lx> ", v));
+ break;
+ default:
+ JS_ASSERT(type == JSVAL_OBJECT);
+ v = OBJECT_TO_JSVAL(*(JSObject**)slot);
+ JS_ASSERT(JSVAL_TAG(v) == JSVAL_OBJECT); /* if this fails the pointer was not aligned */
+ debug_only_v(printf("object<%p:%s> ", JSVAL_TO_OBJECT(v),
+ JSVAL_IS_NULL(v)
+ ? "null"
+ : STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name);)
+ break;
+ }
+ return true;
+}
+
+/* Attempt to unbox the given list of interned globals onto the native global frame. */
+static void
+BuildNativeGlobalFrame(JSContext* cx, unsigned ngslots, uint16* gslots, uint8* mp, double* np)
+{
+ debug_only_v(printf("global: ");)
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ ValueToNative(cx, *vp, *mp, np + gslots[n]);
+ ++mp;
+ );
+ debug_only_v(printf("\n");)
+}
+
+/* Attempt to unbox the given JS frame onto a native frame. */
+static void
+BuildNativeStackFrame(JSContext* cx, unsigned callDepth, uint8* mp, double* np)
+{
+ debug_only_v(printf("stack: ");)
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
+ debug_only_v(printf("%s%u=", vpname, vpnum);)
+ ValueToNative(cx, *vp, *mp, np);
+ ++mp; ++np;
+ );
+ debug_only_v(printf("\n");)
+}
+
+/* Box the given native frame into a JS frame. This only fails due to a hard error
+ (out of memory for example). */
+static int
+FlushNativeGlobalFrame(JSContext* cx, unsigned ngslots, uint16* gslots, uint8* mp, double* np)
+{
+ uint8* mp_base = mp;
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ if (!NativeToValue(cx, *vp, *mp, np + gslots[n]))
+ return -1;
+ ++mp;
+ );
+ debug_only_v(printf("\n");)
+ return mp - mp_base;
+}
+
+/**
+ * Box the given native stack frame into the virtual machine stack. This fails
+ * only due to a hard error (out of memory for example).
+ *
+ * @param callDepth the distance between the entry frame into our trace and
+ * cx->fp when we make this call. If this is not called as a
+ * result of a nested exit, callDepth is 0.
+ * @param mp pointer to an array of type tags (JSVAL_INT, etc.) that indicate
+ * what the types of the things on the stack are.
+ * @param np pointer to the native stack. We want to copy values from here to
+ * the JS stack as needed.
+ * @param stopFrame if non-null, this frame and everything above it should not
+ * be restored.
+ * @return the number of things we popped off of np.
+ */
+static int
+FlushNativeStackFrame(JSContext* cx, unsigned callDepth, uint8* mp, double* np,
+ JSStackFrame* stopFrame)
+{
+ jsval* stopAt = stopFrame ? &stopFrame->argv[-2] : NULL;
+ uint8* mp_base = mp;
+ /* Root all string and object references first (we don't need to call the GC for this). */
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
+ if (vp == stopAt) goto skip;
+ debug_only_v(printf("%s%u=", vpname, vpnum);)
+ if (!NativeToValue(cx, *vp, *mp, np))
+ return -1;
+ ++mp; ++np
+ );
+skip:
+ // Restore thisp from the now-restored argv[-1] in each pending frame.
+ // Keep in mind that we didn't restore frames at stopFrame and above!
+ // Scope to keep |fp| from leaking into the macros we're using.
+ {
+ unsigned n = callDepth+1; // +1 to make sure we restore the entry frame
+ JSStackFrame* fp = cx->fp;
+ if (stopFrame) {
+ for (; fp != stopFrame; fp = fp->down) {
+ JS_ASSERT(n != 0);
+ --n;
+ }
+ // Skip over stopFrame itself.
+ JS_ASSERT(n != 0);
+ --n;
+ fp = fp->down;
+ }
+ for (; n != 0; fp = fp->down) {
+ --n;
+ if (fp->callee) { // might not have it if the entry frame is global
+ JS_ASSERT(JSVAL_IS_OBJECT(fp->argv[-1]));
+ fp->thisp = JSVAL_TO_OBJECT(fp->argv[-1]);
+ }
+ }
+ }
+ debug_only_v(printf("\n");)
+ return mp - mp_base;
+}
+
+/* Emit load instructions onto the trace that read the initial stack state. */
+void
+TraceRecorder::import(LIns* base, ptrdiff_t offset, jsval* p, uint8& t,
+ const char *prefix, uintN index, JSStackFrame *fp)
+{
+ LIns* ins;
+ if (t == JSVAL_INT) { /* demoted */
+ JS_ASSERT(isInt32(*p));
+ /* Ok, we have a valid demotion attempt pending, so insert an integer
+ read and promote it to double since all arithmetic operations expect
+ to see doubles on entry. The first op to use this slot will emit a
+ f2i cast which will cancel out the i2f we insert here. */
+ ins = lir->insLoadi(base, offset);
+ ins = lir->ins1(LIR_i2f, ins);
+ } else {
+ JS_ASSERT(t == JSVAL_BOXED || isNumber(*p) == (t == JSVAL_DOUBLE));
+ if (t == JSVAL_DOUBLE) {
+ ins = lir->insLoad(LIR_ldq, base, offset);
+ } else if (t == JSVAL_BOOLEAN) {
+ ins = lir->insLoad(LIR_ld, base, offset);
+ } else {
+ ins = lir->insLoad(LIR_ldp, base, offset);
+ }
+ }
+ tracker.set(p, ins);
+#ifdef DEBUG
+ char name[64];
+ JS_ASSERT(strlen(prefix) < 10);
+ void* mark = NULL;
+ jsuword* localNames = NULL;
+ const char* funName = NULL;
+ if (*prefix == 'a' || *prefix == 'v') {
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ if (JS_GET_LOCAL_NAME_COUNT(fp->fun) != 0)
+ localNames = js_GetLocalNameArray(cx, fp->fun, &cx->tempPool);
+ funName = fp->fun->atom ? js_AtomToPrintableString(cx, fp->fun->atom) : "<anonymous>";
+ }
+ if (!strcmp(prefix, "argv")) {
+ if (index < fp->fun->nargs) {
+ JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[index]);
+ JS_snprintf(name, sizeof name, "$%s.%s", funName, js_AtomToPrintableString(cx, atom));
+ } else {
+ JS_snprintf(name, sizeof name, "$%s.<arg%d>", funName, index);
+ }
+ } else if (!strcmp(prefix, "vars")) {
+ JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[fp->fun->nargs + index]);
+ JS_snprintf(name, sizeof name, "$%s.%s", funName, js_AtomToPrintableString(cx, atom));
+ } else {
+ JS_snprintf(name, sizeof name, "$%s%d", prefix, index);
+ }
+
+ if (mark)
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ addName(ins, name);
+
+ static const char* typestr[] = {
+ "object", "int", "double", "3", "string", "5", "boolean", "any"
+ };
+ debug_only_v(printf("import vp=%p name=%s type=%s flags=%d\n",
+ p, name, typestr[t & 7], t >> 3);)
+#endif
+}
+
+void
+TraceRecorder::import(TreeInfo* treeInfo, LIns* sp, unsigned ngslots, unsigned callDepth,
+ uint8* globalTypeMap, uint8* stackTypeMap)
+{
+ /* If we get a partial list that doesn't have all the types (i.e. recording from a side
+ exit that was recorded but we added more global slots later), merge the missing types
+ from the entry type map. This is safe because at the loop edge we verify that we
+ have compatible types for all globals (entry type and loop edge type match). While
+ a different trace of the tree might have had a guard with a different type map for
+ these slots we just filled in here (the guard we continue from didn't know about them),
+ since we didn't take that particular guard the only way we could have ended up here
+ is if that other trace had at its end a compatible type distribution with the entry
+ map. Since thats exactly what we used to fill in the types our current side exit
+ didn't provide, this is always safe to do. */
+ unsigned length;
+ if (ngslots < (length = traceMonitor->globalTypeMap->length()))
+ mergeTypeMaps(&globalTypeMap, &ngslots,
+ traceMonitor->globalTypeMap->data(), length,
+ (uint8*)alloca(sizeof(uint8) * length));
+ JS_ASSERT(ngslots == traceMonitor->globalTypeMap->length());
+
+ /* the first time we compile a tree this will be empty as we add entries lazily */
+ uint16* gslots = traceMonitor->globalSlots->data();
+ uint8* m = globalTypeMap;
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ import(gp_ins, nativeGlobalOffset(vp), vp, *m, vpname, vpnum, NULL);
+ m++;
+ );
+ ptrdiff_t offset = -treeInfo->nativeStackBase;
+ m = stackTypeMap;
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
+ import(sp, offset, vp, *m, vpname, vpnum, fp);
+ m++; offset += sizeof(double);
+ );
+}
+
+/* Lazily import a global slot if we don't already have it in the tracker. */
+bool
+TraceRecorder::lazilyImportGlobalSlot(unsigned slot)
+{
+ if (slot != uint16(slot)) /* we use a table of 16-bit ints, bail out if that's not enough */
+ return false;
+ jsval* vp = &STOBJ_GET_SLOT(globalObj, slot);
+ if (tracker.has(vp))
+ return true; /* we already have it */
+ unsigned index = traceMonitor->globalSlots->length();
+ /* If this the first global we are adding, remember the shape of the global object. */
+ if (index == 0)
+ traceMonitor->globalShape = OBJ_SHAPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain));
+ /* Add the slot to the list of interned global slots. */
+ traceMonitor->globalSlots->add(slot);
+ uint8 type = getCoercedType(*vp);
+ if ((type == JSVAL_INT) && oracle.isGlobalSlotUndemotable(cx->fp->script, slot))
+ type = JSVAL_DOUBLE;
+ traceMonitor->globalTypeMap->add(type);
+ import(gp_ins, slot*sizeof(double), vp, type, "global", index, NULL);
+ return true;
+}
+
+/* Write back a value onto the stack or global frames. */
+LIns*
+TraceRecorder::writeBack(LIns* i, LIns* base, ptrdiff_t offset)
+{
+ /* Sink all type casts targeting the stack into the side exit by simply storing the original
+ (uncasted) value. Each guard generates the side exit map based on the types of the
+ last stores to every stack location, so its safe to not perform them on-trace. */
+ if (isPromoteInt(i))
+ i = ::demote(lir, i);
+ return lir->insStorei(i, base, offset);
+}
+
+/* Update the tracker, then issue a write back store. */
+void
+TraceRecorder::set(jsval* p, LIns* i, bool initializing)
+{
+ JS_ASSERT(initializing || tracker.has(p));
+ tracker.set(p, i);
+ /* If we are writing to this location for the first time, calculate the offset into the
+ native frame manually, otherwise just look up the last load or store associated with
+ the same source address (p) and use the same offset/base. */
+ LIns* x = nativeFrameTracker.get(p);
+ if (!x) {
+ if (isGlobal(p))
+ x = writeBack(i, gp_ins, nativeGlobalOffset(p));
+ else
+ x = writeBack(i, lirbuf->sp, -treeInfo->nativeStackBase + nativeStackOffset(p));
+ nativeFrameTracker.set(p, x);
+ } else {
+#define ASSERT_VALID_CACHE_HIT(base, offset) \
+ JS_ASSERT(base == lirbuf->sp || base == gp_ins); \
+ JS_ASSERT(offset == ((base == lirbuf->sp) \
+ ? -treeInfo->nativeStackBase + nativeStackOffset(p) \
+ : nativeGlobalOffset(p))); \
+
+ if (x->isop(LIR_st) || x->isop(LIR_stq)) {
+ ASSERT_VALID_CACHE_HIT(x->oprnd2(), x->oprnd3()->constval());
+ writeBack(i, x->oprnd2(), x->oprnd3()->constval());
+ } else {
+ JS_ASSERT(x->isop(LIR_sti) || x->isop(LIR_stqi));
+ ASSERT_VALID_CACHE_HIT(x->oprnd2(), x->immdisp());
+ writeBack(i, x->oprnd2(), x->immdisp());
+ }
+ }
+#undef ASSERT_VALID_CACHE_HIT
+}
+
+LIns*
+TraceRecorder::get(jsval* p) const
+{
+ return tracker.get(p);
+}
+
+/* Determine whether the current branch instruction terminates the loop. */
+static bool
+js_IsLoopExit(jsbytecode* pc, jsbytecode* header)
+{
+ switch (*pc) {
+ case JSOP_LT:
+ case JSOP_GT:
+ case JSOP_LE:
+ case JSOP_GE:
+ case JSOP_NE:
+ case JSOP_EQ:
+ /* These ops try to dispatch a JSOP_IFEQ or JSOP_IFNE that follows. */
+ JS_ASSERT(js_CodeSpec[*pc].length == 1);
+ pc++;
+ break;
+
+ default:
+ for (;;) {
+ if (*pc == JSOP_AND || *pc == JSOP_OR)
+ pc += GET_JUMP_OFFSET(pc);
+ else if (*pc == JSOP_ANDX || *pc == JSOP_ORX)
+ pc += GET_JUMPX_OFFSET(pc);
+ else
+ break;
+ }
+ }
+
+ switch (*pc) {
+ case JSOP_IFEQ:
+ case JSOP_IFNE:
+ /*
+ * Forward jumps are usually intra-branch, but for-in loops jump to the
+ * trailing enditer to clean up, so check for that case here.
+ */
+ if (pc[GET_JUMP_OFFSET(pc)] == JSOP_ENDITER)
+ return true;
+ return pc + GET_JUMP_OFFSET(pc) == header;
+
+ case JSOP_IFEQX:
+ case JSOP_IFNEX:
+ if (pc[GET_JUMPX_OFFSET(pc)] == JSOP_ENDITER)
+ return true;
+ return pc + GET_JUMPX_OFFSET(pc) == header;
+
+ default:;
+ }
+ return false;
+}
+
+/* Determine whether the current branch is a loop edge (taken or not taken). */
+static bool
+js_IsLoopEdge(jsbytecode* pc, jsbytecode* header)
+{
+ switch (*pc) {
+ case JSOP_IFEQ:
+ case JSOP_IFNE:
+ return ((pc + GET_JUMP_OFFSET(pc)) == header);
+ case JSOP_IFEQX:
+ case JSOP_IFNEX:
+ return ((pc + GET_JUMPX_OFFSET(pc)) == header);
+ default:
+ JS_ASSERT((*pc == JSOP_AND) || (*pc == JSOP_ANDX) ||
+ (*pc == JSOP_OR) || (*pc == JSOP_ORX));
+ }
+ return false;
+}
+
+/* Promote slots if necessary to match the called tree' type map and report error if thats
+ impossible. */
+bool
+TraceRecorder::adjustCallerTypes(Fragment* f, unsigned* demote_slots, bool& trash)
+{
+ JSTraceMonitor* tm = traceMonitor;
+ uint8* m = tm->globalTypeMap->data();
+ uint16* gslots = traceMonitor->globalSlots->data();
+ unsigned ngslots = traceMonitor->globalSlots->length();
+ uint8* map = ((TreeInfo*)f->vmprivate)->stackTypeMap.data();
+ bool ok = true;
+ trash = false;
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ LIns* i = get(vp);
+ bool isPromote = isPromoteInt(i);
+ if (isPromote && *m == JSVAL_DOUBLE)
+ lir->insStorei(get(vp), gp_ins, nativeGlobalOffset(vp));
+ else if (!isPromote && *m == JSVAL_INT) {
+ oracle.markGlobalSlotUndemotable(cx->fp->script, nativeGlobalOffset(vp)/sizeof(double));
+ trash = true;
+ ok = false;
+ }
+ ++m;
+ );
+ m = map;
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ LIns* i = get(vp);
+ bool isPromote = isPromoteInt(i);
+ if (isPromote && *m == JSVAL_DOUBLE) {
+ lir->insStorei(get(vp), lirbuf->sp,
+ -treeInfo->nativeStackBase + nativeStackOffset(vp));
+ /* Aggressively undo speculation so the inner tree will compile if this fails. */
+ ADD_UNDEMOTE_SLOT(demote_slots, unsigned(m - map));
+ } else if (!isPromote && *m == JSVAL_INT) {
+ debug_only_v(printf("adjusting will fail, %s%d, slot %d\n", vpname, vpnum, m - map);)
+ ok = false;
+ ADD_UNDEMOTE_SLOT(demote_slots, unsigned(m - map));
+ } else if (JSVAL_IS_INT(*vp) && *m == JSVAL_DOUBLE) {
+ /* Aggressively undo speculation so the inner tree will compile if this fails. */
+ ADD_UNDEMOTE_SLOT(demote_slots, unsigned(m - map));
+ }
+ ++m;
+ );
+ /* If this isn't okay, tell the oracle. */
+ if (!ok) {
+ for (unsigned i = 1; i <= NUM_UNDEMOTE_SLOTS(demote_slots); i++)
+ oracle.markStackSlotUndemotable(cx->fp->script, cx->fp->regs->pc, demote_slots[i]);
+ }
+ JS_ASSERT(f == f->root);
+ return ok;
+}
+
+uint8
+TraceRecorder::determineSlotType(jsval* vp) const
+{
+ uint8 m;
+ LIns* i = get(vp);
+ m = isNumber(*vp)
+ ? (isPromoteInt(i) ? JSVAL_INT : JSVAL_DOUBLE)
+ : JSVAL_TAG(*vp);
+ JS_ASSERT((m != JSVAL_INT) || isInt32(*vp));
+ return m;
+}
+
+#define IMACRO_PC_ADJ_BITS 8
+#define SCRIPT_PC_ADJ_BITS (32 - IMACRO_PC_ADJ_BITS)
+
+// The stored imacro_pc_adj byte offset is biased by 1.
+#define IMACRO_PC_ADJ_LIMIT (JS_BIT(IMACRO_PC_ADJ_BITS) - 1)
+#define SCRIPT_PC_ADJ_LIMIT JS_BIT(SCRIPT_PC_ADJ_BITS)
+
+#define IMACRO_PC_ADJ(ip) ((uintptr_t)(ip) >> SCRIPT_PC_ADJ_BITS)
+#define SCRIPT_PC_ADJ(ip) ((ip) & JS_BITMASK(SCRIPT_PC_ADJ_BITS))
+
+#define FI_SCRIPT_PC(fi,fp) ((fp)->script->code + SCRIPT_PC_ADJ((fi).ip_adj))
+
+#define FI_IMACRO_PC(fi,fp) (IMACRO_PC_ADJ((fi).ip_adj) \
+ ? imacro_code[*FI_SCRIPT_PC(fi, fp)] + \
+ IMACRO_PC_ADJ((fi).ip_adj) \
+ : NULL)
+
+#define IMACRO_PC_OK(fp,pc) JS_ASSERT(uintN((pc)-imacro_code[*(fp)->imacpc]) \
+ < JS_BIT(IMACRO_PC_ADJ_BITS))
+#define ENCODE_IP_ADJ(fp,pc) ((fp)->imacpc \
+ ? (IMACRO_PC_OK(fp, pc), \
+ (((pc) - imacro_code[*(fp)->imacpc]) \
+ << SCRIPT_PC_ADJ_BITS) + \
+ (fp)->imacpc - (fp)->script->code) \
+ : (pc) - (fp)->script->code)
+
+#define DECODE_IP_ADJ(ip,fp) (IMACRO_PC_ADJ(ip) \
+ ? (fp)->imacpc = (fp)->script->code + \
+ SCRIPT_PC_ADJ(ip), \
+ (fp)->regs->pc = imacro_code[*(fp)->imacpc] + \
+ IMACRO_PC_ADJ(ip) \
+ : (fp)->regs->pc = (fp)->script->code + (ip))
+
+static jsbytecode* imacro_code[JSOP_LIMIT];
+
+LIns*
+TraceRecorder::snapshot(ExitType exitType)
+{
+ JSStackFrame* fp = cx->fp;
+ JSFrameRegs* regs = fp->regs;
+ jsbytecode* pc = regs->pc;
+ if (exitType == BRANCH_EXIT && js_IsLoopExit(pc, (jsbytecode*)fragment->root->ip))
+ exitType = LOOP_EXIT;
+
+ /* Check for a return-value opcode that needs to restart at the next instruction. */
+ const JSCodeSpec& cs = js_CodeSpec[*pc];
+
+ /* WARNING: don't return before restoring the original pc if (resumeAfter). */
+ bool resumeAfter = (pendingTraceableNative &&
+ JSTN_ERRTYPE(pendingTraceableNative) == FAIL_JSVAL);
+ if (resumeAfter) {
+ JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEXTITER);
+ pc += cs.length;
+ regs->pc = pc;
+ MUST_FLOW_THROUGH("restore_pc");
+ }
+
+ /* Generate the entry map for the (possibly advanced) pc and stash it in the trace. */
+ unsigned stackSlots = js_NativeStackSlots(cx, callDepth);
+
+ /* It's sufficient to track the native stack use here since all stores above the
+ stack watermark defined by guards are killed. */
+ trackNativeStackUse(stackSlots + 1);
+
+ /* Capture the type map into a temporary location. */
+ unsigned ngslots = traceMonitor->globalSlots->length();
+ unsigned typemap_size = (stackSlots + ngslots) * sizeof(uint8);
+ uint8* typemap = (uint8*)alloca(typemap_size);
+ uint8* m = typemap;
+
+ /* Determine the type of a store by looking at the current type of the actual value the
+ interpreter is using. For numbers we have to check what kind of store we used last
+ (integer or double) to figure out what the side exit show reflect in its typemap. */
+ FORALL_SLOTS(cx, ngslots, traceMonitor->globalSlots->data(), callDepth,
+ *m++ = determineSlotType(vp);
+ );
+ JS_ASSERT(unsigned(m - typemap) == ngslots + stackSlots);
+
+ /* If we are capturing the stack state on a specific instruction, the value on or near
+ the top of the stack is a boxed value. Either pc[-cs.length] is JSOP_NEXTITER and we
+ want one below top of stack, or else it's JSOP_CALL and we want top of stack. */
+ if (resumeAfter) {
+ m[(pc[-cs.length] == JSOP_NEXTITER) ? -2 : -1] = JSVAL_BOXED;
+
+ /* Now restore the the original pc (after which early returns are ok). */
+ MUST_FLOW_LABEL(restore_pc);
+ regs->pc = pc - cs.length;
+ } else {
+ /* If we take a snapshot on a goto, advance to the target address. This avoids inner
+ trees returning on a break goto, which the outer recorder then would confuse with
+ a break in the outer tree. */
+ if (*pc == JSOP_GOTO)
+ pc += GET_JUMP_OFFSET(pc);
+ else if (*pc == JSOP_GOTOX)
+ pc += GET_JUMPX_OFFSET(pc);
+ }
+ intptr_t ip_adj = ENCODE_IP_ADJ(fp, pc);
+
+ /* Check if we already have a matching side exit. If so use that side exit structure,
+ otherwise we have to create our own. */
+ VMSideExit** exits = treeInfo->sideExits.data();
+ unsigned nexits = treeInfo->sideExits.length();
+ if (exitType == LOOP_EXIT) {
+ for (unsigned n = 0; n < nexits; ++n) {
+ VMSideExit* e = exits[n];
+ if (e->ip_adj == ip_adj &&
+ !memcmp(getTypeMap(exits[n]), typemap, typemap_size)) {
+ LIns* data = lir_buf_writer->skip(sizeof(GuardRecord));
+ GuardRecord* rec = (GuardRecord*)data->payload();
+ /* setup guard record structure with shared side exit */
+ memset(rec, 0, sizeof(GuardRecord));
+ VMSideExit* exit = exits[n];
+ rec->exit = exit;
+ exit->addGuard(rec);
+ AUDIT(mergedLoopExits);
+ return data;
+ }
+ }
+ }
+
+ /* We couldn't find a matching side exit, so create our own side exit structure. */
+ LIns* data = lir_buf_writer->skip(sizeof(GuardRecord) +
+ sizeof(VMSideExit) +
+ (stackSlots + ngslots) * sizeof(uint8));
+ GuardRecord* rec = (GuardRecord*)data->payload();
+ VMSideExit* exit = (VMSideExit*)(rec + 1);
+ /* setup guard record structure */
+ memset(rec, 0, sizeof(GuardRecord));
+ rec->exit = exit;
+ /* setup side exit structure */
+ memset(exit, 0, sizeof(VMSideExit));
+ exit->from = fragment;
+ exit->calldepth = callDepth;
+ exit->numGlobalSlots = ngslots;
+ exit->numStackSlots = stackSlots;
+ exit->numStackSlotsBelowCurrentFrame = cx->fp->callee
+ ? nativeStackOffset(&cx->fp->argv[-2])/sizeof(double)
+ : 0;
+ exit->exitType = exitType;
+ exit->addGuard(rec);
+ exit->ip_adj = ip_adj;
+ exit->sp_adj = (stackSlots * sizeof(double)) - treeInfo->nativeStackBase;
+ exit->rp_adj = exit->calldepth * sizeof(FrameInfo);
+ memcpy(getTypeMap(exit), typemap, typemap_size);
+
+ /* BIG FAT WARNING: If compilation fails, we currently don't reset the lirbuf so its safe
+ to keep references to the side exits here. If we ever start rewinding those lirbufs,
+ we have to make sure we purge the side exits that then no longer will be in valid
+ memory. */
+ if (exitType == LOOP_EXIT)
+ treeInfo->sideExits.add(exit);
+ return data;
+}
+
+/* Emit a guard for condition (cond), expecting to evaluate to boolean result (expected)
+ and using the supplied side exit if the conditon doesn't hold. */
+LIns*
+TraceRecorder::guard(bool expected, LIns* cond, LIns* exit)
+{
+ return lir->insGuard(expected ? LIR_xf : LIR_xt, cond, exit);
+}
+
+/* Emit a guard for condition (cond), expecting to evaluate to boolean result (expected)
+ and generate a side exit with type exitType to jump to if the condition does not hold. */
+LIns*
+TraceRecorder::guard(bool expected, LIns* cond, ExitType exitType)
+{
+ return guard(expected, cond, snapshot(exitType));
+}
+
+/* Try to match the type of a slot to type t. checkType is used to verify that the type of
+ * values flowing into the loop edge is compatible with the type we expect in the loop header.
+ *
+ * @param v Value.
+ * @param t Typemap entry for value.
+ * @param stage_val Outparam for set() address.
+ * @param stage_ins Outparam for set() instruction.
+ * @param stage_count Outparam for set() buffer count.
+ * @return True if types are compatible, false otherwise.
+ */
+bool
+TraceRecorder::checkType(jsval& v, uint8 t, jsval*& stage_val, LIns*& stage_ins,
+ unsigned& stage_count)
+{
+ if (t == JSVAL_INT) { /* initially all whole numbers cause the slot to be demoted */
+ debug_only_v(printf("checkType(tag=1, t=%d, isnum=%d, i2f=%d) stage_count=%d\n",
+ t,
+ isNumber(v),
+ isPromoteInt(get(&v)),
+ stage_count);)
+ if (!isNumber(v))
+ return false; /* not a number? type mismatch */
+ LIns* i = get(&v);
+ /* This is always a type mismatch, we can't close a double to an int. */
+ if (!isPromoteInt(i))
+ return false;
+ /* Looks good, slot is an int32, the last instruction should be promotable. */
+ JS_ASSERT(isInt32(v) && isPromoteInt(i));
+ /* Overwrite the value in this slot with the argument promoted back to an integer. */
+ stage_val = &v;
+ stage_ins = f2i(i);
+ stage_count++;
+ return true;
+ }
+ if (t == JSVAL_DOUBLE) {
+ debug_only_v(printf("checkType(tag=2, t=%d, isnum=%d, promote=%d) stage_count=%d\n",
+ t,
+ isNumber(v),
+ isPromoteInt(get(&v)),
+ stage_count);)
+ if (!isNumber(v))
+ return false; /* not a number? type mismatch */
+ LIns* i = get(&v);
+ /* We sink i2f conversions into the side exit, but at the loop edge we have to make
+ sure we promote back to double if at loop entry we want a double. */
+ if (isPromoteInt(i)) {
+ stage_val = &v;
+ stage_ins = lir->ins1(LIR_i2f, i);
+ stage_count++;
+ }
+ return true;
+ }
+ /* for non-number types we expect a precise match of the type */
+#ifdef DEBUG
+ if (JSVAL_TAG(v) != t) {
+ debug_only_v(printf("Type mismatch: val %c, map %c ", typeChar[JSVAL_TAG(v)],
+ typeChar[t]);)
+ }
+#endif
+ debug_only_v(printf("checkType(tag=%d, t=%d) stage_count=%d\n",
+ (int) JSVAL_TAG(v), t, stage_count);)
+ return JSVAL_TAG(v) == t;
+}
+
+/**
+ * Make sure that the current values in the given stack frame and all stack frames
+ * up and including entryFrame are type-compatible with the entry map.
+ *
+ * @param root_peer First fragment in peer list.
+ * @param stable_peer Outparam for first type stable peer.
+ * @param trash Whether to trash the tree (demotion).
+ * @param demotes Array to store demotable stack slots.
+ * @return True if type stable, false otherwise.
+ */
+bool
+TraceRecorder::deduceTypeStability(Fragment* root_peer, Fragment** stable_peer, unsigned* demotes)
+{
+ uint8* m;
+ uint8* typemap;
+ unsigned ngslots = traceMonitor->globalSlots->length();
+ uint16* gslots = traceMonitor->globalSlots->data();
+ JS_ASSERT(traceMonitor->globalTypeMap->length() == ngslots);
+
+ if (stable_peer)
+ *stable_peer = NULL;
+
+ CLEAR_UNDEMOTE_SLOTLIST(demotes);
+
+ /*
+ * Rather than calculate all of this stuff twice, it gets cached locally. The "stage" buffers
+ * are for calls to set() that will change the exit types.
+ */
+ bool success;
+ bool unstable_from_undemotes;
+ unsigned stage_count;
+ jsval** stage_vals = (jsval**)alloca(sizeof(jsval*) * (ngslots + treeInfo->stackTypeMap.length()));
+ LIns** stage_ins = (LIns**)alloca(sizeof(LIns*) * (ngslots + treeInfo->stackTypeMap.length()));
+
+ /* First run through and see if we can close ourselves - best case! */
+ stage_count = 0;
+ success = false;
+ unstable_from_undemotes = false;
+
+ debug_only_v(printf("Checking type stability against self=%p\n", fragment);)
+
+ m = typemap = traceMonitor->globalTypeMap->data();
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ debug_only_v(printf("%s%d ", vpname, vpnum);)
+ if (!checkType(*vp, *m, stage_vals[stage_count], stage_ins[stage_count], stage_count)) {
+ /* If the failure was an int->double, tell the oracle. */
+ if (*m == JSVAL_INT && isNumber(*vp) && !isPromoteInt(get(vp)))
+ oracle.markGlobalSlotUndemotable(cx->fp->script, gslots[n]);
+ trashTree = true;
+ goto checktype_fail_1;
+ }
+ ++m;
+ );
+ m = typemap = treeInfo->stackTypeMap.data();
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ debug_only_v(printf("%s%d ", vpname, vpnum);)
+ if (!checkType(*vp, *m, stage_vals[stage_count], stage_ins[stage_count], stage_count)) {
+ if (*m == JSVAL_INT && isNumber(*vp) && !isPromoteInt(get(vp)))
+ ADD_UNDEMOTE_SLOT(demotes, unsigned(m - typemap));
+ else
+ goto checktype_fail_1;
+ }
+ ++m;
+ );
+
+ /*
+ * If there's an exit that's unstable because of undemotable slots, we want to search for
+ * peers just in case we can make a connection.
+ */
+ if (NUM_UNDEMOTE_SLOTS(demotes))
+ unstable_from_undemotes = true;
+ else
+ success = true;
+
+checktype_fail_1:
+ /* If we got a success and we don't need to recompile, we should just close here. */
+ if (success) {
+ for (unsigned i = 0; i < stage_count; i++)
+ set(stage_vals[i], stage_ins[i]);
+ return true;
+ /* If we need to trash, don't bother checking peers. */
+ } else if (trashTree) {
+ return false;
+ } else {
+ CLEAR_UNDEMOTE_SLOTLIST(demotes);
+ }
+
+ /* At this point the tree is about to be incomplete, so let's see if we can connect to any
+ * peer fragment that is type stable.
+ */
+ Fragment* f;
+ TreeInfo* ti;
+ for (f = root_peer; f != NULL; f = f->peer) {
+ debug_only_v(printf("Checking type stability against peer=%p (code=%p)\n", f, f->code());)
+ if (!f->code())
+ continue;
+ ti = (TreeInfo*)f->vmprivate;
+ /* Don't allow varying stack depths */
+ if (ti->stackTypeMap.length() != treeInfo->stackTypeMap.length())
+ continue;
+ stage_count = 0;
+ success = false;
+ m = ti->stackTypeMap.data();
+
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ if (!checkType(*vp, *m, stage_vals[stage_count], stage_ins[stage_count], stage_count))
+ goto checktype_fail_2;
+ ++m;
+ );
+
+ success = true;
+
+checktype_fail_2:
+ if (success) {
+ /*
+ * There was a successful match. We don't care about restoring the saved staging, but
+ * we do need to clear the original undemote list.
+ */
+ for (unsigned i = 0; i < stage_count; i++)
+ set(stage_vals[i], stage_ins[i]);
+ if (stable_peer)
+ *stable_peer = f;
+ return false;
+ }
+ }
+
+ JS_ASSERT(NUM_UNDEMOTE_SLOTS(demotes) == 0);
+
+ /*
+ * If this is a loop trace and it would be stable with demotions, build an undemote list
+ * and return true. Our caller should sniff this and trash the tree, recording a new one
+ * that will assumedly stabilize.
+ */
+ if (unstable_from_undemotes && fragment->kind == LoopTrace) {
+ typemap = m = treeInfo->stackTypeMap.data();
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ if (*m == JSVAL_INT) {
+ JS_ASSERT(isNumber(*vp));
+ if (!isPromoteInt(get(vp)))
+ ADD_UNDEMOTE_SLOT(demotes, unsigned(m - typemap));
+ } else if (*m == JSVAL_DOUBLE) {
+ JS_ASSERT(isNumber(*vp));
+ ADD_UNDEMOTE_SLOT(demotes, unsigned(m - typemap));
+ } else {
+ JS_ASSERT(*m == JSVAL_TAG(*vp));
+ }
+ m++;
+ );
+ return true;
+ }
+
+ return false;
+}
+
+/* Check whether the current pc location is the loop header of the loop this recorder records. */
+bool
+TraceRecorder::isLoopHeader(JSContext* cx) const
+{
+ return cx->fp->regs->pc == fragment->root->ip;
+}
+
+/* Compile the current fragment. */
+void
+TraceRecorder::compile(Fragmento* fragmento)
+{
+ if (treeInfo->maxNativeStackSlots >= MAX_NATIVE_STACK_SLOTS) {
+ debug_only_v(printf("Trace rejected: excessive stack use.\n"));
+ js_BlacklistPC(fragmento, fragment);
+ return;
+ }
+ ++treeInfo->branchCount;
+ if (lirbuf->outOmem()) {
+ fragmento->assm()->setError(nanojit::OutOMem);
+ return;
+ }
+ ::compile(fragmento->assm(), fragment);
+ if (anchor)
+ fragmento->assm()->patch(anchor);
+ if (fragmento->assm()->error() != nanojit::None)
+ return;
+ JS_ASSERT(fragment->code());
+ JS_ASSERT(!fragment->vmprivate);
+ if (fragment == fragment->root)
+ fragment->vmprivate = treeInfo;
+ /* :TODO: windows support */
+#if defined DEBUG && !defined WIN32
+ const char* filename = cx->fp->script->filename;
+ char* label = (char*)malloc((filename ? strlen(filename) : 7) + 16);
+ sprintf(label, "%s:%u", filename ? filename : "<stdin>",
+ js_FramePCToLineNumber(cx, cx->fp));
+ fragmento->labels->add(fragment, sizeof(Fragment), 0, label);
+ free(label);
+#endif
+ AUDIT(traceCompleted);
+}
+
+static bool
+js_JoinPeersIfCompatible(Fragmento* frago, Fragment* stableFrag, TreeInfo* stableTree,
+ VMSideExit* exit)
+{
+ JS_ASSERT(exit->numStackSlots == stableTree->stackTypeMap.length());
+ /* Must have a matching type unstable exit. */
+ if (memcmp(getTypeMap(exit) + exit->numGlobalSlots,
+ stableTree->stackTypeMap.data(),
+ stableTree->stackTypeMap.length()) != 0) {
+ return false;
+ }
+
+ exit->target = stableFrag;
+ frago->assm()->patch(exit);
+
+ stableTree->dependentTrees.addUnique(exit->from->root);
+
+ return true;
+}
+
+/* Complete and compile a trace and link it to the existing tree if appropriate. */
+bool
+TraceRecorder::closeLoop(Fragmento* fragmento, bool& demote, unsigned *demotes)
+{
+ bool stable;
+ LIns* exitIns;
+ Fragment* peer;
+ VMSideExit* exit;
+ Fragment* peer_root;
+
+ demote = false;
+
+ exitIns = snapshot(UNSTABLE_LOOP_EXIT);
+ exit = (VMSideExit*)((GuardRecord*)exitIns->payload())->exit;
+
+ if (callDepth != 0) {
+ debug_only_v(printf("Stack depth mismatch, possible recursion\n");)
+ js_BlacklistPC(fragmento, fragment);
+ trashTree = true;
+ return false;
+ }
+
+ JS_ASSERT(exit->numStackSlots == treeInfo->stackTypeMap.length());
+
+ peer_root = fragmento->getLoop(fragment->root->ip);
+ JS_ASSERT(peer_root != NULL);
+ stable = deduceTypeStability(peer_root, &peer, demotes);
+
+ #if DEBUG
+ if (!stable || NUM_UNDEMOTE_SLOTS(demotes))
+ AUDIT(unstableLoopVariable);
+ #endif
+
+ if (trashTree) {
+ debug_only_v(printf("Trashing tree from type instability.\n");)
+ return false;
+ }
+
+ if (stable && NUM_UNDEMOTE_SLOTS(demotes)) {
+ JS_ASSERT(fragment->kind == LoopTrace);
+ demote = true;
+ return false;
+ }
+
+ if (!stable) {
+ fragment->lastIns = lir->insGuard(LIR_x, lir->insImm(1), exitIns);
+
+ /*
+ * If we didn't find a type stable peer, we compile the loop anyway and
+ * hope it becomes stable later.
+ */
+ if (!peer) {
+ /*
+ * If such a fragment does not exist, let's compile the loop ahead
+ * of time anyway. Later, if the loop becomes type stable, we will
+ * connect these two fragments together.
+ */
+ debug_only_v(printf("Trace has unstable loop variable with no stable peer, "
+ "compiling anyway.\n");)
+ UnstableExit* uexit = new UnstableExit;
+ uexit->fragment = fragment;
+ uexit->exit = exit;
+ uexit->next = treeInfo->unstableExits;
+ treeInfo->unstableExits = uexit;
+
+ /*
+ * If we walked out of a loop, this exit is wrong. We need to back
+ * up to the if operation.
+ */
+ if (walkedOutOfLoop())
+ exit->ip_adj = terminate_ip_adj;
+
+ /* If we were trying to stabilize a promotable tree, trash it. */
+ if (promotedPeer)
+ js_TrashTree(cx, promotedPeer);
+ } else {
+ JS_ASSERT(peer->code());
+ exit->target = peer;
+ debug_only_v(printf("Joining type-unstable trace to target fragment %p.\n", peer);)
+ stable = true;
+ ((TreeInfo*)peer->vmprivate)->dependentTrees.addUnique(fragment->root);
+ }
+
+ compile(fragmento);
+ } else {
+ exit->target = fragment->root;
+#if defined(JS_HAS_OPERATION_COUNT) && !JS_HAS_OPERATION_COUNT
+ exit->exitType = TIMEOUT_EXIT;
+ guard(false,
+ lir->ins_eq0(lir->insLoadi(cx_ins,
+ offsetof(JSContext, operationCount))),
+ exitIns);
+#endif
+ fragment->lastIns = lir->insGuard(LIR_loop, lir->insImm(1), exitIns);
+ compile(fragmento);
+ }
+
+ if (fragmento->assm()->error() != nanojit::None)
+ return false;
+
+ joinEdgesToEntry(fragmento, peer_root);
+
+ debug_only_v(printf("recording completed at %s:%u@%u via closeLoop\n",
+ cx->fp->script->filename,
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp));)
+ return true;
+}
+
+void
+TraceRecorder::joinEdgesToEntry(Fragmento* fragmento, Fragment* peer_root)
+{
+ if (fragment->kind == LoopTrace) {
+ TreeInfo* ti;
+ Fragment* peer;
+ uint8* t1, *t2;
+ UnstableExit* uexit, **unext;
+
+ unsigned* demotes = (unsigned*)alloca(treeInfo->stackTypeMap.length() * sizeof(unsigned));
+ for (peer = peer_root; peer != NULL; peer = peer->peer) {
+ if (!peer->code())
+ continue;
+ ti = (TreeInfo*)peer->vmprivate;
+ uexit = ti->unstableExits;
+ unext = &ti->unstableExits;
+ while (uexit != NULL) {
+ bool remove = js_JoinPeersIfCompatible(fragmento, fragment, treeInfo, uexit->exit);
+ JS_ASSERT(!remove || fragment != peer);
+ debug_only_v(if (remove) {
+ printf("Joining type-stable trace to target exit %p->%p.\n",
+ uexit->fragment, uexit->exit); });
+ if (!remove) {
+ /* See if this exit contains mismatch demotions, which imply trashing a tree.
+ This is actually faster than trashing the original tree as soon as the
+ instability is detected, since we could have compiled a fairly stable
+ tree that ran faster with integers. */
+ unsigned count = 0;
+ t1 = treeInfo->stackTypeMap.data();
+ t2 = getTypeMap(uexit->exit) + uexit->exit->numGlobalSlots;
+ for (unsigned i = 0; i < uexit->exit->numStackSlots; i++) {
+ if (t2[i] == JSVAL_INT && t1[i] == JSVAL_DOUBLE) {
+ demotes[count++] = i;
+ } else if (t2[i] != t1[i]) {
+ count = 0;
+ break;
+ }
+ }
+ if (count) {
+ for (unsigned i = 0; i < count; i++)
+ oracle.markStackSlotUndemotable(cx->fp->script,
+ cx->fp->regs->pc, demotes[i]);
+ js_TrashTree(cx, uexit->fragment->root);
+ break;
+ }
+ }
+ if (remove) {
+ *unext = uexit->next;
+ delete uexit;
+ uexit = *unext;
+ } else {
+ unext = &uexit->next;
+ uexit = uexit->next;
+ }
+ }
+ }
+ }
+
+ debug_only_v(js_DumpPeerStability(fragmento, peer_root->ip);)
+}
+
+/* Emit an always-exit guard and compile the tree (used for break statements. */
+void
+TraceRecorder::endLoop(Fragmento* fragmento)
+{
+ LIns* exitIns = snapshot(LOOP_EXIT);
+
+ if (callDepth != 0) {
+ debug_only_v(printf("Stack depth mismatch, possible recursion\n");)
+ js_BlacklistPC(fragmento, fragment);
+ trashTree = true;
+ return;
+ }
+
+ fragment->lastIns = lir->insGuard(LIR_x, lir->insImm(1), exitIns);
+ compile(fragmento);
+
+ if (fragmento->assm()->error() != nanojit::None)
+ return;
+
+ joinEdgesToEntry(fragmento, fragmento->getLoop(fragment->root->ip));
+
+ debug_only_v(printf("recording completed at %s:%u@%u via endLoop\n",
+ cx->fp->script->filename,
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp));)
+}
+
+/* Emit code to adjust the stack to match the inner tree's stack expectations. */
+void
+TraceRecorder::prepareTreeCall(Fragment* inner)
+{
+ TreeInfo* ti = (TreeInfo*)inner->vmprivate;
+ inner_sp_ins = lirbuf->sp;
+ /* The inner tree expects to be called from the current frame. If the outer tree (this
+ trace) is currently inside a function inlining code (calldepth > 0), we have to advance
+ the native stack pointer such that we match what the inner trace expects to see. We
+ move it back when we come out of the inner tree call. */
+ if (callDepth > 0) {
+ /* Calculate the amount we have to lift the native stack pointer by to compensate for
+ any outer frames that the inner tree doesn't expect but the outer tree has. */
+ ptrdiff_t sp_adj = nativeStackOffset(&cx->fp->argv[-2]);
+ /* Calculate the amount we have to lift the call stack by */
+ ptrdiff_t rp_adj = callDepth * sizeof(FrameInfo);
+ /* Guard that we have enough stack space for the tree we are trying to call on top
+ of the new value for sp. */
+ debug_only_v(printf("sp_adj=%d outer=%d inner=%d\n",
+ sp_adj, treeInfo->nativeStackBase, ti->nativeStackBase));
+ LIns* sp_top = lir->ins2i(LIR_piadd, lirbuf->sp,
+ - treeInfo->nativeStackBase /* rebase sp to beginning of outer tree's stack */
+ + sp_adj /* adjust for stack in outer frame inner tree can't see */
+ + ti->maxNativeStackSlots * sizeof(double)); /* plus the inner tree's stack */
+ guard(true, lir->ins2(LIR_lt, sp_top, eos_ins), OOM_EXIT);
+ /* Guard that we have enough call stack space. */
+ LIns* rp_top = lir->ins2i(LIR_piadd, lirbuf->rp, rp_adj +
+ ti->maxCallDepth * sizeof(FrameInfo));
+ guard(true, lir->ins2(LIR_lt, rp_top, eor_ins), OOM_EXIT);
+ /* We have enough space, so adjust sp and rp to their new level. */
+ lir->insStorei(inner_sp_ins = lir->ins2i(LIR_piadd, lirbuf->sp,
+ - treeInfo->nativeStackBase /* rebase sp to beginning of outer tree's stack */
+ + sp_adj /* adjust for stack in outer frame inner tree can't see */
+ + ti->nativeStackBase), /* plus the inner tree's stack base */
+ lirbuf->state, offsetof(InterpState, sp));
+ lir->insStorei(lir->ins2i(LIR_piadd, lirbuf->rp, rp_adj),
+ lirbuf->state, offsetof(InterpState, rp));
+ }
+}
+
+/* Record a call to an inner tree. */
+void
+TraceRecorder::emitTreeCall(Fragment* inner, VMSideExit* exit)
+{
+ TreeInfo* ti = (TreeInfo*)inner->vmprivate;
+ /* Invoke the inner tree. */
+ LIns* args[] = { INS_CONSTPTR(inner), lirbuf->state }; /* reverse order */
+ LIns* ret = lir->insCall(&js_CallTree_ci, args);
+ /* Read back all registers, in case the called tree changed any of them. */
+ import(ti, inner_sp_ins, exit->numGlobalSlots, exit->calldepth,
+ getTypeMap(exit), getTypeMap(exit) + exit->numGlobalSlots);
+ /* Restore sp and rp to their original values (we still have them in a register). */
+ if (callDepth > 0) {
+ lir->insStorei(lirbuf->sp, lirbuf->state, offsetof(InterpState, sp));
+ lir->insStorei(lirbuf->rp, lirbuf->state, offsetof(InterpState, rp));
+ }
+ /* Guard that we come out of the inner tree along the same side exit we came out when
+ we called the inner tree at recording time. */
+ guard(true, lir->ins2(LIR_eq, ret, INS_CONSTPTR(exit)), NESTED_EXIT);
+ /* Register us as a dependent tree of the inner tree. */
+ ((TreeInfo*)inner->vmprivate)->dependentTrees.addUnique(fragment->root);
+}
+
+/* Add a if/if-else control-flow merge point to the list of known merge points. */
+void
+TraceRecorder::trackCfgMerges(jsbytecode* pc)
+{
+ /* If we hit the beginning of an if/if-else, then keep track of the merge point after it. */
+ JS_ASSERT((*pc == JSOP_IFEQ) || (*pc == JSOP_IFEQX));
+ jssrcnote* sn = js_GetSrcNote(cx->fp->script, pc);
+ if (sn != NULL) {
+ if (SN_TYPE(sn) == SRC_IF) {
+ cfgMerges.add((*pc == JSOP_IFEQ)
+ ? pc + GET_JUMP_OFFSET(pc)
+ : pc + GET_JUMPX_OFFSET(pc));
+ } else if (SN_TYPE(sn) == SRC_IF_ELSE)
+ cfgMerges.add(pc + js_GetSrcNoteOffset(sn, 0));
+ }
+}
+
+/* Invert the direction of the guard if this is a loop edge that is not
+ taken (thin loop). */
+void
+TraceRecorder::flipIf(jsbytecode* pc, bool& cond)
+{
+ if (js_IsLoopEdge(pc, (jsbytecode*)fragment->root->ip)) {
+ switch (*pc) {
+ case JSOP_IFEQ:
+ case JSOP_IFEQX:
+ if (!cond)
+ return;
+ break;
+ case JSOP_IFNE:
+ case JSOP_IFNEX:
+ if (cond)
+ return;
+ break;
+ default:
+ JS_NOT_REACHED("flipIf");
+ }
+ /* We are about to walk out of the loop, so terminate it with
+ an inverse loop condition. */
+ debug_only_v(printf("Walking out of the loop, terminating it anyway.\n");)
+ cond = !cond;
+ terminate = true;
+ /* If when we get to closeLoop the tree is decided to be type unstable, we need to
+ reverse this logic because the loop won't be closed after all. Store the real
+ value of the IP the interpreter expects, so we can use it in our final LIR_x.
+ */
+ if (*pc == JSOP_IFEQX || *pc == JSOP_IFNEX)
+ pc += GET_JUMPX_OFFSET(pc);
+ else
+ pc += GET_JUMP_OFFSET(pc);
+ terminate_ip_adj = ENCODE_IP_ADJ(cx->fp, pc);
+ }
+}
+
+/* Emit code for a fused IFEQ/IFNE. */
+void
+TraceRecorder::fuseIf(jsbytecode* pc, bool cond, LIns* x)
+{
+ if (x->isconst()) // no need to guard if condition is constant
+ return;
+ if (*pc == JSOP_IFEQ) {
+ flipIf(pc, cond);
+ guard(cond, x, BRANCH_EXIT);
+ trackCfgMerges(pc);
+ } else if (*pc == JSOP_IFNE) {
+ flipIf(pc, cond);
+ guard(cond, x, BRANCH_EXIT);
+ }
+}
+
+bool
+TraceRecorder::hasMethod(JSObject* obj, jsid id)
+{
+ if (!obj)
+ return false;
+
+ JSObject* pobj;
+ JSProperty* prop;
+ int protoIndex = OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop);
+ if (protoIndex < 0 || !prop)
+ return false;
+
+ bool found = false;
+ if (OBJ_IS_NATIVE(pobj)) {
+ JSScope* scope = OBJ_SCOPE(pobj);
+ JSScopeProperty* sprop = (JSScopeProperty*) prop;
+
+ if (SPROP_HAS_STUB_GETTER(sprop) &&
+ SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ jsval v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
+ if (VALUE_IS_FUNCTION(cx, v)) {
+ found = true;
+ if (!SCOPE_IS_BRANDED(scope)) {
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ SCOPE_SET_BRANDED(scope);
+ }
+ }
+ }
+ }
+
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ return found;
+}
+
+bool
+TraceRecorder::hasToStringMethod(JSObject* obj)
+{
+ JS_ASSERT(cx->fp->regs->sp + 1 <= cx->fp->slots + cx->fp->script->nslots);
+
+ return hasMethod(obj, ATOM_TO_JSID(cx->runtime->atomState.toStringAtom));
+}
+
+bool
+TraceRecorder::hasValueOfMethod(JSObject* obj)
+{
+ JS_ASSERT(cx->fp->regs->sp + 2 <= cx->fp->slots + cx->fp->script->nslots);
+
+ return hasMethod(obj, ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom));
+}
+
+bool
+TraceRecorder::hasIteratorMethod(JSObject* obj)
+{
+ JS_ASSERT(cx->fp->regs->sp + 2 <= cx->fp->slots + cx->fp->script->nslots);
+
+ return hasMethod(obj, ATOM_TO_JSID(cx->runtime->atomState.iteratorAtom));
+}
+
+int
+nanojit::StackFilter::getTop(LInsp guard)
+{
+ VMSideExit* e = (VMSideExit*)guard->record()->exit;
+ if (sp == lirbuf->sp)
+ return e->sp_adj;
+ JS_ASSERT(sp == lirbuf->rp);
+ return e->rp_adj;
+}
+
+#if defined NJ_VERBOSE
+void
+nanojit::LirNameMap::formatGuard(LIns *i, char *out)
+{
+ VMSideExit *x;
+
+ x = (VMSideExit *)i->record()->exit;
+ sprintf(out,
+ "%s: %s %s -> %lu:%lu sp%+ld rp%+ld",
+ formatRef(i),
+ lirNames[i->opcode()],
+ i->oprnd1()->isCond() ? formatRef(i->oprnd1()) : "",
+ IMACRO_PC_ADJ(x->ip_adj),
+ SCRIPT_PC_ADJ(x->ip_adj),
+ (long int)x->sp_adj,
+ (long int)x->rp_adj);
+}
+#endif
+
+void
+nanojit::Fragment::onDestroy()
+{
+ if (root == this) {
+ delete mergeCounts;
+ delete lirbuf;
+ }
+ delete (TreeInfo *)vmprivate;
+}
+
+void
+js_DeleteRecorder(JSContext* cx)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ /* Aborting and completing a trace end up here. */
+ JS_ASSERT(tm->onTrace);
+ tm->onTrace = false;
+
+ delete tm->recorder;
+ tm->recorder = NULL;
+}
+
+/**
+ * Checks whether the shape of the global object has changed.
+ */
+static inline bool
+js_CheckGlobalObjectShape(JSContext* cx, JSTraceMonitor* tm, JSObject* globalObj)
+{
+ /* Check the global shape. */
+ if (OBJ_SHAPE(globalObj) != tm->globalShape) {
+ AUDIT(globalShapeMismatchAtEntry);
+ debug_only_v(printf("Global shape mismatch (%u vs. %u), flushing cache.\n",
+ OBJ_SHAPE(globalObj), tm->globalShape);)
+ return false;
+ }
+ return true;
+}
+
+static bool
+js_StartRecorder(JSContext* cx, VMSideExit* anchor, Fragment* f, TreeInfo* ti,
+ unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap,
+ VMSideExit* expectedInnerExit, Fragment* outer)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ /*
+ * Emulate on-trace semantics and avoid rooting headaches while recording,
+ * by suppressing last-ditch GC attempts while recording a trace. This does
+ * means that trace recording must not nest or the following assertion will
+ * botch.
+ */
+ JS_ASSERT(!tm->onTrace);
+ tm->onTrace = true;
+
+ /* start recording if no exception during construction */
+ tm->recorder = new (&gc) TraceRecorder(cx, anchor, f, ti,
+ ngslots, globalTypeMap, stackTypeMap,
+ expectedInnerExit, outer);
+ if (cx->throwing) {
+ js_AbortRecording(cx, "setting up recorder failed");
+ return false;
+ }
+ /* clear any leftover error state */
+ tm->fragmento->assm()->setError(None);
+ return true;
+}
+
+static void
+js_TrashTree(JSContext* cx, Fragment* f)
+{
+ JS_ASSERT((!f->code()) == (!f->vmprivate));
+ JS_ASSERT(f == f->root);
+ if (!f->code())
+ return;
+ AUDIT(treesTrashed);
+ debug_only_v(printf("Trashing tree info.\n");)
+ Fragmento* fragmento = JS_TRACE_MONITOR(cx).fragmento;
+ TreeInfo* ti = (TreeInfo*)f->vmprivate;
+ f->vmprivate = NULL;
+ f->releaseCode(fragmento);
+ Fragment** data = ti->dependentTrees.data();
+ unsigned length = ti->dependentTrees.length();
+ for (unsigned n = 0; n < length; ++n)
+ js_TrashTree(cx, data[n]);
+ delete ti;
+ JS_ASSERT(!f->code() && !f->vmprivate);
+}
+
+static int
+js_SynthesizeFrame(JSContext* cx, const FrameInfo& fi)
+{
+ JS_ASSERT(HAS_FUNCTION_CLASS(fi.callee));
+
+ JSFunction* fun = GET_FUNCTION_PRIVATE(cx, fi.callee);
+ JS_ASSERT(FUN_INTERPRETED(fun));
+
+ /* Assert that we have a correct sp distance from cx->fp->slots in fi. */
+ JS_ASSERT_IF(!FI_IMACRO_PC(fi, cx->fp),
+ js_ReconstructStackDepth(cx, cx->fp->script, FI_SCRIPT_PC(fi, cx->fp))
+ == uintN(fi.s.spdist - cx->fp->script->nfixed));
+
+ uintN nframeslots = JS_HOWMANY(sizeof(JSInlineFrame), sizeof(jsval));
+ JSScript* script = fun->u.i.script;
+ size_t nbytes = (nframeslots + script->nslots) * sizeof(jsval);
+
+ /* Code duplicated from inline_call: case in js_Interpret (FIXME). */
+ JSArena* a = cx->stackPool.current;
+ void* newmark = (void*) a->avail;
+ uintN argc = fi.s.argc & 0x7fff;
+ jsval* vp = cx->fp->slots + fi.s.spdist - (2 + argc);
+ uintN missing = 0;
+ jsval* newsp;
+
+ if (fun->nargs > argc) {
+ const JSFrameRegs& regs = *cx->fp->regs;
+
+ newsp = vp + 2 + fun->nargs;
+ JS_ASSERT(newsp > regs.sp);
+ if ((jsuword) newsp <= a->limit) {
+ if ((jsuword) newsp > a->avail)
+ a->avail = (jsuword) newsp;
+ jsval* argsp = newsp;
+ do {
+ *--argsp = JSVAL_VOID;
+ } while (argsp != regs.sp);
+ missing = 0;
+ } else {
+ missing = fun->nargs - argc;
+ nbytes += (2 + fun->nargs) * sizeof(jsval);
+ }
+ }
+
+ /* Allocate the inline frame with its vars and operands. */
+ if (a->avail + nbytes <= a->limit) {
+ newsp = (jsval *) a->avail;
+ a->avail += nbytes;
+ JS_ASSERT(missing == 0);
+ } else {
+ JS_ARENA_ALLOCATE_CAST(newsp, jsval *, &cx->stackPool, nbytes);
+ if (!newsp) {
+ js_ReportOutOfScriptQuota(cx);
+ return 0;
+ }
+
+ /*
+ * Move args if the missing ones overflow arena a, then push
+ * undefined for the missing args.
+ */
+ if (missing) {
+ memcpy(newsp, vp, (2 + argc) * sizeof(jsval));
+ vp = newsp;
+ newsp = vp + 2 + argc;
+ do {
+ *newsp++ = JSVAL_VOID;
+ } while (--missing != 0);
+ }
+ }
+
+ /* Claim space for the stack frame and initialize it. */
+ JSInlineFrame* newifp = (JSInlineFrame *) newsp;
+ newsp += nframeslots;
+
+ newifp->frame.callobj = NULL;
+ newifp->frame.argsobj = NULL;
+ newifp->frame.varobj = NULL;
+ newifp->frame.script = script;
+ newifp->frame.callee = fi.callee;
+ newifp->frame.fun = fun;
+
+ bool constructing = fi.s.argc & 0x8000;
+ newifp->frame.argc = argc;
+
+ jsbytecode* imacro_pc = FI_IMACRO_PC(fi, cx->fp);
+ jsbytecode* script_pc = FI_SCRIPT_PC(fi, cx->fp);
+ newifp->callerRegs.pc = imacro_pc ? imacro_pc : script_pc;
+ newifp->callerRegs.sp = cx->fp->slots + fi.s.spdist;
+ cx->fp->imacpc = imacro_pc ? script_pc : NULL;
+
+ newifp->frame.argv = newifp->callerRegs.sp - argc;
+ JS_ASSERT(newifp->frame.argv);
+#ifdef DEBUG
+ // Initialize argv[-1] to a known-bogus value so we'll catch it if
+ // someone forgets to initialize it later.
+ newifp->frame.argv[-1] = JSVAL_HOLE;
+#endif
+ JS_ASSERT(newifp->frame.argv >= StackBase(cx->fp) + 2);
+
+ newifp->frame.rval = JSVAL_VOID;
+ newifp->frame.down = cx->fp;
+ newifp->frame.annotation = NULL;
+ newifp->frame.scopeChain = OBJ_GET_PARENT(cx, fi.callee);
+ newifp->frame.sharpDepth = 0;
+ newifp->frame.sharpArray = NULL;
+ newifp->frame.flags = constructing ? JSFRAME_CONSTRUCTING : 0;
+ newifp->frame.dormantNext = NULL;
+ newifp->frame.xmlNamespace = NULL;
+ newifp->frame.blockChain = NULL;
+ newifp->mark = newmark;
+ newifp->frame.thisp = NULL; // will be set by js_ExecuteTree -> FlushNativeStackFrame
+
+ newifp->frame.regs = cx->fp->regs;
+ newifp->frame.regs->pc = script->code;
+ newifp->frame.regs->sp = newsp + script->nfixed;
+ newifp->frame.imacpc = NULL;
+ newifp->frame.slots = newsp;
+ if (script->staticDepth < JS_DISPLAY_SIZE) {
+ JSStackFrame **disp = &cx->display[script->staticDepth];
+ newifp->frame.displaySave = *disp;
+ *disp = &newifp->frame;
+ }
+#ifdef DEBUG
+ newifp->frame.pcDisabledSave = 0;
+#endif
+
+ /*
+ * Note that cx->fp->script is still the caller's script; set the callee
+ * inline frame's idea of caller version from its version.
+ */
+ newifp->callerVersion = (JSVersion) cx->fp->script->version;
+
+ cx->fp->regs = &newifp->callerRegs;
+ cx->fp = &newifp->frame;
+
+ if (fun->flags & JSFUN_HEAVYWEIGHT) {
+ /*
+ * Set hookData to null because the failure case for js_GetCallObject
+ * involves it calling the debugger hook.
+ */
+ newifp->hookData = NULL;
+ if (!js_GetCallObject(cx, &newifp->frame, newifp->frame.scopeChain))
+ return -1;
+ }
+
+ /*
+ * If there's a call hook, invoke it to compute the hookData used by
+ * debuggers that cooperate with the interpreter.
+ */
+ JSInterpreterHook hook = cx->debugHooks->callHook;
+ if (hook) {
+ newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0,
+ cx->debugHooks->callHookData);
+ } else {
+ newifp->hookData = NULL;
+ }
+
+ // FIXME? we must count stack slots from caller's operand stack up to (but not including)
+ // callee's, including missing arguments. Could we shift everything down to the caller's
+ // fp->slots (where vars start) and avoid some of the complexity?
+ return (fi.s.spdist - cx->fp->down->script->nfixed) +
+ ((fun->nargs > cx->fp->argc) ? fun->nargs - cx->fp->argc : 0) +
+ script->nfixed;
+}
+
+bool
+js_RecordTree(JSContext* cx, JSTraceMonitor* tm, Fragment* f, Fragment* outer, unsigned* demotes)
+{
+ JS_ASSERT(cx->fp->regs->pc == f->ip && f->root == f);
+
+ /* Avoid recording loops in overlarge scripts. */
+ if (cx->fp->script->length >= SCRIPT_PC_ADJ_LIMIT) {
+ js_AbortRecording(cx, "script too large");
+ return false;
+ }
+
+ /* Make sure the global type map didn't change on us. */
+ JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
+ if (!js_CheckGlobalObjectShape(cx, tm, globalObj)) {
+ js_FlushJITCache(cx);
+ return false;
+ }
+ TypeMap current;
+ current.captureGlobalTypes(cx, *tm->globalSlots);
+ if (!current.matches(*tm->globalTypeMap)) {
+ js_FlushJITCache(cx);
+ debug_only_v(printf("Global type map mismatch in RecordTree, flushing cache.\n");)
+ return false;
+ }
+
+ AUDIT(recorderStarted);
+
+ /* Try to find an unused peer fragment, or allocate a new one. */
+ while (f->code() && f->peer)
+ f = f->peer;
+ if (f->code())
+ f = JS_TRACE_MONITOR(cx).fragmento->getAnchor(f->root->ip);
+
+ f->recordAttempts++;
+ f->root = f;
+ /* allocate space to store the LIR for this tree */
+ if (!f->lirbuf) {
+ f->lirbuf = new (&gc) LirBuffer(tm->fragmento, NULL);
+#ifdef DEBUG
+ f->lirbuf->names = new (&gc) LirNameMap(&gc, NULL, tm->fragmento->labels);
+#endif
+ }
+
+ if (f->lirbuf->outOmem()) {
+ js_FlushJITCache(cx);
+ debug_only_v(printf("Out of memory recording new tree, flushing cache.\n");)
+ return false;
+ }
+
+ JS_ASSERT(!f->code() && !f->vmprivate);
+
+ /* setup the VM-private treeInfo structure for this fragment */
+ TreeInfo* ti = new (&gc) TreeInfo(f);
+
+ /* capture the coerced type of each active slot in the stack type map */
+ ti->stackTypeMap.captureStackTypes(cx, 0/*callDepth*/);
+
+ if (demotes) {
+ /* If we get a list of demotions, an outer tree is telling us our types are not callable. */
+ uint8* typeMap = ti->stackTypeMap.data();
+ for (unsigned i = 1; i <= NUM_UNDEMOTE_SLOTS(demotes); i++) {
+ JS_ASSERT(demotes[i] < ti->stackTypeMap.length());
+ if (typeMap[demotes[i]] == JSVAL_INT)
+ typeMap[demotes[i]] = JSVAL_DOUBLE;
+ }
+ }
+
+ /* Check for duplicate entry type maps. This is always wrong and hints at trace explosion
+ since we are trying to stabilize something without properly connecting peer edges. */
+ #ifdef DEBUG
+ TreeInfo* ti_other;
+ for (Fragment* peer = tm->fragmento->getLoop(f->root->ip); peer != NULL; peer = peer->peer) {
+ if (!peer->code() || peer == f)
+ continue;
+ ti_other = (TreeInfo*)peer->vmprivate;
+ JS_ASSERT(ti_other);
+ JS_ASSERT(!ti->stackTypeMap.matches(ti_other->stackTypeMap));
+ }
+ #endif
+
+ /* determine the native frame layout at the entry point */
+ unsigned entryNativeStackSlots = ti->stackTypeMap.length();
+ JS_ASSERT(entryNativeStackSlots == js_NativeStackSlots(cx, 0/*callDepth*/));
+ ti->nativeStackBase = (entryNativeStackSlots -
+ (cx->fp->regs->sp - StackBase(cx->fp))) * sizeof(double);
+ ti->maxNativeStackSlots = entryNativeStackSlots;
+ ti->maxCallDepth = 0;
+ ti->script = cx->fp->script;
+
+ /* recording primary trace */
+ if (!js_StartRecorder(cx, NULL, f, ti,
+ tm->globalSlots->length(), tm->globalTypeMap->data(),
+ ti->stackTypeMap.data(), NULL, outer)) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+js_AttemptToStabilizeTree(JSContext* cx, VMSideExit* exit, Fragment* outer)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ Fragment* from = exit->from->root;
+ unsigned* demotes;
+
+ JS_ASSERT(exit->from->root->code());
+
+ demotes = ALLOCA_UNDEMOTE_SLOTLIST(exit->numStackSlots);
+ CLEAR_UNDEMOTE_SLOTLIST(demotes);
+
+ uint8* t2 = getTypeMap(exit) + exit->numGlobalSlots;
+ for (unsigned i = 0; i < exit->numStackSlots; i++) {
+ if (t2[i] == JSVAL_DOUBLE)
+ ADD_UNDEMOTE_SLOT(demotes, i);
+ }
+
+ if (!NUM_UNDEMOTE_SLOTS(demotes))
+ demotes = NULL;
+
+ if (!js_RecordTree(cx, tm, from->first, outer, demotes))
+ return false;
+
+ tm->recorder->setPromotedPeer(demotes ? from : NULL);
+
+ return true;
+}
+
+static bool
+js_AttemptToExtendTree(JSContext* cx, VMSideExit* anchor, VMSideExit* exitedFrom, Fragment* outer)
+{
+ Fragment* f = anchor->from->root;
+ JS_ASSERT(f->vmprivate);
+ TreeInfo* ti = (TreeInfo*)f->vmprivate;
+
+ /* Don't grow trees above a certain size to avoid code explosion due to tail duplication. */
+ if (ti->branchCount >= MAX_BRANCHES)
+ return false;
+
+ Fragment* c;
+ if (!(c = anchor->target)) {
+ c = JS_TRACE_MONITOR(cx).fragmento->createBranch(anchor, cx->fp->regs->pc);
+ c->spawnedFrom = anchor;
+ c->parent = f;
+ anchor->target = c;
+ c->root = f;
+ }
+
+ debug_only_v(printf("trying to attach another branch to the tree (hits = %d)\n", c->hits());)
+
+ if (++c->hits() >= HOTEXIT) {
+ /* start tracing secondary trace from this point */
+ c->lirbuf = f->lirbuf;
+ unsigned ngslots;
+ uint8* globalTypeMap;
+ uint8* stackTypeMap;
+ TypeMap fullMap;
+ if (exitedFrom == NULL) {
+ /* If we are coming straight from a simple side exit, just use that exit's type map
+ as starting point. */
+ ngslots = anchor->numGlobalSlots;
+ globalTypeMap = getTypeMap(anchor);
+ stackTypeMap = globalTypeMap + ngslots;
+ } else {
+ /* If we side-exited on a loop exit and continue on a nesting guard, the nesting
+ guard (anchor) has the type information for everything below the current scope,
+ and the actual guard we exited from has the types for everything in the current
+ scope (and whatever it inlined). We have to merge those maps here. */
+ VMSideExit* e1 = anchor;
+ VMSideExit* e2 = exitedFrom;
+ fullMap.add(getTypeMap(e1) + e1->numGlobalSlots, e1->numStackSlotsBelowCurrentFrame);
+ fullMap.add(getTypeMap(e2) + e2->numGlobalSlots, e2->numStackSlots);
+ ngslots = e2->numGlobalSlots;
+ globalTypeMap = getTypeMap(e2);
+ stackTypeMap = fullMap.data();
+ }
+ return js_StartRecorder(cx, anchor, c, (TreeInfo*)f->vmprivate,
+ ngslots, globalTypeMap, stackTypeMap, exitedFrom, outer);
+ }
+ return false;
+}
+
+static VMSideExit*
+js_ExecuteTree(JSContext* cx, Fragment* f, uintN& inlineCallCount,
+ VMSideExit** innermostNestedGuardp);
+
+static Fragment*
+js_FindVMCompatiblePeer(JSContext* cx, Fragment* f);
+
+static bool
+js_CloseLoop(JSContext* cx)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ Fragmento* fragmento = tm->fragmento;
+ TraceRecorder* r = tm->recorder;
+ JS_ASSERT(fragmento && r);
+ bool walkedOutOfLoop = r->walkedOutOfLoop();
+
+ if (fragmento->assm()->error()) {
+ js_AbortRecording(cx, "Error during recording");
+
+ /* If we ran out of memory, flush the code cache and abort. */
+ if (fragmento->assm()->error() == OutOMem)
+ js_FlushJITCache(cx);
+ return false;
+ }
+
+ bool demote;
+ Fragment* f = r->getFragment();
+ TreeInfo* ti = r->getTreeInfo();
+ unsigned* demotes = ALLOCA_UNDEMOTE_SLOTLIST(ti->stackTypeMap.length());
+ r->closeLoop(fragmento, demote, demotes);
+ JS_ASSERT(!demote || NUM_UNDEMOTE_SLOTS(demotes));
+ js_DeleteRecorder(cx);
+
+ /*
+ * If we just walked out of a thin loop, we can't immediately start the
+ * compiler again here since we didn't return to the loop header.
+ */
+ if (demote && !walkedOutOfLoop)
+ return js_RecordTree(cx, tm, f, NULL, demotes);
+ return false;
+}
+
+bool
+js_RecordLoopEdge(JSContext* cx, TraceRecorder* r, uintN& inlineCallCount)
+{
+#ifdef JS_THREADSAFE
+ if (OBJ_SCOPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain))->title.ownercx != cx) {
+ js_AbortRecording(cx, "Global object not owned by this context");
+ return false; /* we stay away from shared global objects */
+ }
+#endif
+ Fragmento* fragmento = JS_TRACE_MONITOR(cx).fragmento;
+ /* If we hit our own loop header, close the loop and compile the trace. */
+ if (r->isLoopHeader(cx))
+ return js_CloseLoop(cx);
+ /* does this branch go to an inner loop? */
+ Fragment* f = fragmento->getLoop(cx->fp->regs->pc);
+ Fragment* peer_root = f;
+ if (nesting_enabled && f) {
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ /* Make sure inner tree call will not run into an out-of-memory condition. */
+ if (tm->recoveryDoublePoolPtr < (tm->recoveryDoublePool + MAX_NATIVE_STACK_SLOTS) &&
+ !js_ReplenishRecoveryPool(cx, tm)) {
+ js_AbortRecording(cx, "Couldn't call inner tree (out of memory)");
+ return false;
+ }
+
+ /* Make sure the shape of the global object still matches (this might flush
+ the JIT cache). */
+ JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
+ if (!js_CheckGlobalObjectShape(cx, tm, globalObj)) {
+ js_AbortRecording(cx, "Couldn't call inner tree (prep failed)");
+ return false;
+ }
+
+ debug_only_v(printf("Looking for type-compatible peer (%s:%d@%d)\n",
+ cx->fp->script->filename,
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp));)
+
+ /* Find an acceptable peer, make sure our types fit. */
+ Fragment* empty;
+ bool trash = false;
+ bool success = false;
+ unsigned* demotes = NULL;
+
+ f = r->findNestedCompatiblePeer(f, &empty);
+ if (f && f->code()) {
+ TreeInfo* ti = (TreeInfo*)f->vmprivate;
+ /* alloca docs says it lasts out of scopes. */
+ demotes = ALLOCA_UNDEMOTE_SLOTLIST(ti->stackTypeMap.length());
+ CLEAR_UNDEMOTE_SLOTLIST(demotes);
+ success = r->adjustCallerTypes(f, demotes, trash);
+ }
+
+ if (!success) {
+ AUDIT(noCompatInnerTrees);
+ debug_only_v(printf("No compatible inner tree (%p).\n", f);)
+
+ if (trash) {
+ js_AbortRecording(cx, "No compatible inner tree (global demotions");
+ return false;
+ }
+
+ Fragment* old = fragmento->getLoop(tm->recorder->getFragment()->root->ip);
+ if (old == NULL)
+ old = tm->recorder->getFragment();
+ js_AbortRecording(cx, "No compatible inner tree");
+ if (!f && ++peer_root->hits() < MAX_INNER_RECORD_BLACKLIST)
+ return false;
+ if (old->recordAttempts < MAX_MISMATCH)
+ old->resetHits();
+ f = empty ? empty : tm->fragmento->getAnchor(cx->fp->regs->pc);
+ return js_RecordTree(cx, tm, f, old, demotes);
+ }
+
+ r->prepareTreeCall(f);
+ VMSideExit* innermostNestedGuard = NULL;
+ VMSideExit* lr = js_ExecuteTree(cx, f, inlineCallCount, &innermostNestedGuard);
+ if (!lr) {
+ js_AbortRecording(cx, "Couldn't call inner tree");
+ return false;
+ }
+ Fragment* old;
+ switch (lr->exitType) {
+ case LOOP_EXIT:
+ /* If the inner tree exited on an unknown loop exit, grow the tree around it. */
+ if (innermostNestedGuard) {
+ js_AbortRecording(cx, "Inner tree took different side exit, abort recording");
+ return js_AttemptToExtendTree(cx, innermostNestedGuard, lr, NULL);
+ }
+ /* emit a call to the inner tree and continue recording the outer tree trace */
+ r->emitTreeCall(f, lr);
+ return true;
+ case UNSTABLE_LOOP_EXIT:
+ /* abort recording so the inner loop can become type stable. */
+ old = fragmento->getLoop(tm->recorder->getFragment()->root->ip);
+ js_AbortRecording(cx, "Inner tree is trying to stabilize, abort outer recording");
+ old->resetHits();
+ return js_AttemptToStabilizeTree(cx, lr, old);
+ case BRANCH_EXIT:
+ /* abort recording the outer tree, extend the inner tree */
+ old = fragmento->getLoop(tm->recorder->getFragment()->root->ip);
+ js_AbortRecording(cx, "Inner tree is trying to grow, abort outer recording");
+ old->resetHits();
+ return js_AttemptToExtendTree(cx, lr, NULL, old);
+ default:
+ debug_only_v(printf("exit_type=%d\n", lr->exitType);)
+ js_AbortRecording(cx, "Inner tree not suitable for calling");
+ return false;
+ }
+ }
+
+ /* not returning to our own loop header, not an inner loop we can call, abort trace */
+ AUDIT(returnToDifferentLoopHeader);
+ JS_ASSERT(!cx->fp->imacpc);
+ debug_only_v(printf("loop edge to %d, header %d\n",
+ cx->fp->regs->pc - cx->fp->script->code,
+ (jsbytecode*)r->getFragment()->root->ip - cx->fp->script->code));
+ js_AbortRecording(cx, "Loop edge does not return to header");
+ return false;
+}
+
+static bool
+js_IsEntryTypeCompatible(jsval* vp, uint8* m)
+{
+ unsigned tag = JSVAL_TAG(*vp);
+
+ debug_only_v(printf("%c/%c ", "OIDISIBI"[tag], "OID?S?B?"[*m]);)
+
+ switch (*m) {
+ case JSVAL_INT:
+ jsint i;
+ if (JSVAL_IS_INT(*vp))
+ return true;
+ if ((tag == JSVAL_DOUBLE) && JSDOUBLE_IS_INT(*JSVAL_TO_DOUBLE(*vp), i))
+ return true;
+ debug_only_v(printf("int != tag%u(value=%lu) ", tag, *vp);)
+ return false;
+ case JSVAL_DOUBLE:
+ if (JSVAL_IS_INT(*vp) || tag == JSVAL_DOUBLE)
+ return true;
+ debug_only_v(printf("double != tag%u ", tag);)
+ return false;
+ case JSVAL_BOOLEAN:
+ if (tag == JSVAL_BOOLEAN)
+ return true;
+ debug_only_v(printf("bool != tag%u", tag);)
+ return false;
+ case JSVAL_STRING:
+ if (tag == JSVAL_STRING)
+ return true;
+ debug_only_v(printf("string != tag%u", tag);)
+ return false;
+ default:
+ JS_ASSERT(*m == JSVAL_OBJECT);
+ if (tag == JSVAL_OBJECT)
+ return true;
+ debug_only_v(printf("object != tag%u", tag);)
+ return false;
+ }
+}
+
+Fragment* TraceRecorder::findNestedCompatiblePeer(Fragment* f, Fragment** empty)
+{
+ Fragment* demote;
+ JSTraceMonitor* tm;
+ unsigned max_demotes;
+
+ if (empty)
+ *empty = NULL;
+ demote = NULL;
+
+ tm = &JS_TRACE_MONITOR(cx);
+ unsigned int ngslots = tm->globalSlots->length();
+ uint16* gslots = tm->globalSlots->data();
+ uint8* m = tm->globalTypeMap->data();
+
+ if (ngslots) {
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ debug_only_v(printf("%s%d=", vpname, vpnum);)
+ if (!js_IsEntryTypeCompatible(vp, m))
+ return NULL;
+ m++;
+ );
+ }
+
+ /* We keep a maximum tally - we want to select the peer most likely to work so we don't keep
+ * recording.
+ */
+ max_demotes = 0;
+
+ TreeInfo* ti;
+ for (; f != NULL; f = f->peer) {
+ if (!f->code()) {
+ if (empty)
+ *empty = f;
+ continue;
+ }
+
+ unsigned demotes = 0;
+ ti = (TreeInfo*)f->vmprivate;
+ m = ti->stackTypeMap.data();
+
+ debug_only_v(printf("checking nested types %p: ", f);)
+
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ debug_only_v(printf("%s%d=", vpname, vpnum);)
+ if (!js_IsEntryTypeCompatible(vp, m))
+ goto check_fail;
+ if (*m == JSVAL_STRING && *vp == JSVAL_VOID)
+ goto check_fail;
+ if (*m == JSVAL_INT && !isPromoteInt(get(vp)))
+ demotes++;
+ m++;
+ );
+ JS_ASSERT(unsigned(m - ti->stackTypeMap.data()) == ti->stackTypeMap.length());
+
+ debug_only_v(printf(" (demotes %d)\n", demotes);)
+
+ if (demotes) {
+ if (demotes > max_demotes) {
+ demote = f;
+ max_demotes = demotes;
+ }
+ continue;
+ } else {
+ return f;
+ }
+
+check_fail:
+ debug_only_v(printf("\n"));
+ continue;
+ }
+
+ if (demote)
+ return demote;
+
+ return NULL;
+}
+
+/**
+ * Check if types are usable for trace execution.
+ *
+ * @param cx Context.
+ * @param ti Tree info of peer we're testing.
+ * @return True if compatible (with or without demotions), false otherwise.
+ */
+static bool
+js_CheckEntryTypes(JSContext* cx, TreeInfo* ti)
+{
+ JSTraceMonitor* tm;
+
+ tm = &JS_TRACE_MONITOR(cx);
+ unsigned int ngslots = tm->globalSlots->length();
+ uint16* gslots = tm->globalSlots->data();
+ uint8* m = tm->globalTypeMap->data();
+
+ if (ngslots) {
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ debug_only_v(printf("%s%d=", vpname, vpnum);)
+ if (!js_IsEntryTypeCompatible(vp, m))
+ goto check_fail;
+ m++;
+ );
+ }
+
+ m = ti->stackTypeMap.data();
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ debug_only_v(printf("%s%d=", vpname, vpnum);)
+ if (!js_IsEntryTypeCompatible(vp, m))
+ goto check_fail;
+ m++;
+ );
+ JS_ASSERT(unsigned(m - ti->stackTypeMap.data()) == ti->stackTypeMap.length());
+
+ debug_only_v(printf("\n");)
+ return true;
+
+check_fail:
+ debug_only_v(printf("\n");)
+ return false;
+}
+
+/**
+ * Find an acceptable entry tree given a PC.
+ *
+ * @param cx Context.
+ * @param f First peer fragment.
+ * @param nodemote If true, will try to find a peer that does not require demotion.
+ */
+static Fragment*
+js_FindVMCompatiblePeer(JSContext* cx, Fragment* f)
+{
+ for (; f != NULL; f = f->peer) {
+ if (f->vmprivate == NULL)
+ continue;
+ debug_only_v(printf("checking vm types %p (ip: %p): ", f, f->ip);)
+ if (js_CheckEntryTypes(cx, (TreeInfo*)f->vmprivate))
+ return f;
+ }
+ return NULL;
+}
+
+/**
+ * Executes a tree.
+ */
+static VMSideExit*
+js_ExecuteTree(JSContext* cx, Fragment* f, uintN& inlineCallCount,
+ VMSideExit** innermostNestedGuardp)
+{
+ JS_ASSERT(f->code() && f->vmprivate);
+
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
+ TreeInfo* ti = (TreeInfo*)f->vmprivate;
+ unsigned ngslots = tm->globalSlots->length();
+ uint16* gslots = tm->globalSlots->data();
+ unsigned globalFrameSize = STOBJ_NSLOTS(globalObj);
+ double* global = (double*)alloca((globalFrameSize+1) * sizeof(double));
+ double stack_buffer[MAX_NATIVE_STACK_SLOTS];
+ double* stack = stack_buffer;
+
+ /* Make sure the global object is sane. */
+ JS_ASSERT(!ngslots || (OBJ_SHAPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain)) == tm->globalShape));
+ /* Make sure our caller replenished the double pool. */
+ JS_ASSERT(tm->recoveryDoublePoolPtr >= tm->recoveryDoublePool + MAX_NATIVE_STACK_SLOTS);
+
+#ifdef DEBUG
+ memset(stack_buffer, 0xCD, sizeof(stack_buffer));
+ memset(global, 0xCD, (globalFrameSize+1)*sizeof(double));
+#endif
+
+ debug_only(*(uint64*)&global[globalFrameSize] = 0xdeadbeefdeadbeefLL;)
+ debug_only_v(printf("entering trace at %s:%u@%u, native stack slots: %u code: %p\n",
+ cx->fp->script->filename,
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp),
+ ti->maxNativeStackSlots,
+ f->code());)
+
+ if (ngslots)
+ BuildNativeGlobalFrame(cx, ngslots, gslots, tm->globalTypeMap->data(), global);
+ BuildNativeStackFrame(cx, 0/*callDepth*/, ti->stackTypeMap.data(), stack);
+
+ double* entry_sp = &stack[ti->nativeStackBase/sizeof(double)];
+ FrameInfo callstack_buffer[MAX_CALL_STACK_ENTRIES];
+ FrameInfo* callstack = callstack_buffer;
+
+ InterpState state;
+ state.sp = (void*)entry_sp;
+ state.eos = ((double*)state.sp) + MAX_NATIVE_STACK_SLOTS;
+ state.rp = callstack;
+ state.eor = callstack + MAX_CALL_STACK_ENTRIES;
+ state.gp = global;
+ state.cx = cx;
+ state.lastTreeExitGuard = NULL;
+ state.lastTreeCallGuard = NULL;
+ state.rpAtLastTreeCall = NULL;
+ union { NIns *code; GuardRecord* (FASTCALL *func)(InterpState*, Fragment*); } u;
+ u.code = f->code();
+
+#ifdef JS_JIT_SPEW
+#if defined(NANOJIT_IA32) || (defined(NANOJIT_AMD64) && defined(__GNUC__))
+ uint64 start = rdtsc();
+#endif
+#endif
+
+ /*
+ * We may be called from js_MonitorLoopEdge while not recording, or while
+ * recording. Rather than over-generalize by using a counter instead of a
+ * flag, we simply sample and update tm->onTrace if necessary.
+ */
+ bool onTrace = tm->onTrace;
+ if (!onTrace)
+ tm->onTrace = true;
+ VMSideExit* lr;
+
+ debug_only(fflush(NULL);)
+ GuardRecord* rec;
+#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
+ SIMULATE_FASTCALL(rec, &state, NULL, u.func);
+#else
+ rec = u.func(&state, NULL);
+#endif
+ lr = (VMSideExit*)rec->exit;
+
+ AUDIT(traceTriggered);
+
+ JS_ASSERT(lr->exitType != LOOP_EXIT || !lr->calldepth);
+
+ tm->onTrace = onTrace;
+
+ /* Except if we find that this is a nested bailout, the guard the call returned is the
+ one we have to use to adjust pc and sp. */
+ VMSideExit* innermost = lr;
+
+ /* While executing a tree we do not update state.sp and state.rp even if they grow. Instead,
+ guards tell us by how much sp and rp should be incremented in case of a side exit. When
+ calling a nested tree, however, we actively adjust sp and rp. If we have such frames
+ from outer trees on the stack, then rp will have been adjusted. Before we can process
+ the stack of the frames of the tree we directly exited from, we have to first work our
+ way through the outer frames and generate interpreter frames for them. Once the call
+ stack (rp) is empty, we can process the final frames (which again are not directly
+ visible and only the guard we exited on will tells us about). */
+ FrameInfo* rp = (FrameInfo*)state.rp;
+ if (lr->exitType == NESTED_EXIT) {
+ VMSideExit* nested = state.lastTreeCallGuard;
+ if (!nested) {
+ /* If lastTreeCallGuard is not set in state, we only have a single level of
+ nesting in this exit, so lr itself is the innermost and outermost nested
+ guard, and hence we set nested to lr. The calldepth of the innermost guard
+ is not added to state.rp, so we do it here manually. For a nesting depth
+ greater than 1 the CallTree builtin already added the innermost guard's
+ calldepth to state.rpAtLastTreeCall. */
+ nested = lr;
+ rp += lr->calldepth;
+ } else {
+ /* During unwinding state.rp gets overwritten at every step and we restore
+ it here to its state at the innermost nested guard. The builtin already
+ added the calldepth of that innermost guard to rpAtLastTreeCall. */
+ rp = (FrameInfo*)state.rpAtLastTreeCall;
+ }
+ innermost = state.lastTreeExitGuard;
+ if (innermostNestedGuardp)
+ *innermostNestedGuardp = nested;
+ JS_ASSERT(nested);
+ JS_ASSERT(nested->exitType == NESTED_EXIT);
+ JS_ASSERT(state.lastTreeExitGuard);
+ JS_ASSERT(state.lastTreeExitGuard->exitType != NESTED_EXIT);
+ }
+
+ while (callstack < rp) {
+ /* Synthesize a stack frame and write out the values in it using the type map pointer
+ on the native call stack. */
+ if (js_SynthesizeFrame(cx, *callstack) < 0)
+ return NULL;
+ int slots = FlushNativeStackFrame(cx, 1/*callDepth*/, callstack->typemap, stack, cx->fp);
+#ifdef DEBUG
+ JSStackFrame* fp = cx->fp;
+ debug_only_v(printf("synthesized deep frame for %s:%u@%u, slots=%d\n",
+ fp->script->filename,
+ js_FramePCToLineNumber(cx, fp),
+ FramePCOffset(fp),
+ slots);)
+#endif
+ if (slots < 0)
+ return NULL;
+ /* Keep track of the additional frames we put on the interpreter stack and the native
+ stack slots we consumed. */
+ ++inlineCallCount;
+ ++callstack;
+ stack += slots;
+ }
+
+ /* We already synthesized the frames around the innermost guard. Here we just deal
+ with additional frames inside the tree we are bailing out from. */
+ JS_ASSERT(rp == callstack);
+ unsigned calldepth = innermost->calldepth;
+ unsigned calldepth_slots = 0;
+ for (unsigned n = 0; n < calldepth; ++n) {
+ int nslots = js_SynthesizeFrame(cx, callstack[n]);
+ if (nslots < 0)
+ return NULL;
+ calldepth_slots += nslots;
+ ++inlineCallCount;
+#ifdef DEBUG
+ JSStackFrame* fp = cx->fp;
+ debug_only_v(printf("synthesized shallow frame for %s:%u@%u\n",
+ fp->script->filename, js_FramePCToLineNumber(cx, fp),
+ FramePCOffset(fp));)
+#endif
+ }
+
+ /* Adjust sp and pc relative to the tree we exited from (not the tree we entered into).
+ These are our final values for sp and pc since js_SynthesizeFrame has already taken
+ care of all frames in between. */
+ JSStackFrame* fp = cx->fp;
+
+ /* If we are not exiting from an inlined frame the state->sp is spbase, otherwise spbase
+ is whatever slots frames around us consume. */
+ DECODE_IP_ADJ(innermost->ip_adj, fp);
+ fp->regs->sp = StackBase(fp) + (innermost->sp_adj / sizeof(double)) - calldepth_slots;
+ JS_ASSERT_IF(!fp->imacpc,
+ fp->slots + fp->script->nfixed +
+ js_ReconstructStackDepth(cx, fp->script, fp->regs->pc) == fp->regs->sp);
+
+
+#if defined(JS_JIT_SPEW) && (defined(NANOJIT_IA32) || (defined(NANOJIT_AMD64) && defined(__GNUC__)))
+ uint64 cycles = rdtsc() - start;
+#elif defined(JS_JIT_SPEW)
+ uint64 cycles = 0;
+#endif
+
+ debug_only_v(printf("leaving trace at %s:%u@%u, op=%s, lr=%p, exitType=%d, sp=%d, "
+ "calldepth=%d, cycles=%llu\n",
+ fp->script->filename,
+ js_FramePCToLineNumber(cx, fp),
+ FramePCOffset(fp),
+ js_CodeName[fp->imacpc ? *fp->imacpc : *fp->regs->pc],
+ lr,
+ lr->exitType,
+ fp->regs->sp - StackBase(fp),
+ calldepth,
+ cycles));
+
+ /* If this trace is part of a tree, later branches might have added additional globals for
+ with we don't have any type information available in the side exit. We merge in this
+ information from the entry type-map. See also comment in the constructor of TraceRecorder
+ why this is always safe to do. */
+ unsigned exit_gslots = innermost->numGlobalSlots;
+ JS_ASSERT(ngslots == tm->globalTypeMap->length());
+ JS_ASSERT(ngslots >= exit_gslots);
+ uint8* globalTypeMap = getTypeMap(innermost);
+ if (exit_gslots < ngslots)
+ mergeTypeMaps(&globalTypeMap, &exit_gslots, tm->globalTypeMap->data(), ngslots,
+ (uint8*)alloca(sizeof(uint8) * ngslots));
+ JS_ASSERT(exit_gslots == tm->globalTypeMap->length());
+
+ /* write back interned globals */
+ int slots = FlushNativeGlobalFrame(cx, exit_gslots, gslots, globalTypeMap, global);
+ if (slots < 0)
+ return NULL;
+ JS_ASSERT_IF(ngslots != 0, globalFrameSize == STOBJ_NSLOTS(globalObj));
+ JS_ASSERT(*(uint64*)&global[globalFrameSize] == 0xdeadbeefdeadbeefLL);
+
+ /* write back native stack frame */
+ slots = FlushNativeStackFrame(cx, innermost->calldepth,
+ getTypeMap(innermost) + innermost->numGlobalSlots,
+ stack, NULL);
+ if (slots < 0)
+ return NULL;
+ JS_ASSERT(unsigned(slots) == innermost->numStackSlots);
+
+#ifdef DEBUG
+ // Verify that our state restoration worked
+ for (JSStackFrame* fp = cx->fp; fp; fp = fp->down) {
+ JS_ASSERT(!fp->callee || JSVAL_IS_OBJECT(fp->argv[-1]));
+ JS_ASSERT(!fp->callee || fp->thisp == JSVAL_TO_OBJECT(fp->argv[-1]));
+ }
+#endif
+
+ AUDIT(sideExitIntoInterpreter);
+
+ return innermost;
+}
+
+bool
+js_MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ /* Is the recorder currently active? */
+ if (tm->recorder) {
+ if (js_RecordLoopEdge(cx, tm->recorder, inlineCallCount))
+ return true;
+ /* recording was aborted, treat like a regular loop edge hit */
+ }
+ JS_ASSERT(!tm->recorder);
+
+
+ /* Check the recovery pool of doubles (this might trigger a GC). */
+ if (tm->recoveryDoublePoolPtr < (tm->recoveryDoublePool + MAX_NATIVE_STACK_SLOTS) &&
+ !js_ReplenishRecoveryPool(cx, tm)) {
+ return false; /* Out of memory, don't try to record now. */
+ }
+
+ /* Make sure the shape of the global object still matches (this might flush the JIT cache). */
+ JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
+ if (!js_CheckGlobalObjectShape(cx, tm, globalObj))
+ js_FlushJITCache(cx);
+
+ jsbytecode* pc = cx->fp->regs->pc;
+ Fragmento* fragmento = tm->fragmento;
+ Fragment* f;
+ f = fragmento->getLoop(pc);
+ if (!f)
+ f = fragmento->getAnchor(pc);
+
+ /* If we have no code in the anchor and no peers, we definitively won't be able to
+ activate any trees so increment the hit counter and start compiling if appropriate. */
+ if (!f->code() && !f->peer) {
+monitor_loop:
+ if (++f->hits() >= HOTLOOP) {
+ /* We can give RecordTree the root peer. If that peer is already taken, it will
+ walk the peer list and find us a free slot or allocate a new tree if needed. */
+ return js_RecordTree(cx, tm, f->first, NULL, NULL);
+ }
+ /* Threshold not reached yet. */
+ return false;
+ }
+
+ debug_only_v(printf("Looking for compat peer %d@%d, from %p (ip: %p, hits=%d)\n",
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp),
+ f, f->ip, f->hits());)
+ Fragment* match = js_FindVMCompatiblePeer(cx, f);
+ /* If we didn't find a tree that actually matched, keep monitoring the loop. */
+ if (!match)
+ goto monitor_loop;
+
+ VMSideExit* lr = NULL;
+ VMSideExit* innermostNestedGuard = NULL;
+
+ lr = js_ExecuteTree(cx, match, inlineCallCount, &innermostNestedGuard);
+ if (!lr)
+ return false;
+
+ /* If we exit on a branch, or on a tree call guard, try to grow the inner tree (in case
+ of a branch exit), or the tree nested around the tree we exited from (in case of the
+ tree call guard). */
+ switch (lr->exitType) {
+ case UNSTABLE_LOOP_EXIT:
+ return js_AttemptToStabilizeTree(cx, lr, NULL);
+ case BRANCH_EXIT:
+ return js_AttemptToExtendTree(cx, lr, NULL, NULL);
+ case LOOP_EXIT:
+ if (innermostNestedGuard)
+ return js_AttemptToExtendTree(cx, innermostNestedGuard, lr, NULL);
+ return false;
+ default:
+ /* No, this was an unusual exit (i.e. out of memory/GC), so just resume interpretation. */
+ return false;
+ }
+}
+
+bool
+js_MonitorRecording(TraceRecorder* tr)
+{
+ JSContext* cx = tr->cx;
+
+ if (tr->lirbuf->outOmem()) {
+ js_AbortRecording(cx, "no more LIR memory");
+ js_FlushJITCache(cx);
+ return false;
+ }
+
+ if (tr->walkedOutOfLoop())
+ return js_CloseLoop(cx);
+
+ // Clear one-shot state used to communicate between record_JSOP_CALL and mid- and post-
+ // opcode-case-guts record hooks (record_EnterFrame, record_FastNativeCallComplete).
+ tr->applyingArguments = false;
+ tr->pendingTraceableNative = NULL;
+
+ // In the future, handle dslots realloc by computing an offset from dslots instead.
+ if (tr->global_dslots != tr->globalObj->dslots) {
+ js_AbortRecording(cx, "globalObj->dslots reallocated");
+ return false;
+ }
+
+ // Process deepAbort() requests now.
+ if (tr->wasDeepAborted()) {
+ js_AbortRecording(cx, "deep abort requested");
+ return false;
+ }
+
+ jsbytecode* pc = cx->fp->regs->pc;
+
+ /* If we hit a break, end the loop and generate an always taken loop exit guard. For other
+ downward gotos (like if/else) continue recording. */
+ if (*pc == JSOP_GOTO || *pc == JSOP_GOTOX) {
+ jssrcnote* sn = js_GetSrcNote(cx->fp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_BREAK) {
+ AUDIT(breakLoopExits);
+ tr->endLoop(JS_TRACE_MONITOR(cx).fragmento);
+ js_DeleteRecorder(cx);
+ return false; /* done recording */
+ }
+ }
+
+ /* An explicit return from callDepth 0 should end the loop, not abort it. */
+ if (*pc == JSOP_RETURN && tr->callDepth == 0) {
+ AUDIT(returnLoopExits);
+ tr->endLoop(JS_TRACE_MONITOR(cx).fragmento);
+ js_DeleteRecorder(cx);
+ return false; /* done recording */
+ }
+
+ /* If it's not a break or a return from a loop, continue recording and follow the trace. */
+ return true;
+}
+
+/* If used on a loop trace, blacklists the root peer instead of the given fragment. */
+void
+js_BlacklistPC(Fragmento* frago, Fragment* frag)
+{
+ if (frag->kind == LoopTrace)
+ frag = frago->getLoop(frag->ip);
+ frag->blacklist();
+}
+
+void
+js_AbortRecording(JSContext* cx, const char* reason)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ JS_ASSERT(tm->recorder != NULL);
+ AUDIT(recorderAborted);
+
+ /* Abort the trace and blacklist its starting point. */
+ JSStackFrame* fp = cx->fp;
+ if (fp) {
+ debug_only_v(printf("Abort recording (line %d, pc %d): %s.\n",
+ js_FramePCToLineNumber(cx, fp),
+ FramePCOffset(fp),
+ reason);)
+ }
+ Fragment* f = tm->recorder->getFragment();
+ if (!f) {
+ js_DeleteRecorder(cx);
+ return;
+ }
+ JS_ASSERT(!f->vmprivate);
+ js_BlacklistPC(tm->fragmento, f);
+ Fragment* outer = tm->recorder->getOuterToBlacklist();
+ /* Give outer two chances to stabilize before we start blacklisting. */
+ if (outer != NULL && outer->recordAttempts >= 2)
+ js_BlacklistPC(tm->fragmento, outer);
+ js_DeleteRecorder(cx);
+ /* If this is the primary trace and we didn't succeed compiling, trash the TreeInfo object. */
+ if (!f->code() && (f->root == f))
+ js_TrashTree(cx, f);
+}
+
+#if defined NANOJIT_IA32
+static bool
+js_CheckForSSE2()
+{
+ int features = 0;
+#if defined _MSC_VER
+ __asm
+ {
+ pushad
+ mov eax, 1
+ cpuid
+ mov features, edx
+ popad
+ }
+#elif defined __GNUC__
+ asm("xchg %%esi, %%ebx\n" /* we can't clobber ebx on gcc (PIC register) */
+ "mov $0x01, %%eax\n"
+ "cpuid\n"
+ "mov %%edx, %0\n"
+ "xchg %%esi, %%ebx\n"
+ : "=m" (features)
+ : /* We have no inputs */
+ : "%eax", "%esi", "%ecx", "%edx"
+ );
+#elif defined __SUNPRO_C || defined __SUNPRO_CC
+ asm("push %%ebx\n"
+ "mov $0x01, %%eax\n"
+ "cpuid\n"
+ "pop %%ebx\n"
+ : "=d" (features)
+ : /* We have no inputs */
+ : "%eax", "%ecx"
+ );
+#endif
+ return (features & (1<<26)) != 0;
+}
+#endif
+
+static void InitIMacroCode();
+
+extern void
+js_InitJIT(JSTraceMonitor *tm)
+{
+#if defined NANOJIT_IA32
+ if (!did_we_check_sse2) {
+ avmplus::AvmCore::cmov_available =
+ avmplus::AvmCore::sse2_available = js_CheckForSSE2();
+ did_we_check_sse2 = true;
+ }
+#endif
+ if (!tm->fragmento) {
+ JS_ASSERT(!tm->globalSlots && !tm->globalTypeMap && !tm->recoveryDoublePool);
+ Fragmento* fragmento = new (&gc) Fragmento(core, 24);
+ verbose_only(fragmento->labels = new (&gc) LabelMap(core, NULL);)
+ tm->fragmento = fragmento;
+ tm->globalSlots = new (&gc) SlotList();
+ tm->globalTypeMap = new (&gc) TypeMap();
+ tm->recoveryDoublePoolPtr = tm->recoveryDoublePool = new jsval[MAX_NATIVE_STACK_SLOTS];
+ }
+ if (!tm->reFragmento) {
+ Fragmento* fragmento = new (&gc) Fragmento(core, 20);
+ verbose_only(fragmento->labels = new (&gc) LabelMap(core, NULL);)
+ tm->reFragmento = fragmento;
+ }
+ InitIMacroCode();
+#if !defined XP_WIN
+ debug_only(memset(&jitstats, 0, sizeof(jitstats)));
+#endif
+}
+
+extern void
+js_FinishJIT(JSTraceMonitor *tm)
+{
+#ifdef JS_JIT_SPEW
+ printf("recorder: started(%llu), aborted(%llu), completed(%llu), different header(%llu), "
+ "trees trashed(%llu), slot promoted(%llu), unstable loop variable(%llu), "
+ "breaks(%llu), returns(%llu), unstableInnerCalls(%llu)\n",
+ jitstats.recorderStarted, jitstats.recorderAborted, jitstats.traceCompleted,
+ jitstats.returnToDifferentLoopHeader, jitstats.treesTrashed, jitstats.slotPromoted,
+ jitstats.unstableLoopVariable, jitstats.breakLoopExits, jitstats.returnLoopExits,
+ jitstats.noCompatInnerTrees);
+ printf("monitor: triggered(%llu), exits(%llu), type mismatch(%llu), "
+ "global mismatch(%llu)\n", jitstats.traceTriggered, jitstats.sideExitIntoInterpreter,
+ jitstats.typeMapMismatchAtEntry, jitstats.globalShapeMismatchAtEntry);
+#endif
+ if (tm->fragmento != NULL) {
+ JS_ASSERT(tm->globalSlots && tm->globalTypeMap && tm->recoveryDoublePool);
+ verbose_only(delete tm->fragmento->labels;)
+ delete tm->fragmento;
+ tm->fragmento = NULL;
+ delete tm->globalSlots;
+ tm->globalSlots = NULL;
+ delete tm->globalTypeMap;
+ tm->globalTypeMap = NULL;
+ delete[] tm->recoveryDoublePool;
+ tm->recoveryDoublePool = tm->recoveryDoublePoolPtr = NULL;
+ }
+ if (tm->reFragmento != NULL) {
+ verbose_only(delete tm->reFragmento->labels;)
+ delete tm->reFragmento;
+ }
+}
+
+void
+TraceRecorder::pushAbortStack()
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ JS_ASSERT(tm->abortStack != this);
+
+ nextRecorderToAbort = tm->abortStack;
+ tm->abortStack = this;
+}
+
+void
+TraceRecorder::popAbortStack()
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ JS_ASSERT(tm->abortStack == this);
+
+ tm->abortStack = nextRecorderToAbort;
+ nextRecorderToAbort = NULL;
+}
+
+extern void
+js_FlushJITOracle(JSContext* cx)
+{
+ if (!TRACING_ENABLED(cx))
+ return;
+ oracle.clear();
+}
+
+extern void
+js_FlushJITCache(JSContext* cx)
+{
+ if (!TRACING_ENABLED(cx))
+ return;
+ debug_only_v(printf("Flushing cache.\n");)
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ if (tm->recorder)
+ js_AbortRecording(cx, "flush cache");
+ TraceRecorder* tr;
+ while ((tr = tm->abortStack) != NULL) {
+ tr->removeFragmentoReferences();
+ tr->deepAbort();
+ tr->popAbortStack();
+ }
+ Fragmento* fragmento = tm->fragmento;
+ if (fragmento) {
+ fragmento->clearFrags();
+#ifdef DEBUG
+ JS_ASSERT(fragmento->labels);
+ delete fragmento->labels;
+ fragmento->labels = new (&gc) LabelMap(core, NULL);
+#endif
+ }
+ if (cx->fp) {
+ tm->globalShape = OBJ_SHAPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain));
+ tm->globalSlots->clear();
+ tm->globalTypeMap->clear();
+ }
+}
+
+jsval&
+TraceRecorder::argval(unsigned n) const
+{
+ JS_ASSERT(n < cx->fp->fun->nargs);
+ return cx->fp->argv[n];
+}
+
+jsval&
+TraceRecorder::varval(unsigned n) const
+{
+ JS_ASSERT(n < cx->fp->script->nslots);
+ return cx->fp->slots[n];
+}
+
+jsval&
+TraceRecorder::stackval(int n) const
+{
+ jsval* sp = cx->fp->regs->sp;
+ return sp[n];
+}
+
+LIns*
+TraceRecorder::scopeChain() const
+{
+ return lir->insLoad(LIR_ldp,
+ lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, fp)),
+ offsetof(JSStackFrame, scopeChain));
+}
+
+static inline bool
+FrameInRange(JSStackFrame* fp, JSStackFrame *target, unsigned callDepth)
+{
+ while (fp != target) {
+ if (callDepth-- == 0)
+ return false;
+ if (!(fp = fp->down))
+ return false;
+ }
+ return true;
+}
+
+bool
+TraceRecorder::activeCallOrGlobalSlot(JSObject* obj, jsval*& vp)
+{
+ JS_ASSERT(obj != globalObj);
+
+ JSAtom* atom = atoms[GET_INDEX(cx->fp->regs->pc)];
+ JSObject* obj2;
+ JSProperty* prop;
+ if (js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &obj2, &prop) < 0 || !prop)
+ ABORT_TRACE("failed to find name in non-global scope chain");
+
+ if (obj == globalObj) {
+ JSScopeProperty* sprop = (JSScopeProperty*) prop;
+ if (obj2 != obj || !SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj))) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ ABORT_TRACE("prototype or slotless globalObj property");
+ }
+
+ if (!lazilyImportGlobalSlot(sprop->slot))
+ ABORT_TRACE("lazy import of global slot failed");
+ vp = &STOBJ_GET_SLOT(obj, sprop->slot);
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return true;
+ }
+
+ if (obj == obj2 && OBJ_GET_CLASS(cx, obj) == &js_CallClass) {
+ JSStackFrame* cfp = (JSStackFrame*) JS_GetPrivate(cx, obj);
+ if (cfp && FrameInRange(cx->fp, cfp, callDepth)) {
+ JSScopeProperty* sprop = (JSScopeProperty*) prop;
+ uintN slot = sprop->shortid;
+
+ vp = NULL;
+ if (sprop->getter == js_GetCallArg) {
+ JS_ASSERT(slot < cfp->fun->nargs);
+ vp = &cfp->argv[slot];
+ } else if (sprop->getter == js_GetCallVar) {
+ JS_ASSERT(slot < cfp->script->nslots);
+ vp = &cfp->slots[slot];
+ }
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!vp)
+ ABORT_TRACE("dynamic property of Call object");
+ return true;
+ }
+ }
+
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ ABORT_TRACE("fp->scopeChain is not global or active call object");
+}
+
+LIns*
+TraceRecorder::arg(unsigned n)
+{
+ return get(&argval(n));
+}
+
+void
+TraceRecorder::arg(unsigned n, LIns* i)
+{
+ set(&argval(n), i);
+}
+
+LIns*
+TraceRecorder::var(unsigned n)
+{
+ return get(&varval(n));
+}
+
+void
+TraceRecorder::var(unsigned n, LIns* i)
+{
+ set(&varval(n), i);
+}
+
+LIns*
+TraceRecorder::stack(int n)
+{
+ return get(&stackval(n));
+}
+
+void
+TraceRecorder::stack(int n, LIns* i)
+{
+ set(&stackval(n), i, n >= 0);
+}
+
+LIns*
+TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1)
+{
+ if (v == LIR_fadd || v == LIR_fsub) {
+ jsdouble r;
+ if (v == LIR_fadd)
+ r = v0 + v1;
+ else
+ r = v0 - v1;
+ /*
+ * Calculate the result of the addition for the current values. If the
+ * value is not within the integer range, don't even try to demote
+ * here.
+ */
+ if (!JSDOUBLE_IS_NEGZERO(r) && (jsint(r) == r) && isPromoteInt(s0) && isPromoteInt(s1)) {
+ LIns* d0 = ::demote(lir, s0);
+ LIns* d1 = ::demote(lir, s1);
+ /*
+ * If the inputs are constant, generate an integer constant for
+ * this operation.
+ */
+ if (d0->isconst() && d1->isconst())
+ return lir->ins1(LIR_i2f, lir->insImm(jsint(r)));
+ /*
+ * Speculatively generate code that will perform the addition over
+ * the integer inputs as an integer addition/subtraction and exit
+ * if that fails.
+ */
+ v = (LOpcode)((int)v & ~LIR64);
+ LIns* result = lir->ins2(v, d0, d1);
+ if (!overflowSafe(d0) || !overflowSafe(d1)) {
+ lir->insGuard(LIR_xt, lir->ins1(LIR_ov, result),
+ snapshot(OVERFLOW_EXIT));
+ }
+ return lir->ins1(LIR_i2f, result);
+ }
+ /*
+ * The result doesn't fit into the integer domain, so either generate
+ * a floating point constant or a floating point operation.
+ */
+ if (s0->isconst() && s1->isconst()) {
+ jsdpun u;
+ u.d = r;
+ return lir->insImmq(u.u64);
+ }
+ return lir->ins2(v, s0, s1);
+ }
+ return lir->ins2(v, s0, s1);
+}
+
+LIns*
+TraceRecorder::f2i(LIns* f)
+{
+ return lir->insCall(&js_DoubleToInt32_ci, &f);
+}
+
+LIns*
+TraceRecorder::makeNumberInt32(LIns* f)
+{
+ JS_ASSERT(f->isQuad());
+ LIns* x;
+ if (!isPromote(f)) {
+ x = f2i(f);
+ guard(true, lir->ins2(LIR_feq, f, lir->ins1(LIR_i2f, x)), MISMATCH_EXIT);
+ } else {
+ x = ::demote(lir, f);
+ }
+ return x;
+}
+
+LIns*
+TraceRecorder::stringify(jsval& v)
+{
+ LIns* v_ins = get(&v);
+ if (JSVAL_IS_STRING(v))
+ return v_ins;
+
+ LIns* args[] = { v_ins, cx_ins };
+ const CallInfo* ci;
+ if (JSVAL_IS_NUMBER(v)) {
+ ci = &js_NumberToString_ci;
+ } else if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
+ ci = &js_BooleanOrUndefinedToString_ci;
+ } else {
+ /* We can't stringify objects here (use imacros instead), just return NULL. */
+ return NULL;
+ }
+ v_ins = lir->insCall(ci, args);
+ guard(false, lir->ins_eq0(v_ins), OOM_EXIT);
+ return v_ins;
+}
+
+bool
+TraceRecorder::call_imacro(jsbytecode* imacro)
+{
+ JSStackFrame* fp = cx->fp;
+ JSFrameRegs* regs = fp->regs;
+
+ if (!fp->imacpc) {
+ fp->imacpc = regs->pc;
+ fp->flags |= JSFRAME_IMACRO_START;
+ regs->pc = imacro;
+ atoms = COMMON_ATOMS_START(&cx->runtime->atomState);
+ }
+ return false;
+}
+
+bool
+TraceRecorder::ifop()
+{
+ jsval& v = stackval(-1);
+ LIns* v_ins = get(&v);
+ bool cond;
+ LIns* x;
+ /* no need to guard if condition is constant */
+ if (v_ins->isconst() || v_ins->isconstq())
+ return true;
+ if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
+ /* test for boolean is true, negate later if we are testing for false */
+ cond = JSVAL_TO_BOOLEAN(v) == 1;
+ x = lir->ins2i(LIR_eq, v_ins, 1);
+ } else if (JSVAL_IS_OBJECT(v)) {
+ cond = !JSVAL_IS_NULL(v);
+ x = v_ins;
+ } else if (isNumber(v)) {
+ jsdouble d = asNumber(v);
+ cond = !JSDOUBLE_IS_NaN(d) && d;
+ jsdpun u;
+ u.d = 0;
+ x = lir->ins2(LIR_and,
+ lir->ins2(LIR_feq, v_ins, v_ins),
+ lir->ins_eq0(lir->ins2(LIR_feq, v_ins, lir->insImmq(u.u64))));
+ } else if (JSVAL_IS_STRING(v)) {
+ cond = JSSTRING_LENGTH(JSVAL_TO_STRING(v)) != 0;
+ x = lir->ins2(LIR_piand,
+ lir->insLoad(LIR_ldp,
+ v_ins,
+ (int)offsetof(JSString, length)),
+ INS_CONSTPTR(JSSTRING_LENGTH_MASK));
+ } else {
+ JS_NOT_REACHED("ifop");
+ return false;
+ }
+ flipIf(cx->fp->regs->pc, cond);
+ bool expected = cond;
+ if (!x->isCond()) {
+ x = lir->ins_eq0(x);
+ expected = !expected;
+ }
+ guard(expected, x, BRANCH_EXIT);
+ return true;
+}
+
+bool
+TraceRecorder::switchop()
+{
+ jsval& v = stackval(-1);
+ LIns* v_ins = get(&v);
+ /* no need to guard if condition is constant */
+ if (v_ins->isconst() || v_ins->isconstq())
+ return true;
+ if (isNumber(v)) {
+ jsdouble d = asNumber(v);
+ jsdpun u;
+ u.d = d;
+ guard(true,
+ addName(lir->ins2(LIR_feq, v_ins, lir->insImmq(u.u64)),
+ "guard(switch on numeric)"),
+ BRANCH_EXIT);
+ } else if (JSVAL_IS_STRING(v)) {
+ LIns* args[] = { v_ins, INS_CONSTPTR(JSVAL_TO_STRING(v)) };
+ guard(true,
+ addName(lir->ins_eq0(lir->ins_eq0(lir->insCall(&js_EqualStrings_ci, args))),
+ "guard(switch on string)"),
+ BRANCH_EXIT);
+ } else if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
+ guard(true,
+ addName(lir->ins2(LIR_eq, v_ins, lir->insImm(JSVAL_TO_BOOLEAN(v))),
+ "guard(switch on boolean)"),
+ BRANCH_EXIT);
+ } else {
+ ABORT_TRACE("switch on object or null");
+ }
+ return true;
+}
+
+bool
+TraceRecorder::inc(jsval& v, jsint incr, bool pre)
+{
+ LIns* v_ins = get(&v);
+ if (!inc(v, v_ins, incr, pre))
+ return false;
+ set(&v, v_ins);
+ return true;
+}
+
+/*
+ * On exit, v_ins is the incremented unboxed value, and the appropriate
+ * value (pre- or post-increment as described by pre) is stacked.
+ */
+bool
+TraceRecorder::inc(jsval& v, LIns*& v_ins, jsint incr, bool pre)
+{
+ if (!isNumber(v))
+ ABORT_TRACE("can only inc numbers");
+
+ jsdpun u;
+ u.d = jsdouble(incr);
+
+ LIns* v_after = alu(LIR_fadd, asNumber(v), incr, v_ins, lir->insImmq(u.u64));
+
+ const JSCodeSpec& cs = js_CodeSpec[*cx->fp->regs->pc];
+ JS_ASSERT(cs.ndefs == 1);
+ stack(-cs.nuses, pre ? v_after : v_ins);
+ v_ins = v_after;
+ return true;
+}
+
+bool
+TraceRecorder::incProp(jsint incr, bool pre)
+{
+ jsval& l = stackval(-1);
+ if (JSVAL_IS_PRIMITIVE(l))
+ ABORT_TRACE("incProp on primitive");
+
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ LIns* obj_ins = get(&l);
+
+ uint32 slot;
+ LIns* v_ins;
+ if (!prop(obj, obj_ins, slot, v_ins))
+ return false;
+
+ if (slot == SPROP_INVALID_SLOT)
+ ABORT_TRACE("incProp on invalid slot");
+
+ jsval& v = STOBJ_GET_SLOT(obj, slot);
+ if (!inc(v, v_ins, incr, pre))
+ return false;
+
+ if (!box_jsval(v, v_ins))
+ return false;
+
+ LIns* dslots_ins = NULL;
+ stobj_set_slot(obj_ins, slot, dslots_ins, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::incElem(jsint incr, bool pre)
+{
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+ jsval* vp;
+ LIns* v_ins;
+ LIns* addr_ins;
+ if (!elem(l, r, vp, v_ins, addr_ins))
+ return false;
+ if (!addr_ins) // if we read a hole, abort
+ return false;
+ if (!inc(*vp, v_ins, incr, pre))
+ return false;
+ if (!box_jsval(*vp, v_ins))
+ return false;
+ lir->insStorei(v_ins, addr_ins, 0);
+ return true;
+}
+
+static bool
+evalCmp(LOpcode op, double result)
+{
+ bool cond;
+ switch (op) {
+ case LIR_feq:
+ cond = (result == 0);
+ break;
+ case LIR_flt:
+ cond = result < 0;
+ break;
+ case LIR_fgt:
+ cond = result > 0;
+ break;
+ case LIR_fle:
+ cond = result <= 0;
+ break;
+ case LIR_fge:
+ cond = result >= 0;
+ break;
+ default:
+ JS_NOT_REACHED("unexpected comparison op");
+ return false;
+ }
+ return cond;
+}
+
+static bool
+evalCmp(LOpcode op, double l, double r)
+{
+ return evalCmp(op, l - r);
+}
+
+static bool
+evalCmp(LOpcode op, JSString* l, JSString* r)
+{
+ if (op == LIR_feq)
+ return js_EqualStrings(l, r);
+ return evalCmp(op, js_CompareStrings(l, r));
+}
+
+static struct {
+ jsbytecode obj_any[13];
+ jsbytecode any_obj[11];
+ jsbytecode obj_obj[22];
+} binary_imacros = {
+ {
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+ JSOP_CALL, 0, 1,
+ JSOP_SWAP,
+ JSOP_IMACOP,
+ JSOP_STOP
+ },
+
+ {
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+ JSOP_CALL, 0, 1,
+ JSOP_IMACOP,
+ JSOP_STOP
+ },
+
+ {
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+ JSOP_CALL, 0, 1,
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+ JSOP_CALL, 0, 1,
+ JSOP_IMACOP,
+ JSOP_STOP
+ }
+};
+
+JS_STATIC_ASSERT(sizeof(binary_imacros) < IMACRO_PC_ADJ_LIMIT);
+
+bool
+TraceRecorder::cmp(LOpcode op, int flags)
+{
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+ LIns* x = NULL;
+ bool negate = !!(flags & CMP_NEGATE);
+ bool cond;
+ LIns* l_ins = get(&l);
+ LIns* r_ins = get(&r);
+ bool fp = false;
+
+ if (op != LIR_feq) {
+ if (JSVAL_IS_OBJECT(l) && hasValueOfMethod(l)) {
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.obj_obj);
+ return call_imacro(binary_imacros.obj_any);
+ }
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.any_obj);
+ }
+
+ // CMP_STRICT is set only for JSOP_STRICTEQ and JSOP_STRICTNE, which correspond to the
+ // === and !== operators. negate is true for !== and false for ===. The strict equality
+ // operators produce false if the types of the operands differ, i.e. if only one of
+ // them is a number.
+ if ((flags & CMP_STRICT) && getPromotedType(l) != getPromotedType(r)) {
+ x = INS_CONST(negate);
+ cond = negate;
+ } else if (JSVAL_IS_STRING(l) || JSVAL_IS_STRING(r)) {
+ // Comparing equality of a string against null always produces false.
+ if (op == LIR_feq &&
+ ((JSVAL_IS_NULL(l) && l_ins->isconst()) ||
+ (JSVAL_IS_NULL(r) && r_ins->isconst()))) {
+ x = INS_CONST(negate);
+ cond = negate;
+ } else {
+ if (!JSVAL_IS_STRING(l) || !JSVAL_IS_STRING(r))
+ ABORT_TRACE("unsupported type for cmp vs string");
+
+ LIns* args[] = { r_ins, l_ins };
+ if (op == LIR_feq)
+ l_ins = lir->ins_eq0(lir->insCall(&js_EqualStrings_ci, args));
+ else
+ l_ins = lir->insCall(&js_CompareStrings_ci, args);
+ r_ins = lir->insImm(0);
+ cond = evalCmp(op, JSVAL_TO_STRING(l), JSVAL_TO_STRING(r));
+ }
+ } else if (isNumber(l) || isNumber(r)) {
+ jsval tmp[2] = {l, r};
+ JSAutoTempValueRooter tvr(cx, 2, tmp);
+
+ fp = true;
+
+ // TODO: coerce non-numbers to numbers if it's not string-on-string above
+ jsdouble lnum;
+ jsdouble rnum;
+ LIns* args[] = { l_ins, cx_ins };
+ if (l == JSVAL_NULL && l_ins->isconst()) {
+ jsdpun u;
+ u.d = (op == LIR_feq) ? js_NaN : 0.0;
+ l_ins = lir->insImmq(u.u64);
+ } else if (JSVAL_IS_STRING(l)) {
+ l_ins = lir->insCall(&js_StringToNumber_ci, args);
+ } else if (JSVAL_TAG(l) == JSVAL_BOOLEAN) {
+ /*
+ * What I really want here is for undefined to be type-specialized
+ * differently from real booleans. Failing that, I want to be able
+ * to cmov on quads. Failing that, I want to have small forward
+ * branches. Failing that, I want to be able to ins_choose on quads
+ * without cmov. Failing that, eat flaming builtin!
+ */
+ l_ins = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
+ } else if (!isNumber(l)) {
+ ABORT_TRACE("unsupported LHS type for cmp vs number");
+ }
+ lnum = js_ValueToNumber(cx, &tmp[0]);
+
+ args[0] = r_ins;
+ args[1] = cx_ins;
+ if (r == JSVAL_NULL && r_ins->isconst()) {
+ jsdpun u;
+ u.d = (op == LIR_feq) ? js_NaN : 0.0;
+ r_ins = lir->insImmq(u.u64);
+ } else if (JSVAL_IS_STRING(r)) {
+ r_ins = lir->insCall(&js_StringToNumber_ci, args);
+ } else if (JSVAL_TAG(r) == JSVAL_BOOLEAN) {
+ // See above for the sob story.
+ r_ins = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
+ } else if (!isNumber(r)) {
+ ABORT_TRACE("unsupported RHS type for cmp vs number");
+ }
+ rnum = js_ValueToNumber(cx, &tmp[1]);
+ cond = evalCmp(op, lnum, rnum);
+ } else if ((JSVAL_TAG(l) == JSVAL_BOOLEAN) && (JSVAL_TAG(r) == JSVAL_BOOLEAN)) {
+ // The well-known values of JSVAL_TRUE and JSVAL_FALSE make this very easy.
+ // In particular: JSVAL_TO_BOOLEAN(0) < JSVAL_TO_BOOLEAN(1) so all of these comparisons do
+ // the right thing.
+ cond = evalCmp(op, l, r);
+ // For ==, !=, ===, and !=== the result is magically correct even if undefined (2) is
+ // involved. For the relational operations we need some additional cmov magic to make
+ // the result always false (since undefined becomes NaN per ECMA and that doesn't
+ // compare to anything, even itself). The code for this is emitted a few lines down.
+ } else if (JSVAL_IS_OBJECT(l) && JSVAL_IS_OBJECT(r)) {
+ if (op != LIR_feq) {
+ JS_NOT_REACHED("we should have converted to numbers already");
+ return false;
+ }
+ cond = (l == r);
+ } else {
+ ABORT_TRACE("unsupported operand types for cmp");
+ }
+
+ /* If we didn't generate a constant result yet, then emit the comparison now. */
+ if (!x) {
+ /* If the result is not a number or it's not a quad, we must use an integer compare. */
+ if (!fp) {
+ JS_ASSERT(op >= LIR_feq && op <= LIR_fge);
+ op = LOpcode(op + (LIR_eq - LIR_feq));
+ }
+ x = lir->ins2(op, l_ins, r_ins);
+ if (negate) {
+ x = lir->ins_eq0(x);
+ cond = !cond;
+ }
+ // For boolean comparison we need a bit post-processing to make the result false if
+ // either side is undefined.
+ if (op != LIR_eq && (JSVAL_TAG(l) == JSVAL_BOOLEAN) && (JSVAL_TAG(r) == JSVAL_BOOLEAN)) {
+ x = lir->ins_choose(lir->ins2i(LIR_eq,
+ lir->ins2i(LIR_and,
+ lir->ins2(LIR_or, l_ins, r_ins),
+ JSVAL_TO_BOOLEAN(JSVAL_VOID)),
+ JSVAL_TO_BOOLEAN(JSVAL_VOID)),
+ lir->insImm(JSVAL_TO_BOOLEAN(JSVAL_FALSE)),
+ x);
+ x = lir->ins_eq0(lir->ins_eq0(x));
+ if ((l == JSVAL_VOID) || (r == JSVAL_VOID))
+ cond = false;
+ }
+ }
+
+ /* Don't guard if the same path is always taken. */
+ if (!x->isconst()) {
+ if (flags & CMP_CASE) {
+ guard(cond, x, BRANCH_EXIT);
+ return true;
+ }
+
+ /* The interpreter fuses comparisons and the following branch,
+ so we have to do that here as well. */
+ if (flags & CMP_TRY_BRANCH_AFTER_COND) {
+ fuseIf(cx->fp->regs->pc + 1, cond, x);
+ }
+ } else if (flags & CMP_CASE) {
+ return true;
+ }
+
+ /* We update the stack after the guard. This is safe since
+ the guard bails out at the comparison and the interpreter
+ will therefore re-execute the comparison. This way the
+ value of the condition doesn't have to be calculated and
+ saved on the stack in most cases. */
+ set(&l, x);
+ return true;
+}
+
+bool
+TraceRecorder::unary(LOpcode op)
+{
+ jsval& v = stackval(-1);
+ bool intop = !(op & LIR64);
+ if (isNumber(v)) {
+ LIns* a = get(&v);
+ if (intop)
+ a = f2i(a);
+ a = lir->ins1(op, a);
+ if (intop)
+ a = lir->ins1(LIR_i2f, a);
+ set(&v, a);
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::binary(LOpcode op)
+{
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+
+ if (JSVAL_IS_OBJECT(l) && hasValueOfMethod(l)) {
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.obj_obj);
+ return call_imacro(binary_imacros.obj_any);
+ }
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.any_obj);
+
+ bool intop = !(op & LIR64);
+ LIns* a = get(&l);
+ LIns* b = get(&r);
+
+ bool leftIsNumber = isNumber(l);
+ jsdouble lnum = leftIsNumber ? asNumber(l) : 0;
+
+ bool rightIsNumber = isNumber(r);
+ jsdouble rnum = rightIsNumber ? asNumber(r) : 0;
+
+ if ((op >= LIR_sub && op <= LIR_ush) || // sub, mul, (callh), or, xor, (not,) lsh, rsh, ush
+ (op >= LIR_fsub && op <= LIR_fdiv)) { // fsub, fmul, fdiv
+ LIns* args[2];
+ if (JSVAL_IS_STRING(l)) {
+ args[0] = a;
+ args[1] = cx_ins;
+ a = lir->insCall(&js_StringToNumber_ci, args);
+ lnum = js_StringToNumber(cx, JSVAL_TO_STRING(l));
+ leftIsNumber = true;
+ }
+ if (JSVAL_IS_STRING(r)) {
+ args[0] = b;
+ args[1] = cx_ins;
+ b = lir->insCall(&js_StringToNumber_ci, args);
+ rnum = js_StringToNumber(cx, JSVAL_TO_STRING(r));
+ rightIsNumber = true;
+ }
+ }
+ if (JSVAL_TAG(l) == JSVAL_BOOLEAN) {
+ LIns* args[] = { a, cx_ins };
+ a = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
+ lnum = js_BooleanOrUndefinedToNumber(cx, JSVAL_TO_BOOLEAN(l));
+ leftIsNumber = true;
+ }
+ if (JSVAL_TAG(r) == JSVAL_BOOLEAN) {
+ LIns* args[] = { b, cx_ins };
+ b = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
+ rnum = js_BooleanOrUndefinedToNumber(cx, JSVAL_TO_BOOLEAN(r));
+ rightIsNumber = true;
+ }
+ if (leftIsNumber && rightIsNumber) {
+ if (intop) {
+ LIns *args[] = { a };
+ a = lir->insCall(op == LIR_ush ? &js_DoubleToUint32_ci : &js_DoubleToInt32_ci, args);
+ b = f2i(b);
+ }
+ a = alu(op, lnum, rnum, a, b);
+ if (intop)
+ a = lir->ins1(op == LIR_ush ? LIR_u2f : LIR_i2f, a);
+ set(&l, a);
+ return true;
+ }
+ return false;
+}
+
+JS_STATIC_ASSERT(offsetof(JSObjectOps, newObjectMap) == 0);
+
+bool
+TraceRecorder::map_is_native(JSObjectMap* map, LIns* map_ins, LIns*& ops_ins, size_t op_offset)
+{
+ ops_ins = addName(lir->insLoad(LIR_ldp, map_ins, offsetof(JSObjectMap, ops)), "ops");
+ LIns* n = lir->insLoad(LIR_ldp, ops_ins, op_offset);
+
+#define OP(ops) (*(JSObjectOp*) ((char*)(ops) + op_offset))
+
+ if (OP(map->ops) == OP(&js_ObjectOps)) {
+ guard(true, addName(lir->ins2(LIR_eq, n, INS_CONSTPTR(OP(&js_ObjectOps))),
+ "guard(native-map)"),
+ MISMATCH_EXIT);
+ return true;
+ }
+
+#undef OP
+ ABORT_TRACE("non-native map");
+}
+
+bool
+TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2, jsuword& pcval)
+{
+ jsbytecode* pc = cx->fp->regs->pc;
+ JS_ASSERT(*pc != JSOP_INITPROP && *pc != JSOP_SETNAME && *pc != JSOP_SETPROP);
+
+ // Mimic the interpreter's special case for dense arrays by skipping up one
+ // hop along the proto chain when accessing a named (not indexed) property,
+ // typically to find Array.prototype methods.
+ JSObject* aobj = obj;
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ aobj = OBJ_GET_PROTO(cx, obj);
+ obj_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO);
+ }
+
+ LIns* map_ins = lir->insLoad(LIR_ldp, obj_ins, (int)offsetof(JSObject, map));
+ LIns* ops_ins;
+
+ // Interpreter calls to PROPERTY_CACHE_TEST guard on native object ops
+ // (newObjectMap == js_ObjectOps.newObjectMap) which is required to use
+ // native objects (those whose maps are scopes), or even more narrow
+ // conditions required because the cache miss case will call a particular
+ // object-op (js_GetProperty, js_SetProperty).
+ //
+ // We parameterize using offsetof and guard on match against the hook at
+ // the given offset in js_ObjectOps. TraceRecorder::record_JSOP_SETPROP
+ // guards the js_SetProperty case.
+ uint32 format = js_CodeSpec[*pc].format;
+ uint32 mode = JOF_MODE(format);
+
+ // No need to guard native-ness of global object.
+ JS_ASSERT(OBJ_IS_NATIVE(globalObj));
+ if (aobj != globalObj) {
+ size_t op_offset = 0;
+ if (mode == JOF_PROP || mode == JOF_VARPROP) {
+ JS_ASSERT(!(format & JOF_SET));
+ op_offset = offsetof(JSObjectOps, getProperty);
+ } else {
+ JS_ASSERT(mode == JOF_NAME);
+ }
+
+ if (!map_is_native(aobj->map, map_ins, ops_ins, op_offset))
+ return false;
+ }
+
+ JSAtom* atom;
+ JSPropCacheEntry* entry;
+ PROPERTY_CACHE_TEST(cx, pc, aobj, obj2, entry, atom);
+ if (atom) {
+ // Miss: pre-fill the cache for the interpreter, as well as for our needs.
+ // FIXME: 452357 - correctly propagate exceptions into the interpreter from
+ // js_FindPropertyHelper, js_LookupPropertyWithFlags, and elsewhere.
+ jsid id = ATOM_TO_JSID(atom);
+ JSProperty* prop;
+ if (JOF_OPMODE(*pc) == JOF_NAME) {
+ JS_ASSERT(aobj == obj);
+ if (js_FindPropertyHelper(cx, id, &obj, &obj2, &prop, &entry) < 0)
+ ABORT_TRACE("failed to find name");
+ } else {
+ int protoIndex = js_LookupPropertyWithFlags(cx, aobj, id,
+ cx->resolveFlags,
+ &obj2, &prop);
+ if (protoIndex < 0)
+ ABORT_TRACE("failed to lookup property");
+
+ if (prop) {
+ js_FillPropertyCache(cx, aobj, OBJ_SHAPE(aobj), 0, protoIndex, obj2,
+ (JSScopeProperty*) prop, &entry);
+ }
+ }
+
+ if (!prop) {
+ // Propagate obj from js_FindPropertyHelper to record_JSOP_BINDNAME
+ // via our obj2 out-parameter. If we are recording JSOP_SETNAME and
+ // the global it's assigning does not yet exist, create it.
+ obj2 = obj;
+
+ // Use PCVAL_NULL to return "no such property" to our caller.
+ pcval = PCVAL_NULL;
+ ABORT_TRACE("failed to find property");
+ }
+
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!entry)
+ ABORT_TRACE("failed to fill property cache");
+ }
+
+#ifdef JS_THREADSAFE
+ // There's a potential race in any JS_THREADSAFE embedding that's nuts
+ // enough to share mutable objects on the scope or proto chain, but we
+ // don't care about such insane embeddings. Anyway, the (scope, proto)
+ // entry->vcap coordinates must reach obj2 from aobj at this point.
+ JS_ASSERT(cx->requestDepth);
+#endif
+
+ // Emit guard(s), common code for both hit and miss cases.
+ // Check for first-level cache hit and guard on kshape if possible.
+ // Otherwise guard on key object exact match.
+ if (PCVCAP_TAG(entry->vcap) <= 1) {
+ if (aobj != globalObj) {
+ LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)),
+ "shape");
+ guard(true, addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard(kshape)"),
+ MISMATCH_EXIT);
+ }
+ } else {
+#ifdef DEBUG
+ JSOp op = JSOp(*pc);
+ ptrdiff_t pcoff = (op == JSOP_GETARGPROP) ? ARGNO_LEN :
+ (op == JSOP_GETLOCALPROP) ? SLOTNO_LEN : 0;
+ jsatomid index = js_GetIndexFromBytecode(cx, cx->fp->script, pc, pcoff);
+ JS_ASSERT(entry->kpc == (jsbytecode*) atoms[index]);
+ JS_ASSERT(entry->kshape == jsuword(aobj));
+#endif
+ if (aobj != globalObj) {
+ guard(true, addName(lir->ins2i(LIR_eq, obj_ins, entry->kshape), "guard(kobj)"),
+ MISMATCH_EXIT);
+ }
+ }
+
+ // For any hit that goes up the scope and/or proto chains, we will need to
+ // guard on the shape of the object containing the property.
+ if (PCVCAP_TAG(entry->vcap) >= 1) {
+ jsuword vcap = entry->vcap;
+ uint32 vshape = PCVCAP_SHAPE(vcap);
+ JS_ASSERT(OBJ_SHAPE(obj2) == vshape);
+
+ LIns* obj2_ins;
+ if (PCVCAP_TAG(entry->vcap) == 1) {
+ // Duplicate the special case in PROPERTY_CACHE_TEST.
+ obj2_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO);
+ guard(false, lir->ins_eq0(obj2_ins), MISMATCH_EXIT);
+ } else {
+ obj2_ins = INS_CONSTPTR(obj2);
+ }
+ map_ins = lir->insLoad(LIR_ldp, obj2_ins, (int)offsetof(JSObject, map));
+ if (!map_is_native(obj2->map, map_ins, ops_ins))
+ return false;
+
+ LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)),
+ "shape");
+ guard(true,
+ addName(lir->ins2i(LIR_eq, shape_ins, vshape), "guard(vshape)"),
+ MISMATCH_EXIT);
+ }
+
+ pcval = entry->vword;
+ return true;
+}
+
+bool
+TraceRecorder::test_property_cache_direct_slot(JSObject* obj, LIns* obj_ins, uint32& slot)
+{
+ JSObject* obj2;
+ jsuword pcval;
+
+ /*
+ * Property cache ensures that we are dealing with an existing property,
+ * and guards the shape for us.
+ */
+ if (!test_property_cache(obj, obj_ins, obj2, pcval))
+ return false;
+
+ /* No such property means invalid slot, which callers must check for first. */
+ if (PCVAL_IS_NULL(pcval)) {
+ slot = SPROP_INVALID_SLOT;
+ return true;
+ }
+
+ /* Insist on obj being the directly addressed object. */
+ if (obj2 != obj)
+ ABORT_TRACE("test_property_cache_direct_slot hit prototype chain");
+
+ /* Don't trace getter or setter calls, our caller wants a direct slot. */
+ if (PCVAL_IS_SPROP(pcval)) {
+ JSScopeProperty* sprop = PCVAL_TO_SPROP(pcval);
+
+ uint32 setflags = (js_CodeSpec[*cx->fp->regs->pc].format & (JOF_SET | JOF_INCDEC));
+ if (setflags && !SPROP_HAS_STUB_SETTER(sprop))
+ ABORT_TRACE("non-stub setter");
+ if (setflags != JOF_SET && !SPROP_HAS_STUB_GETTER(sprop))
+ ABORT_TRACE("non-stub getter");
+ if (!SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)))
+ ABORT_TRACE("no valid slot");
+ slot = sprop->slot;
+ } else {
+ if (!PCVAL_IS_SLOT(pcval))
+ ABORT_TRACE("PCE is not a slot");
+ slot = PCVAL_TO_SLOT(pcval);
+ }
+ return true;
+}
+
+void
+TraceRecorder::stobj_set_slot(LIns* obj_ins, unsigned slot, LIns*& dslots_ins, LIns* v_ins)
+{
+ if (slot < JS_INITIAL_NSLOTS) {
+ addName(lir->insStorei(v_ins, obj_ins,
+ offsetof(JSObject, fslots) + slot * sizeof(jsval)),
+ "set_slot(fslots)");
+ } else {
+ if (!dslots_ins)
+ dslots_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots));
+ addName(lir->insStorei(v_ins, dslots_ins,
+ (slot - JS_INITIAL_NSLOTS) * sizeof(jsval)),
+ "set_slot(dslots");
+ }
+}
+
+LIns*
+TraceRecorder::stobj_get_fslot(LIns* obj_ins, unsigned slot)
+{
+ JS_ASSERT(slot < JS_INITIAL_NSLOTS);
+ return lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, fslots) + slot * sizeof(jsval));
+}
+
+LIns*
+TraceRecorder::stobj_get_slot(LIns* obj_ins, unsigned slot, LIns*& dslots_ins)
+{
+ if (slot < JS_INITIAL_NSLOTS)
+ return stobj_get_fslot(obj_ins, slot);
+
+ if (!dslots_ins)
+ dslots_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots));
+ return lir->insLoad(LIR_ldp, dslots_ins, (slot - JS_INITIAL_NSLOTS) * sizeof(jsval));
+}
+
+bool
+TraceRecorder::native_set(LIns* obj_ins, JSScopeProperty* sprop, LIns*& dslots_ins, LIns* v_ins)
+{
+ if (SPROP_HAS_STUB_SETTER(sprop) && sprop->slot != SPROP_INVALID_SLOT) {
+ stobj_set_slot(obj_ins, sprop->slot, dslots_ins, v_ins);
+ return true;
+ }
+ ABORT_TRACE("unallocated or non-stub sprop");
+}
+
+bool
+TraceRecorder::native_get(LIns* obj_ins, LIns* pobj_ins, JSScopeProperty* sprop,
+ LIns*& dslots_ins, LIns*& v_ins)
+{
+ if (!SPROP_HAS_STUB_GETTER(sprop))
+ return false;
+
+ if (sprop->slot != SPROP_INVALID_SLOT)
+ v_ins = stobj_get_slot(pobj_ins, sprop->slot, dslots_ins);
+ else
+ v_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+ return true;
+}
+
+// So box_jsval can emit no LIR_or at all to tag an object jsval.
+JS_STATIC_ASSERT(JSVAL_OBJECT == 0);
+
+bool
+TraceRecorder::box_jsval(jsval v, LIns*& v_ins)
+{
+ if (isNumber(v)) {
+ LIns* args[] = { v_ins, cx_ins };
+ v_ins = lir->insCall(&js_BoxDouble_ci, args);
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)),
+ OOM_EXIT);
+ return true;
+ }
+ switch (JSVAL_TAG(v)) {
+ case JSVAL_BOOLEAN:
+ v_ins = lir->ins2i(LIR_pior, lir->ins2i(LIR_pilsh, v_ins, JSVAL_TAGBITS), JSVAL_BOOLEAN);
+ return true;
+ case JSVAL_OBJECT:
+ return true;
+ case JSVAL_STRING:
+ v_ins = lir->ins2(LIR_pior, v_ins, INS_CONST(JSVAL_STRING));
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::unbox_jsval(jsval v, LIns*& v_ins)
+{
+ if (isNumber(v)) {
+ // JSVAL_IS_NUMBER(v)
+ guard(false,
+ lir->ins_eq0(lir->ins2(LIR_pior,
+ lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_INT)),
+ lir->ins2i(LIR_eq,
+ lir->ins2(LIR_piand, v_ins,
+ INS_CONST(JSVAL_TAGMASK)),
+ JSVAL_DOUBLE))),
+ MISMATCH_EXIT);
+ LIns* args[] = { v_ins };
+ v_ins = lir->insCall(&js_UnboxDouble_ci, args);
+ return true;
+ }
+ switch (JSVAL_TAG(v)) {
+ case JSVAL_BOOLEAN:
+ guard(true,
+ lir->ins2i(LIR_eq,
+ lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_TAGMASK)),
+ JSVAL_BOOLEAN),
+ MISMATCH_EXIT);
+ v_ins = lir->ins2i(LIR_ush, v_ins, JSVAL_TAGBITS);
+ return true;
+ case JSVAL_OBJECT:
+ guard(true,
+ lir->ins2i(LIR_eq,
+ lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_TAGMASK)),
+ JSVAL_OBJECT),
+ MISMATCH_EXIT);
+ return true;
+ case JSVAL_STRING:
+ guard(true,
+ lir->ins2i(LIR_eq,
+ lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_TAGMASK)),
+ JSVAL_STRING),
+ MISMATCH_EXIT);
+ v_ins = lir->ins2(LIR_piand, v_ins, INS_CONST(~JSVAL_TAGMASK));
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::getThis(LIns*& this_ins)
+{
+ if (cx->fp->callee) { /* in a function */
+ if (JSVAL_IS_NULL(cx->fp->argv[-1]))
+ return false;
+ this_ins = get(&cx->fp->argv[-1]);
+ guard(false, lir->ins_eq0(this_ins), MISMATCH_EXIT);
+ } else { /* in global code */
+ this_ins = scopeChain();
+ }
+ return true;
+}
+
+bool
+TraceRecorder::guardClass(JSObject* obj, LIns* obj_ins, JSClass* clasp, ExitType exitType)
+{
+ bool cond = STOBJ_GET_CLASS(obj) == clasp;
+
+ LIns* class_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, classword));
+ class_ins = lir->ins2(LIR_piand, class_ins, lir->insImm(~3));
+
+ char namebuf[32];
+ JS_snprintf(namebuf, sizeof namebuf, "guard(class is %s)", clasp->name);
+ guard(cond, addName(lir->ins2(LIR_eq, class_ins, INS_CONSTPTR(clasp)), namebuf), exitType);
+ return cond;
+}
+
+bool
+TraceRecorder::guardDenseArray(JSObject* obj, LIns* obj_ins, ExitType exitType)
+{
+ return guardClass(obj, obj_ins, &js_ArrayClass, exitType);
+}
+
+bool
+TraceRecorder::guardDenseArrayIndex(JSObject* obj, jsint idx, LIns* obj_ins,
+ LIns* dslots_ins, LIns* idx_ins, ExitType exitType)
+{
+ jsuint length = ARRAY_DENSE_LENGTH(obj);
+
+ bool cond = (jsuint(idx) < jsuint(obj->fslots[JSSLOT_ARRAY_LENGTH]) && jsuint(idx) < length);
+ if (cond) {
+ /* Guard array length */
+ LIns* exit = guard(true,
+ lir->ins2(LIR_ult, idx_ins, stobj_get_fslot(obj_ins, JSSLOT_ARRAY_LENGTH)),
+ exitType)->oprnd2();
+ /* dslots must not be NULL */
+ guard(false,
+ lir->ins_eq0(dslots_ins),
+ exit);
+ /* Guard array capacity */
+ guard(true,
+ lir->ins2(LIR_ult,
+ idx_ins,
+ lir->insLoad(LIR_ldp, dslots_ins, 0 - (int)sizeof(jsval))),
+ exit);
+ } else {
+ /* If not idx < length, stay on trace (and read value as undefined). */
+ LIns* br1 = lir->insBranch(LIR_jf,
+ lir->ins2(LIR_ult,
+ idx_ins,
+ stobj_get_fslot(obj_ins, JSSLOT_ARRAY_LENGTH)),
+ NULL);
+ /* If dslots is NULL, stay on trace (and read value as undefined). */
+ LIns* br2 = lir->insBranch(LIR_jt, lir->ins_eq0(dslots_ins), NULL);
+ /* If not idx < capacity, stay on trace (and read value as undefined). */
+ LIns* br3 = lir->insBranch(LIR_jf,
+ lir->ins2(LIR_ult,
+ idx_ins,
+ lir->insLoad(LIR_ldp, dslots_ins, 0 - (int)sizeof(jsval))),
+ NULL);
+ lir->insGuard(LIR_x, lir->insImm(1), snapshot(exitType));
+ LIns* label = lir->ins0(LIR_label);
+ br1->target(label);
+ br2->target(label);
+ br3->target(label);
+ }
+ return cond;
+}
+
+/*
+ * Guard that a computed property access via an element op (JSOP_GETELEM, etc.)
+ * does not find an alias to a global variable, or a property without a slot,
+ * or a slot-ful property with a getter or setter (depending on op_offset in
+ * JSObjectOps). Finally, beware resolve hooks mutating objects. Oh, and watch
+ * out for bears too ;-).
+ *
+ * One win here is that we do not need to generate a guard that obj_ins does
+ * not result in the global object on trace, because we guard on shape and rule
+ * out obj's shape being the global object's shape at recording time. This is
+ * safe because the global shape cannot change on trace.
+ */
+bool
+TraceRecorder::guardElemOp(JSObject* obj, LIns* obj_ins, jsid id, size_t op_offset, jsval* vp)
+{
+ LIns* map_ins = lir->insLoad(LIR_ldp, obj_ins, (int)offsetof(JSObject, map));
+ LIns* ops_ins;
+ if (!map_is_native(obj->map, map_ins, ops_ins, op_offset))
+ return false;
+
+ uint32 shape = OBJ_SHAPE(obj);
+ if (JSID_IS_ATOM(id) && shape == traceMonitor->globalShape)
+ ABORT_TRACE("elem op probably aliases global");
+
+ JSObject* pobj;
+ JSProperty* prop;
+ if (!js_LookupProperty(cx, obj, id, &pobj, &prop))
+ return false;
+
+ if (vp)
+ *vp = JSVAL_VOID;
+ if (prop) {
+ bool traceable_slot = true;
+ if (pobj == obj) {
+ JSScopeProperty* sprop = (JSScopeProperty*) prop;
+ traceable_slot = ((op_offset == offsetof(JSObjectOps, getProperty))
+ ? SPROP_HAS_STUB_GETTER(sprop)
+ : SPROP_HAS_STUB_SETTER(sprop)) &&
+ SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj));
+ if (vp && traceable_slot)
+ *vp = LOCKED_OBJ_GET_SLOT(obj, sprop->slot);
+ }
+
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ if (pobj != obj)
+ ABORT_TRACE("elem op hit prototype property, can't shape-guard");
+ if (!traceable_slot)
+ ABORT_TRACE("elem op hit direct and slotless getter or setter");
+ }
+
+ // If we got this far, we're almost safe -- but we must check for a rogue resolve hook.
+ if (OBJ_SHAPE(obj) != shape)
+ ABORT_TRACE("resolve hook mutated elem op base object");
+
+ LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)), "shape");
+ guard(true, addName(lir->ins2i(LIR_eq, shape_ins, shape), "guard(shape)"), MISMATCH_EXIT);
+ return true;
+}
+
+void
+TraceRecorder::clearFrameSlotsFromCache()
+{
+ /* Clear out all slots of this frame in the nativeFrameTracker. Different locations on the
+ VM stack might map to different locations on the native stack depending on the
+ number of arguments (i.e.) of the next call, so we have to make sure we map
+ those in to the cache with the right offsets. */
+ JSStackFrame* fp = cx->fp;
+ jsval* vp;
+ jsval* vpstop;
+ if (fp->callee) {
+ vp = &fp->argv[-2];
+ vpstop = &fp->argv[fp->fun->nargs];
+ while (vp < vpstop)
+ nativeFrameTracker.set(vp++, (LIns*)0);
+ }
+ vp = &fp->slots[0];
+ vpstop = &fp->slots[fp->script->nslots];
+ while (vp < vpstop)
+ nativeFrameTracker.set(vp++, (LIns*)0);
+}
+
+bool
+TraceRecorder::record_EnterFrame()
+{
+ JSStackFrame* fp = cx->fp;
+
+ if (++callDepth >= MAX_CALLDEPTH)
+ ABORT_TRACE("exceeded maximum call depth");
+ // FIXME: Allow and attempt to inline a single level of recursion until we compile
+ // recursive calls as independent trees (459301).
+ if (fp->script == fp->down->script && fp->down->down && fp->down->down->script == fp->script)
+ ABORT_TRACE("recursive call");
+
+ debug_only_v(printf("EnterFrame %s, callDepth=%d\n",
+ js_AtomToPrintableString(cx, cx->fp->fun->atom),
+ callDepth);)
+ LIns* void_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+
+ jsval* vp = &fp->argv[fp->argc];
+ jsval* vpstop = vp + ptrdiff_t(fp->fun->nargs) - ptrdiff_t(fp->argc);
+ if (applyingArguments) {
+ applyingArguments = false;
+ while (vp < vpstop) {
+ JS_ASSERT(vp >= fp->down->regs->sp);
+ nativeFrameTracker.set(vp, (LIns*)0);
+ LIns* arg_ins = get(&fp->down->argv[fp->argc + (vp - vpstop)]);
+ set(vp++, arg_ins, true);
+ }
+ } else {
+ while (vp < vpstop) {
+ if (vp >= fp->down->regs->sp)
+ nativeFrameTracker.set(vp, (LIns*)0);
+ set(vp++, void_ins, true);
+ }
+ }
+
+ vp = &fp->slots[0];
+ vpstop = vp + fp->script->nfixed;
+ while (vp < vpstop)
+ set(vp++, void_ins, true);
+ return true;
+}
+
+bool
+TraceRecorder::record_LeaveFrame()
+{
+ debug_only_v(
+ if (cx->fp->fun)
+ printf("LeaveFrame (back to %s), callDepth=%d\n",
+ js_AtomToPrintableString(cx, cx->fp->fun->atom),
+ callDepth);
+ );
+ if (callDepth-- <= 0)
+ ABORT_TRACE("returned out of a loop we started tracing");
+
+ // LeaveFrame gets called after the interpreter popped the frame and
+ // stored rval, so cx->fp not cx->fp->down, and -1 not 0.
+ atoms = cx->fp->script->atomMap.vector;
+ set(&stackval(-1), rval_ins, true);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INTERRUPT()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_PUSH()
+{
+ stack(0, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_POPV()
+{
+ jsval& rval = stackval(-1);
+ LIns *rval_ins = get(&rval);
+ if (!box_jsval(rval, rval_ins))
+ return false;
+
+ // Store it in cx->fp->rval. NB: Tricky dependencies. cx->fp is the right
+ // frame because POPV appears only in global and eval code and we don't
+ // trace JSOP_EVAL or leaving the frame where tracing started.
+ LIns *fp_ins = lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, fp));
+ lir->insStorei(rval_ins, fp_ins, offsetof(JSStackFrame, rval));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_ENTERWITH()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_LEAVEWITH()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_RETURN()
+{
+ jsval& rval = stackval(-1);
+ JSStackFrame *fp = cx->fp;
+ if ((cx->fp->flags & JSFRAME_CONSTRUCTING) && JSVAL_IS_PRIMITIVE(rval)) {
+ JS_ASSERT(OBJECT_TO_JSVAL(fp->thisp) == fp->argv[-1]);
+ rval_ins = get(&fp->argv[-1]);
+ } else {
+ rval_ins = get(&rval);
+ }
+ debug_only_v(printf("returning from %s\n", js_AtomToPrintableString(cx, cx->fp->fun->atom));)
+ clearFrameSlotsFromCache();
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_GOTO()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_IFEQ()
+{
+ trackCfgMerges(cx->fp->regs->pc);
+ return ifop();
+}
+
+bool
+TraceRecorder::record_JSOP_IFNE()
+{
+ return ifop();
+}
+
+bool
+TraceRecorder::record_JSOP_ARGUMENTS()
+{
+#if 1
+ ABORT_TRACE("can't trace arguments yet");
+#else
+ LIns* args[] = { cx_ins };
+ LIns* a_ins = lir->insCall(&js_Arguments_ci, args);
+ guard(false, lir->ins_eq0(a_ins), OOM_EXIT);
+ stack(0, a_ins);
+ return true;
+#endif
+}
+
+bool
+TraceRecorder::record_JSOP_DUP()
+{
+ stack(0, get(&stackval(-1)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_DUP2()
+{
+ stack(0, get(&stackval(-2)));
+ stack(1, get(&stackval(-1)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SWAP()
+{
+ jsval& l = stackval(-2);
+ jsval& r = stackval(-1);
+ LIns* l_ins = get(&l);
+ LIns* r_ins = get(&r);
+ set(&r, l_ins);
+ set(&l, r_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETCONST()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_BITOR()
+{
+ return binary(LIR_or);
+}
+
+bool
+TraceRecorder::record_JSOP_BITXOR()
+{
+ return binary(LIR_xor);
+}
+
+bool
+TraceRecorder::record_JSOP_BITAND()
+{
+ return binary(LIR_and);
+}
+
+bool
+TraceRecorder::record_JSOP_EQ()
+{
+ return cmp(LIR_feq, CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_NE()
+{
+ return cmp(LIR_feq, CMP_NEGATE | CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_LT()
+{
+ return cmp(LIR_flt, CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_LE()
+{
+ return cmp(LIR_fle, CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_GT()
+{
+ return cmp(LIR_fgt, CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_GE()
+{
+ return cmp(LIR_fge, CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_LSH()
+{
+ return binary(LIR_lsh);
+}
+
+bool
+TraceRecorder::record_JSOP_RSH()
+{
+ return binary(LIR_rsh);
+}
+
+bool
+TraceRecorder::record_JSOP_URSH()
+{
+ return binary(LIR_ush);
+}
+
+static struct {
+ jsbytecode obj_any[10];
+ jsbytecode any_obj[8];
+ jsbytecode obj_obj[16];
+} add_imacros = {
+ {
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+ JSOP_CALL, 0, 0,
+ JSOP_SWAP,
+ JSOP_ADD,
+ JSOP_STOP
+ },
+
+ {
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+ JSOP_CALL, 0, 0,
+ JSOP_ADD,
+ JSOP_STOP
+ },
+
+ {
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+ JSOP_CALL, 0, 0,
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+ JSOP_CALL, 0, 0,
+ JSOP_ADD,
+ JSOP_STOP
+ }
+};
+
+JS_STATIC_ASSERT(sizeof(add_imacros) < IMACRO_PC_ADJ_LIMIT);
+
+bool
+TraceRecorder::record_JSOP_ADD()
+{
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+
+ if (JSVAL_IS_OBJECT(l) && hasToStringMethod(l)) {
+ if (JSVAL_IS_OBJECT(r) && hasToStringMethod(r))
+ return call_imacro(add_imacros.obj_obj);
+ return call_imacro(add_imacros.obj_any);
+ }
+ if (JSVAL_IS_OBJECT(r) && hasToStringMethod(r))
+ return call_imacro(add_imacros.any_obj);
+
+ if (JSVAL_IS_STRING(l) || JSVAL_IS_STRING(r)) {
+ LIns* args[] = { stringify(r), stringify(l), cx_ins };
+ if (!args[0] || !args[1])
+ ABORT_TRACE("can't stringify objects");
+ LIns* concat = lir->insCall(&js_ConcatStrings_ci, args);
+ guard(false, lir->ins_eq0(concat), OOM_EXIT);
+ set(&l, concat);
+ return true;
+ }
+
+ return binary(LIR_fadd);
+}
+
+bool
+TraceRecorder::record_JSOP_SUB()
+{
+ return binary(LIR_fsub);
+}
+
+bool
+TraceRecorder::record_JSOP_MUL()
+{
+ return binary(LIR_fmul);
+}
+
+bool
+TraceRecorder::record_JSOP_DIV()
+{
+ return binary(LIR_fdiv);
+}
+
+bool
+TraceRecorder::record_JSOP_MOD()
+{
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+
+ if (JSVAL_IS_OBJECT(l) && hasValueOfMethod(l)) {
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.obj_obj);
+ return call_imacro(binary_imacros.obj_any);
+ }
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.any_obj);
+
+ if (isNumber(l) && isNumber(r)) {
+ LIns* l_ins = get(&l);
+ LIns* r_ins = get(&r);
+ LIns* x;
+ /* We can't demote this in a filter since we need the actual values of l and r. */
+ if (isPromote(l_ins) && isPromote(r_ins) && asNumber(l) >= 0 && asNumber(r) > 0) {
+ LIns* args[] = { ::demote(lir, r_ins), ::demote(lir, l_ins) };
+ x = lir->insCall(&js_imod_ci, args);
+ guard(false, lir->ins2(LIR_eq, x, lir->insImm(-1)), BRANCH_EXIT);
+ x = lir->ins1(LIR_i2f, x);
+ } else {
+ LIns* args[] = { r_ins, l_ins };
+ x = lir->insCall(&js_dmod_ci, args);
+ }
+ set(&l, x);
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_NOT()
+{
+ jsval& v = stackval(-1);
+ if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
+ set(&v, lir->ins_eq0(lir->ins2i(LIR_eq, get(&v), 1)));
+ return true;
+ }
+ if (isNumber(v)) {
+ LIns* v_ins = get(&v);
+ set(&v, lir->ins2(LIR_or, lir->ins2(LIR_feq, v_ins, lir->insImmq(0)),
+ lir->ins_eq0(lir->ins2(LIR_feq, v_ins, v_ins))));
+ return true;
+ }
+ if (JSVAL_IS_OBJECT(v)) {
+ set(&v, lir->ins_eq0(get(&v)));
+ return true;
+ }
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ set(&v, lir->ins_eq0(lir->ins2(LIR_piand,
+ lir->insLoad(LIR_ldp, get(&v), (int)offsetof(JSString, length)),
+ INS_CONSTPTR(JSSTRING_LENGTH_MASK))));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_BITNOT()
+{
+ return unary(LIR_not);
+}
+
+bool
+TraceRecorder::record_JSOP_NEG()
+{
+ jsval& v = stackval(-1);
+ if (isNumber(v)) {
+ LIns* a = get(&v);
+
+ /* If we're a promoted integer, we have to watch out for 0s since -0 is a double.
+ Only follow this path if we're not an integer that's 0 and we're not a double
+ that's zero.
+ */
+ if (isPromoteInt(a) &&
+ (!JSVAL_IS_INT(v) || JSVAL_TO_INT(v) != 0) &&
+ (!JSVAL_IS_DOUBLE(v) || !JSDOUBLE_IS_NEGZERO(*JSVAL_TO_DOUBLE(v)))) {
+ a = lir->ins1(LIR_neg, ::demote(lir, a));
+ lir->insGuard(LIR_xt, lir->ins1(LIR_ov, a), snapshot(OVERFLOW_EXIT));
+ lir->insGuard(LIR_xt, lir->ins2(LIR_eq, a, lir->insImm(0)), snapshot(OVERFLOW_EXIT));
+ a = lir->ins1(LIR_i2f, a);
+ } else {
+ a = lir->ins1(LIR_fneg, a);
+ }
+
+ set(&v, a);
+ return true;
+ }
+ return false;
+}
+
+JSBool
+js_Array(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
+
+JSBool
+js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+JSBool
+js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+JSBool
+js_fun_apply(JSContext* cx, uintN argc, jsval* vp);
+
+bool
+TraceRecorder::functionCall(bool constructing)
+{
+ JSStackFrame* fp = cx->fp;
+ jsbytecode *pc = fp->regs->pc;
+ uintN argc = GET_ARGC(pc);
+
+ jsval& fval = stackval(0 - (2 + argc));
+ JS_ASSERT(&fval >= StackBase(fp));
+
+ if (!VALUE_IS_FUNCTION(cx, fval))
+ ABORT_TRACE("callee is not a function");
+
+ jsval& tval = stackval(0 - (argc + 1));
+ LIns* this_ins = get(&tval);
+
+ if (this_ins->isconstp() && !this_ins->constvalp() && !guardShapelessCallee(fval))
+ return false;
+
+ /*
+ * Require that the callee be a function object, to avoid guarding on its
+ * class here. We know if the callee and this were pushed by JSOP_CALLNAME
+ * or JSOP_CALLPROP that callee is a *particular* function, since these hit
+ * the property cache and guard on the object (this) in which the callee
+ * was found. So it's sufficient to test here that the particular function
+ * is interpreted, not guard on that condition.
+ *
+ * Bytecode sequences that push shapeless callees must guard on the callee
+ * class being Function and the function being interpreted.
+ */
+ JSFunction* fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fval));
+
+ if (FUN_INTERPRETED(fun)) {
+ if (constructing) {
+ LIns* args[] = { get(&fval), cx_ins };
+ LIns* tv_ins = lir->insCall(&js_FastNewObject_ci, args);
+ guard(false, lir->ins_eq0(tv_ins), OOM_EXIT);
+ set(&tval, tv_ins);
+ }
+ return interpretedFunctionCall(fval, fun, argc, constructing);
+ }
+
+ LIns* arg1_ins = NULL;
+ jsval arg1 = JSVAL_VOID;
+ jsval thisval = tval;
+ if (!constructing && FUN_FAST_NATIVE(fun) == js_fun_apply) {
+ if (argc != 2)
+ ABORT_TRACE("can't trace Function.prototype.apply with other than 2 args");
+
+ if (!guardShapelessCallee(tval))
+ return false;
+ JSObject* tfunobj = JSVAL_TO_OBJECT(tval);
+ JSFunction* tfun = GET_FUNCTION_PRIVATE(cx, tfunobj);
+
+ jsval& oval = stackval(-2);
+ if (JSVAL_IS_PRIMITIVE(oval))
+ ABORT_TRACE("can't trace Function.prototype.apply with primitive 1st arg");
+
+ jsval& aval = stackval(-1);
+ if (JSVAL_IS_PRIMITIVE(aval))
+ ABORT_TRACE("can't trace Function.prototype.apply with primitive 2nd arg");
+ JSObject* aobj = JSVAL_TO_OBJECT(aval);
+
+ LIns* aval_ins = get(&aval);
+ if (!aval_ins->isCall())
+ ABORT_TRACE("can't trace Function.prototype.apply on non-builtin-call 2nd arg");
+
+ if (aval_ins->callInfo() == &js_Arguments_ci) {
+ JS_ASSERT(OBJ_GET_CLASS(cx, aobj) == &js_ArgumentsClass);
+ JS_ASSERT(OBJ_GET_PRIVATE(cx, aobj) == fp);
+ if (!FUN_INTERPRETED(tfun))
+ ABORT_TRACE("can't trace Function.prototype.apply(native_function, arguments)");
+
+ // We can only fasttrack applys where the argument array we pass in has the
+ // same length (fp->argc) as the number of arguments the function expects (tfun->nargs).
+ argc = fp->argc;
+ if (tfun->nargs != argc || fp->fun->nargs != argc)
+ ABORT_TRACE("can't trace Function.prototype.apply(scripted_function, arguments)");
+
+ jsval* sp = fp->regs->sp - 4;
+ set(sp, get(&tval));
+ *sp++ = tval;
+ set(sp, get(&oval));
+ *sp++ = oval;
+ jsval* newsp = sp + argc;
+ if (newsp > fp->slots + fp->script->nslots) {
+ JSArena* a = cx->stackPool.current;
+ if (jsuword(newsp) > a->limit)
+ ABORT_TRACE("can't grow stack for Function.prototype.apply");
+ if (jsuword(newsp) > a->avail)
+ a->avail = jsuword(newsp);
+ }
+
+ jsval* argv = fp->argv;
+ for (uintN i = 0; i < JS_MIN(argc, 2); i++) {
+ set(&sp[i], get(&argv[i]));
+ sp[i] = argv[i];
+ }
+ applyingArguments = true;
+ return interpretedFunctionCall(tval, tfun, argc, false);
+ }
+
+ if (aval_ins->callInfo() != &js_Array_1str_ci)
+ ABORT_TRACE("can't trace Function.prototype.apply on other than [str] 2nd arg");
+
+ JS_ASSERT(OBJ_IS_ARRAY(cx, aobj));
+ JS_ASSERT(aobj->fslots[JSSLOT_ARRAY_LENGTH] == 1);
+ JS_ASSERT(JSVAL_IS_STRING(aobj->dslots[0]));
+
+ if (FUN_INTERPRETED(tfun))
+ ABORT_TRACE("can't trace Function.prototype.apply for scripted functions");
+
+ if (!(tfun->flags & JSFUN_TRACEABLE))
+ ABORT_TRACE("Function.prototype.apply on untraceable native");
+
+ thisval = oval;
+ this_ins = get(&oval);
+ arg1_ins = callArgN(aval_ins, 2);
+ arg1 = aobj->dslots[0];
+ fun = tfun;
+ argc = 1;
+ }
+
+ if (!constructing && !(fun->flags & JSFUN_TRACEABLE))
+ ABORT_TRACE("untraceable native");
+
+ static JSTraceableNative knownNatives[] = {
+ { (JSFastNative)js_Array, &js_FastNewArray_ci, "pC", "", FAIL_NULL | JSTN_MORE },
+ { (JSFastNative)js_Array, &js_Array_1int_ci, "pC", "i", FAIL_NULL | JSTN_MORE },
+ { (JSFastNative)js_Array, &js_Array_2obj_ci, "pC", "oo", FAIL_NULL | JSTN_MORE },
+ { (JSFastNative)js_Array, &js_Array_3num_ci, "pC", "ddd", FAIL_NULL | JSTN_MORE },
+ { (JSFastNative)js_Object, &js_FastNewObject_ci, "fC", "", FAIL_NULL | JSTN_MORE },
+ { (JSFastNative)js_Date, &js_FastNewDate_ci, "pC", "", FAIL_NULL },
+ };
+
+ LIns* args[5];
+ JSTraceableNative* known = constructing ? knownNatives : FUN_TRCINFO(fun);
+ do {
+ if (constructing && (JSFastNative)fun->u.n.native != known->native)
+ continue;
+
+ uintN knownargc = strlen(known->argtypes);
+ if (argc != knownargc)
+ continue;
+
+ intN prefixc = strlen(known->prefix);
+ JS_ASSERT(prefixc <= 3);
+ LIns** argp = &args[argc + prefixc - 1];
+ char argtype;
+
+#if defined _DEBUG
+ memset(args, 0xCD, sizeof(args));
+#endif
+
+ uintN i;
+ for (i = prefixc; i--; ) {
+ argtype = known->prefix[i];
+ if (argtype == 'C') {
+ *argp = cx_ins;
+ } else if (argtype == 'T') { /* this, as an object */
+ if (!JSVAL_IS_OBJECT(thisval))
+ goto next_specialization;
+ *argp = this_ins;
+ } else if (argtype == 'S') { /* this, as a string */
+ if (!JSVAL_IS_STRING(thisval))
+ goto next_specialization;
+ *argp = this_ins;
+ } else if (argtype == 'f') {
+ *argp = INS_CONSTPTR(JSVAL_TO_OBJECT(fval));
+ } else if (argtype == 'p') {
+ JSObject* ctor = JSVAL_TO_OBJECT(fval);
+ jsval pval;
+ if (!OBJ_GET_PROPERTY(cx, ctor,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &pval)) {
+ ABORT_TRACE("error getting prototype from constructor");
+ }
+ if (!JSVAL_IS_OBJECT(pval))
+ ABORT_TRACE("got primitive prototype from constructor");
+ *argp = INS_CONSTPTR(JSVAL_TO_OBJECT(pval));
+ } else if (argtype == 'R') {
+ *argp = INS_CONSTPTR(cx->runtime);
+ } else if (argtype == 'P') {
+ *argp = INS_CONSTPTR(pc);
+ } else if (argtype == 'D') { /* this, as a number */
+ if (!isNumber(thisval))
+ goto next_specialization;
+ *argp = this_ins;
+ } else {
+ JS_NOT_REACHED("unknown prefix arg type");
+ }
+ argp--;
+ }
+
+ for (i = knownargc; i--; ) {
+ jsval& arg = (!constructing && i == 0 && arg1_ins) ? arg1 : stackval(0 - (i + 1));
+ *argp = (!constructing && i == 0 && arg1_ins) ? arg1_ins : get(&arg);
+
+ argtype = known->argtypes[i];
+ if (argtype == 'd' || argtype == 'i') {
+ if (!isNumber(arg))
+ goto next_specialization;
+ if (argtype == 'i')
+ *argp = f2i(*argp);
+ } else if (argtype == 'o') {
+ if (!JSVAL_IS_OBJECT(arg))
+ goto next_specialization;
+ } else if (argtype == 's') {
+ if (!JSVAL_IS_STRING(arg))
+ goto next_specialization;
+ } else if (argtype == 'r') {
+ if (!VALUE_IS_REGEXP(cx, arg))
+ goto next_specialization;
+ } else if (argtype == 'f') {
+ if (!VALUE_IS_FUNCTION(cx, arg))
+ goto next_specialization;
+ } else if (argtype == 'v') {
+ if (!box_jsval(arg, *argp))
+ return false;
+ } else {
+ goto next_specialization;
+ }
+ argp--;
+ }
+
+ /*
+ * If we got this far, and we have a charCodeAt, check that charCodeAt
+ * isn't going to return a NaN.
+ */
+ if (!constructing && known->builtin == &js_String_p_charCodeAt_ci) {
+ JSString* str = JSVAL_TO_STRING(thisval);
+ jsval& arg = arg1_ins ? arg1 : stackval(-1);
+
+ JS_ASSERT(JSVAL_IS_STRING(thisval));
+ JS_ASSERT(isNumber(arg));
+
+ if (JSVAL_IS_INT(arg)) {
+ if (size_t(JSVAL_TO_INT(arg)) >= JSSTRING_LENGTH(str))
+ ABORT_TRACE("invalid charCodeAt index");
+ } else {
+ double d = js_DoubleToInteger(*JSVAL_TO_DOUBLE(arg));
+ if (d < 0 || JSSTRING_LENGTH(str) <= d)
+ ABORT_TRACE("invalid charCodeAt index");
+ }
+ }
+ goto success;
+
+next_specialization:;
+ } while ((known++)->flags & JSTN_MORE);
+
+ if (!constructing)
+ ABORT_TRACE("unknown native");
+ if (!(fun->flags & JSFUN_TRACEABLE) && FUN_CLASP(fun))
+ ABORT_TRACE("can't trace native constructor");
+ ABORT_TRACE("can't trace unknown constructor");
+
+success:
+#if defined _DEBUG
+ JS_ASSERT(args[0] != (LIns *)0xcdcdcdcd);
+#endif
+
+ LIns* res_ins = lir->insCall(known->builtin, args);
+ if (!constructing)
+ rval_ins = res_ins;
+ switch (JSTN_ERRTYPE(known)) {
+ case FAIL_NULL:
+ guard(false, lir->ins_eq0(res_ins), OOM_EXIT);
+ break;
+ case FAIL_NEG:
+ {
+ res_ins = lir->ins1(LIR_i2f, res_ins);
+ jsdpun u;
+ u.d = 0.0;
+ guard(false, lir->ins2(LIR_flt, res_ins, lir->insImmq(u.u64)), OOM_EXIT);
+ break;
+ }
+ case FAIL_VOID:
+ guard(false, lir->ins2i(LIR_eq, res_ins, JSVAL_TO_BOOLEAN(JSVAL_VOID)), OOM_EXIT);
+ break;
+ default:;
+ }
+ set(&fval, res_ins);
+
+ if (!constructing) {
+ /*
+ * The return value will be processed by FastNativeCallComplete since
+ * we have to know the actual return value type for calls that return
+ * jsval (like Array_p_pop).
+ */
+ pendingTraceableNative = known;
+ }
+
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NEW()
+{
+ return functionCall(true);
+}
+
+bool
+TraceRecorder::record_JSOP_DELNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DELPROP()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DELELEM()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TYPEOF()
+{
+ jsval& r = stackval(-1);
+ LIns* type;
+ if (JSVAL_IS_STRING(r)) {
+ type = INS_CONSTPTR(ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_STRING]));
+ } else if (isNumber(r)) {
+ type = INS_CONSTPTR(ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]));
+ } else {
+ LIns* args[] = { get(&r), cx_ins };
+ if (JSVAL_TAG(r) == JSVAL_BOOLEAN) {
+ // We specialize identically for boolean and undefined. We must not have a hole here.
+ // Pass the unboxed type here, since TypeOfBoolean knows how to handle it.
+ JS_ASSERT(JSVAL_TO_BOOLEAN(r) <= 2);
+ type = lir->insCall(&js_TypeOfBoolean_ci, args);
+ } else {
+ JS_ASSERT(JSVAL_IS_OBJECT(r));
+ type = lir->insCall(&js_TypeOfObject_ci, args);
+ }
+ }
+ set(&r, type);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_VOID()
+{
+ stack(-1, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INCNAME()
+{
+ return incName(1);
+}
+
+bool
+TraceRecorder::record_JSOP_INCPROP()
+{
+ return incProp(1);
+}
+
+bool
+TraceRecorder::record_JSOP_INCELEM()
+{
+ return incElem(1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECNAME()
+{
+ return incName(-1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECPROP()
+{
+ return incProp(-1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECELEM()
+{
+ return incElem(-1);
+}
+
+bool
+TraceRecorder::incName(jsint incr, bool pre)
+{
+ jsval* vp;
+ if (!name(vp))
+ return false;
+ LIns* v_ins = get(vp);
+ if (!inc(*vp, v_ins, incr, pre))
+ return false;
+ set(vp, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NAMEINC()
+{
+ return incName(1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_PROPINC()
+{
+ return incProp(1, false);
+}
+
+// XXX consolidate with record_JSOP_GETELEM code...
+bool
+TraceRecorder::record_JSOP_ELEMINC()
+{
+ return incElem(1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_NAMEDEC()
+{
+ return incName(-1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_PROPDEC()
+{
+ return incProp(-1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_ELEMDEC()
+{
+ return incElem(-1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_GETPROP()
+{
+ return getProp(stackval(-1));
+}
+
+bool
+TraceRecorder::record_JSOP_SETPROP()
+{
+ jsval& l = stackval(-2);
+ if (JSVAL_IS_PRIMITIVE(l))
+ ABORT_TRACE("primitive this for SETPROP");
+
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ if (obj->map->ops->setProperty != js_SetProperty)
+ ABORT_TRACE("non-native JSObjectOps::setProperty");
+ return true;
+}
+
+bool
+TraceRecorder::record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop)
+{
+ if (sprop->setter == js_watch_set)
+ ABORT_TRACE("watchpoint detected");
+
+ jsbytecode* pc = cx->fp->regs->pc;
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(l));
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ LIns* obj_ins = get(&l);
+
+ if (obj == globalObj) {
+ JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)));
+ uint32 slot = sprop->slot;
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ LIns* r_ins = get(&r);
+ set(&STOBJ_GET_SLOT(obj, slot), r_ins);
+
+ JS_ASSERT(*pc != JSOP_INITPROP);
+ if (pc[JSOP_SETPROP_LENGTH] != JSOP_POP)
+ set(&l, r_ins);
+ return true;
+ }
+
+ // The global object's shape is guarded at trace entry, all others need a guard here.
+ LIns* map_ins = lir->insLoad(LIR_ldp, obj_ins, (int)offsetof(JSObject, map));
+ LIns* ops_ins;
+ if (!map_is_native(obj->map, map_ins, ops_ins, offsetof(JSObjectOps, setProperty)))
+ return false;
+
+ LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)), "shape");
+ guard(true, addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard(shape)"),
+ MISMATCH_EXIT);
+
+ if (entry->kshape != PCVCAP_SHAPE(entry->vcap)) {
+ LIns* args[] = { INS_CONSTPTR(sprop), obj_ins, cx_ins };
+ LIns* ok_ins = lir->insCall(&js_AddProperty_ci, args);
+ guard(false, lir->ins_eq0(ok_ins), OOM_EXIT);
+ }
+
+ LIns* dslots_ins = NULL;
+ LIns* v_ins = get(&r);
+ LIns* boxed_ins = v_ins;
+ if (!box_jsval(r, boxed_ins))
+ return false;
+ if (!native_set(obj_ins, sprop, dslots_ins, boxed_ins))
+ return false;
+
+ if (*pc != JSOP_INITPROP && pc[JSOP_SETPROP_LENGTH] != JSOP_POP)
+ set(&l, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_SetPropMiss(JSPropCacheEntry* entry)
+{
+ if (entry->kpc != cx->fp->regs->pc || !PCVAL_IS_SPROP(entry->vword))
+ ABORT_TRACE("can't trace uncacheable property set");
+
+ JSScopeProperty* sprop = PCVAL_TO_SPROP(entry->vword);
+
+#ifdef DEBUG
+ jsval& l = stackval(-2);
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ JSScope* scope = OBJ_SCOPE(obj);
+ JS_ASSERT(scope->object == obj);
+ JS_ASSERT(scope->shape == PCVCAP_SHAPE(entry->vcap));
+ JS_ASSERT(SCOPE_HAS_PROPERTY(scope, sprop));
+#endif
+
+ return record_SetPropHit(entry, sprop);
+}
+
+bool
+TraceRecorder::record_JSOP_GETELEM()
+{
+ jsval& idx = stackval(-1);
+ jsval& lval = stackval(-2);
+
+ LIns* obj_ins = get(&lval);
+ LIns* idx_ins = get(&idx);
+
+ if (JSVAL_IS_STRING(lval) && JSVAL_IS_INT(idx)) {
+ int i = JSVAL_TO_INT(idx);
+ if ((size_t)i >= JSSTRING_LENGTH(JSVAL_TO_STRING(lval)))
+ ABORT_TRACE("Invalid string index in JSOP_GETELEM");
+ idx_ins = makeNumberInt32(idx_ins);
+ LIns* args[] = { idx_ins, obj_ins, cx_ins };
+ LIns* unitstr_ins = lir->insCall(&js_String_getelem_ci, args);
+ guard(false, lir->ins_eq0(unitstr_ins), MISMATCH_EXIT);
+ set(&lval, unitstr_ins);
+ return true;
+ }
+
+ if (JSVAL_IS_PRIMITIVE(lval))
+ ABORT_TRACE("JSOP_GETLEM on a primitive");
+
+ JSObject* obj = JSVAL_TO_OBJECT(lval);
+ jsval id;
+ jsval v;
+ LIns* v_ins;
+
+ /* Property access using a string name. */
+ if (JSVAL_IS_STRING(idx)) {
+ if (!js_ValueToStringId(cx, idx, &id))
+ return false;
+ // Store the interned string to the stack to save the interpreter from redoing this work.
+ idx = ID_TO_VALUE(id);
+ jsuint index;
+ if (js_IdIsIndex(idx, &index) && guardDenseArray(obj, obj_ins, BRANCH_EXIT)) {
+ v = (index >= ARRAY_DENSE_LENGTH(obj)) ? JSVAL_HOLE : obj->dslots[index];
+ if (v == JSVAL_HOLE)
+ ABORT_TRACE("can't see through hole in dense array");
+ } else {
+ if (!guardElemOp(obj, obj_ins, id, offsetof(JSObjectOps, getProperty), &v))
+ return false;
+ }
+ LIns* args[] = { idx_ins, obj_ins, cx_ins };
+ v_ins = lir->insCall(&js_Any_getprop_ci, args);
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), MISMATCH_EXIT);
+ if (!unbox_jsval(v, v_ins))
+ ABORT_TRACE("JSOP_GETELEM");
+ set(&lval, v_ins);
+ return true;
+ }
+
+ /* At this point we expect a whole number or we bail. */
+ if (!JSVAL_IS_INT(idx))
+ ABORT_TRACE("non-string, non-int JSOP_GETELEM index");
+ if (JSVAL_TO_INT(idx) < 0)
+ ABORT_TRACE("negative JSOP_GETELEM index");
+
+ /* Accessing an object using integer index but not a dense array. */
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ idx_ins = makeNumberInt32(idx_ins);
+ LIns* args[] = { idx_ins, obj_ins, cx_ins };
+ if (!js_IndexToId(cx, JSVAL_TO_INT(idx), &id))
+ return false;
+ idx = ID_TO_VALUE(id);
+ if (!guardElemOp(obj, obj_ins, id, offsetof(JSObjectOps, getProperty), &v))
+ return false;
+ LIns* v_ins = lir->insCall(&js_Any_getelem_ci, args);
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), MISMATCH_EXIT);
+ if (!unbox_jsval(v, v_ins))
+ ABORT_TRACE("JSOP_GETELEM");
+ set(&lval, v_ins);
+ return true;
+ }
+
+ jsval* vp;
+ LIns* addr_ins;
+ if (!elem(lval, idx, vp, v_ins, addr_ins))
+ return false;
+ set(&lval, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETELEM()
+{
+ jsval& v = stackval(-1);
+ jsval& idx = stackval(-2);
+ jsval& lval = stackval(-3);
+
+ /* no guards for type checks, trace specialized this already */
+ if (JSVAL_IS_PRIMITIVE(lval))
+ ABORT_TRACE("left JSOP_SETELEM operand is not an object");
+
+ JSObject* obj = JSVAL_TO_OBJECT(lval);
+ LIns* obj_ins = get(&lval);
+ LIns* idx_ins = get(&idx);
+ LIns* v_ins = get(&v);
+ jsid id;
+
+ LIns* boxed_v_ins = v_ins;
+ if (!box_jsval(v, boxed_v_ins))
+ ABORT_TRACE("boxing JSOP_SETELEM value");
+
+ if (JSVAL_IS_STRING(idx)) {
+ if (!js_ValueToStringId(cx, idx, &id))
+ return false;
+ // Store the interned string to the stack to save the interpreter from redoing this work.
+ idx = ID_TO_VALUE(id);
+ if (!guardElemOp(obj, obj_ins, id, offsetof(JSObjectOps, setProperty), NULL))
+ return false;
+ LIns* args[] = { boxed_v_ins, idx_ins, obj_ins, cx_ins };
+ LIns* ok_ins = lir->insCall(&js_Any_setprop_ci, args);
+ guard(false, lir->ins_eq0(ok_ins), MISMATCH_EXIT);
+ } else if (JSVAL_IS_INT(idx)) {
+ if (JSVAL_TO_INT(idx) < 0)
+ ABORT_TRACE("negative JSOP_SETELEM index");
+ idx_ins = makeNumberInt32(idx_ins);
+ LIns* args[] = { boxed_v_ins, idx_ins, obj_ins, cx_ins };
+ LIns* res_ins;
+ if (guardDenseArray(obj, obj_ins, BRANCH_EXIT)) {
+ res_ins = lir->insCall(&js_Array_dense_setelem_ci, args);
+ } else {
+ if (!js_IndexToId(cx, JSVAL_TO_INT(idx), &id))
+ return false;
+ idx = ID_TO_VALUE(id);
+ if (!guardElemOp(obj, obj_ins, id, offsetof(JSObjectOps, setProperty), NULL))
+ return false;
+ res_ins = lir->insCall(&js_Any_setelem_ci, args);
+ }
+ guard(false, lir->ins_eq0(res_ins), MISMATCH_EXIT);
+ } else {
+ ABORT_TRACE("non-string, non-int JSOP_SETELEM index");
+ }
+
+ jsbytecode* pc = cx->fp->regs->pc;
+ if (*pc == JSOP_SETELEM && pc[JSOP_SETELEM_LENGTH] != JSOP_POP)
+ set(&lval, v_ins);
+
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLNAME()
+{
+ JSObject* obj = cx->fp->scopeChain;
+ if (obj != globalObj) {
+ jsval* vp;
+ if (!activeCallOrGlobalSlot(obj, vp))
+ return false;
+ stack(0, get(vp));
+ stack(1, INS_CONSTPTR(globalObj));
+ return true;
+ }
+
+ LIns* obj_ins = scopeChain();
+ JSObject* obj2;
+ jsuword pcval;
+ if (!test_property_cache(obj, obj_ins, obj2, pcval))
+ return false;
+
+ if (PCVAL_IS_NULL(pcval) || !PCVAL_IS_OBJECT(pcval))
+ ABORT_TRACE("callee is not an object");
+ JS_ASSERT(HAS_FUNCTION_CLASS(PCVAL_TO_OBJECT(pcval)));
+
+ stack(0, INS_CONSTPTR(PCVAL_TO_OBJECT(pcval)));
+ stack(1, obj_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_GETUPVAR()
+{
+ ABORT_TRACE("GETUPVAR");
+}
+
+bool
+TraceRecorder::record_JSOP_CALLUPVAR()
+{
+ ABORT_TRACE("CALLUPVAR");
+}
+
+bool
+TraceRecorder::guardShapelessCallee(jsval& callee)
+{
+ guard(true,
+ addName(lir->ins2(LIR_eq, get(&callee), INS_CONSTPTR(JSVAL_TO_OBJECT(callee))),
+ "guard(shapeless callee)"),
+ MISMATCH_EXIT);
+ return true;
+}
+
+bool
+TraceRecorder::interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc, bool constructing)
+{
+ if (JS_GetGlobalForObject(cx, JSVAL_TO_OBJECT(fval)) != globalObj)
+ ABORT_TRACE("JSOP_CALL or JSOP_NEW crosses global scopes");
+
+ JSStackFrame* fp = cx->fp;
+
+ // TODO: track the copying via the tracker...
+ if (argc < fun->nargs &&
+ jsuword(fp->regs->sp + (fun->nargs - argc)) > cx->stackPool.current->limit) {
+ ABORT_TRACE("can't trace calls with too few args requiring argv move");
+ }
+
+ // Generate a type map for the outgoing frame and stash it in the LIR
+ unsigned stackSlots = js_NativeStackSlots(cx, 0/*callDepth*/);
+ LIns* data = lir_buf_writer->skip(stackSlots * sizeof(uint8));
+ uint8* typemap = (uint8 *)data->payload();
+ uint8* m = typemap;
+ /* Determine the type of a store by looking at the current type of the actual value the
+ interpreter is using. For numbers we have to check what kind of store we used last
+ (integer or double) to figure out what the side exit show reflect in its typemap. */
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0/*callDepth*/,
+ *m++ = determineSlotType(vp);
+ );
+
+ if (argc >= 0x8000)
+ ABORT_TRACE("too many arguments");
+
+ FrameInfo fi = {
+ JSVAL_TO_OBJECT(fval),
+ ENCODE_IP_ADJ(fp, fp->regs->pc),
+ typemap,
+ { { fp->regs->sp - fp->slots, argc | (constructing ? 0x8000 : 0) } }
+ };
+
+ unsigned callDepth = getCallDepth();
+ if (callDepth >= treeInfo->maxCallDepth)
+ treeInfo->maxCallDepth = callDepth + 1;
+
+ lir->insStorei(INS_CONSTPTR(fi.callee), lirbuf->rp,
+ callDepth * sizeof(FrameInfo) + offsetof(FrameInfo, callee));
+ lir->insStorei(INS_CONSTPTR(fi.ip_adj), lirbuf->rp,
+ callDepth * sizeof(FrameInfo) + offsetof(FrameInfo, ip_adj));
+ lir->insStorei(INS_CONSTPTR(fi.typemap), lirbuf->rp,
+ callDepth * sizeof(FrameInfo) + offsetof(FrameInfo, typemap));
+ lir->insStorei(INS_CONST(fi.word), lirbuf->rp,
+ callDepth * sizeof(FrameInfo) + offsetof(FrameInfo, word));
+
+ atoms = fun->u.i.script->atomMap.vector;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALL()
+{
+ return functionCall(false);
+}
+
+bool
+TraceRecorder::record_JSOP_APPLY()
+{
+ return functionCall(false);
+}
+
+bool
+TraceRecorder::record_FastNativeCallComplete()
+{
+ JS_ASSERT(pendingTraceableNative);
+
+ /* At this point the generated code has already called the native function
+ and we can no longer fail back to the original pc location (JSOP_CALL)
+ because that would cause the interpreter to re-execute the native
+ function, which might have side effects.
+
+ Instead, snapshot(), which is invoked from unbox_jsval(), will see that
+ we are currently parked on a traceable native's JSOP_CALL instruction,
+ and it will advance the pc to restore by the length of the current
+ opcode, and indicate in the type map that the element on top of the
+ stack is a boxed value which doesn't need to be boxed if the type guard
+ generated by unbox_jsval() fails. */
+ JS_ASSERT(*cx->fp->regs->pc == JSOP_CALL ||
+ *cx->fp->regs->pc == JSOP_APPLY);
+
+ jsval& v = stackval(-1);
+ LIns* v_ins = get(&v);
+
+ bool ok = true;
+ switch (JSTN_ERRTYPE(pendingTraceableNative)) {
+ case FAIL_JSVAL:
+ ok = unbox_jsval(v, v_ins);
+ if (ok)
+ set(&v, v_ins);
+ break;
+ case FAIL_NEG:
+ /* Already added i2f in functionCall. */
+ JS_ASSERT(JSVAL_IS_NUMBER(v));
+ break;
+ default:
+ /* Convert the result to double if the builtin returns int32. */
+ if (JSVAL_IS_NUMBER(v) &&
+ (pendingTraceableNative->builtin->_argtypes & 3) == nanojit::ARGSIZE_LO) {
+ set(&v, lir->ins1(LIR_i2f, v_ins));
+ }
+ }
+
+ // We'll null pendingTraceableNative in js_MonitorRecording, on the next op cycle.
+ // There must be a next op since the stack is non-empty.
+ return ok;
+}
+
+bool
+TraceRecorder::name(jsval*& vp)
+{
+ JSObject* obj = cx->fp->scopeChain;
+ if (obj != globalObj)
+ return activeCallOrGlobalSlot(obj, vp);
+
+ /* Can't use prop here, because we don't want unboxing from global slots. */
+ LIns* obj_ins = scopeChain();
+ uint32 slot;
+ if (!test_property_cache_direct_slot(obj, obj_ins, slot))
+ return false;
+
+ if (slot == SPROP_INVALID_SLOT)
+ ABORT_TRACE("name op can't find named property");
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ vp = &STOBJ_GET_SLOT(obj, slot);
+ return true;
+}
+
+bool
+TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32& slot, LIns*& v_ins)
+{
+ /*
+ * Can't specialize to assert obj != global, must guard to avoid aliasing
+ * stale homes of stacked global variables.
+ */
+ if (obj == globalObj)
+ ABORT_TRACE("prop op aliases global");
+ guard(false, lir->ins2(LIR_eq, obj_ins, INS_CONSTPTR(globalObj)), MISMATCH_EXIT);
+
+ /*
+ * Property cache ensures that we are dealing with an existing property,
+ * and guards the shape for us.
+ */
+ JSObject* obj2;
+ jsuword pcval;
+ if (!test_property_cache(obj, obj_ins, obj2, pcval))
+ return false;
+
+ /* Check for non-existent property reference, which results in undefined. */
+ const JSCodeSpec& cs = js_CodeSpec[*cx->fp->regs->pc];
+ if (PCVAL_IS_NULL(pcval)) {
+ v_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+ JS_ASSERT(cs.ndefs == 1);
+ stack(-cs.nuses, v_ins);
+ slot = SPROP_INVALID_SLOT;
+ return true;
+ }
+
+ /* Insist if setting on obj being the directly addressed object. */
+ uint32 setflags = (cs.format & (JOF_SET | JOF_INCDEC));
+ LIns* dslots_ins = NULL;
+ if (obj2 != obj) {
+ if (setflags)
+ ABORT_TRACE("JOF_SET opcode hit prototype chain");
+
+ /*
+ * We're getting a proto-property. Walk up the prototype chain emitting
+ * proto slot loads, updating obj as we go, leaving obj set to obj2 with
+ * obj_ins the last proto-load.
+ */
+ while (obj != obj2) {
+ obj_ins = stobj_get_slot(obj_ins, JSSLOT_PROTO, dslots_ins);
+ obj = STOBJ_GET_PROTO(obj);
+ }
+ }
+
+ /* Don't trace getter or setter calls, our caller wants a direct slot. */
+ if (PCVAL_IS_SPROP(pcval)) {
+ JSScopeProperty* sprop = PCVAL_TO_SPROP(pcval);
+
+ if (setflags && !SPROP_HAS_STUB_SETTER(sprop))
+ ABORT_TRACE("non-stub setter");
+ if (setflags != JOF_SET && !SPROP_HAS_STUB_GETTER(sprop)) {
+ // FIXME 450335: generalize this away from regexp built-in getters.
+ if (setflags == 0 &&
+ sprop->getter == js_RegExpClass.getProperty &&
+ sprop->shortid < 0) {
+ if (sprop->shortid == REGEXP_LAST_INDEX)
+ ABORT_TRACE("can't trace regexp.lastIndex yet");
+ LIns* args[] = { INS_CONSTPTR(sprop), obj_ins, cx_ins };
+ v_ins = lir->insCall(&js_CallGetter_ci, args);
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), OOM_EXIT);
+ if (!unbox_jsval((sprop->shortid == REGEXP_SOURCE) ? JSVAL_STRING : JSVAL_BOOLEAN,
+ v_ins)) {
+ ABORT_TRACE("unboxing");
+ }
+ JS_ASSERT(cs.ndefs == 1);
+ stack(-cs.nuses, v_ins);
+ return true;
+ }
+ ABORT_TRACE("non-stub getter");
+ }
+ if (!SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)))
+ ABORT_TRACE("no valid slot");
+ slot = sprop->slot;
+ } else {
+ if (!PCVAL_IS_SLOT(pcval))
+ ABORT_TRACE("PCE is not a slot");
+ slot = PCVAL_TO_SLOT(pcval);
+ }
+
+ v_ins = stobj_get_slot(obj_ins, slot, dslots_ins);
+ if (!unbox_jsval(STOBJ_GET_SLOT(obj, slot), v_ins))
+ ABORT_TRACE("unboxing");
+ return true;
+}
+
+bool
+TraceRecorder::elem(jsval& oval, jsval& idx, jsval*& vp, LIns*& v_ins, LIns*& addr_ins)
+{
+ /* no guards for type checks, trace specialized this already */
+ if (JSVAL_IS_PRIMITIVE(oval) || !JSVAL_IS_INT(idx))
+ return false;
+
+ JSObject* obj = JSVAL_TO_OBJECT(oval);
+ LIns* obj_ins = get(&oval);
+
+ /* make sure the object is actually a dense array */
+ if (!guardDenseArray(obj, obj_ins))
+ return false;
+
+ /* check that the index is within bounds */
+ jsint i = JSVAL_TO_INT(idx);
+ LIns* idx_ins = makeNumberInt32(get(&idx));
+
+ LIns* dslots_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots));
+ if (!guardDenseArrayIndex(obj, i, obj_ins, dslots_ins, idx_ins, BRANCH_EXIT)) {
+ LIns* rt_ins = lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, runtime));
+ guard(true,
+ lir->ins_eq0(lir->insLoad(LIR_ldp, rt_ins,
+ offsetof(JSRuntime, anyArrayProtoHasElement))),
+ MISMATCH_EXIT);
+ // Return undefined and indicate that we didn't actually read this (addr_ins).
+ v_ins = lir->insImm(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+ addr_ins = NULL;
+ return true;
+ }
+
+ // We can't "see through" a hole to a possible Array.prototype property, so
+ // we abort here and guard below (after unboxing).
+ vp = &obj->dslots[i];
+ if (*vp == JSVAL_HOLE)
+ ABORT_TRACE("can't see through hole in dense array");
+
+ addr_ins = lir->ins2(LIR_piadd, dslots_ins,
+ lir->ins2i(LIR_pilsh, idx_ins, (sizeof(jsval) == 4) ? 2 : 3));
+
+ /* Load the value and guard on its type to unbox it. */
+ v_ins = lir->insLoad(LIR_ldp, addr_ins, 0);
+ if (!unbox_jsval(*vp, v_ins))
+ return false;
+
+ if (JSVAL_TAG(*vp) == JSVAL_BOOLEAN) {
+ // Optimize to guard for a hole only after untagging, so we know that
+ // we have a boolean, to avoid an extra guard for non-boolean values.
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_HOLE))),
+ MISMATCH_EXIT);
+ }
+ return true;
+}
+
+bool
+TraceRecorder::getProp(JSObject* obj, LIns* obj_ins)
+{
+ uint32 slot;
+ LIns* v_ins;
+ if (!prop(obj, obj_ins, slot, v_ins))
+ return false;
+
+ const JSCodeSpec& cs = js_CodeSpec[*cx->fp->regs->pc];
+ JS_ASSERT(cs.ndefs == 1);
+ stack(-cs.nuses, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::getProp(jsval& v)
+{
+ if (JSVAL_IS_PRIMITIVE(v))
+ ABORT_TRACE("primitive lhs");
+
+ return getProp(JSVAL_TO_OBJECT(v), get(&v));
+}
+
+bool
+TraceRecorder::record_JSOP_NAME()
+{
+ jsval* vp;
+ if (!name(vp))
+ return false;
+ stack(0, get(vp));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_DOUBLE()
+{
+ jsval v = jsval(atoms[GET_INDEX(cx->fp->regs->pc)]);
+ jsdpun u;
+ u.d = *JSVAL_TO_DOUBLE(v);
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_STRING()
+{
+ JSAtom* atom = atoms[GET_INDEX(cx->fp->regs->pc)];
+ JS_ASSERT(ATOM_IS_STRING(atom));
+ stack(0, INS_CONSTPTR(ATOM_TO_STRING(atom)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_ZERO()
+{
+ jsdpun u;
+ u.d = 0.0;
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_ONE()
+{
+ jsdpun u;
+ u.d = 1.0;
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NULL()
+{
+ stack(0, INS_CONSTPTR(NULL));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_THIS()
+{
+ LIns* this_ins;
+ if (!getThis(this_ins))
+ return false;
+ stack(0, this_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_FALSE()
+{
+ stack(0, lir->insImm(0));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_TRUE()
+{
+ stack(0, lir->insImm(1));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_OR()
+{
+ return ifop();
+}
+
+bool
+TraceRecorder::record_JSOP_AND()
+{
+ return ifop();
+}
+
+bool
+TraceRecorder::record_JSOP_TABLESWITCH()
+{
+ return switchop();
+}
+
+bool
+TraceRecorder::record_JSOP_LOOKUPSWITCH()
+{
+ return switchop();
+}
+
+bool
+TraceRecorder::record_JSOP_STRICTEQ()
+{
+ return cmp(LIR_feq, CMP_STRICT);
+}
+
+bool
+TraceRecorder::record_JSOP_STRICTNE()
+{
+ return cmp(LIR_feq, CMP_STRICT | CMP_NEGATE);
+}
+
+bool
+TraceRecorder::record_JSOP_OBJECT()
+{
+ JSStackFrame* fp = cx->fp;
+ JSScript* script = fp->script;
+ unsigned index = atoms - script->atomMap.vector + GET_INDEX(fp->regs->pc);
+
+ JSObject* obj;
+ JS_GET_SCRIPT_OBJECT(script, index, obj);
+ stack(0, INS_CONSTPTR(obj));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_POP()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_POS()
+{
+ jsval& r = stackval(-1);
+ return isNumber(r);
+}
+
+bool
+TraceRecorder::record_JSOP_TRAP()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GETARG()
+{
+ stack(0, arg(GET_ARGNO(cx->fp->regs->pc)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETARG()
+{
+ arg(GET_ARGNO(cx->fp->regs->pc), stack(-1));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_GETLOCAL()
+{
+ stack(0, var(GET_SLOTNO(cx->fp->regs->pc)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETLOCAL()
+{
+ var(GET_SLOTNO(cx->fp->regs->pc), stack(-1));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_UINT16()
+{
+ jsdpun u;
+ u.d = (jsdouble)GET_UINT16(cx->fp->regs->pc);
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NEWINIT()
+{
+ JSProtoKey key = JSProtoKey(GET_INT8(cx->fp->regs->pc));
+ JSObject* obj;
+ const CallInfo *ci;
+ if (key == JSProto_Array) {
+ if (!js_GetClassPrototype(cx, globalObj, INT_TO_JSID(key), &obj))
+ return false;
+ ci = &js_FastNewArray_ci;
+ } else {
+ jsval v_obj;
+ if (!js_FindClassObject(cx, globalObj, INT_TO_JSID(key), &v_obj))
+ return false;
+ if (JSVAL_IS_PRIMITIVE(v_obj))
+ ABORT_TRACE("primitive Object value");
+ obj = JSVAL_TO_OBJECT(v_obj);
+ ci = &js_FastNewObject_ci;
+ }
+ LIns* args[] = { INS_CONSTPTR(obj), cx_ins };
+ LIns* v_ins = lir->insCall(ci, args);
+ guard(false, lir->ins_eq0(v_ins), OOM_EXIT);
+ stack(0, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_ENDINIT()
+{
+ jsval& v = stackval(-1);
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ JSObject* obj = JSVAL_TO_OBJECT(v);
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ // Until we get JSOP_NEWARRAY working, we do our optimizing here...
+ if (obj->fslots[JSSLOT_ARRAY_LENGTH] == 1 &&
+ obj->dslots && JSVAL_IS_STRING(obj->dslots[0])) {
+ LIns* v_ins = get(&v);
+ JS_ASSERT(v_ins->isCall() && v_ins->callInfo() == &js_FastNewArray_ci);
+ LIns* args[] = { stack(1), callArgN(v_ins, 1), cx_ins };
+ v_ins = lir->insCall(&js_Array_1str_ci, args);
+ set(&v, v_ins);
+ }
+ }
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INITPROP()
+{
+ // All the action is in record_SetPropHit.
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INITELEM()
+{
+ return record_JSOP_SETELEM();
+}
+
+bool
+TraceRecorder::record_JSOP_DEFSHARP()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_USESHARP()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_INCARG()
+{
+ return inc(argval(GET_ARGNO(cx->fp->regs->pc)), 1);
+}
+
+bool
+TraceRecorder::record_JSOP_INCLOCAL()
+{
+ return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), 1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECARG()
+{
+ return inc(argval(GET_ARGNO(cx->fp->regs->pc)), -1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECLOCAL()
+{
+ return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), -1);
+}
+
+bool
+TraceRecorder::record_JSOP_ARGINC()
+{
+ return inc(argval(GET_ARGNO(cx->fp->regs->pc)), 1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_LOCALINC()
+{
+ return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), 1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_ARGDEC()
+{
+ return inc(argval(GET_ARGNO(cx->fp->regs->pc)), -1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_LOCALDEC()
+{
+ return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), -1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_IMACOP()
+{
+ JS_ASSERT(cx->fp->imacpc);
+ return true;
+}
+
+static struct {
+ jsbytecode for_in[10];
+ jsbytecode for_each[10];
+} iter_imacros = {
+ {
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(iterator),
+ JSOP_INT8, JSITER_ENUMERATE,
+ JSOP_CALL, 0, 1,
+ JSOP_PUSH,
+ JSOP_STOP
+ },
+
+ {
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(iterator),
+ JSOP_INT8, JSITER_ENUMERATE | JSITER_FOREACH,
+ JSOP_CALL, 0, 1,
+ JSOP_PUSH,
+ JSOP_STOP
+ }
+};
+
+JS_STATIC_ASSERT(sizeof(iter_imacros) < IMACRO_PC_ADJ_LIMIT);
+
+bool
+TraceRecorder::record_JSOP_ITER()
+{
+ jsval& v = stackval(-1);
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ jsuint flags = cx->fp->regs->pc[1];
+
+ if (!hasIteratorMethod(v)) {
+ LIns* args[] = { get(&v), INS_CONST(flags), cx_ins };
+ LIns* v_ins = lir->insCall(&js_FastValueToIterator_ci, args);
+ guard(false, lir->ins_eq0(v_ins), MISMATCH_EXIT);
+ set(&v, v_ins);
+
+ LIns* void_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+ stack(0, void_ins);
+ return true;
+ }
+
+ if (flags == JSITER_ENUMERATE)
+ return call_imacro(iter_imacros.for_in);
+ if (flags == (JSITER_ENUMERATE | JSITER_FOREACH))
+ return call_imacro(iter_imacros.for_each);
+ ABORT_TRACE("unimplemented JSITER_* flags");
+ }
+
+ ABORT_TRACE("for-in on a primitive value");
+}
+
+static JSTraceableNative js_FastCallIteratorNext_tn = {
+ NULL, // JSFastNative native;
+ &js_FastCallIteratorNext_ci, // const nanojit::CallInfo *builtin;
+ "C", // const char *prefix;
+ "o", // const char *argtypes;
+ FAIL_JSVAL // uintN flags;
+};
+
+static jsbytecode nextiter_imacro[] = {
+ JSOP_POP,
+ JSOP_DUP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(next),
+ JSOP_CALL, 0, 0,
+ JSOP_TRUE,
+ JSOP_STOP
+};
+
+JS_STATIC_ASSERT(sizeof(nextiter_imacro) < IMACRO_PC_ADJ_LIMIT);
+
+bool
+TraceRecorder::record_JSOP_NEXTITER()
+{
+ jsval& iterobj_val = stackval(-2);
+ if (!JSVAL_IS_PRIMITIVE(iterobj_val)) {
+ LIns* iterobj_ins = get(&iterobj_val);
+
+ if (guardClass(JSVAL_TO_OBJECT(iterobj_val), iterobj_ins, &js_IteratorClass, BRANCH_EXIT)) {
+ LIns* args[] = { iterobj_ins, cx_ins };
+ LIns* v_ins = lir->insCall(&js_FastCallIteratorNext_ci, args);
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), OOM_EXIT);
+
+ LIns* flag_ins = lir->ins_eq0(lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_HOLE)));
+ stack(-1, v_ins);
+ stack(0, flag_ins);
+
+ pendingTraceableNative = &js_FastCallIteratorNext_tn;
+ return true;
+ }
+
+ // Custom iterator, possibly a generator.
+ return call_imacro(nextiter_imacro);
+ }
+
+ ABORT_TRACE("for-in on a primitive value");
+}
+
+bool
+TraceRecorder::record_IteratorNextComplete()
+{
+ JS_ASSERT(*cx->fp->regs->pc == JSOP_NEXTITER);
+ JS_ASSERT(pendingTraceableNative == &js_FastCallIteratorNext_tn);
+
+ jsval& v = stackval(-2);
+ LIns* v_ins = get(&v);
+ if (unbox_jsval(v, v_ins)) {
+ set(&v, v_ins);
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ENDITER()
+{
+ LIns* args[] = { stack(-2), cx_ins };
+ LIns* ok_ins = lir->insCall(&js_CloseIterator_ci, args);
+ guard(false, lir->ins_eq0(ok_ins), MISMATCH_EXIT);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_FORNAME()
+{
+ jsval* vp;
+ if (name(vp)) {
+ set(vp, stack(-1));
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_FORPROP()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_FORELEM()
+{
+ return record_JSOP_DUP();
+}
+
+bool
+TraceRecorder::record_JSOP_FORARG()
+{
+ return record_JSOP_SETARG();
+}
+
+bool
+TraceRecorder::record_JSOP_FORLOCAL()
+{
+ return record_JSOP_SETLOCAL();
+}
+
+bool
+TraceRecorder::record_JSOP_POPN()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_BINDNAME()
+{
+ JSObject* obj = cx->fp->scopeChain;
+ if (obj != globalObj)
+ ABORT_TRACE("JSOP_BINDNAME crosses global scopes");
+
+ LIns* obj_ins = scopeChain();
+ JSObject* obj2;
+ jsuword pcval;
+ if (!test_property_cache(obj, obj_ins, obj2, pcval))
+ return false;
+ if (obj2 != obj)
+ ABORT_TRACE("JSOP_BINDNAME found a non-direct property on the global object");
+
+ stack(0, obj_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETNAME()
+{
+ jsval& l = stackval(-2);
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(l));
+
+ /*
+ * Trace cases that are global code or in lightweight functions scoped by
+ * the global object only.
+ */
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ if (obj != cx->fp->scopeChain || obj != globalObj)
+ ABORT_TRACE("JSOP_SETNAME left operand is not the global object");
+
+ // The rest of the work is in record_SetPropHit.
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_THROW()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_IN()
+{
+ jsval& rval = stackval(-1);
+ jsval& lval = stackval(-2);
+
+ if (JSVAL_IS_PRIMITIVE(rval))
+ ABORT_TRACE("JSOP_IN on non-object right operand");
+ JSObject* obj = JSVAL_TO_OBJECT(rval);
+ LIns* obj_ins = get(&rval);
+
+ jsid id;
+ LIns* x;
+ if (JSVAL_IS_INT(lval)) {
+ id = INT_JSVAL_TO_JSID(lval);
+ LIns* args[] = { makeNumberInt32(get(&lval)), obj_ins, cx_ins };
+ x = lir->insCall(&js_HasNamedPropertyInt32_ci, args);
+ } else if (JSVAL_IS_STRING(lval)) {
+ if (!js_ValueToStringId(cx, lval, &id))
+ ABORT_TRACE("left operand of JSOP_IN didn't convert to a string-id");
+ LIns* args[] = { get(&lval), obj_ins, cx_ins };
+ x = lir->insCall(&js_HasNamedProperty_ci, args);
+ } else {
+ ABORT_TRACE("string or integer expected");
+ }
+
+ guard(false, lir->ins2i(LIR_eq, x, JSVAL_TO_BOOLEAN(JSVAL_VOID)), OOM_EXIT);
+ x = lir->ins2i(LIR_eq, x, 1);
+
+ JSObject* obj2;
+ JSProperty* prop;
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ ABORT_TRACE("OBJ_LOOKUP_PROPERTY failed in JSOP_IN");
+ bool cond = prop != NULL;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+
+ /* The interpreter fuses comparisons and the following branch,
+ so we have to do that here as well. */
+ fuseIf(cx->fp->regs->pc + 1, cond, x);
+
+ /* We update the stack after the guard. This is safe since
+ the guard bails out at the comparison and the interpreter
+ will therefore re-execute the comparison. This way the
+ value of the condition doesn't have to be calculated and
+ saved on the stack in most cases. */
+ set(&lval, x);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INSTANCEOF()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DEBUGGER()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GOSUB()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_RETSUB()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_EXCEPTION()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_LINENO()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CONDSWITCH()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CASE()
+{
+ return cmp(LIR_feq, CMP_CASE);
+}
+
+bool
+TraceRecorder::record_JSOP_DEFAULT()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_EVAL()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ENUMELEM()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GETTER()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_SETTER()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DEFFUN()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DEFCONST()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DEFVAR()
+{
+ return false;
+}
+
+/*
+ * XXX could hoist out to jsinterp.h and share with jsinterp.cpp, but
+ * XXX jsopcode.cpp has different definitions of same-named macros.
+ */
+#define GET_FULL_INDEX(PCOFF) \
+ (atoms - script->atomMap.vector + GET_INDEX(regs.pc + PCOFF))
+
+#define LOAD_FUNCTION(PCOFF) \
+ JS_GET_SCRIPT_FUNCTION(script, GET_FULL_INDEX(PCOFF), fun)
+
+bool
+TraceRecorder::record_JSOP_ANONFUNOBJ()
+{
+ JSFunction* fun;
+ JSFrameRegs& regs = *cx->fp->regs;
+ JSScript* script = cx->fp->script;
+ LOAD_FUNCTION(0); // needs script, regs, fun
+
+ JSObject* obj = FUN_OBJECT(fun);
+ if (OBJ_GET_PARENT(cx, obj) != cx->fp->scopeChain)
+ ABORT_TRACE("can't trace with activation object on scopeChain");
+
+ stack(0, INS_CONSTPTR(obj));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NAMEDFUNOBJ()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_SETLOCALPOP()
+{
+ var(GET_SLOTNO(cx->fp->regs->pc), stack(-1));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETCALL()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TRY()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_FINALLY()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NOP()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_ARGSUB()
+{
+ JSStackFrame* fp = cx->fp;
+ if (!(fp->fun->flags & JSFUN_HEAVYWEIGHT)) {
+ uintN slot = GET_ARGNO(fp->regs->pc);
+ if (slot < fp->fun->nargs && slot < fp->argc && !fp->argsobj) {
+ stack(0, get(&cx->fp->argv[slot]));
+ return true;
+ }
+ }
+ ABORT_TRACE("can't trace JSOP_ARGSUB hard case");
+}
+
+bool
+TraceRecorder::record_JSOP_ARGCNT()
+{
+ if (!(cx->fp->fun->flags & JSFUN_HEAVYWEIGHT)) {
+ jsdpun u;
+ u.d = cx->fp->argc;
+ stack(0, lir->insImmq(u.u64));
+ return true;
+ }
+ ABORT_TRACE("can't trace heavyweight JSOP_ARGCNT");
+}
+
+bool
+TraceRecorder::record_DefLocalFunSetSlot(uint32 slot, JSObject* obj)
+{
+ var(slot, INS_CONSTPTR(obj));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_DEFLOCALFUN()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_GOTOX()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_IFEQX()
+{
+ trackCfgMerges(cx->fp->regs->pc);
+ return record_JSOP_IFEQ();
+}
+
+bool
+TraceRecorder::record_JSOP_IFNEX()
+{
+ return record_JSOP_IFNE();
+}
+
+bool
+TraceRecorder::record_JSOP_ORX()
+{
+ return record_JSOP_OR();
+}
+
+bool
+TraceRecorder::record_JSOP_ANDX()
+{
+ return record_JSOP_AND();
+}
+
+bool
+TraceRecorder::record_JSOP_GOSUBX()
+{
+ return record_JSOP_GOSUB();
+}
+
+bool
+TraceRecorder::record_JSOP_CASEX()
+{
+ return cmp(LIR_feq, CMP_CASE);
+}
+
+bool
+TraceRecorder::record_JSOP_DEFAULTX()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_TABLESWITCHX()
+{
+ return switchop();
+}
+
+bool
+TraceRecorder::record_JSOP_LOOKUPSWITCHX()
+{
+ return switchop();
+}
+
+bool
+TraceRecorder::record_JSOP_BACKPATCH()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_BACKPATCH_POP()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_THROWING()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_SETRVAL()
+{
+ // If we implement this, we need to update JSOP_STOP.
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_RETRVAL()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GETGVAR()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_NAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ stack(0, get(&STOBJ_GET_SLOT(globalObj, slot)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETGVAR()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_NAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ set(&STOBJ_GET_SLOT(globalObj, slot), stack(-1));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INCGVAR()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_INCNAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ return inc(STOBJ_GET_SLOT(globalObj, slot), 1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECGVAR()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_INCNAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ return inc(STOBJ_GET_SLOT(globalObj, slot), -1);
+}
+
+bool
+TraceRecorder::record_JSOP_GVARINC()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_INCNAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ return inc(STOBJ_GET_SLOT(globalObj, slot), 1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_GVARDEC()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_INCNAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ return inc(STOBJ_GET_SLOT(globalObj, slot), -1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_REGEXP()
+{
+ return false;
+}
+
+// begin JS_HAS_XML_SUPPORT
+
+bool
+TraceRecorder::record_JSOP_DEFXMLNS()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ANYNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_QNAMEPART()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_QNAMECONST()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_QNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TOATTRNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TOATTRVAL()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ADDATTRNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ADDATTRVAL()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_BINDXMLNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_SETXMLNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DESCENDANTS()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_FILTER()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ENDFILTER()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TOXML()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TOXMLLIST()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLTAGEXPR()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLELTEXPR()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLOBJECT()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLCDATA()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLCOMMENT()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLPI()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GETFUNNS()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_STARTXML()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_STARTXMLEXPR()
+{
+ return false;
+}
+
+// end JS_HAS_XML_SUPPORT
+
+bool
+TraceRecorder::record_JSOP_CALLPROP()
+{
+ jsval& l = stackval(-1);
+ JSObject* obj;
+ LIns* obj_ins;
+ LIns* this_ins;
+ if (!JSVAL_IS_PRIMITIVE(l)) {
+ obj = JSVAL_TO_OBJECT(l);
+ obj_ins = get(&l);
+ this_ins = obj_ins; // |this| for subsequent call
+ if (JSVAL_IS_NULL(l))
+ ABORT_TRACE("callprop on null");
+ if (!this_ins->isconstp())
+ guard(false, lir->ins_eq0(this_ins), MISMATCH_EXIT);
+ } else {
+ jsint i;
+ debug_only(const char* protoname = NULL;)
+ if (JSVAL_IS_STRING(l)) {
+ i = JSProto_String;
+ debug_only(protoname = "String.prototype";)
+ } else if (JSVAL_IS_NUMBER(l)) {
+ i = JSProto_Number;
+ debug_only(protoname = "Number.prototype";)
+ } else if (JSVAL_TAG(l) == JSVAL_BOOLEAN) {
+ if (l == JSVAL_VOID)
+ ABORT_TRACE("callprop on void");
+ guard(false, lir->ins2i(LIR_eq, get(&l), JSVAL_TO_BOOLEAN(JSVAL_VOID)), MISMATCH_EXIT);
+ i = JSProto_Boolean;
+ debug_only(protoname = "Boolean.prototype";)
+ } else {
+ JS_ASSERT(JSVAL_IS_NULL(l) || JSVAL_IS_VOID(l));
+ ABORT_TRACE("callprop on null or void");
+ }
+
+ if (!js_GetClassPrototype(cx, NULL, INT_TO_JSID(i), &obj))
+ ABORT_TRACE("GetClassPrototype failed!");
+
+ obj_ins = INS_CONSTPTR(obj);
+ debug_only(obj_ins = addName(obj_ins, protoname);)
+ this_ins = get(&l); // use primitive as |this|
+ }
+
+ JSObject* obj2;
+ jsuword pcval;
+ if (!test_property_cache(obj, obj_ins, obj2, pcval))
+ return false;
+
+ if (PCVAL_IS_NULL(pcval) || !PCVAL_IS_OBJECT(pcval))
+ ABORT_TRACE("callee is not an object");
+ JS_ASSERT(HAS_FUNCTION_CLASS(PCVAL_TO_OBJECT(pcval)));
+
+ if (JSVAL_IS_PRIMITIVE(l)) {
+ JSFunction* fun = GET_FUNCTION_PRIVATE(cx, PCVAL_TO_OBJECT(pcval));
+ if (!PRIMITIVE_THIS_TEST(fun, l))
+ ABORT_TRACE("callee does not accept primitive |this|");
+ }
+
+ stack(0, this_ins);
+ stack(-1, INS_CONSTPTR(PCVAL_TO_OBJECT(pcval)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_DELDESC()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_UINT24()
+{
+ jsdpun u;
+ u.d = (jsdouble)GET_UINT24(cx->fp->regs->pc);
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INDEXBASE()
+{
+ atoms += GET_INDEXBASE(cx->fp->regs->pc);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_RESETBASE()
+{
+ atoms = cx->fp->script->atomMap.vector;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_RESETBASE0()
+{
+ atoms = cx->fp->script->atomMap.vector;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLELEM()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_STOP()
+{
+ JSStackFrame *fp = cx->fp;
+
+ if (fp->imacpc) {
+ // End of imacro, so return true to the interpreter immediately. The
+ // interpreter's JSOP_STOP case will return from the imacro, back to
+ // the pc after the calling op, still in the same JSStackFrame.
+ atoms = fp->script->atomMap.vector;
+ return true;
+ }
+
+ /*
+ * We know falling off the end of a constructor returns the new object that
+ * was passed in via fp->argv[-1], while falling off the end of a function
+ * returns undefined.
+ *
+ * NB: we do not support script rval (eval, API users who want the result
+ * of the last expression-statement, debugger API calls).
+ */
+ if (fp->flags & JSFRAME_CONSTRUCTING) {
+ JS_ASSERT(OBJECT_TO_JSVAL(fp->thisp) == fp->argv[-1]);
+ rval_ins = get(&fp->argv[-1]);
+ } else {
+ rval_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+ }
+ clearFrameSlotsFromCache();
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_GETXPROP()
+{
+ jsval& l = stackval(-1);
+ if (JSVAL_IS_PRIMITIVE(l))
+ ABORT_TRACE("primitive-this for GETXPROP?");
+
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ if (obj != cx->fp->scopeChain || obj != globalObj)
+ return false;
+
+ jsval* vp;
+ if (!name(vp))
+ return false;
+ stack(-1, get(vp));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLXMLNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TYPEOFEXPR()
+{
+ return record_JSOP_TYPEOF();
+}
+
+bool
+TraceRecorder::record_JSOP_ENTERBLOCK()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_LEAVEBLOCK()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GENERATOR()
+{
+ return false;
+#if 0
+ JSStackFrame* fp = cx->fp;
+ if (fp->callobj || fp->argsobj || fp->varobj)
+ ABORT_TRACE("can't trace hard-case generator");
+
+ // Generate a type map for the outgoing frame and stash it in the LIR
+ unsigned stackSlots = js_NativeStackSlots(cx, 0/*callDepth*/);
+ LIns* data = lir_buf_writer->skip(stackSlots * sizeof(uint8));
+ uint8* typemap = (uint8 *)data->payload();
+ uint8* m = typemap;
+ /* Determine the type of a store by looking at the current type of the actual value the
+ interpreter is using. For numbers we have to check what kind of store we used last
+ (integer or double) to figure out what the side exit show reflect in its typemap. */
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0/*callDepth*/,
+ *m++ = determineSlotType(vp);
+ );
+ FlushNativeStackFrame(cx, 0, typemap, state.???, NULL);
+
+ LIns* args[] = { INS_CONST(fp->argc), INS_CONSTPTR(fp->callee), cx_ins };
+ LIns* g_ins = lir->insCall(&js_FastNewGenerator_ci, args);
+ guard(false, lir->ins_eq0(g_ins), OOM_EXIT);
+ return true;
+#endif
+}
+
+bool
+TraceRecorder::record_JSOP_YIELD()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ARRAYPUSH()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ENUMCONSTELEM()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_LEAVEBLOCKEXPR()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GETTHISPROP()
+{
+ LIns* this_ins;
+
+ /* its safe to just use cx->fp->thisp here because getThis() returns false if thisp
+ is not available */
+ return getThis(this_ins) && getProp(cx->fp->thisp, this_ins);
+}
+
+bool
+TraceRecorder::record_JSOP_GETARGPROP()
+{
+ return getProp(argval(GET_ARGNO(cx->fp->regs->pc)));
+}
+
+bool
+TraceRecorder::record_JSOP_GETLOCALPROP()
+{
+ return getProp(varval(GET_SLOTNO(cx->fp->regs->pc)));
+}
+
+bool
+TraceRecorder::record_JSOP_INDEXBASE1()
+{
+ atoms += 1 << 16;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INDEXBASE2()
+{
+ atoms += 2 << 16;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INDEXBASE3()
+{
+ atoms += 3 << 16;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLGVAR()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_CALLNAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ jsval& v = STOBJ_GET_SLOT(cx->fp->scopeChain, slot);
+ stack(0, get(&v));
+ stack(1, INS_CONSTPTR(NULL));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLLOCAL()
+{
+ uintN slot = GET_SLOTNO(cx->fp->regs->pc);
+ stack(0, var(slot));
+ stack(1, INS_CONSTPTR(NULL));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLARG()
+{
+ uintN slot = GET_ARGNO(cx->fp->regs->pc);
+ stack(0, arg(slot));
+ stack(1, INS_CONSTPTR(NULL));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NULLTHIS()
+{
+ stack(0, INS_CONSTPTR(NULL));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INT8()
+{
+ jsdpun u;
+ u.d = (jsdouble)GET_INT8(cx->fp->regs->pc);
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INT32()
+{
+ jsdpun u;
+ u.d = (jsdouble)GET_INT32(cx->fp->regs->pc);
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_LENGTH()
+{
+ jsval& l = stackval(-1);
+ if (JSVAL_IS_PRIMITIVE(l)) {
+ if (!JSVAL_IS_STRING(l))
+ ABORT_TRACE("non-string primitives unsupported");
+ LIns* str_ins = get(&l);
+ LIns* len_ins = lir->insLoad(LIR_ldp, str_ins, (int)offsetof(JSString, length));
+
+ LIns* masked_len_ins = lir->ins2(LIR_piand,
+ len_ins,
+ INS_CONSTPTR(JSSTRING_LENGTH_MASK));
+
+ LIns *choose_len_ins =
+ lir->ins_choose(lir->ins_eq0(lir->ins2(LIR_piand,
+ len_ins,
+ INS_CONSTPTR(JSSTRFLAG_DEPENDENT))),
+ masked_len_ins,
+ lir->ins_choose(lir->ins_eq0(lir->ins2(LIR_piand,
+ len_ins,
+ INS_CONSTPTR(JSSTRFLAG_PREFIX))),
+ lir->ins2(LIR_piand,
+ len_ins,
+ INS_CONSTPTR(JSSTRDEP_LENGTH_MASK)),
+ masked_len_ins));
+
+ set(&l, lir->ins1(LIR_i2f, choose_len_ins));
+ return true;
+ }
+
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj))
+ ABORT_TRACE("only dense arrays supported");
+ if (!guardDenseArray(obj, get(&l)))
+ ABORT_TRACE("OBJ_IS_DENSE_ARRAY but not?!?");
+ LIns* v_ins = lir->ins1(LIR_i2f, stobj_get_fslot(get(&l), JSSLOT_ARRAY_LENGTH));
+ set(&l, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NEWARRAY()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_HOLE()
+{
+ stack(0, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_HOLE)));
+ return true;
+}
+
+#ifdef JS_JIT_SPEW
+/* Prints information about entry typemaps and unstable exits for all peers at a PC */
+void
+js_DumpPeerStability(Fragmento* frago, const void* ip)
+{
+ Fragment* f;
+ TreeInfo* ti;
+ bool looped = false;
+ unsigned length = 0;
+
+ for (f = frago->getLoop(ip); f != NULL; f = f->peer) {
+ if (!f->vmprivate)
+ continue;
+ printf("fragment %p:\nENTRY: ", f);
+ ti = (TreeInfo*)f->vmprivate;
+ if (looped)
+ JS_ASSERT(ti->stackTypeMap.length() == length);
+ for (unsigned i = 0; i < ti->stackTypeMap.length(); i++)
+ printf("%d ", ti->stackTypeMap.data()[i]);
+ printf("\n");
+ UnstableExit* uexit = ti->unstableExits;
+ while (uexit != NULL) {
+ printf("EXIT: ");
+ uint8* m = getTypeMap(uexit->exit) + uexit->exit->numGlobalSlots;
+ for (unsigned i = 0; i < uexit->exit->numStackSlots; i++)
+ printf("%d ", m[i]);
+ printf("\n");
+ uexit = uexit->next;
+ }
+ length = ti->stackTypeMap.length();
+ looped = true;
+ }
+}
+#endif
+
+/*
+ * 17 potentially-converting binary operators:
+ * | ^ & == != < <= > >= << >> >>> + - * / %
+ */
+JS_STATIC_ASSERT((uintN)(JSOP_MOD - JSOP_BITOR) == 16);
+
+/*
+ * Use an old <ctype.h> trick: bias imacro_code[op] by -1 to allow zero high
+ * FrameInfo.ip_adj byte to mean "not in an imacro".
+ */
+static void
+InitIMacroCode()
+{
+ if (imacro_code[JSOP_NEXTITER]) {
+ JS_ASSERT(imacro_code[JSOP_NEXTITER] == nextiter_imacro - 1);
+ return;
+ }
+
+ for (uintN op = JSOP_BITOR; op <= JSOP_MOD; op++)
+ imacro_code[op] = (jsbytecode*)&binary_imacros - 1;
+
+ // NB: above loop mis-set JSOP_ADD's entry, so order here is crucial.
+ imacro_code[JSOP_ADD] = (jsbytecode*)&add_imacros - 1;
+
+ imacro_code[JSOP_ITER] = (jsbytecode*)&iter_imacros - 1;
+ imacro_code[JSOP_NEXTITER] = nextiter_imacro - 1;
+}
+
+#define UNUSED(n) bool TraceRecorder::record_JSOP_UNUSED##n() { return false; }
+
+UNUSED(131)
+UNUSED(201)
+UNUSED(202)
+UNUSED(203)
+UNUSED(204)
+UNUSED(205)
+UNUSED(206)
+UNUSED(207)
+UNUSED(208)
+UNUSED(209)
+UNUSED(219)
+UNUSED(226)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jstracer.h b/tools/node_modules/expresso/deps/jscoverage/js/jstracer.h
new file mode 100644
index 0000000..9295acb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jstracer.h
@@ -0,0 +1,552 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * May 28, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Brendan Eich <brendan@mozilla.org>
+ *
+ * Contributor(s):
+ * Andreas Gal <gal@mozilla.com>
+ * Mike Shaver <shaver@mozilla.org>
+ * David Anderson <danderson@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jstracer_h___
+#define jstracer_h___
+
+#ifdef JS_TRACER
+
+#include "jscntxt.h"
+#include "jsstddef.h"
+#include "jstypes.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsinterp.h"
+#include "jsbuiltins.h"
+
+#if defined(DEBUG) && !defined(JS_JIT_SPEW)
+#define JS_JIT_SPEW
+#endif
+
+template <typename T>
+class Queue : public avmplus::GCObject {
+ T* _data;
+ unsigned _len;
+ unsigned _max;
+
+ void ensure(unsigned size) {
+ while (_max < size)
+ _max <<= 1;
+ _data = (T*)realloc(_data, _max * sizeof(T));
+ }
+public:
+ Queue(unsigned max = 16) {
+ this->_max = max;
+ this->_len = 0;
+ this->_data = (T*)malloc(max * sizeof(T));
+ }
+
+ ~Queue() {
+ free(_data);
+ }
+
+ bool contains(T a) {
+ for (unsigned n = 0; n < _len; ++n)
+ if (_data[n] == a)
+ return true;
+ return false;
+ }
+
+ void add(T a) {
+ ensure(_len + 1);
+ JS_ASSERT(_len <= _max);
+ _data[_len++] = a;
+ }
+
+ void add(T* chunk, unsigned size) {
+ ensure(_len + size);
+ JS_ASSERT(_len <= _max);
+ memcpy(&_data[_len], chunk, size * sizeof(T));
+ _len += size;
+ }
+
+ void addUnique(T a) {
+ if (!contains(a))
+ add(a);
+ }
+
+ void setLength(unsigned len) {
+ ensure(len + 1);
+ _len = len;
+ }
+
+ void clear() {
+ _len = 0;
+ }
+
+ unsigned length() const {
+ return _len;
+ }
+
+ T* data() const {
+ return _data;
+ }
+};
+
+/*
+ * Tracker is used to keep track of values being manipulated by the interpreter
+ * during trace recording.
+ */
+class Tracker {
+ struct Page {
+ struct Page* next;
+ jsuword base;
+ nanojit::LIns* map[1];
+ };
+ struct Page* pagelist;
+
+ jsuword getPageBase(const void* v) const;
+ struct Page* findPage(const void* v) const;
+ struct Page* addPage(const void* v);
+public:
+ Tracker();
+ ~Tracker();
+
+ bool has(const void* v) const;
+ nanojit::LIns* get(const void* v) const;
+ void set(const void* v, nanojit::LIns* ins);
+ void clear();
+};
+
+/*
+ * The oracle keeps track of slots that should not be demoted to int because we know them
+ * to overflow or they result in type-unstable traces. We are using a simple hash table.
+ * Collisions lead to loss of optimization (demotable slots are not demoted) but have no
+ * correctness implications.
+ */
+#define ORACLE_SIZE 4096
+
+class Oracle {
+ avmplus::BitSet _dontDemote;
+public:
+ void markGlobalSlotUndemotable(JSScript* script, unsigned slot);
+ bool isGlobalSlotUndemotable(JSScript* script, unsigned slot) const;
+ void markStackSlotUndemotable(JSScript* script, jsbytecode* ip, unsigned slot);
+ bool isStackSlotUndemotable(JSScript* script, jsbytecode* ip, unsigned slot) const;
+ void clear();
+};
+
+typedef Queue<uint16> SlotList;
+
+class TypeMap : public Queue<uint8> {
+public:
+ void captureGlobalTypes(JSContext* cx, SlotList& slots);
+ void captureStackTypes(JSContext* cx, unsigned callDepth);
+ bool matches(TypeMap& other) const;
+};
+
+enum ExitType {
+ BRANCH_EXIT,
+ LOOP_EXIT,
+ NESTED_EXIT,
+ MISMATCH_EXIT,
+ OOM_EXIT,
+ OVERFLOW_EXIT,
+ UNSTABLE_LOOP_EXIT,
+ TIMEOUT_EXIT
+};
+
+struct VMSideExit : public nanojit::SideExit
+{
+ intptr_t ip_adj;
+ intptr_t sp_adj;
+ intptr_t rp_adj;
+ int32_t calldepth;
+ uint32 numGlobalSlots;
+ uint32 numStackSlots;
+ uint32 numStackSlotsBelowCurrentFrame;
+ ExitType exitType;
+};
+
+static inline uint8* getTypeMap(nanojit::SideExit* exit)
+{
+ return (uint8*)(((VMSideExit*)exit) + 1);
+}
+
+struct InterpState
+{
+ void* sp; /* native stack pointer, stack[0] is spbase[0] */
+ void* rp; /* call stack pointer */
+ void* gp; /* global frame pointer */
+ JSContext *cx; /* current VM context handle */
+ void* eos; /* first unusable word after the native stack */
+ void* eor; /* first unusable word after the call stack */
+ VMSideExit* lastTreeExitGuard; /* guard we exited on during a tree call */
+ VMSideExit* lastTreeCallGuard; /* guard we want to grow from if the tree
+ call exit guard mismatched */
+ void* rpAtLastTreeCall; /* value of rp at innermost tree call guard */
+};
+
+struct UnstableExit
+{
+ nanojit::Fragment* fragment;
+ VMSideExit* exit;
+ UnstableExit* next;
+};
+
+class TreeInfo MMGC_SUBCLASS_DECL {
+ nanojit::Fragment* fragment;
+public:
+ JSScript* script;
+ unsigned maxNativeStackSlots;
+ ptrdiff_t nativeStackBase;
+ unsigned maxCallDepth;
+ TypeMap stackTypeMap;
+ Queue<nanojit::Fragment*> dependentTrees;
+ unsigned branchCount;
+ Queue<VMSideExit*> sideExits;
+ UnstableExit* unstableExits;
+
+ TreeInfo(nanojit::Fragment* _fragment) : unstableExits(NULL) {
+ fragment = _fragment;
+ }
+ ~TreeInfo();
+};
+
+struct FrameInfo {
+ JSObject* callee; // callee function object
+ intptr_t ip_adj; // callee script-based pc index and imacro pc
+ uint8* typemap; // typemap for the stack frame
+ union {
+ struct {
+ uint16 spdist; // distance from fp->slots to fp->regs->sp at JSOP_CALL
+ uint16 argc; // actual argument count, may be < fun->nargs
+ } s;
+ uint32 word; // for spdist/argc LIR store in record_JSOP_CALL
+ };
+};
+
+class TraceRecorder : public avmplus::GCObject {
+ JSContext* cx;
+ JSTraceMonitor* traceMonitor;
+ JSObject* globalObj;
+ Tracker tracker;
+ Tracker nativeFrameTracker;
+ char* entryTypeMap;
+ unsigned callDepth;
+ JSAtom** atoms;
+ VMSideExit* anchor;
+ nanojit::Fragment* fragment;
+ TreeInfo* treeInfo;
+ nanojit::LirBuffer* lirbuf;
+ nanojit::LirWriter* lir;
+ nanojit::LirBufWriter* lir_buf_writer;
+ nanojit::LirWriter* verbose_filter;
+ nanojit::LirWriter* cse_filter;
+ nanojit::LirWriter* expr_filter;
+ nanojit::LirWriter* func_filter;
+#ifdef NJ_SOFTFLOAT
+ nanojit::LirWriter* float_filter;
+#endif
+ nanojit::LIns* cx_ins;
+ nanojit::LIns* gp_ins;
+ nanojit::LIns* eos_ins;
+ nanojit::LIns* eor_ins;
+ nanojit::LIns* rval_ins;
+ nanojit::LIns* inner_sp_ins;
+ bool deepAborted;
+ bool applyingArguments;
+ bool trashTree;
+ nanojit::Fragment* whichTreeToTrash;
+ Queue<jsbytecode*> cfgMerges;
+ jsval* global_dslots;
+ JSTraceableNative* pendingTraceableNative;
+ bool terminate;
+ intptr_t terminate_ip_adj;
+ nanojit::Fragment* outerToBlacklist;
+ nanojit::Fragment* promotedPeer;
+ TraceRecorder* nextRecorderToAbort;
+ bool wasRootFragment;
+
+ bool isGlobal(jsval* p) const;
+ ptrdiff_t nativeGlobalOffset(jsval* p) const;
+ ptrdiff_t nativeStackOffset(jsval* p) const;
+ void import(nanojit::LIns* base, ptrdiff_t offset, jsval* p, uint8& t,
+ const char *prefix, uintN index, JSStackFrame *fp);
+ void import(TreeInfo* treeInfo, nanojit::LIns* sp, unsigned ngslots, unsigned callDepth,
+ uint8* globalTypeMap, uint8* stackTypeMap);
+ void trackNativeStackUse(unsigned slots);
+
+ bool lazilyImportGlobalSlot(unsigned slot);
+
+ nanojit::LIns* guard(bool expected, nanojit::LIns* cond, ExitType exitType);
+ nanojit::LIns* guard(bool expected, nanojit::LIns* cond, nanojit::LIns* exit);
+ nanojit::LIns* addName(nanojit::LIns* ins, const char* name);
+
+ nanojit::LIns* get(jsval* p) const;
+ nanojit::LIns* writeBack(nanojit::LIns* i, nanojit::LIns* base, ptrdiff_t offset);
+ void set(jsval* p, nanojit::LIns* l, bool initializing = false);
+
+ bool checkType(jsval& v, uint8 t, jsval*& stage_val, nanojit::LIns*& stage_ins,
+ unsigned& stage_count);
+ bool deduceTypeStability(nanojit::Fragment* root_peer, nanojit::Fragment** stable_peer,
+ unsigned* demotes);
+
+ jsval& argval(unsigned n) const;
+ jsval& varval(unsigned n) const;
+ jsval& stackval(int n) const;
+
+ nanojit::LIns* scopeChain() const;
+ bool activeCallOrGlobalSlot(JSObject* obj, jsval*& vp);
+
+ nanojit::LIns* arg(unsigned n);
+ void arg(unsigned n, nanojit::LIns* i);
+ nanojit::LIns* var(unsigned n);
+ void var(unsigned n, nanojit::LIns* i);
+ nanojit::LIns* stack(int n);
+ void stack(int n, nanojit::LIns* i);
+
+ nanojit::LIns* alu(nanojit::LOpcode op, jsdouble v0, jsdouble v1,
+ nanojit::LIns* s0, nanojit::LIns* s1);
+ nanojit::LIns* f2i(nanojit::LIns* f);
+ nanojit::LIns* makeNumberInt32(nanojit::LIns* f);
+ nanojit::LIns* stringify(jsval& v);
+
+ bool call_imacro(jsbytecode* imacro);
+
+ bool ifop();
+ bool switchop();
+ bool inc(jsval& v, jsint incr, bool pre = true);
+ bool inc(jsval& v, nanojit::LIns*& v_ins, jsint incr, bool pre = true);
+ bool incProp(jsint incr, bool pre = true);
+ bool incElem(jsint incr, bool pre = true);
+ bool incName(jsint incr, bool pre = true);
+
+ enum { CMP_NEGATE = 1, CMP_TRY_BRANCH_AFTER_COND = 2, CMP_CASE = 4, CMP_STRICT = 8 };
+ bool cmp(nanojit::LOpcode op, int flags = 0);
+
+ bool unary(nanojit::LOpcode op);
+ bool binary(nanojit::LOpcode op);
+
+ bool ibinary(nanojit::LOpcode op);
+ bool iunary(nanojit::LOpcode op);
+ bool bbinary(nanojit::LOpcode op);
+ void demote(jsval& v, jsdouble result);
+
+ bool map_is_native(JSObjectMap* map, nanojit::LIns* map_ins, nanojit::LIns*& ops_ins,
+ size_t op_offset = 0);
+ bool test_property_cache(JSObject* obj, nanojit::LIns* obj_ins, JSObject*& obj2,
+ jsuword& pcval);
+ bool test_property_cache_direct_slot(JSObject* obj, nanojit::LIns* obj_ins, uint32& slot);
+ void stobj_set_slot(nanojit::LIns* obj_ins, unsigned slot,
+ nanojit::LIns*& dslots_ins, nanojit::LIns* v_ins);
+ nanojit::LIns* stobj_get_fslot(nanojit::LIns* obj_ins, unsigned slot);
+ nanojit::LIns* stobj_get_slot(nanojit::LIns* obj_ins, unsigned slot,
+ nanojit::LIns*& dslots_ins);
+ bool native_set(nanojit::LIns* obj_ins, JSScopeProperty* sprop,
+ nanojit::LIns*& dslots_ins, nanojit::LIns* v_ins);
+ bool native_get(nanojit::LIns* obj_ins, nanojit::LIns* pobj_ins, JSScopeProperty* sprop,
+ nanojit::LIns*& dslots_ins, nanojit::LIns*& v_ins);
+
+ bool name(jsval*& vp);
+ bool prop(JSObject* obj, nanojit::LIns* obj_ins, uint32& slot, nanojit::LIns*& v_ins);
+ bool elem(jsval& oval, jsval& idx, jsval*& vp, nanojit::LIns*& v_ins, nanojit::LIns*& addr_ins);
+
+ bool getProp(JSObject* obj, nanojit::LIns* obj_ins);
+ bool getProp(jsval& v);
+ bool getThis(nanojit::LIns*& this_ins);
+
+ bool box_jsval(jsval v, nanojit::LIns*& v_ins);
+ bool unbox_jsval(jsval v, nanojit::LIns*& v_ins);
+ bool guardClass(JSObject* obj, nanojit::LIns* obj_ins, JSClass* clasp,
+ ExitType exitType = MISMATCH_EXIT);
+ bool guardDenseArray(JSObject* obj, nanojit::LIns* obj_ins,
+ ExitType exitType = MISMATCH_EXIT);
+ bool guardDenseArrayIndex(JSObject* obj, jsint idx, nanojit::LIns* obj_ins,
+ nanojit::LIns* dslots_ins, nanojit::LIns* idx_ins,
+ ExitType exitType);
+ bool guardElemOp(JSObject* obj, nanojit::LIns* obj_ins, jsid id, size_t op_offset, jsval* vp);
+ void clearFrameSlotsFromCache();
+ bool guardShapelessCallee(jsval& callee);
+ bool interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc, bool constructing);
+ bool functionCall(bool constructing);
+
+ void trackCfgMerges(jsbytecode* pc);
+ void flipIf(jsbytecode* pc, bool& cond);
+ void fuseIf(jsbytecode* pc, bool cond, nanojit::LIns* x);
+
+ bool hasMethod(JSObject* obj, jsid id);
+ bool hasToStringMethod(JSObject* obj);
+ bool hasToStringMethod(jsval v) {
+ JS_ASSERT(JSVAL_IS_OBJECT(v));
+ return hasToStringMethod(JSVAL_TO_OBJECT(v));
+ }
+ bool hasValueOfMethod(JSObject* obj);
+ bool hasValueOfMethod(jsval v) {
+ JS_ASSERT(JSVAL_IS_OBJECT(v));
+ return hasValueOfMethod(JSVAL_TO_OBJECT(v));
+ }
+ bool hasIteratorMethod(JSObject* obj);
+ bool hasIteratorMethod(jsval v) {
+ JS_ASSERT(JSVAL_IS_OBJECT(v));
+ return hasIteratorMethod(JSVAL_TO_OBJECT(v));
+ }
+
+public:
+ friend bool js_MonitorRecording(TraceRecorder* tr);
+
+ TraceRecorder(JSContext* cx, VMSideExit*, nanojit::Fragment*, TreeInfo*,
+ unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap,
+ VMSideExit* expectedInnerExit, nanojit::Fragment* outerToBlacklist);
+ ~TraceRecorder();
+
+ uint8 determineSlotType(jsval* vp) const;
+ nanojit::LIns* snapshot(ExitType exitType);
+ nanojit::Fragment* getFragment() const { return fragment; }
+ bool isLoopHeader(JSContext* cx) const;
+ void compile(nanojit::Fragmento* fragmento);
+ bool closeLoop(nanojit::Fragmento* fragmento, bool& demote, unsigned *demotes);
+ void endLoop(nanojit::Fragmento* fragmento);
+ void joinEdgesToEntry(nanojit::Fragmento* fragmento, nanojit::Fragment* peer_root);
+ void blacklist() { fragment->blacklist(); }
+ bool adjustCallerTypes(nanojit::Fragment* f, unsigned* demote_slots, bool& trash);
+ nanojit::Fragment* findNestedCompatiblePeer(nanojit::Fragment* f, nanojit::Fragment** empty);
+ void prepareTreeCall(nanojit::Fragment* inner);
+ void emitTreeCall(nanojit::Fragment* inner, VMSideExit* exit);
+ unsigned getCallDepth() const;
+ void pushAbortStack();
+ void popAbortStack();
+ void removeFragmentoReferences();
+
+ bool record_EnterFrame();
+ bool record_LeaveFrame();
+ bool record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop);
+ bool record_SetPropMiss(JSPropCacheEntry* entry);
+ bool record_DefLocalFunSetSlot(uint32 slot, JSObject* obj);
+ bool record_FastNativeCallComplete();
+ bool record_IteratorNextComplete();
+
+ nanojit::Fragment* getOuterToBlacklist() { return outerToBlacklist; }
+ void deepAbort() { deepAborted = true; }
+ bool wasDeepAborted() { return deepAborted; }
+ bool walkedOutOfLoop() { return terminate; }
+ void setPromotedPeer(nanojit::Fragment* peer) { promotedPeer = peer; }
+ TreeInfo* getTreeInfo() { return treeInfo; }
+
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ bool record_##op();
+# include "jsopcode.tbl"
+#undef OPDEF
+};
+
+#define TRACING_ENABLED(cx) JS_HAS_OPTION(cx, JSOPTION_JIT)
+#define TRACE_RECORDER(cx) (JS_TRACE_MONITOR(cx).recorder)
+#define SET_TRACE_RECORDER(cx,tr) (JS_TRACE_MONITOR(cx).recorder = (tr))
+
+#define JSOP_IS_BINARY(op) ((uintN)((op) - JSOP_BITOR) <= (uintN)(JSOP_MOD - JSOP_BITOR))
+
+/*
+ * See jsinterp.cpp for the ENABLE_TRACER definition. Also note how comparing x
+ * to JSOP_* constants specializes trace-recording code at compile time either
+ * to include imacro support, or exclude it altogether for this particular x.
+ *
+ * We save macro-generated code size also via bool TraceRecorder::record_JSOP_*
+ * return type, instead of a three-state: OK, ABORTED, IMACRO_STARTED. But the
+ * price of this is the JSFRAME_IMACRO_START frame flag. We need one more bit
+ * to detect that TraceRecorder::call_imacro was invoked by the record_JSOP_*
+ * method invoked by TRACE_ARGS_.
+ */
+#define RECORD_ARGS(x,args) \
+ JS_BEGIN_MACRO \
+ if (!js_MonitorRecording(TRACE_RECORDER(cx))) { \
+ ENABLE_TRACER(0); \
+ } else { \
+ TRACE_ARGS_(x, args, \
+ if ((fp->flags & JSFRAME_IMACRO_START) && \
+ (x == JSOP_ITER || x == JSOP_NEXTITER || \
+ JSOP_IS_BINARY(x))) { \
+ fp->flags &= ~JSFRAME_IMACRO_START; \
+ atoms = COMMON_ATOMS_START(&rt->atomState); \
+ op = JSOp(*regs.pc); \
+ DO_OP(); \
+ } \
+ ); \
+ } \
+ JS_END_MACRO
+
+#define TRACE_ARGS_(x,args,onfalse) \
+ JS_BEGIN_MACRO \
+ TraceRecorder* tr_ = TRACE_RECORDER(cx); \
+ if (tr_ && !tr_->record_##x args) { \
+ onfalse \
+ js_AbortRecording(cx, #x); \
+ ENABLE_TRACER(0); \
+ } \
+ JS_END_MACRO
+
+#define TRACE_ARGS(x,args) TRACE_ARGS_(x, args, )
+
+#define RECORD(x) RECORD_ARGS(x, ())
+#define TRACE_0(x) TRACE_ARGS(x, ())
+#define TRACE_1(x,a) TRACE_ARGS(x, (a))
+#define TRACE_2(x,a,b) TRACE_ARGS(x, (a, b))
+
+extern bool
+js_MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount);
+
+extern bool
+js_MonitorRecording(TraceRecorder *tr);
+
+extern void
+js_AbortRecording(JSContext* cx, const char* reason);
+
+extern void
+js_InitJIT(JSTraceMonitor *tm);
+
+extern void
+js_FinishJIT(JSTraceMonitor *tm);
+
+extern void
+js_FlushJITCache(JSContext* cx);
+
+extern void
+js_FlushJITOracle(JSContext* cx);
+
+#else /* !JS_TRACER */
+
+#define RECORD(x) ((void)0)
+#define TRACE_0(x) ((void)0)
+#define TRACE_1(x,a) ((void)0)
+#define TRACE_2(x,a,b) ((void)0)
+
+#endif /* !JS_TRACER */
+
+#endif /* jstracer_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jstypes.h b/tools/node_modules/expresso/deps/jscoverage/js/jstypes.h
new file mode 100644
index 0000000..bf09bfe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jstypes.h
@@ -0,0 +1,490 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+** File: jstypes.h
+** Description: Definitions of NSPR's basic types
+**
+** Prototypes and macros used to make up for deficiencies in ANSI environments
+** that we have found.
+**
+** Since we do not wrap <stdlib.h> and all the other standard headers, authors
+** of portable code will not know in general that they need these definitions.
+** Instead of requiring these authors to find the dependent uses in their code
+** and take the following steps only in those C files, we take steps once here
+** for all C files.
+**/
+
+#ifndef jstypes_h___
+#define jstypes_h___
+
+#include <stddef.h>
+
+/***********************************************************************
+** MACROS: JS_EXTERN_API
+** JS_EXPORT_API
+** DESCRIPTION:
+** These are only for externally visible routines and globals. For
+** internal routines, just use "extern" for type checking and that
+** will not export internal cross-file or forward-declared symbols.
+** Define a macro for declaring procedures return types. We use this to
+** deal with windoze specific type hackery for DLL definitions. Use
+** JS_EXTERN_API when the prototype for the method is declared. Use
+** JS_EXPORT_API for the implementation of the method.
+**
+** Example:
+** in dowhim.h
+** JS_EXTERN_API( void ) DoWhatIMean( void );
+** in dowhim.c
+** JS_EXPORT_API( void ) DoWhatIMean( void ) { return; }
+**
+**
+***********************************************************************/
+#ifdef WIN32
+
+/* These also work for __MWERKS__ */
+# define JS_EXTERN_API(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_API(__type) __declspec(dllexport) __type
+# define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_DATA(__type) __declspec(dllexport) __type
+
+#elif defined(XP_OS2) && defined(__declspec)
+
+# define JS_EXTERN_API(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_API(__type) __declspec(dllexport) __type
+# define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_DATA(__type) __declspec(dllexport) __type
+
+#else /* Unix */
+
+# ifdef HAVE_VISIBILITY_ATTRIBUTE
+# define JS_EXTERNAL_VIS __attribute__((visibility ("default")))
+# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+# define JS_EXTERNAL_VIS __global
+# else
+# define JS_EXTERNAL_VIS
+# endif
+
+# define JS_EXTERN_API(__type) extern JS_EXTERNAL_VIS __type
+# define JS_EXPORT_API(__type) JS_EXTERNAL_VIS __type
+# define JS_EXTERN_DATA(__type) extern JS_EXTERNAL_VIS __type
+# define JS_EXPORT_DATA(__type) JS_EXTERNAL_VIS __type
+
+#endif
+
+#ifdef _WIN32
+# if defined(__MWERKS__) || defined(__GNUC__)
+# define JS_IMPORT_API(__x) __x
+# else
+# define JS_IMPORT_API(__x) __declspec(dllimport) __x
+# endif
+#elif defined(XP_OS2) && defined(__declspec)
+# define JS_IMPORT_API(__x) __declspec(dllimport) __x
+#else
+# define JS_IMPORT_API(__x) JS_EXPORT_API (__x)
+#endif
+
+#if defined(_WIN32) && !defined(__MWERKS__)
+# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
+#elif defined(XP_OS2) && defined(__declspec)
+# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
+#else
+# define JS_IMPORT_DATA(__x) JS_EXPORT_DATA (__x)
+#endif
+
+/*
+ * The linkage of JS API functions differs depending on whether the file is
+ * used within the JS library or not. Any source file within the JS
+ * interpreter should define EXPORT_JS_API whereas any client of the library
+ * should not. STATIC_JS_API is used to build JS as a static library.
+ */
+#if defined(STATIC_JS_API)
+
+# define JS_PUBLIC_API(t) t
+# define JS_PUBLIC_DATA(t) t
+
+#elif defined(EXPORT_JS_API)
+
+# define JS_PUBLIC_API(t) JS_EXPORT_API(t)
+# define JS_PUBLIC_DATA(t) JS_EXPORT_DATA(t)
+
+#else
+
+# define JS_PUBLIC_API(t) JS_IMPORT_API(t)
+# define JS_PUBLIC_DATA(t) JS_IMPORT_DATA(t)
+
+#endif
+
+#define JS_FRIEND_API(t) JS_PUBLIC_API(t)
+#define JS_FRIEND_DATA(t) JS_PUBLIC_DATA(t)
+
+#if defined(_MSC_VER) && defined(_M_IX86)
+#define JS_FASTCALL __fastcall
+#elif defined(__GNUC__) && defined(__i386__) && \
+ ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+#define JS_FASTCALL __attribute__((fastcall))
+#else
+#define JS_FASTCALL
+#define JS_NO_FASTCALL
+#endif
+
+#ifndef JS_INLINE
+# if defined __cplusplus
+# define JS_INLINE inline
+# elif defined _MSC_VER
+# define JS_INLINE __inline
+# elif defined __GNUC__
+# define JS_INLINE __inline__
+# else
+# define JS_INLINE inline
+# endif
+#endif
+
+#ifndef JS_ALWAYS_INLINE
+# if defined DEBUG
+# define JS_ALWAYS_INLINE JS_INLINE
+# elif defined _MSC_VER
+# define JS_ALWAYS_INLINE __forceinline
+# elif defined __GNUC__
+# define JS_ALWAYS_INLINE __attribute__((always_inline))
+# else
+# define JS_ALWAYS_INLINE JS_INLINE
+# endif
+#endif
+
+/***********************************************************************
+** MACROS: JS_BEGIN_MACRO
+** JS_END_MACRO
+** DESCRIPTION:
+** Macro body brackets so that macros with compound statement definitions
+** behave syntactically more like functions when called.
+***********************************************************************/
+#define JS_BEGIN_MACRO do {
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+# define JS_END_MACRO \
+ } __pragma(warning(push)) __pragma(warning(disable:4127)) \
+ while (0) __pragma(warning(pop))
+#else
+# define JS_END_MACRO } while (0)
+#endif
+
+/***********************************************************************
+** MACROS: JS_BEGIN_EXTERN_C
+** JS_END_EXTERN_C
+** DESCRIPTION:
+** Macro shorthands for conditional C++ extern block delimiters.
+***********************************************************************/
+#ifdef __cplusplus
+
+# define JS_BEGIN_EXTERN_C extern "C" {
+# define JS_END_EXTERN_C }
+
+#else
+
+# define JS_BEGIN_EXTERN_C
+# define JS_END_EXTERN_C
+
+#endif
+
+/***********************************************************************
+** MACROS: JS_BIT
+** JS_BITMASK
+** DESCRIPTION:
+** Bit masking macros. XXX n must be <= 31 to be portable
+***********************************************************************/
+#define JS_BIT(n) ((JSUint32)1 << (n))
+#define JS_BITMASK(n) (JS_BIT(n) - 1)
+
+/***********************************************************************
+** MACROS: JS_PTR_TO_INT32
+** JS_PTR_TO_UINT32
+** JS_INT32_TO_PTR
+** JS_UINT32_TO_PTR
+** DESCRIPTION:
+** Integer to pointer and pointer to integer conversion macros.
+***********************************************************************/
+#define JS_PTR_TO_INT32(x) ((jsint)((char *)(x) - (char *)0))
+#define JS_PTR_TO_UINT32(x) ((jsuint)((char *)(x) - (char *)0))
+#define JS_INT32_TO_PTR(x) ((void *)((char *)0 + (jsint)(x)))
+#define JS_UINT32_TO_PTR(x) ((void *)((char *)0 + (jsuint)(x)))
+
+/***********************************************************************
+** MACROS: JS_HOWMANY
+** JS_ROUNDUP
+** JS_MIN
+** JS_MAX
+** DESCRIPTION:
+** Commonly used macros for operations on compatible types.
+***********************************************************************/
+#define JS_HOWMANY(x,y) (((x)+(y)-1)/(y))
+#define JS_ROUNDUP(x,y) (JS_HOWMANY(x,y)*(y))
+#define JS_MIN(x,y) ((x)<(y)?(x):(y))
+#define JS_MAX(x,y) ((x)>(y)?(x):(y))
+
+#if (defined(XP_WIN) && !defined(CROSS_COMPILE)) || defined (WINCE)
+# include "jscpucfg.h" /* Use standard Mac or Windows configuration */
+#elif defined(XP_UNIX) || defined(XP_BEOS) || defined(XP_OS2) || defined(CROSS_COMPILE)
+# include "jsautocfg.h" /* Use auto-detected configuration */
+#else
+# error "Must define one of XP_BEOS, XP_OS2, XP_WIN or XP_UNIX"
+#endif
+
+JS_BEGIN_EXTERN_C
+
+/************************************************************************
+** TYPES: JSUint8
+** JSInt8
+** DESCRIPTION:
+** The int8 types are known to be 8 bits each. There is no type that
+** is equivalent to a plain "char".
+************************************************************************/
+#if JS_BYTES_PER_BYTE == 1
+typedef unsigned char JSUint8;
+typedef signed char JSInt8;
+#else
+# error No suitable type for JSInt8/JSUint8
+#endif
+
+/************************************************************************
+** TYPES: JSUint16
+** JSInt16
+** DESCRIPTION:
+** The int16 types are known to be 16 bits each.
+************************************************************************/
+#if JS_BYTES_PER_SHORT == 2
+typedef unsigned short JSUint16;
+typedef short JSInt16;
+#else
+# error No suitable type for JSInt16/JSUint16
+#endif
+
+/************************************************************************
+** TYPES: JSUint32
+** JSInt32
+** DESCRIPTION:
+** The int32 types are known to be 32 bits each.
+************************************************************************/
+#if JS_BYTES_PER_INT == 4
+typedef unsigned int JSUint32;
+typedef int JSInt32;
+# define JS_INT32(x) x
+# define JS_UINT32(x) x ## U
+#elif JS_BYTES_PER_LONG == 4
+typedef unsigned long JSUint32;
+typedef long JSInt32;
+# define JS_INT32(x) x ## L
+# define JS_UINT32(x) x ## UL
+#else
+# error No suitable type for JSInt32/JSUint32
+#endif
+
+/************************************************************************
+** TYPES: JSUint64
+** JSInt64
+** DESCRIPTION:
+** The int64 types are known to be 64 bits each. Care must be used when
+** declaring variables of type JSUint64 or JSInt64. Different hardware
+** architectures and even different compilers have varying support for
+** 64 bit values. The only guaranteed portability requires the use of
+** the JSLL_ macros (see jslong.h).
+************************************************************************/
+#ifdef JS_HAVE_LONG_LONG
+
+# if JS_BYTES_PER_LONG == 8
+typedef long JSInt64;
+typedef unsigned long JSUint64;
+# elif defined(WIN16)
+typedef __int64 JSInt64;
+typedef unsigned __int64 JSUint64;
+# elif defined(WIN32) && !defined(__GNUC__)
+typedef __int64 JSInt64;
+typedef unsigned __int64 JSUint64;
+# else
+typedef long long JSInt64;
+typedef unsigned long long JSUint64;
+# endif /* JS_BYTES_PER_LONG == 8 */
+
+#else /* !JS_HAVE_LONG_LONG */
+
+typedef struct {
+# ifdef IS_LITTLE_ENDIAN
+ JSUint32 lo, hi;
+# else
+ JSUint32 hi, lo;
+#endif
+} JSInt64;
+typedef JSInt64 JSUint64;
+
+#endif /* !JS_HAVE_LONG_LONG */
+
+/************************************************************************
+** TYPES: JSUintn
+** JSIntn
+** DESCRIPTION:
+** The JSIntn types are most appropriate for automatic variables. They are
+** guaranteed to be at least 16 bits, though various architectures may
+** define them to be wider (e.g., 32 or even 64 bits). These types are
+** never valid for fields of a structure.
+************************************************************************/
+#if JS_BYTES_PER_INT >= 2
+typedef int JSIntn;
+typedef unsigned int JSUintn;
+#else
+# error 'sizeof(int)' not sufficient for platform use
+#endif
+
+/************************************************************************
+** TYPES: JSFloat64
+** DESCRIPTION:
+** NSPR's floating point type is always 64 bits.
+************************************************************************/
+typedef double JSFloat64;
+
+/************************************************************************
+** TYPES: JSSize
+** DESCRIPTION:
+** A type for representing the size of objects.
+************************************************************************/
+typedef size_t JSSize;
+
+/************************************************************************
+** TYPES: JSPtrDiff
+** DESCRIPTION:
+** A type for pointer difference. Variables of this type are suitable
+** for storing a pointer or pointer sutraction.
+************************************************************************/
+typedef ptrdiff_t JSPtrdiff;
+
+/************************************************************************
+** TYPES: JSUptrdiff
+** DESCRIPTION:
+** A type for pointer difference. Variables of this type are suitable
+** for storing a pointer or pointer sutraction.
+************************************************************************/
+#if JS_BYTES_PER_WORD == 8 && JS_BYTES_PER_LONG != 8
+typedef JSUint64 JSUptrdiff;
+#else
+typedef unsigned long JSUptrdiff;
+#endif
+
+/************************************************************************
+** TYPES: JSBool
+** DESCRIPTION:
+** Use JSBool for variables and parameter types. Use JS_FALSE and JS_TRUE
+** for clarity of target type in assignments and actual arguments. Use
+** 'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans
+** just as you would C int-valued conditions.
+************************************************************************/
+typedef JSIntn JSBool;
+#define JS_TRUE (JSIntn)1
+#define JS_FALSE (JSIntn)0
+
+/************************************************************************
+** TYPES: JSPackedBool
+** DESCRIPTION:
+** Use JSPackedBool within structs where bitfields are not desireable
+** but minimum and consistent overhead matters.
+************************************************************************/
+typedef JSUint8 JSPackedBool;
+
+/*
+** A JSWord is an integer that is the same size as a void*
+*/
+#if JS_BYTES_PER_WORD == 8 && JS_BYTES_PER_LONG != 8
+typedef JSInt64 JSWord;
+typedef JSUint64 JSUword;
+#else
+typedef long JSWord;
+typedef unsigned long JSUword;
+#endif
+
+#include "jsotypes.h"
+
+/***********************************************************************
+** MACROS: JS_LIKELY
+** JS_UNLIKELY
+** DESCRIPTION:
+** These macros allow you to give a hint to the compiler about branch
+** probability so that it can better optimize. Use them like this:
+**
+** if (JS_LIKELY(v == 1)) {
+** ... expected code path ...
+** }
+**
+** if (JS_UNLIKELY(v == 0)) {
+** ... non-expected code path ...
+** }
+**
+***********************************************************************/
+#if defined(__GNUC__) && (__GNUC__ > 2)
+
+# define JS_LIKELY(x) (__builtin_expect((x), 1))
+# define JS_UNLIKELY(x) (__builtin_expect((x), 0))
+
+#else
+
+# define JS_LIKELY(x) (x)
+# define JS_UNLIKELY(x) (x)
+
+#endif
+
+/***********************************************************************
+** MACROS: JS_ARRAY_LENGTH
+** JS_ARRAY_END
+** DESCRIPTION:
+** Macros to get the number of elements and the pointer to one past the
+** last element of a C array. Use them like this:
+**
+** jschar buf[10], *s;
+** JSString *str;
+** ...
+** for (s = buf; s != JS_ARRAY_END(buf); ++s) *s = ...;
+** ...
+** str = JS_NewStringCopyN(cx, buf, JS_ARRAY_LENGTH(buf));
+** ...
+**
+***********************************************************************/
+
+#define JS_ARRAY_LENGTH(array) (sizeof (array) / sizeof (array)[0])
+#define JS_ARRAY_END(array) ((array) + JS_ARRAY_LENGTH(array))
+
+JS_END_EXTERN_C
+
+#endif /* jstypes_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsutil.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsutil.cpp
new file mode 100644
index 0000000..5d7eb88
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsutil.cpp
@@ -0,0 +1,345 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * PR assertion checker.
+ */
+#include "jsstddef.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "jstypes.h"
+#include "jsutil.h"
+
+#ifdef WIN32
+# include <windows.h>
+#endif
+
+JS_PUBLIC_API(void) JS_Assert(const char *s, const char *file, JSIntn ln)
+{
+ fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
+#if defined(WIN32)
+ DebugBreak();
+ exit(3);
+#elif defined(XP_OS2) || (defined(__GNUC__) && defined(__i386))
+ asm("int $3");
+#endif
+ abort();
+}
+
+#ifdef JS_BASIC_STATS
+
+#include <math.h>
+#include <string.h>
+#include "jscompat.h"
+#include "jsbit.h"
+
+/*
+ * Histogram bins count occurrences of values <= the bin label, as follows:
+ *
+ * linear: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or more
+ * 2**x: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 or more
+ * 10**x: 0, 1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 or more
+ *
+ * We wish to count occurrences of 0 and 1 values separately, always.
+ */
+static uint32
+BinToVal(uintN logscale, uintN bin)
+{
+ JS_ASSERT(bin <= 10);
+ if (bin <= 1 || logscale == 0)
+ return bin;
+ --bin;
+ if (logscale == 2)
+ return JS_BIT(bin);
+ JS_ASSERT(logscale == 10);
+ return (uint32) pow(10.0, (double) bin);
+}
+
+static uintN
+ValToBin(uintN logscale, uint32 val)
+{
+ uintN bin;
+
+ if (val <= 1)
+ return val;
+ bin = (logscale == 10)
+ ? (uintN) ceil(log10((double) val))
+ : (logscale == 2)
+ ? (uintN) JS_CeilingLog2(val)
+ : val;
+ return JS_MIN(bin, 10);
+}
+
+void
+JS_BasicStatsAccum(JSBasicStats *bs, uint32 val)
+{
+ uintN oldscale, newscale, bin;
+ double mean;
+
+ ++bs->num;
+ if (bs->max < val)
+ bs->max = val;
+ bs->sum += val;
+ bs->sqsum += (double)val * val;
+
+ oldscale = bs->logscale;
+ if (oldscale != 10) {
+ mean = bs->sum / bs->num;
+ if (bs->max > 16 && mean > 8) {
+ newscale = (bs->max > 1e6 && mean > 1000) ? 10 : 2;
+ if (newscale != oldscale) {
+ uint32 newhist[11], newbin;
+
+ memset(newhist, 0, sizeof newhist);
+ for (bin = 0; bin <= 10; bin++) {
+ newbin = ValToBin(newscale, BinToVal(oldscale, bin));
+ newhist[newbin] += bs->hist[bin];
+ }
+ memcpy(bs->hist, newhist, sizeof bs->hist);
+ bs->logscale = newscale;
+ }
+ }
+ }
+
+ bin = ValToBin(bs->logscale, val);
+ ++bs->hist[bin];
+}
+
+double
+JS_MeanAndStdDev(uint32 num, double sum, double sqsum, double *sigma)
+{
+ double var;
+
+ if (num == 0 || sum == 0) {
+ *sigma = 0;
+ return 0;
+ }
+
+ var = num * sqsum - sum * sum;
+ if (var < 0 || num == 1)
+ var = 0;
+ else
+ var /= (double)num * (num - 1);
+
+ /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */
+ *sigma = (var != 0) ? sqrt(var) : 0;
+ return sum / num;
+}
+
+void
+JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp)
+{
+ double mean, sigma;
+
+ mean = JS_MeanAndStdDevBS(bs, &sigma);
+ fprintf(fp, "\nmean %s %g, std. deviation %g, max %lu\n",
+ title, mean, sigma, (unsigned long) bs->max);
+ JS_DumpHistogram(bs, fp);
+}
+
+void
+JS_DumpHistogram(JSBasicStats *bs, FILE *fp)
+{
+ uintN bin;
+ uint32 cnt, max, prev, val, i;
+ double sum, mean;
+
+ for (bin = 0, max = 0, sum = 0; bin <= 10; bin++) {
+ cnt = bs->hist[bin];
+ if (max < cnt)
+ max = cnt;
+ sum += cnt;
+ }
+ mean = sum / cnt;
+ for (bin = 0, prev = 0; bin <= 10; bin++, prev = val) {
+ val = BinToVal(bs->logscale, bin);
+ cnt = bs->hist[bin];
+ if (prev + 1 >= val)
+ fprintf(fp, " [%6u]", val);
+ else
+ fprintf(fp, "[%6u, %6u]", prev + 1, val);
+ fprintf(fp, "%s %8u ", (bin == 10) ? "+" : ":", cnt);
+ if (cnt != 0) {
+ if (max > 1e6 && mean > 1e3)
+ cnt = (uint32) ceil(log10((double) cnt));
+ else if (max > 16 && mean > 8)
+ cnt = JS_CeilingLog2(cnt);
+ for (i = 0; i < cnt; i++)
+ putc('*', fp);
+ }
+ putc('\n', fp);
+ }
+}
+
+#endif /* JS_BASIC_STATS */
+
+#if defined DEBUG_notme && defined XP_UNIX
+
+#define __USE_GNU 1
+#include <dlfcn.h>
+#include <string.h>
+#include "jshash.h"
+#include "jsprf.h"
+
+JSCallsite js_calltree_root = {0, NULL, NULL, 0, NULL, NULL, NULL, NULL};
+
+static JSCallsite *
+CallTree(void **bp)
+{
+ void **bpup, **bpdown, *pc;
+ JSCallsite *parent, *site, **csp;
+ Dl_info info;
+ int ok, offset;
+ const char *symbol;
+ char *method;
+
+ /* Reverse the stack frame list to avoid recursion. */
+ bpup = NULL;
+ for (;;) {
+ bpdown = (void**) bp[0];
+ bp[0] = (void*) bpup;
+ if ((void**) bpdown[0] < bpdown)
+ break;
+ bpup = bp;
+ bp = bpdown;
+ }
+
+ /* Reverse the stack again, finding and building a path in the tree. */
+ parent = &js_calltree_root;
+ do {
+ bpup = (void**) bp[0];
+ bp[0] = (void*) bpdown;
+ pc = bp[1];
+
+ csp = &parent->kids;
+ while ((site = *csp) != NULL) {
+ if (site->pc == (uint32)pc) {
+ /* Put the most recently used site at the front of siblings. */
+ *csp = site->siblings;
+ site->siblings = parent->kids;
+ parent->kids = site;
+
+ /* Site already built -- go up the stack. */
+ goto upward;
+ }
+ csp = &site->siblings;
+ }
+
+ /* Check for recursion: see if pc is on our ancestor line. */
+ for (site = parent; site; site = site->parent) {
+ if (site->pc == (uint32)pc)
+ goto upward;
+ }
+
+ /*
+ * Not in tree at all: let's find our symbolic callsite info.
+ * XXX static syms are masked by nearest lower global
+ */
+ info.dli_fname = info.dli_sname = NULL;
+ ok = dladdr(pc, &info);
+ if (ok < 0) {
+ fprintf(stderr, "dladdr failed!\n");
+ return NULL;
+ }
+
+/* XXXbe sub 0x08040000? or something, see dbaron bug with tenthumbs comment */
+ symbol = info.dli_sname;
+ offset = (char*)pc - (char*)info.dli_fbase;
+ method = symbol
+ ? strdup(symbol)
+ : JS_smprintf("%s+%X",
+ info.dli_fname ? info.dli_fname : "main",
+ offset);
+ if (!method)
+ return NULL;
+
+ /* Create a new callsite record. */
+ site = (JSCallsite *) malloc(sizeof(JSCallsite));
+ if (!site)
+ return NULL;
+
+ /* Insert the new site into the tree. */
+ site->pc = (uint32)pc;
+ site->name = method;
+ site->library = info.dli_fname;
+ site->offset = offset;
+ site->parent = parent;
+ site->siblings = parent->kids;
+ parent->kids = site;
+ site->kids = NULL;
+
+ upward:
+ parent = site;
+ bpdown = bp;
+ bp = bpup;
+ } while (bp);
+
+ return site;
+}
+
+JSCallsite *
+JS_Backtrace(int skip)
+{
+ void **bp, **bpdown;
+
+ /* Stack walking code adapted from Kipp's "leaky". */
+#if defined(__i386)
+ __asm__( "movl %%ebp, %0" : "=g"(bp));
+#elif defined(__x86_64__)
+ __asm__( "movq %%rbp, %0" : "=g"(bp));
+#else
+ /*
+ * It would be nice if this worked uniformly, but at least on i386 and
+ * x86_64, it stopped working with gcc 4.1, because it points to the
+ * end of the saved registers instead of the start.
+ */
+ bp = (void**) __builtin_frame_address(0);
+#endif
+ while (--skip >= 0) {
+ bpdown = (void**) *bp++;
+ if (bpdown < bp)
+ break;
+ bp = bpdown;
+ }
+
+ return CallTree(bp);
+}
+
+#endif /* DEBUG_notme && XP_UNIX */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsutil.h b/tools/node_modules/expresso/deps/jscoverage/js/jsutil.h
new file mode 100644
index 0000000..a6c329c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsutil.h
@@ -0,0 +1,168 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * PR assertion checker.
+ */
+
+#ifndef jsutil_h___
+#define jsutil_h___
+
+JS_BEGIN_EXTERN_C
+
+#ifdef DEBUG
+
+extern JS_PUBLIC_API(void)
+JS_Assert(const char *s, const char *file, JSIntn ln);
+
+#define JS_ASSERT(expr) \
+ ((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
+
+#define JS_ASSERT_IF(cond, expr) \
+ ((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
+
+#define JS_NOT_REACHED(reason) \
+ JS_Assert(reason, __FILE__, __LINE__)
+
+#else
+
+#define JS_ASSERT(expr) ((void) 0)
+#define JS_ASSERT_IF(cond,expr) ((void) 0)
+#define JS_NOT_REACHED(reason)
+
+#endif /* defined(DEBUG) */
+
+/*
+ * Compile-time assert. "condition" must be a constant expression.
+ * The macro can be used only in places where an "extern" declaration is
+ * allowed.
+ */
+
+/*
+ * Sun Studio C++ compiler has a bug
+ * "sizeof expression not accepted as size of array parameter"
+ * The bug number is 6688515. It is not public yet.
+ * Turn off this assert for Sun Studio until this bug is fixed.
+ */
+#ifdef __SUNPRO_CC
+#define JS_STATIC_ASSERT(condition)
+#else
+#define JS_STATIC_ASSERT(condition) \
+ extern void js_static_assert(int arg[(condition) ? 1 : -1])
+#endif
+
+/*
+ * Abort the process in a non-graceful manner. This will cause a core file,
+ * call to the debugger or other moral equivalent as well as causing the
+ * entire process to stop.
+ */
+extern JS_PUBLIC_API(void) JS_Abort(void);
+
+#if 0
+# define JS_BASIC_STATS 1
+# define JS_SCOPE_DEPTH_METER 1
+#endif
+
+#if defined DEBUG && !defined JS_BASIC_STATS
+# define JS_BASIC_STATS 1
+#endif
+
+#ifdef JS_BASIC_STATS
+
+#include <stdio.h>
+
+typedef struct JSBasicStats {
+ uint32 num;
+ uint32 max;
+ double sum;
+ double sqsum;
+ uint32 logscale; /* logarithmic scale: 0 (linear), 2, 10 */
+ uint32 hist[11];
+} JSBasicStats;
+
+#define JS_INIT_STATIC_BASIC_STATS {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}}
+#define JS_BASIC_STATS_INIT(bs) memset((bs), 0, sizeof(JSBasicStats))
+
+#define JS_BASIC_STATS_ACCUM(bs,val) \
+ JS_BasicStatsAccum(bs, val)
+
+#define JS_MeanAndStdDevBS(bs,sigma) \
+ JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma)
+
+extern void
+JS_BasicStatsAccum(JSBasicStats *bs, uint32 val);
+
+extern double
+JS_MeanAndStdDev(uint32 num, double sum, double sqsum, double *sigma);
+
+extern void
+JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp);
+
+extern void
+JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
+
+#else
+
+#define JS_BASIC_STATS_ACCUM(bs,val) /* nothing */
+
+#endif /* JS_BASIC_STATS */
+
+
+#ifdef XP_UNIX
+
+typedef struct JSCallsite JSCallsite;
+
+struct JSCallsite {
+ uint32 pc;
+ char *name;
+ const char *library;
+ int offset;
+ JSCallsite *parent;
+ JSCallsite *siblings;
+ JSCallsite *kids;
+ void *handy;
+};
+
+extern JSCallsite *JS_Backtrace(int skip);
+
+#endif
+
+JS_END_EXTERN_C
+
+#endif /* jsutil_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsversion.h b/tools/node_modules/expresso/deps/jscoverage/js/jsversion.h
new file mode 100644
index 0000000..b16953b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsversion.h
@@ -0,0 +1,243 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS configuration macros.
+ */
+#ifndef JS_VERSION
+#define JS_VERSION 180
+#endif
+
+/*
+ * Compile-time JS version configuration. The JS version numbers lie on the
+ * number line like so:
+ *
+ * 1.0 1.1 1.2 1.3 1.4 ECMAv3 1.5 1.6 1.7 1.8
+ * ^ ^
+ * | |
+ * basis for ECMAv1 close to ECMAv2
+ *
+ * where ECMAv3 stands for ECMA-262 Edition 3. See the runtime version enum
+ * JSVersion in jspubtd.h. Code in the engine can therefore count on version
+ * <= JSVERSION_1_4 to mean "before the Third Edition of ECMA-262" and version
+ * > JSVERSION_1_4 to mean "at or after the Third Edition".
+ *
+ * In the (likely?) event that SpiderMonkey grows to implement JavaScript 2.0,
+ * or ECMA-262 Edition 4 (JS2 without certain extensions), the version number
+ * to use would be near 200, or greater.
+ *
+ * The JS_VERSION_ECMA_3 version is the minimal configuration conforming to
+ * the ECMA-262 Edition 3 specification. Use it for minimal embeddings, where
+ * you're sure you don't need any of the extensions disabled in this version.
+ * In order to facilitate testing, JS_HAS_OBJ_PROTO_PROP is defined as part of
+ * the JS_VERSION_ECMA_3_TEST version.
+ *
+ * To keep things sane in the modern age, where we need exceptions in order to
+ * implement, e.g., iterators and generators, we are dropping support for all
+ * versions <= 1.4.
+ */
+#define JS_VERSION_ECMA_3 148
+#define JS_VERSION_ECMA_3_TEST 149
+
+#if JS_VERSION == JS_VERSION_ECMA_3 || \
+ JS_VERSION == JS_VERSION_ECMA_3_TEST
+
+#define JS_HAS_STR_HTML_HELPERS 0 /* has str.anchor, str.bold, etc. */
+#define JS_HAS_PERL_SUBSTR 0 /* has str.substr */
+#if JS_VERSION == JS_VERSION_ECMA_3_TEST
+#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
+#else
+#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */
+#endif
+#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */
+#define JS_HAS_EVAL_THIS_SCOPE 0 /* Math.eval is same as with (Math) */
+#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */
+#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
+#define JS_HAS_XDR 0 /* has XDR API and internal support */
+#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */
+#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
+#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
+#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */
+#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
+#define JS_HAS_GETTER_SETTER 0 /* has JS2 getter/setter functions */
+#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */
+#define JS_HAS_CONST 0 /* has JS2 const as alternative var */
+#define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */
+#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */
+#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */
+#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */
+#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */
+#define JS_HAS_GENERATORS 0 /* has yield in generator function */
+#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
+#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
+#define JS_HAS_GENERATOR_EXPRS 0 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_EXPR_CLOSURES 0 /* has function (formals) listexpr */
+
+#elif JS_VERSION < 150
+
+#error "unsupported JS_VERSION"
+
+#elif JS_VERSION == 150
+
+#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
+#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
+#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
+#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
+#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
+#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
+#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */
+#define JS_HAS_XDR 1 /* has XDR API and internal support */
+#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */
+#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
+#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
+#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
+#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
+#define JS_HAS_GETTER_SETTER 1 /* has JS2 getter/setter functions */
+#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
+#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
+#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
+#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */
+#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
+#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */
+#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */
+#define JS_HAS_GENERATORS 0 /* has yield in generator function */
+#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
+#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
+#define JS_HAS_GENERATOR_EXPRS 0 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_EXPR_CLOSURES 0 /* has function (formals) listexpr */
+
+#elif JS_VERSION == 160
+
+#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
+#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
+#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
+#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
+#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
+#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
+#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */
+#define JS_HAS_XDR 1 /* has XDR API and internal support */
+#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */
+#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
+#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
+#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
+#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
+#define JS_HAS_GETTER_SETTER 1 /* has JS2 getter/setter functions */
+#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
+#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
+#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
+#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */
+#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
+#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
+#define JS_HAS_ARRAY_EXTRAS 1 /* has indexOf and Lispy extras */
+#define JS_HAS_GENERATORS 0 /* has yield in generator function */
+#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
+#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
+#define JS_HAS_GENERATOR_EXPRS 0 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_EXPR_CLOSURES 0 /* has function (formals) listexpr */
+
+#elif JS_VERSION == 170
+
+#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
+#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
+#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
+#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
+#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
+#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
+#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
+#define JS_HAS_XDR 1 /* has XDR API and internal support */
+#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */
+#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
+#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
+#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
+#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
+#define JS_HAS_GETTER_SETTER 1 /* has JS2 getter/setter functions */
+#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
+#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
+#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
+#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */
+#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
+#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
+#define JS_HAS_ARRAY_EXTRAS 1 /* has indexOf and Lispy extras */
+#define JS_HAS_GENERATORS 1 /* has yield in generator function */
+#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
+#define JS_HAS_DESTRUCTURING 1 /* has [a,b] = ... or {p:a,q:b} = ... */
+#define JS_HAS_GENERATOR_EXPRS 0 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_EXPR_CLOSURES 0 /* has function (formals) listexpr */
+
+#elif JS_VERSION == 180
+
+#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
+#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
+#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
+#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
+#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
+#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
+#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
+#define JS_HAS_XDR 1 /* has XDR API and internal support */
+#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */
+#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
+#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
+#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
+#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
+#define JS_HAS_GETTER_SETTER 1 /* has JS2 getter/setter functions */
+#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
+#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
+#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
+#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */
+#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
+#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
+#define JS_HAS_ARRAY_EXTRAS 1 /* has indexOf and Lispy extras */
+#define JS_HAS_GENERATORS 1 /* has yield in generator function */
+#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
+#define JS_HAS_DESTRUCTURING 2 /* has [a,b] = ... or {p:a,q:b} = ... */
+#define JS_HAS_GENERATOR_EXPRS 1 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_EXPR_CLOSURES 1 /* has function (formals) listexpr */
+
+#else
+
+#error "unknown JS_VERSION"
+
+#endif
+
+/* Features that are present in all versions. */
+#define JS_HAS_RESERVED_JAVA_KEYWORDS 1
+#define JS_HAS_RESERVED_ECMA_KEYWORDS 1
+
+/* Feature-test macro for evolving destructuring support. */
+#define JS_HAS_DESTRUCTURING_SHORTHAND (JS_HAS_DESTRUCTURING == 2)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.cpp
new file mode 100644
index 0000000..5643e73
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.cpp
@@ -0,0 +1,800 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "jsstddef.h"
+#include "jsversion.h"
+
+#if JS_HAS_XDR
+
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsdhash.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jscntxt.h"
+#include "jsnum.h"
+#include "jsobj.h" /* js_XDRObject */
+#include "jsscript.h" /* js_XDRScript */
+#include "jsstr.h"
+#include "jsxdrapi.h"
+
+#ifdef DEBUG
+#define DBG(x) x
+#else
+#define DBG(x) ((void)0)
+#endif
+
+typedef struct JSXDRMemState {
+ JSXDRState state;
+ char *base;
+ uint32 count;
+ uint32 limit;
+} JSXDRMemState;
+
+#define MEM_BLOCK 8192
+#define MEM_PRIV(xdr) ((JSXDRMemState *)(xdr))
+
+#define MEM_BASE(xdr) (MEM_PRIV(xdr)->base)
+#define MEM_COUNT(xdr) (MEM_PRIV(xdr)->count)
+#define MEM_LIMIT(xdr) (MEM_PRIV(xdr)->limit)
+
+#define MEM_LEFT(xdr, bytes) \
+ JS_BEGIN_MACRO \
+ if ((xdr)->mode == JSXDR_DECODE && \
+ MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
+ JS_ReportErrorNumber((xdr)->cx, js_GetErrorMessage, NULL, \
+ JSMSG_END_OF_DATA); \
+ return 0; \
+ } \
+ JS_END_MACRO
+
+#define MEM_NEED(xdr, bytes) \
+ JS_BEGIN_MACRO \
+ if ((xdr)->mode == JSXDR_ENCODE) { \
+ if (MEM_LIMIT(xdr) && \
+ MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
+ uint32 limit_ = JS_ROUNDUP(MEM_COUNT(xdr) + bytes, MEM_BLOCK);\
+ void *data_ = JS_realloc((xdr)->cx, MEM_BASE(xdr), limit_); \
+ if (!data_) \
+ return 0; \
+ MEM_BASE(xdr) = (char *) data_; \
+ MEM_LIMIT(xdr) = limit_; \
+ } \
+ } else { \
+ MEM_LEFT(xdr, bytes); \
+ } \
+ JS_END_MACRO
+
+#define MEM_DATA(xdr) ((void *)(MEM_BASE(xdr) + MEM_COUNT(xdr)))
+#define MEM_INCR(xdr,bytes) (MEM_COUNT(xdr) += (bytes))
+
+static JSBool
+mem_get32(JSXDRState *xdr, uint32 *lp)
+{
+ MEM_LEFT(xdr, 4);
+ *lp = *(uint32 *)MEM_DATA(xdr);
+ MEM_INCR(xdr, 4);
+ return JS_TRUE;
+}
+
+static JSBool
+mem_set32(JSXDRState *xdr, uint32 *lp)
+{
+ MEM_NEED(xdr, 4);
+ *(uint32 *)MEM_DATA(xdr) = *lp;
+ MEM_INCR(xdr, 4);
+ return JS_TRUE;
+}
+
+static JSBool
+mem_getbytes(JSXDRState *xdr, char *bytes, uint32 len)
+{
+ MEM_LEFT(xdr, len);
+ memcpy(bytes, MEM_DATA(xdr), len);
+ MEM_INCR(xdr, len);
+ return JS_TRUE;
+}
+
+static JSBool
+mem_setbytes(JSXDRState *xdr, char *bytes, uint32 len)
+{
+ MEM_NEED(xdr, len);
+ memcpy(MEM_DATA(xdr), bytes, len);
+ MEM_INCR(xdr, len);
+ return JS_TRUE;
+}
+
+static void *
+mem_raw(JSXDRState *xdr, uint32 len)
+{
+ void *data;
+ if (xdr->mode == JSXDR_ENCODE) {
+ MEM_NEED(xdr, len);
+ } else if (xdr->mode == JSXDR_DECODE) {
+ MEM_LEFT(xdr, len);
+ }
+ data = MEM_DATA(xdr);
+ MEM_INCR(xdr, len);
+ return data;
+}
+
+static JSBool
+mem_seek(JSXDRState *xdr, int32 offset, JSXDRWhence whence)
+{
+ switch (whence) {
+ case JSXDR_SEEK_CUR:
+ if ((int32)MEM_COUNT(xdr) + offset < 0) {
+ JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
+ JSMSG_SEEK_BEYOND_START);
+ return JS_FALSE;
+ }
+ if (offset > 0)
+ MEM_NEED(xdr, offset);
+ MEM_COUNT(xdr) += offset;
+ return JS_TRUE;
+ case JSXDR_SEEK_SET:
+ if (offset < 0) {
+ JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
+ JSMSG_SEEK_BEYOND_START);
+ return JS_FALSE;
+ }
+ if (xdr->mode == JSXDR_ENCODE) {
+ if ((uint32)offset > MEM_COUNT(xdr))
+ MEM_NEED(xdr, offset - MEM_COUNT(xdr));
+ MEM_COUNT(xdr) = offset;
+ } else {
+ if ((uint32)offset > MEM_LIMIT(xdr)) {
+ JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
+ JSMSG_SEEK_BEYOND_END);
+ return JS_FALSE;
+ }
+ MEM_COUNT(xdr) = offset;
+ }
+ return JS_TRUE;
+ case JSXDR_SEEK_END:
+ if (offset >= 0 ||
+ xdr->mode == JSXDR_ENCODE ||
+ (int32)MEM_LIMIT(xdr) + offset < 0) {
+ JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
+ JSMSG_END_SEEK);
+ return JS_FALSE;
+ }
+ MEM_COUNT(xdr) = MEM_LIMIT(xdr) + offset;
+ return JS_TRUE;
+ default: {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%d", whence);
+ JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
+ JSMSG_WHITHER_WHENCE, numBuf);
+ return JS_FALSE;
+ }
+ }
+}
+
+static uint32
+mem_tell(JSXDRState *xdr)
+{
+ return MEM_COUNT(xdr);
+}
+
+static void
+mem_finalize(JSXDRState *xdr)
+{
+ JS_free(xdr->cx, MEM_BASE(xdr));
+}
+
+static JSXDROps xdrmem_ops = {
+ mem_get32, mem_set32, mem_getbytes, mem_setbytes,
+ mem_raw, mem_seek, mem_tell, mem_finalize
+};
+
+JS_PUBLIC_API(void)
+JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx)
+{
+ xdr->mode = mode;
+ xdr->cx = cx;
+ xdr->registry = NULL;
+ xdr->numclasses = xdr->maxclasses = 0;
+ xdr->reghash = NULL;
+ xdr->userdata = NULL;
+ xdr->script = NULL;
+}
+
+JS_PUBLIC_API(JSXDRState *)
+JS_XDRNewMem(JSContext *cx, JSXDRMode mode)
+{
+ JSXDRState *xdr = (JSXDRState *) JS_malloc(cx, sizeof(JSXDRMemState));
+ if (!xdr)
+ return NULL;
+ JS_XDRInitBase(xdr, mode, cx);
+ if (mode == JSXDR_ENCODE) {
+ if (!(MEM_BASE(xdr) = (char *) JS_malloc(cx, MEM_BLOCK))) {
+ JS_free(cx, xdr);
+ return NULL;
+ }
+ } else {
+ /* XXXbe ok, so better not deref MEM_BASE(xdr) if not ENCODE */
+ MEM_BASE(xdr) = NULL;
+ }
+ xdr->ops = &xdrmem_ops;
+ MEM_COUNT(xdr) = 0;
+ MEM_LIMIT(xdr) = MEM_BLOCK;
+ return xdr;
+}
+
+JS_PUBLIC_API(void *)
+JS_XDRMemGetData(JSXDRState *xdr, uint32 *lp)
+{
+ if (xdr->ops != &xdrmem_ops)
+ return NULL;
+ *lp = MEM_COUNT(xdr);
+ return MEM_BASE(xdr);
+}
+
+JS_PUBLIC_API(void)
+JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32 len)
+{
+ if (xdr->ops != &xdrmem_ops)
+ return;
+ MEM_LIMIT(xdr) = len;
+ MEM_BASE(xdr) = (char *) data;
+ MEM_COUNT(xdr) = 0;
+}
+
+JS_PUBLIC_API(uint32)
+JS_XDRMemDataLeft(JSXDRState *xdr)
+{
+ if (xdr->ops != &xdrmem_ops)
+ return 0;
+ return MEM_LIMIT(xdr) - MEM_COUNT(xdr);
+}
+
+JS_PUBLIC_API(void)
+JS_XDRMemResetData(JSXDRState *xdr)
+{
+ if (xdr->ops != &xdrmem_ops)
+ return;
+ MEM_COUNT(xdr) = 0;
+}
+
+JS_PUBLIC_API(void)
+JS_XDRDestroy(JSXDRState *xdr)
+{
+ JSContext *cx = xdr->cx;
+ xdr->ops->finalize(xdr);
+ if (xdr->registry) {
+ JS_free(cx, xdr->registry);
+ if (xdr->reghash)
+ JS_DHashTableDestroy((JSDHashTable *) xdr->reghash);
+ }
+ JS_free(cx, xdr);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRUint8(JSXDRState *xdr, uint8 *b)
+{
+ uint32 l = *b;
+ if (!JS_XDRUint32(xdr, &l))
+ return JS_FALSE;
+ *b = (uint8) l;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRUint16(JSXDRState *xdr, uint16 *s)
+{
+ uint32 l = *s;
+ if (!JS_XDRUint32(xdr, &l))
+ return JS_FALSE;
+ *s = (uint16) l;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRUint32(JSXDRState *xdr, uint32 *lp)
+{
+ JSBool ok = JS_TRUE;
+ if (xdr->mode == JSXDR_ENCODE) {
+ uint32 xl = JSXDR_SWAB32(*lp);
+ ok = xdr->ops->set32(xdr, &xl);
+ } else if (xdr->mode == JSXDR_DECODE) {
+ ok = xdr->ops->get32(xdr, lp);
+ *lp = JSXDR_SWAB32(*lp);
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32 len)
+{
+ uint32 padlen;
+ static char padbuf[JSXDR_ALIGN-1];
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ if (!xdr->ops->setbytes(xdr, bytes, len))
+ return JS_FALSE;
+ } else {
+ if (!xdr->ops->getbytes(xdr, bytes, len))
+ return JS_FALSE;
+ }
+ len = xdr->ops->tell(xdr);
+ if (len % JSXDR_ALIGN) {
+ padlen = JSXDR_ALIGN - (len % JSXDR_ALIGN);
+ if (xdr->mode == JSXDR_ENCODE) {
+ if (!xdr->ops->setbytes(xdr, padbuf, padlen))
+ return JS_FALSE;
+ } else {
+ if (!xdr->ops->seek(xdr, padlen, JSXDR_SEEK_CUR))
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+/**
+ * Convert between a C string and the XDR representation:
+ * leading 32-bit count, then counted vector of chars,
+ * then possibly \0 padding to multiple of 4.
+ */
+JS_PUBLIC_API(JSBool)
+JS_XDRCString(JSXDRState *xdr, char **sp)
+{
+ uint32 len;
+
+ if (xdr->mode == JSXDR_ENCODE)
+ len = strlen(*sp);
+ JS_XDRUint32(xdr, &len);
+ if (xdr->mode == JSXDR_DECODE) {
+ if (!(*sp = (char *) JS_malloc(xdr->cx, len + 1)))
+ return JS_FALSE;
+ }
+ if (!JS_XDRBytes(xdr, *sp, len)) {
+ if (xdr->mode == JSXDR_DECODE)
+ JS_free(xdr->cx, *sp);
+ return JS_FALSE;
+ }
+ if (xdr->mode == JSXDR_DECODE) {
+ (*sp)[len] = '\0';
+ } else if (xdr->mode == JSXDR_FREE) {
+ JS_free(xdr->cx, *sp);
+ *sp = NULL;
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRCStringOrNull(JSXDRState *xdr, char **sp)
+{
+ uint32 null = (*sp == NULL);
+ if (!JS_XDRUint32(xdr, &null))
+ return JS_FALSE;
+ if (null) {
+ *sp = NULL;
+ return JS_TRUE;
+ }
+ return JS_XDRCString(xdr, sp);
+}
+
+static JSBool
+XDRChars(JSXDRState *xdr, jschar *chars, uint32 nchars)
+{
+ uint32 i, padlen, nbytes;
+ jschar *raw;
+
+ nbytes = nchars * sizeof(jschar);
+ padlen = nbytes % JSXDR_ALIGN;
+ if (padlen) {
+ padlen = JSXDR_ALIGN - padlen;
+ nbytes += padlen;
+ }
+ if (!(raw = (jschar *) xdr->ops->raw(xdr, nbytes)))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_ENCODE) {
+ for (i = 0; i != nchars; i++)
+ raw[i] = JSXDR_SWAB16(chars[i]);
+ if (padlen)
+ memset((char *)raw + nbytes - padlen, 0, padlen);
+ } else if (xdr->mode == JSXDR_DECODE) {
+ for (i = 0; i != nchars; i++)
+ chars[i] = JSXDR_SWAB16(raw[i]);
+ }
+ return JS_TRUE;
+}
+
+/*
+ * Convert between a JS (Unicode) string and the XDR representation.
+ */
+JS_PUBLIC_API(JSBool)
+JS_XDRString(JSXDRState *xdr, JSString **strp)
+{
+ uint32 nchars;
+ jschar *chars;
+
+ if (xdr->mode == JSXDR_ENCODE)
+ nchars = JSSTRING_LENGTH(*strp);
+ if (!JS_XDRUint32(xdr, &nchars))
+ return JS_FALSE;
+
+ if (xdr->mode == JSXDR_DECODE) {
+ chars = (jschar *) JS_malloc(xdr->cx, (nchars + 1) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+ } else {
+ chars = JSSTRING_CHARS(*strp);
+ }
+
+ if (!XDRChars(xdr, chars, nchars))
+ goto bad;
+ if (xdr->mode == JSXDR_DECODE) {
+ chars[nchars] = 0;
+ *strp = JS_NewUCString(xdr->cx, chars, nchars);
+ if (!*strp)
+ goto bad;
+ }
+ return JS_TRUE;
+
+bad:
+ if (xdr->mode == JSXDR_DECODE)
+ JS_free(xdr->cx, chars);
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp)
+{
+ uint32 null = (*strp == NULL);
+ if (!JS_XDRUint32(xdr, &null))
+ return JS_FALSE;
+ if (null) {
+ *strp = NULL;
+ return JS_TRUE;
+ }
+ return JS_XDRString(xdr, strp);
+}
+
+static JSBool
+XDRDoubleValue(JSXDRState *xdr, jsdouble *dp)
+{
+ jsdpun u;
+
+ if (xdr->mode == JSXDR_ENCODE)
+ u.d = *dp;
+ if (!JS_XDRUint32(xdr, &u.s.lo) || !JS_XDRUint32(xdr, &u.s.hi))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *dp = u.d;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRDouble(JSXDRState *xdr, jsdouble **dpp)
+{
+ jsdouble d;
+
+ if (xdr->mode == JSXDR_ENCODE)
+ d = **dpp;
+ if (!XDRDoubleValue(xdr, &d))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE) {
+ *dpp = JS_NewDouble(xdr->cx, d);
+ if (!*dpp)
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+/* These are magic pseudo-tags: see jsapi.h, near the top, for real tags. */
+#define JSVAL_XDRNULL 0x8
+#define JSVAL_XDRVOID 0xA
+
+static JSBool
+XDRValueBody(JSXDRState *xdr, uint32 type, jsval *vp)
+{
+ switch (type) {
+ case JSVAL_XDRNULL:
+ *vp = JSVAL_NULL;
+ break;
+ case JSVAL_XDRVOID:
+ *vp = JSVAL_VOID;
+ break;
+ case JSVAL_STRING: {
+ JSString *str;
+ if (xdr->mode == JSXDR_ENCODE)
+ str = JSVAL_TO_STRING(*vp);
+ if (!JS_XDRString(xdr, &str))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *vp = STRING_TO_JSVAL(str);
+ break;
+ }
+ case JSVAL_DOUBLE: {
+ jsdouble *dp;
+ if (xdr->mode == JSXDR_ENCODE)
+ dp = JSVAL_TO_DOUBLE(*vp);
+ if (!JS_XDRDouble(xdr, &dp))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *vp = DOUBLE_TO_JSVAL(dp);
+ break;
+ }
+ case JSVAL_OBJECT: {
+ JSObject *obj;
+ if (xdr->mode == JSXDR_ENCODE)
+ obj = JSVAL_TO_OBJECT(*vp);
+ if (!js_XDRObject(xdr, &obj))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *vp = OBJECT_TO_JSVAL(obj);
+ break;
+ }
+ case JSVAL_BOOLEAN: {
+ uint32 b;
+ if (xdr->mode == JSXDR_ENCODE)
+ b = (uint32) JSVAL_TO_BOOLEAN(*vp);
+ if (!JS_XDRUint32(xdr, &b))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *vp = BOOLEAN_TO_JSVAL(!!b);
+ break;
+ }
+ default: {
+ uint32 i;
+
+ JS_ASSERT(type & JSVAL_INT);
+ if (xdr->mode == JSXDR_ENCODE)
+ i = (uint32) JSVAL_TO_INT(*vp);
+ if (!JS_XDRUint32(xdr, &i))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *vp = INT_TO_JSVAL((int32) i);
+ break;
+ }
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRValue(JSXDRState *xdr, jsval *vp)
+{
+ uint32 type;
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ if (JSVAL_IS_NULL(*vp))
+ type = JSVAL_XDRNULL;
+ else if (JSVAL_IS_VOID(*vp))
+ type = JSVAL_XDRVOID;
+ else
+ type = JSVAL_TAG(*vp);
+ }
+ return JS_XDRUint32(xdr, &type) && XDRValueBody(xdr, type, vp);
+}
+
+JSBool
+js_XDRAtom(JSXDRState *xdr, JSAtom **atomp)
+{
+ jsval v;
+ uint32 type;
+ jsdouble d;
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ v = ATOM_KEY(*atomp);
+ return JS_XDRValue(xdr, &v);
+ }
+
+ /*
+ * Inline JS_XDRValue when decoding to avoid ceation of GC things when
+ * then corresponding atom already exists. See bug 321985.
+ */
+ if (!JS_XDRUint32(xdr, &type))
+ return JS_FALSE;
+ if (type == JSVAL_STRING)
+ return js_XDRStringAtom(xdr, atomp);
+
+ if (type == JSVAL_DOUBLE) {
+ if (!XDRDoubleValue(xdr, &d))
+ return JS_FALSE;
+ *atomp = js_AtomizeDouble(xdr->cx, d);
+ return *atomp != NULL;
+ }
+
+ return XDRValueBody(xdr, type, &v) &&
+ js_AtomizePrimitiveValue(xdr->cx, v, atomp);
+}
+
+extern JSBool
+js_XDRStringAtom(JSXDRState *xdr, JSAtom **atomp)
+{
+ JSString *str;
+ uint32 nchars;
+ JSAtom *atom;
+ JSContext *cx;
+ jschar *chars;
+ jschar stackChars[256];
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ JS_ASSERT(ATOM_IS_STRING(*atomp));
+ str = ATOM_TO_STRING(*atomp);
+ return JS_XDRString(xdr, &str);
+ }
+
+ /*
+ * Inline JS_XDRString when decoding to avoid JSString allocation
+ * for already existing atoms. See bug 321985.
+ */
+ if (!JS_XDRUint32(xdr, &nchars))
+ return JS_FALSE;
+ atom = NULL;
+ cx = xdr->cx;
+ if (nchars <= JS_ARRAY_LENGTH(stackChars)) {
+ chars = stackChars;
+ } else {
+ /*
+ * This is very uncommon. Don't use the tempPool arena for this as
+ * most allocations here will be bigger than tempPool's arenasize.
+ */
+ chars = (jschar *) JS_malloc(cx, nchars * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+ }
+
+ if (XDRChars(xdr, chars, nchars))
+ atom = js_AtomizeChars(cx, chars, nchars, 0);
+ if (chars != stackChars)
+ JS_free(cx, chars);
+
+ if (!atom)
+ return JS_FALSE;
+ *atomp = atom;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
+{
+ if (!js_XDRScript(xdr, scriptp, NULL))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ js_CallNewScriptHook(xdr->cx, *scriptp, NULL);
+ return JS_TRUE;
+}
+
+#define CLASS_REGISTRY_MIN 8
+#define CLASS_INDEX_TO_ID(i) ((i)+1)
+#define CLASS_ID_TO_INDEX(id) ((id)-1)
+
+typedef struct JSRegHashEntry {
+ JSDHashEntryHdr hdr;
+ const char *name;
+ uint32 index;
+} JSRegHashEntry;
+
+JS_PUBLIC_API(JSBool)
+JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *idp)
+{
+ uintN numclasses, maxclasses;
+ JSClass **registry;
+
+ numclasses = xdr->numclasses;
+ maxclasses = xdr->maxclasses;
+ if (numclasses == maxclasses) {
+ maxclasses = (maxclasses == 0) ? CLASS_REGISTRY_MIN : maxclasses << 1;
+ registry = (JSClass **)
+ JS_realloc(xdr->cx, xdr->registry, maxclasses * sizeof(JSClass *));
+ if (!registry)
+ return JS_FALSE;
+ xdr->registry = registry;
+ xdr->maxclasses = maxclasses;
+ } else {
+ JS_ASSERT(numclasses && numclasses < maxclasses);
+ registry = xdr->registry;
+ }
+
+ registry[numclasses] = clasp;
+ if (xdr->reghash) {
+ JSRegHashEntry *entry = (JSRegHashEntry *)
+ JS_DHashTableOperate((JSDHashTable *) xdr->reghash,
+ clasp->name, JS_DHASH_ADD);
+ if (!entry) {
+ JS_ReportOutOfMemory(xdr->cx);
+ return JS_FALSE;
+ }
+ entry->name = clasp->name;
+ entry->index = numclasses;
+ }
+ *idp = CLASS_INDEX_TO_ID(numclasses);
+ xdr->numclasses = ++numclasses;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(uint32)
+JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name)
+{
+ uintN i, numclasses;
+
+ numclasses = xdr->numclasses;
+ if (numclasses >= 10) {
+ JSRegHashEntry *entry;
+
+ /* Bootstrap reghash from registry on first overpopulated Find. */
+ if (!xdr->reghash) {
+ xdr->reghash =
+ JS_NewDHashTable(JS_DHashGetStubOps(), NULL,
+ sizeof(JSRegHashEntry),
+ JS_DHASH_DEFAULT_CAPACITY(numclasses));
+ if (xdr->reghash) {
+ for (i = 0; i < numclasses; i++) {
+ JSClass *clasp = xdr->registry[i];
+ entry = (JSRegHashEntry *)
+ JS_DHashTableOperate((JSDHashTable *) xdr->reghash,
+ clasp->name, JS_DHASH_ADD);
+ entry->name = clasp->name;
+ entry->index = i;
+ }
+ }
+ }
+
+ /* If we managed to create reghash, use it for O(1) Find. */
+ if (xdr->reghash) {
+ entry = (JSRegHashEntry *)
+ JS_DHashTableOperate((JSDHashTable *) xdr->reghash,
+ name, JS_DHASH_LOOKUP);
+ if (JS_DHASH_ENTRY_IS_BUSY(&entry->hdr))
+ return CLASS_INDEX_TO_ID(entry->index);
+ }
+ }
+
+ /* Only a few classes, or we couldn't malloc reghash: use linear search. */
+ for (i = 0; i < numclasses; i++) {
+ if (!strcmp(name, xdr->registry[i]->name))
+ return CLASS_INDEX_TO_ID(i);
+ }
+ return 0;
+}
+
+JS_PUBLIC_API(JSClass *)
+JS_XDRFindClassById(JSXDRState *xdr, uint32 id)
+{
+ uintN i = CLASS_ID_TO_INDEX(id);
+
+ if (i >= xdr->numclasses)
+ return NULL;
+ return xdr->registry[i];
+}
+
+#endif /* JS_HAS_XDR */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.h b/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.h
new file mode 100644
index 0000000..23b2636
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.h
@@ -0,0 +1,220 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsxdrapi_h___
+#define jsxdrapi_h___
+
+/*
+ * JS external data representation interface API.
+ *
+ * The XDR system is comprised of three major parts:
+ *
+ * - the state serialization/deserialization APIs, which allow consumers
+ * of the API to serialize JS runtime state (script bytecodes, atom maps,
+ * object graphs, etc.) for later restoration. These portions
+ * are implemented in various appropriate files, such as jsscript.c
+ * for the script portions and jsobj.c for object state.
+ * - the callback APIs through which the runtime requests an opaque
+ * representation of a native object, and through which the runtime
+ * constructs a live native object from an opaque representation. These
+ * portions are the responsibility of the native object implementor.
+ * - utility functions for en/decoding of primitive types, such as
+ * JSStrings. This portion is implemented in jsxdrapi.c.
+ *
+ * Spiritually guided by Sun's XDR, where appropriate.
+ */
+
+#include "jspubtd.h"
+#include "jsprvtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/* We use little-endian byteorder for all encoded data */
+
+#if defined IS_LITTLE_ENDIAN
+#define JSXDR_SWAB32(x) x
+#define JSXDR_SWAB16(x) x
+#elif defined IS_BIG_ENDIAN
+#define JSXDR_SWAB32(x) (((uint32)(x) >> 24) | \
+ (((uint32)(x) >> 8) & 0xff00) | \
+ (((uint32)(x) << 8) & 0xff0000) | \
+ ((uint32)(x) << 24))
+#define JSXDR_SWAB16(x) (((uint16)(x) >> 8) | ((uint16)(x) << 8))
+#else
+#error "unknown byte order"
+#endif
+
+#define JSXDR_ALIGN 4
+
+typedef enum JSXDRMode {
+ JSXDR_ENCODE,
+ JSXDR_DECODE,
+ JSXDR_FREE
+} JSXDRMode;
+
+typedef enum JSXDRWhence {
+ JSXDR_SEEK_SET,
+ JSXDR_SEEK_CUR,
+ JSXDR_SEEK_END
+} JSXDRWhence;
+
+typedef struct JSXDROps {
+ JSBool (*get32)(JSXDRState *, uint32 *);
+ JSBool (*set32)(JSXDRState *, uint32 *);
+ JSBool (*getbytes)(JSXDRState *, char *, uint32);
+ JSBool (*setbytes)(JSXDRState *, char *, uint32);
+ void * (*raw)(JSXDRState *, uint32);
+ JSBool (*seek)(JSXDRState *, int32, JSXDRWhence);
+ uint32 (*tell)(JSXDRState *);
+ void (*finalize)(JSXDRState *);
+} JSXDROps;
+
+struct JSXDRState {
+ JSXDRMode mode;
+ JSXDROps *ops;
+ JSContext *cx;
+ JSClass **registry;
+ uintN numclasses;
+ uintN maxclasses;
+ void *reghash;
+ void *userdata;
+ JSScript *script;
+};
+
+extern JS_PUBLIC_API(void)
+JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx);
+
+extern JS_PUBLIC_API(JSXDRState *)
+JS_XDRNewMem(JSContext *cx, JSXDRMode mode);
+
+extern JS_PUBLIC_API(void *)
+JS_XDRMemGetData(JSXDRState *xdr, uint32 *lp);
+
+extern JS_PUBLIC_API(void)
+JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32 len);
+
+extern JS_PUBLIC_API(uint32)
+JS_XDRMemDataLeft(JSXDRState *xdr);
+
+extern JS_PUBLIC_API(void)
+JS_XDRMemResetData(JSXDRState *xdr);
+
+extern JS_PUBLIC_API(void)
+JS_XDRDestroy(JSXDRState *xdr);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRUint8(JSXDRState *xdr, uint8 *b);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRUint16(JSXDRState *xdr, uint16 *s);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRUint32(JSXDRState *xdr, uint32 *lp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32 len);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRCString(JSXDRState *xdr, char **sp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRCStringOrNull(JSXDRState *xdr, char **sp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRString(JSXDRState *xdr, JSString **strp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRDouble(JSXDRState *xdr, jsdouble **dp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRValue(JSXDRState *xdr, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRScript(JSXDRState *xdr, JSScript **scriptp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *lp);
+
+extern JS_PUBLIC_API(uint32)
+JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name);
+
+extern JS_PUBLIC_API(JSClass *)
+JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
+
+/*
+ * Magic numbers.
+ */
+#define JSXDR_MAGIC_SCRIPT_1 0xdead0001
+#define JSXDR_MAGIC_SCRIPT_2 0xdead0002
+#define JSXDR_MAGIC_SCRIPT_3 0xdead0003
+#define JSXDR_MAGIC_SCRIPT_4 0xdead0004
+#define JSXDR_MAGIC_SCRIPT_5 0xdead0005
+#define JSXDR_MAGIC_SCRIPT_6 0xdead0006
+#define JSXDR_MAGIC_SCRIPT_7 0xdead0007
+#define JSXDR_MAGIC_SCRIPT_8 0xdead0008
+#define JSXDR_MAGIC_SCRIPT_9 0xdead0009
+#define JSXDR_MAGIC_SCRIPT_CURRENT JSXDR_MAGIC_SCRIPT_9
+
+/*
+ * Bytecode version number. Increment the subtrahend whenever JS bytecode
+ * changes incompatibly.
+ *
+ * This version number should be XDR'ed once near the front of any file or
+ * larger storage unit containing XDR'ed bytecode and other data, and checked
+ * before deserialization of bytecode. If the saved version does not match
+ * the current version, abort deserialization and invalidate the file.
+ */
+#define JSXDR_BYTECODE_VERSION (0xb973c0de - 37)
+
+/*
+ * Library-private functions.
+ */
+extern JSBool
+js_XDRAtom(JSXDRState *xdr, JSAtom **atomp);
+
+extern JSBool
+js_XDRStringAtom(JSXDRState *xdr, JSAtom **atomp);
+
+JS_END_EXTERN_C
+
+#endif /* ! jsxdrapi_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsxml.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsxml.cpp
new file mode 100644
index 0000000..b909219
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsxml.cpp
@@ -0,0 +1,8343 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=4 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey E4X code, released August, 2004.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h"
+#include "jsversion.h"
+
+#if JS_HAS_XML_SUPPORT
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jsprf.h"
+#include "jsutil.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsxml.h"
+#include "jsstaticcheck.h"
+
+#ifdef DEBUG
+#include <string.h> /* for #ifdef DEBUG memset calls */
+#endif
+
+/*
+ * NOTES
+ * - in the js shell, you must use the -x command line option, or call
+ * options('xml') before compiling anything that uses XML literals
+ *
+ * TODO
+ * - XXXbe patrol
+ * - Fuse objects and their JSXML* private data into single GC-things
+ * - fix function::foo vs. x.(foo == 42) collision using proper namespacing
+ * - fix the !TCF_HAS_DEFXMLNS optimization in js_FoldConstants
+ * - JSCLASS_DOCUMENT_OBSERVER support -- live two-way binding to Gecko's DOM!
+ * - JS_TypeOfValue sure could use a cleaner interface to "types"
+ */
+
+#ifdef XML_METERING
+static struct {
+ jsrefcount qname;
+ jsrefcount xmlnamespace;
+ jsrefcount xml;
+ jsrefcount xmlobj;
+} xml_stats;
+
+#define METER(x) JS_ATOMIC_INCREMENT(&(x))
+#define UNMETER(x) JS_ATOMIC_DECREMENT(&(x))
+#else
+#define METER(x) /* nothing */
+#define UNMETER(x) /* nothing */
+#endif
+
+/*
+ * Random utilities and global functions.
+ */
+const char js_isXMLName_str[] = "isXMLName";
+const char js_XMLList_str[] = "XMLList";
+const char js_localName_str[] = "localName";
+const char js_xml_parent_str[] = "parent";
+const char js_prefix_str[] = "prefix";
+const char js_toXMLString_str[] = "toXMLString";
+const char js_uri_str[] = "uri";
+
+const char js_amp_entity_str[] = "&amp;";
+const char js_gt_entity_str[] = "&gt;";
+const char js_lt_entity_str[] = "&lt;";
+const char js_quot_entity_str[] = "&quot;";
+
+#define IS_EMPTY(str) (JSSTRING_LENGTH(str) == 0)
+#define IS_STAR(str) (JSSTRING_LENGTH(str) == 1 && *JSSTRING_CHARS(str) == '*')
+/* Slot indexes shared between Namespace and QName objects. */
+const uint32 JSSLOT_PREFIX = JSSLOT_PRIVATE;
+const uint32 JSSLOT_URI = JSSLOT_PRIVATE + 1;
+
+/* Namespace-specific slot. */
+const uint32 JSSLOT_DECLARED = JSSLOT_PRIVATE + 2;
+
+/* QName-specific slot. */
+const uint32 JSSLOT_LOCAL_NAME = JSSLOT_PRIVATE + 2;
+
+const uint32 NAMESPACE_RESERVED_SLOTS = 3;
+const uint32 QNAME_RESERVED_SLOTS = 3;
+
+static JSBool
+IsQNameClass(JSClass *clasp)
+{
+ return clasp == &js_QNameClass.base ||
+ clasp == &js_AttributeNameClass ||
+ clasp == &js_AnyNameClass;
+}
+
+static JSString *
+GetSlotString(const JSObject *obj, uint32 slot)
+{
+ jsval v;
+
+ JS_ASSERT(slot == JSSLOT_PREFIX ||
+ slot == JSSLOT_URI ||
+ slot == JSSLOT_LOCAL_NAME);
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_NamespaceClass.base ||
+ IsQNameClass(STOBJ_GET_CLASS(obj)));
+ JS_ASSERT_IF(STOBJ_GET_CLASS(obj) == &js_NamespaceClass.base,
+ slot != JSSLOT_LOCAL_NAME);
+
+ v = obj->fslots[slot];
+ if (JSVAL_IS_VOID(v))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ return JSVAL_TO_STRING(v);
+}
+
+static JS_INLINE JSString *
+GetPrefix(const JSObject *obj)
+{
+ return GetSlotString(obj, JSSLOT_PREFIX);
+}
+
+static JSString *
+GetURI(const JSObject *obj)
+{
+ return GetSlotString(obj, JSSLOT_URI);
+}
+
+static JSString *
+GetLocalName(const JSObject *obj)
+{
+ return GetSlotString(obj, JSSLOT_LOCAL_NAME);
+}
+
+static JSBool
+IsDeclared(const JSObject *obj)
+{
+ jsval v;
+
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_NamespaceClass.base);
+ v = obj->fslots[JSSLOT_DECLARED];
+ JS_ASSERT(JSVAL_IS_VOID(v) || v == JSVAL_TRUE);
+ return v == JSVAL_TRUE;
+}
+
+static JSBool
+xml_isXMLName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ *rval = BOOLEAN_TO_JSVAL(js_IsXMLName(cx, argv[0]));
+ return JS_TRUE;
+}
+
+/*
+ * Namespace class and library functions.
+ */
+enum namespace_tinyid {
+ NAMESPACE_PREFIX = -1,
+ NAMESPACE_URI = -2
+};
+
+static JSBool
+namespace_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+
+ if (STOBJ_GET_CLASS(obj) != &js_NamespaceClass.base)
+ return JS_TRUE;
+
+ switch (JSVAL_TO_INT(id)) {
+ case NAMESPACE_PREFIX:
+ *vp = obj->fslots[JSSLOT_PREFIX];
+ break;
+ case NAMESPACE_URI:
+ *vp = obj->fslots[JSSLOT_URI];
+ break;
+ }
+ return JS_TRUE;
+}
+
+static void
+namespace_finalize(JSContext *cx, JSObject *obj)
+{
+ if (cx->runtime->functionNamespaceObject == obj)
+ cx->runtime->functionNamespaceObject = NULL;
+}
+
+static JSBool
+namespace_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ JSObject *obj2;
+
+ JS_ASSERT(JSVAL_IS_OBJECT(v));
+ obj2 = JSVAL_TO_OBJECT(v);
+ *bp = (!obj2 || OBJ_GET_CLASS(cx, obj2) != &js_NamespaceClass.base)
+ ? JS_FALSE
+ : js_EqualStrings(GetURI(obj), GetURI(obj2));
+ return JS_TRUE;
+}
+
+JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass = {
+ { "Namespace",
+ JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED |
+ JSCLASS_HAS_RESERVED_SLOTS(NAMESPACE_RESERVED_SLOTS) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Namespace),
+ JS_PropertyStub, JS_PropertyStub, namespace_getProperty, NULL,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, namespace_finalize,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL },
+ namespace_equality,NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+#define NAMESPACE_ATTRS \
+ (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
+
+static JSPropertySpec namespace_props[] = {
+ {js_prefix_str, NAMESPACE_PREFIX, NAMESPACE_ATTRS, 0, 0},
+ {js_uri_str, NAMESPACE_URI, NAMESPACE_ATTRS, 0, 0},
+ {0,0,0,0,0}
+};
+
+static JSBool
+namespace_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_NamespaceClass.base, vp))
+ return JS_FALSE;
+ *vp = obj->fslots[JSSLOT_URI];
+ return JS_TRUE;
+}
+
+static JSFunctionSpec namespace_methods[] = {
+ JS_FN(js_toString_str, namespace_toString, 0,0),
+ JS_FS_END
+};
+
+static JSObject *
+NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri, JSBool declared)
+{
+ JSObject *obj;
+
+ obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_PREFIX]));
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_URI]));
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_DECLARED]));
+ if (prefix)
+ obj->fslots[JSSLOT_PREFIX] = STRING_TO_JSVAL(prefix);
+ if (uri)
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(uri);
+ if (declared)
+ obj->fslots[JSSLOT_DECLARED] = JSVAL_TRUE;
+ METER(xml_stats.xmlnamespace);
+ return obj;
+}
+
+/*
+ * QName class and library functions.
+ */
+enum qname_tinyid {
+ QNAME_URI = -1,
+ QNAME_LOCALNAME = -2
+};
+
+static JSBool
+qname_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+
+ if (STOBJ_GET_CLASS(obj) != &js_QNameClass.base)
+ return JS_TRUE;
+
+ switch (JSVAL_TO_INT(id)) {
+ case QNAME_URI:
+ *vp = obj->fslots[JSSLOT_URI];
+ if (*vp == JSVAL_VOID)
+ *vp = JSVAL_NULL;
+ break;
+ case QNAME_LOCALNAME:
+ *vp = obj->fslots[JSSLOT_LOCAL_NAME];
+ break;
+ }
+ return JS_TRUE;
+}
+
+static void
+anyname_finalize(JSContext* cx, JSObject* obj)
+{
+ /* Make sure the next call to js_GetAnyName doesn't try to use obj. */
+ if (cx->runtime->anynameObject == obj)
+ cx->runtime->anynameObject = NULL;
+}
+
+static JSBool
+qname_identity(JSObject *qna, JSObject *qnb)
+{
+ JSString *uri1 = GetURI(qna);
+ JSString *uri2 = GetURI(qnb);
+
+ if (!uri1 ^ !uri2)
+ return JS_FALSE;
+ if (uri1 && !js_EqualStrings(uri1, uri2))
+ return JS_FALSE;
+ return js_EqualStrings(GetLocalName(qna), GetLocalName(qnb));
+}
+
+static JSBool
+qname_equality(JSContext *cx, JSObject *qn, jsval v, JSBool *bp)
+{
+ JSObject *obj2;
+
+ JS_ASSERT(JSVAL_IS_OBJECT(v));
+ obj2 = JSVAL_TO_OBJECT(v);
+ *bp = (!obj2 || OBJ_GET_CLASS(cx, obj2) != &js_QNameClass.base)
+ ? JS_FALSE
+ : qname_identity(qn, obj2);
+ return JS_TRUE;
+}
+
+JS_FRIEND_DATA(JSExtendedClass) js_QNameClass = {
+ { "QName",
+ JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED |
+ JSCLASS_HAS_RESERVED_SLOTS(QNAME_RESERVED_SLOTS) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_QName),
+ JS_PropertyStub, JS_PropertyStub, qname_getProperty, NULL,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL },
+ qname_equality, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+/*
+ * Classes for the ECMA-357-internal types AttributeName and AnyName, which
+ * are like QName, except that they have no property getters. They share the
+ * qname_toString method, and therefore are exposed as constructable objects
+ * in this implementation.
+ */
+JS_FRIEND_DATA(JSClass) js_AttributeNameClass = {
+ js_AttributeName_str,
+ JSCLASS_CONSTRUCT_PROTOTYPE |
+ JSCLASS_HAS_RESERVED_SLOTS(QNAME_RESERVED_SLOTS) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_AttributeName),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+JS_FRIEND_DATA(JSClass) js_AnyNameClass = {
+ js_AnyName_str,
+ JSCLASS_CONSTRUCT_PROTOTYPE |
+ JSCLASS_HAS_RESERVED_SLOTS(QNAME_RESERVED_SLOTS) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_AnyName),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, anyname_finalize,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+#define QNAME_ATTRS \
+ (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
+
+static JSPropertySpec qname_props[] = {
+ {js_uri_str, QNAME_URI, QNAME_ATTRS, 0, 0},
+ {js_localName_str, QNAME_LOCALNAME, QNAME_ATTRS, 0, 0},
+ {0,0,0,0,0}
+};
+
+static JSBool
+qname_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ JSClass *clasp;
+ JSString *uri, *str, *qualstr;
+ size_t length;
+ jschar *chars;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp != &js_AttributeNameClass &&
+ clasp != &js_AnyNameClass &&
+ !JS_InstanceOf(cx, obj, &js_QNameClass.base, vp + 2)) {
+ return JS_FALSE;
+ }
+
+ uri = GetURI(obj);
+ if (!uri) {
+ /* No uri means wildcard qualifier. */
+ str = ATOM_TO_STRING(cx->runtime->atomState.starQualifierAtom);
+ } else if (IS_EMPTY(uri)) {
+ /* Empty string for uri means localName is in no namespace. */
+ str = cx->runtime->emptyString;
+ } else {
+ qualstr = ATOM_TO_STRING(cx->runtime->atomState.qualifierAtom);
+ str = js_ConcatStrings(cx, uri, qualstr);
+ if (!str)
+ return JS_FALSE;
+ }
+ str = js_ConcatStrings(cx, str, GetLocalName(obj));
+ if (!str)
+ return JS_FALSE;
+
+ if (str && clasp == &js_AttributeNameClass) {
+ length = JSSTRING_LENGTH(str);
+ chars = (jschar *) JS_malloc(cx, (length + 2) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+ *chars = '@';
+ js_strncpy(chars + 1, JSSTRING_CHARS(str), length);
+ chars[++length] = 0;
+ str = js_NewString(cx, chars, length);
+ if (!str) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSFunctionSpec qname_methods[] = {
+ JS_FN(js_toString_str, qname_toString, 0,0),
+ JS_FS_END
+};
+
+
+static void
+InitXMLQName(JSObject *obj, JSString *uri, JSString *prefix,
+ JSString *localName)
+{
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_PREFIX]));
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_URI]));
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_LOCAL_NAME]));
+ if (uri)
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(uri);
+ if (prefix)
+ obj->fslots[JSSLOT_PREFIX] = STRING_TO_JSVAL(prefix);
+ if (localName)
+ obj->fslots[JSSLOT_LOCAL_NAME] = STRING_TO_JSVAL(localName);
+}
+
+static JSObject *
+NewXMLQName(JSContext *cx, JSString *uri, JSString *prefix, JSString *localName,
+ JSClass *clasp = &js_QNameClass.base)
+{
+ JSObject *obj;
+
+ JS_ASSERT(IsQNameClass(clasp));
+ obj = js_NewObject(cx, clasp, NULL, NULL, 0);
+ if (!obj)
+ return NULL;
+ InitXMLQName(obj, uri, prefix, localName);
+ METER(xml_stats.qname);
+ return obj;
+}
+
+JSObject *
+js_ConstructXMLQNameObject(JSContext *cx, jsval nsval, jsval lnval)
+{
+ jsval argv[2];
+
+ /*
+ * ECMA-357 11.1.2,
+ * The _QualifiedIdentifier : PropertySelector :: PropertySelector_
+ * production, step 2.
+ */
+ if (!JSVAL_IS_PRIMITIVE(nsval) &&
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(nsval)) == &js_AnyNameClass) {
+ nsval = JSVAL_NULL;
+ }
+
+ argv[0] = nsval;
+ argv[1] = lnval;
+ return js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 2, argv);
+}
+
+static JSBool
+IsXMLName(const jschar *cp, size_t n)
+{
+ JSBool rv;
+ jschar c;
+
+ rv = JS_FALSE;
+ if (n != 0 && JS_ISXMLNSSTART(*cp)) {
+ while (--n != 0) {
+ c = *++cp;
+ if (!JS_ISXMLNS(c))
+ return rv;
+ }
+ rv = JS_TRUE;
+ }
+ return rv;
+}
+
+JSBool
+js_IsXMLName(JSContext *cx, jsval v)
+{
+ JSString *name;
+ JSErrorReporter older;
+
+ /*
+ * Inline specialization of the QName constructor called with v passed as
+ * the only argument, to compute the localName for the constructed qname,
+ * without actually allocating the object or computing its uri and prefix.
+ * See ECMA-357 13.1.2.1 step 1 and 13.3.2.
+ */
+ if (!JSVAL_IS_PRIMITIVE(v) &&
+ IsQNameClass(OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)))) {
+ name = GetLocalName(JSVAL_TO_OBJECT(v));
+ } else {
+ older = JS_SetErrorReporter(cx, NULL);
+ name = js_ValueToString(cx, v);
+ JS_SetErrorReporter(cx, older);
+ if (!name) {
+ JS_ClearPendingException(cx);
+ return JS_FALSE;
+ }
+ }
+
+ return IsXMLName(JSSTRING_CHARS(name), JSSTRING_LENGTH(name));
+}
+
+/*
+ * When argc is -1, it indicates argv is empty but the code should behave as
+ * if argc is 1 and argv[0] is JSVAL_VOID.
+ */
+static JSBool
+NamespaceHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv,
+ jsval *rval)
+{
+ jsval urival, prefixval;
+ JSObject *uriobj;
+ JSBool isNamespace, isQName;
+ JSClass *clasp;
+ JSString *empty, *uri, *prefix;
+
+ isNamespace = isQName = JS_FALSE;
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ uriobj = NULL;
+#endif
+ if (argc <= 0) {
+ urival = JSVAL_VOID;
+ } else {
+ urival = argv[argc > 1];
+ if (!JSVAL_IS_PRIMITIVE(urival)) {
+ uriobj = JSVAL_TO_OBJECT(urival);
+ clasp = OBJ_GET_CLASS(cx, uriobj);
+ isNamespace = (clasp == &js_NamespaceClass.base);
+ isQName = (clasp == &js_QNameClass.base);
+ }
+ }
+
+ if (!obj) {
+ /* Namespace called as function. */
+ if (argc == 1 && isNamespace) {
+ /* Namespace called with one Namespace argument is identity. */
+ *rval = urival;
+ return JS_TRUE;
+ }
+
+ obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+ METER(xml_stats.xmlnamespace);
+
+ empty = cx->runtime->emptyString;
+ obj->fslots[JSSLOT_PREFIX] = STRING_TO_JSVAL(empty);
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(empty);
+
+ if (argc == 1 || argc == -1) {
+ if (isNamespace) {
+ obj->fslots[JSSLOT_URI] = uriobj->fslots[JSSLOT_URI];
+ obj->fslots[JSSLOT_PREFIX] = uriobj->fslots[JSSLOT_PREFIX];
+ } else if (isQName && (uri = GetURI(uriobj))) {
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(uri);
+ obj->fslots[JSSLOT_PREFIX] = uriobj->fslots[JSSLOT_PREFIX];
+ } else {
+ uri = js_ValueToString(cx, urival);
+ if (!uri)
+ return JS_FALSE;
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(uri);
+ if (!IS_EMPTY(uri))
+ obj->fslots[JSSLOT_PREFIX] = JSVAL_VOID;
+ }
+ } else if (argc == 2) {
+ if (!isQName || !(uri = GetURI(uriobj))) {
+ uri = js_ValueToString(cx, urival);
+ if (!uri)
+ return JS_FALSE;
+ }
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(uri);
+
+ prefixval = argv[0];
+ if (IS_EMPTY(uri)) {
+ if (!JSVAL_IS_VOID(prefixval)) {
+ prefix = js_ValueToString(cx, prefixval);
+ if (!prefix)
+ return JS_FALSE;
+ if (!IS_EMPTY(prefix)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_XML_NAMESPACE,
+ js_ValueToPrintableString(cx,
+ STRING_TO_JSVAL(prefix)));
+ return JS_FALSE;
+ }
+ }
+ } else if (JSVAL_IS_VOID(prefixval) || !js_IsXMLName(cx, prefixval)) {
+ obj->fslots[JSSLOT_PREFIX] = JSVAL_VOID;
+ } else {
+ prefix = js_ValueToString(cx, prefixval);
+ if (!prefix)
+ return JS_FALSE;
+ obj->fslots[JSSLOT_PREFIX] = STRING_TO_JSVAL(prefix);
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+Namespace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ return NamespaceHelper(cx,
+ (cx->fp->flags & JSFRAME_CONSTRUCTING) ? obj : NULL,
+ argc, argv, rval);
+}
+
+/*
+ * When argc is -1, it indicates argv is empty but the code should behave as
+ * if argc is 1 and argv[0] is JSVAL_VOID.
+ */
+static JSBool
+QNameHelper(JSContext *cx, JSObject *obj, JSClass *clasp, intN argc,
+ jsval *argv, jsval *rval)
+{
+ jsval nameval, nsval;
+ JSBool isQName, isNamespace;
+ JSObject *qn;
+ JSString *uri, *prefix, *name;
+ JSObject *obj2;
+
+ JS_ASSERT(clasp == &js_QNameClass.base ||
+ clasp == &js_AttributeNameClass);
+ if (argc <= 0) {
+ nameval = JSVAL_VOID;
+ isQName = JS_FALSE;
+ } else {
+ nameval = argv[argc > 1];
+ isQName =
+ !JSVAL_IS_PRIMITIVE(nameval) &&
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(nameval)) == &js_QNameClass.base;
+ }
+
+ if (!obj) {
+ /* QName called as function. */
+ if (argc == 1 && isQName) {
+ /* QName called with one QName argument is identity. */
+ *rval = nameval;
+ return JS_TRUE;
+ }
+
+ /*
+ * Create and return a new QName or AttributeName object exactly as if
+ * constructed.
+ */
+ obj = js_NewObject(cx, clasp, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+ METER(xml_stats.qname);
+
+ if (isQName) {
+ /* If namespace is not specified and name is a QName, clone it. */
+ qn = JSVAL_TO_OBJECT(nameval);
+ if (argc == 1) {
+ uri = GetURI(qn);
+ prefix = GetPrefix(qn);
+ name = GetLocalName(qn);
+ goto out;
+ }
+
+ /* Namespace and qname were passed -- use the qname's localName. */
+ nameval = qn->fslots[JSSLOT_LOCAL_NAME];
+ }
+
+ if (argc == 0) {
+ name = cx->runtime->emptyString;
+ } else if (argc < 0) {
+ name = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
+ } else {
+ name = js_ValueToString(cx, nameval);
+ if (!name)
+ return JS_FALSE;
+ argv[argc > 1] = STRING_TO_JSVAL(name);
+ }
+
+ if (argc > 1 && !JSVAL_IS_VOID(argv[0])) {
+ nsval = argv[0];
+ } else if (IS_STAR(name)) {
+ nsval = JSVAL_NULL;
+ } else {
+ if (!js_GetDefaultXMLNamespace(cx, &nsval))
+ return JS_FALSE;
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(nsval));
+ JS_ASSERT(OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(nsval)) ==
+ &js_NamespaceClass.base);
+ }
+
+ if (JSVAL_IS_NULL(nsval)) {
+ /* NULL prefix represents *undefined* in ECMA-357 13.3.2 5(a). */
+ uri = prefix = NULL;
+ } else {
+ /*
+ * Inline specialization of the Namespace constructor called with
+ * nsval passed as the only argument, to compute the uri and prefix
+ * for the constructed namespace, without actually allocating the
+ * object or computing other members. See ECMA-357 13.3.2 6(a) and
+ * 13.2.2.
+ */
+ isNamespace = isQName = JS_FALSE;
+ if (!JSVAL_IS_PRIMITIVE(nsval)) {
+ obj2 = JSVAL_TO_OBJECT(nsval);
+ clasp = OBJ_GET_CLASS(cx, obj2);
+ isNamespace = (clasp == &js_NamespaceClass.base);
+ isQName = (clasp == &js_QNameClass.base);
+ }
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ else obj2 = NULL;
+#endif
+
+ if (isNamespace) {
+ uri = GetURI(obj2);
+ prefix = GetPrefix(obj2);
+ } else if (isQName && (uri = GetURI(obj2))) {
+ JS_ASSERT(argc > 1);
+ prefix = GetPrefix(obj2);
+ } else {
+ JS_ASSERT(argc > 1);
+ uri = js_ValueToString(cx, nsval);
+ if (!uri)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(uri); /* local root */
+
+ /* NULL here represents *undefined* in ECMA-357 13.2.2 3(c)iii. */
+ prefix = IS_EMPTY(uri) ? cx->runtime->emptyString : NULL;
+ }
+ }
+
+out:
+ InitXMLQName(obj, uri, prefix, name);
+ return JS_TRUE;
+}
+
+static JSBool
+QName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ return QNameHelper(cx, (cx->fp->flags & JSFRAME_CONSTRUCTING) ? obj : NULL,
+ &js_QNameClass.base, argc, argv, rval);
+}
+
+static JSBool
+AttributeName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ return QNameHelper(cx, (cx->fp->flags & JSFRAME_CONSTRUCTING) ? obj : NULL,
+ &js_AttributeNameClass, argc, argv, rval);
+}
+
+/*
+ * XMLArray library functions.
+ */
+static JSBool
+namespace_identity(const void *a, const void *b)
+{
+ const JSObject *nsa = (const JSObject *) a;
+ const JSObject *nsb = (const JSObject *) b;
+ JSString *prefixa = GetPrefix(nsa);
+ JSString *prefixb = GetPrefix(nsb);
+
+ if (prefixa && prefixb) {
+ if (!js_EqualStrings(prefixa, prefixb))
+ return JS_FALSE;
+ } else {
+ if (prefixa || prefixb)
+ return JS_FALSE;
+ }
+ return js_EqualStrings(GetURI(nsa), GetURI(nsb));
+}
+
+static JSBool
+attr_identity(const void *a, const void *b)
+{
+ const JSXML *xmla = (const JSXML *) a;
+ const JSXML *xmlb = (const JSXML *) b;
+
+ return qname_identity(xmla->name, xmlb->name);
+}
+
+static void
+XMLArrayCursorInit(JSXMLArrayCursor *cursor, JSXMLArray *array)
+{
+ JSXMLArrayCursor *next;
+
+ cursor->array = array;
+ cursor->index = 0;
+ next = cursor->next = array->cursors;
+ if (next)
+ next->prevp = &cursor->next;
+ cursor->prevp = &array->cursors;
+ array->cursors = cursor;
+ cursor->root = NULL;
+}
+
+static void
+XMLArrayCursorFinish(JSXMLArrayCursor *cursor)
+{
+ JSXMLArrayCursor *next;
+
+ if (!cursor->array)
+ return;
+ next = cursor->next;
+ if (next)
+ next->prevp = cursor->prevp;
+ *cursor->prevp = next;
+ cursor->array = NULL;
+}
+
+static void *
+XMLArrayCursorNext(JSXMLArrayCursor *cursor)
+{
+ JSXMLArray *array;
+
+ array = cursor->array;
+ if (!array || cursor->index >= array->length)
+ return NULL;
+ return cursor->root = array->vector[cursor->index++];
+}
+
+static void *
+XMLArrayCursorItem(JSXMLArrayCursor *cursor)
+{
+ JSXMLArray *array;
+
+ array = cursor->array;
+ if (!array || cursor->index >= array->length)
+ return NULL;
+ return cursor->root = array->vector[cursor->index];
+}
+
+static void
+XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor *cursor)
+{
+ void *root;
+#ifdef DEBUG
+ size_t index = 0;
+#endif
+
+ for (; cursor; cursor = cursor->next) {
+ root = cursor->root;
+ JS_SET_TRACING_INDEX(trc, "cursor_root", index++);
+ js_CallValueTracerIfGCThing(trc, (jsval)root);
+ }
+}
+
+/* NB: called with null cx from the GC, via xml_trace => XMLArrayTrim. */
+static JSBool
+XMLArraySetCapacity(JSContext *cx, JSXMLArray *array, uint32 capacity)
+{
+ void **vector;
+
+ if (capacity == 0) {
+ /* We could let realloc(p, 0) free this, but purify gets confused. */
+ if (array->vector)
+ free(array->vector);
+ vector = NULL;
+ } else {
+ if (
+#if JS_BITS_PER_WORD == 32
+ (size_t)capacity > ~(size_t)0 / sizeof(void *) ||
+#endif
+ !(vector = (void **)
+ realloc(array->vector, capacity * sizeof(void *)))) {
+ if (cx)
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ }
+ array->capacity = JSXML_PRESET_CAPACITY | capacity;
+ array->vector = vector;
+ return JS_TRUE;
+}
+
+static void
+XMLArrayTrim(JSXMLArray *array)
+{
+ if (array->capacity & JSXML_PRESET_CAPACITY)
+ return;
+ if (array->length < array->capacity)
+ XMLArraySetCapacity(NULL, array, array->length);
+}
+
+static JSBool
+XMLArrayInit(JSContext *cx, JSXMLArray *array, uint32 capacity)
+{
+ array->length = array->capacity = 0;
+ array->vector = NULL;
+ array->cursors = NULL;
+ return capacity == 0 || XMLArraySetCapacity(cx, array, capacity);
+}
+
+static void
+XMLArrayFinish(JSContext *cx, JSXMLArray *array)
+{
+ JSXMLArrayCursor *cursor;
+
+ JS_free(cx, array->vector);
+
+ while ((cursor = array->cursors) != NULL)
+ XMLArrayCursorFinish(cursor);
+
+#ifdef DEBUG
+ memset(array, 0xd5, sizeof *array);
+#endif
+}
+
+#define XML_NOT_FOUND ((uint32) -1)
+
+static uint32
+XMLArrayFindMember(const JSXMLArray *array, void *elt, JSIdentityOp identity)
+{
+ void **vector;
+ uint32 i, n;
+
+ /* The identity op must not reallocate array->vector. */
+ vector = array->vector;
+ if (identity) {
+ for (i = 0, n = array->length; i < n; i++) {
+ if (identity(vector[i], elt))
+ return i;
+ }
+ } else {
+ for (i = 0, n = array->length; i < n; i++) {
+ if (vector[i] == elt)
+ return i;
+ }
+ }
+ return XML_NOT_FOUND;
+}
+
+/*
+ * Grow array vector capacity by powers of two to LINEAR_THRESHOLD, and after
+ * that, grow by LINEAR_INCREMENT. Both must be powers of two, and threshold
+ * should be greater than increment.
+ */
+#define LINEAR_THRESHOLD 256
+#define LINEAR_INCREMENT 32
+
+static JSBool
+XMLArrayAddMember(JSContext *cx, JSXMLArray *array, uint32 index, void *elt)
+{
+ uint32 capacity, i;
+ int log2;
+ void **vector;
+
+ if (index >= array->length) {
+ if (index >= JSXML_CAPACITY(array)) {
+ /* Arrange to clear JSXML_PRESET_CAPACITY from array->capacity. */
+ capacity = index + 1;
+ if (index >= LINEAR_THRESHOLD) {
+ capacity = JS_ROUNDUP(capacity, LINEAR_INCREMENT);
+ } else {
+ JS_CEILING_LOG2(log2, capacity);
+ capacity = JS_BIT(log2);
+ }
+ if (
+#if JS_BITS_PER_WORD == 32
+ (size_t)capacity > ~(size_t)0 / sizeof(void *) ||
+#endif
+ !(vector = (void **)
+ realloc(array->vector, capacity * sizeof(void *)))) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ array->capacity = capacity;
+ array->vector = vector;
+ for (i = array->length; i < index; i++)
+ vector[i] = NULL;
+ }
+ array->length = index + 1;
+ }
+
+ array->vector[index] = elt;
+ return JS_TRUE;
+}
+
+static JSBool
+XMLArrayInsert(JSContext *cx, JSXMLArray *array, uint32 i, uint32 n)
+{
+ uint32 j;
+ JSXMLArrayCursor *cursor;
+
+ j = array->length;
+ JS_ASSERT(i <= j);
+ if (!XMLArraySetCapacity(cx, array, j + n))
+ return JS_FALSE;
+
+ array->length = j + n;
+ JS_ASSERT(n != (uint32)-1);
+ while (j != i) {
+ --j;
+ array->vector[j + n] = array->vector[j];
+ }
+
+ for (cursor = array->cursors; cursor; cursor = cursor->next) {
+ if (cursor->index > i)
+ cursor->index += n;
+ }
+ return JS_TRUE;
+}
+
+static void *
+XMLArrayDelete(JSContext *cx, JSXMLArray *array, uint32 index, JSBool compress)
+{
+ uint32 length;
+ void **vector, *elt;
+ JSXMLArrayCursor *cursor;
+
+ length = array->length;
+ if (index >= length)
+ return NULL;
+
+ vector = array->vector;
+ elt = vector[index];
+ if (compress) {
+ while (++index < length)
+ vector[index-1] = vector[index];
+ array->length = length - 1;
+ array->capacity = JSXML_CAPACITY(array);
+ } else {
+ vector[index] = NULL;
+ }
+
+ for (cursor = array->cursors; cursor; cursor = cursor->next) {
+ if (cursor->index > index)
+ --cursor->index;
+ }
+ return elt;
+}
+
+static void
+XMLArrayTruncate(JSContext *cx, JSXMLArray *array, uint32 length)
+{
+ void **vector;
+
+ JS_ASSERT(!array->cursors);
+ if (length >= array->length)
+ return;
+
+ if (length == 0) {
+ if (array->vector)
+ free(array->vector);
+ vector = NULL;
+ } else {
+ vector = (void **) realloc(array->vector, length * sizeof(void *));
+ if (!vector)
+ return;
+ }
+
+ if (array->length > length)
+ array->length = length;
+ array->capacity = length;
+ array->vector = vector;
+}
+
+#define XMLARRAY_FIND_MEMBER(a,e,f) XMLArrayFindMember(a, (void *)(e), f)
+#define XMLARRAY_HAS_MEMBER(a,e,f) (XMLArrayFindMember(a, (void *)(e), f) != \
+ XML_NOT_FOUND)
+#define XMLARRAY_MEMBER(a,i,t) (((i) < (a)->length) \
+ ? (t *) (a)->vector[i] \
+ : NULL)
+#define XMLARRAY_SET_MEMBER(a,i,e) JS_BEGIN_MACRO \
+ if ((a)->length <= (i)) \
+ (a)->length = (i) + 1; \
+ ((a)->vector[i] = (void *)(e)); \
+ JS_END_MACRO
+#define XMLARRAY_ADD_MEMBER(x,a,i,e)XMLArrayAddMember(x, a, i, (void *)(e))
+#define XMLARRAY_INSERT(x,a,i,n) XMLArrayInsert(x, a, i, n)
+#define XMLARRAY_APPEND(x,a,e) XMLARRAY_ADD_MEMBER(x, a, (a)->length, (e))
+#define XMLARRAY_DELETE(x,a,i,c,t) ((t *) XMLArrayDelete(x, a, i, c))
+#define XMLARRAY_TRUNCATE(x,a,n) XMLArrayTruncate(x, a, n)
+
+/*
+ * Define XML setting property strings and constants early, so everyone can
+ * use the same names and their magic numbers (tinyids, flags).
+ */
+static const char js_ignoreComments_str[] = "ignoreComments";
+static const char js_ignoreProcessingInstructions_str[]
+ = "ignoreProcessingInstructions";
+static const char js_ignoreWhitespace_str[] = "ignoreWhitespace";
+static const char js_prettyPrinting_str[] = "prettyPrinting";
+static const char js_prettyIndent_str[] = "prettyIndent";
+
+/*
+ * NB: These XML static property tinyids must
+ * (a) not collide with the generic negative tinyids at the top of jsfun.c;
+ * (b) index their corresponding xml_static_props array elements.
+ * Don't change 'em!
+ */
+enum xml_static_tinyid {
+ XML_IGNORE_COMMENTS,
+ XML_IGNORE_PROCESSING_INSTRUCTIONS,
+ XML_IGNORE_WHITESPACE,
+ XML_PRETTY_PRINTING,
+ XML_PRETTY_INDENT
+};
+
+static JSBool
+xml_setting_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setting_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ uint8 flag;
+
+ JS_ASSERT(JSVAL_IS_INT(id));
+
+ flag = JS_BIT(JSVAL_TO_INT(id));
+ if (js_ValueToBoolean(*vp))
+ cx->xmlSettingFlags |= flag;
+ else
+ cx->xmlSettingFlags &= ~flag;
+ return JS_TRUE;
+}
+
+static JSPropertySpec xml_static_props[] = {
+ {js_ignoreComments_str, XML_IGNORE_COMMENTS, JSPROP_PERMANENT,
+ xml_setting_getter, xml_setting_setter},
+ {js_ignoreProcessingInstructions_str,
+ XML_IGNORE_PROCESSING_INSTRUCTIONS, JSPROP_PERMANENT,
+ xml_setting_getter, xml_setting_setter},
+ {js_ignoreWhitespace_str, XML_IGNORE_WHITESPACE, JSPROP_PERMANENT,
+ xml_setting_getter, xml_setting_setter},
+ {js_prettyPrinting_str, XML_PRETTY_PRINTING, JSPROP_PERMANENT,
+ xml_setting_getter, xml_setting_setter},
+ {js_prettyIndent_str, XML_PRETTY_INDENT, JSPROP_PERMANENT,
+ xml_setting_getter, NULL},
+ {0,0,0,0,0}
+};
+
+/* Derive cx->xmlSettingFlags bits from xml_static_props tinyids. */
+#define XSF_IGNORE_COMMENTS JS_BIT(XML_IGNORE_COMMENTS)
+#define XSF_IGNORE_PROCESSING_INSTRUCTIONS \
+ JS_BIT(XML_IGNORE_PROCESSING_INSTRUCTIONS)
+#define XSF_IGNORE_WHITESPACE JS_BIT(XML_IGNORE_WHITESPACE)
+#define XSF_PRETTY_PRINTING JS_BIT(XML_PRETTY_PRINTING)
+#define XSF_CACHE_VALID JS_BIT(XML_PRETTY_INDENT)
+
+/*
+ * Extra, unrelated but necessarily disjoint flag used by ParseNodeToXML.
+ * This flag means a couple of things:
+ *
+ * - The top JSXML created for a parse tree must have an object owning it.
+ *
+ * - That the default namespace normally inherited from the temporary
+ * <parent xmlns='...'> tag that wraps a runtime-concatenated XML source
+ * string must, in the case of a precompiled XML object tree, inherit via
+ * ad-hoc code in ParseNodeToXML.
+ *
+ * Because of the second purpose, we name this flag XSF_PRECOMPILED_ROOT.
+ */
+#define XSF_PRECOMPILED_ROOT (XSF_CACHE_VALID << 1)
+
+/* Macros for special-casing xml:, xmlns= and xmlns:foo= in ParseNodeToQName. */
+#define IS_XML(str) \
+ (JSSTRING_LENGTH(str) == 3 && IS_XML_CHARS(JSSTRING_CHARS(str)))
+
+#define IS_XMLNS(str) \
+ (JSSTRING_LENGTH(str) == 5 && IS_XMLNS_CHARS(JSSTRING_CHARS(str)))
+
+#define IS_XML_CHARS(chars) \
+ (JS_TOLOWER((chars)[0]) == 'x' && \
+ JS_TOLOWER((chars)[1]) == 'm' && \
+ JS_TOLOWER((chars)[2]) == 'l')
+
+#define HAS_NS_AFTER_XML(chars) \
+ (JS_TOLOWER((chars)[3]) == 'n' && \
+ JS_TOLOWER((chars)[4]) == 's')
+
+#define IS_XMLNS_CHARS(chars) \
+ (IS_XML_CHARS(chars) && HAS_NS_AFTER_XML(chars))
+
+#define STARTS_WITH_XML(chars,length) \
+ (length >= 3 && IS_XML_CHARS(chars))
+
+static const char xml_namespace_str[] = "http://www.w3.org/XML/1998/namespace";
+static const char xmlns_namespace_str[] = "http://www.w3.org/2000/xmlns/";
+
+static JSObject *
+ParseNodeToQName(JSContext *cx, JSParseContext *pc, JSParseNode *pn,
+ JSXMLArray *inScopeNSes, JSBool isAttributeName)
+{
+ JSString *str, *uri, *prefix, *localName;
+ size_t length, offset;
+ const jschar *start, *limit, *colon;
+ uint32 n;
+ JSObject *ns;
+ JSString *nsprefix;
+
+ JS_ASSERT(pn->pn_arity == PN_NULLARY);
+ str = ATOM_TO_STRING(pn->pn_atom);
+ JSSTRING_CHARS_AND_LENGTH(str, start, length);
+ JS_ASSERT(length != 0 && *start != '@');
+ JS_ASSERT(length != 1 || *start != '*');
+
+ uri = cx->runtime->emptyString;
+ limit = start + length;
+ colon = js_strchr_limit(start, ':', limit);
+ if (colon) {
+ offset = PTRDIFF(colon, start, jschar);
+ prefix = js_NewDependentString(cx, str, 0, offset);
+ if (!prefix)
+ return NULL;
+
+ if (STARTS_WITH_XML(start, offset)) {
+ if (offset == 3) {
+ uri = JS_InternString(cx, xml_namespace_str);
+ if (!uri)
+ return NULL;
+ } else if (offset == 5 && HAS_NS_AFTER_XML(start)) {
+ uri = JS_InternString(cx, xmlns_namespace_str);
+ if (!uri)
+ return NULL;
+ } else {
+ uri = NULL;
+ }
+ } else {
+ uri = NULL;
+ n = inScopeNSes->length;
+ while (n != 0) {
+ --n;
+ ns = XMLARRAY_MEMBER(inScopeNSes, n, JSObject);
+ nsprefix = GetPrefix(ns);
+ if (nsprefix && js_EqualStrings(nsprefix, prefix)) {
+ uri = GetURI(ns);
+ break;
+ }
+ }
+ }
+
+ if (!uri) {
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn,
+ JSREPORT_ERROR,
+ JSMSG_BAD_XML_NAMESPACE,
+ js_ValueToPrintableString(cx,
+ STRING_TO_JSVAL(prefix)));
+ return NULL;
+ }
+
+ localName = js_NewStringCopyN(cx, colon + 1, length - (offset + 1));
+ if (!localName)
+ return NULL;
+ } else {
+ if (isAttributeName) {
+ /*
+ * An unprefixed attribute is not in any namespace, so set prefix
+ * as well as uri to the empty string.
+ */
+ prefix = uri;
+ } else {
+ /*
+ * Loop from back to front looking for the closest declared default
+ * namespace.
+ */
+ n = inScopeNSes->length;
+ while (n != 0) {
+ --n;
+ ns = XMLARRAY_MEMBER(inScopeNSes, n, JSObject);
+ nsprefix = GetPrefix(ns);
+ if (!nsprefix || IS_EMPTY(nsprefix)) {
+ uri = GetURI(ns);
+ break;
+ }
+ }
+ prefix = IS_EMPTY(uri) ? cx->runtime->emptyString : NULL;
+ }
+ localName = str;
+ }
+
+ return NewXMLQName(cx, uri, prefix, localName);
+}
+
+static JSString *
+ChompXMLWhitespace(JSContext *cx, JSString *str)
+{
+ size_t length, newlength, offset;
+ const jschar *cp, *start, *end;
+ jschar c;
+
+ JSSTRING_CHARS_AND_LENGTH(str, start, length);
+ for (cp = start, end = cp + length; cp < end; cp++) {
+ c = *cp;
+ if (!JS_ISXMLSPACE(c))
+ break;
+ }
+ while (end > cp) {
+ c = end[-1];
+ if (!JS_ISXMLSPACE(c))
+ break;
+ --end;
+ }
+ newlength = PTRDIFF(end, cp, jschar);
+ if (newlength == length)
+ return str;
+ offset = PTRDIFF(cp, start, jschar);
+ return js_NewDependentString(cx, str, offset, newlength);
+}
+
+static JSXML *
+ParseNodeToXML(JSContext *cx, JSParseContext *pc, JSParseNode *pn,
+ JSXMLArray *inScopeNSes, uintN flags)
+{
+ JSXML *xml, *kid, *attr, *attrj;
+ JSString *str;
+ uint32 length, n, i, j;
+ JSParseNode *pn2, *pn3, *head, **pnp;
+ JSObject *ns;
+ JSObject *qn, *attrjqn;
+ JSXMLClass xml_class;
+ int stackDummy;
+
+ if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) {
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn, JSREPORT_ERROR,
+ JSMSG_OVER_RECURSED);
+ return NULL;
+ }
+
+#define PN2X_SKIP_CHILD ((JSXML *) 1)
+
+ /*
+ * Cases return early to avoid common code that gets an outermost xml's
+ * object, which protects GC-things owned by xml and its descendants from
+ * garbage collection.
+ */
+ xml = NULL;
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+ switch (pn->pn_type) {
+ case TOK_XMLELEM:
+ length = inScopeNSes->length;
+ pn2 = pn->pn_head;
+ xml = ParseNodeToXML(cx, pc, pn2, inScopeNSes, flags);
+ if (!xml)
+ goto fail;
+
+ flags &= ~XSF_PRECOMPILED_ROOT;
+ n = pn->pn_count;
+ JS_ASSERT(n >= 2);
+ n -= 2;
+ if (!XMLArraySetCapacity(cx, &xml->xml_kids, n))
+ goto fail;
+
+ i = 0;
+ while ((pn2 = pn2->pn_next) != NULL) {
+ if (!pn2->pn_next) {
+ /* Don't append the end tag! */
+ JS_ASSERT(pn2->pn_type == TOK_XMLETAGO);
+ break;
+ }
+
+ if ((flags & XSF_IGNORE_WHITESPACE) &&
+ n > 1 && pn2->pn_type == TOK_XMLSPACE) {
+ --n;
+ continue;
+ }
+
+ kid = ParseNodeToXML(cx, pc, pn2, inScopeNSes, flags);
+ if (kid == PN2X_SKIP_CHILD) {
+ --n;
+ continue;
+ }
+
+ if (!kid)
+ goto fail;
+
+ /* Store kid in xml right away, to protect it from GC. */
+ XMLARRAY_SET_MEMBER(&xml->xml_kids, i, kid);
+ kid->parent = xml;
+ ++i;
+
+ /* XXX where is this documented in an XML spec, or in E4X? */
+ if ((flags & XSF_IGNORE_WHITESPACE) &&
+ n > 1 && kid->xml_class == JSXML_CLASS_TEXT) {
+ str = ChompXMLWhitespace(cx, kid->xml_value);
+ if (!str)
+ goto fail;
+ kid->xml_value = str;
+ }
+ }
+
+ JS_ASSERT(i == n);
+ if (n < pn->pn_count - 2)
+ XMLArrayTrim(&xml->xml_kids);
+ XMLARRAY_TRUNCATE(cx, inScopeNSes, length);
+ break;
+
+ case TOK_XMLLIST:
+ xml = js_NewXML(cx, JSXML_CLASS_LIST);
+ if (!xml)
+ goto fail;
+
+ n = pn->pn_count;
+ if (!XMLArraySetCapacity(cx, &xml->xml_kids, n))
+ goto fail;
+
+ i = 0;
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ /*
+ * Always ignore insignificant whitespace in lists -- we shouldn't
+ * condition this on an XML.ignoreWhitespace setting when the list
+ * constructor is XMLList (note XML/XMLList unification hazard).
+ */
+ if (pn2->pn_type == TOK_XMLSPACE) {
+ --n;
+ continue;
+ }
+
+ kid = ParseNodeToXML(cx, pc, pn2, inScopeNSes, flags);
+ if (kid == PN2X_SKIP_CHILD) {
+ --n;
+ continue;
+ }
+
+ if (!kid)
+ goto fail;
+
+ XMLARRAY_SET_MEMBER(&xml->xml_kids, i, kid);
+ ++i;
+ }
+
+ if (n < pn->pn_count)
+ XMLArrayTrim(&xml->xml_kids);
+ break;
+
+ case TOK_XMLSTAGO:
+ case TOK_XMLPTAGC:
+ length = inScopeNSes->length;
+ pn2 = pn->pn_head;
+ JS_ASSERT(pn2->pn_type == TOK_XMLNAME);
+ if (pn2->pn_arity == PN_LIST)
+ goto syntax;
+
+ xml = js_NewXML(cx, JSXML_CLASS_ELEMENT);
+ if (!xml)
+ goto fail;
+
+ /* First pass: check syntax and process namespace declarations. */
+ JS_ASSERT(pn->pn_count >= 1);
+ n = pn->pn_count - 1;
+ pnp = &pn2->pn_next;
+ head = *pnp;
+ while ((pn2 = *pnp) != NULL) {
+ size_t length;
+ const jschar *chars;
+
+ if (pn2->pn_type != TOK_XMLNAME || pn2->pn_arity != PN_NULLARY)
+ goto syntax;
+
+ /* Enforce "Well-formedness constraint: Unique Att Spec". */
+ for (pn3 = head; pn3 != pn2; pn3 = pn3->pn_next->pn_next) {
+ if (pn3->pn_atom == pn2->pn_atom) {
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn2,
+ JSREPORT_ERROR,
+ JSMSG_DUPLICATE_XML_ATTR,
+ js_ValueToPrintableString(cx,
+ ATOM_KEY(pn2->pn_atom)));
+ goto fail;
+ }
+ }
+
+ str = ATOM_TO_STRING(pn2->pn_atom);
+ pn2 = pn2->pn_next;
+ JS_ASSERT(pn2);
+ if (pn2->pn_type != TOK_XMLATTR)
+ goto syntax;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ if (length >= 5 &&
+ IS_XMLNS_CHARS(chars) &&
+ (length == 5 || chars[5] == ':')) {
+ JSString *uri, *prefix;
+
+ uri = ATOM_TO_STRING(pn2->pn_atom);
+ if (length == 5) {
+ /* 10.3.2.1. Step 6(h)(i)(1)(a). */
+ prefix = cx->runtime->emptyString;
+ } else {
+ prefix = js_NewStringCopyN(cx, chars + 6, length - 6);
+ if (!prefix)
+ goto fail;
+ }
+
+ /*
+ * Once the new ns is appended to xml->xml_namespaces, it is
+ * protected from GC by the object that owns xml -- which is
+ * either xml->object if outermost, or the object owning xml's
+ * oldest ancestor if !outermost.
+ */
+ ns = NewXMLNamespace(cx, prefix, uri, JS_TRUE);
+ if (!ns)
+ goto fail;
+
+ /*
+ * Don't add a namespace that's already in scope. If someone
+ * extracts a child property from its parent via [[Get]], then
+ * we enforce the invariant, noted many times in ECMA-357, that
+ * the child's namespaces form a possibly-improper superset of
+ * its ancestors' namespaces.
+ */
+ if (!XMLARRAY_HAS_MEMBER(inScopeNSes, ns, namespace_identity)) {
+ if (!XMLARRAY_APPEND(cx, inScopeNSes, ns) ||
+ !XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns)) {
+ goto fail;
+ }
+ }
+
+ JS_ASSERT(n >= 2);
+ n -= 2;
+ *pnp = pn2->pn_next;
+ /* XXXbe recycle pn2 */
+ continue;
+ }
+
+ pnp = &pn2->pn_next;
+ }
+
+ /*
+ * If called from js_ParseNodeToXMLObject, emulate the effect of the
+ * <parent xmlns='%s'>...</parent> wrapping done by "ToXML Applied to
+ * the String Type" (ECMA-357 10.3.1).
+ */
+ if (flags & XSF_PRECOMPILED_ROOT) {
+ JS_ASSERT(length >= 1);
+ ns = XMLARRAY_MEMBER(inScopeNSes, 0, JSObject);
+ JS_ASSERT(!XMLARRAY_HAS_MEMBER(&xml->xml_namespaces, ns,
+ namespace_identity));
+ ns = NewXMLNamespace(cx, GetPrefix(ns), GetURI(ns), JS_FALSE);
+ if (!ns)
+ goto fail;
+ if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns))
+ goto fail;
+ }
+ XMLArrayTrim(&xml->xml_namespaces);
+
+ /* Second pass: process tag name and attributes, using namespaces. */
+ pn2 = pn->pn_head;
+ qn = ParseNodeToQName(cx, pc, pn2, inScopeNSes, JS_FALSE);
+ if (!qn)
+ goto fail;
+ xml->name = qn;
+
+ JS_ASSERT((n & 1) == 0);
+ n >>= 1;
+ if (!XMLArraySetCapacity(cx, &xml->xml_attrs, n))
+ goto fail;
+
+ for (i = 0; (pn2 = pn2->pn_next) != NULL; i++) {
+ qn = ParseNodeToQName(cx, pc, pn2, inScopeNSes, JS_TRUE);
+ if (!qn) {
+ xml->xml_attrs.length = i;
+ goto fail;
+ }
+
+ /*
+ * Enforce "Well-formedness constraint: Unique Att Spec", part 2:
+ * this time checking local name and namespace URI.
+ */
+ for (j = 0; j < i; j++) {
+ attrj = XMLARRAY_MEMBER(&xml->xml_attrs, j, JSXML);
+ attrjqn = attrj->name;
+ if (js_EqualStrings(GetURI(attrjqn), GetURI(qn)) &&
+ js_EqualStrings(GetLocalName(attrjqn), GetLocalName(qn))) {
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn2,
+ JSREPORT_ERROR,
+ JSMSG_DUPLICATE_XML_ATTR,
+ js_ValueToPrintableString(cx,
+ ATOM_KEY(pn2->pn_atom)));
+ goto fail;
+ }
+ }
+
+ pn2 = pn2->pn_next;
+ JS_ASSERT(pn2);
+ JS_ASSERT(pn2->pn_type == TOK_XMLATTR);
+
+ attr = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE);
+ if (!attr)
+ goto fail;
+
+ XMLARRAY_SET_MEMBER(&xml->xml_attrs, i, attr);
+ attr->parent = xml;
+ attr->name = qn;
+ attr->xml_value = ATOM_TO_STRING(pn2->pn_atom);
+ }
+
+ /* Point tag closes its own namespace scope. */
+ if (pn->pn_type == TOK_XMLPTAGC)
+ XMLARRAY_TRUNCATE(cx, inScopeNSes, length);
+ break;
+
+ case TOK_XMLSPACE:
+ case TOK_XMLTEXT:
+ case TOK_XMLCDATA:
+ case TOK_XMLCOMMENT:
+ case TOK_XMLPI:
+ str = ATOM_TO_STRING(pn->pn_atom);
+ qn = NULL;
+ if (pn->pn_type == TOK_XMLCOMMENT) {
+ if (flags & XSF_IGNORE_COMMENTS)
+ goto skip_child;
+ xml_class = JSXML_CLASS_COMMENT;
+ } else if (pn->pn_type == TOK_XMLPI) {
+ if (IS_XML(str)) {
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn,
+ JSREPORT_ERROR,
+ JSMSG_RESERVED_ID,
+ js_ValueToPrintableString(cx,
+ STRING_TO_JSVAL(str)));
+ goto fail;
+ }
+
+ if (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS)
+ goto skip_child;
+
+ qn = ParseNodeToQName(cx, pc, pn, inScopeNSes, JS_FALSE);
+ if (!qn)
+ goto fail;
+
+ str = pn->pn_atom2
+ ? ATOM_TO_STRING(pn->pn_atom2)
+ : cx->runtime->emptyString;
+ xml_class = JSXML_CLASS_PROCESSING_INSTRUCTION;
+ } else {
+ /* CDATA section content, or element text. */
+ xml_class = JSXML_CLASS_TEXT;
+ }
+
+ xml = js_NewXML(cx, xml_class);
+ if (!xml)
+ goto fail;
+ xml->name = qn;
+ if (pn->pn_type == TOK_XMLSPACE)
+ xml->xml_flags |= XMLF_WHITESPACE_TEXT;
+ xml->xml_value = str;
+ break;
+
+ default:
+ goto syntax;
+ }
+
+ js_LeaveLocalRootScopeWithResult(cx, (jsval) xml);
+ if ((flags & XSF_PRECOMPILED_ROOT) && !js_GetXMLObject(cx, xml))
+ return NULL;
+ return xml;
+
+skip_child:
+ js_LeaveLocalRootScope(cx);
+ return PN2X_SKIP_CHILD;
+
+#undef PN2X_SKIP_CHILD
+
+syntax:
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn, JSREPORT_ERROR,
+ JSMSG_BAD_XML_MARKUP);
+fail:
+ js_LeaveLocalRootScope(cx);
+ return NULL;
+}
+
+/*
+ * XML helper, object-ops, and library functions. We start with the helpers,
+ * in ECMA-357 order, but merging XML (9.1) and XMLList (9.2) helpers.
+ */
+static JSBool
+GetXMLSetting(JSContext *cx, const char *name, jsval *vp)
+{
+ jsval v;
+
+ if (!js_FindClassObject(cx, NULL, INT_TO_JSID(JSProto_XML), &v))
+ return JS_FALSE;
+ if (!VALUE_IS_FUNCTION(cx, v)) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ return JS_GetProperty(cx, JSVAL_TO_OBJECT(v), name, vp);
+}
+
+static JSBool
+FillSettingsCache(JSContext *cx)
+{
+ int i;
+ const char *name;
+ jsval v;
+
+ /* Note: XML_PRETTY_INDENT is not a boolean setting. */
+ for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) {
+ name = xml_static_props[i].name;
+ if (!GetXMLSetting(cx, name, &v))
+ return JS_FALSE;
+ if (js_ValueToBoolean(v))
+ cx->xmlSettingFlags |= JS_BIT(i);
+ else
+ cx->xmlSettingFlags &= ~JS_BIT(i);
+ }
+
+ cx->xmlSettingFlags |= XSF_CACHE_VALID;
+ return JS_TRUE;
+}
+
+static JSBool
+GetBooleanXMLSetting(JSContext *cx, const char *name, JSBool *bp)
+{
+ int i;
+
+ if (!(cx->xmlSettingFlags & XSF_CACHE_VALID) && !FillSettingsCache(cx))
+ return JS_FALSE;
+
+ for (i = 0; xml_static_props[i].name; i++) {
+ if (!strcmp(xml_static_props[i].name, name)) {
+ *bp = (cx->xmlSettingFlags & JS_BIT(i)) != 0;
+ return JS_TRUE;
+ }
+ }
+ *bp = JS_FALSE;
+ return JS_TRUE;
+}
+
+static JSBool
+GetUint32XMLSetting(JSContext *cx, const char *name, uint32 *uip)
+{
+ jsval v;
+
+ return GetXMLSetting(cx, name, &v) && JS_ValueToECMAUint32(cx, v, uip);
+}
+
+static JSBool
+GetXMLSettingFlags(JSContext *cx, uintN *flagsp)
+{
+ JSBool flag;
+
+ /* Just get the first flag to validate the setting flags cache. */
+ if (!GetBooleanXMLSetting(cx, js_ignoreComments_str, &flag))
+ return JS_FALSE;
+ *flagsp = cx->xmlSettingFlags;
+ return JS_TRUE;
+}
+
+static JSXML *
+ParseXMLSource(JSContext *cx, JSString *src)
+{
+ jsval nsval;
+ JSString *uri;
+ size_t urilen, srclen, length, offset, dstlen;
+ jschar *chars;
+ const jschar *srcp, *endp;
+ JSXML *xml;
+ JSParseContext pc;
+ const char *filename;
+ uintN lineno;
+ JSStackFrame *fp;
+ JSOp op;
+ JSParseNode *pn;
+ JSXMLArray nsarray;
+ uintN flags;
+
+ static const char prefix[] = "<parent xmlns=\"";
+ static const char middle[] = "\">";
+ static const char suffix[] = "</parent>";
+
+#define constrlen(constr) (sizeof(constr) - 1)
+
+ if (!js_GetDefaultXMLNamespace(cx, &nsval))
+ return NULL;
+ uri = GetURI(JSVAL_TO_OBJECT(nsval));
+ uri = js_EscapeAttributeValue(cx, uri, JS_FALSE);
+
+ urilen = JSSTRING_LENGTH(uri);
+ srclen = JSSTRING_LENGTH(src);
+ length = constrlen(prefix) + urilen + constrlen(middle) + srclen +
+ constrlen(suffix);
+
+ chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!chars)
+ return NULL;
+
+ dstlen = length;
+ js_InflateStringToBuffer(cx, prefix, constrlen(prefix), chars, &dstlen);
+ offset = dstlen;
+ js_strncpy(chars + offset, JSSTRING_CHARS(uri), urilen);
+ offset += urilen;
+ dstlen = length - offset + 1;
+ js_InflateStringToBuffer(cx, middle, constrlen(middle), chars + offset,
+ &dstlen);
+ offset += dstlen;
+ srcp = JSSTRING_CHARS(src);
+ js_strncpy(chars + offset, srcp, srclen);
+ offset += srclen;
+ dstlen = length - offset + 1;
+ js_InflateStringToBuffer(cx, suffix, constrlen(suffix), chars + offset,
+ &dstlen);
+ chars [offset + dstlen] = 0;
+
+ xml = NULL;
+ for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
+ JS_ASSERT(!fp->script);
+ filename = NULL;
+ lineno = 1;
+ if (fp) {
+ op = (JSOp) *fp->regs->pc;
+ if (op == JSOP_TOXML || op == JSOP_TOXMLLIST) {
+ filename = fp->script->filename;
+ lineno = js_FramePCToLineNumber(cx, fp);
+ for (endp = srcp + srclen; srcp < endp; srcp++) {
+ if (*srcp == '\n')
+ --lineno;
+ }
+ }
+ }
+
+ if (!js_InitParseContext(cx, &pc, NULL, NULL, chars, length, NULL,
+ filename, lineno))
+ goto out;
+ pn = js_ParseXMLText(cx, cx->fp->scopeChain, &pc, JS_FALSE);
+ if (pn && XMLArrayInit(cx, &nsarray, 1)) {
+ if (GetXMLSettingFlags(cx, &flags))
+ xml = ParseNodeToXML(cx, &pc, pn, &nsarray, flags);
+
+ XMLArrayFinish(cx, &nsarray);
+ }
+ js_FinishParseContext(cx, &pc);
+
+out:
+ JS_free(cx, chars);
+ return xml;
+
+#undef constrlen
+}
+
+/*
+ * Errata in 10.3.1, 10.4.1, and 13.4.4.24 (at least).
+ *
+ * 10.3.1 Step 6(a) fails to NOTE that implementations that do not enforce
+ * the constraint:
+ *
+ * for all x belonging to XML:
+ * x.[[InScopeNamespaces]] >= x.[[Parent]].[[InScopeNamespaces]]
+ *
+ * must union x.[[InScopeNamespaces]] into x[0].[[InScopeNamespaces]] here
+ * (in new sub-step 6(a), renumbering the others to (b) and (c)).
+ *
+ * Same goes for 10.4.1 Step 7(a).
+ *
+ * In order for XML.prototype.namespaceDeclarations() to work correctly, the
+ * default namespace thereby unioned into x[0].[[InScopeNamespaces]] must be
+ * flagged as not declared, so that 13.4.4.24 Step 8(a) can exclude all such
+ * undeclared namespaces associated with x not belonging to ancestorNS.
+ */
+static JSXML *
+OrphanXMLChild(JSContext *cx, JSXML *xml, uint32 i)
+{
+ JSObject *ns;
+
+ ns = XMLARRAY_MEMBER(&xml->xml_namespaces, 0, JSObject);
+ xml = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (!ns || !xml)
+ return xml;
+ if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns))
+ return NULL;
+ ns->fslots[JSSLOT_DECLARED] = JSVAL_VOID;
+ }
+ xml->parent = NULL;
+ return xml;
+}
+
+static JSObject *
+ToXML(JSContext *cx, jsval v)
+{
+ JSObject *obj;
+ JSXML *xml;
+ JSClass *clasp;
+ JSString *str;
+ uint32 length;
+
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
+ goto bad;
+ } else {
+ obj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, obj)) {
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ if (xml->xml_kids.length != 1)
+ goto bad;
+ xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (xml) {
+ JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST);
+ return js_GetXMLObject(cx, xml);
+ }
+ }
+ return obj;
+ }
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp->flags & JSCLASS_DOCUMENT_OBSERVER) {
+ JS_ASSERT(0);
+ }
+
+ if (clasp != &js_StringClass &&
+ clasp != &js_NumberClass &&
+ clasp != &js_BooleanClass) {
+ goto bad;
+ }
+ }
+
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return NULL;
+ if (IS_EMPTY(str)) {
+ length = 0;
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ xml = NULL;
+#endif
+ } else {
+ xml = ParseXMLSource(cx, str);
+ if (!xml)
+ return NULL;
+ length = JSXML_LENGTH(xml);
+ }
+
+ if (length == 0) {
+ obj = js_NewXMLObject(cx, JSXML_CLASS_TEXT);
+ if (!obj)
+ return NULL;
+ } else if (length == 1) {
+ xml = OrphanXMLChild(cx, xml, 0);
+ if (!xml)
+ return NULL;
+ obj = js_GetXMLObject(cx, xml);
+ if (!obj)
+ return NULL;
+ } else {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+ return obj;
+
+bad:
+ js_ReportValueError(cx, JSMSG_BAD_XML_CONVERSION,
+ JSDVG_IGNORE_STACK, v, NULL);
+ return NULL;
+}
+
+static JSBool
+Append(JSContext *cx, JSXML *list, JSXML *kid);
+
+static JSObject *
+ToXMLList(JSContext *cx, jsval v)
+{
+ JSObject *obj, *listobj;
+ JSXML *xml, *list, *kid;
+ JSClass *clasp;
+ JSString *str;
+ uint32 i, length;
+
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
+ goto bad;
+ } else {
+ obj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, obj)) {
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!listobj)
+ return NULL;
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ if (!Append(cx, list, xml))
+ return NULL;
+ return listobj;
+ }
+ return obj;
+ }
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp->flags & JSCLASS_DOCUMENT_OBSERVER) {
+ JS_ASSERT(0);
+ }
+
+ if (clasp != &js_StringClass &&
+ clasp != &js_NumberClass &&
+ clasp != &js_BooleanClass) {
+ goto bad;
+ }
+ }
+
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return NULL;
+ if (IS_EMPTY(str)) {
+ xml = NULL;
+ length = 0;
+ } else {
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+ xml = ParseXMLSource(cx, str);
+ if (!xml) {
+ js_LeaveLocalRootScope(cx);
+ return NULL;
+ }
+ length = JSXML_LENGTH(xml);
+ }
+
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (listobj) {
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ for (i = 0; i < length; i++) {
+ kid = OrphanXMLChild(cx, xml, i);
+ if (!kid || !Append(cx, list, kid)) {
+ listobj = NULL;
+ break;
+ }
+ }
+ }
+
+ if (xml)
+ js_LeaveLocalRootScopeWithResult(cx, (jsval) listobj);
+ return listobj;
+
+bad:
+ js_ReportValueError(cx, JSMSG_BAD_XMLLIST_CONVERSION,
+ JSDVG_IGNORE_STACK, v, NULL);
+ return NULL;
+}
+
+/*
+ * ECMA-357 10.2.1 Steps 5-7 pulled out as common subroutines of XMLToXMLString
+ * and their library-public js_* counterparts. The guts of MakeXMLCDataString,
+ * MakeXMLCommentString, and MakeXMLPIString are further factored into a common
+ * MakeXMLSpecialString subroutine.
+ *
+ * These functions take ownership of sb->base, if sb is non-null, in all cases
+ * of success or failure.
+ */
+static JSString *
+MakeXMLSpecialString(JSContext *cx, JSStringBuffer *sb,
+ JSString *str, JSString *str2,
+ const jschar *prefix, size_t prefixlength,
+ const jschar *suffix, size_t suffixlength)
+{
+ JSStringBuffer localSB;
+ size_t length, length2, newlength;
+ jschar *bp, *base;
+
+ if (!sb) {
+ sb = &localSB;
+ js_InitStringBuffer(sb);
+ }
+
+ length = JSSTRING_LENGTH(str);
+ length2 = str2 ? JSSTRING_LENGTH(str2) : 0;
+ newlength = STRING_BUFFER_OFFSET(sb) +
+ prefixlength + length + ((length2 != 0) ? 1 + length2 : 0) +
+ suffixlength;
+ bp = base = (jschar *)
+ JS_realloc(cx, sb->base, (newlength + 1) * sizeof(jschar));
+ if (!bp) {
+ js_FinishStringBuffer(sb);
+ return NULL;
+ }
+
+ bp += STRING_BUFFER_OFFSET(sb);
+ js_strncpy(bp, prefix, prefixlength);
+ bp += prefixlength;
+ js_strncpy(bp, JSSTRING_CHARS(str), length);
+ bp += length;
+ if (length2 != 0) {
+ *bp++ = (jschar) ' ';
+ js_strncpy(bp, JSSTRING_CHARS(str2), length2);
+ bp += length2;
+ }
+ js_strncpy(bp, suffix, suffixlength);
+ bp[suffixlength] = 0;
+
+ str = js_NewString(cx, base, newlength);
+ if (!str)
+ free(base);
+ return str;
+}
+
+static JSString *
+MakeXMLCDATAString(JSContext *cx, JSStringBuffer *sb, JSString *str)
+{
+ static const jschar cdata_prefix_ucNstr[] = {'<', '!', '[',
+ 'C', 'D', 'A', 'T', 'A',
+ '['};
+ static const jschar cdata_suffix_ucNstr[] = {']', ']', '>'};
+
+ return MakeXMLSpecialString(cx, sb, str, NULL,
+ cdata_prefix_ucNstr, 9,
+ cdata_suffix_ucNstr, 3);
+}
+
+static JSString *
+MakeXMLCommentString(JSContext *cx, JSStringBuffer *sb, JSString *str)
+{
+ static const jschar comment_prefix_ucNstr[] = {'<', '!', '-', '-'};
+ static const jschar comment_suffix_ucNstr[] = {'-', '-', '>'};
+
+ return MakeXMLSpecialString(cx, sb, str, NULL,
+ comment_prefix_ucNstr, 4,
+ comment_suffix_ucNstr, 3);
+}
+
+static JSString *
+MakeXMLPIString(JSContext *cx, JSStringBuffer *sb, JSString *name,
+ JSString *value)
+{
+ static const jschar pi_prefix_ucNstr[] = {'<', '?'};
+ static const jschar pi_suffix_ucNstr[] = {'?', '>'};
+
+ return MakeXMLSpecialString(cx, sb, name, value,
+ pi_prefix_ucNstr, 2,
+ pi_suffix_ucNstr, 2);
+}
+
+/*
+ * ECMA-357 10.2.1 17(d-g) pulled out into a common subroutine that appends
+ * equals, a double quote, an attribute value, and a closing double quote.
+ */
+static void
+AppendAttributeValue(JSContext *cx, JSStringBuffer *sb, JSString *valstr)
+{
+ js_AppendChar(sb, '=');
+ valstr = js_EscapeAttributeValue(cx, valstr, JS_TRUE);
+ if (!valstr) {
+ if (STRING_BUFFER_OK(sb)) {
+ free(sb->base);
+ sb->base = STRING_BUFFER_ERROR_BASE;
+ }
+ return;
+ }
+ js_AppendJSString(sb, valstr);
+}
+
+/*
+ * ECMA-357 10.2.1.1 EscapeElementValue helper method.
+ *
+ * This function takes ownership of sb->base, if sb is non-null, in all cases
+ * of success or failure.
+ */
+static JSString *
+EscapeElementValue(JSContext *cx, JSStringBuffer *sb, JSString *str)
+{
+ size_t length, newlength;
+ const jschar *cp, *start, *end;
+ jschar c;
+
+ JSSTRING_CHARS_AND_LENGTH(str, start, length);
+ newlength = length;
+ for (cp = start, end = cp + length; cp < end; cp++) {
+ c = *cp;
+ if (c == '<' || c == '>')
+ newlength += 3;
+ else if (c == '&')
+ newlength += 4;
+
+ if (newlength < length) {
+ js_ReportAllocationOverflow(cx);
+ return NULL;
+ }
+ }
+ if ((sb && STRING_BUFFER_OFFSET(sb) != 0) || newlength > length) {
+ JSStringBuffer localSB;
+ if (!sb) {
+ sb = &localSB;
+ js_InitStringBuffer(sb);
+ }
+ if (!sb->grow(sb, newlength)) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ for (cp = start; cp < end; cp++) {
+ c = *cp;
+ if (c == '<')
+ js_AppendCString(sb, js_lt_entity_str);
+ else if (c == '>')
+ js_AppendCString(sb, js_gt_entity_str);
+ else if (c == '&')
+ js_AppendCString(sb, js_amp_entity_str);
+ else
+ js_AppendChar(sb, c);
+ }
+ JS_ASSERT(STRING_BUFFER_OK(sb));
+ str = js_NewString(cx, sb->base, STRING_BUFFER_OFFSET(sb));
+ if (!str)
+ js_FinishStringBuffer(sb);
+ }
+ return str;
+}
+
+/*
+ * ECMA-357 10.2.1.2 EscapeAttributeValue helper method.
+ * This function takes ownership of sb->base, if sb is non-null, in all cases.
+ */
+static JSString *
+EscapeAttributeValue(JSContext *cx, JSStringBuffer *sb, JSString *str,
+ JSBool quote)
+{
+ size_t length, newlength;
+ const jschar *cp, *start, *end;
+ jschar c;
+
+ JSSTRING_CHARS_AND_LENGTH(str, start, length);
+ newlength = length + (quote ? 2 : 0);
+ for (cp = start, end = cp + length; cp < end; cp++) {
+ c = *cp;
+ if (c == '"')
+ newlength += 5;
+ else if (c == '<')
+ newlength += 3;
+ else if (c == '&' || c == '\n' || c == '\r' || c == '\t')
+ newlength += 4;
+
+ if (newlength < length) {
+ js_ReportAllocationOverflow(cx);
+ return NULL;
+ }
+ }
+ if ((sb && STRING_BUFFER_OFFSET(sb) != 0) || newlength > length) {
+ JSStringBuffer localSB;
+ if (!sb) {
+ sb = &localSB;
+ js_InitStringBuffer(sb);
+ }
+ if (!sb->grow(sb, newlength)) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ if (quote)
+ js_AppendChar(sb, '"');
+ for (cp = start; cp < end; cp++) {
+ c = *cp;
+ if (c == '"')
+ js_AppendCString(sb, js_quot_entity_str);
+ else if (c == '<')
+ js_AppendCString(sb, js_lt_entity_str);
+ else if (c == '&')
+ js_AppendCString(sb, js_amp_entity_str);
+ else if (c == '\n')
+ js_AppendCString(sb, "&#xA;");
+ else if (c == '\r')
+ js_AppendCString(sb, "&#xD;");
+ else if (c == '\t')
+ js_AppendCString(sb, "&#x9;");
+ else
+ js_AppendChar(sb, c);
+ }
+ if (quote)
+ js_AppendChar(sb, '"');
+ JS_ASSERT(STRING_BUFFER_OK(sb));
+ str = js_NewString(cx, sb->base, STRING_BUFFER_OFFSET(sb));
+ if (!str)
+ js_FinishStringBuffer(sb);
+ }
+ return str;
+}
+
+/* 13.3.5.4 [[GetNamespace]]([InScopeNamespaces]) */
+static JSObject *
+GetNamespace(JSContext *cx, JSObject *qn, const JSXMLArray *inScopeNSes)
+{
+ JSString *uri, *prefix, *nsprefix;
+ JSObject *match, *ns;
+ uint32 i, n;
+ jsval argv[2];
+
+ uri = GetURI(qn);
+ prefix = GetPrefix(qn);
+ JS_ASSERT(uri);
+ if (!uri) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_XML_NAMESPACE,
+ prefix
+ ? js_ValueToPrintableString(cx,
+ STRING_TO_JSVAL(prefix))
+ : js_undefined_str);
+ return NULL;
+ }
+
+ /* Look for a matching namespace in inScopeNSes, if provided. */
+ match = NULL;
+ if (inScopeNSes) {
+ for (i = 0, n = inScopeNSes->length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(inScopeNSes, i, JSObject);
+ if (!ns)
+ continue;
+
+ /*
+ * Erratum, very tricky, and not specified in ECMA-357 13.3.5.4:
+ * If we preserve prefixes, we must match null prefix against
+ * an empty prefix of ns, in order to avoid generating redundant
+ * prefixed and default namespaces for cases such as:
+ *
+ * x = <t xmlns="http://foo.com"/>
+ * print(x.toXMLString());
+ *
+ * Per 10.3.2.1, the namespace attribute in t has an empty string
+ * prefix (*not* a null prefix), per 10.3.2.1 Step 6(h)(i)(1):
+ *
+ * 1. If the [local name] property of a is "xmlns"
+ * a. Map ns.prefix to the empty string
+ *
+ * But t's name has a null prefix in this implementation, meaning
+ * *undefined*, per 10.3.2.1 Step 6(c)'s NOTE (which refers to
+ * the http://www.w3.org/TR/xml-infoset/ spec, item 2.2.3, without
+ * saying how "no value" maps to an ECMA-357 value -- but it must
+ * map to the *undefined* prefix value).
+ *
+ * Since "" != undefined (or null, in the current implementation)
+ * the ECMA-357 spec will fail to match in [[GetNamespace]] called
+ * on t with argument {} U {(prefix="", uri="http://foo.com")}.
+ * This spec bug leads to ToXMLString results that duplicate the
+ * declared namespace.
+ */
+ if (js_EqualStrings(GetURI(ns), uri)) {
+ nsprefix = GetPrefix(ns);
+ if (nsprefix == prefix ||
+ ((nsprefix && prefix)
+ ? js_EqualStrings(nsprefix, prefix)
+ : IS_EMPTY(nsprefix ? nsprefix : prefix))) {
+ match = ns;
+ break;
+ }
+ }
+ }
+ }
+
+ /* If we didn't match, make a new namespace from qn. */
+ if (!match) {
+ argv[0] = prefix ? STRING_TO_JSVAL(prefix) : JSVAL_VOID;
+ argv[1] = STRING_TO_JSVAL(uri);
+ ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, NULL,
+ 2, argv);
+ if (!ns)
+ return NULL;
+ match = ns;
+ }
+ return match;
+}
+
+static JSString *
+GeneratePrefix(JSContext *cx, JSString *uri, JSXMLArray *decls)
+{
+ const jschar *cp, *start, *end;
+ size_t length, newlength, offset;
+ uint32 i, n, m, serial;
+ jschar *bp, *dp;
+ JSBool done;
+ JSObject *ns;
+ JSString *nsprefix, *prefix;
+
+ JS_ASSERT(!IS_EMPTY(uri));
+
+ /*
+ * If there are no *declared* namespaces, skip all collision detection and
+ * return a short prefix quickly; an example of such a situation:
+ *
+ * var x = <f/>;
+ * var n = new Namespace("http://example.com/");
+ * x.@n::att = "val";
+ * x.toXMLString();
+ *
+ * This is necessary for various log10 uses below to be valid.
+ */
+ if (decls->length == 0)
+ return JS_NewStringCopyZ(cx, "a");
+
+ /*
+ * Try peeling off the last filename suffix or pathname component till
+ * we have a valid XML name. This heuristic will prefer "xul" given
+ * ".../there.is.only.xul", "xbl" given ".../xbl", and "xbl2" given any
+ * likely URI of the form ".../xbl2/2005".
+ */
+ JSSTRING_CHARS_AND_END(uri, start, end);
+ cp = end;
+ while (--cp > start) {
+ if (*cp == '.' || *cp == '/' || *cp == ':') {
+ ++cp;
+ length = PTRDIFF(end, cp, jschar);
+ if (IsXMLName(cp, length) && !STARTS_WITH_XML(cp, length))
+ break;
+ end = --cp;
+ }
+ }
+ length = PTRDIFF(end, cp, jschar);
+
+ /*
+ * If the namespace consisted only of non-XML names or names that begin
+ * case-insensitively with "xml", arbitrarily create a prefix consisting
+ * of 'a's of size length (allowing dp-calculating code to work with or
+ * without this branch executing) plus the space for storing a hyphen and
+ * the serial number (avoiding reallocation if a collision happens).
+ */
+ bp = (jschar *) cp;
+ newlength = length;
+ if (STARTS_WITH_XML(cp, length) || !IsXMLName(cp, length)) {
+ newlength = length + 2 + (size_t) log10((double) decls->length);
+ bp = (jschar *)
+ JS_malloc(cx, (newlength + 1) * sizeof(jschar));
+ if (!bp)
+ return NULL;
+
+ bp[newlength] = 0;
+ for (i = 0; i < newlength; i++)
+ bp[i] = 'a';
+ }
+
+ /*
+ * Now search through decls looking for a collision. If we collide with
+ * an existing prefix, start tacking on a hyphen and a serial number.
+ */
+ serial = 0;
+ do {
+ done = JS_TRUE;
+ for (i = 0, n = decls->length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(decls, i, JSObject);
+ if (ns && (nsprefix = GetPrefix(ns)) &&
+ JSSTRING_LENGTH(nsprefix) == newlength &&
+ !memcmp(JSSTRING_CHARS(nsprefix), bp,
+ newlength * sizeof(jschar))) {
+ if (bp == cp) {
+ newlength = length + 2 + (size_t) log10((double) n);
+ bp = (jschar *)
+ JS_malloc(cx, (newlength + 1) * sizeof(jschar));
+ if (!bp)
+ return NULL;
+ js_strncpy(bp, cp, length);
+ }
+
+ ++serial;
+ JS_ASSERT(serial <= n);
+ dp = bp + length + 2 + (size_t) log10((double) serial);
+ *dp = 0;
+ for (m = serial; m != 0; m /= 10)
+ *--dp = (jschar)('0' + m % 10);
+ *--dp = '-';
+ JS_ASSERT(dp == bp + length);
+
+ done = JS_FALSE;
+ break;
+ }
+ }
+ } while (!done);
+
+ if (bp == cp) {
+ offset = PTRDIFF(cp, start, jschar);
+ prefix = js_NewDependentString(cx, uri, offset, length);
+ } else {
+ prefix = js_NewString(cx, bp, newlength);
+ if (!prefix)
+ JS_free(cx, bp);
+ }
+ return prefix;
+}
+
+static JSBool
+namespace_match(const void *a, const void *b)
+{
+ const JSObject *nsa = (const JSObject *) a;
+ const JSObject *nsb = (const JSObject *) b;
+ JSString *prefixa, *prefixb = GetPrefix(nsb);
+
+ if (prefixb) {
+ prefixa = GetPrefix(nsa);
+ return prefixa && js_EqualStrings(prefixa, prefixb);
+ }
+ return js_EqualStrings(GetURI(nsa), GetURI(nsb));
+}
+
+/* ECMA-357 10.2.1 and 10.2.2 */
+#define TO_SOURCE_FLAG 0x80000000
+
+static JSString *
+XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes,
+ uint32 indentLevel)
+{
+ JSBool pretty, indentKids;
+ JSStringBuffer sb;
+ JSString *str, *prefix, *kidstr, *nsuri;
+ JSXMLArrayCursor cursor;
+ uint32 i, n, nextIndentLevel;
+ JSXMLArray empty, decls, ancdecls;
+ JSObject *ns, *ns2;
+ JSXML *attr, *kid;
+
+ if (!GetBooleanXMLSetting(cx, js_prettyPrinting_str, &pretty))
+ return NULL;
+
+ js_InitStringBuffer(&sb);
+ if (pretty) {
+ js_RepeatChar(&sb, ' ', indentLevel & ~TO_SOURCE_FLAG);
+
+ if (!STRING_BUFFER_OK(&sb)) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ }
+ str = NULL;
+
+ switch (xml->xml_class) {
+ case JSXML_CLASS_TEXT:
+ /* Step 4. */
+ if (pretty) {
+ str = ChompXMLWhitespace(cx, xml->xml_value);
+ if (!str)
+ return NULL;
+ } else {
+ str = xml->xml_value;
+ }
+ return EscapeElementValue(cx, &sb, str);
+
+ case JSXML_CLASS_ATTRIBUTE:
+ /* Step 5. */
+ return EscapeAttributeValue(cx, &sb, xml->xml_value,
+ (indentLevel & TO_SOURCE_FLAG) != 0);
+
+ case JSXML_CLASS_COMMENT:
+ /* Step 6. */
+ return MakeXMLCommentString(cx, &sb, xml->xml_value);
+
+ case JSXML_CLASS_PROCESSING_INSTRUCTION:
+ /* Step 7. */
+ return MakeXMLPIString(cx, &sb, GetLocalName(xml->name),
+ xml->xml_value);
+
+ case JSXML_CLASS_LIST:
+ /* ECMA-357 10.2.2. */
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ i = 0;
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (pretty && i != 0)
+ js_AppendChar(&sb, '\n');
+
+ kidstr = XMLToXMLString(cx, kid, ancestorNSes, indentLevel);
+ if (!kidstr)
+ break;
+
+ js_AppendJSString(&sb, kidstr);
+ ++i;
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (kid)
+ goto list_out;
+
+ if (!sb.base)
+ return cx->runtime->emptyString;
+
+ if (!STRING_BUFFER_OK(&sb)) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+
+ str = js_NewString(cx, sb.base, STRING_BUFFER_OFFSET(&sb));
+ list_out:
+ if (!str && STRING_BUFFER_OK(&sb))
+ js_FinishStringBuffer(&sb);
+ return str;
+
+ default:;
+ }
+
+ /* After this point, control must flow through label out: to exit. */
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+
+ /* ECMA-357 10.2.1 step 8 onward: handle ToXMLString on an XML element. */
+ if (!ancestorNSes) {
+ XMLArrayInit(cx, &empty, 0);
+ ancestorNSes = &empty;
+ }
+ XMLArrayInit(cx, &decls, 0);
+ ancdecls.capacity = 0;
+
+ /* Clone in-scope namespaces not in ancestorNSes into decls. */
+ XMLArrayCursorInit(&cursor, &xml->xml_namespaces);
+ while ((ns = (JSObject *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (!IsDeclared(ns))
+ continue;
+ if (!XMLARRAY_HAS_MEMBER(ancestorNSes, ns, namespace_identity)) {
+ /* NOTE: may want to exclude unused namespaces here. */
+ ns2 = NewXMLNamespace(cx, GetPrefix(ns), GetURI(ns), JS_TRUE);
+ if (!ns2 || !XMLARRAY_APPEND(cx, &decls, ns2))
+ break;
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (ns)
+ goto out;
+
+ /*
+ * Union ancestorNSes and decls into ancdecls. Note that ancdecls does
+ * not own its member references. In the spec, ancdecls has no name, but
+ * is always written out as (AncestorNamespaces U namespaceDeclarations).
+ */
+ if (!XMLArrayInit(cx, &ancdecls, ancestorNSes->length + decls.length))
+ goto out;
+ for (i = 0, n = ancestorNSes->length; i < n; i++) {
+ ns2 = XMLARRAY_MEMBER(ancestorNSes, i, JSObject);
+ if (!ns2)
+ continue;
+ JS_ASSERT(!XMLARRAY_HAS_MEMBER(&decls, ns2, namespace_identity));
+ if (!XMLARRAY_APPEND(cx, &ancdecls, ns2))
+ goto out;
+ }
+ for (i = 0, n = decls.length; i < n; i++) {
+ ns2 = XMLARRAY_MEMBER(&decls, i, JSObject);
+ if (!ns2)
+ continue;
+ JS_ASSERT(!XMLARRAY_HAS_MEMBER(&ancdecls, ns2, namespace_identity));
+ if (!XMLARRAY_APPEND(cx, &ancdecls, ns2))
+ goto out;
+ }
+
+ /* Step 11, except we don't clone ns unless its prefix is undefined. */
+ ns = GetNamespace(cx, xml->name, &ancdecls);
+ if (!ns)
+ goto out;
+
+ /* Step 12 (NULL means *undefined* here), plus the deferred ns cloning. */
+ prefix = GetPrefix(ns);
+ if (!prefix) {
+ /*
+ * Create a namespace prefix that isn't used by any member of decls.
+ * Assign the new prefix to a copy of ns. Flag this namespace as if
+ * it were declared, for assertion-testing's sake later below.
+ *
+ * Erratum: if prefix and xml->name are both null (*undefined* in
+ * ECMA-357), we know that xml was named using the default namespace
+ * (proof: see GetNamespace and the Namespace constructor called with
+ * two arguments). So we ought not generate a new prefix here, when
+ * we can declare ns as the default namespace for xml.
+ *
+ * This helps descendants inherit the namespace instead of redundantly
+ * redeclaring it with generated prefixes in each descendant.
+ */
+ nsuri = GetURI(ns);
+ if (!GetPrefix(xml->name)) {
+ prefix = cx->runtime->emptyString;
+ } else {
+ prefix = GeneratePrefix(cx, nsuri, &ancdecls);
+ if (!prefix)
+ goto out;
+ }
+ ns = NewXMLNamespace(cx, prefix, nsuri, JS_TRUE);
+ if (!ns)
+ goto out;
+
+ /*
+ * If the xml->name was unprefixed, we must remove any declared default
+ * namespace from decls before appending ns. How can you get a default
+ * namespace in decls that doesn't match the one from name? Apparently
+ * by calling x.setNamespace(ns) where ns has no prefix. The other way
+ * to fix this is to update x's in-scope namespaces when setNamespace
+ * is called, but that's not specified by ECMA-357.
+ *
+ * Likely Erratum here, depending on whether the lack of update to x's
+ * in-scope namespace in XML.prototype.setNamespace (13.4.4.36) is an
+ * erratum or not. Note that changing setNamespace to update the list
+ * of in-scope namespaces will change x.namespaceDeclarations().
+ */
+ if (IS_EMPTY(prefix)) {
+ i = XMLArrayFindMember(&decls, ns, namespace_match);
+ if (i != XML_NOT_FOUND)
+ XMLArrayDelete(cx, &decls, i, JS_TRUE);
+ }
+
+ /*
+ * In the spec, ancdecls has no name, but is always written out as
+ * (AncestorNamespaces U namespaceDeclarations). Since we compute
+ * that union in ancdecls, any time we append a namespace strong
+ * ref to decls, we must also append a weak ref to ancdecls. Order
+ * matters here: code at label out: releases strong refs in decls.
+ */
+ if (!XMLARRAY_APPEND(cx, &ancdecls, ns) ||
+ !XMLARRAY_APPEND(cx, &decls, ns)) {
+ goto out;
+ }
+ }
+
+ /* Format the element or point-tag into sb. */
+ js_AppendChar(&sb, '<');
+
+ if (prefix && !IS_EMPTY(prefix)) {
+ js_AppendJSString(&sb, prefix);
+ js_AppendChar(&sb, ':');
+ }
+ js_AppendJSString(&sb, GetLocalName(xml->name));
+
+ /*
+ * Step 16 makes a union to avoid writing two loops in step 17, to share
+ * common attribute value appending spec-code. We prefer two loops for
+ * faster code and less data overhead.
+ */
+
+ /* Step 17(b): append attributes. */
+ XMLArrayCursorInit(&cursor, &xml->xml_attrs);
+ while ((attr = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ js_AppendChar(&sb, ' ');
+ ns2 = GetNamespace(cx, attr->name, &ancdecls);
+ if (!ns2)
+ break;
+
+ /* 17(b)(ii): NULL means *undefined* here. */
+ prefix = GetPrefix(ns2);
+ if (!prefix) {
+ prefix = GeneratePrefix(cx, GetURI(ns2), &ancdecls);
+ if (!prefix)
+ break;
+
+ /* Again, we avoid copying ns2 until we know it's prefix-less. */
+ ns2 = NewXMLNamespace(cx, prefix, GetURI(ns2), JS_TRUE);
+ if (!ns2)
+ break;
+
+ /*
+ * In the spec, ancdecls has no name, but is always written out as
+ * (AncestorNamespaces U namespaceDeclarations). Since we compute
+ * that union in ancdecls, any time we append a namespace strong
+ * ref to decls, we must also append a weak ref to ancdecls. Order
+ * matters here: code at label out: releases strong refs in decls.
+ */
+ if (!XMLARRAY_APPEND(cx, &ancdecls, ns2) ||
+ !XMLARRAY_APPEND(cx, &decls, ns2)) {
+ break;
+ }
+ }
+
+ /* 17(b)(iii). */
+ if (!IS_EMPTY(prefix)) {
+ js_AppendJSString(&sb, prefix);
+ js_AppendChar(&sb, ':');
+ }
+
+ /* 17(b)(iv). */
+ js_AppendJSString(&sb, GetLocalName(attr->name));
+
+ /* 17(d-g). */
+ AppendAttributeValue(cx, &sb, attr->xml_value);
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (attr)
+ goto out;
+
+ /* Step 17(c): append XML namespace declarations. */
+ XMLArrayCursorInit(&cursor, &decls);
+ while ((ns2 = (JSObject *) XMLArrayCursorNext(&cursor)) != NULL) {
+ JS_ASSERT(IsDeclared(ns2));
+
+ js_AppendCString(&sb, " xmlns");
+
+ /* 17(c)(ii): NULL means *undefined* here. */
+ prefix = GetPrefix(ns2);
+ if (!prefix) {
+ prefix = GeneratePrefix(cx, GetURI(ns2), &ancdecls);
+ if (!prefix)
+ break;
+ ns2->fslots[JSSLOT_PREFIX] = STRING_TO_JSVAL(prefix);
+ }
+
+ /* 17(c)(iii). */
+ if (!IS_EMPTY(prefix)) {
+ js_AppendChar(&sb, ':');
+ js_AppendJSString(&sb, prefix);
+ }
+
+ /* 17(d-g). */
+ AppendAttributeValue(cx, &sb, GetURI(ns2));
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (ns2)
+ goto out;
+
+ /* Step 18: handle point tags. */
+ n = xml->xml_kids.length;
+ if (n == 0) {
+ js_AppendCString(&sb, "/>");
+ } else {
+ /* Steps 19 through 25: handle element content, and open the end-tag. */
+ js_AppendChar(&sb, '>');
+ indentKids = n > 1 ||
+ (n == 1 &&
+ (kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML)) &&
+ kid->xml_class != JSXML_CLASS_TEXT);
+
+ if (pretty && indentKids) {
+ if (!GetUint32XMLSetting(cx, js_prettyIndent_str, &i))
+ goto out;
+ nextIndentLevel = indentLevel + i;
+ } else {
+ nextIndentLevel = indentLevel & TO_SOURCE_FLAG;
+ }
+
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (pretty && indentKids)
+ js_AppendChar(&sb, '\n');
+
+ kidstr = XMLToXMLString(cx, kid, &ancdecls, nextIndentLevel);
+ if (!kidstr)
+ break;
+
+ js_AppendJSString(&sb, kidstr);
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (kid)
+ goto out;
+
+ if (pretty && indentKids) {
+ js_AppendChar(&sb, '\n');
+ js_RepeatChar(&sb, ' ', indentLevel & ~TO_SOURCE_FLAG);
+ }
+ js_AppendCString(&sb, "</");
+
+ /* Step 26. */
+ prefix = GetPrefix(ns);
+ if (prefix && !IS_EMPTY(prefix)) {
+ js_AppendJSString(&sb, prefix);
+ js_AppendChar(&sb, ':');
+ }
+
+ /* Step 27. */
+ js_AppendJSString(&sb, GetLocalName(xml->name));
+ js_AppendChar(&sb, '>');
+ }
+
+ if (!STRING_BUFFER_OK(&sb)) {
+ JS_ReportOutOfMemory(cx);
+ goto out;
+ }
+
+ str = js_NewString(cx, sb.base, STRING_BUFFER_OFFSET(&sb));
+out:
+ js_LeaveLocalRootScopeWithResult(cx, STRING_TO_JSVAL(str));
+ if (!str && STRING_BUFFER_OK(&sb))
+ js_FinishStringBuffer(&sb);
+ XMLArrayFinish(cx, &decls);
+ if (ancdecls.capacity != 0)
+ XMLArrayFinish(cx, &ancdecls);
+ return str;
+}
+
+/* ECMA-357 10.2 */
+static JSString *
+ToXMLString(JSContext *cx, jsval v, uint32 toSourceFlag)
+{
+ JSObject *obj;
+ JSString *str;
+ JSXML *xml;
+
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_XML_CONVERSION,
+ JSVAL_IS_NULL(v) ? js_null_str : js_undefined_str);
+ return NULL;
+ }
+
+ if (JSVAL_IS_BOOLEAN(v) || JSVAL_IS_NUMBER(v))
+ return js_ValueToString(cx, v);
+
+ if (JSVAL_IS_STRING(v))
+ return EscapeElementValue(cx, NULL, JSVAL_TO_STRING(v));
+
+ obj = JSVAL_TO_OBJECT(v);
+ if (!OBJECT_IS_XML(cx, obj)) {
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v))
+ return NULL;
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return NULL;
+ return EscapeElementValue(cx, NULL, str);
+ }
+
+ /* Handle non-element cases in this switch, returning from each case. */
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ return XMLToXMLString(cx, xml, NULL, toSourceFlag | 0);
+}
+
+static JSObject *
+ToAttributeName(JSContext *cx, jsval v)
+{
+ JSString *name, *uri, *prefix;
+ JSObject *obj;
+ JSClass *clasp;
+ JSObject *qn;
+
+ if (JSVAL_IS_STRING(v)) {
+ name = JSVAL_TO_STRING(v);
+ uri = prefix = cx->runtime->emptyString;
+ } else {
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ js_ReportValueError(cx, JSMSG_BAD_XML_ATTR_NAME,
+ JSDVG_IGNORE_STACK, v, NULL);
+ return NULL;
+ }
+
+ obj = JSVAL_TO_OBJECT(v);
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp == &js_AttributeNameClass)
+ return obj;
+
+ if (clasp == &js_QNameClass.base) {
+ qn = obj;
+ uri = GetURI(qn);
+ prefix = GetPrefix(qn);
+ name = GetLocalName(qn);
+ } else {
+ if (clasp == &js_AnyNameClass) {
+ name = ATOM_TO_STRING(cx->runtime->atomState.starAtom);
+ } else {
+ name = js_ValueToString(cx, v);
+ if (!name)
+ return NULL;
+ }
+ uri = prefix = cx->runtime->emptyString;
+ }
+ }
+
+ qn = NewXMLQName(cx, uri, prefix, name, &js_AttributeNameClass);
+ if (!qn)
+ return NULL;
+ return qn;
+}
+
+static void
+ReportBadXMLName(JSContext *cx, jsval id)
+{
+ js_ReportValueError(cx, JSMSG_BAD_XML_NAME, JSDVG_IGNORE_STACK, id, NULL);
+}
+
+static JSBool
+IsFunctionQName(JSContext *cx, JSObject *qn, jsid *funidp)
+{
+ JSAtom *atom;
+ JSString *uri;
+
+ atom = cx->runtime->atomState.lazy.functionNamespaceURIAtom;
+ uri = GetURI(qn);
+ if (uri && atom &&
+ (uri == ATOM_TO_STRING(atom) ||
+ js_EqualStrings(uri, ATOM_TO_STRING(atom)))) {
+ return JS_ValueToId(cx, STRING_TO_JSVAL(GetLocalName(qn)), funidp);
+ }
+ *funidp = 0;
+ return JS_TRUE;
+}
+
+JSBool
+js_IsFunctionQName(JSContext *cx, JSObject *obj, jsid *funidp)
+{
+ if (OBJ_GET_CLASS(cx, obj) == &js_QNameClass.base)
+ return IsFunctionQName(cx, obj, funidp);
+ *funidp = 0;
+ return JS_TRUE;
+}
+
+static JSObject *
+ToXMLName(JSContext *cx, jsval v, jsid *funidp)
+{
+ JSString *name;
+ JSObject *obj;
+ JSClass *clasp;
+ uint32 index;
+
+ if (JSVAL_IS_STRING(v)) {
+ name = JSVAL_TO_STRING(v);
+ } else {
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ ReportBadXMLName(cx, v);
+ return NULL;
+ }
+
+ obj = JSVAL_TO_OBJECT(v);
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp == &js_AttributeNameClass || clasp == &js_QNameClass.base)
+ goto out;
+ if (clasp == &js_AnyNameClass) {
+ name = ATOM_TO_STRING(cx->runtime->atomState.starAtom);
+ goto construct;
+ }
+ name = js_ValueToString(cx, v);
+ if (!name)
+ return NULL;
+ }
+
+ /*
+ * ECMA-357 10.6.1 step 1 seems to be incorrect. The spec says:
+ *
+ * 1. If ToString(ToNumber(P)) == ToString(P), throw a TypeError exception
+ *
+ * First, _P_ should be _s_, to refer to the given string.
+ *
+ * Second, why does ToXMLName applied to the string type throw TypeError
+ * only for numeric literals without any leading or trailing whitespace?
+ *
+ * If the idea is to reject uint32 property names, then the check needs to
+ * be stricter, to exclude hexadecimal and floating point literals.
+ */
+ if (js_IdIsIndex(STRING_TO_JSVAL(name), &index))
+ goto bad;
+
+ if (*JSSTRING_CHARS(name) == '@') {
+ name = js_NewDependentString(cx, name, 1, JSSTRING_LENGTH(name) - 1);
+ if (!name)
+ return NULL;
+ *funidp = 0;
+ return ToAttributeName(cx, STRING_TO_JSVAL(name));
+ }
+
+construct:
+ v = STRING_TO_JSVAL(name);
+ obj = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1, &v);
+ if (!obj)
+ return NULL;
+
+out:
+ if (!IsFunctionQName(cx, obj, funidp))
+ return NULL;
+ return obj;
+
+bad:
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_XML_NAME,
+ js_ValueToPrintableString(cx, STRING_TO_JSVAL(name)));
+ return NULL;
+}
+
+/* ECMA-357 9.1.1.13 XML [[AddInScopeNamespace]]. */
+static JSBool
+AddInScopeNamespace(JSContext *cx, JSXML *xml, JSObject *ns)
+{
+ JSString *prefix, *prefix2;
+ JSObject *match, *ns2;
+ uint32 i, n, m;
+
+ if (xml->xml_class != JSXML_CLASS_ELEMENT)
+ return JS_TRUE;
+
+ /* NULL means *undefined* here -- see ECMA-357 9.1.1.13 step 2. */
+ prefix = GetPrefix(ns);
+ if (!prefix) {
+ match = NULL;
+ for (i = 0, n = xml->xml_namespaces.length; i < n; i++) {
+ ns2 = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (ns2 && js_EqualStrings(GetURI(ns2), GetURI(ns))) {
+ match = ns2;
+ break;
+ }
+ }
+ if (!match && !XMLARRAY_ADD_MEMBER(cx, &xml->xml_namespaces, n, ns))
+ return JS_FALSE;
+ } else {
+ if (IS_EMPTY(prefix) && IS_EMPTY(GetURI(xml->name)))
+ return JS_TRUE;
+ match = NULL;
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ m = XML_NOT_FOUND;
+#endif
+ for (i = 0, n = xml->xml_namespaces.length; i < n; i++) {
+ ns2 = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (ns2 && (prefix2 = GetPrefix(ns2)) &&
+ js_EqualStrings(prefix2, prefix)) {
+ match = ns2;
+ m = i;
+ break;
+ }
+ }
+ if (match && !js_EqualStrings(GetURI(match), GetURI(ns))) {
+ ns2 = XMLARRAY_DELETE(cx, &xml->xml_namespaces, m, JS_TRUE,
+ JSObject);
+ JS_ASSERT(ns2 == match);
+ match->fslots[JSSLOT_PREFIX] = JSVAL_VOID;
+ if (!AddInScopeNamespace(cx, xml, match))
+ return JS_FALSE;
+ }
+ if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns))
+ return JS_FALSE;
+ }
+
+ /* OPTION: enforce that descendants have superset namespaces. */
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.2.1.6 XMLList [[Append]]. */
+static JSBool
+Append(JSContext *cx, JSXML *list, JSXML *xml)
+{
+ uint32 i, j, k, n;
+ JSXML *kid;
+
+ JS_ASSERT(list->xml_class == JSXML_CLASS_LIST);
+ i = list->xml_kids.length;
+ n = 1;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ list->xml_target = xml->xml_target;
+ list->xml_targetprop = xml->xml_targetprop;
+ n = JSXML_LENGTH(xml);
+ k = i + n;
+ if (!XMLArraySetCapacity(cx, &list->xml_kids, k))
+ return JS_FALSE;
+ for (j = 0; j < n; j++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, j, JSXML);
+ if (kid)
+ XMLARRAY_SET_MEMBER(&list->xml_kids, i + j, kid);
+ }
+ return JS_TRUE;
+ }
+
+ list->xml_target = xml->parent;
+ if (xml->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION)
+ list->xml_targetprop = NULL;
+ else
+ list->xml_targetprop = xml->name;
+ if (!XMLARRAY_ADD_MEMBER(cx, &list->xml_kids, i, xml))
+ return JS_FALSE;
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.7 XML [[DeepCopy]] and 9.2.1.7 XMLList [[DeepCopy]]. */
+static JSXML *
+DeepCopyInLRS(JSContext *cx, JSXML *xml, uintN flags);
+
+static JSXML *
+DeepCopy(JSContext *cx, JSXML *xml, JSObject *obj, uintN flags)
+{
+ JSXML *copy;
+ JSBool ok;
+
+ /* Our caller may not be protecting newborns with a local root scope. */
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+ copy = DeepCopyInLRS(cx, xml, flags);
+ if (copy) {
+ if (obj) {
+ /* Caller provided the object for this copy, hook 'em up. */
+ ok = JS_SetPrivate(cx, obj, copy);
+ if (ok)
+ copy->object = obj;
+ } else {
+ ok = js_GetXMLObject(cx, copy) != NULL;
+ }
+ if (!ok)
+ copy = NULL;
+ }
+ js_LeaveLocalRootScopeWithResult(cx, (jsval) copy);
+ return copy;
+}
+
+/*
+ * (i) We must be in a local root scope (InLRS).
+ * (ii) parent must have a rooted object.
+ * (iii) from's owning object must be locked if not thread-local.
+ */
+static JSBool
+DeepCopySetInLRS(JSContext *cx, JSXMLArray *from, JSXMLArray *to, JSXML *parent,
+ uintN flags)
+{
+ uint32 j, n;
+ JSXMLArrayCursor cursor;
+ JSBool ok;
+ JSXML *kid, *kid2;
+ JSString *str;
+
+ JS_ASSERT(cx->localRootStack);
+
+ n = from->length;
+ if (!XMLArraySetCapacity(cx, to, n))
+ return JS_FALSE;
+
+ XMLArrayCursorInit(&cursor, from);
+ j = 0;
+ ok = JS_TRUE;
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if ((flags & XSF_IGNORE_COMMENTS) &&
+ kid->xml_class == JSXML_CLASS_COMMENT) {
+ continue;
+ }
+ if ((flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS) &&
+ kid->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION) {
+ continue;
+ }
+ if ((flags & XSF_IGNORE_WHITESPACE) &&
+ (kid->xml_flags & XMLF_WHITESPACE_TEXT)) {
+ continue;
+ }
+ kid2 = DeepCopyInLRS(cx, kid, flags);
+ if (!kid2) {
+ to->length = j;
+ ok = JS_FALSE;
+ break;
+ }
+
+ if ((flags & XSF_IGNORE_WHITESPACE) &&
+ n > 1 && kid2->xml_class == JSXML_CLASS_TEXT) {
+ str = ChompXMLWhitespace(cx, kid2->xml_value);
+ if (!str) {
+ to->length = j;
+ ok = JS_FALSE;
+ break;
+ }
+ kid2->xml_value = str;
+ }
+
+ XMLARRAY_SET_MEMBER(to, j, kid2);
+ ++j;
+ if (parent->xml_class != JSXML_CLASS_LIST)
+ kid2->parent = parent;
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (!ok)
+ return JS_FALSE;
+
+ if (j < n)
+ XMLArrayTrim(to);
+ return JS_TRUE;
+}
+
+static JSXML *
+DeepCopyInLRS(JSContext *cx, JSXML *xml, uintN flags)
+{
+ JSXML *copy;
+ JSObject *qn;
+ JSBool ok;
+ uint32 i, n;
+ JSObject *ns, *ns2;
+
+ /* Our caller must be protecting newborn objects. */
+ JS_ASSERT(cx->localRootStack);
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ copy = js_NewXML(cx, (JSXMLClass) xml->xml_class);
+ if (!copy)
+ return NULL;
+ qn = xml->name;
+ if (qn) {
+ qn = NewXMLQName(cx, GetURI(qn), GetPrefix(qn), GetLocalName(qn));
+ if (!qn) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+ copy->name = qn;
+ copy->xml_flags = xml->xml_flags;
+
+ if (JSXML_HAS_VALUE(xml)) {
+ copy->xml_value = xml->xml_value;
+ ok = JS_TRUE;
+ } else {
+ ok = DeepCopySetInLRS(cx, &xml->xml_kids, &copy->xml_kids, copy, flags);
+ if (!ok)
+ goto out;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ copy->xml_target = xml->xml_target;
+ copy->xml_targetprop = xml->xml_targetprop;
+ } else {
+ n = xml->xml_namespaces.length;
+ ok = XMLArraySetCapacity(cx, &copy->xml_namespaces, n);
+ if (!ok)
+ goto out;
+ for (i = 0; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (!ns)
+ continue;
+ ns2 = NewXMLNamespace(cx, GetPrefix(ns), GetURI(ns),
+ IsDeclared(ns));
+ if (!ns2) {
+ copy->xml_namespaces.length = i;
+ ok = JS_FALSE;
+ goto out;
+ }
+ XMLARRAY_SET_MEMBER(&copy->xml_namespaces, i, ns2);
+ }
+
+ ok = DeepCopySetInLRS(cx, &xml->xml_attrs, &copy->xml_attrs, copy,
+ 0);
+ if (!ok)
+ goto out;
+ }
+ }
+
+out:
+ if (!ok)
+ return NULL;
+ return copy;
+}
+
+/* ECMA-357 9.1.1.4 XML [[DeleteByIndex]]. */
+static void
+DeleteByIndex(JSContext *cx, JSXML *xml, uint32 index)
+{
+ JSXML *kid;
+
+ if (JSXML_HAS_KIDS(xml) && index < xml->xml_kids.length) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML);
+ if (kid)
+ kid->parent = NULL;
+ XMLArrayDelete(cx, &xml->xml_kids, index, JS_TRUE);
+ }
+}
+
+typedef JSBool (*JSXMLNameMatcher)(JSObject *nameqn, JSXML *xml);
+
+static JSBool
+MatchAttrName(JSObject *nameqn, JSXML *attr)
+{
+ JSObject *attrqn = attr->name;
+ JSString *localName = GetLocalName(nameqn);
+ JSString *uri;
+
+ return (IS_STAR(localName) ||
+ js_EqualStrings(GetLocalName(attrqn), localName)) &&
+ (!(uri = GetURI(nameqn)) ||
+ js_EqualStrings(GetURI(attrqn), uri));
+}
+
+static JSBool
+MatchElemName(JSObject *nameqn, JSXML *elem)
+{
+ JSString *localName = GetLocalName(nameqn);
+ JSString *uri;
+
+ return (IS_STAR(localName) ||
+ (elem->xml_class == JSXML_CLASS_ELEMENT &&
+ js_EqualStrings(GetLocalName(elem->name), localName))) &&
+ (!(uri = GetURI(nameqn)) ||
+ (elem->xml_class == JSXML_CLASS_ELEMENT &&
+ js_EqualStrings(GetURI(elem->name), uri)));
+}
+
+/* ECMA-357 9.1.1.8 XML [[Descendants]] and 9.2.1.8 XMLList [[Descendants]]. */
+static JSBool
+DescendantsHelper(JSContext *cx, JSXML *xml, JSObject *nameqn, JSXML *list)
+{
+ uint32 i, n;
+ JSXML *attr, *kid;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ if (xml->xml_class == JSXML_CLASS_ELEMENT &&
+ OBJ_GET_CLASS(cx, nameqn) == &js_AttributeNameClass) {
+ for (i = 0, n = xml->xml_attrs.length; i < n; i++) {
+ attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML);
+ if (attr && MatchAttrName(nameqn, attr)) {
+ if (!Append(cx, list, attr))
+ return JS_FALSE;
+ }
+ }
+ }
+
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (!kid)
+ continue;
+ if (OBJ_GET_CLASS(cx, nameqn) != &js_AttributeNameClass &&
+ MatchElemName(nameqn, kid)) {
+ if (!Append(cx, list, kid))
+ return JS_FALSE;
+ }
+ if (!DescendantsHelper(cx, kid, nameqn, list))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+static JSXML *
+Descendants(JSContext *cx, JSXML *xml, jsval id)
+{
+ jsid funid;
+ JSObject *nameqn;
+ JSObject *listobj;
+ JSXML *list, *kid;
+ uint32 i, n;
+ JSBool ok;
+
+ nameqn = ToXMLName(cx, id, &funid);
+ if (!nameqn)
+ return NULL;
+
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!listobj)
+ return NULL;
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ if (funid)
+ return list;
+
+ /*
+ * Protect nameqn's object and strings from GC by linking list to it
+ * temporarily. The cx->newborn[GCX_OBJECT] GC root protects listobj,
+ * which protects list. Any other object allocations occuring beneath
+ * DescendantsHelper use local roots.
+ */
+ list->name = nameqn;
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ ok = JS_TRUE;
+ for (i = 0, n = xml->xml_kids.length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ ok = DescendantsHelper(cx, kid, nameqn, list);
+ if (!ok)
+ break;
+ }
+ }
+ } else {
+ ok = DescendantsHelper(cx, xml, nameqn, list);
+ }
+ js_LeaveLocalRootScopeWithResult(cx, (jsval) list);
+ if (!ok)
+ return NULL;
+ list->name = NULL;
+ return list;
+}
+
+static JSBool
+xml_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+/* Recursive (JSXML *) parameterized version of Equals. */
+static JSBool
+XMLEquals(JSContext *cx, JSXML *xml, JSXML *vxml, JSBool *bp)
+{
+ JSObject *qn, *vqn;
+ uint32 i, j, n;
+ JSXMLArrayCursor cursor, vcursor;
+ JSXML *kid, *vkid, *attr, *vattr;
+ JSBool ok;
+ JSObject *xobj, *vobj;
+
+retry:
+ if (xml->xml_class != vxml->xml_class) {
+ if (xml->xml_class == JSXML_CLASS_LIST && xml->xml_kids.length == 1) {
+ xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (xml)
+ goto retry;
+ }
+ if (vxml->xml_class == JSXML_CLASS_LIST && vxml->xml_kids.length == 1) {
+ vxml = XMLARRAY_MEMBER(&vxml->xml_kids, 0, JSXML);
+ if (vxml)
+ goto retry;
+ }
+ *bp = JS_FALSE;
+ return JS_TRUE;
+ }
+
+ qn = xml->name;
+ vqn = vxml->name;
+ if (qn) {
+ *bp = vqn &&
+ js_EqualStrings(GetLocalName(qn), GetLocalName(vqn)) &&
+ js_EqualStrings(GetURI(qn), GetURI(vqn));
+ } else {
+ *bp = vqn == NULL;
+ }
+ if (!*bp)
+ return JS_TRUE;
+
+ if (JSXML_HAS_VALUE(xml)) {
+ *bp = js_EqualStrings(xml->xml_value, vxml->xml_value);
+ } else if (xml->xml_kids.length != vxml->xml_kids.length) {
+ *bp = JS_FALSE;
+ } else {
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ XMLArrayCursorInit(&vcursor, &vxml->xml_kids);
+ for (;;) {
+ kid = (JSXML *) XMLArrayCursorNext(&cursor);
+ vkid = (JSXML *) XMLArrayCursorNext(&vcursor);
+ if (!kid || !vkid) {
+ *bp = !kid && !vkid;
+ ok = JS_TRUE;
+ break;
+ }
+ xobj = js_GetXMLObject(cx, kid);
+ vobj = js_GetXMLObject(cx, vkid);
+ ok = xobj && vobj &&
+ xml_equality(cx, xobj, OBJECT_TO_JSVAL(vobj), bp);
+ if (!ok || !*bp)
+ break;
+ }
+ XMLArrayCursorFinish(&vcursor);
+ XMLArrayCursorFinish(&cursor);
+ if (!ok)
+ return JS_FALSE;
+
+ if (*bp && xml->xml_class == JSXML_CLASS_ELEMENT) {
+ n = xml->xml_attrs.length;
+ if (n != vxml->xml_attrs.length)
+ *bp = JS_FALSE;
+ for (i = 0; *bp && i < n; i++) {
+ attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML);
+ if (!attr)
+ continue;
+ j = XMLARRAY_FIND_MEMBER(&vxml->xml_attrs, attr, attr_identity);
+ if (j == XML_NOT_FOUND) {
+ *bp = JS_FALSE;
+ break;
+ }
+ vattr = XMLARRAY_MEMBER(&vxml->xml_attrs, j, JSXML);
+ if (!vattr)
+ continue;
+ *bp = js_EqualStrings(attr->xml_value, vattr->xml_value);
+ }
+ }
+ }
+
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.9 XML [[Equals]] and 9.2.1.9 XMLList [[Equals]]. */
+static JSBool
+Equals(JSContext *cx, JSXML *xml, jsval v, JSBool *bp)
+{
+ JSObject *vobj;
+ JSXML *vxml;
+
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ *bp = JS_FALSE;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ if (xml->xml_kids.length == 1) {
+ vxml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (!vxml)
+ return JS_TRUE;
+ vobj = js_GetXMLObject(cx, vxml);
+ if (!vobj)
+ return JS_FALSE;
+ return js_XMLObjectOps.equality(cx, vobj, v, bp);
+ }
+ if (JSVAL_IS_VOID(v) && xml->xml_kids.length == 0)
+ *bp = JS_TRUE;
+ }
+ } else {
+ vobj = JSVAL_TO_OBJECT(v);
+ if (!OBJECT_IS_XML(cx, vobj)) {
+ *bp = JS_FALSE;
+ } else {
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ if (!XMLEquals(cx, xml, vxml, bp))
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+CheckCycle(JSContext *cx, JSXML *xml, JSXML *kid)
+{
+ JS_ASSERT(kid->xml_class != JSXML_CLASS_LIST);
+
+ do {
+ if (xml == kid) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CYCLIC_VALUE, js_XML_str);
+ return JS_FALSE;
+ }
+ } while ((xml = xml->parent) != NULL);
+
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.11 XML [[Insert]]. */
+static JSBool
+Insert(JSContext *cx, JSXML *xml, uint32 i, jsval v)
+{
+ uint32 j, n;
+ JSXML *vxml, *kid;
+ JSObject *vobj;
+ JSString *str;
+
+ if (!JSXML_HAS_KIDS(xml))
+ return JS_TRUE;
+
+ n = 1;
+ vxml = NULL;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ vobj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, vobj)) {
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ if (vxml->xml_class == JSXML_CLASS_LIST) {
+ n = vxml->xml_kids.length;
+ if (n == 0)
+ return JS_TRUE;
+ for (j = 0; j < n; j++) {
+ kid = XMLARRAY_MEMBER(&vxml->xml_kids, j, JSXML);
+ if (!kid)
+ continue;
+ if (!CheckCycle(cx, xml, kid))
+ return JS_FALSE;
+ }
+ } else if (vxml->xml_class == JSXML_CLASS_ELEMENT) {
+ /* OPTION: enforce that descendants have superset namespaces. */
+ if (!CheckCycle(cx, xml, vxml))
+ return JS_FALSE;
+ }
+ }
+ }
+ if (!vxml) {
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return JS_FALSE;
+
+ vxml = js_NewXML(cx, JSXML_CLASS_TEXT);
+ if (!vxml)
+ return JS_FALSE;
+ vxml->xml_value = str;
+ }
+
+ if (i > xml->xml_kids.length)
+ i = xml->xml_kids.length;
+
+ if (!XMLArrayInsert(cx, &xml->xml_kids, i, n))
+ return JS_FALSE;
+
+ if (vxml->xml_class == JSXML_CLASS_LIST) {
+ for (j = 0; j < n; j++) {
+ kid = XMLARRAY_MEMBER(&vxml->xml_kids, j, JSXML);
+ if (!kid)
+ continue;
+ kid->parent = xml;
+ XMLARRAY_SET_MEMBER(&xml->xml_kids, i + j, kid);
+
+ /* OPTION: enforce that descendants have superset namespaces. */
+ }
+ } else {
+ vxml->parent = xml;
+ XMLARRAY_SET_MEMBER(&xml->xml_kids, i, vxml);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+IndexToIdVal(JSContext *cx, uint32 index, jsval *idvp)
+{
+ JSString *str;
+
+ if (index <= JSVAL_INT_MAX) {
+ *idvp = INT_TO_JSVAL(index);
+ } else {
+ str = js_NumberToString(cx, (jsdouble) index);
+ if (!str)
+ return JS_FALSE;
+ *idvp = STRING_TO_JSVAL(str);
+ }
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.12 XML [[Replace]]. */
+static JSBool
+Replace(JSContext *cx, JSXML *xml, uint32 i, jsval v)
+{
+ uint32 n;
+ JSXML *vxml, *kid;
+ JSObject *vobj;
+ JSString *str;
+
+ if (!JSXML_HAS_KIDS(xml))
+ return JS_TRUE;
+
+ /*
+ * 9.1.1.12
+ * [[Replace]] handles _i >= x.[[Length]]_ by incrementing _x.[[Length]_.
+ * It should therefore constrain callers to pass in _i <= x.[[Length]]_.
+ */
+ n = xml->xml_kids.length;
+ if (i > n)
+ i = n;
+
+ vxml = NULL;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ vobj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, vobj))
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ }
+
+ switch (vxml ? vxml->xml_class : JSXML_CLASS_LIMIT) {
+ case JSXML_CLASS_ELEMENT:
+ /* OPTION: enforce that descendants have superset namespaces. */
+ if (!CheckCycle(cx, xml, vxml))
+ return JS_FALSE;
+ case JSXML_CLASS_COMMENT:
+ case JSXML_CLASS_PROCESSING_INSTRUCTION:
+ case JSXML_CLASS_TEXT:
+ goto do_replace;
+
+ case JSXML_CLASS_LIST:
+ if (i < n)
+ DeleteByIndex(cx, xml, i);
+ if (!Insert(cx, xml, i, v))
+ return JS_FALSE;
+ break;
+
+ default:
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return JS_FALSE;
+
+ vxml = js_NewXML(cx, JSXML_CLASS_TEXT);
+ if (!vxml)
+ return JS_FALSE;
+ vxml->xml_value = str;
+
+ do_replace:
+ vxml->parent = xml;
+ if (i < n) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid)
+ kid->parent = NULL;
+ }
+ if (!XMLARRAY_ADD_MEMBER(cx, &xml->xml_kids, i, vxml))
+ return JS_FALSE;
+ break;
+ }
+
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.3 XML [[Delete]], 9.2.1.3 XML [[Delete]] qname cases. */
+static void
+DeleteNamedProperty(JSContext *cx, JSXML *xml, JSObject *nameqn,
+ JSBool attributes)
+{
+ JSXMLArray *array;
+ uint32 index, deleteCount;
+ JSXML *kid;
+ JSXMLNameMatcher matcher;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ array = &xml->xml_kids;
+ for (index = 0; index < array->length; index++) {
+ kid = XMLARRAY_MEMBER(array, index, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT)
+ DeleteNamedProperty(cx, kid, nameqn, attributes);
+ }
+ } else if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ if (attributes) {
+ array = &xml->xml_attrs;
+ matcher = MatchAttrName;
+ } else {
+ array = &xml->xml_kids;
+ matcher = MatchElemName;
+ }
+ deleteCount = 0;
+ for (index = 0; index < array->length; index++) {
+ kid = XMLARRAY_MEMBER(array, index, JSXML);
+ if (kid && matcher(nameqn, kid)) {
+ kid->parent = NULL;
+ XMLArrayDelete(cx, array, index, JS_FALSE);
+ ++deleteCount;
+ } else if (deleteCount != 0) {
+ XMLARRAY_SET_MEMBER(array,
+ index - deleteCount,
+ array->vector[index]);
+ }
+ }
+ array->length -= deleteCount;
+ }
+}
+
+/* ECMA-357 9.2.1.3 index case. */
+static void
+DeleteListElement(JSContext *cx, JSXML *xml, uint32 index)
+{
+ JSXML *kid, *parent;
+ uint32 kidIndex;
+
+ JS_ASSERT(xml->xml_class == JSXML_CLASS_LIST);
+
+ if (index < xml->xml_kids.length) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML);
+ if (kid) {
+ parent = kid->parent;
+ if (parent) {
+ JS_ASSERT(parent != xml);
+ JS_ASSERT(JSXML_HAS_KIDS(parent));
+
+ if (kid->xml_class == JSXML_CLASS_ATTRIBUTE) {
+ DeleteNamedProperty(cx, parent, kid->name, JS_TRUE);
+ } else {
+ kidIndex = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid,
+ NULL);
+ JS_ASSERT(kidIndex != XML_NOT_FOUND);
+ DeleteByIndex(cx, parent, kidIndex);
+ }
+ }
+ XMLArrayDelete(cx, &xml->xml_kids, index, JS_TRUE);
+ }
+ }
+}
+
+static JSBool
+SyncInScopeNamespaces(JSContext *cx, JSXML *xml)
+{
+ JSXMLArray *nsarray;
+ uint32 i, n;
+ JSObject *ns;
+
+ nsarray = &xml->xml_namespaces;
+ while ((xml = xml->parent) != NULL) {
+ for (i = 0, n = xml->xml_namespaces.length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (ns && !XMLARRAY_HAS_MEMBER(nsarray, ns, namespace_identity)) {
+ if (!XMLARRAY_APPEND(cx, nsarray, ns))
+ return JS_FALSE;
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+GetNamedProperty(JSContext *cx, JSXML *xml, JSObject* nameqn, JSXML *list)
+{
+ JSXMLArray *array;
+ JSXMLNameMatcher matcher;
+ JSXMLArrayCursor cursor;
+ JSXML *kid;
+ JSBool attrs;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (kid->xml_class == JSXML_CLASS_ELEMENT &&
+ !GetNamedProperty(cx, kid, nameqn, list)) {
+ break;
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (kid)
+ return JS_FALSE;
+ } else if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ attrs = (OBJ_GET_CLASS(cx, nameqn) == &js_AttributeNameClass);
+ if (attrs) {
+ array = &xml->xml_attrs;
+ matcher = MatchAttrName;
+ } else {
+ array = &xml->xml_kids;
+ matcher = MatchElemName;
+ }
+
+ XMLArrayCursorInit(&cursor, array);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (matcher(nameqn, kid)) {
+ if (!attrs &&
+ kid->xml_class == JSXML_CLASS_ELEMENT &&
+ !SyncInScopeNamespaces(cx, kid)) {
+ break;
+ }
+ if (!Append(cx, list, kid))
+ break;
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (kid)
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.1 XML [[Get]] and 9.2.1.1 XMLList [[Get]]. */
+static JSBool
+GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSXML *xml, *list, *kid;
+ uint32 index;
+ JSObject *kidobj, *listobj;
+ JSObject *nameqn;
+ jsid funid;
+ jsval roots[2];
+ JSTempValueRooter tvr;
+
+ xml = (JSXML *) JS_GetInstancePrivate(cx, obj, &js_XMLClass, NULL);
+ if (!xml)
+ return JS_TRUE;
+
+ if (js_IdIsIndex(id, &index)) {
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ *vp = (index == 0) ? OBJECT_TO_JSVAL(obj) : JSVAL_VOID;
+ } else {
+ /*
+ * ECMA-357 9.2.1.1 starts here.
+ *
+ * Erratum: 9.2 is not completely clear that indexed properties
+ * correspond to kids, but that's what it seems to say, and it's
+ * what any sane user would want.
+ */
+ if (index < xml->xml_kids.length) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML);
+ if (!kid) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ return JS_FALSE;
+
+ *vp = OBJECT_TO_JSVAL(kidobj);
+ } else {
+ *vp = JSVAL_VOID;
+ }
+ }
+ return JS_TRUE;
+ }
+
+ /*
+ * ECMA-357 9.2.1.1/9.1.1.1 qname case.
+ */
+ nameqn = ToXMLName(cx, id, &funid);
+ if (!nameqn)
+ return JS_FALSE;
+ if (funid)
+ return js_GetXMLFunction(cx, obj, funid, vp);
+
+ roots[0] = OBJECT_TO_JSVAL(nameqn);
+ JS_PUSH_TEMP_ROOT(cx, 1, roots, &tvr);
+
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (listobj) {
+ roots[1] = OBJECT_TO_JSVAL(listobj);
+ tvr.count++;
+
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ if (!GetNamedProperty(cx, xml, nameqn, list)) {
+ listobj = NULL;
+ } else {
+ /*
+ * Erratum: ECMA-357 9.1.1.1 misses that [[Append]] sets the
+ * given list's [[TargetProperty]] to the property that is being
+ * appended. This means that any use of the internal [[Get]]
+ * property returns a list which, when used by e.g. [[Insert]]
+ * duplicates the last element matched by id. See bug 336921.
+ */
+ list->xml_target = xml;
+ list->xml_targetprop = nameqn;
+ *vp = OBJECT_TO_JSVAL(listobj);
+ }
+ }
+
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return listobj != NULL;
+}
+
+static JSXML *
+CopyOnWrite(JSContext *cx, JSXML *xml, JSObject *obj)
+{
+ JS_ASSERT(xml->object != obj);
+
+ xml = DeepCopy(cx, xml, obj, 0);
+ if (!xml)
+ return NULL;
+
+ JS_ASSERT(xml->object == obj);
+ return xml;
+}
+
+#define CHECK_COPY_ON_WRITE(cx,xml,obj) \
+ (xml->object == obj ? xml : CopyOnWrite(cx, xml, obj))
+
+static JSString *
+KidToString(JSContext *cx, JSXML *xml, uint32 index)
+{
+ JSXML *kid;
+ JSObject *kidobj;
+
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML);
+ if (!kid)
+ return cx->runtime->emptyString;
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ return NULL;
+ return js_ValueToString(cx, OBJECT_TO_JSVAL(kidobj));
+}
+
+/* Forward declared -- its implementation uses other statics that call it. */
+static JSBool
+ResolveValue(JSContext *cx, JSXML *list, JSXML **result);
+
+/* ECMA-357 9.1.1.2 XML [[Put]] and 9.2.1.2 XMLList [[Put]]. */
+static JSBool
+PutProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSBool ok, primitiveAssign;
+ enum { OBJ_ROOT, ID_ROOT, VAL_ROOT };
+ jsval roots[3];
+ JSTempValueRooter tvr;
+ JSXML *xml, *vxml, *rxml, *kid, *attr, *parent, *copy, *kid2, *match;
+ JSObject *vobj, *nameobj, *attrobj, *parentobj, *kidobj, *copyobj;
+ JSObject *targetprop, *nameqn, *attrqn;
+ uint32 index, i, j, k, n, q, matchIndex;
+ jsval attrval, nsval;
+ jsid funid;
+ JSString *left, *right, *space, *uri;
+ JSObject *ns;
+
+ xml = (JSXML *) JS_GetInstancePrivate(cx, obj, &js_XMLClass, NULL);
+ if (!xml)
+ return JS_TRUE;
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ /* Precompute vxml for 9.2.1.2 2(c)(vii)(2-3) and 2(d) and 9.1.1.2 1. */
+ vxml = NULL;
+ if (!JSVAL_IS_PRIMITIVE(*vp)) {
+ vobj = JSVAL_TO_OBJECT(*vp);
+ if (OBJECT_IS_XML(cx, vobj))
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ }
+
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ return JS_FALSE;
+ MUST_FLOW_THROUGH("out");
+ roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj);
+ roots[ID_ROOT] = id;
+ roots[VAL_ROOT] = *vp;
+ JS_PUSH_TEMP_ROOT(cx, 3, roots, &tvr);
+
+ if (js_IdIsIndex(id, &index)) {
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ /* See NOTE in spec: this variation is reserved for future use. */
+ ReportBadXMLName(cx, id);
+ goto bad;
+ }
+
+ /*
+ * Step 1 of ECMA-357 9.2.1.2 index case sets i to the property index.
+ */
+ i = index;
+
+ /* 2(a-b). */
+ if (xml->xml_target) {
+ ok = ResolveValue(cx, xml->xml_target, &rxml);
+ if (!ok)
+ goto out;
+ if (!rxml)
+ goto out;
+ JS_ASSERT(rxml->object);
+ } else {
+ rxml = NULL;
+ }
+
+ /* 2(c). */
+ if (index >= xml->xml_kids.length) {
+ /* 2(c)(i). */
+ if (rxml) {
+ if (rxml->xml_class == JSXML_CLASS_LIST) {
+ if (rxml->xml_kids.length != 1)
+ goto out;
+ rxml = XMLARRAY_MEMBER(&rxml->xml_kids, 0, JSXML);
+ if (!rxml)
+ goto out;
+ ok = js_GetXMLObject(cx, rxml) != NULL;
+ if (!ok)
+ goto out;
+ }
+
+ /*
+ * Erratum: ECMA-357 9.2.1.2 step 2(c)(ii) sets
+ * _y.[[Parent]] = r_ where _r_ is the result of
+ * [[ResolveValue]] called on _x.[[TargetObject]] in
+ * 2(a)(i). This can result in text parenting text:
+ *
+ * var MYXML = new XML();
+ * MYXML.appendChild(new XML("<TEAM>Giants</TEAM>"));
+ *
+ * (testcase from Werner Sharp <wsharp@macromedia.com>).
+ *
+ * To match insertChildAfter, insertChildBefore,
+ * prependChild, and setChildren, we should silently
+ * do nothing in this case.
+ */
+ if (!JSXML_HAS_KIDS(rxml))
+ goto out;
+ }
+
+ /* 2(c)(ii) is distributed below as several js_NewXML calls. */
+ targetprop = xml->xml_targetprop;
+ if (!targetprop || IS_STAR(GetLocalName(targetprop))) {
+ /* 2(c)(iv)(1-2), out of order w.r.t. 2(c)(iii). */
+ kid = js_NewXML(cx, JSXML_CLASS_TEXT);
+ if (!kid)
+ goto bad;
+ } else {
+ nameobj = targetprop;
+ if (!nameobj)
+ goto bad;
+ if (OBJ_GET_CLASS(cx, nameobj) == &js_AttributeNameClass) {
+ /*
+ * 2(c)(iii)(1-3).
+ * Note that rxml can't be null here, because target
+ * and targetprop are non-null.
+ */
+ ok = GetProperty(cx, rxml->object, id, &attrval);
+ if (!ok)
+ goto out;
+ if (JSVAL_IS_PRIMITIVE(attrval)) /* no such attribute */
+ goto out;
+ attrobj = JSVAL_TO_OBJECT(attrval);
+ attr = (JSXML *) JS_GetPrivate(cx, attrobj);
+ if (JSXML_LENGTH(attr) != 0)
+ goto out;
+
+ kid = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE);
+ } else {
+ /* 2(c)(v). */
+ kid = js_NewXML(cx, JSXML_CLASS_ELEMENT);
+ }
+ if (!kid)
+ goto bad;
+
+ /* An important bit of 2(c)(ii). */
+ kid->name = targetprop;
+ }
+
+ /* Final important bit of 2(c)(ii). */
+ kid->parent = rxml;
+
+ /* 2(c)(vi-vii). */
+ i = xml->xml_kids.length;
+ if (kid->xml_class != JSXML_CLASS_ATTRIBUTE) {
+ /*
+ * 2(c)(vii)(1) tests whether _y.[[Parent]]_ is not null.
+ * y.[[Parent]] is here called kid->parent, which we know
+ * from 2(c)(ii) is _r_, here called rxml. So let's just
+ * test that! Erratum, the spec should be simpler here.
+ */
+ if (rxml) {
+ JS_ASSERT(JSXML_HAS_KIDS(rxml));
+ n = rxml->xml_kids.length;
+ j = n - 1;
+ if (n != 0 && i != 0) {
+ for (n = j, j = 0; j < n; j++) {
+ if (rxml->xml_kids.vector[j] ==
+ xml->xml_kids.vector[i-1]) {
+ break;
+ }
+ }
+ }
+
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ goto bad;
+ ok = Insert(cx, rxml, j + 1, OBJECT_TO_JSVAL(kidobj));
+ if (!ok)
+ goto out;
+ }
+
+ /*
+ * 2(c)(vii)(2-3).
+ * Erratum: [[PropertyName]] in 2(c)(vii)(3) must be a
+ * typo for [[TargetProperty]].
+ */
+ if (vxml) {
+ kid->name = (vxml->xml_class == JSXML_CLASS_LIST)
+ ? vxml->xml_targetprop
+ : vxml->name;
+ }
+ }
+
+ /* 2(c)(viii). */
+ ok = Append(cx, xml, kid);
+ if (!ok)
+ goto out;
+ }
+
+ /* 2(d). */
+ if (!vxml ||
+ vxml->xml_class == JSXML_CLASS_TEXT ||
+ vxml->xml_class == JSXML_CLASS_ATTRIBUTE) {
+ ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp);
+ if (!ok)
+ goto out;
+ roots[VAL_ROOT] = *vp;
+ }
+
+ /* 2(e). */
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (!kid)
+ goto out;
+ parent = kid->parent;
+ if (kid->xml_class == JSXML_CLASS_ATTRIBUTE) {
+ nameobj = kid->name;
+ if (OBJ_GET_CLASS(cx, nameobj) != &js_AttributeNameClass) {
+ nameobj = NewXMLQName(cx, GetURI(nameobj), GetPrefix(nameobj),
+ GetLocalName(nameobj),
+ &js_AttributeNameClass);
+ if (!nameobj)
+ goto bad;
+ }
+ id = OBJECT_TO_JSVAL(nameobj);
+
+ if (parent) {
+ /* 2(e)(i). */
+ parentobj = js_GetXMLObject(cx, parent);
+ if (!parentobj)
+ goto bad;
+ ok = PutProperty(cx, parentobj, id, vp);
+ if (!ok)
+ goto out;
+
+ /* 2(e)(ii). */
+ ok = GetProperty(cx, parentobj, id, vp);
+ if (!ok)
+ goto out;
+ attr = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(*vp));
+
+ /* 2(e)(iii). */
+ xml->xml_kids.vector[i] = attr->xml_kids.vector[0];
+ }
+ }
+
+ /* 2(f). */
+ else if (vxml && vxml->xml_class == JSXML_CLASS_LIST) {
+ /*
+ * 2(f)(i)
+ *
+ * Erratum: the spec says to create a shallow copy _c_ of _V_, but
+ * if we do that we never change the parent of each child in the
+ * list. Since [[Put]] when called on an XML object deeply copies
+ * the provided list _V_, we also do so here. Perhaps the shallow
+ * copy was a misguided optimization?
+ */
+ copy = DeepCopyInLRS(cx, vxml, 0);
+ if (!copy)
+ goto bad;
+ copyobj = js_GetXMLObject(cx, copy);
+ if (!copyobj)
+ goto bad;
+
+ JS_ASSERT(parent != xml);
+ if (parent) {
+ q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, NULL);
+ JS_ASSERT(q != XML_NOT_FOUND);
+ ok = Replace(cx, parent, q, OBJECT_TO_JSVAL(copyobj));
+ if (!ok)
+ goto out;
+
+#ifdef DEBUG
+ /* Erratum: this loop in the spec is useless. */
+ for (j = 0, n = copy->xml_kids.length; j < n; j++) {
+ kid2 = XMLARRAY_MEMBER(&parent->xml_kids, q + j, JSXML);
+ JS_ASSERT(XMLARRAY_MEMBER(&copy->xml_kids, j, JSXML)
+ == kid2);
+ }
+#endif
+ }
+
+ /*
+ * 2(f)(iv-vi).
+ * Erratum: notice the unhandled zero-length V basis case and
+ * the off-by-one errors for the n != 0 cases in the spec.
+ */
+ n = copy->xml_kids.length;
+ if (n == 0) {
+ XMLArrayDelete(cx, &xml->xml_kids, i, JS_TRUE);
+ } else {
+ ok = XMLArrayInsert(cx, &xml->xml_kids, i + 1, n - 1);
+ if (!ok)
+ goto out;
+
+ for (j = 0; j < n; j++)
+ xml->xml_kids.vector[i + j] = copy->xml_kids.vector[j];
+ }
+ }
+
+ /* 2(g). */
+ else if (vxml || JSXML_HAS_VALUE(kid)) {
+ if (parent) {
+ q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, NULL);
+ JS_ASSERT(q != XML_NOT_FOUND);
+ ok = Replace(cx, parent, q, *vp);
+ if (!ok)
+ goto out;
+
+ vxml = XMLARRAY_MEMBER(&parent->xml_kids, q, JSXML);
+ if (!vxml)
+ goto out;
+ roots[VAL_ROOT] = *vp = OBJECT_TO_JSVAL(vxml->object);
+ }
+
+ /*
+ * 2(g)(iii).
+ * Erratum: _V_ may not be of type XML, but all index-named
+ * properties _x[i]_ in an XMLList _x_ must be of type XML,
+ * according to 9.2.1.1 Overview and other places in the spec.
+ *
+ * Thanks to 2(d), we know _V_ (*vp here) is either a string
+ * or an XML/XMLList object. If *vp is a string, call ToXML
+ * on it to satisfy the constraint.
+ */
+ if (!vxml) {
+ JS_ASSERT(JSVAL_IS_STRING(*vp));
+ vobj = ToXML(cx, *vp);
+ if (!vobj)
+ goto bad;
+ roots[VAL_ROOT] = *vp = OBJECT_TO_JSVAL(vobj);
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ }
+ XMLARRAY_SET_MEMBER(&xml->xml_kids, i, vxml);
+ }
+
+ /* 2(h). */
+ else {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ goto bad;
+ id = ATOM_KEY(cx->runtime->atomState.starAtom);
+ ok = PutProperty(cx, kidobj, id, vp);
+ if (!ok)
+ goto out;
+ }
+ } else {
+ /*
+ * ECMA-357 9.2.1.2/9.1.1.2 qname case.
+ */
+ nameqn = ToXMLName(cx, id, &funid);
+ if (!nameqn)
+ goto bad;
+ if (funid) {
+ ok = js_SetProperty(cx, obj, funid, vp);
+ goto out;
+ }
+ nameobj = nameqn;
+ roots[ID_ROOT] = OBJECT_TO_JSVAL(nameobj);
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /*
+ * Step 3 of 9.2.1.2.
+ * Erratum: if x.[[Length]] > 1 or [[ResolveValue]] returns null
+ * or an r with r.[[Length]] != 1, throw TypeError.
+ */
+ n = JSXML_LENGTH(xml);
+ if (n > 1)
+ goto type_error;
+ if (n == 0) {
+ ok = ResolveValue(cx, xml, &rxml);
+ if (!ok)
+ goto out;
+ if (!rxml || JSXML_LENGTH(rxml) != 1)
+ goto type_error;
+ ok = Append(cx, xml, rxml);
+ if (!ok)
+ goto out;
+ }
+ JS_ASSERT(JSXML_LENGTH(xml) == 1);
+ xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (!xml)
+ goto out;
+ JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST);
+ obj = js_GetXMLObject(cx, xml);
+ if (!obj)
+ goto bad;
+ roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj);
+
+ /* FALL THROUGH to non-list case */
+ }
+
+ /*
+ * ECMA-357 9.1.1.2.
+ * Erratum: move steps 3 and 4 to before 1 and 2, to avoid wasted
+ * effort in ToString or [[DeepCopy]].
+ */
+
+ if (JSXML_HAS_VALUE(xml))
+ goto out;
+
+ if (!vxml ||
+ vxml->xml_class == JSXML_CLASS_TEXT ||
+ vxml->xml_class == JSXML_CLASS_ATTRIBUTE) {
+ ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp);
+ if (!ok)
+ goto out;
+ } else {
+ rxml = DeepCopyInLRS(cx, vxml, 0);
+ if (!rxml || !js_GetXMLObject(cx, rxml))
+ goto bad;
+ vxml = rxml;
+ *vp = OBJECT_TO_JSVAL(vxml->object);
+ }
+ roots[VAL_ROOT] = *vp;
+
+ /*
+ * 6.
+ * Erratum: why is this done here, so early? use is way later....
+ */
+ ok = js_GetDefaultXMLNamespace(cx, &nsval);
+ if (!ok)
+ goto out;
+
+ if (OBJ_GET_CLASS(cx, nameobj) == &js_AttributeNameClass) {
+ /* 7(a). */
+ if (!js_IsXMLName(cx, OBJECT_TO_JSVAL(nameobj)))
+ goto out;
+
+ /* 7(b-c). */
+ if (vxml && vxml->xml_class == JSXML_CLASS_LIST) {
+ n = vxml->xml_kids.length;
+ if (n == 0) {
+ *vp = STRING_TO_JSVAL(cx->runtime->emptyString);
+ } else {
+ left = KidToString(cx, vxml, 0);
+ if (!left)
+ goto bad;
+
+ space = ATOM_TO_STRING(cx->runtime->atomState.spaceAtom);
+ for (i = 1; i < n; i++) {
+ left = js_ConcatStrings(cx, left, space);
+ if (!left)
+ goto bad;
+ right = KidToString(cx, vxml, i);
+ if (!right)
+ goto bad;
+ left = js_ConcatStrings(cx, left, right);
+ if (!left)
+ goto bad;
+ }
+
+ roots[VAL_ROOT] = *vp = STRING_TO_JSVAL(left);
+ }
+ } else {
+ ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp);
+ if (!ok)
+ goto out;
+ roots[VAL_ROOT] = *vp;
+ }
+
+ /* 7(d-e). */
+ match = NULL;
+ for (i = 0, n = xml->xml_attrs.length; i < n; i++) {
+ attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML);
+ if (!attr)
+ continue;
+ attrqn = attr->name;
+ if (js_EqualStrings(GetLocalName(attrqn),
+ GetLocalName(nameqn))) {
+ uri = GetURI(nameqn);
+ if (!uri || js_EqualStrings(GetURI(attrqn), uri)) {
+ if (!match) {
+ match = attr;
+ } else {
+ DeleteNamedProperty(cx, xml, attrqn, JS_TRUE);
+ --i;
+ }
+ }
+ }
+ }
+
+ /* 7(f). */
+ attr = match;
+ if (!attr) {
+ /* 7(f)(i-ii). */
+ uri = GetURI(nameqn);
+ if (!uri) {
+ left = right = cx->runtime->emptyString;
+ } else {
+ left = uri;
+ right = GetPrefix(nameqn);
+ }
+ nameqn = NewXMLQName(cx, left, right, GetLocalName(nameqn));
+ if (!nameqn)
+ goto bad;
+
+ /* 7(f)(iii). */
+ attr = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE);
+ if (!attr)
+ goto bad;
+ attr->parent = xml;
+ attr->name = nameqn;
+
+ /* 7(f)(iv). */
+ ok = XMLARRAY_ADD_MEMBER(cx, &xml->xml_attrs, n, attr);
+ if (!ok)
+ goto out;
+
+ /* 7(f)(v-vi). */
+ ns = GetNamespace(cx, nameqn, NULL);
+ if (!ns)
+ goto bad;
+ ok = AddInScopeNamespace(cx, xml, ns);
+ if (!ok)
+ goto out;
+ }
+
+ /* 7(g). */
+ attr->xml_value = JSVAL_TO_STRING(*vp);
+ goto out;
+ }
+
+ /* 8-9. */
+ if (!js_IsXMLName(cx, OBJECT_TO_JSVAL(nameobj)) &&
+ !IS_STAR(GetLocalName(nameqn))) {
+ goto out;
+ }
+
+ /* 10-11. */
+ id = JSVAL_VOID;
+ primitiveAssign = !vxml && !IS_STAR(GetLocalName(nameqn));
+
+ /* 12. */
+ k = n = xml->xml_kids.length;
+ matchIndex = XML_NOT_FOUND;
+ kid2 = NULL;
+ while (k != 0) {
+ --k;
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, k, JSXML);
+ if (kid && MatchElemName(nameqn, kid)) {
+ if (matchIndex != XML_NOT_FOUND)
+ DeleteByIndex(cx, xml, matchIndex);
+ matchIndex = k;
+ kid2 = kid;
+ }
+ }
+
+ /*
+ * Erratum: ECMA-357 specified child insertion inconsistently:
+ * insertChildBefore and insertChildAfter insert an arbitrary XML
+ * instance, and therefore can create cycles, but appendChild as
+ * specified by the "Overview" of 13.4.4.3 calls [[DeepCopy]] on
+ * its argument. But the "Semantics" in 13.4.4.3 do not include
+ * any [[DeepCopy]] call.
+ *
+ * Fixing this (https://bugzilla.mozilla.org/show_bug.cgi?id=312692)
+ * required adding cycle detection, and allowing duplicate kids to
+ * be created (see comment 6 in the bug). Allowing duplicate kid
+ * references means the loop above will delete all but the lowest
+ * indexed reference, and each [[DeleteByIndex]] nulls the kid's
+ * parent. Thus the need to restore parent here. This is covered
+ * by https://bugzilla.mozilla.org/show_bug.cgi?id=327564.
+ */
+ if (kid2) {
+ JS_ASSERT(kid2->parent == xml || !kid2->parent);
+ if (!kid2->parent)
+ kid2->parent = xml;
+ }
+
+ /* 13. */
+ if (matchIndex == XML_NOT_FOUND) {
+ /* 13(a). */
+ matchIndex = n;
+
+ /* 13(b). */
+ if (primitiveAssign) {
+ uri = GetURI(nameqn);
+ if (!uri) {
+ ns = JSVAL_TO_OBJECT(nsval);
+ left = GetURI(ns);
+ right = GetPrefix(ns);
+ } else {
+ left = uri;
+ right = GetPrefix(nameqn);
+ }
+ nameqn = NewXMLQName(cx, left, right, GetLocalName(nameqn));
+ if (!nameqn)
+ goto bad;
+
+ /* 13(b)(iii). */
+ vobj = js_NewXMLObject(cx, JSXML_CLASS_ELEMENT);
+ if (!vobj)
+ goto bad;
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ vxml->parent = xml;
+ vxml->name = nameqn;
+
+ /* 13(b)(iv-vi). */
+ ns = GetNamespace(cx, nameqn, NULL);
+ if (!ns)
+ goto bad;
+ ok = Replace(cx, xml, matchIndex, OBJECT_TO_JSVAL(vobj));
+ if (!ok)
+ goto out;
+ ok = AddInScopeNamespace(cx, vxml, ns);
+ if (!ok)
+ goto out;
+ }
+ }
+
+ /* 14. */
+ if (primitiveAssign) {
+ JSXMLArrayCursor cursor;
+
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ cursor.index = matchIndex;
+ kid = (JSXML *) XMLArrayCursorItem(&cursor);
+ if (JSXML_HAS_KIDS(kid)) {
+ XMLArrayFinish(cx, &kid->xml_kids);
+ ok = XMLArrayInit(cx, &kid->xml_kids, 1);
+ }
+
+ /* 14(b-c). */
+ /* XXXbe Erratum? redundant w.r.t. 7(b-c) else clause above */
+ if (ok) {
+ ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp);
+ if (ok && !IS_EMPTY(JSVAL_TO_STRING(*vp))) {
+ roots[VAL_ROOT] = *vp;
+ if ((JSXML *) XMLArrayCursorItem(&cursor) == kid)
+ ok = Replace(cx, kid, 0, *vp);
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ } else {
+ /* 15(a). */
+ ok = Replace(cx, xml, matchIndex, *vp);
+ }
+ }
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ js_LeaveLocalRootScope(cx);
+ return ok;
+
+type_error:
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_XMLLIST_PUT,
+ js_ValueToPrintableString(cx, id));
+bad:
+ ok = JS_FALSE;
+ goto out;
+}
+
+/* ECMA-357 9.1.1.10 XML [[ResolveValue]], 9.2.1.10 XMLList [[ResolveValue]]. */
+static JSBool
+ResolveValue(JSContext *cx, JSXML *list, JSXML **result)
+{
+ JSXML *target, *base;
+ JSObject *targetprop;
+ jsval id, tv;
+
+ /* Our caller must be protecting newborn objects. */
+ JS_ASSERT(cx->localRootStack);
+
+ if (list->xml_class != JSXML_CLASS_LIST || list->xml_kids.length != 0) {
+ if (!js_GetXMLObject(cx, list))
+ return JS_FALSE;
+ *result = list;
+ return JS_TRUE;
+ }
+
+ target = list->xml_target;
+ targetprop = list->xml_targetprop;
+ if (!target || !targetprop || IS_STAR(GetLocalName(targetprop))) {
+ *result = NULL;
+ return JS_TRUE;
+ }
+
+ if (OBJ_GET_CLASS(cx, targetprop) == &js_AttributeNameClass) {
+ *result = NULL;
+ return JS_TRUE;
+ }
+
+ if (!ResolveValue(cx, target, &base))
+ return JS_FALSE;
+ if (!base) {
+ *result = NULL;
+ return JS_TRUE;
+ }
+ if (!js_GetXMLObject(cx, base))
+ return JS_FALSE;
+
+ id = OBJECT_TO_JSVAL(targetprop);
+ if (!GetProperty(cx, base->object, id, &tv))
+ return JS_FALSE;
+ target = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(tv));
+
+ if (JSXML_LENGTH(target) == 0) {
+ if (base->xml_class == JSXML_CLASS_LIST && JSXML_LENGTH(base) > 1) {
+ *result = NULL;
+ return JS_TRUE;
+ }
+ tv = STRING_TO_JSVAL(cx->runtime->emptyString);
+ if (!PutProperty(cx, base->object, id, &tv))
+ return JS_FALSE;
+ if (!GetProperty(cx, base->object, id, &tv))
+ return JS_FALSE;
+ target = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(tv));
+ }
+
+ *result = target;
+ return JS_TRUE;
+}
+
+static JSBool
+HasNamedProperty(JSXML *xml, JSObject *nameqn)
+{
+ JSBool found;
+ JSXMLArrayCursor cursor;
+ JSXML *kid;
+ JSXMLArray *array;
+ JSXMLNameMatcher matcher;
+ uint32 i, n;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ found = JS_FALSE;
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ found = HasNamedProperty(kid, nameqn);
+ if (found)
+ break;
+ }
+ XMLArrayCursorFinish(&cursor);
+ return found;
+ }
+
+ if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ if (OBJ_GET_CLASS(cx, nameqn) == &js_AttributeNameClass) {
+ array = &xml->xml_attrs;
+ matcher = MatchAttrName;
+ } else {
+ array = &xml->xml_kids;
+ matcher = MatchElemName;
+ }
+ for (i = 0, n = array->length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(array, i, JSXML);
+ if (kid && matcher(nameqn, kid))
+ return JS_TRUE;
+ }
+ }
+
+ return JS_FALSE;
+}
+
+static JSBool
+HasIndexedProperty(JSXML *xml, uint32 i)
+{
+ if (xml->xml_class == JSXML_CLASS_LIST)
+ return i < JSXML_LENGTH(xml);
+
+ if (xml->xml_class == JSXML_CLASS_ELEMENT)
+ return i == 0;
+
+ return JS_FALSE;
+}
+
+static JSBool
+HasSimpleContent(JSXML *xml);
+
+static JSBool
+HasFunctionProperty(JSContext *cx, JSObject *obj, jsid funid, JSBool *found)
+{
+ JSObject *pobj;
+ JSProperty *prop;
+ JSXML *xml;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_XMLClass);
+
+ if (!js_LookupProperty(cx, obj, funid, &pobj, &prop))
+ return JS_FALSE;
+ if (prop) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ } else {
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (HasSimpleContent(xml)) {
+ /*
+ * Search in String.prototype to set found whenever
+ * js_GetXMLFunction returns existing function.
+ */
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, NULL, &tvr);
+ ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(JSProto_String),
+ &tvr.u.object);
+ JS_ASSERT(tvr.u.object);
+ if (ok) {
+ ok = js_LookupProperty(cx, tvr.u.object, funid, &pobj, &prop);
+ if (ok && prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+ }
+ }
+ *found = (prop != NULL);
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.6 XML [[HasProperty]] and 9.2.1.5 XMLList [[HasProperty]]. */
+static JSBool
+HasProperty(JSContext *cx, JSObject *obj, jsval id, JSBool *found)
+{
+ JSXML *xml;
+ uint32 i;
+ JSObject *qn;
+ jsid funid;
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (js_IdIsIndex(id, &i)) {
+ *found = HasIndexedProperty(xml, i);
+ } else {
+ qn = ToXMLName(cx, id, &funid);
+ if (!qn)
+ return JS_FALSE;
+ if (funid) {
+ if (!HasFunctionProperty(cx, obj, funid, found))
+ return JS_FALSE;
+ } else {
+ *found = HasNamedProperty(xml, qn);
+ }
+ }
+ return JS_TRUE;
+}
+
+static void
+xml_finalize(JSContext *cx, JSObject *obj)
+{
+ JSXML *xml;
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (!xml)
+ return;
+ if (xml->object == obj)
+ xml->object = NULL;
+}
+
+static void
+xml_trace_vector(JSTracer *trc, JSXML **vec, uint32 len)
+{
+ uint32 i;
+ JSXML *xml;
+
+ for (i = 0; i < len; i++) {
+ xml = vec[i];
+ if (xml) {
+ JS_SET_TRACING_INDEX(trc, "xml_vector", i);
+ JS_CallTracer(trc, xml, JSTRACE_XML);
+ }
+ }
+}
+
+/*
+ * js_XMLObjectOps.newObjectMap == js_NewObjectMap, so XML objects appear to
+ * be native. Therefore, xml_lookupProperty must return a valid JSProperty
+ * pointer parameter via *propp to signify "property found". Since the only
+ * call to xml_lookupProperty is via OBJ_LOOKUP_PROPERTY, and then only from
+ * js_FindProperty (in jsobj.c, called from jsinterp.c) or from JSOP_IN case
+ * in the interpreter, the only time we add a JSScopeProperty here is when an
+ * unqualified name is being accessed or when "name in xml" is called.
+ *
+ * This scope property keeps the JSOP_NAME code in js_Interpret happy by
+ * giving it an sprop with (getter, setter) == (GetProperty, PutProperty).
+ *
+ * NB: xml_deleteProperty must take care to remove any property added here.
+ *
+ * FIXME This clashes with the function namespace implementation which also
+ * uses native properties. Effectively after xml_lookupProperty any property
+ * stored previously using assignments to xml.function::name will be removed.
+ * We partially workaround the problem in js_GetXMLFunction. There we take
+ * advantage of the fact that typically function:: is used to access the
+ * functions from XML.prototype. So when js_GetProperty returns a non-function
+ * property, we assume that it represents the result of GetProperty setter
+ * hiding the function and use an extra prototype chain lookup to recover it.
+ * For a proper solution see bug 355257.
+*/
+static JSBool
+xml_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp)
+{
+ jsval v;
+ JSBool found;
+ JSXML *xml;
+ uint32 i;
+ JSObject *qn;
+ jsid funid;
+ JSScopeProperty *sprop;
+
+ v = ID_TO_VALUE(id);
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (js_IdIsIndex(v, &i)) {
+ found = HasIndexedProperty(xml, i);
+ } else {
+ qn = ToXMLName(cx, v, &funid);
+ if (!qn)
+ return JS_FALSE;
+ if (funid)
+ return js_LookupProperty(cx, obj, funid, objp, propp);
+ found = HasNamedProperty(xml, qn);
+ }
+ if (!found) {
+ *objp = NULL;
+ *propp = NULL;
+ } else {
+ sprop = js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty,
+ SPROP_INVALID_SLOT, JSPROP_ENUMERATE,
+ 0, 0);
+ if (!sprop)
+ return JS_FALSE;
+
+ JS_LOCK_OBJ(cx, obj);
+ *objp = obj;
+ *propp = (JSProperty *) sprop;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ JSProperty **propp)
+{
+ if (VALUE_IS_FUNCTION(cx, value) || getter || setter ||
+ (attrs & JSPROP_ENUMERATE) == 0 ||
+ (attrs & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED))) {
+ return js_DefineProperty(cx, obj, id, value, getter, setter, attrs,
+ propp);
+ }
+
+ if (!PutProperty(cx, obj, ID_TO_VALUE(id), &value))
+ return JS_FALSE;
+ if (propp)
+ *propp = NULL;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ if (id == JS_DEFAULT_XML_NAMESPACE_ID) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ return GetProperty(cx, obj, ID_TO_VALUE(id), vp);
+}
+
+static JSBool
+xml_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return PutProperty(cx, obj, ID_TO_VALUE(id), vp);
+}
+
+static JSBool
+FoundProperty(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ JSBool *foundp)
+{
+ if (!prop)
+ return HasProperty(cx, obj, ID_TO_VALUE(id), foundp);
+
+ *foundp = JS_TRUE;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_getAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSBool found;
+
+ if (!FoundProperty(cx, obj, id, prop, &found))
+ return JS_FALSE;
+ *attrsp = found ? JSPROP_ENUMERATE : 0;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSBool found;
+
+ if (!FoundProperty(cx, obj, id, prop, &found))
+ return JS_FALSE;
+ if (found) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_SET_XML_ATTRS);
+ }
+ return !found;
+}
+
+static JSBool
+xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
+{
+ JSXML *xml;
+ jsval idval;
+ uint32 index;
+ JSObject *nameqn;
+ jsid funid;
+
+ idval = ID_TO_VALUE(id);
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (js_IdIsIndex(idval, &index)) {
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ /* See NOTE in spec: this variation is reserved for future use. */
+ ReportBadXMLName(cx, id);
+ return JS_FALSE;
+ }
+
+ /* ECMA-357 9.2.1.3. */
+ DeleteListElement(cx, xml, index);
+ } else {
+ nameqn = ToXMLName(cx, idval, &funid);
+ if (!nameqn)
+ return JS_FALSE;
+ if (funid)
+ return js_DeleteProperty(cx, obj, funid, rval);
+
+ DeleteNamedProperty(cx, xml, nameqn,
+ OBJ_GET_CLASS(cx, nameqn) ==
+ &js_AttributeNameClass);
+ }
+
+ /*
+ * If this object has its own (mutable) scope, then we may have added a
+ * property to the scope in xml_lookupProperty for it to return to mean
+ * "found" and to provide a handle for access operations to call the
+ * property's getter or setter. But now it's time to remove any such
+ * property, to purge the property cache and remove the scope entry.
+ */
+ if (OBJ_SCOPE(obj)->object == obj && !js_DeleteProperty(cx, obj, id, rval))
+ return JS_FALSE;
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_defaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
+{
+ JSXML *xml;
+
+ if (hint == JSTYPE_OBJECT) {
+ /* Called from for..in code in js_Interpret: return an XMLList. */
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ obj = ToXMLList(cx, OBJECT_TO_JSVAL(obj));
+ if (!obj)
+ return JS_FALSE;
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+ }
+
+ return JS_CallFunctionName(cx, obj, js_toString_str, 0, NULL, vp);
+}
+
+static JSBool
+xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ JSXML *xml;
+ uint32 length, index;
+ JSXMLArrayCursor *cursor;
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ length = JSXML_LENGTH(xml);
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ if (length == 0) {
+ cursor = NULL;
+ } else {
+ cursor = (JSXMLArrayCursor *) JS_malloc(cx, sizeof *cursor);
+ if (!cursor)
+ return JS_FALSE;
+ XMLArrayCursorInit(cursor, &xml->xml_kids);
+ }
+ *statep = PRIVATE_TO_JSVAL(cursor);
+ if (idp)
+ *idp = INT_TO_JSID(length);
+ break;
+
+ case JSENUMERATE_NEXT:
+ cursor = (JSXMLArrayCursor *) JSVAL_TO_PRIVATE(*statep);
+ if (cursor && cursor->array && (index = cursor->index) < length) {
+ *idp = INT_TO_JSID(index);
+ cursor->index = index + 1;
+ break;
+ }
+ /* FALL THROUGH */
+
+ case JSENUMERATE_DESTROY:
+ cursor = (JSXMLArrayCursor *) JSVAL_TO_PRIVATE(*statep);
+ if (cursor) {
+ XMLArrayCursorFinish(cursor);
+ JS_free(cx, cursor);
+ }
+ *statep = JSVAL_NULL;
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ return JS_TRUE;
+}
+
+static void
+xml_trace(JSTracer *trc, JSObject *obj)
+{
+ JSXML *xml;
+
+ xml = (JSXML *) JS_GetPrivate(trc->context, obj);
+ if (xml)
+ JS_CALL_TRACER(trc, xml, JSTRACE_XML, "private");
+}
+
+static void
+xml_clear(JSContext *cx, JSObject *obj)
+{
+}
+
+static JSBool
+HasSimpleContent(JSXML *xml)
+{
+ JSXML *kid;
+ JSBool simple;
+ uint32 i, n;
+
+again:
+ switch (xml->xml_class) {
+ case JSXML_CLASS_COMMENT:
+ case JSXML_CLASS_PROCESSING_INSTRUCTION:
+ return JS_FALSE;
+ case JSXML_CLASS_LIST:
+ if (xml->xml_kids.length == 0)
+ return JS_TRUE;
+ if (xml->xml_kids.length == 1) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (kid) {
+ xml = kid;
+ goto again;
+ }
+ }
+ /* FALL THROUGH */
+ default:
+ simple = JS_TRUE;
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ simple = JS_FALSE;
+ break;
+ }
+ }
+ return simple;
+ }
+}
+
+/*
+ * 11.2.2.1 Step 3(d) onward.
+ */
+static JSObject *
+xml_getMethod(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSTempValueRooter tvr;
+
+ JS_ASSERT(JS_InstanceOf(cx, obj, &js_XMLClass, NULL));
+
+ /*
+ * As our callers have a bad habit of passing a pointer to an unrooted
+ * local value as vp, we use a proper root here.
+ */
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ if (!js_GetXMLFunction(cx, obj, id, &tvr.u.value))
+ obj = NULL;
+ *vp = tvr.u.value;
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return obj;
+}
+
+static JSBool
+xml_setMethod(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return js_SetProperty(cx, obj, id, vp);
+}
+
+static JSBool
+xml_enumerateValues(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp, jsval *vp)
+{
+ JSXML *xml, *kid;
+ uint32 length, index;
+ JSXMLArrayCursor *cursor;
+ JSObject *kidobj;
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ length = JSXML_LENGTH(xml);
+ JS_ASSERT(INT_FITS_IN_JSVAL(length));
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ if (length == 0) {
+ cursor = NULL;
+ } else {
+ cursor = (JSXMLArrayCursor *) JS_malloc(cx, sizeof *cursor);
+ if (!cursor)
+ return JS_FALSE;
+ XMLArrayCursorInit(cursor, &xml->xml_kids);
+ }
+ *statep = PRIVATE_TO_JSVAL(cursor);
+ if (idp)
+ *idp = INT_TO_JSID(length);
+ if (vp)
+ *vp = JSVAL_VOID;
+ break;
+
+ case JSENUMERATE_NEXT:
+ cursor = (JSXMLArrayCursor *) JSVAL_TO_PRIVATE(*statep);
+ if (cursor && cursor->array && (index = cursor->index) < length) {
+ while (!(kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML))) {
+ if (++index == length)
+ goto destroy;
+ }
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ return JS_FALSE;
+ JS_ASSERT(INT_FITS_IN_JSVAL(index));
+ *idp = INT_TO_JSID(index);
+ *vp = OBJECT_TO_JSVAL(kidobj);
+ cursor->index = index + 1;
+ break;
+ }
+ /* FALL THROUGH */
+
+ case JSENUMERATE_DESTROY:
+ cursor = (JSXMLArrayCursor *) JSVAL_TO_PRIVATE(*statep);
+ if (cursor) {
+ destroy:
+ XMLArrayCursorFinish(cursor);
+ JS_free(cx, cursor);
+ }
+ *statep = JSVAL_NULL;
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ JSXML *xml, *vxml;
+ JSObject *vobj;
+ JSBool ok;
+ JSString *str, *vstr;
+ jsdouble d, d2;
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ vxml = NULL;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ vobj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, vobj))
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ }
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ ok = Equals(cx, xml, v, bp);
+ } else if (vxml) {
+ if (vxml->xml_class == JSXML_CLASS_LIST) {
+ ok = Equals(cx, vxml, OBJECT_TO_JSVAL(obj), bp);
+ } else {
+ if (((xml->xml_class == JSXML_CLASS_TEXT ||
+ xml->xml_class == JSXML_CLASS_ATTRIBUTE) &&
+ HasSimpleContent(vxml)) ||
+ ((vxml->xml_class == JSXML_CLASS_TEXT ||
+ vxml->xml_class == JSXML_CLASS_ATTRIBUTE) &&
+ HasSimpleContent(xml))) {
+ ok = js_EnterLocalRootScope(cx);
+ if (ok) {
+ str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
+ vstr = js_ValueToString(cx, v);
+ ok = str && vstr;
+ if (ok)
+ *bp = js_EqualStrings(str, vstr);
+ js_LeaveLocalRootScope(cx);
+ }
+ } else {
+ ok = XMLEquals(cx, xml, vxml, bp);
+ }
+ }
+ } else {
+ ok = js_EnterLocalRootScope(cx);
+ if (ok) {
+ if (HasSimpleContent(xml)) {
+ str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
+ vstr = js_ValueToString(cx, v);
+ ok = str && vstr;
+ if (ok)
+ *bp = js_EqualStrings(str, vstr);
+ } else if (JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v)) {
+ str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
+ if (!str) {
+ ok = JS_FALSE;
+ } else if (JSVAL_IS_STRING(v)) {
+ *bp = js_EqualStrings(str, JSVAL_TO_STRING(v));
+ } else {
+ ok = JS_ValueToNumber(cx, STRING_TO_JSVAL(str), &d);
+ if (ok) {
+ d2 = JSVAL_IS_INT(v) ? JSVAL_TO_INT(v)
+ : *JSVAL_TO_DOUBLE(v);
+ *bp = JSDOUBLE_COMPARE(d, ==, d2, JS_FALSE);
+ }
+ }
+ } else {
+ *bp = JS_FALSE;
+ }
+ js_LeaveLocalRootScope(cx);
+ }
+ }
+ return ok;
+}
+
+static JSBool
+xml_concatenate(JSContext *cx, JSObject *obj, jsval v, jsval *vp)
+{
+ JSBool ok;
+ JSObject *listobj, *robj;
+ JSXML *list, *lxml, *rxml;
+
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ return JS_FALSE;
+
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!listobj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ lxml = (JSXML *) JS_GetPrivate(cx, obj);
+ ok = Append(cx, list, lxml);
+ if (!ok)
+ goto out;
+
+ if (VALUE_IS_XML(cx, v)) {
+ rxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ } else {
+ robj = ToXML(cx, v);
+ if (!robj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ rxml = (JSXML *) JS_GetPrivate(cx, robj);
+ }
+ ok = Append(cx, list, rxml);
+ if (!ok)
+ goto out;
+
+ *vp = OBJECT_TO_JSVAL(listobj);
+out:
+ js_LeaveLocalRootScopeWithResult(cx, *vp);
+ return ok;
+}
+
+/* Use js_NewObjectMap so XML objects satisfy OBJ_IS_NATIVE tests. */
+JS_FRIEND_DATA(JSXMLObjectOps) js_XMLObjectOps = {
+ { js_NewObjectMap, js_DestroyObjectMap,
+ xml_lookupProperty, xml_defineProperty,
+ xml_getProperty, xml_setProperty,
+ xml_getAttributes, xml_setAttributes,
+ xml_deleteProperty, xml_defaultValue,
+ xml_enumerate, js_CheckAccess,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, xml_hasInstance,
+ js_SetProtoOrParent, js_SetProtoOrParent,
+ js_TraceObject, xml_clear,
+ NULL, NULL },
+ xml_getMethod, xml_setMethod,
+ xml_enumerateValues, xml_equality,
+ xml_concatenate
+};
+
+static JSObjectOps *
+xml_getObjectOps(JSContext *cx, JSClass *clasp)
+{
+ return &js_XMLObjectOps.base;
+}
+
+JS_FRIEND_DATA(JSClass) js_XMLClass = {
+ js_XML_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_XML),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, xml_finalize,
+ xml_getObjectOps, NULL, NULL, NULL,
+ NULL, NULL, JS_CLASS_TRACE(xml_trace), NULL
+};
+
+static JSXML *
+StartNonListXMLMethod(JSContext *cx, jsval *vp, JSObject **objp)
+{
+ JSXML *xml;
+ JSFunction *fun;
+ char numBuf[12];
+
+ JS_ASSERT(VALUE_IS_FUNCTION(cx, *vp));
+
+ *objp = JS_THIS_OBJECT(cx, vp);
+ xml = (JSXML *) JS_GetInstancePrivate(cx, *objp, &js_XMLClass, vp + 2);
+ if (!xml || xml->xml_class != JSXML_CLASS_LIST)
+ return xml;
+
+ if (xml->xml_kids.length == 1) {
+ xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (xml) {
+ *objp = js_GetXMLObject(cx, xml);
+ if (!*objp)
+ return NULL;
+ vp[1] = OBJECT_TO_JSVAL(*objp);
+ return xml;
+ }
+ }
+
+ fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(*vp));
+ JS_snprintf(numBuf, sizeof numBuf, "%u", xml->xml_kids.length);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_NON_LIST_XML_METHOD,
+ JS_GetFunctionName(fun), numBuf);
+ return NULL;
+}
+
+/* Beware: these two are not bracketed by JS_BEGIN/END_MACRO. */
+#define XML_METHOD_PROLOG \
+ JSObject *obj = JS_THIS_OBJECT(cx, vp); \
+ JSXML *xml = (JSXML *)JS_GetInstancePrivate(cx, obj, &js_XMLClass, vp+2); \
+ if (!xml) \
+ return JS_FALSE
+
+#define NON_LIST_XML_METHOD_PROLOG \
+ JSObject *obj; \
+ JSXML *xml = StartNonListXMLMethod(cx, vp, &obj); \
+ if (!xml) \
+ return JS_FALSE; \
+ JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST)
+
+static JSBool
+xml_addNamespace(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *ns;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (xml->xml_class != JSXML_CLASS_ELEMENT)
+ goto done;
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ if (!NamespaceHelper(cx, NULL, argc == 0 ? -1 : 1, vp + 2, vp))
+ return JS_FALSE;
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
+
+ ns = JSVAL_TO_OBJECT(*vp);
+ if (!AddInScopeNamespace(cx, xml, ns))
+ return JS_FALSE;
+ ns->fslots[JSSLOT_DECLARED] = JSVAL_TRUE;
+
+ done:
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_appendChild(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name, v;
+ JSObject *vobj;
+ JSXML *vxml;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ if (!js_GetAnyName(cx, &name))
+ return JS_FALSE;
+
+ if (!GetProperty(cx, obj, name, &v))
+ return JS_FALSE;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ vobj = JSVAL_TO_OBJECT(v);
+ JS_ASSERT(OBJECT_IS_XML(cx, vobj));
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ JS_ASSERT(vxml->xml_class == JSXML_CLASS_LIST);
+
+ if (!IndexToIdVal(cx, vxml->xml_kids.length, &name))
+ return JS_FALSE;
+ *vp = (argc != 0) ? vp[2] : JSVAL_VOID;
+ if (!PutProperty(cx, JSVAL_TO_OBJECT(v), name, vp))
+ return JS_FALSE;
+
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_attribute(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *qn;
+
+ if (argc == 0) {
+ js_ReportMissingArg(cx, vp, 0);
+ return JS_FALSE;
+ }
+
+ qn = ToAttributeName(cx, vp[2]);
+ if (!qn)
+ return JS_FALSE;
+ vp[2] = OBJECT_TO_JSVAL(qn); /* local root */
+
+ return GetProperty(cx, JS_THIS_OBJECT(cx, vp), vp[2], vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_attributes(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSObject *qn;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ name = ATOM_KEY(cx->runtime->atomState.starAtom);
+ qn = ToAttributeName(cx, name);
+ if (!qn)
+ return JS_FALSE;
+ name = OBJECT_TO_JSVAL(qn);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, name, &tvr);
+ ok = GetProperty(cx, JS_THIS_OBJECT(cx, vp), name, vp);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSXML *
+xml_list_helper(JSContext *cx, JSXML *xml, jsval *rval)
+{
+ JSObject *listobj;
+ JSXML *list;
+
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!listobj)
+ return NULL;
+
+ *rval = OBJECT_TO_JSVAL(listobj);
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ list->xml_target = xml;
+ return list;
+}
+
+static JSBool
+xml_child_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval name,
+ jsval *rval)
+{
+ uint32 index;
+ JSXML *kid;
+ JSObject *kidobj;
+
+ /* ECMA-357 13.4.4.6 */
+ JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST);
+
+ if (js_IdIsIndex(name, &index)) {
+ if (index >= JSXML_LENGTH(xml)) {
+ *rval = JSVAL_VOID;
+ } else {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML);
+ if (!kid) {
+ *rval = JSVAL_VOID;
+ } else {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(kidobj);
+ }
+ }
+ return JS_TRUE;
+ }
+
+ return GetProperty(cx, obj, name, rval);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_child(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name, v;
+ JSXML *list, *kid, *vxml;
+ JSXMLArrayCursor cursor;
+ JSObject *kidobj;
+
+ XML_METHOD_PROLOG;
+ name = argc != 0 ? vp[2] : JSVAL_VOID;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /* ECMA-357 13.5.4.4 */
+ list = xml_list_helper(cx, xml, vp);
+ if (!list)
+ return JS_FALSE;
+
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ break;
+ if (!xml_child_helper(cx, kidobj, kid, name, &v))
+ break;
+ if (JSVAL_IS_VOID(v)) {
+ /* The property didn't exist in this kid. */
+ continue;
+ }
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ if ((!JSXML_HAS_KIDS(vxml) || vxml->xml_kids.length != 0) &&
+ !Append(cx, list, vxml)) {
+ break;
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ return !kid;
+ }
+
+ /* ECMA-357 Edition 2 13.3.4.6 (note 13.3, not 13.4 as in Edition 1). */
+ if (!xml_child_helper(cx, obj, xml, name, vp))
+ return JS_FALSE;
+ if (JSVAL_IS_VOID(*vp) && !xml_list_helper(cx, xml, vp))
+ return JS_FALSE;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_childIndex(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSXML *parent;
+ uint32 i, n;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ parent = xml->parent;
+ if (!parent || xml->xml_class == JSXML_CLASS_ATTRIBUTE) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ for (i = 0, n = JSXML_LENGTH(parent); i < n; i++) {
+ if (XMLARRAY_MEMBER(&parent->xml_kids, i, JSXML) == xml)
+ break;
+ }
+ JS_ASSERT(i < n);
+ return js_NewNumberInRootedValue(cx, i, vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_children(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+
+ name = ATOM_KEY(cx->runtime->atomState.starAtom);
+ return GetProperty(cx, JS_THIS_OBJECT(cx, vp), name, vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_comments_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval *vp)
+{
+ JSXML *list, *kid, *vxml;
+ JSBool ok;
+ uint32 i, n;
+ JSObject *kidobj;
+ jsval v;
+
+ list = xml_list_helper(cx, xml, vp);
+ if (!list)
+ return JS_FALSE;
+
+ ok = JS_TRUE;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /* 13.5.4.6 Step 2. */
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ break;
+ kidobj = js_GetXMLObject(cx, kid);
+ if (kidobj) {
+ ok = xml_comments_helper(cx, kidobj, kid, &v);
+ } else {
+ ok = JS_FALSE;
+ v = JSVAL_NULL;
+ }
+ js_LeaveLocalRootScopeWithResult(cx, v);
+ if (!ok)
+ break;
+ vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ if (JSXML_LENGTH(vxml) != 0) {
+ ok = Append(cx, list, vxml);
+ if (!ok)
+ break;
+ }
+ }
+ }
+ } else {
+ /* 13.4.4.9 Step 2. */
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_COMMENT) {
+ ok = Append(cx, list, kid);
+ if (!ok)
+ break;
+ }
+ }
+ }
+
+ return ok;
+}
+
+static JSBool
+xml_comments(JSContext *cx, uintN argc, jsval *vp)
+{
+ XML_METHOD_PROLOG;
+ return xml_comments_helper(cx, obj, xml, vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_contains(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval value;
+ JSBool eq;
+ JSXMLArrayCursor cursor;
+ JSXML *kid;
+ JSObject *kidobj;
+
+ XML_METHOD_PROLOG;
+ value = argc != 0 ? vp[2] : JSVAL_VOID;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ eq = JS_FALSE;
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj || !xml_equality(cx, kidobj, value, &eq))
+ break;
+ if (eq)
+ break;
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (kid && !eq)
+ return JS_FALSE;
+ } else {
+ if (!xml_equality(cx, obj, value, &eq))
+ return JS_FALSE;
+ }
+ *vp = BOOLEAN_TO_JSVAL(eq);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_copy(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSXML *copy;
+
+ XML_METHOD_PROLOG;
+ copy = DeepCopy(cx, xml, NULL, 0);
+ if (!copy)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(copy->object);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_descendants(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSXML *list;
+
+ XML_METHOD_PROLOG;
+ name = (argc == 0) ? ATOM_KEY(cx->runtime->atomState.starAtom) : vp[2];
+ list = Descendants(cx, xml, name);
+ if (!list)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(list->object);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_elements_helper(JSContext *cx, JSObject *obj, JSXML *xml,
+ JSObject *nameqn, jsval *vp)
+{
+ JSXML *list, *kid, *vxml;
+ jsval v;
+ JSBool ok;
+ JSXMLArrayCursor cursor;
+ JSObject *kidobj;
+ uint32 i, n;
+
+ list = xml_list_helper(cx, xml, vp);
+ if (!list)
+ return JS_FALSE;
+
+ list->xml_targetprop = nameqn;
+ ok = JS_TRUE;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /* 13.5.4.6 */
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (kid->xml_class == JSXML_CLASS_ELEMENT) {
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ break;
+ kidobj = js_GetXMLObject(cx, kid);
+ if (kidobj) {
+ ok = xml_elements_helper(cx, kidobj, kid, nameqn, &v);
+ } else {
+ ok = JS_FALSE;
+ v = JSVAL_NULL;
+ }
+ js_LeaveLocalRootScopeWithResult(cx, v);
+ if (!ok)
+ break;
+ vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ if (JSXML_LENGTH(vxml) != 0) {
+ ok = Append(cx, list, vxml);
+ if (!ok)
+ break;
+ }
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ } else {
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT &&
+ MatchElemName(nameqn, kid)) {
+ ok = Append(cx, list, kid);
+ if (!ok)
+ break;
+ }
+ }
+ }
+
+ return ok;
+}
+
+static JSBool
+xml_elements(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSObject *nameqn;
+ jsid funid;
+
+ XML_METHOD_PROLOG;
+
+ name = (argc == 0) ? ATOM_KEY(cx->runtime->atomState.starAtom) : vp[2];
+ nameqn = ToXMLName(cx, name, &funid);
+ if (!nameqn)
+ return JS_FALSE;
+ vp[2] = OBJECT_TO_JSVAL(nameqn);
+
+ if (funid)
+ return xml_list_helper(cx, xml, vp) != NULL;
+
+ return xml_elements_helper(cx, obj, xml, nameqn, vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_hasOwnProperty(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval name;
+ JSBool found;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_XMLClass, vp + 2))
+ return JS_FALSE;
+
+ name = argc != 0 ? vp[2] : JSVAL_VOID;
+ if (!HasProperty(cx, obj, name, &found))
+ return JS_FALSE;
+ if (found) {
+ *vp = JSVAL_TRUE;
+ return JS_TRUE;
+ }
+ return js_HasOwnPropertyHelper(cx, js_LookupProperty, argc, vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_hasComplexContent(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSXML *kid;
+ JSObject *kidobj;
+ uint32 i, n;
+
+ XML_METHOD_PROLOG;
+again:
+ switch (xml->xml_class) {
+ case JSXML_CLASS_ATTRIBUTE:
+ case JSXML_CLASS_COMMENT:
+ case JSXML_CLASS_PROCESSING_INSTRUCTION:
+ case JSXML_CLASS_TEXT:
+ *vp = JSVAL_FALSE;
+ break;
+ case JSXML_CLASS_LIST:
+ if (xml->xml_kids.length == 0) {
+ *vp = JSVAL_TRUE;
+ } else if (xml->xml_kids.length == 1) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (kid) {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ return JS_FALSE;
+ obj = kidobj;
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ goto again;
+ }
+ }
+ /* FALL THROUGH */
+ default:
+ *vp = JSVAL_FALSE;
+ for (i = 0, n = xml->xml_kids.length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ *vp = JSVAL_TRUE;
+ break;
+ }
+ }
+ break;
+ }
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_hasSimpleContent(JSContext *cx, uintN argc, jsval *vp)
+{
+ XML_METHOD_PROLOG;
+ *vp = BOOLEAN_TO_JSVAL(HasSimpleContent(xml));
+ return JS_TRUE;
+}
+
+typedef struct JSTempRootedNSArray {
+ JSTempValueRooter tvr;
+ JSXMLArray array;
+ jsval value; /* extra root for temporaries */
+} JSTempRootedNSArray;
+
+static void
+TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len)
+{
+ uint32 i;
+ JSObject *obj;
+
+ for (i = 0; i < len; i++) {
+ obj = vec[i];
+ if (obj) {
+ JS_SET_TRACING_INDEX(trc, "vector", i);
+ JS_CallTracer(trc, obj, JSTRACE_OBJECT);
+ }
+ }
+}
+
+static void
+trace_temp_ns_array(JSTracer *trc, JSTempValueRooter *tvr)
+{
+ JSTempRootedNSArray *tmp = (JSTempRootedNSArray *)tvr;
+
+ TraceObjectVector(trc,
+ (JSObject **) tmp->array.vector,
+ tmp->array.length);
+ XMLArrayCursorTrace(trc, tmp->array.cursors);
+ JS_CALL_VALUE_TRACER(trc, tmp->value, "temp_ns_array_value");
+}
+
+static void
+InitTempNSArray(JSContext *cx, JSTempRootedNSArray *tmp)
+{
+ XMLArrayInit(cx, &tmp->array, 0);
+ tmp->value = JSVAL_NULL;
+ JS_PUSH_TEMP_ROOT_TRACE(cx, trace_temp_ns_array, &tmp->tvr);
+}
+
+static void
+FinishTempNSArray(JSContext *cx, JSTempRootedNSArray *tmp)
+{
+ JS_ASSERT(tmp->tvr.u.trace == trace_temp_ns_array);
+ JS_POP_TEMP_ROOT(cx, &tmp->tvr);
+ XMLArrayFinish(cx, &tmp->array);
+}
+
+/*
+ * Populate a new JS array with elements of JSTempRootedNSArray.array and
+ * place the result into rval. rval must point to a rooted location.
+ */
+static JSBool
+TempNSArrayToJSArray(JSContext *cx, JSTempRootedNSArray *tmp, jsval *rval)
+{
+ JSObject *arrayobj;
+ uint32 i, n;
+ JSObject *ns;
+
+ arrayobj = js_NewArrayObject(cx, 0, NULL);
+ if (!arrayobj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(arrayobj);
+ for (i = 0, n = tmp->array.length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&tmp->array, i, JSObject);
+ if (!ns)
+ continue;
+ tmp->value = OBJECT_TO_JSVAL(ns);
+ if (!OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(i), &tmp->value))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+FindInScopeNamespaces(JSContext *cx, JSXML *xml, JSXMLArray *nsarray)
+{
+ uint32 length, i, j, n;
+ JSObject *ns, *ns2;
+ JSString *prefix, *prefix2;
+
+ length = nsarray->length;
+ do {
+ if (xml->xml_class != JSXML_CLASS_ELEMENT)
+ continue;
+ for (i = 0, n = xml->xml_namespaces.length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (!ns)
+ continue;
+
+ prefix = GetPrefix(ns);
+ for (j = 0; j < length; j++) {
+ ns2 = XMLARRAY_MEMBER(nsarray, j, JSObject);
+ if (ns2) {
+ prefix2 = GetPrefix(ns2);
+ if ((prefix2 && prefix)
+ ? js_EqualStrings(prefix2, prefix)
+ : js_EqualStrings(GetURI(ns2), GetURI(ns))) {
+ break;
+ }
+ }
+ }
+
+ if (j == length) {
+ if (!XMLARRAY_APPEND(cx, nsarray, ns))
+ return JS_FALSE;
+ ++length;
+ }
+ }
+ } while ((xml = xml->parent) != NULL);
+ JS_ASSERT(length == nsarray->length);
+
+ return JS_TRUE;
+}
+
+static JSBool
+xml_inScopeNamespaces(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSTempRootedNSArray namespaces;
+ JSBool ok;
+
+ NON_LIST_XML_METHOD_PROLOG;
+
+ InitTempNSArray(cx, &namespaces);
+ ok = FindInScopeNamespaces(cx, xml, &namespaces.array) &&
+ TempNSArrayToJSArray(cx, &namespaces, vp);
+ FinishTempNSArray(cx, &namespaces);
+ return ok;
+}
+
+static JSBool
+xml_insertChildAfter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval arg;
+ JSXML *kid;
+ uint32 i;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ *vp = OBJECT_TO_JSVAL(obj);
+ if (!JSXML_HAS_KIDS(xml) || argc == 0)
+ return JS_TRUE;
+
+ arg = vp[2];
+ if (JSVAL_IS_NULL(arg)) {
+ kid = NULL;
+ i = 0;
+ } else {
+ if (!VALUE_IS_XML(cx, arg))
+ return JS_TRUE;
+ kid = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(arg));
+ i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, NULL);
+ if (i == XML_NOT_FOUND)
+ return JS_TRUE;
+ ++i;
+ }
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+ return Insert(cx, xml, i, argc >= 2 ? vp[3] : JSVAL_VOID);
+}
+
+static JSBool
+xml_insertChildBefore(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval arg;
+ JSXML *kid;
+ uint32 i;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ *vp = OBJECT_TO_JSVAL(obj);
+ if (!JSXML_HAS_KIDS(xml) || argc == 0)
+ return JS_TRUE;
+
+ arg = vp[2];
+ if (JSVAL_IS_NULL(arg)) {
+ kid = NULL;
+ i = xml->xml_kids.length;
+ } else {
+ if (!VALUE_IS_XML(cx, arg))
+ return JS_TRUE;
+ kid = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(arg));
+ i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, NULL);
+ if (i == XML_NOT_FOUND)
+ return JS_TRUE;
+ }
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+ return Insert(cx, xml, i, argc >= 2 ? vp[3] : JSVAL_VOID);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_length(JSContext *cx, uintN argc, jsval *vp)
+{
+ XML_METHOD_PROLOG;
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ *vp = JSVAL_ONE;
+ } else {
+ if (!js_NewNumberInRootedValue(cx, xml->xml_kids.length, vp))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_localName(JSContext *cx, uintN argc, jsval *vp)
+{
+ NON_LIST_XML_METHOD_PROLOG;
+ *vp = xml->name ? xml->name->fslots[JSSLOT_LOCAL_NAME] : JSVAL_NULL;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_name(JSContext *cx, uintN argc, jsval *vp)
+{
+ NON_LIST_XML_METHOD_PROLOG;
+ *vp = OBJECT_TO_JSVAL(xml->name);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_namespace(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *prefix, *nsprefix;
+ JSTempRootedNSArray inScopeNSes;
+ JSBool ok;
+ jsuint i, length;
+ JSObject *ns;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (argc == 0 && !JSXML_HAS_NAME(xml)) {
+ *vp = JSVAL_NULL;
+ return JS_TRUE;
+ }
+
+ if (argc == 0) {
+ prefix = NULL;
+ } else {
+ prefix = js_ValueToString(cx, vp[2]);
+ if (!prefix)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(prefix); /* local root */
+ }
+
+ InitTempNSArray(cx, &inScopeNSes);
+ MUST_FLOW_THROUGH("out");
+ ok = FindInScopeNamespaces(cx, xml, &inScopeNSes.array);
+ if (!ok)
+ goto out;
+
+ if (!prefix) {
+ ns = GetNamespace(cx, xml->name, &inScopeNSes.array);
+ if (!ns) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ } else {
+ ns = NULL;
+ for (i = 0, length = inScopeNSes.array.length; i < length; i++) {
+ ns = XMLARRAY_MEMBER(&inScopeNSes.array, i, JSObject);
+ if (ns) {
+ nsprefix = GetPrefix(ns);
+ if (nsprefix && js_EqualStrings(nsprefix, prefix))
+ break;
+ ns = NULL;
+ }
+ }
+ }
+
+ *vp = (!ns) ? JSVAL_VOID : OBJECT_TO_JSVAL(ns);
+
+ out:
+ FinishTempNSArray(cx, &inScopeNSes);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_namespaceDeclarations(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSBool ok;
+ JSTempRootedNSArray ancestors, declared;
+ JSXML *yml;
+ uint32 i, n;
+ JSObject *ns;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (JSXML_HAS_VALUE(xml))
+ return JS_TRUE;
+
+ /* From here, control flow must goto out to finish these arrays. */
+ ok = JS_TRUE;
+ InitTempNSArray(cx, &ancestors);
+ InitTempNSArray(cx, &declared);
+ yml = xml;
+
+ while ((yml = yml->parent) != NULL) {
+ JS_ASSERT(yml->xml_class == JSXML_CLASS_ELEMENT);
+ for (i = 0, n = yml->xml_namespaces.length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&yml->xml_namespaces, i, JSObject);
+ if (ns &&
+ !XMLARRAY_HAS_MEMBER(&ancestors.array, ns, namespace_match)) {
+ ok = XMLARRAY_APPEND(cx, &ancestors.array, ns);
+ if (!ok)
+ goto out;
+ }
+ }
+ }
+
+ for (i = 0, n = xml->xml_namespaces.length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (!ns)
+ continue;
+ if (!IsDeclared(ns))
+ continue;
+ if (!XMLARRAY_HAS_MEMBER(&ancestors.array, ns, namespace_match)) {
+ ok = XMLARRAY_APPEND(cx, &declared.array, ns);
+ if (!ok)
+ goto out;
+ }
+ }
+
+ ok = TempNSArrayToJSArray(cx, &declared, vp);
+
+out:
+ /* Finishing must be in reverse order of initialization to follow LIFO. */
+ FinishTempNSArray(cx, &declared);
+ FinishTempNSArray(cx, &ancestors);
+ return ok;
+}
+
+static const char js_attribute_str[] = "attribute";
+static const char js_text_str[] = "text";
+
+/* Exported to jsgc.c #ifdef DEBUG. */
+const char *js_xml_class_str[] = {
+ "list",
+ "element",
+ js_attribute_str,
+ "processing-instruction",
+ js_text_str,
+ "comment"
+};
+
+static JSBool
+xml_nodeKind(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ str = JS_InternString(cx, js_xml_class_str[xml->xml_class]);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static void
+NormalizingDelete(JSContext *cx, JSXML *xml, uint32 index)
+{
+ if (xml->xml_class == JSXML_CLASS_LIST)
+ DeleteListElement(cx, xml, index);
+ else
+ DeleteByIndex(cx, xml, index);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_normalize_helper(JSContext *cx, JSObject *obj, JSXML *xml)
+{
+ JSXML *kid, *kid2;
+ uint32 i, n;
+ JSObject *kidobj;
+ JSString *str;
+
+ if (!JSXML_HAS_KIDS(xml))
+ return JS_TRUE;
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ for (i = 0, n = xml->xml_kids.length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (!kid)
+ continue;
+ if (kid->xml_class == JSXML_CLASS_ELEMENT) {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj || !xml_normalize_helper(cx, kidobj, kid))
+ return JS_FALSE;
+ } else if (kid->xml_class == JSXML_CLASS_TEXT) {
+ while (i + 1 < n &&
+ (kid2 = XMLARRAY_MEMBER(&xml->xml_kids, i + 1, JSXML)) &&
+ kid2->xml_class == JSXML_CLASS_TEXT) {
+ str = js_ConcatStrings(cx, kid->xml_value, kid2->xml_value);
+ if (!str)
+ return JS_FALSE;
+ NormalizingDelete(cx, xml, i + 1);
+ n = xml->xml_kids.length;
+ kid->xml_value = str;
+ }
+ if (IS_EMPTY(kid->xml_value)) {
+ NormalizingDelete(cx, xml, i);
+ n = xml->xml_kids.length;
+ --i;
+ }
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+xml_normalize(JSContext *cx, uintN argc, jsval *vp)
+{
+ XML_METHOD_PROLOG;
+ *vp = OBJECT_TO_JSVAL(obj);
+ return xml_normalize_helper(cx, obj, xml);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_parent(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSXML *parent, *kid;
+ uint32 i, n;
+ JSObject *parentobj;
+
+ XML_METHOD_PROLOG;
+ parent = xml->parent;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ *vp = JSVAL_VOID;
+ n = xml->xml_kids.length;
+ if (n == 0)
+ return JS_TRUE;
+
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (!kid)
+ return JS_TRUE;
+ parent = kid->parent;
+ for (i = 1; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->parent != parent)
+ return JS_TRUE;
+ }
+ }
+
+ if (!parent) {
+ *vp = JSVAL_NULL;
+ return JS_TRUE;
+ }
+
+ parentobj = js_GetXMLObject(cx, parent);
+ if (!parentobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(parentobj);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_processingInstructions_helper(JSContext *cx, JSObject *obj, JSXML *xml,
+ JSObject *nameqn, jsval *vp)
+{
+ JSXML *list, *kid, *vxml;
+ JSBool ok;
+ JSXMLArrayCursor cursor;
+ JSObject *kidobj;
+ jsval v;
+ uint32 i, n;
+ JSString *localName;
+
+ list = xml_list_helper(cx, xml, vp);
+ if (!list)
+ return JS_FALSE;
+
+ list->xml_targetprop = nameqn;
+ ok = JS_TRUE;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /* 13.5.4.17 Step 4 (misnumbered 9 -- Erratum?). */
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (kid->xml_class == JSXML_CLASS_ELEMENT) {
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ break;
+ kidobj = js_GetXMLObject(cx, kid);
+ if (kidobj) {
+ ok = xml_processingInstructions_helper(cx, kidobj, kid,
+ nameqn, &v);
+ } else {
+ ok = JS_FALSE;
+ v = JSVAL_NULL;
+ }
+ js_LeaveLocalRootScopeWithResult(cx, v);
+ if (!ok)
+ break;
+ vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ if (JSXML_LENGTH(vxml) != 0) {
+ ok = Append(cx, list, vxml);
+ if (!ok)
+ break;
+ }
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ } else {
+ /* 13.4.4.28 Step 4. */
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION) {
+ localName = GetLocalName(nameqn);
+ if (IS_STAR(localName) ||
+ js_EqualStrings(localName, GetLocalName(kid->name))) {
+ ok = Append(cx, list, kid);
+ if (!ok)
+ break;
+ }
+ }
+ }
+ }
+
+ return ok;
+}
+
+static JSBool
+xml_processingInstructions(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSObject *nameqn;
+ jsid funid;
+
+ XML_METHOD_PROLOG;
+
+ name = (argc == 0) ? ATOM_KEY(cx->runtime->atomState.starAtom) : vp[2];
+ nameqn = ToXMLName(cx, name, &funid);
+ if (!nameqn)
+ return JS_FALSE;
+ vp[2] = OBJECT_TO_JSVAL(nameqn);
+
+ if (funid)
+ return xml_list_helper(cx, xml, vp) != NULL;
+
+ return xml_processingInstructions_helper(cx, obj, xml, nameqn, vp);
+}
+
+static JSBool
+xml_prependChild(JSContext *cx, uintN argc, jsval *vp)
+{
+ NON_LIST_XML_METHOD_PROLOG;
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(obj);
+ return Insert(cx, xml, 0, argc != 0 ? vp[2] : JSVAL_VOID);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp)
+{
+ uint32 index;
+
+ XML_METHOD_PROLOG;
+ *vp = JSVAL_FALSE;
+ if (argc != 0 && js_IdIsIndex(vp[2], &index)) {
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /* 13.5.4.18. */
+ *vp = BOOLEAN_TO_JSVAL(index < xml->xml_kids.length);
+ } else {
+ /* 13.4.4.30. */
+ *vp = BOOLEAN_TO_JSVAL(index == 0);
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+namespace_full_match(const void *a, const void *b)
+{
+ const JSObject *nsa = (const JSObject *) a;
+ const JSObject *nsb = (const JSObject *) b;
+ JSString *prefixa = GetPrefix(nsa);
+ JSString *prefixb;
+
+ if (prefixa) {
+ prefixb = GetPrefix(nsb);
+ if (prefixb && !js_EqualStrings(prefixa, prefixb))
+ return JS_FALSE;
+ }
+ return js_EqualStrings(GetURI(nsa), GetURI(nsb));
+}
+
+static JSBool
+xml_removeNamespace_helper(JSContext *cx, JSXML *xml, JSObject *ns)
+{
+ JSObject *thisns, *attrns;
+ uint32 i, n;
+ JSXML *attr, *kid;
+
+ thisns = GetNamespace(cx, xml->name, &xml->xml_namespaces);
+ JS_ASSERT(thisns);
+ if (thisns == ns)
+ return JS_TRUE;
+
+ for (i = 0, n = xml->xml_attrs.length; i < n; i++) {
+ attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML);
+ if (!attr)
+ continue;
+ attrns = GetNamespace(cx, attr->name, &xml->xml_namespaces);
+ JS_ASSERT(attrns);
+ if (attrns == ns)
+ return JS_TRUE;
+ }
+
+ i = XMLARRAY_FIND_MEMBER(&xml->xml_namespaces, ns, namespace_full_match);
+ if (i != XML_NOT_FOUND)
+ XMLArrayDelete(cx, &xml->xml_namespaces, i, JS_TRUE);
+
+ for (i = 0, n = xml->xml_kids.length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ if (!xml_removeNamespace_helper(cx, kid, ns))
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_removeNamespace(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *ns;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (xml->xml_class != JSXML_CLASS_ELEMENT)
+ goto done;
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ if (!NamespaceHelper(cx, NULL, argc == 0 ? -1 : 1, vp + 2, vp))
+ return JS_FALSE;
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
+ ns = JSVAL_TO_OBJECT(*vp);
+
+ /* NOTE: remove ns from each ancestor if not used by that ancestor. */
+ if (!xml_removeNamespace_helper(cx, xml, ns))
+ return JS_FALSE;
+ done:
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_replace(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval value;
+ JSXML *vxml, *kid;
+ uint32 index, i;
+ JSObject *nameqn;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (xml->xml_class != JSXML_CLASS_ELEMENT)
+ goto done;
+
+ if (argc <= 1) {
+ value = STRING_TO_JSVAL(ATOM_TO_STRING(cx->runtime->atomState.
+ typeAtoms[JSTYPE_VOID]));
+ } else {
+ value = vp[3];
+ vxml = VALUE_IS_XML(cx, value)
+ ? (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(value))
+ : NULL;
+ if (!vxml) {
+ if (!JS_ConvertValue(cx, value, JSTYPE_STRING, &vp[3]))
+ return JS_FALSE;
+ value = vp[3];
+ } else {
+ vxml = DeepCopy(cx, vxml, NULL, 0);
+ if (!vxml)
+ return JS_FALSE;
+ value = vp[3] = OBJECT_TO_JSVAL(vxml->object);
+ }
+ }
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ if (argc == 0 || !js_IdIsIndex(vp[2], &index)) {
+ /*
+ * Call function QName per spec, not ToXMLName, to avoid attribute
+ * names.
+ */
+ if (!QNameHelper(cx, NULL, &js_QNameClass.base, argc == 0 ? -1 : 1,
+ vp + 2, vp)) {
+ return JS_FALSE;
+ }
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
+ nameqn = JSVAL_TO_OBJECT(*vp);
+
+ i = xml->xml_kids.length;
+ index = XML_NOT_FOUND;
+ while (i != 0) {
+ --i;
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && MatchElemName(nameqn, kid)) {
+ if (i != XML_NOT_FOUND)
+ DeleteByIndex(cx, xml, i);
+ index = i;
+ }
+ }
+
+ if (index == XML_NOT_FOUND)
+ goto done;
+ }
+
+ if (!Replace(cx, xml, index, value))
+ return JS_FALSE;
+
+ done:
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setChildren(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ if (!StartNonListXMLMethod(cx, vp, &obj))
+ return JS_FALSE;
+
+ *vp = argc != 0 ? vp[2] : JSVAL_VOID; /* local root */
+ if (!PutProperty(cx, obj, ATOM_KEY(cx->runtime->atomState.starAtom), vp))
+ return JS_FALSE;
+
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setLocalName(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSObject *nameqn;
+ JSString *namestr;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (!JSXML_HAS_NAME(xml))
+ return JS_TRUE;
+
+ if (argc == 0) {
+ namestr = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
+ } else {
+ name = vp[2];
+ if (!JSVAL_IS_PRIMITIVE(name) &&
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(name)) == &js_QNameClass.base) {
+ nameqn = JSVAL_TO_OBJECT(name);
+ namestr = GetLocalName(nameqn);
+ } else {
+ if (!JS_ConvertValue(cx, name, JSTYPE_STRING, &vp[2]))
+ return JS_FALSE;
+ name = vp[2];
+ namestr = JSVAL_TO_STRING(name);
+ }
+ }
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+ xml->name->fslots[JSSLOT_LOCAL_NAME] = namestr
+ ? STRING_TO_JSVAL(namestr)
+ : JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setName(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSObject *nameqn;
+ JSXML *nsowner;
+ JSXMLArray *nsarray;
+ uint32 i, n;
+ JSObject *ns;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (!JSXML_HAS_NAME(xml))
+ return JS_TRUE;
+
+ if (argc == 0) {
+ name = STRING_TO_JSVAL(ATOM_TO_STRING(cx->runtime->atomState.
+ typeAtoms[JSTYPE_VOID]));
+ } else {
+ name = vp[2];
+ if (!JSVAL_IS_PRIMITIVE(name) &&
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(name)) == &js_QNameClass.base &&
+ !GetURI(nameqn = JSVAL_TO_OBJECT(name))) {
+ name = vp[2] = nameqn->fslots[JSSLOT_LOCAL_NAME];
+ }
+ }
+
+ nameqn = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1, &name);
+ if (!nameqn)
+ return JS_FALSE;
+
+ /* ECMA-357 13.4.4.35 Step 4. */
+ if (xml->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION)
+ nameqn->fslots[JSSLOT_URI] = STRING_TO_JSVAL(cx->runtime->emptyString);
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+ xml->name = nameqn;
+
+ /*
+ * Erratum: nothing in 13.4.4.35 talks about making the name match the
+ * in-scope namespaces, either by finding an in-scope namespace with a
+ * matching uri and setting the new name's prefix to that namespace's
+ * prefix, or by extending the in-scope namespaces for xml (which are in
+ * xml->parent if xml is an attribute or a PI).
+ */
+ if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ nsowner = xml;
+ } else {
+ if (!xml->parent || xml->parent->xml_class != JSXML_CLASS_ELEMENT)
+ return JS_TRUE;
+ nsowner = xml->parent;
+ }
+
+ if (GetPrefix(nameqn)) {
+ /*
+ * The name being set has a prefix, which originally came from some
+ * namespace object (which may be the null namespace, where both the
+ * prefix and uri are the empty string). We must go through a full
+ * GetNamespace in case that namespace is in-scope in nsowner.
+ *
+ * If we find such an in-scope namespace, we return true right away,
+ * in this block. Otherwise, we fall through to the final return of
+ * AddInScopeNamespace(cx, nsowner, ns).
+ */
+ ns = GetNamespace(cx, nameqn, &nsowner->xml_namespaces);
+ if (!ns)
+ return JS_FALSE;
+
+ /* XXXbe have to test membership to see whether GetNamespace added */
+ if (XMLARRAY_HAS_MEMBER(&nsowner->xml_namespaces, ns, NULL))
+ return JS_TRUE;
+ } else {
+ /*
+ * At this point, we know prefix of nameqn is null, so its uri can't
+ * be the empty string (the null namespace always uses the empty string
+ * for both prefix and uri).
+ *
+ * This means we must inline GetNamespace and specialize it to match
+ * uri only, never prefix. If we find a namespace with nameqn's uri
+ * already in nsowner->xml_namespaces, then all that we need do is set
+ * prefix of nameqn to that namespace's prefix.
+ *
+ * If no such namespace exists, we can create one without going through
+ * the constructor, because we know uri of nameqn is non-empty (so
+ * prefix does not need to be converted from null to empty by QName).
+ */
+ JS_ASSERT(!IS_EMPTY(GetURI(nameqn)));
+
+ nsarray = &nsowner->xml_namespaces;
+ for (i = 0, n = nsarray->length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(nsarray, i, JSObject);
+ if (ns && js_EqualStrings(GetURI(ns), GetURI(nameqn))) {
+ nameqn->fslots[JSSLOT_PREFIX] = ns->fslots[JSSLOT_PREFIX];
+ return JS_TRUE;
+ }
+ }
+
+ ns = NewXMLNamespace(cx, NULL, GetURI(nameqn), JS_TRUE);
+ if (!ns)
+ return JS_FALSE;
+ }
+
+ if (!AddInScopeNamespace(cx, nsowner, ns))
+ return JS_FALSE;
+ vp[0] = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setNamespace(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *qn;
+ JSObject *ns;
+ jsval qnargv[2];
+ JSXML *nsowner;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (!JSXML_HAS_NAME(xml))
+ return JS_TRUE;
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, obj,
+ argc == 0 ? 0 : 1, vp + 2);
+ if (!ns)
+ return JS_FALSE;
+ vp[0] = OBJECT_TO_JSVAL(ns);
+ ns->fslots[JSSLOT_DECLARED] = JSVAL_TRUE;
+
+ qnargv[0] = vp[2] = OBJECT_TO_JSVAL(ns);
+ qnargv[1] = OBJECT_TO_JSVAL(xml->name);
+ qn = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 2, qnargv);
+ if (!qn)
+ return JS_FALSE;
+
+ xml->name = qn;
+
+ /*
+ * Erratum: the spec fails to update the governing in-scope namespaces.
+ * See the erratum noted in xml_setName, above.
+ */
+ if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ nsowner = xml;
+ } else {
+ if (!xml->parent || xml->parent->xml_class != JSXML_CLASS_ELEMENT)
+ return JS_TRUE;
+ nsowner = xml->parent;
+ }
+ if (!AddInScopeNamespace(cx, nsowner, ns))
+ return JS_FALSE;
+ vp[0] = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_text_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval *vp)
+{
+ JSXML *list, *kid, *vxml;
+ uint32 i, n;
+ JSBool ok;
+ JSObject *kidobj;
+ jsval v;
+
+ list = xml_list_helper(cx, xml, vp);
+ if (!list)
+ return JS_FALSE;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ ok = JS_TRUE;
+ for (i = 0, n = xml->xml_kids.length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ break;
+ kidobj = js_GetXMLObject(cx, kid);
+ if (kidobj) {
+ ok = xml_text_helper(cx, kidobj, kid, &v);
+ } else {
+ ok = JS_FALSE;
+ v = JSVAL_NULL;
+ }
+ js_LeaveLocalRootScopeWithResult(cx, v);
+ if (!ok)
+ return JS_FALSE;
+ vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ if (JSXML_LENGTH(vxml) != 0 && !Append(cx, list, vxml))
+ return JS_FALSE;
+ }
+ }
+ } else {
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_TEXT) {
+ if (!Append(cx, list, kid))
+ return JS_FALSE;
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_text(JSContext *cx, uintN argc, jsval *vp)
+{
+ XML_METHOD_PROLOG;
+ return xml_text_helper(cx, obj, xml, vp);
+}
+
+/* XML and XMLList */
+static JSString *
+xml_toString_helper(JSContext *cx, JSXML *xml)
+{
+ JSString *str, *kidstr;
+ JSXML *kid;
+ JSXMLArrayCursor cursor;
+
+ if (xml->xml_class == JSXML_CLASS_ATTRIBUTE ||
+ xml->xml_class == JSXML_CLASS_TEXT) {
+ return xml->xml_value;
+ }
+
+ if (!HasSimpleContent(xml))
+ return ToXMLString(cx, OBJECT_TO_JSVAL(xml->object), 0);
+
+ str = cx->runtime->emptyString;
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (kid->xml_class != JSXML_CLASS_COMMENT &&
+ kid->xml_class != JSXML_CLASS_PROCESSING_INSTRUCTION) {
+ kidstr = xml_toString_helper(cx, kid);
+ if (!kidstr) {
+ str = NULL;
+ break;
+ }
+ str = js_ConcatStrings(cx, str, kidstr);
+ if (!str)
+ break;
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ js_LeaveLocalRootScopeWithResult(cx, STRING_TO_JSVAL(str));
+ return str;
+}
+
+static JSBool
+xml_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval thisv;
+ JSString *str;
+
+ thisv = JS_THIS(cx, vp);
+ if (JSVAL_IS_NULL(thisv))
+ return JS_FALSE;
+ str = ToXMLString(cx, thisv, TO_SOURCE_FLAG);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ XML_METHOD_PROLOG;
+ str = xml_toString_helper(cx, xml);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_toXMLString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval thisv;
+ JSString *str;
+
+ thisv = JS_THIS(cx, vp);
+ if (JSVAL_IS_NULL(thisv))
+ return JS_FALSE;
+ str = ToXMLString(cx, thisv, 0);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_valueOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ *vp = JS_THIS(cx, vp);
+ return !JSVAL_IS_NULL(*vp);
+}
+
+static JSFunctionSpec xml_methods[] = {
+ JS_FN("addNamespace", xml_addNamespace, 1,0),
+ JS_FN("appendChild", xml_appendChild, 1,0),
+ JS_FN(js_attribute_str, xml_attribute, 1,0),
+ JS_FN("attributes", xml_attributes, 0,0),
+ JS_FN("child", xml_child, 1,0),
+ JS_FN("childIndex", xml_childIndex, 0,0),
+ JS_FN("children", xml_children, 0,0),
+ JS_FN("comments", xml_comments, 0,0),
+ JS_FN("contains", xml_contains, 1,0),
+ JS_FN("copy", xml_copy, 0,0),
+ JS_FN("descendants", xml_descendants, 1,0),
+ JS_FN("elements", xml_elements, 1,0),
+ JS_FN("hasOwnProperty", xml_hasOwnProperty, 1,0),
+ JS_FN("hasComplexContent", xml_hasComplexContent, 1,0),
+ JS_FN("hasSimpleContent", xml_hasSimpleContent, 1,0),
+ JS_FN("inScopeNamespaces", xml_inScopeNamespaces, 0,0),
+ JS_FN("insertChildAfter", xml_insertChildAfter, 2,0),
+ JS_FN("insertChildBefore", xml_insertChildBefore, 2,0),
+ JS_FN(js_length_str, xml_length, 0,0),
+ JS_FN(js_localName_str, xml_localName, 0,0),
+ JS_FN(js_name_str, xml_name, 0,0),
+ JS_FN(js_namespace_str, xml_namespace, 1,0),
+ JS_FN("namespaceDeclarations", xml_namespaceDeclarations, 0,0),
+ JS_FN("nodeKind", xml_nodeKind, 0,0),
+ JS_FN("normalize", xml_normalize, 0,0),
+ JS_FN(js_xml_parent_str, xml_parent, 0,0),
+ JS_FN("processingInstructions",xml_processingInstructions,1,0),
+ JS_FN("prependChild", xml_prependChild, 1,0),
+ JS_FN("propertyIsEnumerable", xml_propertyIsEnumerable, 1,0),
+ JS_FN("removeNamespace", xml_removeNamespace, 1,0),
+ JS_FN("replace", xml_replace, 2,0),
+ JS_FN("setChildren", xml_setChildren, 1,0),
+ JS_FN("setLocalName", xml_setLocalName, 1,0),
+ JS_FN("setName", xml_setName, 1,0),
+ JS_FN("setNamespace", xml_setNamespace, 1,0),
+ JS_FN(js_text_str, xml_text, 0,0),
+ JS_FN(js_toSource_str, xml_toSource, 0,0),
+ JS_FN(js_toString_str, xml_toString, 0,0),
+ JS_FN(js_toXMLString_str, xml_toXMLString, 0,0),
+ JS_FN(js_valueOf_str, xml_valueOf, 0,0),
+ JS_FS_END
+};
+
+static JSBool
+CopyXMLSettings(JSContext *cx, JSObject *from, JSObject *to)
+{
+ int i;
+ const char *name;
+ jsval v;
+
+ for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) {
+ name = xml_static_props[i].name;
+ if (!JS_GetProperty(cx, from, name, &v))
+ return JS_FALSE;
+ if (JSVAL_IS_BOOLEAN(v) && !JS_SetProperty(cx, to, name, &v))
+ return JS_FALSE;
+ }
+
+ name = xml_static_props[i].name;
+ if (!JS_GetProperty(cx, from, name, &v))
+ return JS_FALSE;
+ if (JSVAL_IS_NUMBER(v) && !JS_SetProperty(cx, to, name, &v))
+ return JS_FALSE;
+ return JS_TRUE;
+}
+
+static JSBool
+SetDefaultXMLSettings(JSContext *cx, JSObject *obj)
+{
+ int i;
+ jsval v;
+
+ for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) {
+ v = JSVAL_TRUE;
+ if (!JS_SetProperty(cx, obj, xml_static_props[i].name, &v))
+ return JS_FALSE;
+ }
+ v = INT_TO_JSVAL(2);
+ return JS_SetProperty(cx, obj, xml_static_props[i].name, &v);
+}
+
+static JSBool
+xml_settings(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *settings;
+ JSObject *obj;
+
+ settings = JS_NewObject(cx, NULL, NULL, NULL);
+ if (!settings)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(settings);
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && CopyXMLSettings(cx, obj, settings);
+}
+
+static JSBool
+xml_setSettings(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj, *settings;
+ jsval v;
+ JSBool ok;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ v = (argc == 0) ? JSVAL_VOID : vp[2];
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) {
+ cx->xmlSettingFlags = 0;
+ ok = SetDefaultXMLSettings(cx, obj);
+ } else {
+ if (JSVAL_IS_PRIMITIVE(v))
+ return JS_TRUE;
+ settings = JSVAL_TO_OBJECT(v);
+ cx->xmlSettingFlags = 0;
+ ok = CopyXMLSettings(cx, settings, obj);
+ }
+ if (ok)
+ cx->xmlSettingFlags |= XSF_CACHE_VALID;
+ return ok;
+}
+
+static JSBool
+xml_defaultSettings(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *settings;
+
+ settings = JS_NewObject(cx, NULL, NULL, NULL);
+ if (!settings)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(settings);
+ return SetDefaultXMLSettings(cx, settings);
+}
+
+static JSFunctionSpec xml_static_methods[] = {
+ JS_FN("settings", xml_settings, 0,0),
+ JS_FN("setSettings", xml_setSettings, 1,0),
+ JS_FN("defaultSettings", xml_defaultSettings, 0,0),
+ JS_FS_END
+};
+
+static JSBool
+XML(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsval v;
+ JSXML *xml, *copy;
+ JSObject *xobj, *vobj;
+ JSClass *clasp;
+
+ v = argv[0];
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
+ v = STRING_TO_JSVAL(cx->runtime->emptyString);
+
+ xobj = ToXML(cx, v);
+ if (!xobj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(xobj);
+ xml = (JSXML *) JS_GetPrivate(cx, xobj);
+
+ if ((cx->fp->flags & JSFRAME_CONSTRUCTING) && !JSVAL_IS_PRIMITIVE(v)) {
+ vobj = JSVAL_TO_OBJECT(v);
+ clasp = OBJ_GET_CLASS(cx, vobj);
+ if (clasp == &js_XMLClass ||
+ (clasp->flags & JSCLASS_DOCUMENT_OBSERVER)) {
+ /* No need to lock obj, it's newly constructed and thread local. */
+ copy = DeepCopy(cx, xml, obj, 0);
+ if (!copy)
+ return JS_FALSE;
+ JS_ASSERT(copy->object == obj);
+ *rval = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+XMLList(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsval v;
+ JSObject *vobj, *listobj;
+ JSXML *xml, *list;
+
+ v = argv[0];
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
+ v = STRING_TO_JSVAL(cx->runtime->emptyString);
+
+ if ((cx->fp->flags & JSFRAME_CONSTRUCTING) && !JSVAL_IS_PRIMITIVE(v)) {
+ vobj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, vobj)) {
+ xml = (JSXML *) JS_GetPrivate(cx, vobj);
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!listobj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(listobj);
+
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ if (!Append(cx, list, xml))
+ return JS_FALSE;
+ return JS_TRUE;
+ }
+ }
+ }
+
+ /* Toggle on XML support since the script has explicitly requested it. */
+ listobj = ToXMLList(cx, v);
+ if (!listobj)
+ return JS_FALSE;
+
+ *rval = OBJECT_TO_JSVAL(listobj);
+ return JS_TRUE;
+}
+
+#define JSXML_LIST_SIZE (offsetof(JSXML, u) + sizeof(struct JSXMLListVar))
+#define JSXML_ELEMENT_SIZE (offsetof(JSXML, u) + sizeof(struct JSXMLElemVar))
+#define JSXML_LEAF_SIZE (offsetof(JSXML, u) + sizeof(JSString *))
+
+static size_t sizeof_JSXML[JSXML_CLASS_LIMIT] = {
+ JSXML_LIST_SIZE, /* JSXML_CLASS_LIST */
+ JSXML_ELEMENT_SIZE, /* JSXML_CLASS_ELEMENT */
+ JSXML_LEAF_SIZE, /* JSXML_CLASS_ATTRIBUTE */
+ JSXML_LEAF_SIZE, /* JSXML_CLASS_PROCESSING_INSTRUCTION */
+ JSXML_LEAF_SIZE, /* JSXML_CLASS_TEXT */
+ JSXML_LEAF_SIZE /* JSXML_CLASS_COMMENT */
+};
+
+#ifdef DEBUG_notme
+JSCList xml_leaks = JS_INIT_STATIC_CLIST(&xml_leaks);
+uint32 xml_serial;
+#endif
+
+JSXML *
+js_NewXML(JSContext *cx, JSXMLClass xml_class)
+{
+ JSXML *xml;
+
+ xml = (JSXML *) js_NewGCThing(cx, GCX_XML, sizeof_JSXML[xml_class]);
+ if (!xml)
+ return NULL;
+
+ xml->object = NULL;
+ xml->domnode = NULL;
+ xml->parent = NULL;
+ xml->name = NULL;
+ xml->xml_class = xml_class;
+ xml->xml_flags = 0;
+ if (JSXML_CLASS_HAS_VALUE(xml_class)) {
+ xml->xml_value = cx->runtime->emptyString;
+ } else {
+ XMLArrayInit(cx, &xml->xml_kids, 0);
+ if (xml_class == JSXML_CLASS_LIST) {
+ xml->xml_target = NULL;
+ xml->xml_targetprop = NULL;
+ } else {
+ XMLArrayInit(cx, &xml->xml_namespaces, 0);
+ XMLArrayInit(cx, &xml->xml_attrs, 0);
+ }
+ }
+
+#ifdef DEBUG_notme
+ JS_APPEND_LINK(&xml->links, &xml_leaks);
+ xml->serial = xml_serial++;
+#endif
+ METER(xml_stats.xml);
+ return xml;
+}
+
+void
+js_TraceXML(JSTracer *trc, JSXML *xml)
+{
+ if (xml->object)
+ JS_CALL_OBJECT_TRACER(trc, xml->object, "object");
+ if (xml->name)
+ JS_CALL_OBJECT_TRACER(trc, xml->name, "name");
+ if (xml->parent)
+ JS_CALL_TRACER(trc, xml->parent, JSTRACE_XML, "xml_parent");
+
+ if (JSXML_HAS_VALUE(xml)) {
+ if (xml->xml_value)
+ JS_CALL_STRING_TRACER(trc, xml->xml_value, "value");
+ return;
+ }
+
+ xml_trace_vector(trc,
+ (JSXML **) xml->xml_kids.vector,
+ xml->xml_kids.length);
+ XMLArrayCursorTrace(trc, xml->xml_kids.cursors);
+ if (IS_GC_MARKING_TRACER(trc))
+ XMLArrayTrim(&xml->xml_kids);
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ if (xml->xml_target)
+ JS_CALL_TRACER(trc, xml->xml_target, JSTRACE_XML, "target");
+ if (xml->xml_targetprop)
+ JS_CALL_OBJECT_TRACER(trc, xml->xml_targetprop, "targetprop");
+ } else {
+ TraceObjectVector(trc,
+ (JSObject **) xml->xml_namespaces.vector,
+ xml->xml_namespaces.length);
+ XMLArrayCursorTrace(trc, xml->xml_namespaces.cursors);
+ if (IS_GC_MARKING_TRACER(trc))
+ XMLArrayTrim(&xml->xml_namespaces);
+
+ xml_trace_vector(trc,
+ (JSXML **) xml->xml_attrs.vector,
+ xml->xml_attrs.length);
+ XMLArrayCursorTrace(trc, xml->xml_attrs.cursors);
+ if (IS_GC_MARKING_TRACER(trc))
+ XMLArrayTrim(&xml->xml_attrs);
+ }
+}
+
+void
+js_FinalizeXML(JSContext *cx, JSXML *xml)
+{
+ if (JSXML_HAS_KIDS(xml)) {
+ XMLArrayFinish(cx, &xml->xml_kids);
+ if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ XMLArrayFinish(cx, &xml->xml_namespaces);
+ XMLArrayFinish(cx, &xml->xml_attrs);
+ }
+ }
+
+#ifdef DEBUG_notme
+ JS_REMOVE_LINK(&xml->links);
+#endif
+}
+
+JSObject *
+js_ParseNodeToXMLObject(JSContext *cx, JSParseContext *pc, JSParseNode *pn)
+{
+ jsval nsval;
+ JSObject *ns;
+ JSXMLArray nsarray;
+ JSXML *xml;
+
+ if (!js_GetDefaultXMLNamespace(cx, &nsval))
+ return NULL;
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(nsval));
+ ns = JSVAL_TO_OBJECT(nsval);
+
+ if (!XMLArrayInit(cx, &nsarray, 1))
+ return NULL;
+
+ XMLARRAY_APPEND(cx, &nsarray, ns);
+ xml = ParseNodeToXML(cx, pc, pn, &nsarray, XSF_PRECOMPILED_ROOT);
+ XMLArrayFinish(cx, &nsarray);
+ if (!xml)
+ return NULL;
+
+ return xml->object;
+}
+
+JSObject *
+js_NewXMLObject(JSContext *cx, JSXMLClass xml_class)
+{
+ JSXML *xml;
+ JSObject *obj;
+ JSTempValueRooter tvr;
+
+ xml = js_NewXML(cx, xml_class);
+ if (!xml)
+ return NULL;
+ JS_PUSH_TEMP_ROOT_XML(cx, xml, &tvr);
+ obj = js_GetXMLObject(cx, xml);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return obj;
+}
+
+static JSObject *
+NewXMLObject(JSContext *cx, JSXML *xml)
+{
+ JSObject *obj;
+
+ obj = js_NewObject(cx, &js_XMLClass, NULL, NULL, 0);
+ if (!obj || !JS_SetPrivate(cx, obj, xml)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+ }
+ METER(xml_stats.xmlobj);
+ return obj;
+}
+
+JSObject *
+js_GetXMLObject(JSContext *cx, JSXML *xml)
+{
+ JSObject *obj;
+
+ obj = xml->object;
+ if (obj) {
+ JS_ASSERT(JS_GetPrivate(cx, obj) == xml);
+ return obj;
+ }
+
+ /*
+ * A JSXML cannot be shared among threads unless it has an object.
+ * A JSXML cannot be given an object unless:
+ * (a) it has no parent; or
+ * (b) its parent has no object (therefore is thread-private); or
+ * (c) its parent's object is locked.
+ *
+ * Once given an object, a JSXML is immutable.
+ */
+ JS_ASSERT(!xml->parent ||
+ !xml->parent->object ||
+ JS_IS_OBJ_LOCKED(cx, xml->parent->object));
+
+ obj = NewXMLObject(cx, xml);
+ if (!obj)
+ return NULL;
+ xml->object = obj;
+ return obj;
+}
+
+JSObject *
+js_InitNamespaceClass(JSContext *cx, JSObject *obj)
+{
+ return JS_InitClass(cx, obj, NULL, &js_NamespaceClass.base, Namespace, 2,
+ namespace_props, namespace_methods, NULL, NULL);
+}
+
+JSObject *
+js_InitQNameClass(JSContext *cx, JSObject *obj)
+{
+ return JS_InitClass(cx, obj, NULL, &js_QNameClass.base, QName, 2,
+ qname_props, qname_methods, NULL, NULL);
+}
+
+JSObject *
+js_InitAttributeNameClass(JSContext *cx, JSObject *obj)
+{
+ return JS_InitClass(cx, obj, NULL, &js_AttributeNameClass, AttributeName, 2,
+ qname_props, qname_methods, NULL, NULL);
+}
+
+JSObject *
+js_InitAnyNameClass(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+
+ if (!js_GetAnyName(cx, &v))
+ return NULL;
+ return JSVAL_TO_OBJECT(v);
+}
+
+JSObject *
+js_InitXMLClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto, *pobj;
+ JSFunction *fun;
+ JSXML *xml;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ jsval cval, vp[3];
+
+ /* Define the isXMLName function. */
+ if (!JS_DefineFunction(cx, obj, js_isXMLName_str, xml_isXMLName, 1, 0))
+ return NULL;
+
+ /* Define the XML class constructor and prototype. */
+ proto = JS_InitClass(cx, obj, NULL, &js_XMLClass, XML, 1,
+ NULL, xml_methods,
+ xml_static_props, xml_static_methods);
+ if (!proto)
+ return NULL;
+
+ xml = js_NewXML(cx, JSXML_CLASS_TEXT);
+ if (!xml || !JS_SetPrivate(cx, proto, xml))
+ return NULL;
+ xml->object = proto;
+ METER(xml_stats.xmlobj);
+
+ /*
+ * Prepare to set default settings on the XML constructor we just made.
+ * NB: We can't use JS_GetConstructor, because it calls OBJ_GET_PROPERTY,
+ * which is xml_getProperty, which creates a new XMLList every time! We
+ * must instead call js_LookupProperty directly.
+ */
+ if (!js_LookupProperty(cx, proto,
+ ATOM_TO_JSID(cx->runtime->atomState.constructorAtom),
+ &pobj, &prop)) {
+ return NULL;
+ }
+ JS_ASSERT(prop);
+ sprop = (JSScopeProperty *) prop;
+ JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)));
+ cval = OBJ_GET_SLOT(cx, pobj, sprop->slot);
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ JS_ASSERT(VALUE_IS_FUNCTION(cx, cval));
+
+ /* Set default settings. */
+ vp[0] = JSVAL_NULL;
+ vp[1] = cval;
+ vp[2] = JSVAL_VOID;
+ if (!xml_setSettings(cx, 1, vp))
+ return NULL;
+
+ /* Define the XMLList function and give it the same prototype as XML. */
+ fun = JS_DefineFunction(cx, obj, js_XMLList_str, XMLList, 1, 0);
+ if (!fun)
+ return NULL;
+ if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), proto,
+ JSPROP_READONLY | JSPROP_PERMANENT)) {
+ return NULL;
+ }
+ return proto;
+}
+
+JSObject *
+js_InitXMLClasses(JSContext *cx, JSObject *obj)
+{
+ if (!js_InitNamespaceClass(cx, obj))
+ return NULL;
+ if (!js_InitQNameClass(cx, obj))
+ return NULL;
+ if (!js_InitAttributeNameClass(cx, obj))
+ return NULL;
+ if (!js_InitAnyNameClass(cx, obj))
+ return NULL;
+ if (!js_InitXMLFilterClass(cx, obj))
+ return NULL;
+ return js_InitXMLClass(cx, obj);
+}
+
+JSBool
+js_GetFunctionNamespace(JSContext *cx, jsval *vp)
+{
+ JSRuntime *rt;
+ JSObject *obj;
+ JSAtom *atom;
+ JSString *prefix, *uri;
+
+ /* An invalid URI, for internal use only, guaranteed not to collide. */
+ static const char anti_uri[] = "@mozilla.org/js/function";
+
+ /* Optimize by avoiding JS_LOCK_GC(rt) for the common case. */
+ rt = cx->runtime;
+ obj = rt->functionNamespaceObject;
+ if (!obj) {
+ JS_LOCK_GC(rt);
+ obj = rt->functionNamespaceObject;
+ if (!obj) {
+ JS_UNLOCK_GC(rt);
+
+ /*
+ * Note that any race to atomize anti_uri here is resolved by
+ * the atom table code, such that at most one atom for anti_uri
+ * is created. We store in rt->atomState.lazy unconditionally,
+ * since we are guaranteed to overwrite either null or the same
+ * atom pointer.
+ */
+ atom = js_Atomize(cx, anti_uri, sizeof anti_uri - 1, ATOM_PINNED);
+ if (!atom)
+ return JS_FALSE;
+ rt->atomState.lazy.functionNamespaceURIAtom = atom;
+
+ prefix = ATOM_TO_STRING(rt->atomState.typeAtoms[JSTYPE_FUNCTION]);
+ uri = ATOM_TO_STRING(atom);
+ obj = NewXMLNamespace(cx, prefix, uri, JS_FALSE);
+ if (!obj)
+ return JS_FALSE;
+
+ /*
+ * Avoid entraining any in-scope Object.prototype. The loss of
+ * Namespace.prototype is not detectable, as there is no way to
+ * refer to this instance in scripts. When used to qualify method
+ * names, its prefix and uri references are copied to the QName.
+ */
+ OBJ_CLEAR_PROTO(cx, obj);
+ OBJ_CLEAR_PARENT(cx, obj);
+
+ JS_LOCK_GC(rt);
+ if (!rt->functionNamespaceObject)
+ rt->functionNamespaceObject = obj;
+ else
+ obj = rt->functionNamespaceObject;
+ }
+ JS_UNLOCK_GC(rt);
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+/*
+ * Note the asymmetry between js_GetDefaultXMLNamespace and js_SetDefaultXML-
+ * Namespace. Get searches fp->scopeChain for JS_DEFAULT_XML_NAMESPACE_ID,
+ * while Set sets JS_DEFAULT_XML_NAMESPACE_ID in fp->varobj (unless fp is a
+ * lightweight function activation). There's no requirement that fp->varobj
+ * lie directly on fp->scopeChain, although it should be reachable using the
+ * prototype chain from a scope object (cf. JSOPTION_VAROBJFIX in jsapi.h).
+ *
+ * If Get can't find JS_DEFAULT_XML_NAMESPACE_ID along the scope chain, it
+ * creates a default namespace via 'new Namespace()'. In contrast, Set uses
+ * its v argument as the uri of a new Namespace, with "" as the prefix. See
+ * ECMA-357 12.1 and 12.1.1. Note that if Set is called with a Namespace n,
+ * the default XML namespace will be set to ("", n.uri). So the uri string
+ * is really the only usefully stored value of the default namespace.
+ */
+JSBool
+js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
+{
+ JSStackFrame *fp;
+ JSObject *ns, *obj, *tmp;
+ jsval v;
+
+ fp = cx->fp;
+ ns = fp->xmlNamespace;
+ if (ns) {
+ *vp = OBJECT_TO_JSVAL(ns);
+ return JS_TRUE;
+ }
+
+ obj = NULL;
+ for (tmp = fp->scopeChain; tmp; tmp = OBJ_GET_PARENT(cx, obj)) {
+ obj = tmp;
+ if (!OBJ_GET_PROPERTY(cx, obj, JS_DEFAULT_XML_NAMESPACE_ID, &v))
+ return JS_FALSE;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ fp->xmlNamespace = JSVAL_TO_OBJECT(v);
+ *vp = v;
+ return JS_TRUE;
+ }
+ }
+
+ ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, obj, 0, NULL);
+ if (!ns)
+ return JS_FALSE;
+ v = OBJECT_TO_JSVAL(ns);
+ if (obj &&
+ !OBJ_DEFINE_PROPERTY(cx, obj, JS_DEFAULT_XML_NAMESPACE_ID, v,
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_PERMANENT, NULL)) {
+ return JS_FALSE;
+ }
+ fp->xmlNamespace = ns;
+ *vp = v;
+ return JS_TRUE;
+}
+
+JSBool
+js_SetDefaultXMLNamespace(JSContext *cx, jsval v)
+{
+ jsval argv[2];
+ JSObject *ns, *varobj;
+ JSStackFrame *fp;
+
+ argv[0] = STRING_TO_JSVAL(cx->runtime->emptyString);
+ argv[1] = v;
+ ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, NULL, 2, argv);
+ if (!ns)
+ return JS_FALSE;
+ v = OBJECT_TO_JSVAL(ns);
+
+ fp = cx->fp;
+ varobj = fp->varobj;
+ if (varobj) {
+ if (!OBJ_DEFINE_PROPERTY(cx, varobj, JS_DEFAULT_XML_NAMESPACE_ID, v,
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_PERMANENT, NULL)) {
+ return JS_FALSE;
+ }
+ } else {
+ JS_ASSERT(fp->fun && !JSFUN_HEAVYWEIGHT_TEST(fp->fun->flags));
+ }
+ fp->xmlNamespace = JSVAL_TO_OBJECT(v);
+ return JS_TRUE;
+}
+
+JSBool
+js_ToAttributeName(JSContext *cx, jsval *vp)
+{
+ JSObject *qn;
+
+ qn = ToAttributeName(cx, *vp);
+ if (!qn)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(qn);
+ return JS_TRUE;
+}
+
+JSString *
+js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote)
+{
+ return EscapeAttributeValue(cx, NULL, str, quote);
+}
+
+JSString *
+js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str, JSString *str2)
+{
+ size_t len, len2, newlen;
+ jschar *chars, *chars2;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, len);
+ if (!JSSTRING_IS_MUTABLE(str)) {
+ str = js_NewStringCopyN(cx, chars, len);
+ if (!str)
+ return NULL;
+ chars = JSFLATSTR_CHARS(str);
+ } else {
+ /*
+ * Reallocating str (because we know it has no other references)
+ * requires purging any deflated string cached for it.
+ */
+ js_PurgeDeflatedStringCache(cx->runtime, str);
+ }
+
+ JSSTRING_CHARS_AND_LENGTH(str2, chars2, len2);
+ newlen = (isName) ? len + 1 + len2 : len + 2 + len2 + 1;
+ chars = (jschar *) JS_realloc(cx, chars, (newlen+1) * sizeof(jschar));
+ if (!chars)
+ return NULL;
+
+ JSFLATSTR_INIT(str, chars, newlen);
+ chars += len;
+ if (isName) {
+ *chars++ = ' ';
+ js_strncpy(chars, chars2, len2);
+ chars += len2;
+ } else {
+ *chars++ = '=';
+ *chars++ = '"';
+ js_strncpy(chars, chars2, len2);
+ chars += len2;
+ *chars++ = '"';
+ }
+ *chars = 0;
+ return str;
+}
+
+JSString *
+js_EscapeElementValue(JSContext *cx, JSString *str)
+{
+ return EscapeElementValue(cx, NULL, str);
+}
+
+JSString *
+js_ValueToXMLString(JSContext *cx, jsval v)
+{
+ return ToXMLString(cx, v, 0);
+}
+
+static JSBool
+anyname_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ *rval = ATOM_KEY(cx->runtime->atomState.starAtom);
+ return JS_TRUE;
+}
+
+JSBool
+js_GetAnyName(JSContext *cx, jsval *vp)
+{
+ JSRuntime *rt;
+ JSObject *obj;
+ JSBool ok;
+
+ /* Optimize by avoiding JS_LOCK_GC(rt) for the common case. */
+ rt = cx->runtime;
+ obj = rt->anynameObject;
+ if (!obj) {
+ JS_LOCK_GC(rt);
+ obj = rt->anynameObject;
+ if (!obj) {
+ JS_UNLOCK_GC(rt);
+
+ /*
+ * Protect multiple newborns created below, in the do-while(0)
+ * loop used to ensure that we leave this local root scope.
+ */
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ return JS_FALSE;
+
+ do {
+ obj = js_NewObjectWithGivenProto(cx, &js_AnyNameClass, NULL,
+ NULL, 0);
+ if (!obj) {
+ ok = JS_FALSE;
+ break;
+ }
+ InitXMLQName(obj, rt->emptyString, rt->emptyString,
+ ATOM_TO_STRING(rt->atomState.starAtom));
+ METER(xml_stats.qname);
+
+ /*
+ * Avoid entraining any Object.prototype found via cx's scope
+ * chain or global object. This loses the default toString,
+ * but no big deal: we want to customize toString anyway for
+ * clearer diagnostics.
+ */
+ if (!JS_DefineFunction(cx, obj, js_toString_str,
+ anyname_toString, 0, 0)) {
+ ok = JS_FALSE;
+ break;
+ }
+ JS_ASSERT(!OBJ_GET_PROTO(cx, obj));
+ JS_ASSERT(!OBJ_GET_PARENT(cx, obj));
+ } while (0);
+
+ js_LeaveLocalRootScopeWithResult(cx, OBJECT_TO_JSVAL(obj));
+ if (!ok)
+ return JS_FALSE;
+
+ JS_LOCK_GC(rt);
+ if (!rt->anynameObject)
+ rt->anynameObject = obj;
+ else
+ obj = rt->anynameObject;
+ }
+ JS_UNLOCK_GC(rt);
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+JSBool
+js_FindXMLProperty(JSContext *cx, jsval nameval, JSObject **objp, jsid *idp)
+{
+ JSObject *nameobj;
+ jsval v;
+ JSObject *qn;
+ jsid funid;
+ JSObject *obj, *target, *proto, *pobj;
+ JSXML *xml;
+ JSBool found;
+ JSProperty *prop;
+ const char *printable;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(nameval));
+ nameobj = JSVAL_TO_OBJECT(nameval);
+ if (OBJ_GET_CLASS(cx, nameobj) == &js_AnyNameClass) {
+ v = STRING_TO_JSVAL(ATOM_TO_STRING(cx->runtime->atomState.starAtom));
+ nameobj = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1,
+ &v);
+ if (!nameobj)
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(OBJ_GET_CLASS(cx, nameobj) == &js_AttributeNameClass ||
+ OBJ_GET_CLASS(cx, nameobj) == &js_QNameClass.base);
+ }
+
+ qn = nameobj;
+ if (!IsFunctionQName(cx, qn, &funid))
+ return JS_FALSE;
+
+ obj = cx->fp->scopeChain;
+ do {
+ /* Skip any With object that can wrap XML. */
+ target = obj;
+ while (OBJ_GET_CLASS(cx, target) == &js_WithClass) {
+ proto = OBJ_GET_PROTO(cx, target);
+ if (!proto)
+ break;
+ target = proto;
+ }
+
+ if (OBJECT_IS_XML(cx, target)) {
+ if (funid == 0) {
+ xml = (JSXML *) JS_GetPrivate(cx, target);
+ found = HasNamedProperty(xml, qn);
+ } else {
+ if (!HasFunctionProperty(cx, target, funid, &found))
+ return JS_FALSE;
+ }
+ if (found) {
+ *idp = OBJECT_TO_JSID(nameobj);
+ *objp = target;
+ return JS_TRUE;
+ }
+ } else if (funid != 0) {
+ if (!OBJ_LOOKUP_PROPERTY(cx, target, funid, &pobj, &prop))
+ return JS_FALSE;
+ if (prop) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ *idp = funid;
+ *objp = target;
+ return JS_TRUE;
+ }
+ }
+ } while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL);
+
+ printable = js_ValueToPrintableString(cx, OBJECT_TO_JSVAL(nameobj));
+ if (printable) {
+ JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_UNDEFINED_XML_NAME, printable);
+ }
+ return JS_FALSE;
+}
+
+JSBool
+js_GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSObject *target;
+ JSXML *xml;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ JS_ASSERT(OBJECT_IS_XML(cx, obj));
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, NULL, &tvr);
+
+ /*
+ * See comments before xml_lookupProperty about the need for the proto
+ * chain lookup.
+ */
+ target = obj;
+ for (;;) {
+ ok = js_GetProperty(cx, target, id, vp);
+ if (!ok)
+ goto out;
+ if (VALUE_IS_FUNCTION(cx, *vp)) {
+ ok = JS_TRUE;
+ goto out;
+ }
+ target = OBJ_GET_PROTO(cx, target);
+ if (target == NULL)
+ break;
+ tvr.u.object = target;
+ }
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (HasSimpleContent(xml)) {
+ /* Search in String.prototype to implement 11.2.2.1 Step 3(f). */
+ ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(JSProto_String),
+ &tvr.u.object);
+ if (!ok)
+ goto out;
+ JS_ASSERT(tvr.u.object);
+ ok = OBJ_GET_PROPERTY(cx, tvr.u.object, id, vp);
+ }
+
+ out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSXML *
+GetPrivate(JSContext *cx, JSObject *obj, const char *method)
+{
+ JSXML *xml;
+
+ xml = (JSXML *) JS_GetInstancePrivate(cx, obj, &js_XMLClass, NULL);
+ if (!xml) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_INCOMPATIBLE_METHOD,
+ js_XML_str, method, OBJ_GET_CLASS(cx, obj)->name);
+ }
+ return xml;
+}
+
+JSBool
+js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSXML *xml, *list;
+
+ xml = GetPrivate(cx, obj, "descendants internal method");
+ if (!xml)
+ return JS_FALSE;
+
+ list = Descendants(cx, xml, id);
+ if (!list)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(list->object);
+ return JS_TRUE;
+}
+
+JSBool
+js_DeleteXMLListElements(JSContext *cx, JSObject *listobj)
+{
+ JSXML *list;
+ uint32 n;
+
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ for (n = list->xml_kids.length; n != 0; --n)
+ DeleteListElement(cx, list, 0);
+
+ return JS_TRUE;
+}
+
+typedef struct JSXMLFilter {
+ JSXML *list;
+ JSXML *result;
+ JSXML *kid;
+ JSXMLArrayCursor cursor;
+
+} JSXMLFilter;
+
+static void
+xmlfilter_trace(JSTracer *trc, JSObject *obj)
+{
+ JSXMLFilter *filter;
+
+ filter = (JSXMLFilter *) JS_GetPrivate(trc->context, obj);
+ if (!filter)
+ return;
+
+ JS_ASSERT(filter->list);
+ JS_CALL_TRACER(trc, filter->list, JSTRACE_XML, "list");
+ if (filter->result)
+ JS_CALL_TRACER(trc, filter->result, JSTRACE_XML, "result");
+ if (filter->kid)
+ JS_CALL_TRACER(trc, filter->kid, JSTRACE_XML, "kid");
+
+ /*
+ * We do not need to trace the cursor as that would be done when
+ * tracing the filter->list.
+ */
+}
+
+static void
+xmlfilter_finalize(JSContext *cx, JSObject *obj)
+{
+ JSXMLFilter *filter;
+
+ filter = (JSXMLFilter *) JS_GetPrivate(cx, obj);
+ if (!filter)
+ return;
+
+ XMLArrayCursorFinish(&filter->cursor);
+ JS_free(cx, filter);
+}
+
+JSClass js_XMLFilterClass = {
+ "XMLFilter",
+ JSCLASS_HAS_PRIVATE |
+ JSCLASS_IS_ANONYMOUS |
+ JSCLASS_MARK_IS_TRACE |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_XMLFilter),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, xmlfilter_finalize,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, JS_CLASS_TRACE(xmlfilter_trace), NULL
+};
+
+JSObject *
+js_InitXMLFilterClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_XMLFilterClass, NULL, 0, NULL,
+ NULL, NULL, NULL);
+ if (!proto)
+ return NULL;
+
+ OBJ_CLEAR_PROTO(cx, proto);
+ return proto;
+}
+
+JSBool
+js_StepXMLListFilter(JSContext *cx, JSBool initialized)
+{
+ jsval *sp;
+ JSObject *obj, *filterobj, *resobj, *kidobj;
+ JSXML *xml, *list;
+ JSXMLFilter *filter;
+
+ sp = cx->fp->regs->sp;
+ if (!initialized) {
+ /*
+ * We haven't iterated yet, so initialize the filter based on the
+ * value stored in sp[-2].
+ */
+ if (!VALUE_IS_XML(cx, sp[-2])) {
+ js_ReportValueError(cx, JSMSG_NON_XML_FILTER, -2, sp[-2], NULL);
+ return JS_FALSE;
+ }
+ obj = JSVAL_TO_OBJECT(sp[-2]);
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ list = xml;
+ } else {
+ obj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!obj)
+ return JS_FALSE;
+
+ /*
+ * Root just-created obj. sp[-2] cannot be used yet for rooting
+ * as it may be the only root holding xml.
+ */
+ sp[-1] = OBJECT_TO_JSVAL(obj);
+ list = (JSXML *) JS_GetPrivate(cx, obj);
+ if (!Append(cx, list, xml))
+ return JS_FALSE;
+ }
+
+ filterobj = js_NewObject(cx, &js_XMLFilterClass, NULL, NULL, 0);
+ if (!filterobj)
+ return JS_FALSE;
+
+ filter = (JSXMLFilter *) JS_malloc(cx, sizeof *filter);
+ if (!filter)
+ return JS_FALSE;
+
+ /*
+ * Init all filter fields before JS_SetPrivate exposes it to
+ * xmlfilter_trace or xmlfilter_finalize.
+ */
+ filter->list = list;
+ filter->result = NULL;
+ filter->kid = NULL;
+ XMLArrayCursorInit(&filter->cursor, &list->xml_kids);
+ JS_SetPrivate(cx, filterobj, filter);
+
+ /* Store filterobj to use in the later iterations. */
+ sp[-2] = OBJECT_TO_JSVAL(filterobj);
+
+ resobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!resobj)
+ return JS_FALSE;
+
+ /* This also roots resobj. */
+ filter->result = (JSXML *) JS_GetPrivate(cx, resobj);
+ } else {
+ /* We have iterated at least once. */
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(sp[-2]));
+ JS_ASSERT(OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(sp[-2])) ==
+ &js_XMLFilterClass);
+ filter = (JSXMLFilter *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(sp[-2]));
+ JS_ASSERT(filter->kid);
+
+ /* Check if the filter expression wants to append the element. */
+ if (js_ValueToBoolean(sp[-1]) &&
+ !Append(cx, filter->result, filter->kid)) {
+ return JS_FALSE;
+ }
+ }
+
+ /* Do the iteration. */
+ filter->kid = (JSXML *) XMLArrayCursorNext(&filter->cursor);
+ if (!filter->kid) {
+ /*
+ * Do not defer finishing the cursor until the next GC cycle to avoid
+ * accumulation of dead cursors associated with filter->list.
+ */
+ XMLArrayCursorFinish(&filter->cursor);
+ JS_ASSERT(filter->result->object);
+ sp[-2] = OBJECT_TO_JSVAL(filter->result->object);
+ kidobj = NULL;
+ } else {
+ kidobj = js_GetXMLObject(cx, filter->kid);
+ if (!kidobj)
+ return JS_FALSE;
+ }
+
+ /* Null as kidobj at sp[-1] signals filter termination. */
+ sp[-1] = OBJECT_TO_JSVAL(kidobj);
+ return JS_TRUE;
+}
+
+JSObject *
+js_ValueToXMLObject(JSContext *cx, jsval v)
+{
+ return ToXML(cx, v);
+}
+
+JSObject *
+js_ValueToXMLListObject(JSContext *cx, jsval v)
+{
+ return ToXMLList(cx, v);
+}
+
+JSObject *
+js_CloneXMLObject(JSContext *cx, JSObject *obj)
+{
+ uintN flags;
+ JSXML *xml;
+
+ if (!GetXMLSettingFlags(cx, &flags))
+ return NULL;
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (flags & (XSF_IGNORE_COMMENTS |
+ XSF_IGNORE_PROCESSING_INSTRUCTIONS |
+ XSF_IGNORE_WHITESPACE)) {
+ xml = DeepCopy(cx, xml, NULL, flags);
+ if (!xml)
+ return NULL;
+ return xml->object;
+ }
+ return NewXMLObject(cx, xml);
+}
+
+JSObject *
+js_NewXMLSpecialObject(JSContext *cx, JSXMLClass xml_class, JSString *name,
+ JSString *value)
+{
+ uintN flags;
+ JSObject *obj;
+ JSXML *xml;
+ JSObject *qn;
+
+ if (!GetXMLSettingFlags(cx, &flags))
+ return NULL;
+
+ if ((xml_class == JSXML_CLASS_COMMENT &&
+ (flags & XSF_IGNORE_COMMENTS)) ||
+ (xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION &&
+ (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS))) {
+ return js_NewXMLObject(cx, JSXML_CLASS_TEXT);
+ }
+
+ obj = js_NewXMLObject(cx, xml_class);
+ if (!obj)
+ return NULL;
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (name) {
+ qn = NewXMLQName(cx, cx->runtime->emptyString, NULL, name);
+ if (!qn)
+ return NULL;
+ xml->name = qn;
+ }
+ xml->xml_value = value;
+ return obj;
+}
+
+JSString *
+js_MakeXMLCDATAString(JSContext *cx, JSString *str)
+{
+ return MakeXMLCDATAString(cx, NULL, str);
+}
+
+JSString *
+js_MakeXMLCommentString(JSContext *cx, JSString *str)
+{
+ return MakeXMLCommentString(cx, NULL, str);
+}
+
+JSString *
+js_MakeXMLPIString(JSContext *cx, JSString *name, JSString *str)
+{
+ return MakeXMLPIString(cx, NULL, name, str);
+}
+
+#endif /* JS_HAS_XML_SUPPORT */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsxml.h b/tools/node_modules/expresso/deps/jscoverage/js/jsxml.h
new file mode 100644
index 0000000..6952efc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsxml.h
@@ -0,0 +1,298 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey E4X code, released August, 2004.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsxml_h___
+#define jsxml_h___
+
+#include "jsstddef.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+extern const char js_AnyName_str[];
+extern const char js_AttributeName_str[];
+extern const char js_isXMLName_str[];
+extern const char js_XMLList_str[];
+
+extern const char js_amp_entity_str[];
+extern const char js_gt_entity_str[];
+extern const char js_lt_entity_str[];
+extern const char js_quot_entity_str[];
+
+typedef JSBool
+(* JSIdentityOp)(const void *a, const void *b);
+
+struct JSXMLArray {
+ uint32 length;
+ uint32 capacity;
+ void **vector;
+ JSXMLArrayCursor *cursors;
+};
+
+#define JSXML_PRESET_CAPACITY JS_BIT(31)
+#define JSXML_CAPACITY_MASK JS_BITMASK(31)
+#define JSXML_CAPACITY(array) ((array)->capacity & JSXML_CAPACITY_MASK)
+
+struct JSXMLArrayCursor {
+ JSXMLArray *array;
+ uint32 index;
+ JSXMLArrayCursor *next;
+ JSXMLArrayCursor **prevp;
+ void *root;
+};
+
+/*
+ * NB: don't reorder this enum without changing all array initializers that
+ * depend on it in jsxml.c.
+ */
+typedef enum JSXMLClass {
+ JSXML_CLASS_LIST,
+ JSXML_CLASS_ELEMENT,
+ JSXML_CLASS_ATTRIBUTE,
+ JSXML_CLASS_PROCESSING_INSTRUCTION,
+ JSXML_CLASS_TEXT,
+ JSXML_CLASS_COMMENT,
+ JSXML_CLASS_LIMIT
+} JSXMLClass;
+
+#define JSXML_CLASS_HAS_KIDS(class_) ((class_) < JSXML_CLASS_ATTRIBUTE)
+#define JSXML_CLASS_HAS_VALUE(class_) ((class_) >= JSXML_CLASS_ATTRIBUTE)
+#define JSXML_CLASS_HAS_NAME(class_) \
+ ((uintN)((class_) - JSXML_CLASS_ELEMENT) <= \
+ (uintN)(JSXML_CLASS_PROCESSING_INSTRUCTION - JSXML_CLASS_ELEMENT))
+
+#ifdef DEBUG_notme
+#include "jsclist.h"
+#endif
+
+typedef struct JSXMLListVar {
+ JSXMLArray kids; /* NB: must come first */
+ JSXML *target;
+ JSObject *targetprop;
+} JSXMLListVar;
+
+typedef struct JSXMLElemVar {
+ JSXMLArray kids; /* NB: must come first */
+ JSXMLArray namespaces;
+ JSXMLArray attrs;
+} JSXMLElemVar;
+
+struct JSXML {
+#ifdef DEBUG_notme
+ JSCList links;
+ uint32 serial;
+#endif
+ JSObject *object;
+ void *domnode; /* DOM node if mapped info item */
+ JSXML *parent;
+ JSObject *name;
+ uint16 xml_class; /* discriminates u, below */
+ uint16 xml_flags; /* flags, see below */
+ union {
+ JSXMLListVar list;
+ JSXMLElemVar elem;
+ JSString *value;
+ } u;
+
+ /* Don't add anything after u -- see js_NewXML for why. */
+};
+
+/* union member shorthands */
+#define xml_kids u.list.kids
+#define xml_target u.list.target
+#define xml_targetprop u.list.targetprop
+#define xml_namespaces u.elem.namespaces
+#define xml_attrs u.elem.attrs
+#define xml_value u.value
+
+/* xml_flags values */
+#define XMLF_WHITESPACE_TEXT 0x1
+
+/* xml_class-testing macros */
+#define JSXML_HAS_KIDS(xml) JSXML_CLASS_HAS_KIDS((xml)->xml_class)
+#define JSXML_HAS_VALUE(xml) JSXML_CLASS_HAS_VALUE((xml)->xml_class)
+#define JSXML_HAS_NAME(xml) JSXML_CLASS_HAS_NAME((xml)->xml_class)
+#define JSXML_LENGTH(xml) (JSXML_CLASS_HAS_KIDS((xml)->xml_class) \
+ ? (xml)->xml_kids.length \
+ : 0)
+
+extern JSXML *
+js_NewXML(JSContext *cx, JSXMLClass xml_class);
+
+extern void
+js_TraceXML(JSTracer *trc, JSXML *xml);
+
+extern void
+js_FinalizeXML(JSContext *cx, JSXML *xml);
+
+extern JSObject *
+js_ParseNodeToXMLObject(JSContext *cx, JSParseContext *pc, JSParseNode *pn);
+
+extern JSObject *
+js_NewXMLObject(JSContext *cx, JSXMLClass xml_class);
+
+extern JSObject *
+js_GetXMLObject(JSContext *cx, JSXML *xml);
+
+extern JS_FRIEND_DATA(JSXMLObjectOps) js_XMLObjectOps;
+extern JS_FRIEND_DATA(JSClass) js_XMLClass;
+extern JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass;
+extern JS_FRIEND_DATA(JSExtendedClass) js_QNameClass;
+extern JS_FRIEND_DATA(JSClass) js_AttributeNameClass;
+extern JS_FRIEND_DATA(JSClass) js_AnyNameClass;
+extern JSClass js_XMLFilterClass;
+
+/*
+ * Macros to test whether an object or a value is of type "xml" (per typeof).
+ * NB: jsobj.h must be included before any call to OBJECT_IS_XML, and jsapi.h
+ * and jsobj.h must be included before any call to VALUE_IS_XML.
+ */
+#define OBJECT_IS_XML(cx,obj) ((obj)->map->ops == &js_XMLObjectOps.base)
+#define VALUE_IS_XML(cx,v) (!JSVAL_IS_PRIMITIVE(v) && \
+ OBJECT_IS_XML(cx, JSVAL_TO_OBJECT(v)))
+
+extern JSObject *
+js_InitNamespaceClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitQNameClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitAttributeNameClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitAnyNameClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitXMLClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitXMLClasses(JSContext *cx, JSObject *obj);
+
+extern JSBool
+js_GetFunctionNamespace(JSContext *cx, jsval *vp);
+
+/*
+ * If obj is QName corresponding to function::name, set *funidp to name's id,
+ * otherwise set *funidp to 0.
+ */
+JSBool
+js_IsFunctionQName(JSContext *cx, JSObject *obj, jsid *funidp);
+
+extern JSBool
+js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp);
+
+extern JSBool
+js_SetDefaultXMLNamespace(JSContext *cx, jsval v);
+
+/*
+ * Return true if v is a XML QName object, or if it converts to a string that
+ * contains a valid XML qualified name (one containing no :), false otherwise.
+ * NB: This function is an infallible predicate, it hides exceptions.
+ */
+extern JSBool
+js_IsXMLName(JSContext *cx, jsval v);
+
+extern JSBool
+js_ToAttributeName(JSContext *cx, jsval *vp);
+
+extern JSString *
+js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote);
+
+extern JSString *
+js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str,
+ JSString *str2);
+
+extern JSString *
+js_EscapeElementValue(JSContext *cx, JSString *str);
+
+extern JSString *
+js_ValueToXMLString(JSContext *cx, jsval v);
+
+extern JSObject *
+js_ConstructXMLQNameObject(JSContext *cx, jsval nsval, jsval lnval);
+
+extern JSBool
+js_GetAnyName(JSContext *cx, jsval *vp);
+
+/*
+ * Note: nameval must be either QName, AttributeName, or AnyName.
+ */
+extern JSBool
+js_FindXMLProperty(JSContext *cx, jsval nameval, JSObject **objp, jsid *idp);
+
+extern JSBool
+js_GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSBool
+js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+extern JSBool
+js_DeleteXMLListElements(JSContext *cx, JSObject *listobj);
+
+extern JSObject *
+js_InitXMLFilterClass(JSContext *cx, JSObject* obj);
+
+extern JSBool
+js_StepXMLListFilter(JSContext *cx, JSBool initialized);
+
+extern JSObject *
+js_ValueToXMLObject(JSContext *cx, jsval v);
+
+extern JSObject *
+js_ValueToXMLListObject(JSContext *cx, jsval v);
+
+extern JSObject *
+js_CloneXMLObject(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_NewXMLSpecialObject(JSContext *cx, JSXMLClass xml_class, JSString *name,
+ JSString *value);
+
+extern JSString *
+js_MakeXMLCDATAString(JSContext *cx, JSString *str);
+
+extern JSString *
+js_MakeXMLCommentString(JSContext *cx, JSString *str);
+
+extern JSString *
+js_MakeXMLPIString(JSContext *cx, JSString *name, JSString *str);
+
+JS_END_EXTERN_C
+
+#endif /* jsxml_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/lock_SunOS.s b/tools/node_modules/expresso/deps/jscoverage/js/lock_SunOS.s
new file mode 100644
index 0000000..6feb202
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/lock_SunOS.s
@@ -0,0 +1,119 @@
+!
+! ***** BEGIN LICENSE BLOCK *****
+! Version: MPL 1.1/GPL 2.0/LGPL 2.1
+!
+! The contents of this file are subject to the Mozilla Public License Version
+! 1.1 (the "License"); you may not use this file except in compliance with
+! the License. You may obtain a copy of the License at
+! http://www.mozilla.org/MPL/
+!
+! Software distributed under the License is distributed on an "AS IS" basis,
+! WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+! for the specific language governing rights and limitations under the
+! License.
+!
+! The Original Code is Mozilla Communicator client code, released
+! March 31, 1998.
+!
+! The Initial Developer of the Original Code is
+! Netscape Communications Corporation.
+! Portions created by the Initial Developer are Copyright (C) 1998-1999
+! the Initial Developer. All Rights Reserved.
+!
+! Contributor(s):
+!
+! Alternatively, the contents of this file may be used under the terms of
+! either the GNU General Public License Version 2 or later (the "GPL"), or
+! the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+! in which case the provisions of the GPL or the LGPL are applicable instead
+! of those above. If you wish to allow use of your version of this file only
+! under the terms of either the GPL or the LGPL, and not to allow others to
+! use your version of this file under the terms of the MPL, indicate your
+! decision by deleting the provisions above and replace them with the notice
+! and other provisions required by the GPL or the LGPL. If you do not delete
+! the provisions above, a recipient may use your version of this file under
+! the terms of any one of the MPL, the GPL or the LGPL.
+!
+! ***** END LICENSE BLOCK *****
+
+!
+! atomic compare-and-swap routines for V8 sparc
+! and for V8+ (ultrasparc)
+!
+!
+! standard asm linkage macros; this module must be compiled
+! with the -P option (use C preprocessor)
+
+#include <sys/asm_linkage.h>
+
+! ======================================================================
+!
+! Perform the sequence *a = b atomically with respect to previous value
+! of a (a0). If *a==a0 then assign *a to b, all in one atomic operation.
+! Returns 1 if assignment happened, and 0 otherwise.
+!
+! usage : old_val = compare_and_swap(address, oldval, newval)
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created;
+! we use the caller stack frame so what would normally be %i (input)
+! registers are actually %o (output registers). Also, we must not
+! overwrite the contents of %l (local) registers as they are not
+! assumed to be volatile during calls.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the value to increment
+! %o1 [input] - the old value to compare with
+! %o2 [input] - the new value to set for [%o0]
+! %o3 [local] - work register
+! -----------------------
+#ifndef ULTRA_SPARC
+! v8
+
+ ENTRY(compare_and_swap) ! standard assembler/ELF prologue
+
+ stbar
+ mov -1,%o3 ! busy flag
+ swap [%o0],%o3 ! get current value
+l1: cmp %o3,-1 ! busy?
+ be,a l1 ! if so, spin
+ swap [%o0],%o3 ! using branch-delay to swap back value
+ cmp %o1,%o3 ! compare old with current
+ be,a l2 ! if equal then swap in new value
+ swap [%o0],%o2 ! done.
+ swap [%o0],%o3 ! otherwise, swap back current value
+ retl
+ mov 0,%o0 ! return false
+l2: retl
+ mov 1,%o0 ! return true
+
+ SET_SIZE(compare_and_swap) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+#else /* ULTRA_SPARC */
+! ======================================================================
+!
+! v9
+
+ ENTRY(compare_and_swap) ! standard assembler/ELF prologue
+
+ stbar
+ cas [%o0],%o1,%o2 ! compare *w with old value and set to new if equal
+ cmp %o1,%o2 ! did we succeed?
+ be,a m1 ! yes
+ mov 1,%o0 ! return true (annulled when no jump)
+ mov 0,%o0 ! return false
+m1: retl
+ nop
+
+ SET_SIZE(compare_and_swap) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+! ======================================================================
+!
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/editline.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/editline.d
new file mode 100644
index 0000000..31ad136
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/editline.d
@@ -0,0 +1 @@
+../obj/editline/editline.o: editline.c editline.h unix.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/libedit.a b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/libedit.a
new file mode 100644
index 0000000..18c6db8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/libedit.a
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/sysunix.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/sysunix.d
new file mode 100644
index 0000000..4a0da6f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/sysunix.d
@@ -0,0 +1 @@
+../obj/editline/sysunix.o: sysunix.c editline.h unix.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/js b/tools/node_modules/expresso/deps/jscoverage/js/obj/js
new file mode 100755
index 0000000..cd46434
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/js
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h b/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h
new file mode 100644
index 0000000..600253e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef js_config_h___
+#define js_config_h___
+
+/* Definitions set at build time that affect SpiderMonkey's public API.
+ This header file is generated by the SpiderMonkey configure script,
+ and installed along with jsapi.h. */
+
+/* Define to 1 if SpiderMonkey should support multi-threaded clients. */
+#undef JS_THREADSAFE
+
+/* Define to 1 if SpiderMonkey should support the ability to perform
+ entirely too much GC. */
+#undef JS_GC_ZEAL
+
+#endif /* js_config_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h.stamp b/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h.stamp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h.stamp
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/js.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/js.d
new file mode 100644
index 0000000..65fab29
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/js.d
@@ -0,0 +1,7 @@
+obj/js.o: js.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsarena.h jscompat.h jslong.h jsutil.h jsprf.h jsapi.h obj/js-config.h \
+ jspubtd.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h jsatom.h jshash.h \
+ jsdhash.h jslock.h jsbuiltins.h builtins.tbl jscntxt.h jsclist.h jsgc.h \
+ jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h \
+ jsregexp.h jsstr.h js.msg jsdbgapi.h jsemit.h jsnum.h jsparse.h jsscan.h \
+ jskeyword.tbl jsscope.h jsshell.msg
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsapi.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsapi.d
new file mode 100644
index 0000000..9a6b6c0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsapi.d
@@ -0,0 +1,8 @@
+obj/jsapi.o: jsapi.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsarena.h jscompat.h jslong.h jsutil.h jsclist.h jsdhash.h jsprf.h \
+ jsapi.h obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsarray.h \
+ jsprvtd.h jsatom.h jshash.h jslock.h jsbool.h jsbuiltins.h builtins.tbl \
+ jscntxt.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsdate.h jsdtoa.h \
+ jsemit.h jsexn.h jsiter.h jsmath.h jsnum.h json.h jsparse.h jsscan.h \
+ jskeyword.tbl jsscope.h prmjtime.h jsstaticcheck.h jsxml.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarena.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarena.d
new file mode 100644
index 0000000..8a77c8c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarena.d
@@ -0,0 +1,2 @@
+obj/jsarena.o: jsarena.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsbit.h jsutil.h jsarena.h jscompat.h jslong.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarray.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarray.d
new file mode 100644
index 0000000..ae6af74
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarray.d
@@ -0,0 +1,7 @@
+obj/jsarray.o: jsarray.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsutil.h jsapi.h obj/js-config.h jspubtd.h jscompat.h \
+ jslong.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h jsatom.h jshash.h \
+ jsdhash.h jslock.h jsbit.h jsbool.h jsbuiltins.h builtins.tbl jscntxt.h \
+ jsarena.h jsclist.h jsgc.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsdbgapi.h jsdtoa.h \
+ jsnum.h jsscope.h jsstaticcheck.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsatom.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsatom.d
new file mode 100644
index 0000000..61fb258
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsatom.d
@@ -0,0 +1,6 @@
+obj/jsatom.o: jsatom.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jshash.h jscompat.h jslong.h jsprf.h jsapi.h obj/js-config.h \
+ jspubtd.h jsproto.tbl jsversion.h jsatom.h jsdhash.h jsprvtd.h jslock.h \
+ jscntxt.h jsarena.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h \
+ jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsnum.h \
+ jsscan.h jskeyword.tbl
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautocfg.h b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautocfg.h
new file mode 100644
index 0000000..f5b2da8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautocfg.h
@@ -0,0 +1,56 @@
+#ifndef js_cpucfg___
+#define js_cpucfg___
+
+/* AUTOMATICALLY GENERATED - DO NOT EDIT */
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define JS_BYTES_PER_BYTE 1L
+#define JS_BYTES_PER_SHORT 2L
+#define JS_BYTES_PER_INT 4L
+#define JS_BYTES_PER_INT64 8L
+#define JS_BYTES_PER_LONG 8L
+#define JS_BYTES_PER_FLOAT 4L
+#define JS_BYTES_PER_DOUBLE 8L
+#define JS_BYTES_PER_WORD 8L
+#define JS_BYTES_PER_DWORD 8L
+
+#define JS_BITS_PER_BYTE 8L
+#define JS_BITS_PER_SHORT 16L
+#define JS_BITS_PER_INT 32L
+#define JS_BITS_PER_INT64 64L
+#define JS_BITS_PER_LONG 64L
+#define JS_BITS_PER_FLOAT 32L
+#define JS_BITS_PER_DOUBLE 64L
+#define JS_BITS_PER_WORD 64L
+
+#define JS_BITS_PER_BYTE_LOG2 3L
+#define JS_BITS_PER_SHORT_LOG2 4L
+#define JS_BITS_PER_INT_LOG2 5L
+#define JS_BITS_PER_INT64_LOG2 6L
+#define JS_BITS_PER_LONG_LOG2 6L
+#define JS_BITS_PER_FLOAT_LOG2 5L
+#define JS_BITS_PER_DOUBLE_LOG2 6L
+#define JS_BITS_PER_WORD_LOG2 6L
+
+#define JS_ALIGN_OF_SHORT 2L
+#define JS_ALIGN_OF_INT 4L
+#define JS_ALIGN_OF_LONG 8L
+#define JS_ALIGN_OF_INT64 8L
+#define JS_ALIGN_OF_FLOAT 4L
+#define JS_ALIGN_OF_DOUBLE 8L
+#define JS_ALIGN_OF_POINTER 8L
+#define JS_ALIGN_OF_WORD 8L
+
+#define JS_BYTES_PER_WORD_LOG2 3L
+#define JS_BYTES_PER_DWORD_LOG2 3L
+#define JS_WORDS_PER_DWORD_LOG2 0L
+
+#define JS_STACK_GROWTH_DIRECTION (-1)
+
+#define JS_HAVE_LONG_LONG
+
+#define HAVE_VA_LIST_AS_ARRAY 1
+
+#endif /* js_cpucfg___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautokw.h b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautokw.h
new file mode 100644
index 0000000..f3d58f9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautokw.h
@@ -0,0 +1,401 @@
+ /*
+ * Generating switch for the list of 61 entries:
+ * break
+ * case
+ * continue
+ * default
+ * delete
+ * do
+ * else
+ * export
+ * false
+ * for
+ * function
+ * if
+ * in
+ * new
+ * null
+ * return
+ * switch
+ * this
+ * true
+ * typeof
+ * var
+ * void
+ * while
+ * with
+ * const
+ * try
+ * catch
+ * finally
+ * throw
+ * instanceof
+ * abstract
+ * boolean
+ * byte
+ * char
+ * class
+ * double
+ * extends
+ * final
+ * float
+ * goto
+ * implements
+ * import
+ * int
+ * interface
+ * long
+ * native
+ * package
+ * private
+ * protected
+ * public
+ * short
+ * static
+ * super
+ * synchronized
+ * throws
+ * transient
+ * volatile
+ * enum
+ * debugger
+ * yield
+ * let
+ */
+ switch (JSKW_LENGTH()) {
+ case 2:
+ if (JSKW_AT(0) == 'd') {
+ if (JSKW_AT(1)=='o') {
+ JSKW_GOT_MATCH(5) /* do */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'i') {
+ if (JSKW_AT(1) == 'f') {
+ JSKW_GOT_MATCH(11) /* if */
+ }
+ if (JSKW_AT(1) == 'n') {
+ JSKW_GOT_MATCH(12) /* in */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 3:
+ switch (JSKW_AT(2)) {
+ case 'r':
+ if (JSKW_AT(0) == 'f') {
+ if (JSKW_AT(1)=='o') {
+ JSKW_GOT_MATCH(9) /* for */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'v') {
+ if (JSKW_AT(1)=='a') {
+ JSKW_GOT_MATCH(20) /* var */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 't':
+ if (JSKW_AT(0) == 'i') {
+ if (JSKW_AT(1)=='n') {
+ JSKW_GOT_MATCH(42) /* int */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'l') {
+ if (JSKW_AT(1)=='e') {
+ JSKW_GOT_MATCH(60) /* let */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 'w':
+ if (JSKW_AT(0)=='n' && JSKW_AT(1)=='e') {
+ JSKW_GOT_MATCH(13) /* new */
+ }
+ JSKW_NO_MATCH()
+ case 'y':
+ if (JSKW_AT(0)=='t' && JSKW_AT(1)=='r') {
+ JSKW_GOT_MATCH(25) /* try */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 4:
+ switch (JSKW_AT(3)) {
+ case 'd':
+ if (JSKW_AT(0)=='v' && JSKW_AT(1)=='o' && JSKW_AT(2)=='i') {
+ JSKW_GOT_MATCH(21) /* void */
+ }
+ JSKW_NO_MATCH()
+ case 'e':
+ if (JSKW_AT(2) == 's') {
+ if (JSKW_AT(0) == 'c') {
+ if (JSKW_AT(1)=='a') {
+ JSKW_GOT_MATCH(1) /* case */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'e') {
+ if (JSKW_AT(1)=='l') {
+ JSKW_GOT_MATCH(6) /* else */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(2) == 't') {
+ if (JSKW_AT(0)=='b' && JSKW_AT(1)=='y') {
+ JSKW_GOT_MATCH(32) /* byte */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(2) == 'u') {
+ if (JSKW_AT(0)=='t' && JSKW_AT(1)=='r') {
+ JSKW_GOT_MATCH(18) /* true */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 'g':
+ if (JSKW_AT(0)=='l' && JSKW_AT(1)=='o' && JSKW_AT(2)=='n') {
+ JSKW_GOT_MATCH(44) /* long */
+ }
+ JSKW_NO_MATCH()
+ case 'h':
+ if (JSKW_AT(0)=='w' && JSKW_AT(1)=='i' && JSKW_AT(2)=='t') {
+ JSKW_GOT_MATCH(23) /* with */
+ }
+ JSKW_NO_MATCH()
+ case 'l':
+ if (JSKW_AT(0)=='n' && JSKW_AT(1)=='u' && JSKW_AT(2)=='l') {
+ JSKW_GOT_MATCH(14) /* null */
+ }
+ JSKW_NO_MATCH()
+ case 'm':
+ if (JSKW_AT(0)=='e' && JSKW_AT(1)=='n' && JSKW_AT(2)=='u') {
+ JSKW_GOT_MATCH(57) /* enum */
+ }
+ JSKW_NO_MATCH()
+ case 'o':
+ if (JSKW_AT(0)=='g' && JSKW_AT(1)=='o' && JSKW_AT(2)=='t') {
+ JSKW_GOT_MATCH(39) /* goto */
+ }
+ JSKW_NO_MATCH()
+ case 'r':
+ if (JSKW_AT(0)=='c' && JSKW_AT(1)=='h' && JSKW_AT(2)=='a') {
+ JSKW_GOT_MATCH(33) /* char */
+ }
+ JSKW_NO_MATCH()
+ case 's':
+ if (JSKW_AT(0)=='t' && JSKW_AT(1)=='h' && JSKW_AT(2)=='i') {
+ JSKW_GOT_MATCH(17) /* this */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 5:
+ switch (JSKW_AT(3)) {
+ case 'a':
+ if (JSKW_AT(0) == 'b') {
+ if (JSKW_AT(4)=='k' && JSKW_AT(1)=='r' && JSKW_AT(2)=='e') {
+ JSKW_GOT_MATCH(0) /* break */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'f') {
+ if (JSKW_AT(4) == 'l') {
+ if (JSKW_AT(2)=='n' && JSKW_AT(1)=='i') {
+ JSKW_GOT_MATCH(37) /* final */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(4) == 't') {
+ if (JSKW_AT(2)=='o' && JSKW_AT(1)=='l') {
+ JSKW_GOT_MATCH(38) /* float */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 'c':
+ if (JSKW_AT(0)=='c' && JSKW_AT(1)=='a' && JSKW_AT(2)=='t' && JSKW_AT(4)=='h') {
+ JSKW_GOT_MATCH(26) /* catch */
+ }
+ JSKW_NO_MATCH()
+ case 'e':
+ if (JSKW_AT(0)=='s' && JSKW_AT(1)=='u' && JSKW_AT(2)=='p' && JSKW_AT(4)=='r') {
+ JSKW_GOT_MATCH(52) /* super */
+ }
+ JSKW_NO_MATCH()
+ case 'l':
+ if (JSKW_AT(0) == 'w') {
+ if (JSKW_AT(4)=='e' && JSKW_AT(1)=='h' && JSKW_AT(2)=='i') {
+ JSKW_GOT_MATCH(22) /* while */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'y') {
+ if (JSKW_AT(4)=='d' && JSKW_AT(1)=='i' && JSKW_AT(2)=='e') {
+ JSKW_GOT_MATCH(59) /* yield */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 'o':
+ if (JSKW_AT(0)=='t' && JSKW_AT(1)=='h' && JSKW_AT(2)=='r' && JSKW_AT(4)=='w') {
+ JSKW_GOT_MATCH(28) /* throw */
+ }
+ JSKW_NO_MATCH()
+ case 'r':
+ if (JSKW_AT(0)=='s' && JSKW_AT(1)=='h' && JSKW_AT(2)=='o' && JSKW_AT(4)=='t') {
+ JSKW_GOT_MATCH(50) /* short */
+ }
+ JSKW_NO_MATCH()
+ case 's':
+ if (JSKW_AT(0) == 'c') {
+ if (JSKW_AT(4) == 's') {
+ if (JSKW_AT(2)=='a' && JSKW_AT(1)=='l') {
+ JSKW_GOT_MATCH(34) /* class */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(4) == 't') {
+ if (JSKW_AT(2)=='n' && JSKW_AT(1)=='o') {
+ JSKW_GOT_MATCH(24) /* const */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'f') {
+ if (JSKW_AT(4)=='e' && JSKW_AT(1)=='a' && JSKW_AT(2)=='l') {
+ JSKW_GOT_MATCH(8) /* false */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 6:
+ switch (JSKW_AT(0)) {
+ case 'd':
+ if (JSKW_AT(1) == 'o') {
+ if (JSKW_AT(5)=='e' && JSKW_AT(4)=='l' && JSKW_AT(2)=='u' && JSKW_AT(3)=='b') {
+ JSKW_GOT_MATCH(35) /* double */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(1) == 'e') {
+ if (JSKW_AT(5)=='e' && JSKW_AT(4)=='t' && JSKW_AT(2)=='l' && JSKW_AT(3)=='e') {
+ JSKW_GOT_MATCH(4) /* delete */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 'e':
+ JSKW_TEST_GUESS(7) /* export */
+ case 'i':
+ JSKW_TEST_GUESS(41) /* import */
+ case 'n':
+ JSKW_TEST_GUESS(45) /* native */
+ case 'p':
+ JSKW_TEST_GUESS(49) /* public */
+ case 'r':
+ JSKW_TEST_GUESS(15) /* return */
+ case 's':
+ if (JSKW_AT(1) == 't') {
+ if (JSKW_AT(5)=='c' && JSKW_AT(4)=='i' && JSKW_AT(2)=='a' && JSKW_AT(3)=='t') {
+ JSKW_GOT_MATCH(51) /* static */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(1) == 'w') {
+ if (JSKW_AT(5)=='h' && JSKW_AT(4)=='c' && JSKW_AT(2)=='i' && JSKW_AT(3)=='t') {
+ JSKW_GOT_MATCH(16) /* switch */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 't':
+ if (JSKW_AT(5) == 'f') {
+ if (JSKW_AT(4)=='o' && JSKW_AT(1)=='y' && JSKW_AT(2)=='p' && JSKW_AT(3)=='e') {
+ JSKW_GOT_MATCH(19) /* typeof */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(5) == 's') {
+ if (JSKW_AT(4)=='w' && JSKW_AT(1)=='h' && JSKW_AT(2)=='r' && JSKW_AT(3)=='o') {
+ JSKW_GOT_MATCH(54) /* throws */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 7:
+ switch (JSKW_AT(0)) {
+ case 'b':
+ JSKW_TEST_GUESS(31) /* boolean */
+ case 'd':
+ JSKW_TEST_GUESS(3) /* default */
+ case 'e':
+ JSKW_TEST_GUESS(36) /* extends */
+ case 'f':
+ JSKW_TEST_GUESS(27) /* finally */
+ case 'p':
+ if (JSKW_AT(1) == 'a') {
+ JSKW_TEST_GUESS(46) /* package */
+ }
+ if (JSKW_AT(1) == 'r') {
+ JSKW_TEST_GUESS(47) /* private */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 8:
+ switch (JSKW_AT(4)) {
+ case 'g':
+ JSKW_TEST_GUESS(58) /* debugger */
+ case 'i':
+ JSKW_TEST_GUESS(2) /* continue */
+ case 'r':
+ JSKW_TEST_GUESS(30) /* abstract */
+ case 't':
+ if (JSKW_AT(1) == 'o') {
+ JSKW_TEST_GUESS(56) /* volatile */
+ }
+ if (JSKW_AT(1) == 'u') {
+ JSKW_TEST_GUESS(10) /* function */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 9:
+ if (JSKW_AT(1) == 'n') {
+ JSKW_TEST_GUESS(43) /* interface */
+ }
+ if (JSKW_AT(1) == 'r') {
+ if (JSKW_AT(0) == 'p') {
+ JSKW_TEST_GUESS(48) /* protected */
+ }
+ if (JSKW_AT(0) == 't') {
+ JSKW_TEST_GUESS(55) /* transient */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 10:
+ if (JSKW_AT(1) == 'n') {
+ JSKW_TEST_GUESS(29) /* instanceof */
+ }
+ if (JSKW_AT(1) == 'm') {
+ JSKW_TEST_GUESS(40) /* implements */
+ }
+ JSKW_NO_MATCH()
+ case 12:
+ JSKW_TEST_GUESS(53) /* synchronized */
+ }
+ JSKW_NO_MATCH()
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautooplen.h b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautooplen.h
new file mode 100644
index 0000000..136defe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautooplen.h
@@ -0,0 +1,237 @@
+/*
+ * Automatically generated header with JS opcode length constants.
+ *
+ * Do not edit it, alter jsopcode.tbl instead.
+ */
+#define JSOP_INTERRUPT_LENGTH 1
+#define JSOP_PUSH_LENGTH 1
+#define JSOP_POPV_LENGTH 1
+#define JSOP_ENTERWITH_LENGTH 1
+#define JSOP_LEAVEWITH_LENGTH 1
+#define JSOP_RETURN_LENGTH 1
+#define JSOP_GOTO_LENGTH 3
+#define JSOP_IFEQ_LENGTH 3
+#define JSOP_IFNE_LENGTH 3
+#define JSOP_ARGUMENTS_LENGTH 1
+#define JSOP_FORARG_LENGTH 3
+#define JSOP_FORLOCAL_LENGTH 3
+#define JSOP_DUP_LENGTH 1
+#define JSOP_DUP2_LENGTH 1
+#define JSOP_SETCONST_LENGTH 3
+#define JSOP_BITOR_LENGTH 1
+#define JSOP_BITXOR_LENGTH 1
+#define JSOP_BITAND_LENGTH 1
+#define JSOP_EQ_LENGTH 1
+#define JSOP_NE_LENGTH 1
+#define JSOP_LT_LENGTH 1
+#define JSOP_LE_LENGTH 1
+#define JSOP_GT_LENGTH 1
+#define JSOP_GE_LENGTH 1
+#define JSOP_LSH_LENGTH 1
+#define JSOP_RSH_LENGTH 1
+#define JSOP_URSH_LENGTH 1
+#define JSOP_ADD_LENGTH 1
+#define JSOP_SUB_LENGTH 1
+#define JSOP_MUL_LENGTH 1
+#define JSOP_DIV_LENGTH 1
+#define JSOP_MOD_LENGTH 1
+#define JSOP_NOT_LENGTH 1
+#define JSOP_BITNOT_LENGTH 1
+#define JSOP_NEG_LENGTH 1
+#define JSOP_NEW_LENGTH 3
+#define JSOP_DELNAME_LENGTH 3
+#define JSOP_DELPROP_LENGTH 3
+#define JSOP_DELELEM_LENGTH 1
+#define JSOP_TYPEOF_LENGTH 1
+#define JSOP_VOID_LENGTH 1
+#define JSOP_INCNAME_LENGTH 3
+#define JSOP_INCPROP_LENGTH 3
+#define JSOP_INCELEM_LENGTH 1
+#define JSOP_DECNAME_LENGTH 3
+#define JSOP_DECPROP_LENGTH 3
+#define JSOP_DECELEM_LENGTH 1
+#define JSOP_NAMEINC_LENGTH 3
+#define JSOP_PROPINC_LENGTH 3
+#define JSOP_ELEMINC_LENGTH 1
+#define JSOP_NAMEDEC_LENGTH 3
+#define JSOP_PROPDEC_LENGTH 3
+#define JSOP_ELEMDEC_LENGTH 1
+#define JSOP_GETPROP_LENGTH 3
+#define JSOP_SETPROP_LENGTH 3
+#define JSOP_GETELEM_LENGTH 1
+#define JSOP_SETELEM_LENGTH 1
+#define JSOP_CALLNAME_LENGTH 3
+#define JSOP_CALL_LENGTH 3
+#define JSOP_NAME_LENGTH 3
+#define JSOP_DOUBLE_LENGTH 3
+#define JSOP_STRING_LENGTH 3
+#define JSOP_ZERO_LENGTH 1
+#define JSOP_ONE_LENGTH 1
+#define JSOP_NULL_LENGTH 1
+#define JSOP_THIS_LENGTH 1
+#define JSOP_FALSE_LENGTH 1
+#define JSOP_TRUE_LENGTH 1
+#define JSOP_OR_LENGTH 3
+#define JSOP_AND_LENGTH 3
+#define JSOP_TABLESWITCH_LENGTH -1
+#define JSOP_LOOKUPSWITCH_LENGTH -1
+#define JSOP_STRICTEQ_LENGTH 1
+#define JSOP_STRICTNE_LENGTH 1
+#define JSOP_NULLTHIS_LENGTH 1
+#define JSOP_ITER_LENGTH 2
+#define JSOP_NEXTITER_LENGTH 1
+#define JSOP_ENDITER_LENGTH 1
+#define JSOP_APPLY_LENGTH 3
+#define JSOP_SWAP_LENGTH 1
+#define JSOP_OBJECT_LENGTH 3
+#define JSOP_POP_LENGTH 1
+#define JSOP_POS_LENGTH 1
+#define JSOP_TRAP_LENGTH 1
+#define JSOP_GETARG_LENGTH 3
+#define JSOP_SETARG_LENGTH 3
+#define JSOP_GETLOCAL_LENGTH 3
+#define JSOP_SETLOCAL_LENGTH 3
+#define JSOP_UINT16_LENGTH 3
+#define JSOP_NEWINIT_LENGTH 2
+#define JSOP_ENDINIT_LENGTH 1
+#define JSOP_INITPROP_LENGTH 3
+#define JSOP_INITELEM_LENGTH 1
+#define JSOP_DEFSHARP_LENGTH 3
+#define JSOP_USESHARP_LENGTH 3
+#define JSOP_INCARG_LENGTH 3
+#define JSOP_DECARG_LENGTH 3
+#define JSOP_ARGINC_LENGTH 3
+#define JSOP_ARGDEC_LENGTH 3
+#define JSOP_INCLOCAL_LENGTH 3
+#define JSOP_DECLOCAL_LENGTH 3
+#define JSOP_LOCALINC_LENGTH 3
+#define JSOP_LOCALDEC_LENGTH 3
+#define JSOP_IMACOP_LENGTH 1
+#define JSOP_FORNAME_LENGTH 3
+#define JSOP_FORPROP_LENGTH 3
+#define JSOP_FORELEM_LENGTH 1
+#define JSOP_POPN_LENGTH 3
+#define JSOP_BINDNAME_LENGTH 3
+#define JSOP_SETNAME_LENGTH 3
+#define JSOP_THROW_LENGTH 1
+#define JSOP_IN_LENGTH 1
+#define JSOP_INSTANCEOF_LENGTH 1
+#define JSOP_DEBUGGER_LENGTH 1
+#define JSOP_GOSUB_LENGTH 3
+#define JSOP_RETSUB_LENGTH 1
+#define JSOP_EXCEPTION_LENGTH 1
+#define JSOP_LINENO_LENGTH 3
+#define JSOP_CONDSWITCH_LENGTH 1
+#define JSOP_CASE_LENGTH 3
+#define JSOP_DEFAULT_LENGTH 3
+#define JSOP_EVAL_LENGTH 3
+#define JSOP_ENUMELEM_LENGTH 1
+#define JSOP_GETTER_LENGTH 1
+#define JSOP_SETTER_LENGTH 1
+#define JSOP_DEFFUN_LENGTH 3
+#define JSOP_DEFCONST_LENGTH 3
+#define JSOP_DEFVAR_LENGTH 3
+#define JSOP_ANONFUNOBJ_LENGTH 3
+#define JSOP_NAMEDFUNOBJ_LENGTH 3
+#define JSOP_SETLOCALPOP_LENGTH 3
+#define JSOP_UNUSED131_LENGTH 1
+#define JSOP_SETCALL_LENGTH 3
+#define JSOP_TRY_LENGTH 1
+#define JSOP_FINALLY_LENGTH 1
+#define JSOP_NOP_LENGTH 1
+#define JSOP_ARGSUB_LENGTH 3
+#define JSOP_ARGCNT_LENGTH 1
+#define JSOP_DEFLOCALFUN_LENGTH 5
+#define JSOP_GOTOX_LENGTH 5
+#define JSOP_IFEQX_LENGTH 5
+#define JSOP_IFNEX_LENGTH 5
+#define JSOP_ORX_LENGTH 5
+#define JSOP_ANDX_LENGTH 5
+#define JSOP_GOSUBX_LENGTH 5
+#define JSOP_CASEX_LENGTH 5
+#define JSOP_DEFAULTX_LENGTH 5
+#define JSOP_TABLESWITCHX_LENGTH -1
+#define JSOP_LOOKUPSWITCHX_LENGTH -1
+#define JSOP_BACKPATCH_LENGTH 3
+#define JSOP_BACKPATCH_POP_LENGTH 3
+#define JSOP_THROWING_LENGTH 1
+#define JSOP_SETRVAL_LENGTH 1
+#define JSOP_RETRVAL_LENGTH 1
+#define JSOP_GETGVAR_LENGTH 3
+#define JSOP_SETGVAR_LENGTH 3
+#define JSOP_INCGVAR_LENGTH 3
+#define JSOP_DECGVAR_LENGTH 3
+#define JSOP_GVARINC_LENGTH 3
+#define JSOP_GVARDEC_LENGTH 3
+#define JSOP_REGEXP_LENGTH 3
+#define JSOP_DEFXMLNS_LENGTH 1
+#define JSOP_ANYNAME_LENGTH 1
+#define JSOP_QNAMEPART_LENGTH 3
+#define JSOP_QNAMECONST_LENGTH 3
+#define JSOP_QNAME_LENGTH 1
+#define JSOP_TOATTRNAME_LENGTH 1
+#define JSOP_TOATTRVAL_LENGTH 1
+#define JSOP_ADDATTRNAME_LENGTH 1
+#define JSOP_ADDATTRVAL_LENGTH 1
+#define JSOP_BINDXMLNAME_LENGTH 1
+#define JSOP_SETXMLNAME_LENGTH 1
+#define JSOP_XMLNAME_LENGTH 1
+#define JSOP_DESCENDANTS_LENGTH 1
+#define JSOP_FILTER_LENGTH 3
+#define JSOP_ENDFILTER_LENGTH 3
+#define JSOP_TOXML_LENGTH 1
+#define JSOP_TOXMLLIST_LENGTH 1
+#define JSOP_XMLTAGEXPR_LENGTH 1
+#define JSOP_XMLELTEXPR_LENGTH 1
+#define JSOP_XMLOBJECT_LENGTH 3
+#define JSOP_XMLCDATA_LENGTH 3
+#define JSOP_XMLCOMMENT_LENGTH 3
+#define JSOP_XMLPI_LENGTH 3
+#define JSOP_CALLPROP_LENGTH 3
+#define JSOP_GETFUNNS_LENGTH 1
+#define JSOP_GETUPVAR_LENGTH 3
+#define JSOP_DELDESC_LENGTH 1
+#define JSOP_UINT24_LENGTH 4
+#define JSOP_INDEXBASE_LENGTH 2
+#define JSOP_RESETBASE_LENGTH 1
+#define JSOP_RESETBASE0_LENGTH 1
+#define JSOP_STARTXML_LENGTH 1
+#define JSOP_STARTXMLEXPR_LENGTH 1
+#define JSOP_CALLELEM_LENGTH 1
+#define JSOP_STOP_LENGTH 1
+#define JSOP_GETXPROP_LENGTH 3
+#define JSOP_CALLXMLNAME_LENGTH 1
+#define JSOP_TYPEOFEXPR_LENGTH 1
+#define JSOP_ENTERBLOCK_LENGTH 3
+#define JSOP_LEAVEBLOCK_LENGTH 3
+#define JSOP_UNUSED201_LENGTH 1
+#define JSOP_UNUSED202_LENGTH 1
+#define JSOP_UNUSED203_LENGTH 1
+#define JSOP_UNUSED204_LENGTH 1
+#define JSOP_UNUSED205_LENGTH 1
+#define JSOP_UNUSED206_LENGTH 1
+#define JSOP_UNUSED207_LENGTH 1
+#define JSOP_UNUSED208_LENGTH 1
+#define JSOP_UNUSED209_LENGTH 1
+#define JSOP_GENERATOR_LENGTH 1
+#define JSOP_YIELD_LENGTH 1
+#define JSOP_ARRAYPUSH_LENGTH 3
+#define JSOP_CALLUPVAR_LENGTH 3
+#define JSOP_ENUMCONSTELEM_LENGTH 1
+#define JSOP_LEAVEBLOCKEXPR_LENGTH 3
+#define JSOP_GETTHISPROP_LENGTH 3
+#define JSOP_GETARGPROP_LENGTH 5
+#define JSOP_GETLOCALPROP_LENGTH 5
+#define JSOP_UNUSED219_LENGTH 1
+#define JSOP_INDEXBASE1_LENGTH 1
+#define JSOP_INDEXBASE2_LENGTH 1
+#define JSOP_INDEXBASE3_LENGTH 1
+#define JSOP_CALLGVAR_LENGTH 3
+#define JSOP_CALLLOCAL_LENGTH 3
+#define JSOP_CALLARG_LENGTH 3
+#define JSOP_UNUSED226_LENGTH 1
+#define JSOP_INT8_LENGTH 2
+#define JSOP_INT32_LENGTH 5
+#define JSOP_LENGTH_LENGTH 1
+#define JSOP_NEWARRAY_LENGTH 4
+#define JSOP_HOLE_LENGTH 1
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsbool.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsbool.d
new file mode 100644
index 0000000..94638dd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsbool.d
@@ -0,0 +1,6 @@
+obj/jsbool.o: jsbool.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jsapi.h obj/js-config.h jspubtd.h jscompat.h jslong.h \
+ jsproto.tbl jsversion.h jsatom.h jshash.h jsdhash.h jsprvtd.h jslock.h \
+ jsbool.h jscntxt.h jsarena.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsnum.h jsprf.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jscntxt.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscntxt.d
new file mode 100644
index 0000000..e0b45c7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscntxt.d
@@ -0,0 +1,7 @@
+obj/jscntxt.o: jscntxt.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h jsclist.h jsprf.h \
+ jsatom.h jsversion.h jshash.h jsdhash.h jsapi.h obj/js-config.h \
+ jspubtd.h jsproto.tbl jsprvtd.h jslock.h jscntxt.h jsgc.h jsbit.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsdbgapi.h jsexn.h jsnum.h jsscan.h jskeyword.tbl \
+ jsscope.h jstracer.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg
new file mode 100755
index 0000000..cbcaa26
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg.d
new file mode 100644
index 0000000..428ec55
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg.d
@@ -0,0 +1 @@
+obj/jscpucfg.o: jscpucfg.cpp
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdate.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdate.d
new file mode 100644
index 0000000..615e8c8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdate.d
@@ -0,0 +1,6 @@
+obj/jsdate.o: jsdate.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsprf.h prmjtime.h jslong.h jsutil.h jsapi.h obj/js-config.h jspubtd.h \
+ jscompat.h jsproto.tbl jsversion.h jsbuiltins.h builtins.tbl jscntxt.h \
+ jsarena.h jsclist.h jsatom.h jshash.h jsdhash.h jsprvtd.h jslock.h \
+ jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl \
+ jsscript.h jsregexp.h jsstr.h js.msg jsdate.h jsnum.h jsdtoa.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdbgapi.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdbgapi.d
new file mode 100644
index 0000000..9d8f92b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdbgapi.d
@@ -0,0 +1,7 @@
+obj/jsdbgapi.o: jsdbgapi.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsutil.h jsclist.h jsapi.h obj/js-config.h jspubtd.h \
+ jscompat.h jslong.h jsproto.tbl jsversion.h jscntxt.h jsarena.h jsatom.h \
+ jshash.h jsdhash.h jsprvtd.h jslock.h jsgc.h jsbit.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsdbgapi.h jsemit.h jsparse.h jsscan.h jskeyword.tbl jsscope.h \
+ obj/jsautooplen.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdhash.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdhash.d
new file mode 100644
index 0000000..2ccc9e5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdhash.d
@@ -0,0 +1,2 @@
+obj/jsdhash.o: jsdhash.cpp jsbit.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jsdhash.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdtoa.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdtoa.d
new file mode 100644
index 0000000..a89c019
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdtoa.d
@@ -0,0 +1,3 @@
+obj/jsdtoa.o: jsdtoa.cpp jsstddef.h jslibmath.h jsversion.h jstypes.h \
+ obj/jsautocfg.h jsotypes.h jsdtoa.h jscompat.h jslong.h jsprf.h jsutil.h \
+ jspubtd.h jsproto.tbl jsnum.h jsbit.h dtoa.c
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsemit.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsemit.d
new file mode 100644
index 0000000..ae918e6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsemit.d
@@ -0,0 +1,7 @@
+obj/jsemit.o: jsemit.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsarena.h jscompat.h jslong.h jsutil.h jsbit.h jsprf.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsatom.h jshash.h \
+ jsdhash.h jsprvtd.h jslock.h jsbool.h jscntxt.h jsclist.h jsgc.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsemit.h jsnum.h jsparse.h jsscan.h jskeyword.tbl \
+ jsscope.h obj/jsautooplen.h jsstaticcheck.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsexn.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsexn.d
new file mode 100644
index 0000000..8f507d7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsexn.d
@@ -0,0 +1,6 @@
+obj/jsexn.o: jsexn.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsbit.h jsutil.h jsprf.h jsapi.h obj/js-config.h jspubtd.h jscompat.h \
+ jslong.h jsproto.tbl jsversion.h jscntxt.h jsarena.h jsclist.h jsatom.h \
+ jshash.h jsdhash.h jsprvtd.h jslock.h jsgc.h jsinterp.h jsfun.h jsobj.h \
+ jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsdbgapi.h \
+ jsexn.h jsnum.h jsscope.h jsstaticcheck.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsfun.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsfun.d
new file mode 100644
index 0000000..6b70eac
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsfun.d
@@ -0,0 +1,7 @@
+obj/jsfun.o: jsfun.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsbit.h jsutil.h jsapi.h obj/js-config.h jspubtd.h jscompat.h jslong.h \
+ jsproto.tbl jsversion.h jsarray.h jsprvtd.h jsatom.h jshash.h jsdhash.h \
+ jslock.h jsbuiltins.h builtins.tbl jscntxt.h jsarena.h jsclist.h jsgc.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsdbgapi.h jsemit.h jsnum.h jsparse.h jsscan.h \
+ jskeyword.tbl jsscope.h jsexn.h jsstaticcheck.h jsiter.h jsxdrapi.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsgc.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsgc.d
new file mode 100644
index 0000000..4d05348
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsgc.d
@@ -0,0 +1,7 @@
+obj/jsgc.o: jsgc.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jshash.h jscompat.h jslong.h jsbit.h jsclist.h jsprf.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsatom.h jsdhash.h \
+ jsprvtd.h jslock.h jscntxt.h jsarena.h jsgc.h jsinterp.h jsfun.h jsobj.h \
+ jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsdbgapi.h \
+ jsexn.h jsiter.h jsnum.h jsparse.h jsscan.h jskeyword.tbl jsscope.h \
+ jstracer.h jsxml.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jshash.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jshash.d
new file mode 100644
index 0000000..55d434e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jshash.d
@@ -0,0 +1,2 @@
+obj/jshash.o: jshash.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsbit.h jsutil.h jshash.h jscompat.h jslong.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinterp.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinterp.d
new file mode 100644
index 0000000..0fc0a96
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinterp.d
@@ -0,0 +1,8 @@
+obj/jsinterp.o: jsinterp.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h jsprf.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h \
+ jsatom.h jshash.h jsdhash.h jslock.h jsbool.h jscntxt.h jsclist.h jsgc.h \
+ jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h \
+ jsregexp.h jsstr.h js.msg jsdbgapi.h jsiter.h jsnum.h jsscan.h \
+ jskeyword.tbl jsscope.h jsstaticcheck.h jstracer.h jsxml.h \
+ obj/jsautooplen.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinvoke.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinvoke.d
new file mode 100644
index 0000000..c8fe979
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinvoke.d
@@ -0,0 +1,8 @@
+obj/jsinvoke.o: jsinvoke.cpp jsinterp.cpp jsstddef.h jstypes.h \
+ obj/jsautocfg.h jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h \
+ jsprf.h jsapi.h obj/js-config.h jspubtd.h jsproto.tbl jsversion.h \
+ jsarray.h jsprvtd.h jsatom.h jshash.h jsdhash.h jslock.h jsbool.h \
+ jscntxt.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsdbgapi.h jsiter.h \
+ jsnum.h jsscan.h jskeyword.tbl jsscope.h jsstaticcheck.h jstracer.h \
+ jsxml.h obj/jsautooplen.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsiter.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsiter.d
new file mode 100644
index 0000000..d8a6eba
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsiter.d
@@ -0,0 +1,6 @@
+obj/jsiter.o: jsiter.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jsarena.h jscompat.h jslong.h jsapi.h obj/js-config.h jspubtd.h \
+ jsproto.tbl jsversion.h jsarray.h jsprvtd.h jsatom.h jshash.h jsdhash.h \
+ jslock.h jsbool.h jscntxt.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsexn.h jsiter.h jsnum.h jsscan.h jskeyword.tbl jsscope.h jsxml.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen b/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen
new file mode 100755
index 0000000..274c184
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen.d
new file mode 100644
index 0000000..c6c2cb4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen.d
@@ -0,0 +1 @@
+obj/jskwgen: jskwgen.cpp jsstddef.h jsversion.h jskeyword.tbl
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jslock.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslock.d
new file mode 100644
index 0000000..2f0db29
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslock.d
@@ -0,0 +1 @@
+obj/jslock.o: jslock.cpp
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jslog2.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslog2.d
new file mode 100644
index 0000000..57c6194
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslog2.d
@@ -0,0 +1,2 @@
+obj/jslog2.o: jslog2.cpp jsstddef.h jsbit.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsutil.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jslong.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslong.d
new file mode 100644
index 0000000..d6cdd4c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslong.d
@@ -0,0 +1,2 @@
+obj/jslong.o: jslong.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jslong.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsmath.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsmath.d
new file mode 100644
index 0000000..4eacf46
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsmath.d
@@ -0,0 +1,6 @@
+obj/jsmath.o: jsmath.cpp jsstddef.h jslibmath.h jsversion.h jstypes.h \
+ obj/jsautocfg.h jsotypes.h jslong.h prmjtime.h jsapi.h obj/js-config.h \
+ jspubtd.h jscompat.h jsproto.tbl jsutil.h jsatom.h jshash.h jsdhash.h \
+ jsprvtd.h jslock.h jsbuiltins.h builtins.tbl jscntxt.h jsarena.h \
+ jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsmath.h jsnum.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsnum.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsnum.d
new file mode 100644
index 0000000..00442d3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsnum.d
@@ -0,0 +1,6 @@
+obj/jsnum.o: jsnum.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jsapi.h obj/js-config.h jspubtd.h jscompat.h jslong.h \
+ jsproto.tbl jsversion.h jsatom.h jshash.h jsdhash.h jsprvtd.h jslock.h \
+ jsbuiltins.h builtins.tbl jscntxt.h jsarena.h jsclist.h jsgc.h jsbit.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsdtoa.h jsnum.h jsprf.h jsscope.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsobj.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsobj.d
new file mode 100644
index 0000000..c6f20a6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsobj.d
@@ -0,0 +1,8 @@
+obj/jsobj.o: jsobj.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsarena.h jscompat.h jslong.h jsbit.h jsutil.h jshash.h jsdhash.h \
+ jsprf.h jsapi.h obj/js-config.h jspubtd.h jsproto.tbl jsversion.h \
+ jsarray.h jsprvtd.h jsatom.h jslock.h jsbool.h jsbuiltins.h builtins.tbl \
+ jscntxt.h jsclist.h jsgc.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsemit.h jsnum.h \
+ jsparse.h jsscan.h jskeyword.tbl jsscope.h jsdbgapi.h jsstaticcheck.h \
+ jsiter.h jsxml.h jsxdrapi.h obj/jsautooplen.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/json.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/json.d
new file mode 100644
index 0000000..ad64d0c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/json.d
@@ -0,0 +1,6 @@
+obj/json.o: json.cpp jsapi.h obj/js-config.h jspubtd.h jstypes.h \
+ obj/jsautocfg.h jsotypes.h jscompat.h jslong.h jsproto.tbl jsversion.h \
+ jsutil.h jsarena.h jsarray.h jsprvtd.h jsatom.h jshash.h jsdhash.h \
+ jslock.h jsbool.h jscntxt.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsdtoa.h jsiter.h jsnum.h jsprf.h jsscan.h jskeyword.tbl json.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsopcode.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsopcode.d
new file mode 100644
index 0000000..829d95c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsopcode.d
@@ -0,0 +1,8 @@
+obj/jsopcode.o: jsopcode.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h jsdtoa.h jsprf.h \
+ jsapi.h obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsarray.h \
+ jsprvtd.h jsatom.h jshash.h jsdhash.h jslock.h jscntxt.h jsclist.h \
+ jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl \
+ jsscript.h jsregexp.h jsstr.h js.msg jsdbgapi.h jsemit.h jsiter.h \
+ jsnum.h jsscan.h jskeyword.tbl jsscope.h jsstaticcheck.h jstracer.h \
+ obj/jsautooplen.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen
new file mode 100755
index 0000000..619a313
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen.d
new file mode 100644
index 0000000..6094d24
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen.d
@@ -0,0 +1 @@
+obj/jsoplengen: jsoplengen.cpp jsopcode.tbl
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsparse.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsparse.d
new file mode 100644
index 0000000..ce7ca2b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsparse.d
@@ -0,0 +1,7 @@
+obj/jsparse.o: jsparse.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h \
+ jsatom.h jshash.h jsdhash.h jslock.h jscntxt.h jsclist.h jsgc.h jsbit.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsemit.h jsiter.h jsnum.h jsparse.h jsscan.h \
+ jskeyword.tbl jsscope.h jsstaticcheck.h jsxml.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsprf.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsprf.d
new file mode 100644
index 0000000..9f45c2e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsprf.d
@@ -0,0 +1,3 @@
+obj/jsprf.o: jsprf.cpp jsstddef.h jsprf.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jslong.h jsutil.h jspubtd.h jscompat.h jsproto.tbl \
+ jsversion.h jsstr.h jsprvtd.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsregexp.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsregexp.d
new file mode 100644
index 0000000..a5ee9eb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsregexp.d
@@ -0,0 +1,7 @@
+obj/jsregexp.o: jsregexp.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h \
+ jsatom.h jshash.h jsdhash.h jslock.h jsbuiltins.h builtins.tbl jscntxt.h \
+ jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsnum.h jsscan.h \
+ jskeyword.tbl jsscope.h jsreops.tbl jsxdrapi.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscan.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscan.d
new file mode 100644
index 0000000..d1e348d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscan.d
@@ -0,0 +1,7 @@
+obj/jsscan.o: jsscan.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsarena.h jscompat.h jslong.h jsutil.h jsdtoa.h jsprf.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsatom.h jshash.h \
+ jsdhash.h jsprvtd.h jslock.h jscntxt.h jsclist.h jsgc.h jsbit.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsemit.h jsexn.h jsnum.h jsparse.h jsscan.h jskeyword.tbl \
+ jsstaticcheck.h jsxml.h obj/jsautokw.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscope.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscope.d
new file mode 100644
index 0000000..ac99d20
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscope.d
@@ -0,0 +1,6 @@
+obj/jsscope.o: jsscope.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsbit.h jsutil.h jsclist.h \
+ jsdhash.h jsapi.h obj/js-config.h jspubtd.h jsproto.tbl jsversion.h \
+ jsatom.h jshash.h jsprvtd.h jslock.h jscntxt.h jsgc.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsdbgapi.h jsnum.h jsscope.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscript.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscript.d
new file mode 100644
index 0000000..8d8ce7f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscript.d
@@ -0,0 +1,7 @@
+obj/jsscript.o: jsscript.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsutil.h jsprf.h jsapi.h obj/js-config.h jspubtd.h jscompat.h \
+ jslong.h jsproto.tbl jsversion.h jsatom.h jshash.h jsdhash.h jsprvtd.h \
+ jslock.h jscntxt.h jsarena.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsdbgapi.h jsemit.h jsnum.h jsparse.h jsscan.h jskeyword.tbl jsscope.h \
+ jsxdrapi.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsstr.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsstr.d
new file mode 100644
index 0000000..d9e0123
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsstr.d
@@ -0,0 +1,6 @@
+obj/jsstr.o: jsstr.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jshash.h jscompat.h jslong.h jsprf.h jsapi.h obj/js-config.h \
+ jspubtd.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h jsatom.h jsdhash.h \
+ jslock.h jsbool.h jsbuiltins.h builtins.tbl jscntxt.h jsarena.h \
+ jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsnum.h jsscope.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsutil.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsutil.d
new file mode 100644
index 0000000..8e006a2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsutil.d
@@ -0,0 +1,2 @@
+obj/jsutil.o: jsutil.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxdrapi.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxdrapi.d
new file mode 100644
index 0000000..c4b0c9b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxdrapi.d
@@ -0,0 +1,6 @@
+obj/jsxdrapi.o: jsxdrapi.cpp jsstddef.h jsversion.h jstypes.h \
+ obj/jsautocfg.h jsotypes.h jsutil.h jsdhash.h jsprf.h jsapi.h \
+ obj/js-config.h jspubtd.h jscompat.h jslong.h jsproto.tbl jscntxt.h \
+ jsarena.h jsclist.h jsatom.h jshash.h jsprvtd.h jslock.h jsgc.h jsbit.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsnum.h jsxdrapi.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxml.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxml.d
new file mode 100644
index 0000000..aa039af
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxml.d
@@ -0,0 +1,7 @@
+obj/jsxml.o: jsxml.cpp jsstddef.h jsversion.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsbit.h jsutil.h jsprf.h jsapi.h obj/js-config.h jspubtd.h \
+ jscompat.h jslong.h jsproto.tbl jsarray.h jsprvtd.h jsatom.h jshash.h \
+ jsdhash.h jslock.h jsbool.h jscntxt.h jsarena.h jsclist.h jsgc.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsnum.h jsparse.h jsscan.h jskeyword.tbl jsscope.h \
+ jsxml.h jsstaticcheck.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.a b/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.a
new file mode 100644
index 0000000..be68e4d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.a
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.so b/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.so
new file mode 100755
index 0000000..31cc07a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.so
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/prmjtime.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/prmjtime.d
new file mode 100644
index 0000000..60dfae7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/prmjtime.d
@@ -0,0 +1,3 @@
+obj/prmjtime.o: prmjtime.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsutil.h jsprf.h jslock.h jsprvtd.h jspubtd.h jscompat.h \
+ jslong.h jsproto.tbl jsversion.h prmjtime.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/plify_jsdhash.sed b/tools/node_modules/expresso/deps/jscoverage/js/plify_jsdhash.sed
new file mode 100644
index 0000000..6827485
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/plify_jsdhash.sed
@@ -0,0 +1,35 @@
+/ * Double hashing implementation./a\
+ * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!!
+/ * Double hashing, a la Knuth 6./a\
+ * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!!
+s/jsdhash_h___/pldhash_h___/
+s/jsdhash\.bigdump/pldhash.bigdump/
+s/jstypes\.h/nscore.h/
+s/jsbit\.h/prbit.h/
+s/jsdhash\.h/pldhash.h/
+s/jsdhash\.c/pldhash.c/
+s/jsdhash:/pldhash:/
+s/jsutil\.h/nsDebug.h/
+s/JS_DHASH/PL_DHASH/g
+s/JS_DHash/PL_DHash/g
+s/JSDHash/PLDHash/g
+s/JSHash/PLHash/g
+s/uint32 /PRUint32/g
+s/\([^U]\)int32 /\1PRInt32/g
+s/uint16 /PRUint16/g
+s/\([^U]\)int16 /\1PRInt16/g
+s/uint32/PRUint32/g
+s/\([^U]\)int32/\1PRInt32/g
+s/uint16/PRUint16/g
+s/\([^U]\)int16/\1PRInt16/g
+s/JSBool/PRBool/g
+s/extern JS_PUBLIC_API(\([^()]*\))/NS_COM_GLUE \1/
+s/JS_PUBLIC_API(\([^()]*\))/\1/
+s/JS_NewDHashTable/PL_NewDHashTable/
+s/JS_ASSERT(0)/NS_NOTREACHED("0")/
+s/\( *\)JS_ASSERT(\(.*\));/\1NS_ASSERTION(\2,\n\1 "\2");/
+s/JSDHASH_ONELINE_ASSERT(\(.*\));/NS_ASSERTION(\1, "\1");/
+s/JS_UNLIKELY/NS_UNLIKELY/g
+s/JS_LIKELY/NS_LIKELY/g
+s/JS_/PR_/g
+s/fprintf(stderr,/printf_stderr(/
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.cpp b/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.cpp
new file mode 100644
index 0000000..881dd70
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.cpp
@@ -0,0 +1,846 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * PR time code.
+ */
+#include "jsstddef.h"
+#ifdef SOLARIS
+#define _REENTRANT 1
+#endif
+#include <string.h>
+#include <time.h>
+#include "jstypes.h"
+#include "jsutil.h"
+
+#include "jsprf.h"
+#include "jslock.h"
+#include "prmjtime.h"
+
+#define PRMJ_DO_MILLISECONDS 1
+
+#ifdef XP_OS2
+#include <sys/timeb.h>
+#endif
+#ifdef XP_WIN
+#include <windef.h>
+#include <winbase.h>
+#include <math.h> /* for fabs */
+#include <mmsystem.h> /* for timeBegin/EndPeriod */
+/* VC++ 8.0 or later, and not WINCE */
+#if _MSC_VER >= 1400 && !defined(WINCE)
+#define NS_HAVE_INVALID_PARAMETER_HANDLER 1
+#endif
+#ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
+#include <stdlib.h> /* for _set_invalid_parameter_handler */
+#include <crtdbg.h> /* for _CrtSetReportMode */
+#endif
+
+#ifdef JS_THREADSAFE
+#include <prinit.h>
+#endif
+
+#endif
+
+#if defined(XP_UNIX) || defined(XP_BEOS)
+
+#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */
+extern int gettimeofday(struct timeval *tv);
+#endif
+
+#include <sys/time.h>
+
+#endif /* XP_UNIX */
+
+#define PRMJ_YEAR_DAYS 365L
+#define PRMJ_FOUR_YEARS_DAYS (4 * PRMJ_YEAR_DAYS + 1)
+#define PRMJ_CENTURY_DAYS (25 * PRMJ_FOUR_YEARS_DAYS - 1)
+#define PRMJ_FOUR_CENTURIES_DAYS (4 * PRMJ_CENTURY_DAYS + 1)
+#define PRMJ_HOUR_SECONDS 3600L
+#define PRMJ_DAY_SECONDS (24L * PRMJ_HOUR_SECONDS)
+#define PRMJ_YEAR_SECONDS (PRMJ_DAY_SECONDS * PRMJ_YEAR_DAYS)
+#define PRMJ_MAX_UNIX_TIMET 2145859200L /*time_t value equiv. to 12/31/2037 */
+
+/* function prototypes */
+static void PRMJ_basetime(JSInt64 tsecs, PRMJTime *prtm);
+/*
+ * get the difference in seconds between this time zone and UTC (GMT)
+ */
+JSInt32
+PRMJ_LocalGMTDifference()
+{
+ struct tm ltime;
+
+ /* get the difference between this time zone and GMT */
+ memset((char *)&ltime,0,sizeof(ltime));
+ ltime.tm_mday = 2;
+ ltime.tm_year = 70;
+ return (JSInt32)mktime(&ltime) - (24L * 3600L);
+}
+
+/* Constants for GMT offset from 1970 */
+#define G1970GMTMICROHI 0x00dcdcad /* micro secs to 1970 hi */
+#define G1970GMTMICROLOW 0x8b3fa000 /* micro secs to 1970 low */
+
+#define G2037GMTMICROHI 0x00e45fab /* micro secs to 2037 high */
+#define G2037GMTMICROLOW 0x7a238000 /* micro secs to 2037 low */
+
+/* Convert from base time to extended time */
+static JSInt64
+PRMJ_ToExtendedTime(JSInt32 base_time)
+{
+ JSInt64 exttime;
+ JSInt64 g1970GMTMicroSeconds;
+ JSInt64 low;
+ JSInt32 diff;
+ JSInt64 tmp;
+ JSInt64 tmp1;
+
+ diff = PRMJ_LocalGMTDifference();
+ JSLL_UI2L(tmp, PRMJ_USEC_PER_SEC);
+ JSLL_I2L(tmp1,diff);
+ JSLL_MUL(tmp,tmp,tmp1);
+
+ JSLL_UI2L(g1970GMTMicroSeconds,G1970GMTMICROHI);
+ JSLL_UI2L(low,G1970GMTMICROLOW);
+#ifndef JS_HAVE_LONG_LONG
+ JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16);
+ JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16);
+#else
+ JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,32);
+#endif
+ JSLL_ADD(g1970GMTMicroSeconds,g1970GMTMicroSeconds,low);
+
+ JSLL_I2L(exttime,base_time);
+ JSLL_ADD(exttime,exttime,g1970GMTMicroSeconds);
+ JSLL_SUB(exttime,exttime,tmp);
+ return exttime;
+}
+
+#ifdef XP_WIN
+typedef struct CalibrationData
+{
+ long double freq; /* The performance counter frequency */
+ long double offset; /* The low res 'epoch' */
+ long double timer_offset; /* The high res 'epoch' */
+
+ /* The last high res time that we returned since recalibrating */
+ JSInt64 last;
+
+ JSBool calibrated;
+
+#ifdef JS_THREADSAFE
+ CRITICAL_SECTION data_lock;
+ CRITICAL_SECTION calibration_lock;
+#endif
+} CalibrationData;
+
+static const JSInt64 win2un = JSLL_INIT(0x19DB1DE, 0xD53E8000);
+
+static CalibrationData calibration = { 0 };
+
+#define FILETIME2INT64(ft) (((JSInt64)ft.dwHighDateTime) << 32LL | (JSInt64)ft.dwLowDateTime)
+
+static void
+NowCalibrate()
+{
+ FILETIME ft, ftStart;
+ LARGE_INTEGER liFreq, now;
+
+ if (calibration.freq == 0.0) {
+ if(!QueryPerformanceFrequency(&liFreq)) {
+ /* High-performance timer is unavailable */
+ calibration.freq = -1.0;
+ } else {
+ calibration.freq = (long double) liFreq.QuadPart;
+ }
+ }
+ if (calibration.freq > 0.0) {
+ JSInt64 calibrationDelta = 0;
+
+ /* By wrapping a timeBegin/EndPeriod pair of calls around this loop,
+ the loop seems to take much less time (1 ms vs 15ms) on Vista. */
+ timeBeginPeriod(1);
+ GetSystemTimeAsFileTime(&ftStart);
+ do {
+ GetSystemTimeAsFileTime(&ft);
+ } while (memcmp(&ftStart,&ft, sizeof(ft)) == 0);
+ timeEndPeriod(1);
+
+ /*
+ calibrationDelta = (FILETIME2INT64(ft) - FILETIME2INT64(ftStart))/10;
+ fprintf(stderr, "Calibration delta was %I64d us\n", calibrationDelta);
+ */
+
+ QueryPerformanceCounter(&now);
+
+ calibration.offset = (long double) FILETIME2INT64(ft);
+ calibration.timer_offset = (long double) now.QuadPart;
+
+ /* The windows epoch is around 1600. The unix epoch is around
+ 1970. win2un is the difference (in windows time units which
+ are 10 times more highres than the JS time unit) */
+ calibration.offset -= win2un;
+ calibration.offset *= 0.1;
+ calibration.last = 0;
+
+ calibration.calibrated = JS_TRUE;
+ }
+}
+
+#define CALIBRATIONLOCK_SPINCOUNT 0
+#define DATALOCK_SPINCOUNT 4096
+#define LASTLOCK_SPINCOUNT 4096
+
+#ifdef JS_THREADSAFE
+static PRStatus
+NowInit(void)
+{
+ memset(&calibration, 0, sizeof(calibration));
+ NowCalibrate();
+ InitializeCriticalSectionAndSpinCount(&calibration.calibration_lock, CALIBRATIONLOCK_SPINCOUNT);
+ InitializeCriticalSectionAndSpinCount(&calibration.data_lock, DATALOCK_SPINCOUNT);
+ return PR_SUCCESS;
+}
+
+void
+PRMJ_NowShutdown()
+{
+ DeleteCriticalSection(&calibration.calibration_lock);
+ DeleteCriticalSection(&calibration.data_lock);
+}
+
+#define MUTEX_LOCK(m) EnterCriticalSection(m)
+#define MUTEX_TRYLOCK(m) TryEnterCriticalSection(m)
+#define MUTEX_UNLOCK(m) LeaveCriticalSection(m)
+#define MUTEX_SETSPINCOUNT(m, c) SetCriticalSectionSpinCount((m),(c))
+
+static PRCallOnceType calibrationOnce = { 0 };
+
+#else
+
+#define MUTEX_LOCK(m)
+#define MUTEX_TRYLOCK(m) 1
+#define MUTEX_UNLOCK(m)
+#define MUTEX_SETSPINCOUNT(m, c)
+
+#endif
+
+
+#endif /* XP_WIN */
+
+/*
+
+Win32 python-esque pseudo code
+Please see bug 363258 for why the win32 timing code is so complex.
+
+calibration mutex : Win32CriticalSection(spincount=0)
+data mutex : Win32CriticalSection(spincount=4096)
+
+def NowInit():
+ init mutexes
+ PRMJ_NowCalibration()
+
+def NowCalibration():
+ expensive up-to-15ms call
+
+def PRMJ_Now():
+ returnedTime = 0
+ needCalibration = False
+ cachedOffset = 0.0
+ calibrated = False
+ PR_CallOnce(PRMJ_NowInit)
+ do
+ if not global.calibrated or needCalibration:
+ acquire calibration mutex
+ acquire data mutex
+
+ // Only recalibrate if someone didn't already
+ if cachedOffset == calibration.offset:
+ // Have all waiting threads immediately wait
+ set data mutex spin count = 0
+ PRMJ_NowCalibrate()
+ calibrated = 1
+
+ set data mutex spin count = default
+ release data mutex
+ release calibration mutex
+
+ calculate lowres time
+
+ if highres timer available:
+ acquire data mutex
+ calculate highres time
+ cachedOffset = calibration.offset
+ highres time = calibration.last = max(highres time, calibration.last)
+ release data mutex
+
+ get kernel tick interval
+
+ if abs(highres - lowres) < kernel tick:
+ returnedTime = highres time
+ needCalibration = False
+ else:
+ if calibrated:
+ returnedTime = lowres
+ needCalibration = False
+ else:
+ needCalibration = True
+ else:
+ returnedTime = lowres
+ while needCalibration
+
+*/
+
+JSInt64
+PRMJ_Now(void)
+{
+#ifdef XP_OS2
+ JSInt64 s, us, ms2us, s2us;
+ struct timeb b;
+#endif
+#ifdef XP_WIN
+ static int nCalls = 0;
+ long double lowresTime, highresTimerValue;
+ FILETIME ft;
+ LARGE_INTEGER now;
+ JSBool calibrated = JS_FALSE;
+ JSBool needsCalibration = JS_FALSE;
+ JSInt64 returnedTime;
+ long double cachedOffset = 0.0;
+#endif
+#if defined(XP_UNIX) || defined(XP_BEOS)
+ struct timeval tv;
+ JSInt64 s, us, s2us;
+#endif /* XP_UNIX */
+
+#ifdef XP_OS2
+ ftime(&b);
+ JSLL_UI2L(ms2us, PRMJ_USEC_PER_MSEC);
+ JSLL_UI2L(s2us, PRMJ_USEC_PER_SEC);
+ JSLL_UI2L(s, b.time);
+ JSLL_UI2L(us, b.millitm);
+ JSLL_MUL(us, us, ms2us);
+ JSLL_MUL(s, s, s2us);
+ JSLL_ADD(s, s, us);
+ return s;
+#endif
+#ifdef XP_WIN
+
+ /* To avoid regressing startup time (where high resolution is likely
+ not needed), give the old behavior for the first few calls.
+ This does not appear to be needed on Vista as the timeBegin/timeEndPeriod
+ calls seem to immediately take effect. */
+ int thiscall = JS_ATOMIC_INCREMENT(&nCalls);
+ /* 10 seems to be the number of calls to load with a blank homepage */
+ if (thiscall <= 10) {
+ GetSystemTimeAsFileTime(&ft);
+ return (FILETIME2INT64(ft)-win2un)/10L;
+ }
+
+ /* For non threadsafe platforms, NowInit is not necessary */
+#ifdef JS_THREADSAFE
+ PR_CallOnce(&calibrationOnce, NowInit);
+#endif
+ do {
+ if (!calibration.calibrated || needsCalibration) {
+ MUTEX_LOCK(&calibration.calibration_lock);
+ MUTEX_LOCK(&calibration.data_lock);
+
+ /* Recalibrate only if no one else did before us */
+ if(calibration.offset == cachedOffset) {
+ /* Since calibration can take a while, make any other
+ threads immediately wait */
+ MUTEX_SETSPINCOUNT(&calibration.data_lock, 0);
+
+ NowCalibrate();
+
+ calibrated = JS_TRUE;
+
+ /* Restore spin count */
+ MUTEX_SETSPINCOUNT(&calibration.data_lock, DATALOCK_SPINCOUNT);
+ }
+ MUTEX_UNLOCK(&calibration.data_lock);
+ MUTEX_UNLOCK(&calibration.calibration_lock);
+ }
+
+
+ /* Calculate a low resolution time */
+ GetSystemTimeAsFileTime(&ft);
+ lowresTime = 0.1*(long double)(FILETIME2INT64(ft) - win2un);
+
+ if (calibration.freq > 0.0) {
+ long double highresTime, diff;
+
+ DWORD timeAdjustment, timeIncrement;
+ BOOL timeAdjustmentDisabled;
+
+ /* Default to 15.625 ms if the syscall fails */
+ long double skewThreshold = 15625.25;
+ /* Grab high resolution time */
+ QueryPerformanceCounter(&now);
+ highresTimerValue = (long double)now.QuadPart;
+
+ MUTEX_LOCK(&calibration.data_lock);
+ highresTime = calibration.offset + PRMJ_USEC_PER_SEC*
+ (highresTimerValue-calibration.timer_offset)/calibration.freq;
+ cachedOffset = calibration.offset;
+
+ /* On some dual processor/core systems, we might get an earlier time
+ so we cache the last time that we returned */
+ calibration.last = max(calibration.last,(JSInt64)highresTime);
+ returnedTime = calibration.last;
+ MUTEX_UNLOCK(&calibration.data_lock);
+
+ /* Rather than assume the NT kernel ticks every 15.6ms, ask it */
+ if (GetSystemTimeAdjustment(&timeAdjustment,
+ &timeIncrement,
+ &timeAdjustmentDisabled)) {
+ if (timeAdjustmentDisabled) {
+ /* timeAdjustment is in units of 100ns */
+ skewThreshold = timeAdjustment/10.0;
+ } else {
+ /* timeIncrement is in units of 100ns */
+ skewThreshold = timeIncrement/10.0;
+ }
+ }
+
+ /* Check for clock skew */
+ diff = lowresTime - highresTime;
+
+ /* For some reason that I have not determined, the skew can be
+ up to twice a kernel tick. This does not seem to happen by
+ itself, but I have only seen it triggered by another program
+ doing some kind of file I/O. The symptoms are a negative diff
+ followed by an equally large positive diff. */
+ if (fabs(diff) > 2*skewThreshold) {
+ /*fprintf(stderr,"Clock skew detected (diff = %f)!\n", diff);*/
+
+ if (calibrated) {
+ /* If we already calibrated once this instance, and the
+ clock is still skewed, then either the processor(s) are
+ wildly changing clockspeed or the system is so busy that
+ we get switched out for long periods of time. In either
+ case, it would be infeasible to make use of high
+ resolution results for anything, so let's resort to old
+ behavior for this call. It's possible that in the
+ future, the user will want the high resolution timer, so
+ we don't disable it entirely. */
+ returnedTime = (JSInt64)lowresTime;
+ needsCalibration = JS_FALSE;
+ } else {
+ /* It is possible that when we recalibrate, we will return a
+ value less than what we have returned before; this is
+ unavoidable. We cannot tell the different between a
+ faulty QueryPerformanceCounter implementation and user
+ changes to the operating system time. Since we must
+ respect user changes to the operating system time, we
+ cannot maintain the invariant that Date.now() never
+ decreases; the old implementation has this behavior as
+ well. */
+ needsCalibration = JS_TRUE;
+ }
+ } else {
+ /* No detectable clock skew */
+ returnedTime = (JSInt64)highresTime;
+ needsCalibration = JS_FALSE;
+ }
+ } else {
+ /* No high resolution timer is available, so fall back */
+ returnedTime = (JSInt64)lowresTime;
+ }
+ } while (needsCalibration);
+
+ return returnedTime;
+#endif
+
+#if defined(XP_UNIX) || defined(XP_BEOS)
+#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */
+ gettimeofday(&tv);
+#else
+ gettimeofday(&tv, 0);
+#endif /* _SVID_GETTOD */
+ JSLL_UI2L(s2us, PRMJ_USEC_PER_SEC);
+ JSLL_UI2L(s, tv.tv_sec);
+ JSLL_UI2L(us, tv.tv_usec);
+ JSLL_MUL(s, s, s2us);
+ JSLL_ADD(s, s, us);
+ return s;
+#endif /* XP_UNIX */
+}
+
+/* Get the DST timezone offset for the time passed in */
+JSInt64
+PRMJ_DSTOffset(JSInt64 local_time)
+{
+ JSInt64 us2s;
+ time_t local;
+ JSInt32 diff;
+ JSInt64 maxtimet;
+ struct tm tm;
+ PRMJTime prtm;
+#ifndef HAVE_LOCALTIME_R
+ struct tm *ptm;
+#endif
+
+
+ JSLL_UI2L(us2s, PRMJ_USEC_PER_SEC);
+ JSLL_DIV(local_time, local_time, us2s);
+
+ /* get the maximum of time_t value */
+ JSLL_UI2L(maxtimet,PRMJ_MAX_UNIX_TIMET);
+
+ if(JSLL_CMP(local_time,>,maxtimet)){
+ JSLL_UI2L(local_time,PRMJ_MAX_UNIX_TIMET);
+ } else if(!JSLL_GE_ZERO(local_time)){
+ /*go ahead a day to make localtime work (does not work with 0) */
+ JSLL_UI2L(local_time,PRMJ_DAY_SECONDS);
+ }
+ JSLL_L2UI(local,local_time);
+ PRMJ_basetime(local_time,&prtm);
+#ifndef HAVE_LOCALTIME_R
+ ptm = localtime(&local);
+ if(!ptm){
+ return 0;
+ }
+ tm = *ptm;
+#else
+ localtime_r(&local,&tm); /* get dst information */
+#endif
+
+ diff = ((tm.tm_hour - prtm.tm_hour) * PRMJ_HOUR_SECONDS) +
+ ((tm.tm_min - prtm.tm_min) * 60);
+
+ if(diff < 0){
+ diff += PRMJ_DAY_SECONDS;
+ }
+
+ JSLL_UI2L(local_time,diff);
+
+ JSLL_MUL(local_time,local_time,us2s);
+
+ return(local_time);
+}
+
+#ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
+static void
+PRMJ_InvalidParameterHandler(const wchar_t *expression,
+ const wchar_t *function,
+ const wchar_t *file,
+ unsigned int line,
+ uintptr_t pReserved)
+{
+ /* empty */
+}
+#endif
+
+/* Format a time value into a buffer. Same semantics as strftime() */
+size_t
+PRMJ_FormatTime(char *buf, int buflen, const char *fmt, PRMJTime *prtm)
+{
+ size_t result = 0;
+#if defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS)
+ struct tm a;
+ int fake_tm_year = 0;
+#ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
+ _invalid_parameter_handler oldHandler;
+ int oldReportMode;
+#endif
+
+ /* Zero out the tm struct. Linux, SunOS 4 struct tm has extra members int
+ * tm_gmtoff, char *tm_zone; when tm_zone is garbage, strftime gets
+ * confused and dumps core. NSPR20 prtime.c attempts to fill these in by
+ * calling mktime on the partially filled struct, but this doesn't seem to
+ * work as well; the result string has "can't get timezone" for ECMA-valid
+ * years. Might still make sense to use this, but find the range of years
+ * for which valid tz information exists, and map (per ECMA hint) from the
+ * given year into that range.
+
+ * N.B. This hasn't been tested with anything that actually _uses_
+ * tm_gmtoff; zero might be the wrong thing to set it to if you really need
+ * to format a time. This fix is for jsdate.c, which only uses
+ * JS_FormatTime to get a string representing the time zone. */
+ memset(&a, 0, sizeof(struct tm));
+
+ a.tm_sec = prtm->tm_sec;
+ a.tm_min = prtm->tm_min;
+ a.tm_hour = prtm->tm_hour;
+ a.tm_mday = prtm->tm_mday;
+ a.tm_mon = prtm->tm_mon;
+ a.tm_wday = prtm->tm_wday;
+
+ /*
+ * Years before 1900 and after 9999 cause strftime() to abort on Windows.
+ * To avoid that we replace it with FAKE_YEAR_BASE + year % 100 and then
+ * replace matching substrings in the strftime() result with the real year.
+ * Note that FAKE_YEAR_BASE should be a multiple of 100 to make 2-digit
+ * year formats (%y) work correctly (since we won't find the fake year
+ * in that case).
+ * e.g. new Date(1873, 0).toLocaleFormat('%Y %y') => "1873 73"
+ * See bug 327869.
+ */
+#define FAKE_YEAR_BASE 9900
+ if (prtm->tm_year < 1900 || prtm->tm_year > 9999) {
+ fake_tm_year = FAKE_YEAR_BASE + prtm->tm_year % 100;
+ a.tm_year = fake_tm_year - 1900;
+ }
+ else {
+ a.tm_year = prtm->tm_year - 1900;
+ }
+ a.tm_yday = prtm->tm_yday;
+ a.tm_isdst = prtm->tm_isdst;
+
+ /*
+ * Even with the above, SunOS 4 seems to detonate if tm_zone and tm_gmtoff
+ * are null. This doesn't quite work, though - the timezone is off by
+ * tzoff + dst. (And mktime seems to return -1 for the exact dst
+ * changeover time.)
+ */
+
+#ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
+ oldHandler = _set_invalid_parameter_handler(PRMJ_InvalidParameterHandler);
+ oldReportMode = _CrtSetReportMode(_CRT_ASSERT, 0);
+#endif
+
+ result = strftime(buf, buflen, fmt, &a);
+
+#ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
+ _set_invalid_parameter_handler(oldHandler);
+ _CrtSetReportMode(_CRT_ASSERT, oldReportMode);
+#endif
+
+ if (fake_tm_year && result) {
+ char real_year[16];
+ char fake_year[16];
+ size_t real_year_len;
+ size_t fake_year_len;
+ char* p;
+
+ sprintf(real_year, "%d", prtm->tm_year);
+ real_year_len = strlen(real_year);
+ sprintf(fake_year, "%d", fake_tm_year);
+ fake_year_len = strlen(fake_year);
+
+ /* Replace the fake year in the result with the real year. */
+ for (p = buf; (p = strstr(p, fake_year)); p += real_year_len) {
+ size_t new_result = result + real_year_len - fake_year_len;
+ if ((int)new_result >= buflen) {
+ return 0;
+ }
+ memmove(p + real_year_len, p + fake_year_len, strlen(p + fake_year_len));
+ memcpy(p, real_year, real_year_len);
+ result = new_result;
+ *(buf + result) = '\0';
+ }
+ }
+#endif
+ return result;
+}
+
+/* table for number of days in a month */
+static int mtab[] = {
+ /* jan, feb,mar,apr,may,jun */
+ 31,28,31,30,31,30,
+ /* july,aug,sep,oct,nov,dec */
+ 31,31,30,31,30,31
+};
+
+/*
+ * basic time calculation functionality for localtime and gmtime
+ * setups up prtm argument with correct values based upon input number
+ * of seconds.
+ */
+static void
+PRMJ_basetime(JSInt64 tsecs, PRMJTime *prtm)
+{
+ /* convert tsecs back to year,month,day,hour,secs */
+ JSInt32 year = 0;
+ JSInt32 month = 0;
+ JSInt32 yday = 0;
+ JSInt32 mday = 0;
+ JSInt32 wday = 6; /* start on a Sunday */
+ JSInt32 days = 0;
+ JSInt32 seconds = 0;
+ JSInt32 minutes = 0;
+ JSInt32 hours = 0;
+ JSInt32 isleap = 0;
+
+ /* Temporaries used for various computations */
+ JSInt64 result;
+ JSInt64 result1;
+ JSInt64 result2;
+
+ JSInt64 base;
+
+ /* Some variables for intermediate result storage to make computing isleap
+ easier/faster */
+ JSInt32 fourCenturyBlocks;
+ JSInt32 centuriesLeft;
+ JSInt32 fourYearBlocksLeft;
+ JSInt32 yearsLeft;
+
+ /* Since leap years work by 400/100/4 year intervals, precompute the length
+ of those in seconds if they start at the beginning of year 1. */
+ JSInt64 fourYears;
+ JSInt64 century;
+ JSInt64 fourCenturies;
+
+ JSLL_UI2L(result, PRMJ_DAY_SECONDS);
+
+ JSLL_I2L(fourYears, PRMJ_FOUR_YEARS_DAYS);
+ JSLL_MUL(fourYears, fourYears, result);
+
+ JSLL_I2L(century, PRMJ_CENTURY_DAYS);
+ JSLL_MUL(century, century, result);
+
+ JSLL_I2L(fourCenturies, PRMJ_FOUR_CENTURIES_DAYS);
+ JSLL_MUL(fourCenturies, fourCenturies, result);
+
+ /* get the base time via UTC */
+ base = PRMJ_ToExtendedTime(0);
+ JSLL_UI2L(result, PRMJ_USEC_PER_SEC);
+ JSLL_DIV(base,base,result);
+ JSLL_ADD(tsecs,tsecs,base);
+
+ /* Compute our |year|, |isleap|, and part of |days|. When this part is
+ done, |year| should hold the year our date falls in (number of whole
+ years elapsed before our date), isleap should hold 1 if the year the
+ date falls in is a leap year and 0 otherwise. */
+
+ /* First do year 0; it's special and nonleap. */
+ JSLL_UI2L(result, PRMJ_YEAR_SECONDS);
+ if (!JSLL_CMP(tsecs,<,result)) {
+ days = PRMJ_YEAR_DAYS;
+ year = 1;
+ JSLL_SUB(tsecs, tsecs, result);
+ }
+
+ /* Now use those constants we computed above */
+ JSLL_UDIVMOD(&result1, &result2, tsecs, fourCenturies);
+ JSLL_L2I(fourCenturyBlocks, result1);
+ year += fourCenturyBlocks * 400;
+ days += fourCenturyBlocks * PRMJ_FOUR_CENTURIES_DAYS;
+ tsecs = result2;
+
+ JSLL_UDIVMOD(&result1, &result2, tsecs, century);
+ JSLL_L2I(centuriesLeft, result1);
+ year += centuriesLeft * 100;
+ days += centuriesLeft * PRMJ_CENTURY_DAYS;
+ tsecs = result2;
+
+ JSLL_UDIVMOD(&result1, &result2, tsecs, fourYears);
+ JSLL_L2I(fourYearBlocksLeft, result1);
+ year += fourYearBlocksLeft * 4;
+ days += fourYearBlocksLeft * PRMJ_FOUR_YEARS_DAYS;
+ tsecs = result2;
+
+ /* Recall that |result| holds PRMJ_YEAR_SECONDS */
+ JSLL_UDIVMOD(&result1, &result2, tsecs, result);
+ JSLL_L2I(yearsLeft, result1);
+ year += yearsLeft;
+ days += yearsLeft * PRMJ_YEAR_DAYS;
+ tsecs = result2;
+
+ /* now compute isleap. Note that we don't have to use %, since we've
+ already computed those remainders. Also note that they're all offset by
+ 1 because of the 1 for year 0. */
+ isleap =
+ (yearsLeft == 3) && (fourYearBlocksLeft != 24 || centuriesLeft == 3);
+ JS_ASSERT(isleap ==
+ ((year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)));
+
+ JSLL_UI2L(result1,PRMJ_DAY_SECONDS);
+
+ JSLL_DIV(result,tsecs,result1);
+ JSLL_L2I(mday,result);
+
+ /* let's find the month */
+ while(((month == 1 && isleap) ?
+ (mday >= mtab[month] + 1) :
+ (mday >= mtab[month]))){
+ yday += mtab[month];
+ days += mtab[month];
+
+ mday -= mtab[month];
+
+ /* it's a Feb, check if this is a leap year */
+ if(month == 1 && isleap != 0){
+ yday++;
+ days++;
+ mday--;
+ }
+ month++;
+ }
+
+ /* now adjust tsecs */
+ JSLL_MUL(result,result,result1);
+ JSLL_SUB(tsecs,tsecs,result);
+
+ mday++; /* day of month always start with 1 */
+ days += mday;
+ wday = (days + wday) % 7;
+
+ yday += mday;
+
+ /* get the hours */
+ JSLL_UI2L(result1,PRMJ_HOUR_SECONDS);
+ JSLL_DIV(result,tsecs,result1);
+ JSLL_L2I(hours,result);
+ JSLL_MUL(result,result,result1);
+ JSLL_SUB(tsecs,tsecs,result);
+
+ /* get minutes */
+ JSLL_UI2L(result1,60);
+ JSLL_DIV(result,tsecs,result1);
+ JSLL_L2I(minutes,result);
+ JSLL_MUL(result,result,result1);
+ JSLL_SUB(tsecs,tsecs,result);
+
+ JSLL_L2I(seconds,tsecs);
+
+ prtm->tm_usec = 0L;
+ prtm->tm_sec = (JSInt8)seconds;
+ prtm->tm_min = (JSInt8)minutes;
+ prtm->tm_hour = (JSInt8)hours;
+ prtm->tm_mday = (JSInt8)mday;
+ prtm->tm_mon = (JSInt8)month;
+ prtm->tm_wday = (JSInt8)wday;
+ prtm->tm_year = (JSInt16)year;
+ prtm->tm_yday = (JSInt16)yday;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.h b/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.h
new file mode 100644
index 0000000..e553945
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef prmjtime_h___
+#define prmjtime_h___
+/*
+ * PR date stuff for mocha and java. Placed here temporarily not to break
+ * Navigator and localize changes to mocha.
+ */
+#include <time.h>
+#include "jslong.h"
+#ifdef MOZILLA_CLIENT
+#include "jscompat.h"
+#endif
+
+JS_BEGIN_EXTERN_C
+
+typedef struct PRMJTime PRMJTime;
+
+/*
+ * Broken down form of 64 bit time value.
+ */
+struct PRMJTime {
+ JSInt32 tm_usec; /* microseconds of second (0-999999) */
+ JSInt8 tm_sec; /* seconds of minute (0-59) */
+ JSInt8 tm_min; /* minutes of hour (0-59) */
+ JSInt8 tm_hour; /* hour of day (0-23) */
+ JSInt8 tm_mday; /* day of month (1-31) */
+ JSInt8 tm_mon; /* month of year (0-11) */
+ JSInt8 tm_wday; /* 0=sunday, 1=monday, ... */
+ JSInt32 tm_year; /* absolute year, AD */
+ JSInt16 tm_yday; /* day of year (0 to 365) */
+ JSInt8 tm_isdst; /* non-zero if DST in effect */
+};
+
+/* Some handy constants */
+#define PRMJ_USEC_PER_SEC 1000000L
+#define PRMJ_USEC_PER_MSEC 1000L
+
+/* Return the current local time in micro-seconds */
+extern JSInt64
+PRMJ_Now(void);
+
+/* Release the resources associated with PRMJ_Now; don't call PRMJ_Now again */
+#if defined(JS_THREADSAFE) && defined(XP_WIN)
+extern void
+PRMJ_NowShutdown(void);
+#else
+#define PRMJ_NowShutdown()
+#endif
+
+/* get the difference between this time zone and gmt timezone in seconds */
+extern JSInt32
+PRMJ_LocalGMTDifference(void);
+
+/* Format a time value into a buffer. Same semantics as strftime() */
+extern size_t
+PRMJ_FormatTime(char *buf, int buflen, const char *fmt, PRMJTime *tm);
+
+/* Get the DST offset for the local time passed in */
+extern JSInt64
+PRMJ_DSTOffset(JSInt64 local_time);
+
+JS_END_EXTERN_C
+
+#endif /* prmjtime_h___ */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.1.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.1.mk
new file mode 100644
index 0000000..09c7cb9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.1.mk
@@ -0,0 +1,65 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for AIX
+#
+
+CC = xlC_r
+CCC = xlC_r
+
+RANLIB = ranlib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+ARCH := aix
+CPU_ARCH = rs6000
+GFX_ARCH = x
+INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1
+
+OS_CFLAGS = -qarch=com -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DHAVE_LOCALTIME_R
+OS_LIBS = -lbsd -lsvld -lm
+#-lpthreads -lc_r
+
+MKSHLIB = $(LD) -bM:SRE -bh:4 -bnoentry -berok
+XLDFLAGS += -lc
+
+ifdef JS_THREADSAFE
+XLDFLAGS += -lsvld
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.2.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.2.mk
new file mode 100644
index 0000000..1e3f1f1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.2.mk
@@ -0,0 +1,64 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for AIX
+#
+
+CC = xlC_r
+CCC = xlC_r
+CFLAGS += -qarch=com -qnoansialias -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DHAVE_LOCALTIME_R
+
+RANLIB = ranlib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+ARCH := aix
+CPU_ARCH = rs6000
+GFX_ARCH = x
+INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1
+
+#-lpthreads -lc_r
+
+MKSHLIB = /usr/lpp/xlC/bin/makeC++SharedLib_r -p 0 -G -berok
+
+ifdef JS_THREADSAFE
+XLDFLAGS += -ldl
+endif
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.3.mk
new file mode 100644
index 0000000..df05d8c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.3.mk
@@ -0,0 +1,65 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for AIX
+#
+
+CC = xlC_r
+CCC = xlC_r
+CFLAGS += -qarch=com -qnoansialias -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DAIX4_3 -DHAVE_LOCALTIME_R
+
+RANLIB = ranlib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+ARCH := aix
+CPU_ARCH = rs6000
+GFX_ARCH = x
+INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1
+
+#-lpthreads -lc_r
+
+MKSHLIB_BIN = /usr/ibmcxx/bin/makeC++SharedLib_r
+MKSHLIB = $(MKSHLIB_BIN) -p 0 -G -berok -bM:UR
+
+ifdef JS_THREADSAFE
+XLDFLAGS += -ldl
+endif
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Cygwin.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Cygwin.mk
new file mode 100644
index 0000000..6319682
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Cygwin.mk
@@ -0,0 +1,14 @@
+CC = gcc
+CXX = g++
+LD = g++
+OS_CFLAGS_NO_ANSI = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R
+OS_CFLAGS = -ansi $(OS_CFLAGS_NO_ANSI)
+PROGRAM_CFLAGS = $(OPTIMIZER) $(OS_CFLAGS_NO_ANSI) $(DEFINES) $(INCLUDES) $(XCFLAGS)
+RANLIB = ranlib
+MKSHLIB = $(LD) -shared $(XMKSHLIBOPTS)
+
+all:
+
+obj/js.o: js.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ -c $(PROGRAM_CFLAGS) js.cpp
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin.mk
new file mode 100644
index 0000000..86c4b9d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin.mk
@@ -0,0 +1,85 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = gcc
+CCC = g++
+CFLAGS += -Wall -Wno-format -MMD
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN
+
+RANLIB = ranlib
+MKSHLIB = $(CCC) -dynamiclib $(XMKSHLIBOPTS) -framework System
+
+SO_SUFFIX = dylib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS+= -DX86_LINUX
+OS_CFLAGS += -DAVMPLUS_IA32 -DAVMPLUS_UNIX
+NANOJIT_ARCH = i386
+endif
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.3.mk
new file mode 100644
index 0000000..05d3767
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.3.mk
@@ -0,0 +1,81 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = cc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DRHAPSODY
+
+RANLIB = ranlib
+MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS+= -DX86_LINUX
+endif
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.4.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.4.mk
new file mode 100644
index 0000000..f7b6af8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.4.mk
@@ -0,0 +1,41 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mike McCabe <mike+mozilla@meer.net>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+include $(DEPTH)/config/Darwin1.3.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.2.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.2.mk
new file mode 100644
index 0000000..9b9b6ff
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.2.mk
@@ -0,0 +1,81 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = cc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN
+
+RANLIB = ranlib
+MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS+= -DX86_LINUX
+endif
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.3.mk
new file mode 100644
index 0000000..9b9b6ff
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.3.mk
@@ -0,0 +1,81 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = cc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN
+
+RANLIB = ranlib
+MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS+= -DX86_LINUX
+endif
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin64.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin64.mk
new file mode 100644
index 0000000..db195b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin64.mk
@@ -0,0 +1,72 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = cc
+CCC = g++
+CFLAGS += -Wall -Wno-format -MMD
+OS_LDFLAGS += -m64
+OS_CFLAGS = -m64 -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN
+
+RANLIB = ranlib
+MKSHLIB = $(CCC) -dynamiclib $(XMKSHLIBOPTS) -framework System
+
+SO_SUFFIX = dylib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86_64
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.10.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.10.mk
new file mode 100644
index 0000000..8cd9d20
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.10.mk
@@ -0,0 +1,77 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for HPUX
+#
+
+# CC = gcc
+# CCC = g++
+# CFLAGS += -Wall -Wno-format -fPIC
+
+CC = cc -Ae +Z
+CCC = CC -Ae +a1 +eh +Z
+
+RANLIB = echo
+MKSHLIB = $(LD) -b
+
+SO_SUFFIX = sl
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = hppa
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -DHAVE_LOCALTIME_R
+OS_LIBS = -ldld
+
+ifeq ($(OS_RELEASE),B.10)
+PLATFORM_FLAGS += -DHPUX10 -Dhpux10
+PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H
+ifeq ($(OS_VERSION),.10)
+PLATFORM_FLAGS += -DHPUX10_10
+endif
+ifeq ($(OS_VERSION),.20)
+PLATFORM_FLAGS += -DHPUX10_20
+endif
+ifeq ($(OS_VERSION),.30)
+PLATFORM_FLAGS += -DHPUX10_30
+endif
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.20.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.20.mk
new file mode 100644
index 0000000..8cd9d20
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.20.mk
@@ -0,0 +1,77 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for HPUX
+#
+
+# CC = gcc
+# CCC = g++
+# CFLAGS += -Wall -Wno-format -fPIC
+
+CC = cc -Ae +Z
+CCC = CC -Ae +a1 +eh +Z
+
+RANLIB = echo
+MKSHLIB = $(LD) -b
+
+SO_SUFFIX = sl
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = hppa
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -DHAVE_LOCALTIME_R
+OS_LIBS = -ldld
+
+ifeq ($(OS_RELEASE),B.10)
+PLATFORM_FLAGS += -DHPUX10 -Dhpux10
+PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H
+ifeq ($(OS_VERSION),.10)
+PLATFORM_FLAGS += -DHPUX10_10
+endif
+ifeq ($(OS_VERSION),.20)
+PLATFORM_FLAGS += -DHPUX10_20
+endif
+ifeq ($(OS_VERSION),.30)
+PLATFORM_FLAGS += -DHPUX10_30
+endif
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.11.00.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.11.00.mk
new file mode 100644
index 0000000..239188d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.11.00.mk
@@ -0,0 +1,80 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for HPUX
+#
+
+ifdef NS_USE_NATIVE
+ CC = cc +Z +DAportable +DS2.0 +u4
+# LD = aCC +Z -b -Wl,+s -Wl,-B,symbolic
+else
+ CC = gcc -Wall -Wno-format -fPIC
+ CCC = g++ -Wall -Wno-format -fPIC
+endif
+
+RANLIB = echo
+MKSHLIB = $(LD) -b
+
+SO_SUFFIX = sl
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = hppa
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -D_HPUX -DNATIVE -D_POSIX_C_SOURCE=199506L -DHAVE_LOCALTIME_R
+OS_LIBS = -ldld
+
+XLDFLAGS = -lpthread
+
+ifeq ($(OS_RELEASE),B.10)
+PLATFORM_FLAGS += -DHPUX10 -Dhpux10
+PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H
+ifeq ($(OS_VERSION),.10)
+PLATFORM_FLAGS += -DHPUX10_10
+endif
+ifeq ($(OS_VERSION),.20)
+PLATFORM_FLAGS += -DHPUX10_20
+endif
+ifeq ($(OS_VERSION),.30)
+PLATFORM_FLAGS += -DHPUX10_30
+endif
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX.mk
new file mode 100644
index 0000000..88b162f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX.mk
@@ -0,0 +1,87 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX
+#
+
+CPU_ARCH = mips
+GFX_ARCH = x
+
+RANLIB = /bin/true
+
+#NS_USE_GCC = 1
+
+ifndef NS_USE_NATIVE
+CC = gcc
+CCC = g++
+AS = $(CC) -x assembler-with-cpp
+ODD_CFLAGS = -Wall -Wno-format
+ifdef BUILD_OPT
+OPTIMIZER = -O6
+endif
+else
+ifeq ($(OS_RELEASE),6.2)
+CC = cc -n32 -DIRIX6_2
+endif
+ifeq ($(OS_RELEASE),6.3)
+CC = cc -n32 -DIRIX6_3
+endif
+ifeq ($(OS_RELEASE),6.5)
+CC = cc -n32 -DIRIX6_5
+endif
+CCC = CC
+# LD = CC
+ODD_CFLAGS = -fullwarn -xansi
+ifdef BUILD_OPT
+OPTIMIZER += -Olimit 4000
+endif
+endif
+
+# For purify
+HAVE_PURIFY = 1
+PURE_OS_CFLAGS = $(ODD_CFLAGS) -DXP_UNIX -DSVR4 -DSW_THREADS -DIRIX -DHAVE_LOCALTIME_R
+
+OS_CFLAGS = $(PURE_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
+
+BSDECHO = echo
+MKSHLIB = $(LD) -n32 -shared
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX5.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX5.3.mk
new file mode 100644
index 0000000..f38cc94
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX5.3.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX5.3
+#
+
+include $(DEPTH)/config/IRIX.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.1.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.1.mk
new file mode 100644
index 0000000..354f1d1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.1.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX6.3
+#
+
+include $(DEPTH)/config/IRIX.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.2.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.2.mk
new file mode 100644
index 0000000..354f1d1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.2.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX6.3
+#
+
+include $(DEPTH)/config/IRIX.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.3.mk
new file mode 100644
index 0000000..354f1d1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.3.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX6.3
+#
+
+include $(DEPTH)/config/IRIX.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.5.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.5.mk
new file mode 100644
index 0000000..354f1d1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.5.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX6.3
+#
+
+include $(DEPTH)/config/IRIX.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Linux_All.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Linux_All.mk
new file mode 100644
index 0000000..6c289b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Linux_All.mk
@@ -0,0 +1,105 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for all versions of Linux
+#
+
+CC = gcc
+CCC = g++
+LD = g++
+CFLAGS += -Wall -Wno-format -MMD
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R -DLINUX
+
+RANLIB = echo
+MKSHLIB = $(LD) -shared $(XMKSHLIBOPTS)
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+# don't filter in x86-64 architecture
+ifneq (x86_64,$(CPU_ARCH))
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS += -DX86_LINUX -DAVMPLUS_IA32 -DAVMPLUS_UNIX -DAVMPLUS_LINUX
+NANOJIT_ARCH = i386
+endif # 86
+endif # !x86_64
+
+#JIT disabled until x64 port is cleaned up
+#ifeq ($(CPU_ARCH),x86_64)
+#OS_CFLAGS += -DAVMPLUS_AMD64 -DAVMPLUS_64BIT -DAVMPLUS_UNIX -DAVMPLUS_LINUX
+#NANOJIT_ARCH = i386
+#endif
+
+ifeq ($(CPU_ARCH),arm)
+OS_CFLAGS += -DAVMPLUS_ARM -DAVMPLUS_UNIX -DAVMPLUS_LINUX
+NANOJIT_ARCH = ARM
+endif
+
+GFX_ARCH = x
+
+OS_LIBS = -lm -lc
+
+ASFLAGS += -x assembler-with-cpp
+
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+ifeq ($(CPU_ARCH),x86_64)
+# Use VA_COPY() standard macro on x86-64
+# FIXME: better use it everywhere
+OS_CFLAGS += -DHAVE_VA_COPY -DVA_COPY=va_copy
+endif
+
+ifeq ($(CPU_ARCH),x86_64)
+# We need PIC code for shared libraries
+# FIXME: better patch rules.mk & fdlibm/Makefile*
+OS_CFLAGS += -DPIC -fPIC
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/MSYS.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/MSYS.mk
new file mode 100644
index 0000000..61c3ab6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/MSYS.mk
@@ -0,0 +1,7 @@
+CC = gcc
+CXX = g++
+LD = g++
+OS_CFLAGS = -DXP_WIN -DEXPORT_JS_API=1
+RANLIB = ranlib
+MKSHLIB = $(LD) -shared $(XMKSHLIBOPTS)
+OTHER_LIBS = -lwinmm
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Mac_OS10.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Mac_OS10.0.mk
new file mode 100644
index 0000000..74ba151
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Mac_OS10.0.mk
@@ -0,0 +1,82 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = cc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE
+-DRHAPSODY
+
+RANLIB = ranlib
+MKSHLIB = libtool -dynamic $(XMKSHLIBOPTS) -framework System
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS+= -DX86_LINUX
+endif
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V4.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V4.0.mk
new file mode 100644
index 0000000..337ca74
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V4.0.mk
@@ -0,0 +1,72 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for Data General DG/UX
+#
+
+#
+# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com)
+#
+
+ifndef NS_USE_NATIVE
+CC = gcc
+CCC = g++
+CFLAGS += -mieee -Wall -Wno-format
+else
+CC = cc
+CCC = cxx
+CFLAGS += -ieee -std
+# LD = cxx
+endif
+
+RANLIB = echo
+MKSHLIB = $(LD) -shared -taso -all -expect_unresolved "*"
+
+#
+# _DGUX_SOURCE is needed to turn on a lot of stuff in the headers if
+# you're not using DG's compiler. It shouldn't hurt if you are.
+#
+# _POSIX4A_DRAFT10_SOURCE is needed to pick up localtime_r, used in
+# prtime.c
+#
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DDGUX -D_DGUX_SOURCE -D_POSIX4A_DRAFT10_SOURCE -DOSF1 -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl
+
+NOSUCHFILE = /no-such-file
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V5.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V5.0.mk
new file mode 100644
index 0000000..b65738c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V5.0.mk
@@ -0,0 +1,69 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for Tru64 Unix 5.0
+#
+
+#
+# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com)
+#
+
+ifndef NS_USE_NATIVE
+CC = gcc
+CCC = g++
+CFLAGS += -mieee -Wall -Wno-format
+else
+CC = cc
+CCC = cxx
+CFLAGS += -ieee -std -pthread
+# LD = cxx
+endif
+
+RANLIB = echo
+MKSHLIB = $(LD) -shared -all -expect_unresolved "*"
+
+#
+# _POSIX4A_DRAFT10_SOURCE is needed to pick up localtime_r, used in
+# prtime.c
+#
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_POSIX4A_DRAFT10_SOURCE -DOSF1 -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl
+
+NOSUCHFILE = /no-such-file
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS4.1.4.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS4.1.4.mk
new file mode 100644
index 0000000..62f4815
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS4.1.4.mk
@@ -0,0 +1,101 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS4.1
+#
+
+CC = gcc
+CCC = g++
+RANLIB = ranlib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = sparc
+GFX_ARCH = x
+
+# A pile of -D's to build xfe on sunos
+MOZ_CFLAGS = -DSTRINGS_ALIGNED -DNO_REGEX -DNO_ISDIR -DUSE_RE_COMP \
+ -DNO_REGCOMP -DUSE_GETWD -DNO_MEMMOVE -DNO_ALLOCA \
+ -DBOGUS_MB_MAX -DNO_CONST
+
+# Purify doesn't like -MDupdate
+NOMD_OS_CFLAGS = -DXP_UNIX -Wall -Wno-format -DSW_THREADS -DSUNOS4 -DNEED_SYSCALL \
+ $(MOZ_CFLAGS)
+
+OS_CFLAGS = $(NOMD_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
+OS_LIBS = -ldl -lm
+
+MKSHLIB = $(LD) -L$(MOTIF)/lib
+
+HAVE_PURIFY = 1
+MOTIF = /home/motif/usr
+MOTIFLIB = -L$(MOTIF)/lib -lXm
+INCLUDES += -I/usr/X11R5/include -I$(MOTIF)/include
+
+NOSUCHFILE = /solaris-rm-f-sucks
+
+LOCALE_MAP = $(DEPTH)/cmd/xfe/intl/sunos.lm
+
+EN_LOCALE = en_US
+DE_LOCALE = de
+FR_LOCALE = fr
+JP_LOCALE = ja
+SJIS_LOCALE = ja_JP.SJIS
+KR_LOCALE = ko
+CN_LOCALE = zh
+TW_LOCALE = zh_TW
+I2_LOCALE = i2
+IT_LOCALE = it
+SV_LOCALE = sv
+ES_LOCALE = es
+NL_LOCALE = nl
+PT_LOCALE = pt
+
+LOC_LIB_DIR = /usr/openwin/lib/locale
+
+BSDECHO = echo
+
+#
+# These defines are for building unix plugins
+#
+BUILD_UNIX_PLUGINS = 1
+DSO_LDOPTS =
+DSO_LDFLAGS =
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.10.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.10.mk
new file mode 100644
index 0000000..dc0b0a0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.10.mk
@@ -0,0 +1,50 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.10, using vendor gcc and NSPR
+#
+
+include $(DEPTH)/config/SunOS5.5.mk
+
+INCLUDES += -I/usr/sfw/include/mozilla/nspr
+OTHER_LIBS += -L/usr/sfw/lib/mozilla -R/usr/sfw/lib/mozilla
+
+CC=gcc
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.3.mk
new file mode 100644
index 0000000..bd615de
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.3.mk
@@ -0,0 +1,91 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.3
+#
+
+CC = gcc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+
+#CC = /opt/SUNWspro/SC3.0.1/bin/cc
+RANLIB = echo
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = sparc
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl -ldl
+
+ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
+
+HAVE_PURIFY = 1
+
+NOSUCHFILE = /solaris-rm-f-sucks
+
+ifndef JS_NO_ULTRA
+ULTRA_OPTIONS := -xarch=v8plus
+ULTRA_OPTIONSD := -DULTRA_SPARC
+else
+ULTRA_OPTIONS := -xarch=v8
+ULTRA_OPTIONSD :=
+endif
+
+ifeq ($(OS_CPUARCH),sun4u)
+DEFINES += $(ULTRA_OPTIONSD)
+ifeq ($(findstring gcc,$(CC)),gcc)
+DEFINES += -Wa,$(ULTRA_OPTIONS),$(ULTRA_OPTIONSD)
+else
+ASFLAGS += $(ULTRA_OPTIONS) $(ULTRA_OPTIONSD)
+endif
+endif
+
+ifeq ($(OS_CPUARCH),sun4m)
+ifeq ($(findstring gcc,$(CC)),gcc)
+DEFINES += -Wa,-xarch=v8
+else
+ASFLAGS += -xarch=v8
+endif
+endif
+
+MKSHLIB = $(LD) -G
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.4.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.4.mk
new file mode 100644
index 0000000..de01924
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.4.mk
@@ -0,0 +1,92 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.4
+#
+
+ifdef NS_USE_NATIVE
+CC = cc
+CCC = CC
+else
+CC = gcc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+endif
+
+RANLIB = echo
+
+CPU_ARCH = sparc
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D__svr4 -DSOLARIS -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl -ldl
+
+ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
+
+HAVE_PURIFY = 1
+
+NOSUCHFILE = /solaris-rm-f-sucks
+
+ifndef JS_NO_ULTRA
+ULTRA_OPTIONS := -xarch=v8plus
+ULTRA_OPTIONSD := -DULTRA_SPARC
+else
+ULTRA_OPTIONS := -xarch=v8
+ULTRA_OPTIONSD :=
+endif
+
+ifeq ($(OS_CPUARCH),sun4u)
+DEFINES += $(ULTRA_OPTIONSD)
+ifeq ($(findstring gcc,$(CC)),gcc)
+DEFINES += -Wa,$(ULTRA_OPTIONS),$(ULTRA_OPTIONSD)
+else
+ASFLAGS += $(ULTRA_OPTIONS) $(ULTRA_OPTIONSD)
+endif
+endif
+
+ifeq ($(OS_CPUARCH),sun4m)
+ifeq ($(findstring gcc,$(CC)),gcc)
+DEFINES += -Wa,-xarch=v8
+else
+ASFLAGS += -xarch=v8
+endif
+endif
+
+MKSHLIB = $(LD) -G
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.1.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.1.mk
new file mode 100644
index 0000000..648f72f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.1.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.5.1
+#
+
+include $(DEPTH)/config/SunOS5.5.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.mk
new file mode 100644
index 0000000..e26b3a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.mk
@@ -0,0 +1,87 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.5
+#
+
+AS = /usr/ccs/bin/as
+ifndef NS_USE_NATIVE
+CC = gcc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+else
+CC = cc
+CCC = CC
+endif
+
+RANLIB = echo
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = sparc
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl -ldl
+
+ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
+
+HAVE_PURIFY = 1
+
+NOSUCHFILE = /solaris-rm-f-sucks
+
+ifeq ($(OS_CPUARCH),sun4u) # ultra sparc?
+ifeq ($(CC),gcc) # using gcc?
+ifndef JS_NO_ULTRA # do we want ultra?
+ifdef JS_THREADSAFE # only in thread-safe mode
+DEFINES += -DULTRA_SPARC
+DEFINES += -Wa,-xarch=v8plus,-DULTRA_SPARC
+else
+ASFLAGS += -xarch=v8plus -DULTRA_SPARC
+endif
+endif
+endif
+endif
+
+MKSHLIB = $(LD) -G
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.6.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.6.mk
new file mode 100644
index 0000000..efe1152
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.6.mk
@@ -0,0 +1,89 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.5
+#
+
+AS = /usr/ccs/bin/as
+ifndef NS_USE_NATIVE
+ CC = gcc
+ CCC = g++
+ CFLAGS += -Wall -Wno-format
+else
+ CC = cc
+ CCC = CC
+ CFLAGS += -mt -KPIC
+# LD = CC
+endif
+
+RANLIB = echo
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = sparc
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl -ldl
+
+ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
+
+HAVE_PURIFY = 1
+
+NOSUCHFILE = /solaris-rm-f-sucks
+
+ifeq ($(OS_CPUARCH),sun4u) # ultra sparc?
+ifeq ($(CC),gcc) # using gcc?
+ifndef JS_NO_ULTRA # do we want ultra?
+ifdef JS_THREADSAFE # only in thread-safe mode
+DEFINES += -DULTRA_SPARC
+DEFINES += -Wa,-xarch=v8plus,-DULTRA_SPARC
+else
+ASFLAGS += -xarch=v8plus -DULTRA_SPARC
+endif
+endif
+endif
+endif
+
+MKSHLIB = $(LD) -G
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.7.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.7.mk
new file mode 100644
index 0000000..2cb02f2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.7.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.7
+#
+
+include $(DEPTH)/config/SunOS5.5.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.8.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.8.mk
new file mode 100644
index 0000000..dd8a32d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.8.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.8
+#
+
+include $(DEPTH)/config/SunOS5.5.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.9.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.9.mk
new file mode 100644
index 0000000..b01ec9c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.9.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.9
+#
+
+include $(DEPTH)/config/SunOS5.5.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT4.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT4.0.mk
new file mode 100644
index 0000000..1d36f91
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT4.0.mk
@@ -0,0 +1,118 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Windows NT using MS Visual C++ (version?)
+#
+
+CC = cl
+CXX = cl
+
+RANLIB = echo
+
+PDBFILE = $(basename $(@F)).pdb
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86 # XXX fixme
+GFX_ARCH = win32
+
+# MSVC compiler options for both debug/optimize
+# -nologo - suppress copyright message
+# -W3 - Warning level 3
+# -Gm - enable minimal rebuild
+# -Z7 - put debug info into the executable, not in .pdb file
+# -Zi - put debug info into .pdb file
+# -YX - automatic precompiled headers
+# -GX - enable C++ exception support
+WIN_CFLAGS = -nologo -W3
+
+# MSVC compiler options for debug builds linked to MSVCRTD.DLL
+# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_IDG_CFLAGS = -MDd -Od -Z7
+
+# MSVC compiler options for debug builds linked to MSVCRT.DLL
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE)
+
+# MSVC compiler options for release (optimized) builds
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime)
+# -O2 - Optimize for speed
+# -G5 - Optimize for Pentium
+WIN_OPT_CFLAGS = -MD -O2
+
+ifdef BUILD_OPT
+OPTIMIZER = $(WIN_OPT_CFLAGS)
+else
+ifdef BUILD_IDG
+OPTIMIZER = $(WIN_IDG_CFLAGS)
+else
+OPTIMIZER = $(WIN_DEBUG_CFLAGS)
+endif
+endif
+
+OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 $(WIN_CFLAGS)
+JSDLL_CFLAGS = -DEXPORT_JS_API
+OS_LIBS = -lm -lc
+
+PREBUILT_CPUCFG = 1
+USE_MSVC = 1
+
+LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib \
+ winmm.lib \
+ -nologo\
+ -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\
+ -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+# CAFEDIR = t:/cafe
+# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip
+# JAVAC = $(CAFEDIR)/Bin/sj.exe
+# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe
+# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.0.mk
new file mode 100644
index 0000000..7681e01
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.0.mk
@@ -0,0 +1,118 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Windows NT using MS Visual C++ (version?)
+#
+
+CC = cl
+CXX = cl
+
+RANLIB = echo
+
+PDBFILE = $(basename $(@F)).pdb
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86 # XXX fixme
+GFX_ARCH = win32
+
+# MSVC compiler options for both debug/optimize
+# -nologo - suppress copyright message
+# -W3 - Warning level 3
+# -Gm - enable minimal rebuild
+# -Z7 - put debug info into the executable, not in .pdb file
+# -Zi - put debug info into .pdb file
+# -YX - automatic precompiled headers
+# -GX - enable C++ exception support
+WIN_CFLAGS = -nologo -W3
+
+# MSVC compiler options for debug builds linked to MSVCRTD.DLL
+# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_IDG_CFLAGS = -MDd -Od -Z7
+
+# MSVC compiler options for debug builds linked to MSVCRT.DLL
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE)
+
+# MSVC compiler options for release (optimized) builds
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime)
+# -O2 - Optimize for speed
+# -G5 - Optimize for Pentium
+WIN_OPT_CFLAGS = -MD -O2
+
+ifdef BUILD_OPT
+OPTIMIZER = $(WIN_OPT_CFLAGS)
+else
+ifdef BUILD_IDG
+OPTIMIZER = $(WIN_IDG_CFLAGS)
+else
+OPTIMIZER = $(WIN_DEBUG_CFLAGS)
+endif
+endif
+
+OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 -DWINVER=0x500 -D_WIN32_WINNT=0x500 $(WIN_CFLAGS)
+JSDLL_CFLAGS = -DEXPORT_JS_API
+OS_LIBS = -lm -lc
+
+PREBUILT_CPUCFG = 1
+USE_MSVC = 1
+
+LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib \
+ winmm.lib \
+ -nologo\
+ -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\
+ -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+# CAFEDIR = t:/cafe
+# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip
+# JAVAC = $(CAFEDIR)/Bin/sj.exe
+# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe
+# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.1.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.1.mk
new file mode 100644
index 0000000..7681e01
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.1.mk
@@ -0,0 +1,118 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Windows NT using MS Visual C++ (version?)
+#
+
+CC = cl
+CXX = cl
+
+RANLIB = echo
+
+PDBFILE = $(basename $(@F)).pdb
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86 # XXX fixme
+GFX_ARCH = win32
+
+# MSVC compiler options for both debug/optimize
+# -nologo - suppress copyright message
+# -W3 - Warning level 3
+# -Gm - enable minimal rebuild
+# -Z7 - put debug info into the executable, not in .pdb file
+# -Zi - put debug info into .pdb file
+# -YX - automatic precompiled headers
+# -GX - enable C++ exception support
+WIN_CFLAGS = -nologo -W3
+
+# MSVC compiler options for debug builds linked to MSVCRTD.DLL
+# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_IDG_CFLAGS = -MDd -Od -Z7
+
+# MSVC compiler options for debug builds linked to MSVCRT.DLL
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE)
+
+# MSVC compiler options for release (optimized) builds
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime)
+# -O2 - Optimize for speed
+# -G5 - Optimize for Pentium
+WIN_OPT_CFLAGS = -MD -O2
+
+ifdef BUILD_OPT
+OPTIMIZER = $(WIN_OPT_CFLAGS)
+else
+ifdef BUILD_IDG
+OPTIMIZER = $(WIN_IDG_CFLAGS)
+else
+OPTIMIZER = $(WIN_DEBUG_CFLAGS)
+endif
+endif
+
+OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 -DWINVER=0x500 -D_WIN32_WINNT=0x500 $(WIN_CFLAGS)
+JSDLL_CFLAGS = -DEXPORT_JS_API
+OS_LIBS = -lm -lc
+
+PREBUILT_CPUCFG = 1
+USE_MSVC = 1
+
+LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib \
+ winmm.lib \
+ -nologo\
+ -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\
+ -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+# CAFEDIR = t:/cafe
+# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip
+# JAVAC = $(CAFEDIR)/Bin/sj.exe
+# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe
+# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.2.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.2.mk
new file mode 100644
index 0000000..5fbcbfe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.2.mk
@@ -0,0 +1,118 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Windows NT using MS Visual C++ (version?)
+#
+
+CC = cl
+CXX = cl
+
+RANLIB = echo
+
+PDBFILE = $(basename $(@F)).pdb
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86 # XXX fixme
+GFX_ARCH = win32
+
+# MSVC compiler options for both debug/optimize
+# -nologo - suppress copyright message
+# -W3 - Warning level 3
+# -Gm - enable minimal rebuild
+# -Z7 - put debug info into the executable, not in .pdb file
+# -Zi - put debug info into .pdb file
+# -YX - automatic precompiled headers
+# -GX - enable C++ exception support
+WIN_CFLAGS = -nologo -W3
+
+# MSVC compiler options for debug builds linked to MSVCRTD.DLL
+# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_IDG_CFLAGS = -MDd -Od -Z7
+
+# MSVC compiler options for debug builds linked to MSVCRT.DLL
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE)
+
+# MSVC compiler options for release (optimized) builds
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime)
+# -O2 - Optimize for speed
+# -G5 - Optimize for Pentium
+WIN_OPT_CFLAGS = -MD -O2
+
+ifdef BUILD_OPT
+OPTIMIZER = $(WIN_OPT_CFLAGS)
+else
+ifdef BUILD_IDG
+OPTIMIZER = $(WIN_IDG_CFLAGS)
+else
+OPTIMIZER = $(WIN_DEBUG_CFLAGS)
+endif
+endif
+
+OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 -DWINVER=0x500 -D_WIN32_WINNT=0x500 $(WIN_CFLAGS) -DAVMPLUS_WIN32 -DAVMPLUS_IA32
+JSDLL_CFLAGS = -DEXPORT_JS_API
+OS_LIBS = -lm -lc
+
+PREBUILT_CPUCFG = 1
+USE_MSVC = 1
+
+LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib \
+ winmm.lib \
+ -nologo\
+ -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\
+ -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+# CAFEDIR = t:/cafe
+# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip
+# JAVAC = $(CAFEDIR)/Bin/sj.exe
+# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe
+# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT6.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT6.0.mk
new file mode 100644
index 0000000..7681e01
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT6.0.mk
@@ -0,0 +1,118 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Windows NT using MS Visual C++ (version?)
+#
+
+CC = cl
+CXX = cl
+
+RANLIB = echo
+
+PDBFILE = $(basename $(@F)).pdb
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86 # XXX fixme
+GFX_ARCH = win32
+
+# MSVC compiler options for both debug/optimize
+# -nologo - suppress copyright message
+# -W3 - Warning level 3
+# -Gm - enable minimal rebuild
+# -Z7 - put debug info into the executable, not in .pdb file
+# -Zi - put debug info into .pdb file
+# -YX - automatic precompiled headers
+# -GX - enable C++ exception support
+WIN_CFLAGS = -nologo -W3
+
+# MSVC compiler options for debug builds linked to MSVCRTD.DLL
+# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_IDG_CFLAGS = -MDd -Od -Z7
+
+# MSVC compiler options for debug builds linked to MSVCRT.DLL
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE)
+
+# MSVC compiler options for release (optimized) builds
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime)
+# -O2 - Optimize for speed
+# -G5 - Optimize for Pentium
+WIN_OPT_CFLAGS = -MD -O2
+
+ifdef BUILD_OPT
+OPTIMIZER = $(WIN_OPT_CFLAGS)
+else
+ifdef BUILD_IDG
+OPTIMIZER = $(WIN_IDG_CFLAGS)
+else
+OPTIMIZER = $(WIN_DEBUG_CFLAGS)
+endif
+endif
+
+OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 -DWINVER=0x500 -D_WIN32_WINNT=0x500 $(WIN_CFLAGS)
+JSDLL_CFLAGS = -DEXPORT_JS_API
+OS_LIBS = -lm -lc
+
+PREBUILT_CPUCFG = 1
+USE_MSVC = 1
+
+LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib \
+ winmm.lib \
+ -nologo\
+ -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\
+ -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+# CAFEDIR = t:/cafe
+# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip
+# JAVAC = $(CAFEDIR)/Bin/sj.exe
+# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe
+# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/dgux.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/dgux.mk
new file mode 100644
index 0000000..3b5967e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/dgux.mk
@@ -0,0 +1,64 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for Data General DG/UX
+#
+
+#
+# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com)
+#
+
+AS = as
+CC = gcc
+CCC = g++
+
+RANLIB = echo
+
+#
+# _DGUX_SOURCE is needed to turn on a lot of stuff in the headers if
+# you're not using DG's compiler. It shouldn't hurt if you are.
+#
+# _POSIX4A_DRAFT10_SOURCE is needed to pick up localtime_r, used in
+# prtime.c
+#
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DDGUX -D_DGUX_SOURCE -D_POSIX4A_DRAFT10_SOURCE -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl
+
+NOSUCHFILE = /no-such-file
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/resource.h b/tools/node_modules/expresso/deps/jscoverage/js/resource.h
new file mode 100644
index 0000000..9301810
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by js3240.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/rules.mk b/tools/node_modules/expresso/deps/jscoverage/js/rules.mk
new file mode 100644
index 0000000..5a1e053
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/rules.mk
@@ -0,0 +1,206 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998-1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Michael Ang <mang@subcarrier.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# JSRef GNUmake makefile rules
+#
+
+ifdef USE_MSVC
+LIB_OBJS = $(addprefix $(OBJDIR)/, $(LIB_CPPFILES:.cpp=.obj))
+PROG_OBJS = $(addprefix $(OBJDIR)/, $(PROG_CPPFILES:.cpp=.obj))
+else
+LIB_OBJS = $(addprefix $(OBJDIR)/, $(LIB_CPPFILES:.cpp=.o))
+LIB_OBJS += $(addprefix $(OBJDIR)/, $(LIB_ASFILES:.s=.o))
+PROG_OBJS = $(addprefix $(OBJDIR)/, $(PROG_CPPFILES:.cpp=.o))
+endif
+
+CPPFILES = $(LIB_CPPFILES) $(PROG_CPPFILES)
+OBJS = $(LIB_OBJS) $(PROG_OBJS)
+
+ifdef USE_MSVC
+# TARGETS = $(LIBRARY) # $(PROGRAM) not supported for MSVC yet
+TARGETS += $(SHARED_LIBRARY) $(PROGRAM) # it is now
+else
+TARGETS += $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM)
+endif
+
+all:
+ +$(LOOP_OVER_PREDIRS)
+ifneq "$(strip $(TARGETS))" ""
+ $(MAKE) -f Makefile.ref $(TARGETS)
+endif
+ +$(LOOP_OVER_DIRS)
+
+$(OBJDIR)/%: %.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ $(CFLAGS) $(OPTIMIZER) $< $(LDFLAGS)
+
+# This rule must come before the rule with no dep on header
+$(OBJDIR)/%.o: %.cpp %.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ -c $(CFLAGS) $(OPTIMIZER) $<
+
+$(OBJDIR)/jsinterp.o: jsinterp.cpp jsinterp.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ -c $(CFLAGS) $(INTERP_OPTIMIZER) jsinterp.cpp
+
+$(OBJDIR)/jsbuiltins.o: jsbuiltins.cpp jsinterp.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ -c $(CFLAGS) $(BUILTINS_OPTIMIZER) jsbuiltins.cpp
+
+$(OBJDIR)/%.o: %.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ -c $(CFLAGS) $(OPTIMIZER) $<
+
+$(OBJDIR)/%.o: %.s
+ @$(MAKE_OBJDIR)
+ $(AS) -o $@ $(ASFLAGS) $<
+
+# This rule must come before rule with no dep on header
+$(OBJDIR)/%.obj: %.cpp %.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $(OPTIMIZER) $<
+
+$(OBJDIR)/jsinterp.obj: jsinterp.cpp jsinterp.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $(INTERP_OPTIMIZER) jsinterp.cpp
+
+$(OBJDIR)/jsbuiltins.obj: jsbuiltins.cpp jsinterp.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $(BUILTINS_OPTIMIZER) jsbuiltins.cpp
+
+$(OBJDIR)/%.obj: %.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $(OPTIMIZER) $<
+
+$(OBJDIR)/js.obj: js.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(OPTIMIZER) $<
+
+ifeq ($(OS_ARCH),OS2)
+$(LIBRARY): $(LIB_OBJS)
+ $(AR) $@ $? $(AR_OS2_SUFFIX)
+ $(RANLIB) $@
+else
+ifdef USE_MSVC
+$(SHARED_LIBRARY): $(LIB_OBJS)
+ link.exe $(LIB_LINK_FLAGS) /base:0x61000000 $(OTHER_LIBS) \
+ /out:"$@" /pdb:none\
+ /implib:"$(OBJDIR)/$(@F:.dll=.lib)" $^
+else
+$(LIBRARY): $(LIB_OBJS)
+ $(AR) rv $@ $?
+ $(RANLIB) $@
+
+$(SHARED_LIBRARY): $(LIB_OBJS)
+ $(MKSHLIB) -o $@ $(LIB_OBJS) $(LDFLAGS) $(OTHER_LIBS)
+endif
+endif
+
+# Java stuff
+$(CLASSDIR)/$(OBJDIR)/$(JARPATH)/%.class: %.java
+ mkdir -p $(@D)
+ $(JAVAC) $(JAVAC_FLAGS) $<
+
+define MAKE_OBJDIR
+if test ! -d $(@D); then rm -rf $(@D); mkdir -p $(@D); fi
+endef
+
+ifdef DIRS
+LOOP_OVER_DIRS = \
+ @for d in $(DIRS); do \
+ if test -d $$d; then \
+ set -e; \
+ echo "cd $$d; $(MAKE) -f Makefile.ref $@"; \
+ cd $$d; $(MAKE) -f Makefile.ref $@; cd ..; \
+ set +e; \
+ else \
+ echo "Skipping non-directory $$d..."; \
+ fi; \
+ done
+endif
+
+ifdef PREDIRS
+LOOP_OVER_PREDIRS = \
+ @for d in $(PREDIRS); do \
+ if test -d $$d; then \
+ set -e; \
+ echo "cd $$d; $(MAKE) -f Makefile.ref $@"; \
+ cd $$d; $(MAKE) -f Makefile.ref $@; cd ..; \
+ set +e; \
+ else \
+ echo "Skipping non-directory $$d..."; \
+ fi; \
+ done
+endif
+
+export:
+ +$(LOOP_OVER_PREDIRS)
+ mkdir -p $(DIST)/include $(DIST)/$(LIBDIR) $(DIST)/bin
+ifneq "$(strip $(HFILES))" ""
+ $(CP) $(HFILES) $(DIST)/include
+endif
+ifneq "$(strip $(LIBRARY))" ""
+ $(CP) $(LIBRARY) $(DIST)/$(LIBDIR)
+endif
+ifneq "$(strip $(JARS))" ""
+ $(CP) $(JARS) $(DIST)/$(LIBDIR)
+endif
+ifneq "$(strip $(SHARED_LIBRARY))" ""
+ $(CP) $(SHARED_LIBRARY) $(DIST)/$(LIBDIR)
+endif
+ifneq "$(strip $(PROGRAM))" ""
+ $(CP) $(PROGRAM) $(DIST)/bin
+endif
+ +$(LOOP_OVER_DIRS)
+
+clean:
+ +$(LOOP_OVER_PREDIRS)
+ rm -rf $(OBJS) $(GARBAGE)
+
+clobber:
+ +$(LOOP_OVER_PREDIRS)
+ rm -rf $(OBJS) $(TARGETS) $(DEPENDENCIES) $(GARBAGE)
+ if test -d $(OBJDIR); then rmdir $(OBJDIR); fi
+
+tar:
+ tar cvf $(TARNAME) $(TARFILES)
+ gzip $(TARNAME)
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/time.sh b/tools/node_modules/expresso/deps/jscoverage/js/time.sh
new file mode 100755
index 0000000..05b3499
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/time.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+echo -n interp:' '
+for i in 1 2 3 4 5; do
+ INTERP=`Darwin_OPT.OBJ/js -e 'var d = Date.now(); load("'$1'"); print(Date.now() - d);'`
+ echo -n $INTERP' '
+done
+echo -ne '\njit: '
+for i in 1 2 3 4 5; do
+ JIT=`Darwin_OPT.OBJ/js -j -e 'var d = Date.now(); load("'$1'"); print(Date.now() - d);'`
+ echo -n $JIT' '
+done
+echo -ne '\njit factor: '
+(echo scale=2; echo $INTERP / $JIT ) | bc
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/win32.order b/tools/node_modules/expresso/deps/jscoverage/js/win32.order
new file mode 100644
index 0000000..069403d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/win32.order
@@ -0,0 +1,384 @@
+js_MarkGCThing ; 5893956
+JS_GetPrivate ; 2090130
+JS_HashTableRawLookup ; 1709984
+js_Mark ; 1547496
+js_GetToken ; 1406677
+js_UngetToken ; 1154416
+js_MarkAtom ; 992874
+js_MatchToken ; 980277
+js_CompareStrings ; 662772
+js_Lock ; 628184
+js_Unlock ; 628184
+js_HashString ; 611102
+js_DropScopeProperty ; 546476
+JS_malloc ; 484350
+js_InflateStringToBuffer ; 460739
+js_HoldScopeProperty ; 442612
+JS_free ; 382991
+js_MarkScript ; 376942
+js_HashId ; 365238
+JS_CompareValues ; 352366
+js_IdToValue ; 337594
+JS_GetClass ; 325296
+js_LookupProperty ; 324680
+js_GetAtom ; 244669
+js_DropProperty ; 223217
+JS_GetParent ; 209680
+js_LiveContext ; 205767
+js_PeekToken ; 200646
+js_GetSlotThreadSafe ; 198839
+JS_GetStringChars ; 190862
+JS_HashTableRawAdd ; 179156
+js_FoldConstants ; 162626
+js_EmitTree ; 145634
+JS_EnumerateStub ; 140640
+js_NewSrcNote ; 136983
+js_GetProperty ; 135639
+js_NewScopeProperty ; 135057
+js_MutateScope ; 135057
+js_GetMutableScope ; 135057
+js_AllocSlot ; 132401
+JS_GetRuntime ; 127316
+JS_FrameIterator ; 121963
+JS_GetFrameFunctionObject ; 120567
+js_AllocGCThing ; 119828
+js_DestroyScopeProperty ; 115989
+js_Emit3 ; 109135
+JS_HashTableLookup ; 107154
+JS_InstanceOf ; 103905
+js_DefineProperty ; 99514
+js_strncpy ; 88276
+js_PeekTokenSameLine ; 87197
+js_HoldObjectMap ; 79084
+js_DropObjectMap ; 77824
+js_NewObject ; 72421
+js_ValueToString ; 72143
+js_GetClassPrototype ; 66235
+js_UnlockRuntime ; 64699
+js_LockRuntime ; 64699
+js_ContextIterator ; 64586
+JS_ClearWatchPointsForObject ; 64155
+js_FinalizeObject ; 63925
+js_IndexAtom ; 63789
+JS_SetPrivate ; 63702
+JS_GetGlobalObject ; 63546
+js_Emit1 ; 63012
+JS_ContextIterator ; 57847
+JS_GetInstancePrivate ; 57817
+JS_HashTableRawRemove ; 57057
+js_Invoke ; 53568
+js_FindProperty ; 53150
+JS_GetFrameScript ; 51395
+js_LinkFunctionObject ; 50651
+js_SetSrcNoteOffset ; 47735
+js_InWithStatement ; 47346
+js_NewFunction ; 47074
+js_NewSrcNote2 ; 46165
+JS_HashTableAdd ; 45503
+JS_HashTableRemove ; 45213
+js_InCatchBlock ; 42198
+js_AddRootRT ; 40587
+js_AddRoot ; 40587
+js_SetProperty ; 40558
+JS_AddNamedRoot ; 40462
+js_RemoveRoot ; 40384
+JS_RemoveRootRT ; 38129
+js_NewString ; 37471
+js_DefineFunction ; 36629
+JS_GetContextThread ; 36498
+JS_LookupProperty ; 35137
+JS_ValueToString ; 34072
+JS_realloc ; 33776
+JS_DefineFunction ; 33268
+JS_SetErrorReporter ; 32851
+js_FinalizeString ; 30311
+js_FinalizeStringRT ; 30311
+JS_ArenaAllocate ; 30099
+JS_BeginRequest ; 29323
+JS_EndRequest ; 29323
+JS_GetContextPrivate ; 29189
+JS_CompactArenaPool ; 28874
+js_ValueToStringAtom ; 27934
+JS_ValueToId ; 26517
+js_ValueToBoolean ; 25908
+JS_InternString ; 25467
+js_PopStatement ; 24364
+js_PushStatement ; 24364
+js_NewStringCopyN ; 23911
+js_FlushPropertyCacheByProp ; 23883
+js_GetStringBytes ; 23421
+JS_ArenaRelease ; 23267
+JS_GetStringBytes ; 23106
+js_FreeStack ; 22399
+js_AllocStack ; 22399
+JS_SetProperty ; 21240
+js_InitObjectMap ; 19991
+js_NewScope ; 19991
+js_strlen ; 19070
+JS_GetScriptPrincipals ; 18063
+js_SrcNoteLength ; 17369
+js_DestroyObjectMap ; 17198
+js_DestroyScope ; 17198
+JS_GetStringLength ; 16306
+js_PopStatementCG ; 15418
+JS_GetFrameAnnotation ; 14949
+js_Interpret ; 14032
+js_TransferScopeLock ; 13899
+JS_ResolveStandardClass ; 13645
+JS_ResumeRequest ; 12837
+JS_SuspendRequest ; 12837
+JS_GetProperty ; 12488
+JS_NewObject ; 11660
+js_AllocTryNotes ; 11418
+js_NewNumberValue ; 10859
+js_InternalInvoke ; 10051
+js_NewDouble ; 9936
+js_SetJumpOffset ; 9886
+js_SkipWhiteSpace ; 9299
+js_NewDoubleValue ; 7474
+JS_GetPendingException ; 7404
+js_NewObjectMap ; 7236
+JS_ClearPendingException ; 7092
+JS_strtod ; 7053
+js_strtod ; 7053
+js_InflateString ; 7004
+JS_GetFunctionName ; 6808
+JS_NewHashTable ; 6794
+JS_NewFunction ; 6575
+js_FreeSlot ; 6476
+js_LockScope ; 6332
+JS_HashTableEnumerateEntries ; 6285
+js_GetLengthProperty ; 6162
+js_LockObj ; 6149
+JS_NewUCStringCopyN ; 5994
+JS_NewNumberValue ; 5904
+js_NewStringCopyZ ; 5809
+JS_NewUCStringCopyZ ; 5809
+js_DeflateString ; 5612
+js_ValueToNumber ; 5456
+JS_SetOptions ; 5322
+js_NewScript ; 4941
+js_InitCodeGenerator ; 4810
+js_FinishTakingSrcNotes ; 4810
+js_NewScriptFromParams ; 4810
+js_FinishTakingTryNotes ; 4810
+js_NewScriptFromCG ; 4810
+js_FinishCodeGenerator ; 4810
+JS_strdup ; 4534
+JS_HashTableDestroy ; 4119
+js_CheckRedeclaration ; 3965
+JS_DefineFunctions ; 3808
+js_EmitFunctionBody ; 3739
+js_TryMethod ; 3685
+js_DefaultValue ; 3610
+js_CloneFunctionObject ; 3577
+JS_InitClass ; 3546
+js_SetClassPrototype ; 3377
+JS_GetPrototype ; 3268
+JS_DefineProperties ; 3115
+js_FindVariable ; 3093
+js_DestroyScript ; 3041
+JS_ClearScriptTraps ; 3041
+js_FreeAtomMap ; 3041
+JS_NewStringCopyZ ; 2953
+js_AtomizeObject ; 2709
+JS_ValueToBoolean ; 2643
+js_SetLengthProperty ; 2637
+JS_GetOptions ; 2593
+js_ValueToObject ; 2522
+js_ValueToNonNullObject ; 2510
+js_StringToObject ; 2482
+JS_SetElement ; 2448
+js_NumberToString ; 2407
+JS_TypeOfValue ; 2275
+js_NewBufferTokenStream ; 2253
+js_NewTokenStream ; 2253
+js_CloseTokenStream ; 2253
+JS_RemoveRoot ; 2148
+JS_NewDouble ; 2129
+JS_vsnprintf ; 1937
+JS_snprintf ; 1937
+JS_CallFunctionValue ; 1844
+JS_DHashVoidPtrKeyStub ; 1840
+JS_DHashTableOperate ; 1840
+js_SetProtoOrParent ; 1758
+js_DoubleToInteger ; 1729
+JS_SetVersion ; 1531
+js_ValueToFunction ; 1476
+JS_SetPrototype ; 1408
+JS_CeilingLog2 ; 1317
+js_Execute ; 1199
+js_CompileFunctionBody ; 1182
+JS_CompileUCFunctionForPrincipals ; 1182
+js_GetSrcNoteOffset ; 1139
+JS_DHashMatchEntryStub ; 1094
+JS_VersionToString ; 1090
+JS_CompileUCScriptForPrincipals ; 1071
+js_CompileTokenStream ; 1071
+js_CurrentThreadId ; 1058
+JS_IdToValue ; 1046
+js_ConstructObject ; 974
+JS_DestroyScript ; 967
+js_PCToLineNumber ; 967
+JS_DefineProperty ; 930
+JS_GetScriptFilename ; 924
+JS_GetFramePC ; 899
+JS_EvaluateUCScriptForPrincipals ; 892
+JS_PCToLineNumber ; 848
+JS_StringToVersion ; 761
+js_ExecuteRegExp ; 755
+JS_MaybeGC ; 717
+JS_ValueToNumber ; 698
+JS_GetVersion ; 698
+JS_AliasProperty ; 693
+js_AtomizeValue ; 664
+js_BooleanToString ; 664
+js_SetSlotThreadSafe ; 596
+JS_DHashClearEntryStub ; 584
+JS_DHashTableRawRemove ; 584
+JS_DefineObject ; 557
+js_PutCallObject ; 516
+js_GetCallObject ; 516
+js_strchr ; 511
+JS_DefineUCProperty ; 480
+JS_dtostr ; 475
+JS_ValueToInt32 ; 464
+js_ValueToInt32 ; 464
+JS_FinishArenaPool ; 453
+js_NewTryNote ; 441
+js_strtointeger ; 437
+JS_vsmprintf ; 428
+JS_DHashTableInit ; 423
+JS_DHashAllocTable ; 423
+JS_DHashGetStubOps ; 423
+JS_NewDHashTable ; 423
+JS_DHashTableDestroy ; 423
+JS_DHashFreeTable ; 423
+JS_DHashTableFinish ; 423
+js_EmitBreak ; 412
+js_GetAttributes ; 412
+JS_DefineConstDoubles ; 407
+JS_ArenaGrow ; 374
+js_AtomizeInt ; 372
+JS_SetParent ; 345
+JS_CloneFunctionObject ; 343
+JS_IsNativeFrame ; 343
+JS_ReportErrorNumber ; 340
+js_ErrorToException ; 340
+js_ReportErrorNumberVA ; 340
+js_GetErrorMessage ; 340
+js_ExpandErrorArguments ; 340
+js_ReportUncaughtException ; 315
+JS_IsExceptionPending ; 315
+js_ReportErrorAgain ; 315
+js_ErrorFromException ; 315
+JS_LookupUCProperty ; 307
+JS_InitArenaPool ; 293
+PRMJ_Now ; 262
+DllMain@12 ; 235
+JS_ExecuteScript ; 232
+JS_GetFrameFunction ; 226
+PRMJ_LocalGMTDifference ; 175
+JS_GetConstructor ; 175
+JS_SetGlobalObject ; 164
+js_LockGCThing ; 155
+js_NewRegExpObject ; 152
+js_NewRegExp ; 152
+js_InitObjectClass ; 131
+js_InitFunctionClass ; 131
+js_EmitN ; 128
+JS_ArenaFinish ; 124
+js_GC ; 124
+js_SweepAtomState ; 124
+js_MarkAtomState ; 124
+JS_ArenaRealloc ; 124
+js_ForceGC ; 124
+js_FlushPropertyCache ; 122
+js_InitNumberClass ; 114
+JS_smprintf ; 112
+js_DoubleToECMAInt32 ; 112
+js_ValueToECMAInt32 ; 111
+JS_ValueToECMAInt32 ; 111
+JS_SetContextPrivate ; 109
+PRMJ_DSTOffset ; 108
+js_Clear ; 105
+JS_ClearScope ; 105
+JS_NewScriptObject ; 104
+JS_smprintf_free ; 104
+JS_ConvertValue ; 99
+js_GetSrcNote ; 98
+JS_ValueToECMAUint32 ; 93
+js_ValueToECMAUint32 ; 93
+js_printf ; 93
+js_DoubleToECMAUint32 ; 93
+js_DestroyRegExp ; 89
+js_UnlockGCThing ; 89
+js_TryValueOf ; 87
+js_NewSrcNote3 ; 86
+JS_ConvertStub ; 81
+JS_SetPendingException ; 80
+js_InitStringClass ; 79
+JS_GC ; 78
+js_InitArrayClass ; 74
+js_InitDateClass ; 67
+JS_NewContext ; 64
+JS_AddArgumentFormatter ; 64
+js_InitContextForLocking ; 64
+js_NewContext ; 64
+JS_SetBranchCallback ; 64
+JS_ClearRegExpStatics ; 64
+js_InitRegExpStatics ; 64
+js_InitCallClass ; 63
+js_InitRegExpClass ; 61
+js_Enumerate ; 58
+JS_DestroyContext ; 46
+js_DestroyContext ; 46
+js_FreeRegExpStatics ; 46
+js_InitScanner ; 39
+js_NewPrinter ; 36
+js_DestroyPrinter ; 36
+js_GetPrinterOutput ; 36
+JS_FreeArenaPool ; 36
+js_DecompileCode ; 34
+js_EmitContinue ; 33
+js_CheckAccess ; 30
+js_DecompileValueGenerator ; 28
+js_InitMathClass ; 27
+js_InitExceptionClasses ; 25
+js_NewArrayObject ; 24
+js_InitArgumentsClass ; 21
+js_puts ; 20
+js_InitBooleanClass ; 19
+JS_InitStandardClasses ; 19
+js_InitScriptClass ; 19
+js_obj_toString ; 15
+js_GetArgsValue ; 14
+js_GetArgsObject ; 14
+JS_DestroyIdArray ; 11
+js_NewIdArray ; 11
+JS_GetElement ; 11
+JS_EvaluateScript ; 9
+JS_EvaluateUCScript ; 9
+JS_DecompileFunction ; 8
+js_DecompileFunction ; 8
+JS_NewString ; 8
+js_SetStringBytes ; 8
+JS_GetArrayLength ; 7
+JS_NewArrayObject ; 7
+JS_IsArrayObject ; 7
+JS_ValueToObject ; 7
+JS_DefineElement ; 6
+js_DecompileScript ; 6
+JS_PushArguments ; 4
+JS_PopArguments ; 4
+JS_PushArgumentsVA ; 4
+js_PutArgsObject ; 2
+JS_SetGCCallbackRT ; 2
+JS_Init ; 1
+js_SetupLocks ; 1
+js_InitRuntimeNumberState ; 1
+js_InitRuntimeStringState ; 1
+js_InitLock ; 1
+js_InitGC ; 1
+js_InitAtomState ; 1
+js_InitStringGlobals ; 1
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-help.txt b/tools/node_modules/expresso/deps/jscoverage/jscoverage-help.txt
new file mode 100644
index 0000000..e20938b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-help.txt
@@ -0,0 +1,12 @@
+Usage: jscoverage SOURCE-DIRECTORY DESTINATION-DIRECTORY
+Instrument JavaScript with code coverage information.
+
+Options:
+ --encoding=ENCODING assume .js files use the given character encoding
+ --exclude=PATH do not copy PATH
+ --js-version=VERSION use the specified JavaScript version
+ --no-highlight do not perform syntax highlighting
+ --no-instrument=PATH copy but do not instrument PATH
+ -v, --verbose explain what is being done
+ -h, --help display this help and exit
+ -V, --version display version information and exit
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-highlight.css b/tools/node_modules/expresso/deps/jscoverage/jscoverage-highlight.css
new file mode 100644
index 0000000..31a4695
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-highlight.css
@@ -0,0 +1,38 @@
+/*
+ jscoverage-highlight.css - JSCoverage syntax highlighting style sheet
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/* keyword, type, symbol, cbracket */
+#sourceTable .k {
+ font-weight: bold;
+}
+
+/* string, regexp, number */
+#sourceTable .s {
+ color: #006400;
+}
+
+/* specialchar */
+#sourceTable .t {
+ color: #2e8b57;
+}
+
+/* comment */
+#sourceTable .c {
+ font-style: italic;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-ie.css b/tools/node_modules/expresso/deps/jscoverage/jscoverage-ie.css
new file mode 100644
index 0000000..afb2b80
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-ie.css
@@ -0,0 +1,89 @@
+#headingDiv {
+ position: static;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding-top: 0.5em;
+}
+
+#tabs {
+ clear: all;
+ position: static;
+ top: auto;
+ left: auto;
+ right: auto;
+ height: auto;
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+#tabs div {
+ position: relative;
+ height: auto;
+ line-height: normal;
+ padding-top: 5px;
+ padding-bottom: 5px;
+}
+
+#tabs div.selected {
+ padding-bottom: 6px;
+ z-index: 2;
+}
+
+.TabPage {
+ position: relative;
+ top: -1px;
+ left: auto;
+ right: auto;
+ bottom: auto;
+ clear: left;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 10px;
+ z-index: 1;
+}
+
+#locationDiv {
+ margin-bottom: 10px;
+}
+
+#iframeDiv {
+ position: static;
+ width: 100%;
+}
+
+#summaryDiv {
+ position: static;
+ width: 100%;
+}
+
+#fileDiv {
+ margin-bottom: 10px;
+}
+
+#sourceDiv {
+ position: static;
+ width: 100%;
+}
+
+#storeDiv {
+ position: static;
+ width: 100%;
+}
+
+/* some defaults */
+
+.TabPage {
+ height: 650px;
+}
+
+#iframeDiv {
+ height: 600px;
+}
+
+#summaryDiv {
+ height: 600px;
+}
+
+#sourceDiv {
+ height: 600px;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-overlay.js b/tools/node_modules/expresso/deps/jscoverage/jscoverage-overlay.js
new file mode 100644
index 0000000..35e6181
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-overlay.js
@@ -0,0 +1,211 @@
+/*
+ jscoverage-overlay.js - script for XUL overlay
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+Components.utils.import('resource://gre/modules/jscoverage.jsm');
+
+// https://developer.mozilla.org/en/Code_snippets/Tabbed_browser
+function openAndReuseOneTabPerURL(url) {
+ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator);
+ var browserEnumerator = wm.getEnumerator("navigator:browser");
+
+ // Check each browser instance for our URL
+ var found = false;
+ while (!found && browserEnumerator.hasMoreElements()) {
+ var browserWin = browserEnumerator.getNext();
+ var tabbrowser = browserWin.getBrowser();
+
+ // Check each tab of this browser instance
+ var numTabs = tabbrowser.browsers.length;
+ for(var index=0; index<numTabs; index++) {
+ var currentBrowser = tabbrowser.getBrowserAtIndex(index);
+ if (url == currentBrowser.currentURI.spec) {
+
+ // The URL is already opened. Select this tab.
+ tabbrowser.selectedTab = tabbrowser.mTabs[index];
+
+ // Focus *this* browser-window
+ browserWin.focus();
+
+ found = true;
+ break;
+ }
+ }
+ }
+
+ // Our URL isn't open. Open it now.
+ if (!found) {
+ var recentWindow = wm.getMostRecentWindow("navigator:browser");
+ if (recentWindow) {
+ // Use an existing browser window
+ recentWindow.delayedOpenTab(url, null, null, null, null);
+ }
+ else {
+ // No browser windows are open, so open a new one.
+ window.open(url);
+ }
+ }
+}
+
+function jscoverage_view() {
+ openAndReuseOneTabPerURL('chrome://jscoverage/content/jscoverage.html');
+}
+
+function jscoverage_pad(s) {
+ return '0000'.substr(s.length) + s;
+}
+
+function jscoverage_quote(s) {
+ return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) {
+ switch (c) {
+ case '\b':
+ return '\\b';
+ case '\f':
+ return '\\f';
+ case '\n':
+ return '\\n';
+ case '\r':
+ return '\\r';
+ case '\t':
+ return '\\t';
+ case '\v':
+ return '\\v';
+ case '"':
+ return '\\"';
+ case '\\':
+ return '\\\\';
+ default:
+ return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16));
+ }
+ }) + '"';
+}
+
+function jscoverage_store() {
+ try {
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+
+ var directoryService = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties);
+ var reportDirectory = directoryService.get('CurWorkD', Ci.nsILocalFile);
+ reportDirectory.appendRelativePath('jscoverage-report');
+ if (! reportDirectory.exists()) {
+ reportDirectory.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
+ }
+
+ var ioService = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
+ var copyChrome = function(filename) {
+ var channel = ioService.newChannel('chrome://jscoverage/content/' + filename, null, null);
+ var binaryInputStream = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
+ try {
+ binaryInputStream.setInputStream(channel.open());
+
+ var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
+ file.initWithFile(reportDirectory);
+ file.appendRelativePath(filename);
+ var fileOutputStream = Cc['@mozilla.org/network/file-output-stream;1'].createInstance(Ci.nsIFileOutputStream);
+ fileOutputStream.init(file, 0x02 | 0x08 | 0x20, 0644, 0);
+ var binaryOutputStream = Cc['@mozilla.org/binaryoutputstream;1'].createInstance(Ci.nsIBinaryOutputStream);
+ try {
+ binaryOutputStream.setOutputStream(fileOutputStream);
+
+ for (;;) {
+ var available = binaryInputStream.available();
+ if (available === 0) {
+ break;
+ }
+ var bytes = binaryInputStream.readBytes(available);
+ binaryOutputStream.writeBytes(bytes, bytes.length);
+ }
+
+ if (filename === 'jscoverage.js') {
+ var s = 'jscoverage_isReport = true;\n';
+ binaryOutputStream.write(s, s.length);
+ }
+ }
+ finally {
+ binaryOutputStream.close();
+ }
+ }
+ finally {
+ binaryInputStream.close();
+ }
+ };
+ copyChrome('jscoverage.html');
+ copyChrome('jscoverage.js');
+ copyChrome('jscoverage.css');
+ copyChrome('jscoverage-throbber.gif');
+ copyChrome('jscoverage-highlight.css');
+
+ // write the coverage data
+ var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
+ file.initWithFile(reportDirectory);
+ file.appendRelativePath('jscoverage.json');
+ var fileOutputStream = Cc['@mozilla.org/network/file-output-stream;1'].createInstance(Ci.nsIFileOutputStream);
+ try {
+ fileOutputStream.init(file, 0x02 | 0x08 | 0x20, 0644, 0);
+ function write(s) {
+ fileOutputStream.write(s, s.length);
+ }
+ write('{');
+ var first = true;
+ for (var file in _$jscoverage) {
+ if (first) {
+ first = false;
+ }
+ else {
+ write(',');
+ }
+ write(jscoverage_quote(file));
+ write(':{"coverage":[');
+ var coverage = _$jscoverage[file];
+ var length = coverage.length;
+ for (var line = 0; line < length; line++) {
+ if (line > 0) {
+ write(',');
+ }
+ var value = coverage[line];
+ if (value === undefined || value === null) {
+ value = 'null';
+ }
+ write(value.toString());
+ }
+ write('],"source":[');
+ var source = coverage.source;
+ length = source.length;
+ for (line = 0; line < length; line++) {
+ if (line > 0) {
+ write(',');
+ }
+ write(jscoverage_quote(source[line]));
+ }
+ write(']}');
+ }
+ write('}');
+ alert('Coverage data stored.');
+ }
+ finally {
+ fileOutputStream.close();
+ }
+ }
+ catch (e) {
+ alert(e);
+ dump(e);
+ dump('\n');
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-server b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server
new file mode 100755
index 0000000..fabccc7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-server-help.txt b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server-help.txt
new file mode 100644
index 0000000..98415b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server-help.txt
@@ -0,0 +1,17 @@
+Usage: jscoverage-server [OPTION]...
+Run a server for instrumenting JavaScript with code coverage information.
+
+Options:
+ --document-root=DIR serve content from DIR (default: current directory)
+ --encoding=ENCODING assume .js files use the given character encoding
+ --ip-address=ADDRESS bind to ADDRESS (default: 127.0.0.1)
+ --js-version=VERSION use the specified JavaScript version
+ --no-highlight do not perform syntax highlighting
+ --no-instrument=URL do not instrument URL
+ --port=PORT use PORT for TCP port (default: 8080)
+ --proxy run as a proxy
+ --report-dir=DIR store report to DIR (default: `jscoverage-report')
+ --shutdown stop a running server
+ -v, --verbose explain what is being done
+ -h, --help display this help and exit
+ -V, --version display version information and exit
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.1 b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.1
new file mode 100644
index 0000000..cfb4b09
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.1
@@ -0,0 +1,79 @@
+.TH jscoverage-server 1 local
+.SH NAME
+jscoverage-server \- Run a server for instrumenting JavaScript with code coverage information
+
+.SH SYNOPSIS
+jscoverage-server [OPTION]...
+
+.SH DESCRIPTION
+
+jscoverage-server is a simple web server that instruments JavaScript code as it is served.
+
+.SH OPTIONS
+
+.TP
+.B --document-root=DIR
+serve content from
+.B DIR
+(default: current directory).
+
+.TP
+.B --encoding=ENCODING
+assume .js files use the given character encoding.
+
+.TP
+.B --ip-address=ADDRESS
+bind to
+.B ADDRESS
+(default: 127.0.0.1).
+
+.TP
+.B --js-version=VERSION
+use the specified JavaScript version; valid values for
+.B VERSION
+are 1.0, 1.1, 1.2, ..., 1.8, or ECMAv3 (the default).
+
+.TP
+.B --no-highlight
+do not perform syntax highlighting.
+
+.TP
+.B --no-instrument=URL
+do not instrument
+.B URL.
+
+.TP
+.B --port=PORT
+use
+.B PORT
+for TCP port (default: 8080).
+
+.TP
+.B --proxy
+run as a proxy.
+
+.TP
+.B --report-dir=DIR
+store report to
+.B DIR
+(default: jscoverage-report).
+
+.TP
+.B --shutdown
+stop a running server.
+
+.TP
+.B -v, --verbose
+explain what is being done.
+
+.TP
+.B -h, --help
+display this help and exit.
+
+.TP
+.B -V, --version
+display version information and exit.
+.
+.SH AUTHORS
+
+siliconforks.com
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.c b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.c
new file mode 100644
index 0000000..7fc02bc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.c
@@ -0,0 +1,1307 @@
+/*
+ jscoverage-server.c - JSCoverage server main routine
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <signal.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <dirent.h>
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#include "encoding.h"
+#include "global.h"
+#include "http-server.h"
+#include "instrument-js.h"
+#include "resource-manager.h"
+#include "stream.h"
+#include "util.h"
+
+static const char * specified_encoding = NULL;
+const char * jscoverage_encoding = "ISO-8859-1";
+bool jscoverage_highlight = true;
+
+typedef struct SourceCache {
+ char * url;
+ uint16_t * characters;
+ size_t num_characters;
+ struct SourceCache * next;
+} SourceCache;
+
+static SourceCache * source_cache = NULL;
+
+static const struct {
+ const char * extension;
+ const char * mime_type;
+} mime_types[] = {
+ {".gif", "image/gif"},
+ {".jpg", "image/jpeg"},
+ {".jpeg", "image/jpeg"},
+ {".png", "image/png"},
+ {".css", "text/css"},
+ {".html", "text/html"},
+ {".htm", "text/html"},
+ {".js", "text/javascript"},
+ {".txt", "text/plain"},
+ {".xml", "application/xml"},
+};
+
+static bool verbose = false;
+static const char * report_directory = "jscoverage-report";
+static const char * document_root = ".";
+static bool proxy = false;
+static const char ** no_instrument;
+static size_t num_no_instrument = 0;
+
+#ifdef __MINGW32__
+CRITICAL_SECTION javascript_mutex;
+CRITICAL_SECTION source_cache_mutex;
+#define LOCK EnterCriticalSection
+#define UNLOCK LeaveCriticalSection
+#else
+pthread_mutex_t javascript_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t source_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define LOCK pthread_mutex_lock
+#define UNLOCK pthread_mutex_unlock
+#endif
+
+static const SourceCache * find_cached_source(const char * url) {
+ SourceCache * result = NULL;
+ LOCK(&source_cache_mutex);
+ for (SourceCache * p = source_cache; p != NULL; p = p->next) {
+ if (strcmp(url, p->url) == 0) {
+ result = p;
+ break;
+ }
+ }
+ UNLOCK(&source_cache_mutex);
+ return result;
+}
+
+static void add_cached_source(const char * url, uint16_t * characters, size_t num_characters) {
+ SourceCache * new_source_cache = xmalloc(sizeof(SourceCache));
+ new_source_cache->url = xstrdup(url);
+ new_source_cache->characters = characters;
+ new_source_cache->num_characters = num_characters;
+ LOCK(&source_cache_mutex);
+ new_source_cache->next = source_cache;
+ source_cache = new_source_cache;
+ UNLOCK(&source_cache_mutex);
+}
+
+static int get(const char * url, uint16_t ** characters, size_t * num_characters) __attribute__((warn_unused_result));
+
+static int get(const char * url, uint16_t ** characters, size_t * num_characters) {
+ char * host = NULL;
+ uint16_t port;
+ char * abs_path = NULL;
+ char * query = NULL;
+ HTTPConnection * connection = NULL;
+ HTTPExchange * exchange = NULL;
+ Stream * stream = NULL;
+
+ int result = URL_parse(url, &host, &port, &abs_path, &query);
+ if (result != 0) {
+ goto done;
+ }
+
+ connection = HTTPConnection_new_client(host, port);
+ if (connection == NULL) {
+ result = -1;
+ goto done;
+ }
+
+ exchange = HTTPExchange_new(connection);
+ HTTPExchange_set_request_uri(exchange, url);
+ result = HTTPExchange_write_request_headers(exchange);
+ if (result != 0) {
+ goto done;
+ }
+
+ result = HTTPExchange_read_response_headers(exchange);
+ if (result != 0) {
+ goto done;
+ }
+
+ stream = Stream_new(0);
+ result = HTTPExchange_read_entire_response_entity_body(exchange, stream);
+ if (result != 0) {
+ goto done;
+ }
+ char * encoding = HTTPMessage_get_charset(HTTPExchange_get_response_message(exchange));
+ if (encoding == NULL) {
+ encoding = xstrdup(jscoverage_encoding);
+ }
+ result = jscoverage_bytes_to_characters(encoding, stream->data, stream->length, characters, num_characters);
+ free(encoding);
+ if (result != 0) {
+ goto done;
+ }
+
+ result = 0;
+
+done:
+ if (stream != NULL) {
+ Stream_delete(stream);
+ }
+ if (exchange != NULL) {
+ HTTPExchange_delete(exchange);
+ }
+ if (connection != NULL) {
+ if (HTTPConnection_delete(connection) != 0) {
+ HTTPServer_log_err("Warning: error closing connection after retrieving URL: %s\n", url);
+ }
+ }
+ free(host);
+ free(abs_path);
+ free(query);
+ return result;
+}
+
+static void send_response(HTTPExchange * exchange, uint16_t status_code, const char * html) {
+ HTTPExchange_set_status_code(exchange, status_code);
+ if (HTTPExchange_write_response(exchange, html, strlen(html)) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+}
+
+/*
+RFC 2396, Appendix A: we are checking for `pchar'
+*/
+static bool is_escaped(char c) {
+ /* `pchar' */
+ if (strchr(":@&=+$,", c) != NULL) {
+ return false;
+ }
+
+ if (isalnum((unsigned char) c)) {
+ return false;
+ }
+
+ /* `mark' */
+ if (strchr("-_.!~*'()", c) != NULL) {
+ return false;
+ }
+
+ return true;
+}
+
+static char * encode_uri_component(const char * s) {
+ size_t length = 0;
+ for (const char * p = s; *p != '\0'; p++) {
+ if (is_escaped(*p)) {
+ length = addst(length, 3);
+ }
+ else {
+ length = addst(length, 1);
+ }
+ }
+
+ length = addst(length, 1);
+ char * result = xmalloc(length);
+ size_t i = 0;
+ for (const char * p = s; *p != '\0'; p++) {
+ if (is_escaped(*p)) {
+ result[i] = '%';
+ i++;
+ snprintf(result + i, 3, "%02X", *p);
+ i += 2;
+ }
+ else {
+ result[i] = *p;
+ i++;
+ }
+ }
+ result[i] = '\0';
+
+ return result;
+}
+
+static unsigned int hex_value(char c) {
+ if ('0' <= c && c <= '9') {
+ return c - '0';
+ }
+ else if ('A' <= c && c <= 'F') {
+ return c - 'A' + 10;
+ }
+ else if ('a' <= c && c <= 'f') {
+ return c - 'a' + 10;
+ }
+ else {
+ return 0;
+ }
+}
+
+static char * decode_uri_component(const char * s) {
+ size_t length = strlen(s);
+ char * result = xmalloc(length + 1);
+ char * p = result;
+ while (*s != '\0') {
+ if (*s == '%') {
+ if (s[1] == '\0' || s[2] == '\0') {
+ *p = '\0';
+ return result;
+ }
+ *p = hex_value(s[1]) * 16 + hex_value(s[2]);
+ s += 2;
+ }
+ else {
+ *p = *s;
+ }
+ p++;
+ s++;
+ }
+ *p = '\0';
+ return result;
+}
+
+static const char * get_entity(char c) {
+ switch(c) {
+ case '<':
+ return "&lt;";
+ case '>':
+ return "&gt;";
+ case '&':
+ return "&amp;";
+ case '\'':
+ return "&apos;";
+ case '"':
+ return "&quot;";
+ default:
+ return NULL;
+ }
+}
+
+static char * encode_html(const char * s) {
+ size_t length = 0;
+ for (const char * p = s; *p != '\0'; p++) {
+ const char * entity = get_entity(*p);
+ if (entity == NULL) {
+ length = addst(length, 1);
+ }
+ else {
+ length = addst(length, strlen(entity));
+ }
+ }
+
+ length = addst(length, 1);
+ char * result = xmalloc(length);
+ size_t i = 0;
+ for (const char * p = s; *p != '\0'; p++) {
+ const char * entity = get_entity(*p);
+ if (entity == NULL) {
+ result[i] = *p;
+ i++;
+ }
+ else {
+ strcpy(result + i, entity);
+ i += strlen(entity);
+ }
+ }
+ result[i] = '\0';
+
+ return result;
+}
+
+static const char * get_content_type(const char * path) {
+ char * last_dot = strrchr(path, '.');
+ if (last_dot == NULL) {
+ return "application/octet-stream";
+ }
+ for (size_t i = 0; i < sizeof(mime_types) / sizeof(mime_types[0]); i++) {
+ if (strcmp(last_dot, mime_types[i].extension) == 0) {
+ return mime_types[i].mime_type;
+ }
+ }
+ return "application/octet-stream";
+}
+
+/**
+Checks whether a URI is on the no-instrument list.
+@param uri the HTTP "Request-URI"; must not be NULL, and must not be a zero-length string
+@return true if the URI is on the no-instrument list, false otherwise
+*/
+static bool is_no_instrument(const char * uri) {
+ assert(*uri != '\0');
+
+ for (size_t i = 0; i < num_no_instrument; i++) {
+ if (str_starts_with(uri, no_instrument[i])) {
+ return true;
+ }
+
+ /*
+ For a local URL, accept "/foo/bar" and "foo/bar" on the no-instrument list.
+ */
+ if (! proxy && str_starts_with(uri + 1, no_instrument[i])) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool is_javascript(HTTPExchange * exchange) {
+ const char * header = HTTPExchange_find_response_header(exchange, HTTP_CONTENT_TYPE);
+ if (header == NULL) {
+ /* guess based on extension */
+ return str_ends_with(HTTPExchange_get_request_uri(exchange), ".js");
+ }
+ else {
+ char * semicolon = strchr(header, ';');
+ char * content_type;
+ if (semicolon == NULL) {
+ content_type = xstrdup(header);
+ }
+ else {
+ content_type = xstrndup(header, semicolon - header);
+ }
+ /* RFC 4329 */
+ bool result = strcmp(content_type, "text/javascript") == 0 ||
+ strcmp(content_type, "text/ecmascript") == 0 ||
+ strcmp(content_type, "text/javascript1.0") == 0 ||
+ strcmp(content_type, "text/javascript1.1") == 0 ||
+ strcmp(content_type, "text/javascript1.2") == 0 ||
+ strcmp(content_type, "text/javascript1.3") == 0 ||
+ strcmp(content_type, "text/javascript1.4") == 0 ||
+ strcmp(content_type, "text/javascript1.5") == 0 ||
+ strcmp(content_type, "text/jscript") == 0 ||
+ strcmp(content_type, "text/livescript") == 0 ||
+ strcmp(content_type, "text/x-javascript") == 0 ||
+ strcmp(content_type, "text/x-ecmascript") == 0 ||
+ strcmp(content_type, "application/x-javascript") == 0 ||
+ strcmp(content_type, "application/x-ecmascript") == 0 ||
+ strcmp(content_type, "application/javascript") == 0 ||
+ strcmp(content_type, "application/ecmascript") == 0;
+ free(content_type);
+ return result;
+ }
+}
+
+static bool should_instrument_request(HTTPExchange * exchange) {
+ if (! is_javascript(exchange)) {
+ return false;
+ }
+
+ if (is_no_instrument(HTTPExchange_get_request_uri(exchange))) {
+ return false;
+ }
+
+ return true;
+}
+
+static int merge(Coverage * coverage, FILE * f) __attribute__((warn_unused_result));
+
+static int merge(Coverage * coverage, FILE * f) {
+ Stream * stream = Stream_new(0);
+ Stream_write_file_contents(stream, f);
+
+ LOCK(&javascript_mutex);
+ int result = jscoverage_parse_json(coverage, stream->data, stream->length);
+ UNLOCK(&javascript_mutex);
+
+ Stream_delete(stream);
+ return result;
+}
+
+static void write_js_quoted_string(FILE * f, char * data, size_t length) {
+ putc('"', f);
+ for (size_t i = 0; i < length; i++) {
+ char c = data[i];
+ switch (c) {
+ case '\b':
+ fputs("\\b", f);
+ break;
+ case '\f':
+ fputs("\\f", f);
+ break;
+ case '\n':
+ fputs("\\n", f);
+ break;
+ case '\r':
+ fputs("\\r", f);
+ break;
+ case '\t':
+ fputs("\\t", f);
+ break;
+ /* IE doesn't support this */
+ /*
+ case '\v':
+ fputs("\\v", f);
+ break;
+ */
+ case '"':
+ fputs("\\\"", f);
+ break;
+ case '\\':
+ fputs("\\\\", f);
+ break;
+ default:
+ putc(c, f);
+ break;
+ }
+ }
+ putc('"', f);
+}
+
+static void write_source(const char * id, const uint16_t * characters, size_t num_characters, FILE * f) {
+ Stream * output = Stream_new(num_characters);
+ jscoverage_write_source(id, characters, num_characters, output);
+ fwrite(output->data, 1, output->length, f);
+ Stream_delete(output);
+}
+
+static void write_json_for_file(const FileCoverage * file_coverage, int i, void * p) {
+ FILE * f = p;
+
+ if (i > 0) {
+ putc(',', f);
+ }
+
+ write_js_quoted_string(f, file_coverage->id, strlen(file_coverage->id));
+
+ fputs(":{\"coverage\":[", f);
+ for (uint32_t i = 0; i < file_coverage->num_coverage_lines; i++) {
+ if (i > 0) {
+ putc(',', f);
+ }
+ int timesExecuted = file_coverage->coverage_lines[i];
+ if (timesExecuted < 0) {
+ fputs("null", f);
+ }
+ else {
+ fprintf(f, "%d", timesExecuted);
+ }
+ }
+ fputs("],\"source\":", f);
+ if (file_coverage->source_lines == NULL) {
+ if (proxy) {
+ const SourceCache * cached = find_cached_source(file_coverage->id);
+ if (cached == NULL) {
+ uint16_t * characters;
+ size_t num_characters;
+ if (get(file_coverage->id, &characters, &num_characters) == 0) {
+ write_source(file_coverage->id, characters, num_characters, f);
+ add_cached_source(file_coverage->id, characters, num_characters);
+ }
+ else {
+ fputs("[]", f);
+ HTTPServer_log_err("Warning: cannot retrieve URL: %s\n", file_coverage->id);
+ }
+ }
+ else {
+ write_source(file_coverage->id, cached->characters, cached->num_characters, f);
+ }
+ }
+ else {
+ /* check that the path begins with / */
+ if (file_coverage->id[0] == '/') {
+ char * source_path = make_path(document_root, file_coverage->id + 1);
+ FILE * source_file = fopen(source_path, "rb");
+ free(source_path);
+ if (source_file == NULL) {
+ fputs("[]", f);
+ HTTPServer_log_err("Warning: cannot open file: %s\n", file_coverage->id);
+ }
+ else {
+ Stream * stream = Stream_new(0);
+ Stream_write_file_contents(stream, source_file);
+ fclose(source_file);
+ uint16_t * characters;
+ size_t num_characters;
+ int result = jscoverage_bytes_to_characters(jscoverage_encoding, stream->data, stream->length, &characters, &num_characters);
+ Stream_delete(stream);
+ if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) {
+ fputs("[]", f);
+ HTTPServer_log_err("Warning: encoding %s not supported\n", jscoverage_encoding);
+ }
+ else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) {
+ fputs("[]", f);
+ HTTPServer_log_err("Warning: error decoding %s in file %s\n", jscoverage_encoding, file_coverage->id);
+ }
+ else {
+ write_source(file_coverage->id, characters, num_characters, f);
+ free(characters);
+ }
+ }
+ }
+ else {
+ /* path does not begin with / */
+ fputs("[]", f);
+ HTTPServer_log_err("Warning: invalid source path: %s\n", file_coverage->id);
+ }
+ }
+ }
+ else {
+ fputc('[', f);
+ for (uint32_t i = 0; i < file_coverage->num_source_lines; i++) {
+ if (i > 0) {
+ fputc(',', f);
+ }
+ char * source_line = file_coverage->source_lines[i];
+ write_js_quoted_string(f, source_line, strlen(source_line));
+ }
+ fputc(']', f);
+ }
+ fputc('}', f);
+}
+
+static int write_json(Coverage * coverage, const char * path) __attribute__((warn_unused_result));
+
+static int write_json(Coverage * coverage, const char * path) {
+ /* write the JSON */
+ FILE * f = fopen(path, "wb");
+ if (f == NULL) {
+ return -1;
+ }
+ putc('{', f);
+ Coverage_foreach_file(coverage, write_json_for_file, f);
+ putc('}', f);
+ if (fclose(f) == EOF) {
+ return -1;
+ }
+ return 0;
+}
+
+static void handle_jscoverage_request(HTTPExchange * exchange) {
+ /* set the `Server' response-header (RFC 2616 14.38, 3.8) */
+ HTTPExchange_set_response_header(exchange, HTTP_SERVER, "jscoverage-server/" VERSION);
+
+ const char * abs_path = HTTPExchange_get_abs_path(exchange);
+ assert(*abs_path != '\0');
+ if (str_starts_with(abs_path, "/jscoverage-store")) {
+ if (strcmp(HTTPExchange_get_method(exchange), "POST") != 0) {
+ HTTPExchange_set_response_header(exchange, HTTP_ALLOW, "POST");
+ send_response(exchange, 405, "Method not allowed\n");
+ return;
+ }
+
+ Stream * json = Stream_new(0);
+
+ /* read the POST body */
+ if (HTTPExchange_read_entire_request_entity_body(exchange, json) != 0) {
+ Stream_delete(json);
+ send_response(exchange, 400, "Could not read request body\n");
+ return;
+ }
+
+ Coverage * coverage = Coverage_new();
+ LOCK(&javascript_mutex);
+ int result = jscoverage_parse_json(coverage, json->data, json->length);
+ UNLOCK(&javascript_mutex);
+ Stream_delete(json);
+
+ if (result != 0) {
+ Coverage_delete(coverage);
+ send_response(exchange, 400, "Could not parse coverage data\n");
+ return;
+ }
+
+ mkdir_if_necessary(report_directory);
+ char * current_report_directory;
+ if (str_starts_with(abs_path, "/jscoverage-store/") && abs_path[18] != '\0') {
+ char * dir = decode_uri_component(abs_path + 18);
+ current_report_directory = make_path(report_directory, dir);
+ free(dir);
+ }
+ else {
+ current_report_directory = xstrdup(report_directory);
+ }
+ mkdir_if_necessary(current_report_directory);
+ char * path = make_path(current_report_directory, "jscoverage.json");
+
+ /* check if the JSON file exists */
+ struct stat buf;
+ if (stat(path, &buf) == 0) {
+ /* it exists: merge */
+ FILE * f = fopen(path, "rb");
+ if (f == NULL) {
+ result = 1;
+ }
+ else {
+ result = merge(coverage, f);
+ if (fclose(f) == EOF) {
+ result = 1;
+ }
+ }
+ if (result != 0) {
+ free(current_report_directory);
+ free(path);
+ Coverage_delete(coverage);
+ send_response(exchange, 500, "Could not merge with existing coverage data\n");
+ return;
+ }
+ }
+
+ result = write_json(coverage, path);
+ free(path);
+ Coverage_delete(coverage);
+ if (result != 0) {
+ free(current_report_directory);
+ send_response(exchange, 500, "Could not write coverage data\n");
+ return;
+ }
+
+ /* copy other files */
+ jscoverage_copy_resources(current_report_directory);
+ path = make_path(current_report_directory, "jscoverage.js");
+ free(current_report_directory);
+ FILE * f = fopen(path, "ab");
+ free(path);
+ if (f == NULL) {
+ send_response(exchange, 500, "Could not write to file: jscoverage.js\n");
+ return;
+ }
+ fputs("jscoverage_isReport = true;\r\n", f);
+ if (fclose(f) == EOF) {
+ send_response(exchange, 500, "Could not write to file: jscoverage.js\n");
+ return;
+ }
+
+ send_response(exchange, 200, "Coverage data stored\n");
+ }
+ else if (str_starts_with(abs_path, "/jscoverage-shutdown")) {
+ if (strcmp(HTTPExchange_get_method(exchange), "POST") != 0) {
+ HTTPExchange_set_response_header(exchange, HTTP_ALLOW, "POST");
+ send_response(exchange, 405, "Method not allowed\n");
+ return;
+ }
+
+ /* allow only from localhost */
+ struct sockaddr_in client;
+ if (HTTPExchange_get_peer(exchange, &client) != 0) {
+ send_response(exchange, 500, "Cannot get client address\n");
+ return;
+ }
+ if (client.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
+ send_response(exchange, 403, "This operation can be performed only by localhost\n");
+ return;
+ }
+
+ send_response(exchange, 200, "The server will now shut down\n");
+ HTTPServer_shutdown();
+ }
+ else {
+ const char * path = abs_path + 1;
+ const struct Resource * resource = get_resource(path);
+ if (resource == NULL) {
+ send_response(exchange, 404, "Not found\n");
+ return;
+ }
+ HTTPExchange_set_response_header(exchange, HTTP_CONTENT_TYPE, get_content_type(path));
+ if (HTTPExchange_write_response(exchange, resource->data, resource->length) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ return;
+ }
+ if (strcmp(abs_path, "/jscoverage.js") == 0) {
+ const char * s = "jscoverage_isServer = true;\r\n";
+ if (HTTPExchange_write_response(exchange, s, strlen(s)) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ }
+ }
+}
+
+static void instrument_js(const char * id, const uint16_t * characters, size_t num_characters, Stream * output_stream) {
+ const struct Resource * resource = get_resource("report.js");
+ Stream_write(output_stream, resource->data, resource->length);
+
+ LOCK(&javascript_mutex);
+ jscoverage_instrument_js(id, characters, num_characters, output_stream);
+ UNLOCK(&javascript_mutex);
+}
+
+static bool is_hop_by_hop_header(const char * h) {
+ /* hop-by-hop headers (RFC 2616 13.5.1) */
+ return strcasecmp(h, HTTP_CONNECTION) == 0 ||
+ strcasecmp(h, "Keep-Alive") == 0 ||
+ strcasecmp(h, HTTP_PROXY_AUTHENTICATE) == 0 ||
+ strcasecmp(h, HTTP_PROXY_AUTHORIZATION) == 0 ||
+ strcasecmp(h, HTTP_TE) == 0 ||
+ strcasecmp(h, HTTP_TRAILER) == 0 ||
+ strcasecmp(h, HTTP_TRANSFER_ENCODING) == 0 ||
+ strcasecmp(h, HTTP_UPGRADE) == 0;
+}
+
+static void add_via_header(HTTPMessage * message, const char * version) {
+ char * value;
+ xasprintf(&value, "%s jscoverage-server", version);
+ HTTPMessage_add_header(message, HTTP_VIA, value);
+ free(value);
+}
+
+static int copy_http_message_body(HTTPMessage * from, HTTPMessage * to) __attribute__((warn_unused_result));
+
+static int copy_http_message_body(HTTPMessage * from, HTTPMessage * to) {
+ uint8_t * buffer[8192];
+ for (;;) {
+ size_t bytes_read;
+ int result = HTTPMessage_read_message_body(from, buffer, 8192, &bytes_read);
+ if (result != 0) {
+ return result;
+ }
+ if (bytes_read == 0) {
+ return 0;
+ }
+ result = HTTPMessage_write(to, buffer, bytes_read);
+ if (result != 0) {
+ return result;
+ }
+ }
+}
+
+static void handle_proxy_request(HTTPExchange * client_exchange) {
+ HTTPConnection * server_connection = NULL;
+ HTTPExchange * server_exchange = NULL;
+
+ const char * abs_path = HTTPExchange_get_abs_path(client_exchange);
+ if (str_starts_with(abs_path, "/jscoverage")) {
+ handle_jscoverage_request(client_exchange);
+ return;
+ }
+
+ const char * host = HTTPExchange_get_host(client_exchange);
+ uint16_t port = HTTPExchange_get_port(client_exchange);
+
+ /* create a new connection */
+ server_connection = HTTPConnection_new_client(host, port);
+ if (server_connection == NULL) {
+ send_response(client_exchange, 504, "Could not connect to server\n");
+ goto done;
+ }
+
+ /* create a new exchange */
+ server_exchange = HTTPExchange_new(server_connection);
+ HTTPExchange_set_method(server_exchange, HTTPExchange_get_method(client_exchange));
+ HTTPExchange_set_request_uri(server_exchange, HTTPExchange_get_request_uri(client_exchange));
+ for (const HTTPHeader * h = HTTPExchange_get_request_headers(client_exchange); h != NULL; h = h->next) {
+ if (strcasecmp(h->name, HTTP_TRAILER) == 0 || strcasecmp(h->name, HTTP_TRANSFER_ENCODING) == 0) {
+ /* do nothing: we want to keep this header */
+ }
+ else if (is_hop_by_hop_header(h->name) ||
+ strcasecmp(h->name, HTTP_ACCEPT_ENCODING) == 0 ||
+ strcasecmp(h->name, HTTP_RANGE) == 0) {
+ continue;
+ }
+ HTTPExchange_add_request_header(server_exchange, h->name, h->value);
+ }
+ add_via_header(HTTPExchange_get_request_message(server_exchange), HTTPExchange_get_request_http_version(client_exchange));
+
+ /* send the request */
+ if (HTTPExchange_write_request_headers(server_exchange) != 0) {
+ send_response(client_exchange, 502, "Could not write to server\n");
+ goto done;
+ }
+
+ /* handle POST or PUT */
+ if (HTTPExchange_request_has_body(client_exchange)) {
+ HTTPMessage * client_request = HTTPExchange_get_request_message(client_exchange);
+ HTTPMessage * server_request = HTTPExchange_get_request_message(server_exchange);
+ if (copy_http_message_body(client_request, server_request) != 0) {
+ send_response(client_exchange, 400, "Error copying request body from client to server\n");
+ goto done;
+ }
+ }
+
+ if (HTTPExchange_flush_request(server_exchange) != 0) {
+ send_response(client_exchange, 502, "Could not write to server\n");
+ goto done;
+ }
+
+ /* receive the response */
+ if (HTTPExchange_read_response_headers(server_exchange) != 0) {
+ send_response(client_exchange, 502, "Could not read headers from server\n");
+ goto done;
+ }
+
+ HTTPExchange_set_status_code(client_exchange, HTTPExchange_get_status_code(server_exchange));
+
+ if (HTTPExchange_response_has_body(server_exchange) && should_instrument_request(server_exchange)) {
+ /* needs instrumentation */
+ Stream * input_stream = Stream_new(0);
+ if (HTTPExchange_read_entire_response_entity_body(server_exchange, input_stream) != 0) {
+ Stream_delete(input_stream);
+ send_response(client_exchange, 502, "Could not read body from server\n");
+ goto done;
+ }
+
+ const char * request_uri = HTTPExchange_get_request_uri(client_exchange);
+ char * encoding = HTTPMessage_get_charset(HTTPExchange_get_response_message(server_exchange));
+ if (encoding == NULL) {
+ encoding = xstrdup(jscoverage_encoding);
+ }
+ uint16_t * characters;
+ size_t num_characters;
+ int result = jscoverage_bytes_to_characters(encoding, input_stream->data, input_stream->length, &characters, &num_characters);
+ free(encoding);
+ Stream_delete(input_stream);
+ if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) {
+ send_response(client_exchange, 500, "Encoding not supported\n");
+ goto done;
+ }
+ else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) {
+ send_response(client_exchange, 502, "Error decoding response\n");
+ goto done;
+ }
+
+ Stream * output_stream = Stream_new(0);
+ instrument_js(request_uri, characters, num_characters, output_stream);
+
+ /* send the headers to the client */
+ for (const HTTPHeader * h = HTTPExchange_get_response_headers(server_exchange); h != NULL; h = h->next) {
+ if (is_hop_by_hop_header(h->name) || strcasecmp(h->name, HTTP_CONTENT_LENGTH) == 0) {
+ continue;
+ }
+ else if (strcasecmp(h->name, HTTP_CONTENT_TYPE) == 0) {
+ HTTPExchange_add_response_header(client_exchange, HTTP_CONTENT_TYPE, "text/javascript; charset=ISO-8859-1");
+ continue;
+ }
+ HTTPExchange_add_response_header(client_exchange, h->name, h->value);
+ }
+ add_via_header(HTTPExchange_get_response_message(client_exchange), HTTPExchange_get_response_http_version(server_exchange));
+ HTTPExchange_set_response_content_length(client_exchange, output_stream->length);
+
+ /* send the instrumented code to the client */
+ if (HTTPExchange_write_response(client_exchange, output_stream->data, output_stream->length) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+
+ /* characters go on the cache */
+ /*
+ free(characters);
+ */
+ Stream_delete(output_stream);
+ add_cached_source(request_uri, characters, num_characters);
+ }
+ else {
+ /* does not need instrumentation */
+
+ /* send the headers to the client */
+ for (const HTTPHeader * h = HTTPExchange_get_response_headers(server_exchange); h != NULL; h = h->next) {
+ if (strcasecmp(h->name, HTTP_TRAILER) == 0 || strcasecmp(h->name, HTTP_TRANSFER_ENCODING) == 0) {
+ /* do nothing: we want to keep this header */
+ }
+ else if (is_hop_by_hop_header(h->name)) {
+ continue;
+ }
+ HTTPExchange_add_response_header(client_exchange, h->name, h->value);
+ }
+ add_via_header(HTTPExchange_get_response_message(client_exchange), HTTPExchange_get_response_http_version(server_exchange));
+
+ if (HTTPExchange_write_response_headers(client_exchange) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ goto done;
+ }
+
+ if (HTTPExchange_response_has_body(server_exchange)) {
+ /* read the body from the server and send it to the client */
+ HTTPMessage * client_response = HTTPExchange_get_response_message(client_exchange);
+ HTTPMessage * server_response = HTTPExchange_get_response_message(server_exchange);
+ if (copy_http_message_body(server_response, client_response) != 0) {
+ HTTPServer_log_err("Warning: error copying response body from server to client\n");
+ goto done;
+ }
+ }
+ }
+
+done:
+ if (server_exchange != NULL) {
+ HTTPExchange_delete(server_exchange);
+ }
+ if (server_connection != NULL) {
+ if (HTTPConnection_delete(server_connection) != 0) {
+ HTTPServer_log_err("Warning: error closing connection to server\n");
+ }
+ }
+}
+
+static void handle_local_request(HTTPExchange * exchange) {
+ /* add the `Server' response-header (RFC 2616 14.38, 3.8) */
+ HTTPExchange_add_response_header(exchange, HTTP_SERVER, "jscoverage-server/" VERSION);
+
+ char * decoded_path = NULL;
+ char * filesystem_path = NULL;
+
+ const char * abs_path = HTTPExchange_get_abs_path(exchange);
+ assert(*abs_path != '\0');
+
+ decoded_path = decode_uri_component(abs_path);
+
+ if (str_starts_with(decoded_path, "/jscoverage")) {
+ handle_jscoverage_request(exchange);
+ goto done;
+ }
+
+ if (strstr(decoded_path, "..") != NULL) {
+ send_response(exchange, 403, "Forbidden\n");
+ goto done;
+ }
+
+ filesystem_path = make_path(document_root, decoded_path + 1);
+ size_t filesystem_path_length = strlen(filesystem_path);
+ if (filesystem_path_length > 0 && filesystem_path[filesystem_path_length - 1] == '/') {
+ /* stat on Windows doesn't work with trailing slash */
+ filesystem_path[filesystem_path_length - 1] = '\0';
+ }
+
+ struct stat buf;
+ if (stat(filesystem_path, &buf) == -1) {
+ send_response(exchange, 404, "Not found\n");
+ goto done;
+ }
+
+ if (S_ISDIR(buf.st_mode)) {
+ if (abs_path[strlen(abs_path) - 1] != '/') {
+ const char * request_uri = HTTPExchange_get_request_uri(exchange);
+ char * uri = xmalloc(strlen(request_uri) + 2);
+ strcpy(uri, request_uri);
+ strcat(uri, "/");
+ HTTPExchange_add_response_header(exchange, "Location", uri);
+ free(uri);
+ send_response(exchange, 301, "Moved permanently\n");
+ goto done;
+ }
+
+ DIR * d = opendir(filesystem_path);
+ if (d == NULL) {
+ send_response(exchange, 404, "Not found\n");
+ goto done;
+ }
+
+ struct dirent * entry;
+ while ((entry = readdir(d)) != NULL) {
+ char * href = encode_uri_component(entry->d_name);
+ char * html_href = encode_html(href);
+ char * link = encode_html(entry->d_name);
+ char * directory_entry;
+ xasprintf(&directory_entry, "<a href=\"%s\">%s</a><br>\n", html_href, link);
+ if (HTTPExchange_write_response(exchange, directory_entry, strlen(directory_entry)) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ free(directory_entry);
+ free(href);
+ free(html_href);
+ free(link);
+ }
+ closedir(d);
+ }
+ else if (S_ISREG(buf.st_mode)) {
+ FILE * f = fopen(filesystem_path, "rb");
+ if (f == NULL) {
+ send_response(exchange, 404, "Not found\n");
+ goto done;
+ }
+
+ /*
+ When do we send a charset with Content-Type?
+ if Content-Type is "text" or "application"
+ if instrumented JavaScript
+ use Content-Type: application/javascript; charset=ISO-8859-1
+ else if --encoding is given
+ use that encoding
+ else
+ send no charset
+ else
+ send no charset
+ */
+ const char * content_type = get_content_type(filesystem_path);
+ if (strcmp(content_type, "text/javascript") == 0 && ! is_no_instrument(abs_path)) {
+ HTTPExchange_set_response_header(exchange, HTTP_CONTENT_TYPE, "text/javascript; charset=ISO-8859-1");
+
+ Stream * input_stream = Stream_new(0);
+ Stream_write_file_contents(input_stream, f);
+
+ uint16_t * characters;
+ size_t num_characters;
+ int result = jscoverage_bytes_to_characters(jscoverage_encoding, input_stream->data, input_stream->length, &characters, &num_characters);
+ Stream_delete(input_stream);
+
+ if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) {
+ send_response(exchange, 500, "Encoding not supported\n");
+ goto done;
+ }
+ else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) {
+ send_response(exchange, 500, "Error decoding JavaScript file\n");
+ goto done;
+ }
+
+ Stream * output_stream = Stream_new(0);
+ instrument_js(abs_path, characters, num_characters, output_stream);
+ free(characters);
+
+ if (HTTPExchange_write_response(exchange, output_stream->data, output_stream->length) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ Stream_delete(output_stream);
+ }
+ else {
+ /* send the Content-Type with charset if necessary */
+ if (specified_encoding != NULL && (str_starts_with(content_type, "text/") || str_starts_with(content_type, "application/"))) {
+ char * content_type_with_charset = NULL;
+ xasprintf(&content_type_with_charset, "%s; charset=%s", content_type, specified_encoding);
+ HTTPExchange_set_response_header(exchange, HTTP_CONTENT_TYPE, content_type_with_charset);
+ free(content_type_with_charset);
+ }
+ else {
+ HTTPExchange_set_response_header(exchange, HTTP_CONTENT_TYPE, content_type);
+ }
+
+ char buffer[8192];
+ size_t bytes_read;
+ while ((bytes_read = fread(buffer, 1, 8192, f)) > 0) {
+ if (HTTPExchange_write_response(exchange, buffer, bytes_read) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ }
+ }
+ fclose(f);
+ }
+ else {
+ send_response(exchange, 404, "Not found\n");
+ goto done;
+ }
+
+done:
+ free(filesystem_path);
+ free(decoded_path);
+}
+
+static void handler(HTTPExchange * exchange) {
+ if (verbose) {
+ HTTPServer_log_out("%s", HTTPExchange_get_request_line(exchange));
+ }
+
+ if (proxy) {
+ handle_proxy_request(exchange);
+ }
+ else {
+ handle_local_request(exchange);
+ }
+}
+
+int main(int argc, char ** argv) {
+ program = "jscoverage-server";
+
+ const char * ip_address = "127.0.0.1";
+ const char * port = "8080";
+ int shutdown = 0;
+
+ no_instrument = xnew(const char *, argc - 1);
+
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
+ copy_resource_to_stream("jscoverage-server-help.txt", stdout);
+ exit(EXIT_SUCCESS);
+ }
+ else if (strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "--version") == 0) {
+ version();
+ }
+ else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose = 1;
+ }
+
+ else if (strcmp(argv[i], "--report-dir") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--report-dir: option requires an argument");
+ }
+ report_directory = argv[i];
+ }
+ else if (strncmp(argv[i], "--report-dir=", 13) == 0) {
+ report_directory = argv[i] + 13;
+ }
+
+ else if (strcmp(argv[i], "--document-root") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--document-root: option requires an argument");
+ }
+ document_root = argv[i];
+ }
+ else if (strncmp(argv[i], "--document-root=", 16) == 0) {
+ document_root = argv[i] + 16;
+ }
+
+ else if (strcmp(argv[i], "--encoding") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--encoding: option requires an argument");
+ }
+ jscoverage_encoding = argv[i];
+ specified_encoding = jscoverage_encoding;
+ }
+ else if (strncmp(argv[i], "--encoding=", 11) == 0) {
+ jscoverage_encoding = argv[i] + 11;
+ specified_encoding = jscoverage_encoding;
+ }
+
+ else if (strcmp(argv[i], "--ip-address") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--ip-address: option requires an argument");
+ }
+ ip_address = argv[i];
+ }
+ else if (strncmp(argv[i], "--ip-address=", 13) == 0) {
+ ip_address = argv[i] + 13;
+ }
+
+ else if (strcmp(argv[i], "--js-version") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--js-version: option requires an argument");
+ }
+ jscoverage_set_js_version(argv[i]);
+ }
+ else if (strncmp(argv[i], "--js-version=", 13) == 0) {
+ jscoverage_set_js_version(argv[i] + 13);
+ }
+
+ else if (strcmp(argv[i], "--no-highlight") == 0) {
+ jscoverage_highlight = false;
+ }
+
+ else if (strcmp(argv[i], "--no-instrument") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--no-instrument: option requires an argument");
+ }
+ no_instrument[num_no_instrument] = argv[i];
+ num_no_instrument++;
+ }
+ else if (strncmp(argv[i], "--no-instrument=", 16) == 0) {
+ no_instrument[num_no_instrument] = argv[i] + 16;
+ num_no_instrument++;
+ }
+
+ else if (strcmp(argv[i], "--port") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--port: option requires an argument");
+ }
+ port = argv[i];
+ }
+ else if (strncmp(argv[i], "--port=", 7) == 0) {
+ port = argv[i] + 7;
+ }
+
+ else if (strcmp(argv[i], "--proxy") == 0) {
+ proxy = 1;
+ }
+
+ else if (strcmp(argv[i], "--shutdown") == 0) {
+ shutdown = 1;
+ }
+
+ else if (strncmp(argv[i], "-", 1) == 0) {
+ fatal_command_line("unrecognized option `%s'", argv[i]);
+ }
+ else {
+ fatal_command_line("too many arguments");
+ }
+ }
+
+ /* check the port */
+ char * end;
+ unsigned long numeric_port = strtoul(port, &end, 10);
+ if (*end != '\0') {
+ fatal_command_line("--port: option must be an integer");
+ }
+ if (numeric_port > UINT16_MAX) {
+ fatal_command_line("--port: option must be 16 bits");
+ }
+
+ /* is this a shutdown? */
+ if (shutdown) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ fatal("could not start Winsock");
+ }
+#endif
+
+ /* INADDR_LOOPBACK */
+ HTTPConnection * connection = HTTPConnection_new_client("127.0.0.1", numeric_port);
+ if (connection == NULL) {
+ fatal("could not connect to server");
+ }
+ HTTPExchange * exchange = HTTPExchange_new(connection);
+ HTTPExchange_set_method(exchange, "POST");
+ HTTPExchange_set_request_uri(exchange, "/jscoverage-shutdown");
+ if (HTTPExchange_write_request_headers(exchange) != 0) {
+ fatal("could not write request headers to server");
+ }
+ if (HTTPExchange_read_response_headers(exchange) != 0) {
+ fatal("could not read response headers from server");
+ }
+ Stream * stream = Stream_new(0);
+ if (HTTPExchange_read_entire_response_entity_body(exchange, stream) != 0) {
+ fatal("could not read response body from server");
+ }
+ fwrite(stream->data, 1, stream->length, stdout);
+ Stream_delete(stream);
+ HTTPExchange_delete(exchange);
+ if (HTTPConnection_delete(connection) != 0) {
+ fatal("could not close connection with server");
+ }
+ exit(EXIT_SUCCESS);
+ }
+
+ jscoverage_init();
+
+#ifndef __MINGW32__
+ /* handle broken pipe */
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+#ifdef __MINGW32__
+InitializeCriticalSection(&javascript_mutex);
+InitializeCriticalSection(&source_cache_mutex);
+#endif
+
+ if (verbose) {
+ printf("Starting HTTP server on %s:%lu\n", ip_address, numeric_port);
+ fflush(stdout);
+ }
+ HTTPServer_run(ip_address, (uint16_t) numeric_port, handler);
+ if (verbose) {
+ printf("Stopping HTTP server\n");
+ fflush(stdout);
+ }
+
+ jscoverage_cleanup();
+
+ free(no_instrument);
+
+ LOCK(&source_cache_mutex);
+ while (source_cache != NULL) {
+ SourceCache * p = source_cache;
+ source_cache = source_cache->next;
+ free(p->url);
+ free(p->characters);
+ free(p);
+ }
+ UNLOCK(&source_cache_mutex);
+
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-throbber.gif b/tools/node_modules/expresso/deps/jscoverage/jscoverage-throbber.gif
new file mode 100644
index 0000000..f13c0b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-throbber.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.1 b/tools/node_modules/expresso/deps/jscoverage/jscoverage.1
new file mode 100644
index 0000000..bedc5a7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.1
@@ -0,0 +1,52 @@
+.TH jscoverage 1 local
+.SH NAME
+jscoverage \- Instrument JavaScript with code coverage information
+
+.SH SYNOPSIS
+jscoverage [OPTION] SOURCE-DIRECTORY DESTINATION-DIRECTORY
+
+.SH DESCRIPTION
+
+Copy JavaScript code from SOURCE-DIRECTORY to DESTINATION-DIRECTORY and add code instrumentation.
+
+.SH OPTIONS
+
+.TP
+.B --encoding=ENCODING
+assume .js files use the given character encoding.
+
+.TP
+.B --exclude=PATH
+do not copy
+.B PATH.
+
+.TP
+.B --js-version=VERSION
+use the specified JavaScript version; valid values for
+.B VERSION
+are 1.0, 1.1, 1.2, ..., 1.8, or ECMAv3 (the default).
+
+.TP
+.B --no-highlight
+do not perform syntax highlighting.
+
+.TP
+.B --no-instrument=PATH
+copy but do not instrument
+.B PATH.
+
+.TP
+.B -v, --verbose
+explain what is being done.
+
+.TP
+.B -h, --help
+display this help and exit.
+
+.TP
+.B -V, --version
+display version information and exit.
+.
+.SH AUTHORS
+
+siliconforks.com
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.c b/tools/node_modules/expresso/deps/jscoverage/jscoverage.c
new file mode 100644
index 0000000..f011148
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.c
@@ -0,0 +1,142 @@
+/*
+ jscoverage.c - main routine for `jscoverage' program
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "global.h"
+#include "instrument.h"
+#include "instrument-js.h"
+#include "resource-manager.h"
+#include "util.h"
+
+const char * jscoverage_encoding = "ISO-8859-1";
+bool jscoverage_highlight = true;
+
+int main(int argc, char ** argv) {
+ int verbose = 0;
+
+ // program = argv[0];
+ program = "jscoverage";
+
+ char * source = NULL;
+ char * destination = NULL;
+
+ char ** no_instrument = xnew(char *, argc - 1);
+ int num_no_instrument = 0;
+
+ char ** exclude = xnew(char *, argc - 1);
+ int num_exclude = 0;
+
+ jscoverage_highlight = false;
+
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
+ copy_resource_to_stream("jscoverage-help.txt", stdout);
+ exit(EXIT_SUCCESS);
+ }
+ else if (strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "--version") == 0) {
+ version();
+ }
+ else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose = 1;
+ }
+ else if (strcmp(argv[i], "--mozilla") == 0) {
+ jscoverage_mozilla = true;
+ jscoverage_set_js_version("180");
+ }
+ else if (strcmp(argv[i], "--no-instrument") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--no-instrument: option requires an argument");
+ }
+ no_instrument[num_no_instrument] = argv[i];
+ num_no_instrument++;
+ }
+ else if (strncmp(argv[i], "--no-instrument=", 16) == 0) {
+ no_instrument[num_no_instrument] = argv[i] + 16;
+ num_no_instrument++;
+ }
+ else if (strcmp(argv[i], "--exclude") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--exclude: option requires an argument");
+ }
+ exclude[num_exclude] = argv[i];
+ num_exclude++;
+ }
+ else if (strncmp(argv[i], "--exclude=", 10) == 0) {
+ exclude[num_exclude] = argv[i] + 10;
+ num_exclude++;
+ }
+ else if (strcmp(argv[i], "--encoding") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--encoding: option requires an argument");
+ }
+ jscoverage_encoding = argv[i];
+ }
+ else if (strncmp(argv[i], "--encoding=", 11) == 0) {
+ jscoverage_encoding = argv[i] + 11;
+ }
+ else if (strcmp(argv[i], "--js-version") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--js-version: option requires an argument");
+ }
+ jscoverage_set_js_version(argv[i]);
+ }
+ else if (strncmp(argv[i], "--js-version=", 13) == 0) {
+ jscoverage_set_js_version(argv[i] + 13);
+ }
+ else if (strncmp(argv[i], "-", 1) == 0) {
+ fatal_command_line("unrecognized option `%s'", argv[i]);
+ }
+ else if (source == NULL) {
+ source = argv[i];
+ }
+ else if (destination == NULL) {
+ destination = argv[i];
+ }
+ else {
+ fatal_command_line("too many arguments");
+ }
+ }
+
+ if (source == NULL || destination == NULL) {
+ fatal_command_line("missing argument");
+ }
+
+ source = make_canonical_path(source);
+ destination = make_canonical_path(destination);
+
+ jscoverage_init();
+ jscoverage_instrument(source, destination, verbose, exclude, num_exclude, no_instrument, num_no_instrument);
+ jscoverage_cleanup();
+
+ free(source);
+ free(destination);
+ free(exclude);
+ free(no_instrument);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.css b/tools/node_modules/expresso/deps/jscoverage/jscoverage.css
new file mode 100644
index 0000000..98af69b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.css
@@ -0,0 +1,328 @@
+/*
+ jscoverage.css - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+body {
+ background-color: #bfffbf;
+ font-family: sans-serif;
+ font-size: 100%;
+ margin: 0;
+}
+
+#mainDiv {
+ font-size: 0.8125em;
+}
+
+#headingDiv {
+ position: absolute;
+ top: 0.5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 0;
+ line-height: 1.5em;
+}
+
+h1 {
+ float: left;
+ margin: 0;
+ padding-bottom: 0.5em;
+ font-size: 1.3em;
+}
+
+.ProgressBar {
+ float: left;
+ visibility: hidden;
+}
+
+.ProgressPercentage {
+ display: block;
+ float: left;
+ width: 5em;
+ text-align: right;
+}
+
+.ProgressGraph {
+ float: left;
+ width: 100px;
+ height: 10px;
+ border: 1px solid black;
+ margin-top: 0.3em;
+ background-color: #d4d0c8;
+ overflow: hidden;
+}
+
+.ProgressCovered {
+ /* windows system color ActiveCaption or Highlight */
+ background-color: #0a246a;
+ width: 0;
+ height: 10px;
+ overflow: hidden;
+}
+
+#progressLabel {
+ display: block;
+ float: left;
+ padding-left: 0.3em;
+}
+
+/*******************************************************************************
+browser tab
+*/
+
+input#location, button {
+ border: 1px solid black;
+ margin-left: 1px;
+ margin-right: 1px;
+}
+
+#iframeDiv {
+ position: absolute;
+ top: 3.5em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+}
+
+iframe {
+ width: 100%;
+ height: 100%;
+}
+
+/*******************************************************************************
+summary tab
+*/
+
+#summaryDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#summaryTable {
+ width: 100%;
+ margin-left: 0px;
+ margin-right: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+table#summaryTable th, table#summaryTable td {
+ border-left: 1px solid #d9d9d9;
+}
+
+table#summaryTable th.leftColumn, table#summaryTable td.leftColumn {
+ border-left-width: 0px;
+}
+
+table#summaryTable th, table#summaryTable td {
+ padding: 2px;
+}
+
+th {
+ background-color: #e6ffe6;
+}
+
+td.numeric {
+ text-align: right;
+}
+
+abbr {
+ cursor: help;
+}
+
+tr#summaryTotals td.leftColumn span {
+ float: right;
+}
+tr#summaryTotals td.leftColumn span.title {
+ float: left;
+ font-weight: bold;
+}
+tr#summaryTotals td {
+ background-color: #ffd;
+}
+td.coverage {
+ width: 150px;
+}
+td.coverage span {
+ float: right;
+ margin-right: 5px;
+}
+.pctGraph {
+ width: 100px;
+ height: 10px;
+ float: right;
+ border: 1px solid #000;
+ background-color: #e00000;
+ overflow: hidden;
+ margin-top: 4px;
+}
+.pctGraph .covered {
+ background-color: #00f000;
+ width: 0;
+ height: 10px;
+}
+.pctGraph .skipped {
+ background-color: #d4d0c8;
+ width: 100px;
+ height: 10px;
+}
+tbody#summaryTbody tr.even td {
+ background-color: #e6ffe6;
+}
+
+/*******************************************************************************
+source tab
+*/
+
+#fileDiv {
+ font-size: large;
+ font-weight: bold;
+}
+
+#sourceDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#sourceTable {
+ border: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+/*
+IE default behavior is to make <pre> smaller than surrounding text. Because
+the table already has font-size small, this would make the font-size within the
+<pre> x-small. So we don't rely on the default.
+*/
+table#sourceTable pre {
+ font-size: medium;
+}
+
+table#sourceTable td {
+ border: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+table#sourceTable pre {
+ border: 0px;
+ margin: 0px;
+}
+
+.g {
+ background-color: #bfffbf;
+}
+
+.y {
+ background-color: #ffffbf;
+}
+
+.r {
+ background-color: #ffbfbf;
+}
+
+/*******************************************************************************
+store tab
+*/
+
+#storeDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+/*******************************************************************************
+about tab
+*/
+
+p {
+ margin-top: 0;
+}
+
+/*******************************************************************************
+tabs
+*/
+
+#tabs {
+ position: absolute;
+ top: 3em;
+ left: 1.5em;
+ right: 1.5em;
+ height: 2em;
+}
+
+#tabs div {
+ background-color: white;
+ position: relative;
+ float: left;
+ border: 1px solid black;
+ border-bottom-width: 0;
+ cursor: pointer;
+ margin-left: 0.5em;
+ margin-right: 0.5em;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ height: 2em;
+ z-index: 1;
+ line-height: 1.8em;
+}
+
+#tabs div.selected {
+ z-index: 3;
+ cursor: default;
+}
+
+#tabs div.disabled {
+ /* windows system color GrayText */
+ color: #808080;
+ cursor: default;
+}
+
+.TabPage {
+ background-color: white;
+ border: 1px solid black;
+ position: absolute;
+ top: 5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 1.5em;
+ z-index: 2;
+ padding: 1em;
+ display: none;
+}
+
+#tabPages div.selected {
+ display: block;
+}
+
+img {
+ visibility: hidden;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.html b/tools/node_modules/expresso/deps/jscoverage/jscoverage.html
new file mode 100644
index 0000000..601f62a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<!--
+ jscoverage.html - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
+
+<html>
+<head>
+<title>JSCoverage</title>
+<link rel="stylesheet" type="text/css" href="jscoverage-highlight.css">
+<link rel="stylesheet" type="text/css" href="jscoverage.css">
+<!--[if IE]>
+<link rel="stylesheet" type="text/css" href="jscoverage-ie.css">
+<![endif]-->
+<script type="text/javascript" src="jscoverage.js"></script>
+</head>
+
+<body onload="jscoverage_body_load();" onresize="jscoverage_body_resize();">
+<div id="mainDiv">
+<div id="headingDiv">
+<h1>JSCoverage</h1>
+<div class="ProgressBar" id="progressBar"><span class="ProgressPercentage"></span><div class="ProgressGraph"><div class="ProgressCovered"></div></div></div>
+<span id="progressLabel"></span>
+</div>
+
+<div id="tabs" class="Tabs">
+ <div id="browserTab"><img src="jscoverage-throbber.gif" alt=""> Browser <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="summaryTab"><img id="summaryThrobber" src="jscoverage-throbber.gif" alt=""> Summary <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="sourceTab" class="disabled"><img src="jscoverage-throbber.gif" alt=""> Source <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="storeTab"><img id="storeThrobber" src="jscoverage-throbber.gif" alt=""> Store <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="aboutTab"><img src="jscoverage-throbber.gif" alt=""> About <img src="jscoverage-throbber.gif" alt=""></div>
+</div>
+<div id="tabPages" class="TabPages">
+ <div class="TabPage" id="browserTabPage">
+ <div id="locationDiv">
+ URL: <input id="location" type="text" size="70" onkeypress="jscoverage_input_keypress(event)">
+ <button onclick="jscoverage_button_click();">Go</button>
+ </div>
+ <div id="iframeDiv">
+ <iframe id="browserIframe" onload="jscoverage_browser_load();"></iframe>
+ </div>
+ </div>
+ <div class="TabPage">
+ <input type="checkbox" id="checkbox" onclick="return jscoverage_checkbox_click();"> <label for="checkbox">Show missing statements column</label>
+ <div id="summaryDiv">
+ <div id="summaryErrorDiv"></div>
+ <table id="summaryTable">
+ <thead>
+ <tr id="headerRow">
+ <th class="leftColumn">File</th>
+ <th><abbr title="The total number of executable statements">Statements</abbr></th>
+ <th><abbr title="The number of statements actually executed">Executed</abbr></th>
+ <th><abbr title="Number of executed statements as a percentage of total number of statements">Coverage</abbr></th>
+ </tr>
+ <tr id="summaryTotals">
+ <td class="leftColumn">
+ <span class="title">Total:</span>
+ <span>0</span>
+ </td>
+ <td class="numeric">0</td>
+ <td class="numeric">0</td>
+ <td class="coverage">
+ <div class="pctGraph">
+ <div class="covered"></div>
+ </div>
+ <span class="pct">0%</span>
+ </td>
+ </tr>
+
+ </thead>
+ <tbody id="summaryTbody">
+
+ <!--
+ <tr>
+ <td>0</td>
+ <td>0</td>
+ <td>0</td>
+ <td>0%</td>
+ <td>0</td>
+ </tr>
+ -->
+
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="TabPage">
+ <div id="fileDiv"></div>
+ <div id="sourceDiv"></div>
+ </div>
+ <div class="TabPage" id="storeTabPage">
+ <button id="storeButton" onclick="jscoverage_storeButton_click();">Store Report</button>
+ <img id="storeImg" src="jscoverage-throbber.gif" alt="loading...">
+ <div id="storeDiv"></div>
+ </div>
+ <div class="TabPage">
+ <p>
+ This is version 0.4 of JSCoverage, a program that calculates code
+ coverage statistics for JavaScript.
+ </p>
+ <p>
+ See <a href="http://siliconforks.com/jscoverage/">http://siliconforks.com/jscoverage/</a> for more information.
+ </p>
+ <p>
+ Copyright &copy; 2007, 2008 siliconforks.com
+ </p>
+ </div>
+</div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.js b/tools/node_modules/expresso/deps/jscoverage/jscoverage.js
new file mode 100644
index 0000000..9e2ea5b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.js
@@ -0,0 +1,1024 @@
+/*
+ jscoverage.js - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/**
+Initializes the _$jscoverage object in a window. This should be the first
+function called in the page.
+@param w this should always be the global window object
+*/
+function jscoverage_init(w) {
+ try {
+ // in Safari, "import" is a syntax error
+ Components.utils['import']('resource://gre/modules/jscoverage.jsm');
+ jscoverage_isInvertedMode = true;
+ return;
+ }
+ catch (e) {}
+
+ if (w.opener && w.opener.top._$jscoverage) {
+ // we are in inverted mode
+ jscoverage_isInvertedMode = true;
+ if (! w._$jscoverage) {
+ w._$jscoverage = w.opener.top._$jscoverage;
+ }
+ }
+ else {
+ // we are not in inverted mode
+ jscoverage_isInvertedMode = false;
+ if (! w._$jscoverage) {
+ w._$jscoverage = {};
+ }
+ }
+}
+
+var jscoverage_currentFile = null;
+var jscoverage_currentLine = null;
+
+var jscoverage_inLengthyOperation = false;
+
+/*
+Possible states:
+ isInvertedMode isServer isReport tabs
+normal false false false Browser
+inverted true false false
+server, normal false true false Browser, Store
+server, inverted true true false Store
+report false false true
+*/
+var jscoverage_isInvertedMode = false;
+var jscoverage_isServer = false;
+var jscoverage_isReport = false;
+
+jscoverage_init(window);
+
+function jscoverage_createRequest() {
+ // Note that the IE7 XMLHttpRequest does not support file URL's.
+ // http://xhab.blogspot.com/2006/11/ie7-support-for-xmlhttprequest.html
+ // http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx
+//#JSCOVERAGE_IF
+ if (window.ActiveXObject) {
+ return new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ else {
+ return new XMLHttpRequest();
+ }
+}
+
+// http://www.quirksmode.org/js/findpos.html
+function jscoverage_findPos(obj) {
+ var result = 0;
+ do {
+ result += obj.offsetTop;
+ obj = obj.offsetParent;
+ }
+ while (obj);
+ return result;
+}
+
+// http://www.quirksmode.org/viewport/compatibility.html
+function jscoverage_getViewportHeight() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ if (self.innerHeight) {
+ // all except Explorer
+ return self.innerHeight;
+ }
+ else if (document.documentElement && document.documentElement.clientHeight) {
+ // Explorer 6 Strict Mode
+ return document.documentElement.clientHeight;
+ }
+ else if (document.body) {
+ // other Explorers
+ return document.body.clientHeight;
+ }
+ else {
+ throw "Couldn't calculate viewport height";
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Indicates visually that a lengthy operation has begun. The progress bar is
+displayed, and the cursor is changed to busy (on browsers which support this).
+*/
+function jscoverage_beginLengthyOperation() {
+ jscoverage_inLengthyOperation = true;
+
+ var progressBar = document.getElementById('progressBar');
+ progressBar.style.visibility = 'visible';
+ ProgressBar.setPercentage(progressBar, 0);
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'visible';
+
+ /* blacklist buggy browsers */
+//#JSCOVERAGE_IF
+ if (! /Opera|WebKit/.test(navigator.userAgent)) {
+ /*
+ Change the cursor style of each element. Note that changing the class of the
+ element (to one with a busy cursor) is buggy in IE.
+ */
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = 'wait';
+ }
+ }
+}
+
+/**
+Removes the progress bar and busy cursor.
+*/
+function jscoverage_endLengthyOperation() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 100);
+ setTimeout(function() {
+ jscoverage_inLengthyOperation = false;
+ progressBar.style.visibility = 'hidden';
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'hidden';
+ progressLabel.innerHTML = '';
+
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = '';
+ }
+ }, 50);
+}
+
+function jscoverage_setSize() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ var viewportHeight = jscoverage_getViewportHeight();
+
+ /*
+ border-top-width: 1px
+ padding-top: 10px
+ padding-bottom: 10px
+ border-bottom-width: 1px
+ margin-bottom: 10px
+ ----
+ 32px
+ */
+ var tabPages = document.getElementById('tabPages');
+ var tabPageHeight = (viewportHeight - jscoverage_findPos(tabPages) - 32) + 'px';
+ var nodeList = tabPages.childNodes;
+ var length = nodeList.length;
+ for (var i = 0; i < length; i++) {
+ var node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+ node.style.height = tabPageHeight;
+ }
+
+ var iframeDiv = document.getElementById('iframeDiv');
+ // may not exist if we have removed the first tab
+ if (iframeDiv) {
+ iframeDiv.style.height = (viewportHeight - jscoverage_findPos(iframeDiv) - 21) + 'px';
+ }
+
+ var summaryDiv = document.getElementById('summaryDiv');
+ summaryDiv.style.height = (viewportHeight - jscoverage_findPos(summaryDiv) - 21) + 'px';
+
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.style.height = (viewportHeight - jscoverage_findPos(sourceDiv) - 21) + 'px';
+
+ var storeDiv = document.getElementById('storeDiv');
+ if (storeDiv) {
+ storeDiv.style.height = (viewportHeight - jscoverage_findPos(storeDiv) - 21) + 'px';
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Returns the boolean value of a string. Values 'false', 'f', 'no', 'n', 'off',
+and '0' (upper or lower case) are false.
+@param s the string
+@return a boolean value
+*/
+function jscoverage_getBooleanValue(s) {
+ s = s.toLowerCase();
+ if (s === 'false' || s === 'f' || s === 'no' || s === 'n' || s === 'off' || s === '0') {
+ return false;
+ }
+ return true;
+}
+
+function jscoverage_removeTab(id) {
+ var tab = document.getElementById(id + 'Tab');
+ tab.parentNode.removeChild(tab);
+ var tabPage = document.getElementById(id + 'TabPage');
+ tabPage.parentNode.removeChild(tabPage);
+}
+
+/**
+Initializes the contents of the tabs. This sets the initial values of the
+input field and iframe in the "Browser" tab and the checkbox in the "Summary"
+tab.
+@param queryString this should always be location.search
+*/
+function jscoverage_initTabContents(queryString) {
+ var showMissingColumn = false;
+ var parameters, parameter, i, index, url, name, value;
+ if (queryString.length > 0) {
+ // chop off the question mark
+ queryString = queryString.substring(1);
+ parameters = queryString.split(/&|;/);
+ for (i = 0; i < parameters.length; i++) {
+ parameter = parameters[i];
+ index = parameter.indexOf('=');
+ if (index === -1) {
+ // still works with old syntax
+ url = parameter;
+ }
+ else {
+ name = parameter.substr(0, index);
+ value = parameter.substr(index + 1);
+ if (name === 'missing' || name === 'm') {
+ showMissingColumn = jscoverage_getBooleanValue(value);
+ }
+ else if (name === 'url' || name === 'u') {
+ url = value;
+ }
+ }
+ }
+ }
+
+ var checkbox = document.getElementById('checkbox');
+ checkbox.checked = showMissingColumn;
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+
+ // this will automatically propagate to the input field
+ if (url) {
+ frames[0].location = url;
+ }
+
+ // if the browser tab is absent, we have to initialize the summary tab
+ if (! document.getElementById('browserTab')) {
+ jscoverage_recalculateSummaryTab();
+ }
+}
+
+function jscoverage_body_load() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.init(progressBar);
+
+ function reportError(e) {
+ jscoverage_endLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'hidden';
+ var div = document.getElementById('summaryErrorDiv');
+ div.innerHTML = 'Error: ' + e;
+ }
+
+ if (jscoverage_isReport) {
+ jscoverage_beginLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'visible';
+ var request = jscoverage_createRequest();
+ try {
+ request.open('GET', 'jscoverage.json', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ try {
+ if (request.status !== 0 && request.status !== 200) {
+ throw request.status;
+ }
+ var response = request.responseText;
+ if (response === '') {
+ throw 404;
+ }
+ var json = eval('(' + response + ')');
+ var file;
+ for (file in json) {
+ var fileCoverage = json[file];
+ _$jscoverage[file] = fileCoverage.coverage;
+ _$jscoverage[file].source = fileCoverage.source;
+ }
+ jscoverage_recalculateSummaryTab();
+ summaryThrobber.style.visibility = 'hidden';
+ }
+ catch (e) {
+ reportError(e);
+ }
+ }
+ };
+ request.send(null);
+ }
+ catch (e) {
+ reportError(e);
+ }
+
+ jscoverage_removeTab('browser');
+ jscoverage_removeTab('store');
+ }
+ else {
+ if (jscoverage_isInvertedMode) {
+ jscoverage_removeTab('browser');
+ }
+
+ if (! jscoverage_isServer) {
+ jscoverage_removeTab('store');
+ }
+ }
+
+ jscoverage_initTabControl();
+
+ jscoverage_initTabContents(location.search);
+}
+
+function jscoverage_body_resize() {
+ if (/MSIE/.test(navigator.userAgent)) {
+ jscoverage_setSize();
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 1
+
+function jscoverage_updateBrowser() {
+ var input = document.getElementById("location");
+ frames[0].location = input.value;
+}
+
+function jscoverage_input_keypress(e) {
+ if (e.keyCode === 13) {
+ jscoverage_updateBrowser();
+ }
+}
+
+function jscoverage_button_click() {
+ jscoverage_updateBrowser();
+}
+
+function jscoverage_browser_load() {
+ /* update the input box */
+ var input = document.getElementById("location");
+
+ /* sometimes IE seems to fire this after the tab has been removed */
+ if (input) {
+ input.value = frames[0].location;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 2
+
+function jscoverage_createLink(file, line) {
+ var link = document.createElement("a");
+
+ var url;
+ var call;
+ var text;
+ if (line) {
+ url = file + ".jscoverage.html?" + line;
+ call = "jscoverage_get('" + file + "', " + line + ");";
+ text = line.toString();
+ }
+ else {
+ url = file + ".jscoverage.html";
+ call = "jscoverage_get('" + file + "');";
+ text = file;
+ }
+
+ link.setAttribute('href', 'javascript:' + call);
+ link.appendChild(document.createTextNode(text));
+
+ return link;
+}
+
+function jscoverage_recalculateSummaryTab(cc) {
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+
+ if (! cc) {
+ cc = window._$jscoverage;
+ }
+ if (! cc) {
+//#JSCOVERAGE_IF 0
+ throw "No coverage information found.";
+//#JSCOVERAGE_ENDIF
+ }
+
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+
+ var totals = { files:0, statements:0, executed:0, coverage:0, skipped:0 };
+
+ var file;
+ var files = [];
+ for (file in cc) {
+ files.push(file);
+ }
+ files.sort();
+
+ var rowCounter = 0;
+ for (var f = 0; f < files.length; f++) {
+ file = files[f];
+ var lineNumber;
+ var num_statements = 0;
+ var num_executed = 0;
+ var missing = [];
+ var fileCC = cc[file];
+ var length = fileCC.length;
+ var currentConditionalEnd = 0;
+ var conditionals = null;
+ if (fileCC.conditionals) {
+ conditionals = fileCC.conditionals;
+ }
+ for (lineNumber = 0; lineNumber < length; lineNumber++) {
+ var n = fileCC[lineNumber];
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && conditionals && conditionals[lineNumber]) {
+ currentConditionalEnd = conditionals[lineNumber];
+ }
+
+ if (currentConditionalEnd !== 0) {
+ continue;
+ }
+
+ if (n === undefined || n === null) {
+ continue;
+ }
+
+ if (n === 0) {
+ missing.push(lineNumber);
+ }
+ else {
+ num_executed++;
+ }
+ num_statements++;
+ }
+
+ var percentage = ( num_statements === 0 ? 0 : parseInt(100 * num_executed / num_statements) );
+
+ var row = document.createElement("tr");
+ row.className = ( rowCounter++ % 2 == 0 ? "odd" : "even" );
+
+ var cell = document.createElement("td");
+ cell.className = 'leftColumn';
+ var link = jscoverage_createLink(file);
+ cell.appendChild(link);
+
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_statements));
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_executed));
+ row.appendChild(cell);
+
+ // new coverage td containing a bar graph
+ cell = document.createElement("td");
+ cell.className = 'coverage';
+ var pctGraph = document.createElement("div"),
+ covered = document.createElement("div"),
+ pct = document.createElement("span");
+ pctGraph.className = "pctGraph";
+ if( num_statements === 0 ) {
+ covered.className = "skipped";
+ pct.appendChild(document.createTextNode("N/A"));
+ } else {
+ covered.className = "covered";
+ covered.style.width = percentage + "px";
+ pct.appendChild(document.createTextNode(percentage + '%'));
+ }
+ pct.className = "pct";
+ pctGraph.appendChild(covered);
+ cell.appendChild(pctGraph);
+ cell.appendChild(pct);
+ row.appendChild(cell);
+
+ if (showMissingColumn) {
+ cell = document.createElement("td");
+ for (var i = 0; i < missing.length; i++) {
+ if (i !== 0) {
+ cell.appendChild(document.createTextNode(", "));
+ }
+ link = jscoverage_createLink(file, missing[i]);
+ cell.appendChild(link);
+ }
+ row.appendChild(cell);
+ }
+
+ tbody.appendChild(row);
+
+ totals['files'] ++;
+ totals['statements'] += num_statements;
+ totals['executed'] += num_executed;
+ totals['coverage'] += percentage;
+ if( num_statements === 0 ) {
+ totals['skipped']++;
+ }
+
+ // write totals data into summaryTotals row
+ var tr = document.getElementById("summaryTotals");
+ if (tr) {
+ var tds = tr.getElementsByTagName("td");
+ tds[0].getElementsByTagName("span")[1].firstChild.nodeValue = totals['files'];
+ tds[1].firstChild.nodeValue = totals['statements'];
+ tds[2].firstChild.nodeValue = totals['executed'];
+
+ var coverage = parseInt(totals['coverage'] / ( totals['files'] - totals['skipped'] ) );
+ if( isNaN( coverage ) ) {
+ coverage = 0;
+ }
+ tds[3].getElementsByTagName("span")[0].firstChild.nodeValue = coverage + '%';
+ tds[3].getElementsByTagName("div")[1].style.width = coverage + 'px';
+ }
+
+ }
+ jscoverage_endLengthyOperation();
+}
+
+function jscoverage_appendMissingColumn() {
+ var headerRow = document.getElementById('headerRow');
+ var missingHeader = document.createElement('th');
+ missingHeader.id = 'missingHeader';
+ missingHeader.innerHTML = '<abbr title="List of statements missed during execution">Missing</abbr>';
+ headerRow.appendChild(missingHeader);
+ var summaryTotals = document.getElementById('summaryTotals');
+ var empty = document.createElement('td');
+ empty.id = 'missingCell';
+ summaryTotals.appendChild(empty);
+}
+
+function jscoverage_removeMissingColumn() {
+ var missingNode;
+ missingNode = document.getElementById('missingHeader');
+ missingNode.parentNode.removeChild(missingNode);
+ missingNode = document.getElementById('missingCell');
+ missingNode.parentNode.removeChild(missingNode);
+}
+
+function jscoverage_checkbox_click() {
+ if (jscoverage_inLengthyOperation) {
+ return false;
+ }
+ jscoverage_beginLengthyOperation();
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+ setTimeout(function() {
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+ else {
+ jscoverage_removeMissingColumn();
+ }
+ jscoverage_recalculateSummaryTab();
+ }, 50);
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+// tab 3
+
+function jscoverage_makeTable() {
+ var coverage = _$jscoverage[jscoverage_currentFile];
+ var lines = coverage.source;
+
+ // this can happen if there is an error in the original JavaScript file
+ if (! lines) {
+ lines = [];
+ }
+
+ var rows = ['<table id="sourceTable">'];
+ var i = 0;
+ var progressBar = document.getElementById('progressBar');
+ var tableHTML;
+ var currentConditionalEnd = 0;
+
+ function joinTableRows() {
+ tableHTML = rows.join('');
+ ProgressBar.setPercentage(progressBar, 60);
+ /*
+ This may be a long delay, so set a timeout of 100 ms to make sure the
+ display is updated.
+ */
+ setTimeout(appendTable, 100);
+ }
+
+ function appendTable() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = tableHTML;
+ ProgressBar.setPercentage(progressBar, 80);
+ setTimeout(jscoverage_scrollToLine, 0);
+ }
+
+ while (i < lines.length) {
+ var lineNumber = i + 1;
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && coverage.conditionals && coverage.conditionals[lineNumber]) {
+ currentConditionalEnd = coverage.conditionals[lineNumber];
+ }
+
+ var row = '<tr>';
+ row += '<td class="numeric">' + lineNumber + '</td>';
+ var timesExecuted = coverage[lineNumber];
+ if (timesExecuted !== undefined && timesExecuted !== null) {
+ if (currentConditionalEnd !== 0) {
+ row += '<td class="y numeric">';
+ }
+ else if (timesExecuted === 0) {
+ row += '<td class="r numeric" id="line-' + lineNumber + '">';
+ }
+ else {
+ row += '<td class="g numeric">';
+ }
+ row += timesExecuted;
+ row += '</td>';
+ }
+ else {
+ row += '<td></td>';
+ }
+ row += '<td><pre>' + lines[i] + '</pre></td>';
+ row += '</tr>';
+ row += '\n';
+ rows[lineNumber] = row;
+ i++;
+ }
+ rows[i + 1] = '</table>';
+ ProgressBar.setPercentage(progressBar, 40);
+ setTimeout(joinTableRows, 0);
+}
+
+function jscoverage_scrollToLine() {
+ jscoverage_selectTab('sourceTab');
+ if (! window.jscoverage_currentLine) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var div = document.getElementById('sourceDiv');
+ if (jscoverage_currentLine === 1) {
+ div.scrollTop = 0;
+ }
+ else {
+ var cell = document.getElementById('line-' + jscoverage_currentLine);
+
+ // this might not be there if there is an error in the original JavaScript
+ if (cell) {
+ var divOffset = jscoverage_findPos(div);
+ var cellOffset = jscoverage_findPos(cell);
+ div.scrollTop = cellOffset - divOffset;
+ }
+ }
+ jscoverage_currentLine = 0;
+ jscoverage_endLengthyOperation();
+}
+
+/**
+Loads the given file (and optional line) in the source tab.
+*/
+function jscoverage_get(file, line) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ jscoverage_selectTab('sourceTab');
+ if (file === jscoverage_currentFile) {
+ jscoverage_currentLine = line;
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ if (jscoverage_currentFile === null) {
+ var tab = document.getElementById('sourceTab');
+ tab.className = '';
+ tab.onclick = jscoverage_tab_click;
+ }
+ jscoverage_currentFile = file;
+ jscoverage_currentLine = line || 1; // when changing the source, always scroll to top
+ var fileDiv = document.getElementById('fileDiv');
+ fileDiv.innerHTML = jscoverage_currentFile;
+ jscoverage_recalculateSourceTab();
+ return;
+ }
+ }, 50);
+}
+
+/**
+Calculates coverage statistics for the current source file.
+*/
+function jscoverage_recalculateSourceTab() {
+ if (! jscoverage_currentFile) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.innerHTML = 'Calculating coverage ...';
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 20);
+ setTimeout(jscoverage_makeTable, 0);
+}
+
+// -----------------------------------------------------------------------------
+// tabs
+
+/**
+Initializes the tab control. This function must be called when the document is
+loaded.
+*/
+function jscoverage_initTabControl() {
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child.className !== 'disabled') {
+ child.onclick = jscoverage_tab_click;
+ }
+ tabNum++;
+ }
+ }
+ jscoverage_selectTab(0);
+}
+
+/**
+Selects a tab.
+@param tab the integer index of the tab (0, 1, 2, or 3)
+ OR
+ the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_selectTab(tab) {
+ if (typeof tab !== 'number') {
+ tab = jscoverage_tabIndexOf(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var tabPages = document.getElementById('tabPages');
+ var nodeList;
+ var tabNum;
+ var i;
+ var node;
+
+ nodeList = tabs.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (node.className !== 'disabled') {
+ if (tabNum === tab) {
+ node.className = 'selected';
+ }
+ else {
+ node.className = '';
+ }
+ }
+ tabNum++;
+ }
+
+ nodeList = tabPages.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (tabNum === tab) {
+ node.className = 'selected TabPage';
+ }
+ else {
+ node.className = 'TabPage';
+ }
+ tabNum++;
+ }
+}
+
+/**
+Returns an integer (0, 1, 2, or 3) representing the index of a given tab.
+@param tab the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_tabIndexOf(tab) {
+ if (typeof tab === 'string') {
+ tab = document.getElementById(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child === tab) {
+ return tabNum;
+ }
+ tabNum++;
+ }
+ }
+//#JSCOVERAGE_IF 0
+ throw "Tab not found";
+//#JSCOVERAGE_ENDIF
+}
+
+function jscoverage_tab_click(e) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ var target;
+//#JSCOVERAGE_IF
+ if (e) {
+ target = e.target;
+ }
+ else if (window.event) {
+ // IE
+ target = window.event.srcElement;
+ }
+ if (target.className === 'selected') {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ if (target.id === 'summaryTab') {
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+ }
+ else if (target.id === 'sourceTab') {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ }
+ jscoverage_selectTab(target);
+ if (target.id === 'summaryTab') {
+ jscoverage_recalculateSummaryTab();
+ }
+ else if (target.id === 'sourceTab') {
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ jscoverage_endLengthyOperation();
+ }
+ }, 50);
+}
+
+// -----------------------------------------------------------------------------
+// progress bar
+
+var ProgressBar = {
+ init: function(element) {
+ element._percentage = 0;
+
+ /* doing this via JavaScript crashes Safari */
+/*
+ var pctGraph = document.createElement('div');
+ pctGraph.className = 'pctGraph';
+ element.appendChild(pctGraph);
+ var covered = document.createElement('div');
+ covered.className = 'covered';
+ pctGraph.appendChild(covered);
+ var pct = document.createElement('span');
+ pct.className = 'pct';
+ element.appendChild(pct);
+*/
+
+ ProgressBar._update(element);
+ },
+ setPercentage: function(element, percentage) {
+ element._percentage = percentage;
+ ProgressBar._update(element);
+ },
+ _update: function(element) {
+ var pctGraph = element.getElementsByTagName('div').item(0);
+ var covered = pctGraph.getElementsByTagName('div').item(0);
+ var pct = element.getElementsByTagName('span').item(0);
+ pct.innerHTML = element._percentage.toString() + '%';
+ covered.style.width = element._percentage + 'px';
+ }
+};
+
+// -----------------------------------------------------------------------------
+// reports
+
+function jscoverage_pad(s) {
+ return '0000'.substr(s.length) + s;
+}
+
+function jscoverage_quote(s) {
+ return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) {
+ switch (c) {
+ case '\b':
+ return '\\b';
+ case '\f':
+ return '\\f';
+ case '\n':
+ return '\\n';
+ case '\r':
+ return '\\r';
+ case '\t':
+ return '\\t';
+ // IE doesn't support this
+ /*
+ case '\v':
+ return '\\v';
+ */
+ case '"':
+ return '\\"';
+ case '\\':
+ return '\\\\';
+ default:
+ return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16));
+ }
+ }) + '"';
+}
+
+function jscoverage_serializeCoverageToJSON() {
+ var json = [];
+ for (var file in _$jscoverage) {
+ var coverage = _$jscoverage[file];
+ var array = [];
+ var length = coverage.length;
+ for (var line = 0; line < length; line++) {
+ var value = coverage[line];
+ if (value === undefined || value === null) {
+ value = 'null';
+ }
+ array.push(value);
+ }
+ json.push(jscoverage_quote(file) + ':[' + array.join(',') + ']');
+ }
+ return '{' + json.join(',') + '}';
+}
+
+function jscoverage_storeButton_click() {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+
+ jscoverage_beginLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'visible';
+
+ var request = jscoverage_createRequest();
+ request.open('POST', '/jscoverage-store', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ var message;
+ try {
+ if (request.status !== 200 && request.status !== 201 && request.status !== 204) {
+ throw request.status;
+ }
+ message = request.responseText;
+ }
+ catch (e) {
+ if (e.toString().search(/^\d{3}$/) === 0) {
+ message = e + ': ' + request.responseText;
+ }
+ else {
+ message = 'Could not connect to server: ' + e;
+ }
+ }
+
+ jscoverage_endLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'hidden';
+
+ var div = document.getElementById('storeDiv');
+ div.appendChild(document.createTextNode(new Date() + ': ' + message));
+ div.appendChild(document.createElement('br'));
+ }
+ };
+ request.setRequestHeader('Content-Type', 'application/json');
+ var json = jscoverage_serializeCoverageToJSON();
+ request.setRequestHeader('Content-Length', json.length.toString());
+ request.send(json);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.jsm b/tools/node_modules/expresso/deps/jscoverage/jscoverage.jsm
new file mode 100644
index 0000000..053691c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.jsm
@@ -0,0 +1,22 @@
+/*
+ jscoverage.jsm - Firefox module
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+var EXPORTED_SYMBOLS = ['_$jscoverage'];
+
+var _$jscoverage = {};
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.manifest b/tools/node_modules/expresso/deps/jscoverage/jscoverage.manifest
new file mode 100644
index 0000000..a0f3d9f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.manifest
@@ -0,0 +1,2 @@
+content jscoverage jscoverage/
+overlay chrome://browser/content/browser.xul chrome://jscoverage/content/jscoverage.xul
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.xul b/tools/node_modules/expresso/deps/jscoverage/jscoverage.xul
new file mode 100644
index 0000000..c7296b2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+ jscoverage.xul - XUL overlay
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
+
+<overlay id="jscoverageOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="jscoverage-overlay.js"></script>
+ <commandset>
+ <command id="jscoverageViewCommand" oncommand="jscoverage_view();"/>
+ <command id="jscoverageStoreCommand" oncommand="jscoverage_store();"/>
+ </commandset>
+ <menupopup id="menu_ToolsPopup">
+ <menu label="JSCoverage" insertafter="javascriptConsole,devToolsSeparator">
+ <menupopup>
+ <menuitem label="View Coverage" command="jscoverageViewCommand"/>
+ <menuitem label="Store Coverage" command="jscoverageStoreCommand"/>
+ </menupopup>
+ </menu>
+ </menupopup>
+</overlay>
diff --git a/tools/node_modules/expresso/deps/jscoverage/m4/iconv.m4 b/tools/node_modules/expresso/deps/jscoverage/m4/iconv.m4
new file mode 100644
index 0000000..66bc76f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/m4/iconv.m4
@@ -0,0 +1,180 @@
+# iconv.m4 serial AM6 (gettext-0.17)
+dnl Copyright (C) 2000-2002, 2007 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
+[
+ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+
+ dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+ dnl accordingly.
+ AC_LIB_LINKFLAGS_BODY([iconv])
+])
+
+AC_DEFUN([AM_ICONV_LINK],
+[
+ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
+ dnl those with the standalone portable GNU libiconv installed).
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+ dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+ dnl accordingly.
+ AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
+
+ dnl Add $INCICONV to CPPFLAGS before performing the following checks,
+ dnl because if the user has installed libiconv and not disabled its use
+ dnl via --without-libiconv-prefix, he wants to use it. The first
+ dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed.
+ am_save_CPPFLAGS="$CPPFLAGS"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
+
+ AC_CACHE_CHECK([for iconv], am_cv_func_iconv, [
+ am_cv_func_iconv="no, consider installing GNU libiconv"
+ am_cv_lib_iconv=no
+ AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+ [iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);],
+ am_cv_func_iconv=yes)
+ if test "$am_cv_func_iconv" != yes; then
+ am_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBICONV"
+ AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+ [iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);],
+ am_cv_lib_iconv=yes
+ am_cv_func_iconv=yes)
+ LIBS="$am_save_LIBS"
+ fi
+ ])
+ if test "$am_cv_func_iconv" = yes; then
+ AC_CACHE_CHECK([for working iconv], am_cv_func_iconv_works, [
+ dnl This tests against bugs in AIX 5.1 and HP-UX 11.11.
+ am_save_LIBS="$LIBS"
+ if test $am_cv_lib_iconv = yes; then
+ LIBS="$LIBS $LIBICONV"
+ fi
+ AC_TRY_RUN([
+#include <iconv.h>
+#include <string.h>
+int main ()
+{
+ /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
+ returns. */
+ {
+ iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
+ if (cd_utf8_to_88591 != (iconv_t)(-1))
+ {
+ static const char input[] = "\342\202\254"; /* EURO SIGN */
+ char buf[10];
+ const char *inptr = input;
+ size_t inbytesleft = strlen (input);
+ char *outptr = buf;
+ size_t outbytesleft = sizeof (buf);
+ size_t res = iconv (cd_utf8_to_88591,
+ (char **) &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if (res == 0)
+ return 1;
+ }
+ }
+#if 0 /* This bug could be worked around by the caller. */
+ /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */
+ {
+ iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
+ if (cd_88591_to_utf8 != (iconv_t)(-1))
+ {
+ static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
+ char buf[50];
+ const char *inptr = input;
+ size_t inbytesleft = strlen (input);
+ char *outptr = buf;
+ size_t outbytesleft = sizeof (buf);
+ size_t res = iconv (cd_88591_to_utf8,
+ (char **) &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if ((int)res > 0)
+ return 1;
+ }
+ }
+#endif
+ /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
+ provided. */
+ if (/* Try standardized names. */
+ iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
+ /* Try IRIX, OSF/1 names. */
+ && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
+ /* Try AIX names. */
+ && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
+ /* Try HP-UX names. */
+ && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
+ return 1;
+ return 0;
+}], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no],
+ [case "$host_os" in
+ aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
+ *) am_cv_func_iconv_works="guessing yes" ;;
+ esac])
+ LIBS="$am_save_LIBS"
+ ])
+ case "$am_cv_func_iconv_works" in
+ *no) am_func_iconv=no am_cv_lib_iconv=no ;;
+ *) am_func_iconv=yes ;;
+ esac
+ else
+ am_func_iconv=no am_cv_lib_iconv=no
+ fi
+ if test "$am_func_iconv" = yes; then
+ AC_DEFINE(HAVE_ICONV, 1,
+ [Define if you have the iconv() function and it works.])
+ fi
+ if test "$am_cv_lib_iconv" = yes; then
+ AC_MSG_CHECKING([how to link with libiconv])
+ AC_MSG_RESULT([$LIBICONV])
+ else
+ dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
+ dnl either.
+ CPPFLAGS="$am_save_CPPFLAGS"
+ LIBICONV=
+ LTLIBICONV=
+ fi
+ AC_SUBST(LIBICONV)
+ AC_SUBST(LTLIBICONV)
+])
+
+AC_DEFUN([AM_ICONV],
+[
+ AM_ICONV_LINK
+ if test "$am_cv_func_iconv" = yes; then
+ AC_MSG_CHECKING([for iconv declaration])
+ AC_CACHE_VAL(am_cv_proto_iconv, [
+ AC_TRY_COMPILE([
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
+ am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+ am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+ AC_MSG_RESULT([$]{ac_t:-
+ }[$]am_cv_proto_iconv)
+ AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
+ [Define as const if the declaration of iconv() needs const.])
+ fi
+])
diff --git a/tools/node_modules/expresso/deps/jscoverage/m4/lib-ld.m4 b/tools/node_modules/expresso/deps/jscoverage/m4/lib-ld.m4
new file mode 100644
index 0000000..96c4e2c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/m4/lib-ld.m4
@@ -0,0 +1,110 @@
+# lib-ld.m4 serial 3 (gettext-0.13)
+dnl Copyright (C) 1996-2003 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Subroutines of libtool.m4,
+dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
+dnl with libtool.m4.
+
+dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
+AC_DEFUN([AC_LIB_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ acl_cv_prog_gnu_ld=yes ;;
+*)
+ acl_cv_prog_gnu_ld=no ;;
+esac])
+with_gnu_ld=$acl_cv_prog_gnu_ld
+])
+
+dnl From libtool-1.4. Sets the variable LD.
+AC_DEFUN([AC_LIB_PROG_LD],
+[AC_ARG_WITH(gnu-ld,
+[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by GCC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]* | [A-Za-z]:[\\/]*)]
+ [re_direlt='/[^/][^/]*/\.\./']
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(acl_cv_path_LD,
+[if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ acl_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break ;;
+ *)
+ test "$with_gnu_ld" != yes && break ;;
+ esac
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_LIB_PROG_LD_GNU
+])
diff --git a/tools/node_modules/expresso/deps/jscoverage/m4/lib-link.m4 b/tools/node_modules/expresso/deps/jscoverage/m4/lib-link.m4
new file mode 100644
index 0000000..e3d26fc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/m4/lib-link.m4
@@ -0,0 +1,709 @@
+# lib-link.m4 serial 13 (gettext-0.17)
+dnl Copyright (C) 2001-2007 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_PREREQ(2.54)
+
+dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
+dnl augments the CPPFLAGS variable.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+ define([Name],[translit([$1],[./-], [___])])
+ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
+ AC_LIB_LINKFLAGS_BODY([$1], [$2])
+ ac_cv_lib[]Name[]_libs="$LIB[]NAME"
+ ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
+ ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
+ ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
+ ])
+ LIB[]NAME="$ac_cv_lib[]Name[]_libs"
+ LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
+ INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
+ LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+ AC_SUBST([LIB]NAME)
+ AC_SUBST([LTLIB]NAME)
+ AC_SUBST([LIB]NAME[_PREFIX])
+ dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
+ dnl results of this search when this library appears as a dependency.
+ HAVE_LIB[]NAME=yes
+ undefine([Name])
+ undefine([NAME])
+])
+
+dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode)
+dnl searches for libname and the libraries corresponding to explicit and
+dnl implicit dependencies, together with the specified include files and
+dnl the ability to compile and link the specified testcode. If found, it
+dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and
+dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and
+dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
+dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+ define([Name],[translit([$1],[./-], [___])])
+ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+
+ dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
+ dnl accordingly.
+ AC_LIB_LINKFLAGS_BODY([$1], [$2])
+
+ dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
+ dnl because if the user has installed lib[]Name and not disabled its use
+ dnl via --without-lib[]Name-prefix, he wants to use it.
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+
+ AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
+ ac_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIB[]NAME"
+ AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no])
+ LIBS="$ac_save_LIBS"
+ ])
+ if test "$ac_cv_lib[]Name" = yes; then
+ HAVE_LIB[]NAME=yes
+ AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.])
+ AC_MSG_CHECKING([how to link with lib[]$1])
+ AC_MSG_RESULT([$LIB[]NAME])
+ else
+ HAVE_LIB[]NAME=no
+ dnl If $LIB[]NAME didn't lead to a usable library, we don't need
+ dnl $INC[]NAME either.
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIB[]NAME=
+ LTLIB[]NAME=
+ LIB[]NAME[]_PREFIX=
+ fi
+ AC_SUBST([HAVE_LIB]NAME)
+ AC_SUBST([LIB]NAME)
+ AC_SUBST([LTLIB]NAME)
+ AC_SUBST([LIB]NAME[_PREFIX])
+ undefine([Name])
+ undefine([NAME])
+])
+
+dnl Determine the platform dependent parameters needed to use rpath:
+dnl acl_libext,
+dnl acl_shlibext,
+dnl acl_hardcode_libdir_flag_spec,
+dnl acl_hardcode_libdir_separator,
+dnl acl_hardcode_direct,
+dnl acl_hardcode_minus_L.
+AC_DEFUN([AC_LIB_RPATH],
+[
+ dnl Tell automake >= 1.10 to complain if config.rpath is missing.
+ m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
+ AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS
+ AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
+ AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
+ AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [
+ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+ . ./conftest.sh
+ rm -f ./conftest.sh
+ acl_cv_rpath=done
+ ])
+ wl="$acl_cv_wl"
+ acl_libext="$acl_cv_libext"
+ acl_shlibext="$acl_cv_shlibext"
+ acl_libname_spec="$acl_cv_libname_spec"
+ acl_library_names_spec="$acl_cv_library_names_spec"
+ acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+ acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+ acl_hardcode_direct="$acl_cv_hardcode_direct"
+ acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
+ dnl Determine whether the user wants rpath handling at all.
+ AC_ARG_ENABLE(rpath,
+ [ --disable-rpath do not hardcode runtime library paths],
+ :, enable_rpath=yes)
+])
+
+dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
+dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
+dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ dnl Autoconf >= 2.61 supports dots in --with options.
+ define([N_A_M_E],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit([$1],[.],[_])],[$1])])
+ dnl By default, look in $includedir and $libdir.
+ use_additional=yes
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ AC_LIB_ARG_WITH([lib]N_A_M_E[-prefix],
+[ --with-lib]N_A_M_E[-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib
+ --without-lib]N_A_M_E[-prefix don't search for lib$1 in includedir and libdir],
+[
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/$acl_libdirstem"
+ fi
+ fi
+])
+ dnl Search the library and its dependencies in $additional_libdir and
+ dnl $LDFLAGS. Using breadth-first-seach.
+ LIB[]NAME=
+ LTLIB[]NAME=
+ INC[]NAME=
+ LIB[]NAME[]_PREFIX=
+ rpathdirs=
+ ltrpathdirs=
+ names_already_handled=
+ names_next_round='$1 $2'
+ while test -n "$names_next_round"; do
+ names_this_round="$names_next_round"
+ names_next_round=
+ for name in $names_this_round; do
+ already_handled=
+ for n in $names_already_handled; do
+ if test "$n" = "$name"; then
+ already_handled=yes
+ break
+ fi
+ done
+ if test -z "$already_handled"; then
+ names_already_handled="$names_already_handled $name"
+ dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
+ dnl or AC_LIB_HAVE_LINKFLAGS call.
+ uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+ eval value=\"\$HAVE_LIB$uppername\"
+ if test -n "$value"; then
+ if test "$value" = yes; then
+ eval value=\"\$LIB$uppername\"
+ test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
+ eval value=\"\$LTLIB$uppername\"
+ test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
+ else
+ dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
+ dnl that this library doesn't exist. So just drop it.
+ :
+ fi
+ else
+ dnl Search the library lib$name in $additional_libdir and $LDFLAGS
+ dnl and the already constructed $LIBNAME/$LTLIBNAME.
+ found_dir=
+ found_la=
+ found_so=
+ found_a=
+ eval libname=\"$acl_libname_spec\" # typically: libname=lib$name
+ if test -n "$acl_shlibext"; then
+ shrext=".$acl_shlibext" # typically: shrext=.so
+ else
+ shrext=
+ fi
+ if test $use_additional = yes; then
+ dir="$additional_libdir"
+ dnl The same code as in the loop below:
+ dnl First look for a shared library.
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ dnl Then look for a static library.
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ for x in $LDFLAGS $LTLIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ case "$x" in
+ -L*)
+ dir=`echo "X$x" | sed -e 's/^X-L//'`
+ dnl First look for a shared library.
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ dnl Then look for a static library.
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ ;;
+ esac
+ if test "X$found_dir" != "X"; then
+ break
+ fi
+ done
+ fi
+ if test "X$found_dir" != "X"; then
+ dnl Found the library.
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
+ if test "X$found_so" != "X"; then
+ dnl Linking with a shared library. We attempt to hardcode its
+ dnl directory into the executable's runpath, unless it's the
+ dnl standard /usr/lib.
+ if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then
+ dnl No hardcoding is needed.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ dnl Use an explicit option to hardcode DIR into the resulting
+ dnl binary.
+ dnl Potentially add DIR to ltrpathdirs.
+ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $found_dir"
+ fi
+ dnl The hardcoding into $LIBNAME is system dependent.
+ if test "$acl_hardcode_direct" = yes; then
+ dnl Using DIR/libNAME.so during linking hardcodes DIR into the
+ dnl resulting binary.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+ dnl Use an explicit option to hardcode DIR into the resulting
+ dnl binary.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ dnl Potentially add DIR to rpathdirs.
+ dnl The rpathdirs will be appended to $LIBNAME at the end.
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $found_dir"
+ fi
+ else
+ dnl Rely on "-L$found_dir".
+ dnl But don't add it if it's already contained in the LDFLAGS
+ dnl or the already constructed $LIBNAME
+ haveit=
+ for x in $LDFLAGS $LIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
+ fi
+ if test "$acl_hardcode_minus_L" != no; then
+ dnl FIXME: Not sure whether we should use
+ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+ dnl here.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH
+ dnl here, because this doesn't fit in flags passed to the
+ dnl compiler. So give up. No hardcoding. This affects only
+ dnl very old systems.
+ dnl FIXME: Not sure whether we should use
+ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+ dnl here.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+ fi
+ fi
+ fi
+ fi
+ else
+ if test "X$found_a" != "X"; then
+ dnl Linking with a static library.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
+ else
+ dnl We shouldn't come here, but anyway it's good to have a
+ dnl fallback.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
+ fi
+ fi
+ dnl Assume the include files are nearby.
+ additional_includedir=
+ case "$found_dir" in
+ */$acl_libdirstem | */$acl_libdirstem/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
+ LIB[]NAME[]_PREFIX="$basedir"
+ additional_includedir="$basedir/include"
+ ;;
+ esac
+ if test "X$additional_includedir" != "X"; then
+ dnl Potentially add $additional_includedir to $INCNAME.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/include,
+ dnl 2. if it's /usr/local/include and we are using GCC on Linux,
+ dnl 3. if it's already present in $CPPFLAGS or the already
+ dnl constructed $INCNAME,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ for x in $CPPFLAGS $INC[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ dnl Really add $additional_includedir to $INCNAME.
+ INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ fi
+ dnl Look for dependencies.
+ if test -n "$found_la"; then
+ dnl Read the .la file. It defines the variables
+ dnl dlname, library_names, old_library, dependency_libs, current,
+ dnl age, revision, installed, dlopen, dlpreopen, libdir.
+ save_libdir="$libdir"
+ case "$found_la" in
+ */* | *\\*) . "$found_la" ;;
+ *) . "./$found_la" ;;
+ esac
+ libdir="$save_libdir"
+ dnl We use only dependency_libs.
+ for dep in $dependency_libs; do
+ case "$dep" in
+ -L*)
+ additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+ dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/lib,
+ dnl 2. if it's /usr/local/lib and we are using GCC on Linux,
+ dnl 3. if it's already present in $LDFLAGS or the already
+ dnl constructed $LIBNAME,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+ haveit=
+ if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ haveit=
+ for x in $LDFLAGS $LIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LIBNAME.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
+ fi
+ fi
+ haveit=
+ for x in $LDFLAGS $LTLIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LTLIBNAME.
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ ;;
+ -R*)
+ dir=`echo "X$dep" | sed -e 's/^X-R//'`
+ if test "$enable_rpath" != no; then
+ dnl Potentially add DIR to rpathdirs.
+ dnl The rpathdirs will be appended to $LIBNAME at the end.
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ dnl Potentially add DIR to ltrpathdirs.
+ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $dir"
+ fi
+ fi
+ ;;
+ -l*)
+ dnl Handle this in the next round.
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+ ;;
+ *.la)
+ dnl Handle this in the next round. Throw away the .la's
+ dnl directory; it is already contained in a preceding -L
+ dnl option.
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+ ;;
+ *)
+ dnl Most likely an immediate library name.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
+ ;;
+ esac
+ done
+ fi
+ else
+ dnl Didn't find the library; assume it is in the system directories
+ dnl known to the linker and runtime loader. (All the system
+ dnl directories known to the linker should also be known to the
+ dnl runtime loader, otherwise the system is severely misconfigured.)
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
+ fi
+ fi
+ fi
+ done
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n "$acl_hardcode_libdir_separator"; then
+ dnl Weird platform: only the last -rpath option counts, the user must
+ dnl pass all path elements in one option. We can arrange that for a
+ dnl single library, but not when more than one $LIBNAMEs are used.
+ alldirs=
+ for found_dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
+ done
+ dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+ else
+ dnl The -rpath options are cumulative.
+ for found_dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$found_dir"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+ done
+ fi
+ fi
+ if test "X$ltrpathdirs" != "X"; then
+ dnl When using libtool, the option that works for both libraries and
+ dnl executables is -R. The -R options are cumulative.
+ for found_dir in $ltrpathdirs; do
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
+ done
+ fi
+])
+
+dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
+dnl unless already present in VAR.
+dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
+dnl contains two or three consecutive elements that belong together.
+AC_DEFUN([AC_LIB_APPENDTOVAR],
+[
+ for element in [$2]; do
+ haveit=
+ for x in $[$1]; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X$element"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ [$1]="${[$1]}${[$1]:+ }$element"
+ fi
+ done
+])
+
+dnl For those cases where a variable contains several -L and -l options
+dnl referring to unknown libraries and directories, this macro determines the
+dnl necessary additional linker options for the runtime path.
+dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL])
+dnl sets LDADDVAR to linker options needed together with LIBSVALUE.
+dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed,
+dnl otherwise linking without libtool is assumed.
+AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS],
+[
+ AC_REQUIRE([AC_LIB_RPATH])
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ $1=
+ if test "$enable_rpath" != no; then
+ if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+ dnl Use an explicit option to hardcode directories into the resulting
+ dnl binary.
+ rpathdirs=
+ next=
+ for opt in $2; do
+ if test -n "$next"; then
+ dir="$next"
+ dnl No need to hardcode the standard /usr/lib.
+ if test "X$dir" != "X/usr/$acl_libdirstem"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ next=
+ else
+ case $opt in
+ -L) next=yes ;;
+ -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'`
+ dnl No need to hardcode the standard /usr/lib.
+ if test "X$dir" != "X/usr/$acl_libdirstem"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ next= ;;
+ *) next= ;;
+ esac
+ fi
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n ""$3""; then
+ dnl libtool is used for linking. Use -R options.
+ for dir in $rpathdirs; do
+ $1="${$1}${$1:+ }-R$dir"
+ done
+ else
+ dnl The linker is used for linking directly.
+ if test -n "$acl_hardcode_libdir_separator"; then
+ dnl Weird platform: only the last -rpath option counts, the user
+ dnl must pass all path elements in one option.
+ alldirs=
+ for dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir"
+ done
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ $1="$flag"
+ else
+ dnl The -rpath options are cumulative.
+ for dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$dir"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ $1="${$1}${$1:+ }$flag"
+ done
+ fi
+ fi
+ fi
+ fi
+ fi
+ AC_SUBST([$1])
+])
diff --git a/tools/node_modules/expresso/deps/jscoverage/m4/lib-prefix.m4 b/tools/node_modules/expresso/deps/jscoverage/m4/lib-prefix.m4
new file mode 100644
index 0000000..a8684e1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/m4/lib-prefix.m4
@@ -0,0 +1,185 @@
+# lib-prefix.m4 serial 5 (gettext-0.15)
+dnl Copyright (C) 2001-2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
+dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
+dnl require excessive bracketing.
+ifdef([AC_HELP_STRING],
+[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
+[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
+
+dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
+dnl to access previously installed libraries. The basic assumption is that
+dnl a user will want packages to use other packages he previously installed
+dnl with the same --prefix option.
+dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
+dnl libraries, but is otherwise very convenient.
+AC_DEFUN([AC_LIB_PREFIX],
+[
+ AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ dnl By default, look in $includedir and $libdir.
+ use_additional=yes
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ AC_LIB_ARG_WITH([lib-prefix],
+[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
+ --without-lib-prefix don't search for libraries in includedir and libdir],
+[
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/$acl_libdirstem"
+ fi
+ fi
+])
+ if test $use_additional = yes; then
+ dnl Potentially add $additional_includedir to $CPPFLAGS.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/include,
+ dnl 2. if it's already present in $CPPFLAGS,
+ dnl 3. if it's /usr/local/include and we are using GCC on Linux,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ for x in $CPPFLAGS; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ dnl Really add $additional_includedir to $CPPFLAGS.
+ CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ dnl Potentially add $additional_libdir to $LDFLAGS.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/lib,
+ dnl 2. if it's already present in $LDFLAGS,
+ dnl 3. if it's /usr/local/lib and we are using GCC on Linux,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+ haveit=
+ for x in $LDFLAGS; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LDFLAGS.
+ LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ fi
+])
+
+dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
+dnl acl_final_exec_prefix, containing the values to which $prefix and
+dnl $exec_prefix will expand at the end of the configure script.
+AC_DEFUN([AC_LIB_PREPARE_PREFIX],
+[
+ dnl Unfortunately, prefix and exec_prefix get only finally determined
+ dnl at the end of configure.
+ if test "X$prefix" = "XNONE"; then
+ acl_final_prefix="$ac_default_prefix"
+ else
+ acl_final_prefix="$prefix"
+ fi
+ if test "X$exec_prefix" = "XNONE"; then
+ acl_final_exec_prefix='${prefix}'
+ else
+ acl_final_exec_prefix="$exec_prefix"
+ fi
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+ prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
+dnl variables prefix and exec_prefix bound to the values they will have
+dnl at the end of the configure script.
+AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
+[
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ $1
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing
+dnl the basename of the libdir, either "lib" or "lib64".
+AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
+[
+ dnl There is no formal standard regarding lib and lib64. The current
+ dnl practice is that on a system supporting 32-bit and 64-bit instruction
+ dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit
+ dnl libraries go under $prefix/lib. We determine the compiler's default
+ dnl mode by looking at the compiler's library search path. If at least
+ dnl of its elements ends in /lib64 or points to a directory whose absolute
+ dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the
+ dnl default, namely "lib".
+ acl_libdirstem=lib
+ searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
+ if test -n "$searchpath"; then
+ acl_save_IFS="${IFS= }"; IFS=":"
+ for searchdir in $searchpath; do
+ if test -d "$searchdir"; then
+ case "$searchdir" in
+ */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
+ *) searchdir=`cd "$searchdir" && pwd`
+ case "$searchdir" in
+ */lib64 ) acl_libdirstem=lib64 ;;
+ esac ;;
+ esac
+ fi
+ done
+ IFS="$acl_save_IFS"
+ fi
+])
diff --git a/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh b/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh
new file mode 100644
index 0000000..cdc95f2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+set -e
+
+version=0.4
+distdir=jscoverage-${version}
+zipfile=${distdir}-windows.zip
+
+rm -fr $distdir
+mkdir $distdir
+
+cp -a doc $distdir
+cp -a jscoverage.exe jscoverage-server.exe $distdir
+strip $distdir/*.exe
+cp -a COPYING $distdir
+unix2dos $distdir/COPYING
+cp -a README $distdir/README.txt
+unix2dos $distdir/README.txt
+
+timestamp=`cat TIMESTAMP`
+find $distdir -exec touch -d "$timestamp" {} \;
+
+rm -f $zipfile
+zip -X -r $zipfile $distdir -x '*/.svn/*'
diff --git a/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh.in b/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh.in
new file mode 100644
index 0000000..16bde27
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh.in
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+set -e
+
+version=@VERSION@
+distdir=jscoverage-${version}
+zipfile=${distdir}-windows.zip
+
+rm -fr $distdir
+mkdir $distdir
+
+cp -a doc $distdir
+cp -a jscoverage.exe jscoverage-server.exe $distdir
+strip $distdir/*.exe
+cp -a COPYING $distdir
+unix2dos $distdir/COPYING
+cp -a README $distdir/README.txt
+unix2dos $distdir/README.txt
+
+timestamp=`cat TIMESTAMP`
+find $distdir -exec touch -d "$timestamp" {} \;
+
+rm -f $zipfile
+zip -X -r $zipfile $distdir -x '*/.svn/*'
diff --git a/tools/node_modules/expresso/deps/jscoverage/make-dist.sh b/tools/node_modules/expresso/deps/jscoverage/make-dist.sh
new file mode 100644
index 0000000..bf7ee0e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/make-dist.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+set -e
+
+version=0.4
+distdir=jscoverage-${version}
+
+rm -fr $distdir
+mkdir $distdir
+
+# copy all files in SVN
+for file in $(svn status -qv | sed 's/.* //' | sort)
+do
+ if [ -f "$file" ]
+ then
+ cp -a --parents "$file" $distdir
+ fi
+done
+
+# add generated files
+cp -a --parents aclocal.m4 \
+ configure \
+ config.h.in \
+ Makefile.in config.guess config.sub depcomp install-sh missing \
+ $distdir
+cp -a --parents tests/Makefile.in $distdir
+cp -a --parents doc/instrumented $distdir
+cp -a --parents doc/instrumented-inverted $distdir
+
+# remove unnecessary files
+rm $distdir/TIMESTAMP
+rm $distdir/bootstrap.sh
+rm $distdir/make-maintainer-clean.sh
+rm -r $distdir/scriptaculous*
+rm -r $distdir/selenium
+
+timestamp=`cat TIMESTAMP`
+find $distdir -exec touch -d "$timestamp" {} \;
+
+tarfile=${distdir}.tar
+tar cvf $tarfile --owner=root --group=root $distdir
+bzip2 -c $tarfile > ${tarfile}.bz2
+lzma -c $tarfile > ${tarfile}.lzma
diff --git a/tools/node_modules/expresso/deps/jscoverage/make-dist.sh.in b/tools/node_modules/expresso/deps/jscoverage/make-dist.sh.in
new file mode 100644
index 0000000..f0a4282
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/make-dist.sh.in
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+set -e
+
+version=@VERSION@
+distdir=jscoverage-${version}
+
+rm -fr $distdir
+mkdir $distdir
+
+# copy all files in SVN
+for file in $(svn status -qv | sed 's/.* //' | sort)
+do
+ if [ -f "$file" ]
+ then
+ cp -a --parents "$file" $distdir
+ fi
+done
+
+# add generated files
+cp -a --parents aclocal.m4 \
+ configure \
+ config.h.in \
+ Makefile.in config.guess config.sub depcomp install-sh missing \
+ $distdir
+cp -a --parents tests/Makefile.in $distdir
+cp -a --parents doc/instrumented $distdir
+cp -a --parents doc/instrumented-inverted $distdir
+
+# remove unnecessary files
+rm $distdir/TIMESTAMP
+rm $distdir/bootstrap.sh
+rm $distdir/make-maintainer-clean.sh
+rm -r $distdir/scriptaculous*
+rm -r $distdir/selenium
+
+timestamp=`cat TIMESTAMP`
+find $distdir -exec touch -d "$timestamp" {} \;
+
+tarfile=${distdir}.tar
+tar cvf $tarfile --owner=root --group=root $distdir
+bzip2 -c $tarfile > ${tarfile}.bz2
+lzma -c $tarfile > ${tarfile}.lzma
diff --git a/tools/node_modules/expresso/deps/jscoverage/missing b/tools/node_modules/expresso/deps/jscoverage/missing
new file mode 100755
index 0000000..1c8ff70
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/missing
@@ -0,0 +1,367 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2006-05-10.23
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ # Exit code 63 means version mismatch. This often happens
+ # when the user try to use an ancient version of a tool on
+ # a file that requires a minimum version. In this case we
+ # we should proceed has if the program had been absent, or
+ # if --run hadn't been passed.
+ if test $? = 63; then
+ run=:
+ msg="probably too old"
+ fi
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ autom4te touch the output file, or create a stub one
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Send bug reports to <bug-automake@gnu.org>."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# Now exit if we have it, but it failed. Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).
+case $1 in
+ lex|yacc)
+ # Not GNU programs, they don't have --version.
+ ;;
+
+ tar)
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ exit 1
+ fi
+ ;;
+
+ *)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ # Could not run --version or --help. This is probably someone
+ # running `$TOOL --version' or `$TOOL --help' to check whether
+ # $TOOL exists and not knowing $TOOL uses missing.
+ exit 1
+ fi
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $1 in
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case $f in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f y.tab.h; then
+ echo >y.tab.h
+ fi
+ if test ! -f y.tab.c; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f lex.yy.c; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit 1
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ # The file to touch is that specified with -o ...
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -z "$file"; then
+ # ... or it is the one specified with @setfilename ...
+ infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '
+ /^@setfilename/{
+ s/.* \([^ ]*\) *$/\1/
+ p
+ q
+ }' $infile`
+ # ... or it is derived from the source name (dir/f.texi becomes f.info)
+ test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+ fi
+ # If the file does not exist, the user really needs makeinfo;
+ # let's fail without touching anything.
+ test -f $file || exit 1
+ touch $file
+ ;;
+
+ tar)
+ shift
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar "$@" && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar "$@" && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case $firstarg in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ case $firstarg in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequisites for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/node-jscoverage b/tools/node_modules/expresso/deps/jscoverage/node-jscoverage
new file mode 100755
index 0000000..56fcddd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/node-jscoverage
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/report.js b/tools/node_modules/expresso/deps/jscoverage/report.js
new file mode 100644
index 0000000..13ce04a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/report.js
@@ -0,0 +1,76 @@
+if (! window.jscoverage_report) {
+ window.jscoverage_report = function jscoverage_report(dir) {
+ var createRequest = function () {
+ if (window.XMLHttpRequest) {
+ return new XMLHttpRequest();
+ }
+ else if (window.ActiveXObject) {
+ return new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ };
+
+ var pad = function (s) {
+ return '0000'.substr(s.length) + s;
+ };
+
+ var quote = function (s) {
+ return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) {
+ switch (c) {
+ case '\b':
+ return '\\b';
+ case '\f':
+ return '\\f';
+ case '\n':
+ return '\\n';
+ case '\r':
+ return '\\r';
+ case '\t':
+ return '\\t';
+ // IE doesn't support this
+ /*
+ case '\v':
+ return '\\v';
+ */
+ case '"':
+ return '\\"';
+ case '\\':
+ return '\\\\';
+ default:
+ return '\\u' + pad(c.charCodeAt(0).toString(16));
+ }
+ }) + '"';
+ };
+
+ var json = [];
+ for (var file in top._$jscoverage) {
+ var coverage = top._$jscoverage[file];
+ var array = [];
+ var length = coverage.length;
+ for (var line = 0; line < length; line++) {
+ var value = coverage[line];
+ if (value === undefined || value === null) {
+ value = 'null';
+ }
+ array.push(value);
+ }
+ json.push(quote(file) + ':[' + array.join(',') + ']');
+ }
+ json = '{' + json.join(',') + '}';
+
+ var request = createRequest();
+ var url = '/jscoverage-store';
+ if (dir) {
+ url += '/' + encodeURIComponent(dir);
+ }
+ request.open('POST', url, false);
+ request.setRequestHeader('Content-Type', 'application/json');
+ request.setRequestHeader('Content-Length', json.length.toString());
+ request.send(json);
+ if (request.status === 200 || request.status === 201 || request.status === 204) {
+ return request.responseText;
+ }
+ else {
+ throw request.status;
+ }
+ };
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/resource-manager.c b/tools/node_modules/expresso/deps/jscoverage/resource-manager.c
new file mode 100644
index 0000000..e8e8885
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/resource-manager.c
@@ -0,0 +1,59 @@
+/*
+ resource-manager.c - handles embedded files
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "resource-manager.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+#include "resources.c"
+
+const struct Resource * get_resource(const char * name) {
+ int num_resources = sizeof(RESOURCES) / sizeof(struct Resource);
+ for (int i = 0; i < num_resources; i++) {
+ if (strcmp(RESOURCES[i].name, name) == 0) {
+ return &RESOURCES[i];
+ }
+ }
+ return NULL;
+}
+
+void copy_resource_to_stream(const char * resource, FILE * stream) {
+ const struct Resource * r = get_resource(resource);
+ assert(r != NULL);
+ if (fwrite(r->data, 1, r->length, stream) != r->length) {
+ fatal("cannot write to stream");
+ }
+}
+
+void copy_resource(const char * resource, const char * destination_directory) {
+ char * file = make_path(destination_directory, resource);
+ char * directory = make_dirname(file);
+ mkdirs(directory);
+ free(directory);
+ FILE * f = xfopen(file, "wb");
+ copy_resource_to_stream(resource, f);
+ fclose(f);
+ free(file);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/resource-manager.h b/tools/node_modules/expresso/deps/jscoverage/resource-manager.h
new file mode 100644
index 0000000..5a0a681
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/resource-manager.h
@@ -0,0 +1,46 @@
+/*
+ resource-manager.h - handles embedded files
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef RESOURCE_MANAGER_H_
+#define RESOURCE_MANAGER_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Resource {
+ const char * name;
+ const unsigned char * data;
+ const size_t length;
+};
+
+const struct Resource * get_resource(const char * name);
+
+void copy_resource_to_stream(const char * resource, FILE * stream);
+
+void copy_resource(const char * resource, const char * destination_directory);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RESOURCE_MANAGER_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/resources.c b/tools/node_modules/expresso/deps/jscoverage/resources.c
new file mode 100644
index 0000000..8b9664e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/resources.c
@@ -0,0 +1,3596 @@
+const unsigned char RESOURCE1_[] = {
+
+ 0x55,0x73,0x61,0x67,0x65,0x3a,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x20,0x53,0x4f,0x55,0x52,0x43,0x45,0x2d,0x44,0x49,0x52,0x45,0x43,0x54,0x4f,
+ 0x52,0x59,0x20,0x44,0x45,0x53,0x54,0x49,0x4e,0x41,0x54,0x49,0x4f,0x4e,0x2d,0x44,
+ 0x49,0x52,0x45,0x43,0x54,0x4f,0x52,0x59,0x0a,0x49,0x6e,0x73,0x74,0x72,0x75,0x6d,
+ 0x65,0x6e,0x74,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x20,0x77,
+ 0x69,0x74,0x68,0x20,0x63,0x6f,0x64,0x65,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x20,0x69,0x6e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0a,0x0a,
+ 0x4f,0x70,0x74,0x69,0x6f,0x6e,0x73,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,
+ 0x2d,0x65,0x6e,0x63,0x6f,0x64,0x69,0x6e,0x67,0x3d,0x45,0x4e,0x43,0x4f,0x44,0x49,
+ 0x4e,0x47,0x20,0x20,0x20,0x61,0x73,0x73,0x75,0x6d,0x65,0x20,0x2e,0x6a,0x73,0x20,
+ 0x66,0x69,0x6c,0x65,0x73,0x20,0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x67,0x69,
+ 0x76,0x65,0x6e,0x20,0x63,0x68,0x61,0x72,0x61,0x63,0x74,0x65,0x72,0x20,0x65,0x6e,
+ 0x63,0x6f,0x64,0x69,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x65,
+ 0x78,0x63,0x6c,0x75,0x64,0x65,0x3d,0x50,0x41,0x54,0x48,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x64,0x6f,0x20,0x6e,0x6f,0x74,0x20,0x63,0x6f,0x70,0x79,0x20,0x50,
+ 0x41,0x54,0x48,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x6a,0x73,0x2d,0x76,
+ 0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x20,0x20,
+ 0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x73,0x70,0x65,0x63,0x69,0x66,0x69,0x65,
+ 0x64,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x20,0x76,0x65,0x72,
+ 0x73,0x69,0x6f,0x6e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x6e,0x6f,0x2d,
+ 0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x64,0x6f,0x20,0x6e,0x6f,0x74,0x20,0x70,0x65,0x72,0x66,0x6f,0x72,0x6d,0x20,
+ 0x73,0x79,0x6e,0x74,0x61,0x78,0x20,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,
+ 0x69,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x6e,0x6f,0x2d,0x69,
+ 0x6e,0x73,0x74,0x72,0x75,0x6d,0x65,0x6e,0x74,0x3d,0x50,0x41,0x54,0x48,0x20,0x20,
+ 0x63,0x6f,0x70,0x79,0x20,0x62,0x75,0x74,0x20,0x64,0x6f,0x20,0x6e,0x6f,0x74,0x20,
+ 0x69,0x6e,0x73,0x74,0x72,0x75,0x6d,0x65,0x6e,0x74,0x20,0x50,0x41,0x54,0x48,0x0a,
+ 0x20,0x20,0x2d,0x76,0x2c,0x20,0x2d,0x2d,0x76,0x65,0x72,0x62,0x6f,0x73,0x65,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x78,0x70,0x6c,
+ 0x61,0x69,0x6e,0x20,0x77,0x68,0x61,0x74,0x20,0x69,0x73,0x20,0x62,0x65,0x69,0x6e,
+ 0x67,0x20,0x64,0x6f,0x6e,0x65,0x0a,0x20,0x20,0x2d,0x68,0x2c,0x20,0x2d,0x2d,0x68,
+ 0x65,0x6c,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x64,0x69,0x73,0x70,0x6c,0x61,0x79,0x20,0x74,0x68,0x69,0x73,0x20,
+ 0x68,0x65,0x6c,0x70,0x20,0x61,0x6e,0x64,0x20,0x65,0x78,0x69,0x74,0x0a,0x20,0x20,
+ 0x2d,0x56,0x2c,0x20,0x2d,0x2d,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x64,0x69,0x73,0x70,0x6c,0x61,
+ 0x79,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x69,0x6e,0x66,0x6f,0x72,0x6d,
+ 0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x6e,0x64,0x20,0x65,0x78,0x69,0x74,0x0a,
+};
+const unsigned char RESOURCE2_[] = {
+
+ 0x55,0x73,0x61,0x67,0x65,0x3a,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2d,0x73,0x65,0x72,0x76,0x65,0x72,0x20,0x5b,0x4f,0x50,0x54,0x49,0x4f,0x4e,
+ 0x5d,0x2e,0x2e,0x2e,0x0a,0x52,0x75,0x6e,0x20,0x61,0x20,0x73,0x65,0x72,0x76,0x65,
+ 0x72,0x20,0x66,0x6f,0x72,0x20,0x69,0x6e,0x73,0x74,0x72,0x75,0x6d,0x65,0x6e,0x74,
+ 0x69,0x6e,0x67,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x20,0x77,
+ 0x69,0x74,0x68,0x20,0x63,0x6f,0x64,0x65,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x20,0x69,0x6e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0a,0x0a,
+ 0x4f,0x70,0x74,0x69,0x6f,0x6e,0x73,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,
+ 0x2d,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2d,0x72,0x6f,0x6f,0x74,0x3d,0x44,
+ 0x49,0x52,0x20,0x20,0x20,0x73,0x65,0x72,0x76,0x65,0x20,0x63,0x6f,0x6e,0x74,0x65,
+ 0x6e,0x74,0x20,0x66,0x72,0x6f,0x6d,0x20,0x44,0x49,0x52,0x20,0x28,0x64,0x65,0x66,
+ 0x61,0x75,0x6c,0x74,0x3a,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x20,0x64,0x69,
+ 0x72,0x65,0x63,0x74,0x6f,0x72,0x79,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,
+ 0x2d,0x65,0x6e,0x63,0x6f,0x64,0x69,0x6e,0x67,0x3d,0x45,0x4e,0x43,0x4f,0x44,0x49,
+ 0x4e,0x47,0x20,0x20,0x20,0x61,0x73,0x73,0x75,0x6d,0x65,0x20,0x2e,0x6a,0x73,0x20,
+ 0x66,0x69,0x6c,0x65,0x73,0x20,0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x67,0x69,
+ 0x76,0x65,0x6e,0x20,0x63,0x68,0x61,0x72,0x61,0x63,0x74,0x65,0x72,0x20,0x65,0x6e,
+ 0x63,0x6f,0x64,0x69,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x69,
+ 0x70,0x2d,0x61,0x64,0x64,0x72,0x65,0x73,0x73,0x3d,0x41,0x44,0x44,0x52,0x45,0x53,
+ 0x53,0x20,0x20,0x62,0x69,0x6e,0x64,0x20,0x74,0x6f,0x20,0x41,0x44,0x44,0x52,0x45,
+ 0x53,0x53,0x20,0x28,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x3a,0x20,0x31,0x32,0x37,
+ 0x2e,0x30,0x2e,0x30,0x2e,0x31,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,
+ 0x6a,0x73,0x2d,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x56,0x45,0x52,0x53,0x49,
+ 0x4f,0x4e,0x20,0x20,0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x73,0x70,0x65,0x63,
+ 0x69,0x66,0x69,0x65,0x64,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,
+ 0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,
+ 0x2d,0x6e,0x6f,0x2d,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x64,0x6f,0x20,0x6e,0x6f,0x74,0x20,0x70,0x65,0x72,0x66,
+ 0x6f,0x72,0x6d,0x20,0x73,0x79,0x6e,0x74,0x61,0x78,0x20,0x68,0x69,0x67,0x68,0x6c,
+ 0x69,0x67,0x68,0x74,0x69,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,
+ 0x6e,0x6f,0x2d,0x69,0x6e,0x73,0x74,0x72,0x75,0x6d,0x65,0x6e,0x74,0x3d,0x55,0x52,
+ 0x4c,0x20,0x20,0x20,0x64,0x6f,0x20,0x6e,0x6f,0x74,0x20,0x69,0x6e,0x73,0x74,0x72,
+ 0x75,0x6d,0x65,0x6e,0x74,0x20,0x55,0x52,0x4c,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x2d,0x2d,0x70,0x6f,0x72,0x74,0x3d,0x50,0x4f,0x52,0x54,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x75,0x73,0x65,0x20,0x50,0x4f,0x52,0x54,0x20,0x66,
+ 0x6f,0x72,0x20,0x54,0x43,0x50,0x20,0x70,0x6f,0x72,0x74,0x20,0x28,0x64,0x65,0x66,
+ 0x61,0x75,0x6c,0x74,0x3a,0x20,0x38,0x30,0x38,0x30,0x29,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x2d,0x2d,0x70,0x72,0x6f,0x78,0x79,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x75,0x6e,0x20,0x61,0x73,0x20,0x61,
+ 0x20,0x70,0x72,0x6f,0x78,0x79,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x72,
+ 0x65,0x70,0x6f,0x72,0x74,0x2d,0x64,0x69,0x72,0x3d,0x44,0x49,0x52,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x73,0x74,0x6f,0x72,0x65,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x20,
+ 0x74,0x6f,0x20,0x44,0x49,0x52,0x20,0x28,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x3a,
+ 0x20,0x60,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x72,0x65,0x70,
+ 0x6f,0x72,0x74,0x27,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x73,0x68,
+ 0x75,0x74,0x64,0x6f,0x77,0x6e,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x73,0x74,0x6f,0x70,0x20,0x61,0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,
+ 0x20,0x73,0x65,0x72,0x76,0x65,0x72,0x0a,0x20,0x20,0x2d,0x76,0x2c,0x20,0x2d,0x2d,
+ 0x76,0x65,0x72,0x62,0x6f,0x73,0x65,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x20,0x77,0x68,0x61,0x74,
+ 0x20,0x69,0x73,0x20,0x62,0x65,0x69,0x6e,0x67,0x20,0x64,0x6f,0x6e,0x65,0x0a,0x20,
+ 0x20,0x2d,0x68,0x2c,0x20,0x2d,0x2d,0x68,0x65,0x6c,0x70,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x64,0x69,0x73,0x70,0x6c,
+ 0x61,0x79,0x20,0x74,0x68,0x69,0x73,0x20,0x68,0x65,0x6c,0x70,0x20,0x61,0x6e,0x64,
+ 0x20,0x65,0x78,0x69,0x74,0x0a,0x20,0x20,0x2d,0x56,0x2c,0x20,0x2d,0x2d,0x76,0x65,
+ 0x72,0x73,0x69,0x6f,0x6e,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x64,0x69,0x73,0x70,0x6c,0x61,0x79,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,
+ 0x6e,0x20,0x69,0x6e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x6e,
+ 0x64,0x20,0x65,0x78,0x69,0x74,0x0a,
+};
+const unsigned char RESOURCE3_[] = {
+
+ 0x2f,0x2a,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2e,0x6a,0x73,0x6d,0x20,0x2d,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,0x78,0x20,
+ 0x6d,0x6f,0x64,0x75,0x6c,0x65,0x0a,0x20,0x20,0x20,0x20,0x43,0x6f,0x70,0x79,0x72,
+ 0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30,0x38,0x20,0x73,0x69,
+ 0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x0a,0x0a,
+ 0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,
+ 0x20,0x69,0x73,0x20,0x66,0x72,0x65,0x65,0x20,0x73,0x6f,0x66,0x74,0x77,0x61,0x72,
+ 0x65,0x3b,0x20,0x79,0x6f,0x75,0x20,0x63,0x61,0x6e,0x20,0x72,0x65,0x64,0x69,0x73,
+ 0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x20,0x69,0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,
+ 0x72,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,
+ 0x75,0x6e,0x64,0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,
+ 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,
+ 0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,
+ 0x65,0x20,0x61,0x73,0x20,0x70,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,
+ 0x79,0x0a,0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,
+ 0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,
+ 0x6f,0x6e,0x3b,0x20,0x65,0x69,0x74,0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,
+ 0x6f,0x6e,0x20,0x32,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,
+ 0x6e,0x73,0x65,0x2c,0x20,0x6f,0x72,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,
+ 0x79,0x6f,0x75,0x72,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,
+ 0x20,0x6c,0x61,0x74,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0a,
+ 0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,
+ 0x6d,0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,
+ 0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,0x61,
+ 0x74,0x20,0x69,0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,0x65,
+ 0x66,0x75,0x6c,0x2c,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,0x49,0x54,
+ 0x48,0x4f,0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,
+ 0x59,0x3b,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,0x6e,0x20,
+ 0x74,0x68,0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,0x72,0x72,
+ 0x61,0x6e,0x74,0x79,0x20,0x6f,0x66,0x0a,0x20,0x20,0x20,0x20,0x4d,0x45,0x52,0x43,
+ 0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,0x72,0x20,0x46,
+ 0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,0x50,0x41,0x52,
+ 0x54,0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,0x53,0x45,0x2e,
+ 0x20,0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0a,0x20,0x20,0x20,0x20,0x47,0x4e,
+ 0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,
+ 0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,0x20,0x6d,0x6f,0x72,
+ 0x65,0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0a,0x0a,0x20,0x20,0x20,0x20,
+ 0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x68,0x61,0x76,0x65,0x20,
+ 0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,0x63,0x6f,0x70,0x79,0x20,
+ 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,
+ 0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,
+ 0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68,
+ 0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x3b,0x20,0x69,
+ 0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,0x65,0x20,0x74,0x6f,0x20,
+ 0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,
+ 0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x49,0x6e,
+ 0x63,0x2e,0x2c,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,0x20,0x46,0x72,0x61,0x6e,0x6b,
+ 0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,0x2c,0x20,0x46,0x69,0x66,0x74,
+ 0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,0x6f,0x73,0x74,0x6f,0x6e,0x2c,
+ 0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,0x31,0x33,0x30,0x31,0x20,0x55,
+ 0x53,0x41,0x2e,0x0a,0x2a,0x2f,0x0a,0x0a,0x76,0x61,0x72,0x20,0x45,0x58,0x50,0x4f,
+ 0x52,0x54,0x45,0x44,0x5f,0x53,0x59,0x4d,0x42,0x4f,0x4c,0x53,0x20,0x3d,0x20,0x5b,
+ 0x27,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x27,0x5d,0x3b,
+ 0x0a,0x0a,0x76,0x61,0x72,0x20,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,
+};
+const unsigned char RESOURCE4_[] = {
+
+ 0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2f,0x0a,0x6f,
+ 0x76,0x65,0x72,0x6c,0x61,0x79,0x20,0x63,0x68,0x72,0x6f,0x6d,0x65,0x3a,0x2f,0x2f,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x2f,0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2f,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x2e,0x78,0x75,0x6c,0x20,0x63,0x68,0x72,0x6f,
+ 0x6d,0x65,0x3a,0x2f,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2f,
+ 0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x78,0x75,0x6c,0x0a,
+};
+const unsigned char RESOURCE5_[] = {
+
+ 0x3c,0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,
+ 0x2e,0x30,0x22,0x3f,0x3e,0x0a,0x3c,0x21,0x2d,0x2d,0x0a,0x20,0x20,0x20,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x78,0x75,0x6c,0x20,0x2d,0x20,
+ 0x58,0x55,0x4c,0x20,0x6f,0x76,0x65,0x72,0x6c,0x61,0x79,0x0a,0x20,0x20,0x20,0x20,
+ 0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,
+ 0x30,0x38,0x20,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,
+ 0x63,0x6f,0x6d,0x0a,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,
+ 0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,0x66,0x72,0x65,0x65,0x20,0x73,0x6f,
+ 0x66,0x74,0x77,0x61,0x72,0x65,0x3b,0x20,0x79,0x6f,0x75,0x20,0x63,0x61,0x6e,0x20,
+ 0x72,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x20,0x69,0x74,0x20,
+ 0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x74,0x20,0x75,0x6e,0x64,0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x74,
+ 0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,
+ 0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,
+ 0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x73,0x20,0x70,0x75,0x62,0x6c,0x69,0x73,
+ 0x68,0x65,0x64,0x20,0x62,0x79,0x0a,0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x46,
+ 0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,
+ 0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x3b,0x20,0x65,0x69,0x74,0x68,0x65,0x72,0x20,
+ 0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x32,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,
+ 0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x2c,0x20,0x6f,0x72,0x0a,0x20,0x20,0x20,
+ 0x20,0x28,0x61,0x74,0x20,0x79,0x6f,0x75,0x72,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,
+ 0x29,0x20,0x61,0x6e,0x79,0x20,0x6c,0x61,0x74,0x65,0x72,0x20,0x76,0x65,0x72,0x73,
+ 0x69,0x6f,0x6e,0x2e,0x0a,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,
+ 0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,
+ 0x62,0x75,0x74,0x65,0x64,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,
+ 0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x69,0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,
+ 0x65,0x20,0x75,0x73,0x65,0x66,0x75,0x6c,0x2c,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,
+ 0x74,0x20,0x57,0x49,0x54,0x48,0x4f,0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,
+ 0x52,0x52,0x41,0x4e,0x54,0x59,0x3b,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,
+ 0x65,0x76,0x65,0x6e,0x20,0x74,0x68,0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,
+ 0x20,0x77,0x61,0x72,0x72,0x61,0x6e,0x74,0x79,0x20,0x6f,0x66,0x0a,0x20,0x20,0x20,
+ 0x20,0x4d,0x45,0x52,0x43,0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,
+ 0x20,0x6f,0x72,0x20,0x46,0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,
+ 0x41,0x20,0x50,0x41,0x52,0x54,0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,
+ 0x50,0x4f,0x53,0x45,0x2e,0x20,0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0a,0x20,
+ 0x20,0x20,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,
+ 0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,
+ 0x72,0x20,0x6d,0x6f,0x72,0x65,0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0a,
+ 0x0a,0x20,0x20,0x20,0x20,0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,
+ 0x68,0x61,0x76,0x65,0x20,0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,
+ 0x63,0x6f,0x70,0x79,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,
+ 0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,
+ 0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0a,0x20,0x20,0x20,
+ 0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
+ 0x61,0x6d,0x3b,0x20,0x69,0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,
+ 0x65,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,
+ 0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,
+ 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x2c,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,0x20,
+ 0x46,0x72,0x61,0x6e,0x6b,0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,0x2c,
+ 0x20,0x46,0x69,0x66,0x74,0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,0x6f,
+ 0x73,0x74,0x6f,0x6e,0x2c,0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,0x31,
+ 0x33,0x30,0x31,0x20,0x55,0x53,0x41,0x2e,0x0a,0x2d,0x2d,0x3e,0x0a,0x0a,0x3c,0x6f,
+ 0x76,0x65,0x72,0x6c,0x61,0x79,0x20,0x69,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x4f,0x76,0x65,0x72,0x6c,0x61,0x79,0x22,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,
+ 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,
+ 0x2e,0x6f,0x72,0x67,0x2f,0x6b,0x65,0x79,0x6d,0x61,0x73,0x74,0x65,0x72,0x2f,0x67,
+ 0x61,0x74,0x65,0x6b,0x65,0x65,0x70,0x65,0x72,0x2f,0x74,0x68,0x65,0x72,0x65,0x2e,
+ 0x69,0x73,0x2e,0x6f,0x6e,0x6c,0x79,0x2e,0x78,0x75,0x6c,0x22,0x3e,0x0a,0x20,0x20,
+ 0x3c,0x73,0x63,0x72,0x69,0x70,0x74,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x6f,0x76,0x65,0x72,0x6c,0x61,0x79,0x2e,
+ 0x6a,0x73,0x22,0x3e,0x3c,0x2f,0x73,0x63,0x72,0x69,0x70,0x74,0x3e,0x0a,0x20,0x20,
+ 0x3c,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x73,0x65,0x74,0x3e,0x0a,0x20,0x20,0x20,
+ 0x20,0x3c,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x69,0x64,0x3d,0x22,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x56,0x69,0x65,0x77,0x43,0x6f,0x6d,0x6d,
+ 0x61,0x6e,0x64,0x22,0x20,0x6f,0x6e,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x3d,0x22,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x76,0x69,0x65,0x77,0x28,
+ 0x29,0x3b,0x22,0x2f,0x3e,0x0a,0x20,0x20,0x20,0x20,0x3c,0x63,0x6f,0x6d,0x6d,0x61,
+ 0x6e,0x64,0x20,0x69,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x53,0x74,0x6f,0x72,0x65,0x43,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x22,0x20,0x6f,
+ 0x6e,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x73,0x74,0x6f,0x72,0x65,0x28,0x29,0x3b,0x22,0x2f,0x3e,
+ 0x0a,0x20,0x20,0x3c,0x2f,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x73,0x65,0x74,0x3e,
+ 0x0a,0x20,0x20,0x3c,0x6d,0x65,0x6e,0x75,0x70,0x6f,0x70,0x75,0x70,0x20,0x69,0x64,
+ 0x3d,0x22,0x6d,0x65,0x6e,0x75,0x5f,0x54,0x6f,0x6f,0x6c,0x73,0x50,0x6f,0x70,0x75,
+ 0x70,0x22,0x3e,0x0a,0x20,0x20,0x20,0x20,0x3c,0x6d,0x65,0x6e,0x75,0x20,0x6c,0x61,
+ 0x62,0x65,0x6c,0x3d,0x22,0x4a,0x53,0x43,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x22,
+ 0x20,0x69,0x6e,0x73,0x65,0x72,0x74,0x61,0x66,0x74,0x65,0x72,0x3d,0x22,0x6a,0x61,
+ 0x76,0x61,0x73,0x63,0x72,0x69,0x70,0x74,0x43,0x6f,0x6e,0x73,0x6f,0x6c,0x65,0x2c,
+ 0x64,0x65,0x76,0x54,0x6f,0x6f,0x6c,0x73,0x53,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,
+ 0x72,0x22,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x6d,0x65,0x6e,0x75,0x70,
+ 0x6f,0x70,0x75,0x70,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x6d,
+ 0x65,0x6e,0x75,0x69,0x74,0x65,0x6d,0x20,0x6c,0x61,0x62,0x65,0x6c,0x3d,0x22,0x56,
+ 0x69,0x65,0x77,0x20,0x43,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x22,0x20,0x63,0x6f,
+ 0x6d,0x6d,0x61,0x6e,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x56,0x69,0x65,0x77,0x43,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x22,0x2f,0x3e,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x6d,0x65,0x6e,0x75,0x69,0x74,0x65,
+ 0x6d,0x20,0x6c,0x61,0x62,0x65,0x6c,0x3d,0x22,0x53,0x74,0x6f,0x72,0x65,0x20,0x43,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x22,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,
+ 0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x53,0x74,0x6f,0x72,
+ 0x65,0x43,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x22,0x2f,0x3e,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x3c,0x2f,0x6d,0x65,0x6e,0x75,0x70,0x6f,0x70,0x75,0x70,0x3e,0x0a,0x20,
+ 0x20,0x20,0x20,0x3c,0x2f,0x6d,0x65,0x6e,0x75,0x3e,0x0a,0x20,0x20,0x3c,0x2f,0x6d,
+ 0x65,0x6e,0x75,0x70,0x6f,0x70,0x75,0x70,0x3e,0x0a,0x3c,0x2f,0x6f,0x76,0x65,0x72,
+ 0x6c,0x61,0x79,0x3e,0x0a,
+};
+const unsigned char RESOURCE6_[] = {
+
+ 0x2f,0x2a,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2d,0x6f,0x76,0x65,0x72,0x6c,0x61,0x79,0x2e,0x6a,0x73,0x20,0x2d,0x20,0x73,
+ 0x63,0x72,0x69,0x70,0x74,0x20,0x66,0x6f,0x72,0x20,0x58,0x55,0x4c,0x20,0x6f,0x76,
+ 0x65,0x72,0x6c,0x61,0x79,0x0a,0x20,0x20,0x20,0x20,0x43,0x6f,0x70,0x79,0x72,0x69,
+ 0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30,0x38,0x20,0x73,0x69,0x6c,
+ 0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x0a,0x0a,0x20,
+ 0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,
+ 0x69,0x73,0x20,0x66,0x72,0x65,0x65,0x20,0x73,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,
+ 0x3b,0x20,0x79,0x6f,0x75,0x20,0x63,0x61,0x6e,0x20,0x72,0x65,0x64,0x69,0x73,0x74,
+ 0x72,0x69,0x62,0x75,0x74,0x65,0x20,0x69,0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,
+ 0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,0x75,
+ 0x6e,0x64,0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,0x6f,
+ 0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,
+ 0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,
+ 0x20,0x61,0x73,0x20,0x70,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,0x79,
+ 0x0a,0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,
+ 0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,
+ 0x6e,0x3b,0x20,0x65,0x69,0x74,0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,
+ 0x6e,0x20,0x32,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,0x6e,
+ 0x73,0x65,0x2c,0x20,0x6f,0x72,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,0x79,
+ 0x6f,0x75,0x72,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,0x20,
+ 0x6c,0x61,0x74,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0a,0x0a,
+ 0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,
+ 0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,
+ 0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,0x61,0x74,
+ 0x20,0x69,0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x66,
+ 0x75,0x6c,0x2c,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,0x49,0x54,0x48,
+ 0x4f,0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x59,
+ 0x3b,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,0x6e,0x20,0x74,
+ 0x68,0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,0x72,0x72,0x61,
+ 0x6e,0x74,0x79,0x20,0x6f,0x66,0x0a,0x20,0x20,0x20,0x20,0x4d,0x45,0x52,0x43,0x48,
+ 0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,0x72,0x20,0x46,0x49,
+ 0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,0x50,0x41,0x52,0x54,
+ 0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,0x53,0x45,0x2e,0x20,
+ 0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0a,0x20,0x20,0x20,0x20,0x47,0x4e,0x55,
+ 0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,
+ 0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,0x20,0x6d,0x6f,0x72,0x65,
+ 0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0a,0x0a,0x20,0x20,0x20,0x20,0x59,
+ 0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x68,0x61,0x76,0x65,0x20,0x72,
+ 0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,0x63,0x6f,0x70,0x79,0x20,0x6f,
+ 0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,
+ 0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,
+ 0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68,0x20,
+ 0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x3b,0x20,0x69,0x66,
+ 0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,0x65,0x20,0x74,0x6f,0x20,0x74,
+ 0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,
+ 0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x49,0x6e,0x63,
+ 0x2e,0x2c,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,0x20,0x46,0x72,0x61,0x6e,0x6b,0x6c,
+ 0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,0x2c,0x20,0x46,0x69,0x66,0x74,0x68,
+ 0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,0x6f,0x73,0x74,0x6f,0x6e,0x2c,0x20,
+ 0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,0x31,0x33,0x30,0x31,0x20,0x55,0x53,
+ 0x41,0x2e,0x0a,0x2a,0x2f,0x0a,0x0a,0x43,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,
+ 0x73,0x2e,0x75,0x74,0x69,0x6c,0x73,0x2e,0x69,0x6d,0x70,0x6f,0x72,0x74,0x28,0x27,
+ 0x72,0x65,0x73,0x6f,0x75,0x72,0x63,0x65,0x3a,0x2f,0x2f,0x67,0x72,0x65,0x2f,0x6d,
+ 0x6f,0x64,0x75,0x6c,0x65,0x73,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2e,0x6a,0x73,0x6d,0x27,0x29,0x3b,0x0a,0x0a,0x2f,0x2f,0x20,0x68,0x74,0x74,
+ 0x70,0x73,0x3a,0x2f,0x2f,0x64,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x2e,0x6d,
+ 0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,0x65,0x6e,0x2f,0x43,0x6f,
+ 0x64,0x65,0x5f,0x73,0x6e,0x69,0x70,0x70,0x65,0x74,0x73,0x2f,0x54,0x61,0x62,0x62,
+ 0x65,0x64,0x5f,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x0a,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6f,0x70,0x65,0x6e,0x41,0x6e,0x64,0x52,0x65,0x75,0x73,0x65,
+ 0x4f,0x6e,0x65,0x54,0x61,0x62,0x50,0x65,0x72,0x55,0x52,0x4c,0x28,0x75,0x72,0x6c,
+ 0x29,0x20,0x7b,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x77,0x6d,0x20,0x3d,0x20,0x43,
+ 0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0x2e,0x63,0x6c,0x61,0x73,0x73,0x65,
+ 0x73,0x5b,0x22,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,
+ 0x61,0x70,0x70,0x73,0x68,0x65,0x6c,0x6c,0x2f,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2d,
+ 0x6d,0x65,0x64,0x69,0x61,0x74,0x6f,0x72,0x3b,0x31,0x22,0x5d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x2e,0x67,0x65,0x74,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x28,0x43,0x6f,
+ 0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0x2e,0x69,0x6e,0x74,0x65,0x72,0x66,0x61,
+ 0x63,0x65,0x73,0x2e,0x6e,0x73,0x49,0x57,0x69,0x6e,0x64,0x6f,0x77,0x4d,0x65,0x64,
+ 0x69,0x61,0x74,0x6f,0x72,0x29,0x3b,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x62,0x72,
+ 0x6f,0x77,0x73,0x65,0x72,0x45,0x6e,0x75,0x6d,0x65,0x72,0x61,0x74,0x6f,0x72,0x20,
+ 0x3d,0x20,0x77,0x6d,0x2e,0x67,0x65,0x74,0x45,0x6e,0x75,0x6d,0x65,0x72,0x61,0x74,
+ 0x6f,0x72,0x28,0x22,0x6e,0x61,0x76,0x69,0x67,0x61,0x74,0x6f,0x72,0x3a,0x62,0x72,
+ 0x6f,0x77,0x73,0x65,0x72,0x22,0x29,0x3b,0x0a,0x0a,0x20,0x20,0x2f,0x2f,0x20,0x43,
+ 0x68,0x65,0x63,0x6b,0x20,0x65,0x61,0x63,0x68,0x20,0x62,0x72,0x6f,0x77,0x73,0x65,
+ 0x72,0x20,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x20,0x66,0x6f,0x72,0x20,0x6f,
+ 0x75,0x72,0x20,0x55,0x52,0x4c,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x6f,0x75,
+ 0x6e,0x64,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0a,0x20,0x20,0x77,0x68,
+ 0x69,0x6c,0x65,0x20,0x28,0x21,0x66,0x6f,0x75,0x6e,0x64,0x20,0x26,0x26,0x20,0x62,
+ 0x72,0x6f,0x77,0x73,0x65,0x72,0x45,0x6e,0x75,0x6d,0x65,0x72,0x61,0x74,0x6f,0x72,
+ 0x2e,0x68,0x61,0x73,0x4d,0x6f,0x72,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,
+ 0x28,0x29,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x62,0x72,
+ 0x6f,0x77,0x73,0x65,0x72,0x57,0x69,0x6e,0x20,0x3d,0x20,0x62,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x45,0x6e,0x75,0x6d,0x65,0x72,0x61,0x74,0x6f,0x72,0x2e,0x67,0x65,0x74,
+ 0x4e,0x65,0x78,0x74,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x74,0x61,0x62,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x3d,0x20,0x62,0x72,0x6f,
+ 0x77,0x73,0x65,0x72,0x57,0x69,0x6e,0x2e,0x67,0x65,0x74,0x42,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x28,0x29,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x43,0x68,
+ 0x65,0x63,0x6b,0x20,0x65,0x61,0x63,0x68,0x20,0x74,0x61,0x62,0x20,0x6f,0x66,0x20,
+ 0x74,0x68,0x69,0x73,0x20,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x69,0x6e,0x73,
+ 0x74,0x61,0x6e,0x63,0x65,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,0x75,
+ 0x6d,0x54,0x61,0x62,0x73,0x20,0x3d,0x20,0x74,0x61,0x62,0x62,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x2e,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x73,0x2e,0x6c,0x65,0x6e,0x67,
+ 0x74,0x68,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x28,0x76,0x61,0x72,0x20,
+ 0x69,0x6e,0x64,0x65,0x78,0x3d,0x30,0x3b,0x20,0x69,0x6e,0x64,0x65,0x78,0x3c,0x6e,
+ 0x75,0x6d,0x54,0x61,0x62,0x73,0x3b,0x20,0x69,0x6e,0x64,0x65,0x78,0x2b,0x2b,0x29,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x75,0x72,
+ 0x72,0x65,0x6e,0x74,0x42,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x3d,0x20,0x74,0x61,
+ 0x62,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x2e,0x67,0x65,0x74,0x42,0x72,0x6f,0x77,
+ 0x73,0x65,0x72,0x41,0x74,0x49,0x6e,0x64,0x65,0x78,0x28,0x69,0x6e,0x64,0x65,0x78,
+ 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x75,0x72,0x6c,
+ 0x20,0x3d,0x3d,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x42,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x2e,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x55,0x52,0x49,0x2e,0x73,0x70,
+ 0x65,0x63,0x29,0x20,0x7b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x2f,
+ 0x2f,0x20,0x54,0x68,0x65,0x20,0x55,0x52,0x4c,0x20,0x69,0x73,0x20,0x61,0x6c,0x72,
+ 0x65,0x61,0x64,0x79,0x20,0x6f,0x70,0x65,0x6e,0x65,0x64,0x2e,0x20,0x53,0x65,0x6c,
+ 0x65,0x63,0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x74,0x61,0x62,0x2e,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,
+ 0x2e,0x73,0x65,0x6c,0x65,0x63,0x74,0x65,0x64,0x54,0x61,0x62,0x20,0x3d,0x20,0x74,
+ 0x61,0x62,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x2e,0x6d,0x54,0x61,0x62,0x73,0x5b,
+ 0x69,0x6e,0x64,0x65,0x78,0x5d,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x2f,0x2f,0x20,0x46,0x6f,0x63,0x75,0x73,0x20,0x2a,0x74,0x68,0x69,0x73,0x2a,
+ 0x20,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x2d,0x77,0x69,0x6e,0x64,0x6f,0x77,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x57,
+ 0x69,0x6e,0x2e,0x66,0x6f,0x63,0x75,0x73,0x28,0x29,0x3b,0x0a,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x3d,0x20,0x74,0x72,0x75,
+ 0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x72,0x65,0x61,0x6b,
+ 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,
+ 0x20,0x20,0x7d,0x0a,0x0a,0x20,0x20,0x2f,0x2f,0x20,0x4f,0x75,0x72,0x20,0x55,0x52,
+ 0x4c,0x20,0x69,0x73,0x6e,0x27,0x74,0x20,0x6f,0x70,0x65,0x6e,0x2e,0x20,0x4f,0x70,
+ 0x65,0x6e,0x20,0x69,0x74,0x20,0x6e,0x6f,0x77,0x2e,0x0a,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x21,0x66,0x6f,0x75,0x6e,0x64,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x72,0x65,0x63,0x65,0x6e,0x74,0x57,0x69,0x6e,0x64,0x6f,0x77,0x20,
+ 0x3d,0x20,0x77,0x6d,0x2e,0x67,0x65,0x74,0x4d,0x6f,0x73,0x74,0x52,0x65,0x63,0x65,
+ 0x6e,0x74,0x57,0x69,0x6e,0x64,0x6f,0x77,0x28,0x22,0x6e,0x61,0x76,0x69,0x67,0x61,
+ 0x74,0x6f,0x72,0x3a,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x22,0x29,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x72,0x65,0x63,0x65,0x6e,0x74,0x57,0x69,0x6e,
+ 0x64,0x6f,0x77,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,
+ 0x55,0x73,0x65,0x20,0x61,0x6e,0x20,0x65,0x78,0x69,0x73,0x74,0x69,0x6e,0x67,0x20,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x63,0x65,0x6e,0x74,0x57,0x69,0x6e,0x64,0x6f,
+ 0x77,0x2e,0x64,0x65,0x6c,0x61,0x79,0x65,0x64,0x4f,0x70,0x65,0x6e,0x54,0x61,0x62,
+ 0x28,0x75,0x72,0x6c,0x2c,0x20,0x6e,0x75,0x6c,0x6c,0x2c,0x20,0x6e,0x75,0x6c,0x6c,
+ 0x2c,0x20,0x6e,0x75,0x6c,0x6c,0x2c,0x20,0x6e,0x75,0x6c,0x6c,0x29,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x4e,0x6f,0x20,0x62,0x72,0x6f,0x77,
+ 0x73,0x65,0x72,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x73,0x20,0x61,0x72,0x65,0x20,
+ 0x6f,0x70,0x65,0x6e,0x2c,0x20,0x73,0x6f,0x20,0x6f,0x70,0x65,0x6e,0x20,0x61,0x20,
+ 0x6e,0x65,0x77,0x20,0x6f,0x6e,0x65,0x2e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x77,
+ 0x69,0x6e,0x64,0x6f,0x77,0x2e,0x6f,0x70,0x65,0x6e,0x28,0x75,0x72,0x6c,0x29,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x7d,0x0a,0x7d,0x0a,0x0a,0x66,0x75,
+ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x76,0x69,0x65,0x77,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,0x6f,0x70,0x65,
+ 0x6e,0x41,0x6e,0x64,0x52,0x65,0x75,0x73,0x65,0x4f,0x6e,0x65,0x54,0x61,0x62,0x50,
+ 0x65,0x72,0x55,0x52,0x4c,0x28,0x27,0x63,0x68,0x72,0x6f,0x6d,0x65,0x3a,0x2f,0x2f,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2f,0x63,0x6f,0x6e,0x74,0x65,
+ 0x6e,0x74,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x68,0x74,
+ 0x6d,0x6c,0x27,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x70,0x61,0x64,
+ 0x28,0x73,0x29,0x20,0x7b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,
+ 0x30,0x30,0x30,0x30,0x27,0x2e,0x73,0x75,0x62,0x73,0x74,0x72,0x28,0x73,0x2e,0x6c,
+ 0x65,0x6e,0x67,0x74,0x68,0x29,0x20,0x2b,0x20,0x73,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,
+ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x71,0x75,0x6f,0x74,0x65,0x28,0x73,0x29,0x20,0x7b,0x0a,0x20,0x20,
+ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x22,0x27,0x20,0x2b,0x20,0x73,0x2e,0x72,
+ 0x65,0x70,0x6c,0x61,0x63,0x65,0x28,0x2f,0x5b,0x5c,0x75,0x30,0x30,0x30,0x30,0x2d,
+ 0x5c,0x75,0x30,0x30,0x31,0x66,0x22,0x5c,0x5c,0x5c,0x75,0x30,0x30,0x37,0x66,0x2d,
+ 0x5c,0x75,0x66,0x66,0x66,0x66,0x5d,0x2f,0x67,0x2c,0x20,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x28,0x63,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x73,0x77,
+ 0x69,0x74,0x63,0x68,0x20,0x28,0x63,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x63,
+ 0x61,0x73,0x65,0x20,0x27,0x5c,0x62,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x62,0x27,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x66,0x27,0x3a,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x66,0x27,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x6e,0x27,0x3a,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,
+ 0x6e,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x72,
+ 0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x27,0x5c,0x5c,0x72,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,
+ 0x27,0x5c,0x74,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,
+ 0x72,0x6e,0x20,0x27,0x5c,0x5c,0x74,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,
+ 0x73,0x65,0x20,0x27,0x5c,0x76,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,
+ 0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x76,0x27,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x22,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x22,0x27,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x5c,0x27,0x3a,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x5c,0x5c,
+ 0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x3a,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,
+ 0x75,0x27,0x20,0x2b,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x70,0x61,0x64,0x28,0x63,0x2e,0x63,0x68,0x61,0x72,0x43,0x6f,0x64,0x65,0x41,0x74,
+ 0x28,0x30,0x29,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,0x28,0x31,0x36,0x29,
+ 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x7d,0x29,0x20,0x2b,0x20,
+ 0x27,0x22,0x27,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,
+ 0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x74,0x6f,0x72,
+ 0x65,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x43,0x63,0x20,0x3d,0x20,0x43,0x6f,0x6d,
+ 0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0x2e,0x63,0x6c,0x61,0x73,0x73,0x65,0x73,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x43,0x69,0x20,0x3d,0x20,
+ 0x43,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0x2e,0x69,0x6e,0x74,0x65,0x72,
+ 0x66,0x61,0x63,0x65,0x73,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x64,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,0x53,0x65,0x72,0x76,0x69,0x63,0x65,
+ 0x20,0x3d,0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,
+ 0x6f,0x72,0x67,0x2f,0x66,0x69,0x6c,0x65,0x2f,0x64,0x69,0x72,0x65,0x63,0x74,0x6f,
+ 0x72,0x79,0x5f,0x73,0x65,0x72,0x76,0x69,0x63,0x65,0x3b,0x31,0x27,0x5d,0x2e,0x67,
+ 0x65,0x74,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,
+ 0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x29,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x44,0x69,0x72,0x65,0x63,
+ 0x74,0x6f,0x72,0x79,0x20,0x3d,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,
+ 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x2e,0x67,0x65,0x74,0x28,0x27,0x43,0x75,0x72,
+ 0x57,0x6f,0x72,0x6b,0x44,0x27,0x2c,0x20,0x43,0x69,0x2e,0x6e,0x73,0x49,0x4c,0x6f,
+ 0x63,0x61,0x6c,0x46,0x69,0x6c,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,
+ 0x70,0x6f,0x72,0x74,0x44,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,0x2e,0x61,0x70,
+ 0x70,0x65,0x6e,0x64,0x52,0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x50,0x61,0x74,0x68,
+ 0x28,0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x72,0x65,0x70,
+ 0x6f,0x72,0x74,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x21,
+ 0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x44,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,
+ 0x2e,0x65,0x78,0x69,0x73,0x74,0x73,0x28,0x29,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x44,0x69,0x72,0x65,0x63,0x74,0x6f,
+ 0x72,0x79,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,
+ 0x46,0x69,0x6c,0x65,0x2e,0x44,0x49,0x52,0x45,0x43,0x54,0x4f,0x52,0x59,0x5f,0x54,
+ 0x59,0x50,0x45,0x2c,0x20,0x30,0x37,0x35,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x6f,0x53,0x65,0x72,
+ 0x76,0x69,0x63,0x65,0x20,0x3d,0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,
+ 0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,0x6e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x2f,
+ 0x69,0x6f,0x2d,0x73,0x65,0x72,0x76,0x69,0x63,0x65,0x3b,0x31,0x27,0x5d,0x2e,0x67,
+ 0x65,0x74,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,
+ 0x49,0x4f,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,0x65,0x20,0x3d,
+ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x66,0x69,0x6c,0x65,0x6e,0x61,
+ 0x6d,0x65,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x63,0x68,0x61,0x6e,0x6e,0x65,0x6c,0x20,0x3d,0x20,0x69,0x6f,0x53,0x65,0x72,0x76,
+ 0x69,0x63,0x65,0x2e,0x6e,0x65,0x77,0x43,0x68,0x61,0x6e,0x6e,0x65,0x6c,0x28,0x27,
+ 0x63,0x68,0x72,0x6f,0x6d,0x65,0x3a,0x2f,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x2f,0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2f,0x27,0x20,0x2b,0x20,
+ 0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x6e,0x75,0x6c,0x6c,0x2c,0x20,
+ 0x6e,0x75,0x6c,0x6c,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x49,0x6e,0x70,0x75,0x74,0x53,0x74,0x72,0x65,
+ 0x61,0x6d,0x20,0x3d,0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,
+ 0x61,0x2e,0x6f,0x72,0x67,0x2f,0x62,0x69,0x6e,0x61,0x72,0x79,0x69,0x6e,0x70,0x75,
+ 0x74,0x73,0x74,0x72,0x65,0x61,0x6d,0x3b,0x31,0x27,0x5d,0x2e,0x63,0x72,0x65,0x61,
+ 0x74,0x65,0x49,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,
+ 0x49,0x42,0x69,0x6e,0x61,0x72,0x79,0x49,0x6e,0x70,0x75,0x74,0x53,0x74,0x72,0x65,
+ 0x61,0x6d,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x49,
+ 0x6e,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,0x73,0x65,0x74,0x49,0x6e,
+ 0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x28,0x63,0x68,0x61,0x6e,0x6e,0x65,
+ 0x6c,0x2e,0x6f,0x70,0x65,0x6e,0x28,0x29,0x29,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x20,0x3d,0x20,0x43,
+ 0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,
+ 0x66,0x69,0x6c,0x65,0x2f,0x6c,0x6f,0x63,0x61,0x6c,0x3b,0x31,0x27,0x5d,0x2e,0x63,
+ 0x72,0x65,0x61,0x74,0x65,0x49,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x28,0x43,0x69,
+ 0x2e,0x6e,0x73,0x49,0x4c,0x6f,0x63,0x61,0x6c,0x46,0x69,0x6c,0x65,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x2e,0x69,0x6e,0x69,
+ 0x74,0x57,0x69,0x74,0x68,0x46,0x69,0x6c,0x65,0x28,0x72,0x65,0x70,0x6f,0x72,0x74,
+ 0x44,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x52,
+ 0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x50,0x61,0x74,0x68,0x28,0x66,0x69,0x6c,0x65,
+ 0x6e,0x61,0x6d,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,
+ 0x65,0x61,0x6d,0x20,0x3d,0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,
+ 0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,0x6e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x2f,0x66,
+ 0x69,0x6c,0x65,0x2d,0x6f,0x75,0x74,0x70,0x75,0x74,0x2d,0x73,0x74,0x72,0x65,0x61,
+ 0x6d,0x3b,0x31,0x27,0x5d,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x49,0x6e,0x73,0x74,
+ 0x61,0x6e,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,0x46,0x69,0x6c,0x65,0x4f,
+ 0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x29,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,
+ 0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,0x69,0x6e,0x69,0x74,0x28,0x66,0x69,0x6c,0x65,
+ 0x2c,0x20,0x30,0x78,0x30,0x32,0x20,0x7c,0x20,0x30,0x78,0x30,0x38,0x20,0x7c,0x20,
+ 0x30,0x78,0x32,0x30,0x2c,0x20,0x30,0x36,0x34,0x34,0x2c,0x20,0x30,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x62,0x69,0x6e,0x61,
+ 0x72,0x79,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x20,0x3d,
+ 0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,
+ 0x67,0x2f,0x62,0x69,0x6e,0x61,0x72,0x79,0x6f,0x75,0x74,0x70,0x75,0x74,0x73,0x74,
+ 0x72,0x65,0x61,0x6d,0x3b,0x31,0x27,0x5d,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x49,
+ 0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,0x42,0x69,
+ 0x6e,0x61,0x72,0x79,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,
+ 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x69,0x6e,0x61,0x72,
+ 0x79,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,0x73,0x65,
+ 0x74,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x28,0x66,0x69,
+ 0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x29,0x3b,
+ 0x0a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,
+ 0x28,0x3b,0x3b,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x61,0x76,0x61,0x69,0x6c,0x61,0x62,0x6c,0x65,
+ 0x20,0x3d,0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x49,0x6e,0x70,0x75,0x74,0x53,0x74,
+ 0x72,0x65,0x61,0x6d,0x2e,0x61,0x76,0x61,0x69,0x6c,0x61,0x62,0x6c,0x65,0x28,0x29,
+ 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,
+ 0x20,0x28,0x61,0x76,0x61,0x69,0x6c,0x61,0x62,0x6c,0x65,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x30,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x62,0x72,0x65,0x61,0x6b,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x62,0x79,0x74,0x65,0x73,0x20,0x3d,0x20,
+ 0x62,0x69,0x6e,0x61,0x72,0x79,0x49,0x6e,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,
+ 0x6d,0x2e,0x72,0x65,0x61,0x64,0x42,0x79,0x74,0x65,0x73,0x28,0x61,0x76,0x61,0x69,
+ 0x6c,0x61,0x62,0x6c,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x4f,0x75,0x74,0x70,0x75,0x74,
+ 0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,0x77,0x72,0x69,0x74,0x65,0x42,0x79,0x74,0x65,
+ 0x73,0x28,0x62,0x79,0x74,0x65,0x73,0x2c,0x20,0x62,0x79,0x74,0x65,0x73,0x2e,0x6c,
+ 0x65,0x6e,0x67,0x74,0x68,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x7d,0x0a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,
+ 0x66,0x20,0x28,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x6a,0x73,0x27,0x29,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x73,0x20,0x3d,0x20,0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x69,0x73,0x52,0x65,0x70,0x6f,0x72,0x74,0x20,0x3d,0x20,0x74,0x72,
+ 0x75,0x65,0x3b,0x5c,0x6e,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x4f,0x75,0x74,0x70,0x75,0x74,
+ 0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x2c,0x20,
+ 0x73,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x69,0x6e,0x61,0x6c,0x6c,0x79,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x69,0x6e,
+ 0x61,0x72,0x79,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,
+ 0x63,0x6c,0x6f,0x73,0x65,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x66,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x49,0x6e,0x70,0x75,0x74,0x53,0x74,
+ 0x72,0x65,0x61,0x6d,0x2e,0x63,0x6c,0x6f,0x73,0x65,0x28,0x29,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,0x65,0x28,0x27,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x68,0x74,0x6d,0x6c,0x27,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,0x65,0x28,0x27,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x6a,0x73,0x27,0x29,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,0x65,0x28,
+ 0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x63,0x73,0x73,0x27,
+ 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,
+ 0x65,0x28,0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x74,0x68,
+ 0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x27,0x29,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,0x65,0x28,0x27,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,
+ 0x68,0x74,0x2e,0x63,0x73,0x73,0x27,0x29,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x2f,
+ 0x2f,0x20,0x77,0x72,0x69,0x74,0x65,0x20,0x74,0x68,0x65,0x20,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x20,0x64,0x61,0x74,0x61,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,
+ 0x72,0x20,0x66,0x69,0x6c,0x65,0x20,0x3d,0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,
+ 0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,0x66,0x69,0x6c,0x65,0x2f,0x6c,
+ 0x6f,0x63,0x61,0x6c,0x3b,0x31,0x27,0x5d,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x49,
+ 0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,0x4c,0x6f,
+ 0x63,0x61,0x6c,0x46,0x69,0x6c,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x69,
+ 0x6c,0x65,0x2e,0x69,0x6e,0x69,0x74,0x57,0x69,0x74,0x68,0x46,0x69,0x6c,0x65,0x28,
+ 0x72,0x65,0x70,0x6f,0x72,0x74,0x44,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,0x29,
+ 0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x2e,0x61,0x70,0x70,0x65,0x6e,
+ 0x64,0x52,0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x50,0x61,0x74,0x68,0x28,0x27,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x6a,0x73,0x6f,0x6e,0x27,0x29,
+ 0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x4f,0x75,
+ 0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x20,0x3d,0x20,0x43,0x63,0x5b,
+ 0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,0x6e,0x65,
+ 0x74,0x77,0x6f,0x72,0x6b,0x2f,0x66,0x69,0x6c,0x65,0x2d,0x6f,0x75,0x74,0x70,0x75,
+ 0x74,0x2d,0x73,0x74,0x72,0x65,0x61,0x6d,0x3b,0x31,0x27,0x5d,0x2e,0x63,0x72,0x65,
+ 0x61,0x74,0x65,0x49,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,
+ 0x73,0x49,0x46,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,
+ 0x61,0x6d,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,
+ 0x74,0x72,0x65,0x61,0x6d,0x2e,0x69,0x6e,0x69,0x74,0x28,0x66,0x69,0x6c,0x65,0x2c,
+ 0x20,0x30,0x78,0x30,0x32,0x20,0x7c,0x20,0x30,0x78,0x30,0x38,0x20,0x7c,0x20,0x30,
+ 0x78,0x32,0x30,0x2c,0x20,0x30,0x36,0x34,0x34,0x2c,0x20,0x30,0x29,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x77,0x72,
+ 0x69,0x74,0x65,0x28,0x73,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x66,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,
+ 0x6d,0x2e,0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x2c,0x20,0x73,0x2e,0x6c,0x65,0x6e,
+ 0x67,0x74,0x68,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,0x28,0x27,0x7b,0x27,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x72,0x73,0x74,0x20,
+ 0x3d,0x20,0x74,0x72,0x75,0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6f,
+ 0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x20,0x69,0x6e,0x20,0x5f,
+ 0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x29,0x20,0x7b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x66,0x69,0x72,0x73,0x74,
+ 0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x69,
+ 0x72,0x73,0x74,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,
+ 0x6c,0x73,0x65,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x77,0x72,0x69,0x74,0x65,0x28,0x27,0x2c,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x72,
+ 0x69,0x74,0x65,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x71,
+ 0x75,0x6f,0x74,0x65,0x28,0x66,0x69,0x6c,0x65,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,0x28,0x27,0x3a,0x7b,0x22,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x22,0x3a,0x5b,0x27,0x29,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x20,0x3d,0x20,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5b,0x66,0x69,0x6c,0x65,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3d,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,
+ 0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x30,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3c,
+ 0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x2b,0x2b,0x29,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x6c,0x69,0x6e,0x65,0x20,0x3e,0x20,0x30,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,0x28,0x27,
+ 0x2c,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x76,
+ 0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,
+ 0x6c,0x69,0x6e,0x65,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x69,0x66,0x20,0x28,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x75,
+ 0x6e,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x20,0x7c,0x7c,0x20,0x76,0x61,0x6c,0x75,
+ 0x65,0x20,0x3d,0x3d,0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x29,0x20,0x7b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,
+ 0x3d,0x20,0x27,0x6e,0x75,0x6c,0x6c,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x77,0x72,0x69,0x74,0x65,0x28,0x76,0x61,0x6c,0x75,0x65,0x2e,0x74,0x6f,0x53,0x74,
+ 0x72,0x69,0x6e,0x67,0x28,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,
+ 0x28,0x27,0x5d,0x2c,0x22,0x73,0x6f,0x75,0x72,0x63,0x65,0x22,0x3a,0x5b,0x27,0x29,
+ 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x6f,
+ 0x75,0x72,0x63,0x65,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,
+ 0x73,0x6f,0x75,0x72,0x63,0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3d,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x2e,
+ 0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x66,0x6f,0x72,0x20,0x28,0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x30,0x3b,0x20,0x6c,
+ 0x69,0x6e,0x65,0x20,0x3c,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x6c,0x69,
+ 0x6e,0x65,0x2b,0x2b,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x6c,0x69,0x6e,0x65,0x20,0x3e,0x20,0x30,0x29,0x20,
+ 0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x72,
+ 0x69,0x74,0x65,0x28,0x27,0x2c,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x77,0x72,0x69,0x74,0x65,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x71,0x75,0x6f,0x74,0x65,0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x5b,0x6c,0x69,
+ 0x6e,0x65,0x5d,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,0x28,0x27,
+ 0x5d,0x7d,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,0x28,0x27,0x7d,0x27,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x61,0x6c,0x65,0x72,0x74,0x28,0x27,0x43,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x20,0x64,0x61,0x74,0x61,0x20,0x73,0x74,0x6f,0x72,0x65,
+ 0x64,0x2e,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,
+ 0x66,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x66,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,
+ 0x2e,0x63,0x6c,0x6f,0x73,0x65,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,
+ 0x20,0x20,0x7d,0x0a,0x20,0x20,0x63,0x61,0x74,0x63,0x68,0x20,0x28,0x65,0x29,0x20,
+ 0x7b,0x0a,0x20,0x20,0x20,0x20,0x61,0x6c,0x65,0x72,0x74,0x28,0x65,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x64,0x75,0x6d,0x70,0x28,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x64,0x75,0x6d,0x70,0x28,0x27,0x5c,0x6e,0x27,0x29,0x3b,0x0a,0x20,0x20,0x7d,
+ 0x0a,0x7d,0x0a,
+};
+const unsigned char RESOURCE7_[] = {
+
+ 0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x68,0x74,0x6d,0x6c,0x3e,0x0d,
+ 0x0a,0x3c,0x21,0x2d,0x2d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x2e,0x68,0x74,0x6d,0x6c,0x20,0x2d,0x20,0x63,0x6f,0x64,
+ 0x65,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x66,0x6f,0x72,0x20,0x4a,
+ 0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x0d,0x0a,0x20,0x20,0x20,0x20,0x43,
+ 0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30,
+ 0x37,0x2c,0x20,0x32,0x30,0x30,0x38,0x20,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,
+ 0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,
+ 0x66,0x72,0x65,0x65,0x20,0x73,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x3b,0x20,0x79,
+ 0x6f,0x75,0x20,0x63,0x61,0x6e,0x20,0x72,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,
+ 0x75,0x74,0x65,0x20,0x69,0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x6d,0x6f,
+ 0x64,0x69,0x66,0x79,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,0x75,0x6e,0x64,
+ 0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,
+ 0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,
+ 0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,
+ 0x73,0x20,0x70,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,0x79,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,
+ 0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,
+ 0x3b,0x20,0x65,0x69,0x74,0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,
+ 0x20,0x32,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,
+ 0x65,0x2c,0x20,0x6f,0x72,0x0d,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,0x79,
+ 0x6f,0x75,0x72,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,0x20,
+ 0x6c,0x61,0x74,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
+ 0x61,0x6d,0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,
+ 0x64,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,
+ 0x61,0x74,0x20,0x69,0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,
+ 0x65,0x66,0x75,0x6c,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,
+ 0x49,0x54,0x48,0x4f,0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,
+ 0x4e,0x54,0x59,0x3b,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,
+ 0x6e,0x20,0x74,0x68,0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,
+ 0x72,0x72,0x61,0x6e,0x74,0x79,0x20,0x6f,0x66,0x0d,0x0a,0x20,0x20,0x20,0x20,0x4d,
+ 0x45,0x52,0x43,0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,
+ 0x72,0x20,0x46,0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,
+ 0x50,0x41,0x52,0x54,0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,
+ 0x53,0x45,0x2e,0x20,0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,
+ 0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,
+ 0x20,0x6d,0x6f,0x72,0x65,0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,
+ 0x20,0x68,0x61,0x76,0x65,0x20,0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,
+ 0x20,0x63,0x6f,0x70,0x79,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,
+ 0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,
+ 0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,
+ 0x67,0x72,0x61,0x6d,0x3b,0x20,0x69,0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,
+ 0x69,0x74,0x65,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,
+ 0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,
+ 0x69,0x6f,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x35,0x31,0x20,0x46,0x72,0x61,0x6e,0x6b,0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,
+ 0x65,0x74,0x2c,0x20,0x46,0x69,0x66,0x74,0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,
+ 0x20,0x42,0x6f,0x73,0x74,0x6f,0x6e,0x2c,0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,
+ 0x30,0x2d,0x31,0x33,0x30,0x31,0x20,0x55,0x53,0x41,0x2e,0x0d,0x0a,0x2d,0x2d,0x3e,
+ 0x0d,0x0a,0x0d,0x0a,0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,
+ 0x64,0x3e,0x0d,0x0a,0x3c,0x74,0x69,0x74,0x6c,0x65,0x3e,0x4a,0x53,0x43,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x0d,0x0a,0x3c,
+ 0x6c,0x69,0x6e,0x6b,0x20,0x72,0x65,0x6c,0x3d,0x22,0x73,0x74,0x79,0x6c,0x65,0x73,
+ 0x68,0x65,0x65,0x74,0x22,0x20,0x74,0x79,0x70,0x65,0x3d,0x22,0x74,0x65,0x78,0x74,
+ 0x2f,0x63,0x73,0x73,0x22,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,
+ 0x2e,0x63,0x73,0x73,0x22,0x3e,0x0d,0x0a,0x3c,0x6c,0x69,0x6e,0x6b,0x20,0x72,0x65,
+ 0x6c,0x3d,0x22,0x73,0x74,0x79,0x6c,0x65,0x73,0x68,0x65,0x65,0x74,0x22,0x20,0x74,
+ 0x79,0x70,0x65,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x63,0x73,0x73,0x22,0x20,0x68,
+ 0x72,0x65,0x66,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,
+ 0x63,0x73,0x73,0x22,0x3e,0x0d,0x0a,0x3c,0x21,0x2d,0x2d,0x5b,0x69,0x66,0x20,0x49,
+ 0x45,0x5d,0x3e,0x0d,0x0a,0x3c,0x6c,0x69,0x6e,0x6b,0x20,0x72,0x65,0x6c,0x3d,0x22,
+ 0x73,0x74,0x79,0x6c,0x65,0x73,0x68,0x65,0x65,0x74,0x22,0x20,0x74,0x79,0x70,0x65,
+ 0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x63,0x73,0x73,0x22,0x20,0x68,0x72,0x65,0x66,
+ 0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x69,0x65,0x2e,
+ 0x63,0x73,0x73,0x22,0x3e,0x0d,0x0a,0x3c,0x21,0x5b,0x65,0x6e,0x64,0x69,0x66,0x5d,
+ 0x2d,0x2d,0x3e,0x0d,0x0a,0x3c,0x73,0x63,0x72,0x69,0x70,0x74,0x20,0x74,0x79,0x70,
+ 0x65,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x6a,0x61,0x76,0x61,0x73,0x63,0x72,0x69,
+ 0x70,0x74,0x22,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x2e,0x6a,0x73,0x22,0x3e,0x3c,0x2f,0x73,0x63,0x72,0x69,0x70,0x74,
+ 0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x0d,0x0a,0x3c,0x62,
+ 0x6f,0x64,0x79,0x20,0x6f,0x6e,0x6c,0x6f,0x61,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x6f,0x64,0x79,0x5f,0x6c,0x6f,0x61,0x64,
+ 0x28,0x29,0x3b,0x22,0x20,0x6f,0x6e,0x72,0x65,0x73,0x69,0x7a,0x65,0x3d,0x22,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x6f,0x64,0x79,0x5f,0x72,
+ 0x65,0x73,0x69,0x7a,0x65,0x28,0x29,0x3b,0x22,0x3e,0x0d,0x0a,0x3c,0x64,0x69,0x76,
+ 0x20,0x69,0x64,0x3d,0x22,0x6d,0x61,0x69,0x6e,0x44,0x69,0x76,0x22,0x3e,0x0d,0x0a,
+ 0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x68,0x65,0x61,0x64,0x69,0x6e,0x67,
+ 0x44,0x69,0x76,0x22,0x3e,0x0d,0x0a,0x3c,0x68,0x31,0x3e,0x4a,0x53,0x43,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x3c,0x64,0x69,0x76,
+ 0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x42,0x61,0x72,0x22,0x20,0x69,0x64,0x3d,0x22,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,
+ 0x73,0x42,0x61,0x72,0x22,0x3e,0x3c,0x73,0x70,0x61,0x6e,0x20,0x63,0x6c,0x61,0x73,
+ 0x73,0x3d,0x22,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x50,0x65,0x72,0x63,0x65,
+ 0x6e,0x74,0x61,0x67,0x65,0x22,0x3e,0x3c,0x2f,0x73,0x70,0x61,0x6e,0x3e,0x3c,0x64,
+ 0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x50,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x47,0x72,0x61,0x70,0x68,0x22,0x3e,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,
+ 0x61,0x73,0x73,0x3d,0x22,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x43,0x6f,0x76,
+ 0x65,0x72,0x65,0x64,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x3c,0x2f,0x64,0x69,
+ 0x76,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x3c,0x73,0x70,0x61,0x6e,0x20,
+ 0x69,0x64,0x3d,0x22,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x4c,0x61,0x62,0x65,
+ 0x6c,0x22,0x3e,0x3c,0x2f,0x73,0x70,0x61,0x6e,0x3e,0x0d,0x0a,0x3c,0x2f,0x64,0x69,
+ 0x76,0x3e,0x0d,0x0a,0x0d,0x0a,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x74,
+ 0x61,0x62,0x73,0x22,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x54,0x61,0x62,0x73,
+ 0x22,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x62,
+ 0x72,0x6f,0x77,0x73,0x65,0x72,0x54,0x61,0x62,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,
+ 0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,
+ 0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,0x6c,
+ 0x74,0x3d,0x22,0x22,0x3e,0x20,0x42,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x3c,0x69,
+ 0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,
+ 0x20,0x61,0x6c,0x74,0x3d,0x22,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,
+ 0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x75,0x6d,0x6d,0x61,
+ 0x72,0x79,0x54,0x61,0x62,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x69,0x64,0x3d,0x22,
+ 0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x22,
+ 0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,
+ 0x6c,0x74,0x3d,0x22,0x22,0x3e,0x20,0x53,0x75,0x6d,0x6d,0x61,0x72,0x79,0x20,0x3c,
+ 0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,
+ 0x22,0x20,0x61,0x6c,0x74,0x3d,0x22,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,
+ 0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x6f,0x75,0x72,
+ 0x63,0x65,0x54,0x61,0x62,0x22,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x64,0x69,
+ 0x73,0x61,0x62,0x6c,0x65,0x64,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,
+ 0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x74,0x68,0x72,
+ 0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,0x6c,0x74,0x3d,0x22,
+ 0x22,0x3e,0x20,0x53,0x6f,0x75,0x72,0x63,0x65,0x20,0x3c,0x69,0x6d,0x67,0x20,0x73,
+ 0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x74,
+ 0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,0x6c,0x74,
+ 0x3d,0x22,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x64,
+ 0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x74,0x6f,0x72,0x65,0x54,0x61,0x62,0x22,
+ 0x3e,0x3c,0x69,0x6d,0x67,0x20,0x69,0x64,0x3d,0x22,0x73,0x74,0x6f,0x72,0x65,0x54,
+ 0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x22,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,
+ 0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,0x6c,0x74,0x3d,0x22,0x22,0x3e,0x20,0x53,
+ 0x74,0x6f,0x72,0x65,0x20,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,
+ 0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,0x6c,0x74,0x3d,0x22,0x22,0x3e,0x3c,
+ 0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,
+ 0x3d,0x22,0x61,0x62,0x6f,0x75,0x74,0x54,0x61,0x62,0x22,0x3e,0x3c,0x69,0x6d,0x67,
+ 0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,
+ 0x6c,0x74,0x3d,0x22,0x22,0x3e,0x20,0x41,0x62,0x6f,0x75,0x74,0x20,0x3c,0x69,0x6d,
+ 0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,
+ 0x61,0x6c,0x74,0x3d,0x22,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x3c,
+ 0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,
+ 0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x22,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,
+ 0x22,0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x3c,
+ 0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x54,0x61,0x62,0x50,0x61,
+ 0x67,0x65,0x22,0x20,0x69,0x64,0x3d,0x22,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x54,
+ 0x61,0x62,0x50,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x64,
+ 0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x44,
+ 0x69,0x76,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x55,0x52,0x4c,0x3a,0x20,0x3c,
+ 0x69,0x6e,0x70,0x75,0x74,0x20,0x69,0x64,0x3d,0x22,0x6c,0x6f,0x63,0x61,0x74,0x69,
+ 0x6f,0x6e,0x22,0x20,0x74,0x79,0x70,0x65,0x3d,0x22,0x74,0x65,0x78,0x74,0x22,0x20,
+ 0x73,0x69,0x7a,0x65,0x3d,0x22,0x37,0x30,0x22,0x20,0x6f,0x6e,0x6b,0x65,0x79,0x70,
+ 0x72,0x65,0x73,0x73,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x69,0x6e,0x70,0x75,0x74,0x5f,0x6b,0x65,0x79,0x70,0x72,0x65,0x73,0x73,0x28,
+ 0x65,0x76,0x65,0x6e,0x74,0x29,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x62,
+ 0x75,0x74,0x74,0x6f,0x6e,0x20,0x6f,0x6e,0x63,0x6c,0x69,0x63,0x6b,0x3d,0x22,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x75,0x74,0x74,0x6f,0x6e,
+ 0x5f,0x63,0x6c,0x69,0x63,0x6b,0x28,0x29,0x3b,0x22,0x3e,0x47,0x6f,0x3c,0x2f,0x62,
+ 0x75,0x74,0x74,0x6f,0x6e,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x64,0x69,
+ 0x76,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,
+ 0x22,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x22,0x3e,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x3c,0x69,0x66,0x72,0x61,0x6d,0x65,0x20,0x69,0x64,0x3d,0x22,0x62,0x72,
+ 0x6f,0x77,0x73,0x65,0x72,0x49,0x66,0x72,0x61,0x6d,0x65,0x22,0x20,0x6f,0x6e,0x6c,
+ 0x6f,0x61,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x5f,0x6c,0x6f,0x61,0x64,0x28,0x29,0x3b,0x22,
+ 0x3e,0x3c,0x2f,0x69,0x66,0x72,0x61,0x6d,0x65,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x2f,0x64,0x69,0x76,0x3e,
+ 0x0d,0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,
+ 0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x69,0x6e,0x70,0x75,0x74,0x20,0x74,0x79,0x70,0x65,0x3d,0x22,0x63,0x68,0x65,0x63,
+ 0x6b,0x62,0x6f,0x78,0x22,0x20,0x69,0x64,0x3d,0x22,0x63,0x68,0x65,0x63,0x6b,0x62,
+ 0x6f,0x78,0x22,0x20,0x6f,0x6e,0x63,0x6c,0x69,0x63,0x6b,0x3d,0x22,0x72,0x65,0x74,
+ 0x75,0x72,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,
+ 0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x5f,0x63,0x6c,0x69,0x63,0x6b,0x28,0x29,0x3b,
+ 0x22,0x3e,0x20,0x3c,0x6c,0x61,0x62,0x65,0x6c,0x20,0x66,0x6f,0x72,0x3d,0x22,0x63,
+ 0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x22,0x3e,0x53,0x68,0x6f,0x77,0x20,0x6d,0x69,
+ 0x73,0x73,0x69,0x6e,0x67,0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,
+ 0x20,0x63,0x6f,0x6c,0x75,0x6d,0x6e,0x3c,0x2f,0x6c,0x61,0x62,0x65,0x6c,0x3e,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x75,
+ 0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,
+ 0x45,0x72,0x72,0x6f,0x72,0x44,0x69,0x76,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x69,0x64,0x3d,
+ 0x22,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x22,0x3e,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x3c,0x74,0x72,0x20,0x69,0x64,0x3d,0x22,0x68,0x65,0x61,0x64,0x65,0x72,
+ 0x52,0x6f,0x77,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x68,0x20,0x63,
+ 0x6c,0x61,0x73,0x73,0x3d,0x22,0x6c,0x65,0x66,0x74,0x43,0x6f,0x6c,0x75,0x6d,0x6e,
+ 0x22,0x3e,0x46,0x69,0x6c,0x65,0x3c,0x2f,0x74,0x68,0x3e,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x3c,0x74,0x68,0x3e,0x3c,0x61,0x62,0x62,0x72,0x20,0x74,0x69,0x74,0x6c,0x65,
+ 0x3d,0x22,0x54,0x68,0x65,0x20,0x74,0x6f,0x74,0x61,0x6c,0x20,0x6e,0x75,0x6d,0x62,
+ 0x65,0x72,0x20,0x6f,0x66,0x20,0x65,0x78,0x65,0x63,0x75,0x74,0x61,0x62,0x6c,0x65,
+ 0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x22,0x3e,0x53,0x74,0x61,
+ 0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x3c,0x2f,0x61,0x62,0x62,0x72,0x3e,0x3c,0x2f,
+ 0x74,0x68,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x68,0x3e,0x3c,0x61,0x62,
+ 0x62,0x72,0x20,0x74,0x69,0x74,0x6c,0x65,0x3d,0x22,0x54,0x68,0x65,0x20,0x6e,0x75,
+ 0x6d,0x62,0x65,0x72,0x20,0x6f,0x66,0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,
+ 0x74,0x73,0x20,0x61,0x63,0x74,0x75,0x61,0x6c,0x6c,0x79,0x20,0x65,0x78,0x65,0x63,
+ 0x75,0x74,0x65,0x64,0x22,0x3e,0x45,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x3c,0x2f,
+ 0x61,0x62,0x62,0x72,0x3e,0x3c,0x2f,0x74,0x68,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x3c,0x74,0x68,0x3e,0x3c,0x61,0x62,0x62,0x72,0x20,0x74,0x69,0x74,0x6c,0x65,0x3d,
+ 0x22,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x6f,0x66,0x20,0x65,0x78,0x65,0x63,0x75,
+ 0x74,0x65,0x64,0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,0x61,
+ 0x73,0x20,0x61,0x20,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x20,0x6f,
+ 0x66,0x20,0x74,0x6f,0x74,0x61,0x6c,0x20,0x6e,0x75,0x6d,0x62,0x65,0x72,0x20,0x6f,
+ 0x66,0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x22,0x3e,0x43,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x3c,0x2f,0x61,0x62,0x62,0x72,0x3e,0x3c,0x2f,0x74,
+ 0x68,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x72,0x3e,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x3c,0x74,0x72,0x20,0x69,0x64,0x3d,0x22,0x73,0x75,0x6d,0x6d,0x61,
+ 0x72,0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x3c,0x74,0x64,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x6c,
+ 0x65,0x66,0x74,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x73,0x70,0x61,0x6e,0x20,0x63,
+ 0x6c,0x61,0x73,0x73,0x3d,0x22,0x74,0x69,0x74,0x6c,0x65,0x22,0x3e,0x54,0x6f,0x74,
+ 0x61,0x6c,0x3a,0x3c,0x2f,0x73,0x70,0x61,0x6e,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x73,0x70,0x61,0x6e,0x3e,0x30,0x3c,
+ 0x2f,0x73,0x70,0x61,0x6e,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,
+ 0x74,0x64,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x6e,0x75,0x6d,0x65,0x72,0x69,
+ 0x63,0x22,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x3c,0x74,0x64,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x6e,0x75,
+ 0x6d,0x65,0x72,0x69,0x63,0x22,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74,0x64,0x20,0x63,0x6c,0x61,0x73,0x73,
+ 0x3d,0x22,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x63,
+ 0x6c,0x61,0x73,0x73,0x3d,0x22,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x22,0x3e,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x63,0x6f,
+ 0x76,0x65,0x72,0x65,0x64,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x64,0x69,0x76,
+ 0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,
+ 0x73,0x70,0x61,0x6e,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x70,0x63,0x74,0x22,
+ 0x3e,0x30,0x25,0x3c,0x2f,0x73,0x70,0x61,0x6e,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x2f,0x74,0x72,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x68,
+ 0x65,0x61,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x62,0x6f,0x64,0x79,
+ 0x20,0x69,0x64,0x3d,0x22,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x62,0x6f,0x64,
+ 0x79,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x21,0x2d,0x2d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x72,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x74,0x64,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x74,0x64,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x74,0x64,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x74,0x64,0x3e,0x30,0x25,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x3c,0x74,0x64,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x3c,0x2f,0x74,0x72,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2d,0x2d,0x3e,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65,0x3e,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x2f,0x64,0x69,
+ 0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,
+ 0x3d,0x22,0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x66,0x69,0x6c,0x65,0x44,0x69,
+ 0x76,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,
+ 0x76,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x2f,0x64,
+ 0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,
+ 0x73,0x3d,0x22,0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x22,0x20,0x69,0x64,0x3d,0x22,
+ 0x73,0x74,0x6f,0x72,0x65,0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x3c,0x62,0x75,0x74,0x74,0x6f,0x6e,0x20,0x69,0x64,0x3d,0x22,
+ 0x73,0x74,0x6f,0x72,0x65,0x42,0x75,0x74,0x74,0x6f,0x6e,0x22,0x20,0x6f,0x6e,0x63,
+ 0x6c,0x69,0x63,0x6b,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x73,0x74,0x6f,0x72,0x65,0x42,0x75,0x74,0x74,0x6f,0x6e,0x5f,0x63,0x6c,0x69,
+ 0x63,0x6b,0x28,0x29,0x3b,0x22,0x3e,0x53,0x74,0x6f,0x72,0x65,0x20,0x52,0x65,0x70,
+ 0x6f,0x72,0x74,0x3c,0x2f,0x62,0x75,0x74,0x74,0x6f,0x6e,0x3e,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x3c,0x69,0x6d,0x67,0x20,0x69,0x64,0x3d,0x22,0x73,0x74,0x6f,0x72,0x65,
+ 0x49,0x6d,0x67,0x22,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,
+ 0x66,0x22,0x20,0x61,0x6c,0x74,0x3d,0x22,0x6c,0x6f,0x61,0x64,0x69,0x6e,0x67,0x2e,
+ 0x2e,0x2e,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,
+ 0x64,0x3d,0x22,0x73,0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x22,0x3e,0x3c,0x2f,0x64,
+ 0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,
+ 0x20,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x54,0x61,0x62,
+ 0x50,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x70,0x3e,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x76,0x65,0x72,
+ 0x73,0x69,0x6f,0x6e,0x20,0x30,0x2e,0x34,0x20,0x6f,0x66,0x20,0x4a,0x53,0x43,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x2c,0x20,0x61,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,
+ 0x6d,0x20,0x74,0x68,0x61,0x74,0x20,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,
+ 0x73,0x20,0x63,0x6f,0x64,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x20,0x73,0x74,0x61,0x74,0x69,0x73,0x74,0x69,0x63,0x73,0x20,
+ 0x66,0x6f,0x72,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x2e,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x70,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x53,0x65,0x65,0x20,0x3c,0x61,0x20,0x68,
+ 0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x69,0x6c,0x69,
+ 0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x2f,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,
+ 0x2f,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,
+ 0x6d,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2f,0x3c,0x2f,0x61,
+ 0x3e,0x20,0x66,0x6f,0x72,0x20,0x6d,0x6f,0x72,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72,
+ 0x6d,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x70,
+ 0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x26,0x63,0x6f,0x70,0x79,0x3b,
+ 0x20,0x32,0x30,0x30,0x37,0x2c,0x20,0x32,0x30,0x30,0x38,0x20,0x73,0x69,0x6c,0x69,
+ 0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x2f,0x64,0x69,0x76,0x3e,
+ 0x0d,0x0a,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x3c,0x2f,0x64,0x69,0x76,0x3e,
+ 0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74,0x6d,
+ 0x6c,0x3e,0x0d,0x0a,
+};
+const unsigned char RESOURCE8_[] = {
+
+ 0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x63,0x73,0x73,0x20,0x2d,0x20,0x63,0x6f,0x64,0x65,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x66,0x6f,0x72,0x20,0x4a,0x61,0x76,0x61,0x53,
+ 0x63,0x72,0x69,0x70,0x74,0x0d,0x0a,0x20,0x20,0x20,0x20,0x43,0x6f,0x70,0x79,0x72,
+ 0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30,0x37,0x2c,0x20,0x32,
+ 0x30,0x30,0x38,0x20,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,
+ 0x2e,0x63,0x6f,0x6d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,
+ 0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,0x66,0x72,0x65,0x65,
+ 0x20,0x73,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x3b,0x20,0x79,0x6f,0x75,0x20,0x63,
+ 0x61,0x6e,0x20,0x72,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x20,
+ 0x69,0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,0x75,0x6e,0x64,0x65,0x72,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,
+ 0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,
+ 0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x73,0x20,0x70,0x75,
+ 0x62,0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,0x79,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,
+ 0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x3b,0x20,0x65,0x69,
+ 0x74,0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x32,0x20,0x6f,
+ 0x66,0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x2c,0x20,0x6f,
+ 0x72,0x0d,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,0x79,0x6f,0x75,0x72,0x20,
+ 0x6f,0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,0x20,0x6c,0x61,0x74,0x65,
+ 0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,
+ 0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x69,0x6e,
+ 0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x69,
+ 0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x66,0x75,0x6c,
+ 0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,0x49,0x54,0x48,0x4f,
+ 0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x59,0x3b,
+ 0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,0x6e,0x20,0x74,0x68,
+ 0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,0x72,0x72,0x61,0x6e,
+ 0x74,0x79,0x20,0x6f,0x66,0x0d,0x0a,0x20,0x20,0x20,0x20,0x4d,0x45,0x52,0x43,0x48,
+ 0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,0x72,0x20,0x46,0x49,
+ 0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,0x50,0x41,0x52,0x54,
+ 0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,0x53,0x45,0x2e,0x20,
+ 0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x47,0x4e,
+ 0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,
+ 0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,0x20,0x6d,0x6f,0x72,
+ 0x65,0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x68,0x61,0x76,
+ 0x65,0x20,0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,0x63,0x6f,0x70,
+ 0x79,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,
+ 0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,
+ 0x6e,0x73,0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0d,0x0a,0x20,0x20,0x20,0x20,0x77,
+ 0x69,0x74,0x68,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,
+ 0x3b,0x20,0x69,0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,0x65,0x20,
+ 0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,
+ 0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x2c,
+ 0x20,0x49,0x6e,0x63,0x2e,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,0x20,0x46,
+ 0x72,0x61,0x6e,0x6b,0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,0x2c,0x20,
+ 0x46,0x69,0x66,0x74,0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,0x6f,0x73,
+ 0x74,0x6f,0x6e,0x2c,0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,0x31,0x33,
+ 0x30,0x31,0x20,0x55,0x53,0x41,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,0x0a,0x62,
+ 0x6f,0x64,0x79,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,
+ 0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x62,0x66,0x66,0x66,
+ 0x62,0x66,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x66,0x61,0x6d,0x69,
+ 0x6c,0x79,0x3a,0x20,0x73,0x61,0x6e,0x73,0x2d,0x73,0x65,0x72,0x69,0x66,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x3a,0x20,0x31,0x30,
+ 0x30,0x25,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x3a,0x20,0x30,
+ 0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x6d,0x61,0x69,0x6e,0x44,0x69,0x76,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x3a,
+ 0x20,0x30,0x2e,0x38,0x31,0x32,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x23,0x68,0x65,0x61,0x64,0x69,0x6e,0x67,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,0x73,0x6f,
+ 0x6c,0x75,0x74,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,0x30,0x2e,
+ 0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x2e,
+ 0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,
+ 0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,
+ 0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x69,0x6e,0x65,0x2d,0x68,0x65,0x69,0x67,
+ 0x68,0x74,0x3a,0x20,0x31,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x68,0x31,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,
+ 0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x3a,
+ 0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x62,
+ 0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x30,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x3a,0x20,0x31,0x2e,0x33,0x65,
+ 0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x50,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x42,0x61,0x72,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
+ 0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x69,0x73,0x69,0x62,
+ 0x69,0x6c,0x69,0x74,0x79,0x3a,0x20,0x68,0x69,0x64,0x64,0x65,0x6e,0x3b,0x0d,0x0a,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x50,0x65,
+ 0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x64,0x69,
+ 0x73,0x70,0x6c,0x61,0x79,0x3a,0x20,0x62,0x6c,0x6f,0x63,0x6b,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x74,0x65,0x78,0x74,0x2d,0x61,0x6c,0x69,0x67,0x6e,0x3a,0x20,0x72,0x69,0x67,0x68,
+ 0x74,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x50,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x47,0x72,0x61,0x70,0x68,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6c,0x6f,
+ 0x61,0x74,0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x77,0x69,0x64,
+ 0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,
+ 0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x62,
+ 0x6f,0x72,0x64,0x65,0x72,0x3a,0x20,0x31,0x70,0x78,0x20,0x73,0x6f,0x6c,0x69,0x64,
+ 0x20,0x62,0x6c,0x61,0x63,0x6b,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,
+ 0x6e,0x2d,0x74,0x6f,0x70,0x3a,0x20,0x30,0x2e,0x33,0x65,0x6d,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,
+ 0x72,0x3a,0x20,0x23,0x64,0x34,0x64,0x30,0x63,0x38,0x3b,0x0d,0x0a,0x20,0x20,0x6f,
+ 0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x68,0x69,0x64,0x64,0x65,0x6e,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x43,0x6f,0x76,0x65,0x72,0x65,0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x20,
+ 0x77,0x69,0x6e,0x64,0x6f,0x77,0x73,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x20,0x63,
+ 0x6f,0x6c,0x6f,0x72,0x20,0x41,0x63,0x74,0x69,0x76,0x65,0x43,0x61,0x70,0x74,0x69,
+ 0x6f,0x6e,0x20,0x6f,0x72,0x20,0x48,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,0x20,
+ 0x2a,0x2f,0x0d,0x0a,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,
+ 0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x30,0x61,0x32,0x34,0x36,0x61,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x30,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x6f,0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x68,0x69,0x64,0x64,
+ 0x65,0x6e,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x70,0x72,0x6f,0x67,0x72,
+ 0x65,0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x64,0x69,
+ 0x73,0x70,0x6c,0x61,0x79,0x3a,0x20,0x62,0x6c,0x6f,0x63,0x6b,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x6c,0x65,0x66,0x74,0x3a,0x20,0x30,
+ 0x2e,0x33,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0d,0x0a,0x62,0x72,
+ 0x6f,0x77,0x73,0x65,0x72,0x20,0x74,0x61,0x62,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,
+ 0x0a,0x69,0x6e,0x70,0x75,0x74,0x23,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2c,
+ 0x20,0x62,0x75,0x74,0x74,0x6f,0x6e,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,
+ 0x64,0x65,0x72,0x3a,0x20,0x31,0x70,0x78,0x20,0x73,0x6f,0x6c,0x69,0x64,0x20,0x62,
+ 0x6c,0x61,0x63,0x6b,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,
+ 0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,
+ 0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x70,0x78,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,
+ 0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,
+ 0x20,0x61,0x62,0x73,0x6f,0x6c,0x75,0x74,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,
+ 0x70,0x3a,0x20,0x33,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,
+ 0x74,0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,
+ 0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,
+ 0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x69,0x66,0x72,
+ 0x61,0x6d,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,
+ 0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,
+ 0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0d,0x0a,0x73,
+ 0x75,0x6d,0x6d,0x61,0x72,0x79,0x20,0x74,0x61,0x62,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,
+ 0x0d,0x0a,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,0x73,
+ 0x6f,0x6c,0x75,0x74,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,0x33,
+ 0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x65,0x6d,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x65,0x6d,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x31,0x65,0x6d,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x6f,0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x61,0x75,
+ 0x74,0x6f,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x61,0x62,0x6c,0x65,0x23,
+ 0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x6c,0x65,0x66,0x74,0x3a,0x20,0x30,
+ 0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,
+ 0x67,0x68,0x74,0x3a,0x20,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,
+ 0x64,0x65,0x72,0x2d,0x63,0x6f,0x6c,0x6c,0x61,0x70,0x73,0x65,0x3a,0x20,0x63,0x6f,
+ 0x6c,0x6c,0x61,0x70,0x73,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,
+ 0x73,0x69,0x7a,0x65,0x3a,0x20,0x73,0x6d,0x61,0x6c,0x6c,0x3b,0x0d,0x0a,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x74,0x61,0x62,0x6c,0x65,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,
+ 0x54,0x61,0x62,0x6c,0x65,0x20,0x74,0x68,0x2c,0x20,0x74,0x61,0x62,0x6c,0x65,0x23,
+ 0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x20,0x74,0x64,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x2d,0x6c,0x65,0x66,0x74,
+ 0x3a,0x20,0x31,0x70,0x78,0x20,0x73,0x6f,0x6c,0x69,0x64,0x20,0x23,0x64,0x39,0x64,
+ 0x39,0x64,0x39,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x61,0x62,0x6c,0x65,
+ 0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x20,0x74,0x68,
+ 0x2e,0x6c,0x65,0x66,0x74,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x2c,0x20,0x74,0x61,0x62,
+ 0x6c,0x65,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x20,
+ 0x74,0x64,0x2e,0x6c,0x65,0x66,0x74,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x2d,0x6c,0x65,0x66,0x74,0x2d,0x77,
+ 0x69,0x64,0x74,0x68,0x3a,0x20,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x74,0x61,0x62,0x6c,0x65,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,
+ 0x62,0x6c,0x65,0x20,0x74,0x68,0x2c,0x20,0x74,0x61,0x62,0x6c,0x65,0x23,0x73,0x75,
+ 0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x20,0x74,0x64,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x3a,0x20,0x32,0x70,0x78,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x68,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,
+ 0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,
+ 0x20,0x23,0x65,0x36,0x66,0x66,0x65,0x36,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x74,0x64,0x2e,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x74,0x65,0x78,0x74,0x2d,0x61,0x6c,0x69,0x67,0x6e,0x3a,0x20,0x72,0x69,0x67,0x68,
+ 0x74,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x61,0x62,0x62,0x72,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x3a,0x20,0x68,0x65,0x6c,0x70,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x72,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,
+ 0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x20,0x74,0x64,0x2e,0x6c,0x65,0x66,0x74,0x43,
+ 0x6f,0x6c,0x75,0x6d,0x6e,0x20,0x73,0x70,0x61,0x6e,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x72,0x69,0x67,0x68,0x74,0x3b,0x0d,
+ 0x0a,0x7d,0x0d,0x0a,0x74,0x72,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x6f,
+ 0x74,0x61,0x6c,0x73,0x20,0x74,0x64,0x2e,0x6c,0x65,0x66,0x74,0x43,0x6f,0x6c,0x75,
+ 0x6d,0x6e,0x20,0x73,0x70,0x61,0x6e,0x2e,0x74,0x69,0x74,0x6c,0x65,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x6c,0x65,0x66,0x74,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x77,0x65,0x69,0x67,
+ 0x68,0x74,0x3a,0x20,0x62,0x6f,0x6c,0x64,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x74,0x72,
+ 0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x20,0x74,
+ 0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,
+ 0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x66,0x66,0x64,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x74,0x64,0x2e,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x31,
+ 0x35,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x74,0x64,0x2e,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x20,0x73,0x70,0x61,0x6e,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x72,0x69,0x67,0x68,0x74,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,
+ 0x74,0x3a,0x20,0x35,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x2e,0x70,0x63,0x74,
+ 0x47,0x72,0x61,0x70,0x68,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,0x64,
+ 0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x72,0x69,0x67,0x68,0x74,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3a,0x20,0x31,0x70,
+ 0x78,0x20,0x73,0x6f,0x6c,0x69,0x64,0x20,0x23,0x30,0x30,0x30,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,
+ 0x6c,0x6f,0x72,0x3a,0x20,0x23,0x65,0x30,0x30,0x30,0x30,0x30,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x6f,0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x68,0x69,0x64,
+ 0x64,0x65,0x6e,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,
+ 0x2d,0x74,0x6f,0x70,0x3a,0x20,0x34,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x2e,
+ 0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x20,0x2e,0x63,0x6f,0x76,0x65,0x72,0x65,
+ 0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,
+ 0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x30,0x30,0x66,0x30,
+ 0x30,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,
+ 0x30,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,
+ 0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x2e,0x70,0x63,0x74,0x47,0x72,
+ 0x61,0x70,0x68,0x20,0x2e,0x73,0x6b,0x69,0x70,0x70,0x65,0x64,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,
+ 0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x64,0x34,0x64,0x30,0x63,0x38,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x70,0x78,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,
+ 0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x74,0x62,0x6f,0x64,0x79,0x23,0x73,
+ 0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x62,0x6f,0x64,0x79,0x20,0x74,0x72,0x2e,0x65,
+ 0x76,0x65,0x6e,0x20,0x74,0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x61,
+ 0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,
+ 0x23,0x65,0x36,0x66,0x66,0x65,0x36,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0d,
+ 0x0a,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x74,0x61,0x62,0x0d,0x0a,0x2a,0x2f,0x0d,
+ 0x0a,0x0d,0x0a,0x23,0x66,0x69,0x6c,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x3a,0x20,0x6c,0x61,0x72,0x67,
+ 0x65,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x77,0x65,0x69,0x67,0x68,
+ 0x74,0x3a,0x20,0x62,0x6f,0x6c,0x64,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,
+ 0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,
+ 0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,0x73,0x6f,0x6c,0x75,0x74,
+ 0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,0x33,0x65,0x6d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x6f,0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,
+ 0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x61,0x62,0x6c,0x65,0x23,0x73,0x6f,0x75,0x72,
+ 0x63,0x65,0x54,0x61,0x62,0x6c,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,
+ 0x64,0x65,0x72,0x3a,0x20,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,
+ 0x64,0x65,0x72,0x2d,0x63,0x6f,0x6c,0x6c,0x61,0x70,0x73,0x65,0x3a,0x20,0x63,0x6f,
+ 0x6c,0x6c,0x61,0x70,0x73,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,
+ 0x73,0x69,0x7a,0x65,0x3a,0x20,0x73,0x6d,0x61,0x6c,0x6c,0x3b,0x0d,0x0a,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x2f,0x2a,0x0d,0x0a,0x49,0x45,0x20,0x64,0x65,0x66,0x61,0x75,0x6c,
+ 0x74,0x20,0x62,0x65,0x68,0x61,0x76,0x69,0x6f,0x72,0x20,0x69,0x73,0x20,0x74,0x6f,
+ 0x20,0x6d,0x61,0x6b,0x65,0x20,0x3c,0x70,0x72,0x65,0x3e,0x20,0x73,0x6d,0x61,0x6c,
+ 0x6c,0x65,0x72,0x20,0x74,0x68,0x61,0x6e,0x20,0x73,0x75,0x72,0x72,0x6f,0x75,0x6e,
+ 0x64,0x69,0x6e,0x67,0x20,0x74,0x65,0x78,0x74,0x2e,0x20,0x20,0x42,0x65,0x63,0x61,
+ 0x75,0x73,0x65,0x0d,0x0a,0x74,0x68,0x65,0x20,0x74,0x61,0x62,0x6c,0x65,0x20,0x61,
+ 0x6c,0x72,0x65,0x61,0x64,0x79,0x20,0x68,0x61,0x73,0x20,0x66,0x6f,0x6e,0x74,0x2d,
+ 0x73,0x69,0x7a,0x65,0x20,0x73,0x6d,0x61,0x6c,0x6c,0x2c,0x20,0x74,0x68,0x69,0x73,
+ 0x20,0x77,0x6f,0x75,0x6c,0x64,0x20,0x6d,0x61,0x6b,0x65,0x20,0x74,0x68,0x65,0x20,
+ 0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x20,0x77,0x69,0x74,0x68,0x69,0x6e,
+ 0x20,0x74,0x68,0x65,0x0d,0x0a,0x3c,0x70,0x72,0x65,0x3e,0x20,0x78,0x2d,0x73,0x6d,
+ 0x61,0x6c,0x6c,0x2e,0x20,0x20,0x53,0x6f,0x20,0x77,0x65,0x20,0x64,0x6f,0x6e,0x27,
+ 0x74,0x20,0x72,0x65,0x6c,0x79,0x20,0x6f,0x6e,0x20,0x74,0x68,0x65,0x20,0x64,0x65,
+ 0x66,0x61,0x75,0x6c,0x74,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x74,0x61,0x62,0x6c,
+ 0x65,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,0x65,0x20,0x70,0x72,
+ 0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,
+ 0x3a,0x20,0x6d,0x65,0x64,0x69,0x75,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x74,0x61,0x62,0x6c,0x65,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,
+ 0x65,0x20,0x74,0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,
+ 0x3a,0x20,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,
+ 0x67,0x2d,0x74,0x6f,0x70,0x3a,0x20,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,
+ 0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x30,
+ 0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x6c,
+ 0x65,0x66,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,
+ 0x64,0x64,0x69,0x6e,0x67,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,0x70,
+ 0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x61,0x62,0x6c,0x65,0x23,0x73,
+ 0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,0x65,0x20,0x70,0x72,0x65,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3a,0x20,0x30,0x70,0x78,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x3a,0x20,0x30,0x70,0x78,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x67,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,
+ 0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,
+ 0x20,0x23,0x62,0x66,0x66,0x66,0x62,0x66,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x2e,0x79,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,
+ 0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x66,0x66,0x66,0x66,0x62,
+ 0x66,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x72,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,
+ 0x72,0x3a,0x20,0x23,0x66,0x66,0x62,0x66,0x62,0x66,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,
+ 0x0d,0x0a,0x2f,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x0d,0x0a,0x73,0x74,0x6f,0x72,0x65,0x20,0x74,0x61,0x62,0x0d,0x0a,0x2a,
+ 0x2f,0x0d,0x0a,0x0d,0x0a,0x23,0x73,0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,
+ 0x73,0x6f,0x6c,0x75,0x74,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,
+ 0x33,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x65,
+ 0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x65,0x6d,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x31,0x65,0x6d,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x6f,0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x61,
+ 0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0d,0x0a,0x61,0x62,0x6f,
+ 0x75,0x74,0x20,0x74,0x61,0x62,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,0x0a,0x70,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x74,0x6f,0x70,0x3a,
+ 0x20,0x30,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0d,0x0a,0x74,0x61,0x62,0x73,
+ 0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,0x62,0x73,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,0x73,
+ 0x6f,0x6c,0x75,0x74,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,0x33,
+ 0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x2e,0x35,
+ 0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x2e,
+ 0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,
+ 0x32,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,0x62,0x73,
+ 0x20,0x64,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,
+ 0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x77,0x68,0x69,0x74,
+ 0x65,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,
+ 0x72,0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6c,0x6f,
+ 0x61,0x74,0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,
+ 0x64,0x65,0x72,0x3a,0x20,0x31,0x70,0x78,0x20,0x73,0x6f,0x6c,0x69,0x64,0x20,0x62,
+ 0x6c,0x61,0x63,0x6b,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x2d,
+ 0x62,0x6f,0x74,0x74,0x6f,0x6d,0x2d,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x30,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x3a,0x20,0x70,0x6f,0x69,0x6e,
+ 0x74,0x65,0x72,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x6c,
+ 0x65,0x66,0x74,0x3a,0x20,0x30,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6d,
+ 0x61,0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x30,0x2e,0x35,
+ 0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x6c,
+ 0x65,0x66,0x74,0x3a,0x20,0x30,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x70,
+ 0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x30,0x2e,
+ 0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,
+ 0x32,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x7a,0x2d,0x69,0x6e,0x64,0x65,0x78,0x3a,
+ 0x20,0x31,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x69,0x6e,0x65,0x2d,0x68,0x65,0x69,0x67,
+ 0x68,0x74,0x3a,0x20,0x31,0x2e,0x38,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x23,0x74,0x61,0x62,0x73,0x20,0x64,0x69,0x76,0x2e,0x73,0x65,0x6c,0x65,0x63,
+ 0x74,0x65,0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x7a,0x2d,0x69,0x6e,0x64,0x65,0x78,
+ 0x3a,0x20,0x33,0x3b,0x0d,0x0a,0x20,0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x3a,0x20,
+ 0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,
+ 0x74,0x61,0x62,0x73,0x20,0x64,0x69,0x76,0x2e,0x64,0x69,0x73,0x61,0x62,0x6c,0x65,
+ 0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,
+ 0x73,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x47,
+ 0x72,0x61,0x79,0x54,0x65,0x78,0x74,0x20,0x2a,0x2f,0x0d,0x0a,0x20,0x20,0x63,0x6f,
+ 0x6c,0x6f,0x72,0x3a,0x20,0x23,0x38,0x30,0x38,0x30,0x38,0x30,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x3a,0x20,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,
+ 0x3b,0x20,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x54,0x61,0x62,0x50,0x61,0x67,
+ 0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,
+ 0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x77,0x68,0x69,0x74,0x65,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3a,0x20,0x31,0x70,0x78,0x20,0x73,
+ 0x6f,0x6c,0x69,0x64,0x20,0x62,0x6c,0x61,0x63,0x6b,0x3b,0x0d,0x0a,0x20,0x20,0x70,
+ 0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,0x73,0x6f,0x6c,0x75,0x74,
+ 0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,0x35,0x65,0x6d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x2e,0x35,0x65,0x6d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x2e,0x35,0x65,0x6d,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x31,0x2e,0x35,0x65,
+ 0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x7a,0x2d,0x69,0x6e,0x64,0x65,0x78,0x3a,0x20,0x32,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x3a,0x20,0x31,0x65,
+ 0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x64,0x69,0x73,0x70,0x6c,0x61,0x79,0x3a,0x20,0x6e,
+ 0x6f,0x6e,0x65,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,0x62,0x50,
+ 0x61,0x67,0x65,0x73,0x20,0x64,0x69,0x76,0x2e,0x73,0x65,0x6c,0x65,0x63,0x74,0x65,
+ 0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x64,0x69,0x73,0x70,0x6c,0x61,0x79,0x3a,0x20,
+ 0x62,0x6c,0x6f,0x63,0x6b,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x69,0x6d,0x67,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,
+ 0x3a,0x20,0x68,0x69,0x64,0x64,0x65,0x6e,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,
+};
+const unsigned char RESOURCE9_[] = {
+
+ 0x23,0x68,0x65,0x61,0x64,0x69,0x6e,0x67,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x73,0x74,0x61,0x74,0x69,
+ 0x63,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x6c,0x65,0x66,
+ 0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,
+ 0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x74,0x6f,0x70,0x3a,0x20,
+ 0x30,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,
+ 0x62,0x73,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x63,0x6c,0x65,0x61,0x72,0x3a,0x20,0x61,
+ 0x6c,0x6c,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,
+ 0x20,0x73,0x74,0x61,0x74,0x69,0x63,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,
+ 0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,
+ 0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,
+ 0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,
+ 0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,
+ 0x2d,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,
+ 0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,0x62,0x73,0x20,
+ 0x64,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
+ 0x6e,0x3a,0x20,0x72,0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x6c,0x69,0x6e,0x65,0x2d,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x6e,0x6f,
+ 0x72,0x6d,0x61,0x6c,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,
+ 0x2d,0x74,0x6f,0x70,0x3a,0x20,0x35,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,
+ 0x64,0x64,0x69,0x6e,0x67,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x35,0x70,
+ 0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,0x62,0x73,0x20,0x64,
+ 0x69,0x76,0x2e,0x73,0x65,0x6c,0x65,0x63,0x74,0x65,0x64,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,
+ 0x20,0x36,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x7a,0x2d,0x69,0x6e,0x64,0x65,0x78,
+ 0x3a,0x20,0x32,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x54,0x61,0x62,0x50,
+ 0x61,0x67,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
+ 0x6e,0x3a,0x20,0x72,0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x74,0x6f,0x70,0x3a,0x20,0x2d,0x31,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,
+ 0x66,0x74,0x3a,0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,
+ 0x68,0x74,0x3a,0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,
+ 0x74,0x6f,0x6d,0x3a,0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x63,0x6c,
+ 0x65,0x61,0x72,0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,
+ 0x72,0x67,0x69,0x6e,0x2d,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,0x74,
+ 0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,
+ 0x6e,0x67,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x7a,0x2d,0x69,
+ 0x6e,0x64,0x65,0x78,0x3a,0x20,0x31,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,
+ 0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,
+ 0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x69,0x66,0x72,
+ 0x61,0x6d,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,
+ 0x74,0x69,0x6f,0x6e,0x3a,0x20,0x73,0x74,0x61,0x74,0x69,0x63,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,0x7d,
+ 0x0d,0x0a,0x0d,0x0a,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x73,
+ 0x74,0x61,0x74,0x69,0x63,0x3b,0x0d,0x0a,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,
+ 0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x66,0x69,
+ 0x6c,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,
+ 0x6e,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,
+ 0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,
+ 0x73,0x74,0x61,0x74,0x69,0x63,0x3b,0x0d,0x0a,0x20,0x20,0x77,0x69,0x64,0x74,0x68,
+ 0x3a,0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x73,
+ 0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,
+ 0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x73,0x74,0x61,0x74,0x69,0x63,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x20,0x73,0x6f,0x6d,0x65,0x20,0x64,0x65,0x66,
+ 0x61,0x75,0x6c,0x74,0x73,0x20,0x2a,0x2f,0x0d,0x0a,0x0d,0x0a,0x2e,0x54,0x61,0x62,
+ 0x50,0x61,0x67,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,
+ 0x3a,0x20,0x36,0x35,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,
+ 0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x68,
+ 0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x36,0x30,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,
+ 0x0d,0x0a,0x0d,0x0a,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x36,0x30,0x30,
+ 0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x73,0x6f,0x75,0x72,0x63,
+ 0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,
+ 0x3a,0x20,0x36,0x30,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,
+};
+const unsigned char RESOURCE10_[] = {
+
+ 0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2d,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,0x2e,0x63,0x73,0x73,
+ 0x20,0x2d,0x20,0x4a,0x53,0x43,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x73,0x79,
+ 0x6e,0x74,0x61,0x78,0x20,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,0x69,0x6e,
+ 0x67,0x20,0x73,0x74,0x79,0x6c,0x65,0x20,0x73,0x68,0x65,0x65,0x74,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,
+ 0x20,0x32,0x30,0x30,0x38,0x20,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,
+ 0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,
+ 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,0x66,0x72,
+ 0x65,0x65,0x20,0x73,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x3b,0x20,0x79,0x6f,0x75,
+ 0x20,0x63,0x61,0x6e,0x20,0x72,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,
+ 0x65,0x20,0x69,0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x6d,0x6f,0x64,0x69,
+ 0x66,0x79,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,0x75,0x6e,0x64,0x65,0x72,
+ 0x20,0x74,0x68,0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,
+ 0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,
+ 0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x73,0x20,
+ 0x70,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,0x79,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,
+ 0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x3b,0x20,
+ 0x65,0x69,0x74,0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x32,
+ 0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x2c,
+ 0x20,0x6f,0x72,0x0d,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,0x79,0x6f,0x75,
+ 0x72,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,0x20,0x6c,0x61,
+ 0x74,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,
+ 0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,
+ 0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,0x61,0x74,
+ 0x20,0x69,0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x66,
+ 0x75,0x6c,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,0x49,0x54,
+ 0x48,0x4f,0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,
+ 0x59,0x3b,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,0x6e,0x20,
+ 0x74,0x68,0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,0x72,0x72,
+ 0x61,0x6e,0x74,0x79,0x20,0x6f,0x66,0x0d,0x0a,0x20,0x20,0x20,0x20,0x4d,0x45,0x52,
+ 0x43,0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,0x72,0x20,
+ 0x46,0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,0x50,0x41,
+ 0x52,0x54,0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,0x53,0x45,
+ 0x2e,0x20,0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,
+ 0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,0x20,0x6d,
+ 0x6f,0x72,0x65,0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0d,0x0a,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x68,
+ 0x61,0x76,0x65,0x20,0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,0x63,
+ 0x6f,0x70,0x79,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,
+ 0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,
+ 0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
+ 0x61,0x6d,0x3b,0x20,0x69,0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,
+ 0x65,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,
+ 0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,
+ 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,
+ 0x20,0x46,0x72,0x61,0x6e,0x6b,0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,
+ 0x2c,0x20,0x46,0x69,0x66,0x74,0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,
+ 0x6f,0x73,0x74,0x6f,0x6e,0x2c,0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,
+ 0x31,0x33,0x30,0x31,0x20,0x55,0x53,0x41,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,
+ 0x0a,0x2f,0x2a,0x20,0x6b,0x65,0x79,0x77,0x6f,0x72,0x64,0x2c,0x20,0x74,0x79,0x70,
+ 0x65,0x2c,0x20,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x2c,0x20,0x63,0x62,0x72,0x61,0x63,
+ 0x6b,0x65,0x74,0x20,0x2a,0x2f,0x0d,0x0a,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,
+ 0x61,0x62,0x6c,0x65,0x20,0x2e,0x6b,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,
+ 0x74,0x2d,0x77,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x62,0x6f,0x6c,0x64,0x3b,0x0d,
+ 0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2c,
+ 0x20,0x72,0x65,0x67,0x65,0x78,0x70,0x2c,0x20,0x6e,0x75,0x6d,0x62,0x65,0x72,0x20,
+ 0x2a,0x2f,0x0d,0x0a,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,0x65,
+ 0x20,0x2e,0x73,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,
+ 0x23,0x30,0x30,0x36,0x34,0x30,0x30,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,
+ 0x2a,0x20,0x73,0x70,0x65,0x63,0x69,0x61,0x6c,0x63,0x68,0x61,0x72,0x20,0x2a,0x2f,
+ 0x0d,0x0a,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,0x65,0x20,0x2e,
+ 0x74,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x32,
+ 0x65,0x38,0x62,0x35,0x37,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x20,
+ 0x63,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x20,0x2a,0x2f,0x0d,0x0a,0x23,0x73,0x6f,0x75,
+ 0x72,0x63,0x65,0x54,0x61,0x62,0x6c,0x65,0x20,0x2e,0x63,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x74,0x79,0x6c,0x65,0x3a,0x20,0x69,0x74,0x61,
+ 0x6c,0x69,0x63,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,
+};
+const unsigned char RESOURCE11_[] = {
+
+ 0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x6a,0x73,0x20,0x2d,0x20,0x63,0x6f,0x64,0x65,0x20,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x20,0x66,0x6f,0x72,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,
+ 0x72,0x69,0x70,0x74,0x0d,0x0a,0x20,0x20,0x20,0x20,0x43,0x6f,0x70,0x79,0x72,0x69,
+ 0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30,0x37,0x2c,0x20,0x32,0x30,
+ 0x30,0x38,0x20,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,
+ 0x63,0x6f,0x6d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,
+ 0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,0x66,0x72,0x65,0x65,0x20,
+ 0x73,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x3b,0x20,0x79,0x6f,0x75,0x20,0x63,0x61,
+ 0x6e,0x20,0x72,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x20,0x69,
+ 0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,0x75,0x6e,0x64,0x65,0x72,0x20,0x74,0x68,
+ 0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,
+ 0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,
+ 0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x73,0x20,0x70,0x75,0x62,
+ 0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,0x79,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,
+ 0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,
+ 0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x3b,0x20,0x65,0x69,0x74,
+ 0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x32,0x20,0x6f,0x66,
+ 0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x2c,0x20,0x6f,0x72,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,0x79,0x6f,0x75,0x72,0x20,0x6f,
+ 0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,0x20,0x6c,0x61,0x74,0x65,0x72,
+ 0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,
+ 0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x69,0x6e,0x20,
+ 0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x69,0x74,
+ 0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x66,0x75,0x6c,0x2c,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,0x49,0x54,0x48,0x4f,0x55,
+ 0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x59,0x3b,0x20,
+ 0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,0x6e,0x20,0x74,0x68,0x65,
+ 0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,0x72,0x72,0x61,0x6e,0x74,
+ 0x79,0x20,0x6f,0x66,0x0d,0x0a,0x20,0x20,0x20,0x20,0x4d,0x45,0x52,0x43,0x48,0x41,
+ 0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,0x72,0x20,0x46,0x49,0x54,
+ 0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,0x50,0x41,0x52,0x54,0x49,
+ 0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,0x53,0x45,0x2e,0x20,0x20,
+ 0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x47,0x4e,0x55,
+ 0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,
+ 0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,0x20,0x6d,0x6f,0x72,0x65,
+ 0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x68,0x61,0x76,0x65,
+ 0x20,0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,0x63,0x6f,0x70,0x79,
+ 0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,
+ 0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,
+ 0x73,0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0d,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,
+ 0x74,0x68,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x3b,
+ 0x20,0x69,0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,0x65,0x20,0x74,
+ 0x6f,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,
+ 0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x2c,0x20,
+ 0x49,0x6e,0x63,0x2e,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,0x20,0x46,0x72,
+ 0x61,0x6e,0x6b,0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,0x2c,0x20,0x46,
+ 0x69,0x66,0x74,0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,0x6f,0x73,0x74,
+ 0x6f,0x6e,0x2c,0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,0x31,0x33,0x30,
+ 0x31,0x20,0x55,0x53,0x41,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,
+ 0x2a,0x0d,0x0a,0x49,0x6e,0x69,0x74,0x69,0x61,0x6c,0x69,0x7a,0x65,0x73,0x20,0x74,
+ 0x68,0x65,0x20,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,
+ 0x6f,0x62,0x6a,0x65,0x63,0x74,0x20,0x69,0x6e,0x20,0x61,0x20,0x77,0x69,0x6e,0x64,
+ 0x6f,0x77,0x2e,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,
+ 0x20,0x62,0x65,0x20,0x74,0x68,0x65,0x20,0x66,0x69,0x72,0x73,0x74,0x0d,0x0a,0x66,
+ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x61,0x6c,0x6c,0x65,0x64,0x20,0x69,
+ 0x6e,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x67,0x65,0x2e,0x0d,0x0a,0x40,0x70,0x61,
+ 0x72,0x61,0x6d,0x20,0x20,0x77,0x20,0x20,0x74,0x68,0x69,0x73,0x20,0x73,0x68,0x6f,
+ 0x75,0x6c,0x64,0x20,0x61,0x6c,0x77,0x61,0x79,0x73,0x20,0x62,0x65,0x20,0x74,0x68,
+ 0x65,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x20,
+ 0x6f,0x62,0x6a,0x65,0x63,0x74,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,
+ 0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x69,0x6e,0x69,0x74,0x28,0x77,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x74,0x72,0x79,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x69,0x6e,0x20,0x53,0x61,
+ 0x66,0x61,0x72,0x69,0x2c,0x20,0x22,0x69,0x6d,0x70,0x6f,0x72,0x74,0x22,0x20,0x69,
+ 0x73,0x20,0x61,0x20,0x73,0x79,0x6e,0x74,0x61,0x78,0x20,0x65,0x72,0x72,0x6f,0x72,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x43,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,
+ 0x2e,0x75,0x74,0x69,0x6c,0x73,0x5b,0x27,0x69,0x6d,0x70,0x6f,0x72,0x74,0x27,0x5d,
+ 0x28,0x27,0x72,0x65,0x73,0x6f,0x75,0x72,0x63,0x65,0x3a,0x2f,0x2f,0x67,0x72,0x65,
+ 0x2f,0x6d,0x6f,0x64,0x75,0x6c,0x65,0x73,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x2e,0x6a,0x73,0x6d,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x73,0x49,0x6e,0x76,
+ 0x65,0x72,0x74,0x65,0x64,0x4d,0x6f,0x64,0x65,0x20,0x3d,0x20,0x74,0x72,0x75,0x65,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x63,0x61,0x74,0x63,0x68,0x20,0x28,0x65,0x29,
+ 0x20,0x7b,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x77,0x2e,0x6f,
+ 0x70,0x65,0x6e,0x65,0x72,0x20,0x26,0x26,0x20,0x77,0x2e,0x6f,0x70,0x65,0x6e,0x65,
+ 0x72,0x2e,0x74,0x6f,0x70,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x77,0x65,
+ 0x20,0x61,0x72,0x65,0x20,0x69,0x6e,0x20,0x69,0x6e,0x76,0x65,0x72,0x74,0x65,0x64,
+ 0x20,0x6d,0x6f,0x64,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x73,0x49,0x6e,0x76,0x65,0x72,0x74,0x65,0x64,
+ 0x4d,0x6f,0x64,0x65,0x20,0x3d,0x20,0x74,0x72,0x75,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x77,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x77,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,
+ 0x3d,0x20,0x77,0x2e,0x6f,0x70,0x65,0x6e,0x65,0x72,0x2e,0x74,0x6f,0x70,0x2e,0x5f,
+ 0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x77,0x65,0x20,0x61,0x72,
+ 0x65,0x20,0x6e,0x6f,0x74,0x20,0x69,0x6e,0x20,0x69,0x6e,0x76,0x65,0x72,0x74,0x65,
+ 0x64,0x20,0x6d,0x6f,0x64,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x73,0x49,0x6e,0x76,0x65,0x72,0x74,0x65,
+ 0x64,0x4d,0x6f,0x64,0x65,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x77,0x2e,0x5f,0x24,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x77,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x76,0x61,0x72,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,
+ 0x46,0x69,0x6c,0x65,0x20,0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x3b,0x0d,0x0a,0x76,0x61,
+ 0x72,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,
+ 0x72,0x65,0x6e,0x74,0x4c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x3b,
+ 0x0d,0x0a,0x0d,0x0a,0x76,0x61,0x72,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,
+ 0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,
+ 0x0d,0x0a,0x2f,0x2a,0x0d,0x0a,0x50,0x6f,0x73,0x73,0x69,0x62,0x6c,0x65,0x20,0x73,
+ 0x74,0x61,0x74,0x65,0x73,0x3a,0x0d,0x0a,0x09,0x09,0x09,0x69,0x73,0x49,0x6e,0x76,
+ 0x65,0x72,0x74,0x65,0x64,0x4d,0x6f,0x64,0x65,0x09,0x69,0x73,0x53,0x65,0x72,0x76,
+ 0x65,0x72,0x09,0x69,0x73,0x52,0x65,0x70,0x6f,0x72,0x74,0x09,0x74,0x61,0x62,0x73,
+ 0x0d,0x0a,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x09,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,
+ 0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,
+ 0x42,0x72,0x6f,0x77,0x73,0x65,0x72,0x0d,0x0a,0x69,0x6e,0x76,0x65,0x72,0x74,0x65,
+ 0x64,0x09,0x09,0x74,0x72,0x75,0x65,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,
+ 0x66,0x61,0x6c,0x73,0x65,0x09,0x09,0x0d,0x0a,0x73,0x65,0x72,0x76,0x65,0x72,0x2c,
+ 0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,
+ 0x74,0x72,0x75,0x65,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,0x42,0x72,0x6f,
+ 0x77,0x73,0x65,0x72,0x2c,0x20,0x53,0x74,0x6f,0x72,0x65,0x0d,0x0a,0x73,0x65,0x72,
+ 0x76,0x65,0x72,0x2c,0x20,0x69,0x6e,0x76,0x65,0x72,0x74,0x65,0x64,0x09,0x74,0x72,
+ 0x75,0x65,0x09,0x09,0x74,0x72,0x75,0x65,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,
+ 0x09,0x53,0x74,0x6f,0x72,0x65,0x0d,0x0a,0x72,0x65,0x70,0x6f,0x72,0x74,0x09,0x09,
+ 0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,0x74,
+ 0x72,0x75,0x65,0x09,0x09,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x76,0x61,0x72,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x73,0x49,0x6e,0x76,0x65,
+ 0x72,0x74,0x65,0x64,0x4d,0x6f,0x64,0x65,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,
+ 0x3b,0x0d,0x0a,0x76,0x61,0x72,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x69,0x73,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x3d,0x20,0x66,0x61,0x6c,
+ 0x73,0x65,0x3b,0x0d,0x0a,0x76,0x61,0x72,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x69,0x73,0x52,0x65,0x70,0x6f,0x72,0x74,0x20,0x3d,0x20,0x66,
+ 0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,0x0d,0x0a,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x69,0x6e,0x69,0x74,0x28,0x77,0x69,0x6e,0x64,0x6f,0x77,0x29,
+ 0x3b,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x72,0x65,0x61,0x74,0x65,0x52,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x2f,0x2f,
+ 0x20,0x4e,0x6f,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x74,0x68,0x65,0x20,0x49,
+ 0x45,0x37,0x20,0x58,0x4d,0x4c,0x48,0x74,0x74,0x70,0x52,0x65,0x71,0x75,0x65,0x73,
+ 0x74,0x20,0x64,0x6f,0x65,0x73,0x20,0x6e,0x6f,0x74,0x20,0x73,0x75,0x70,0x70,0x6f,
+ 0x72,0x74,0x20,0x66,0x69,0x6c,0x65,0x20,0x55,0x52,0x4c,0x27,0x73,0x2e,0x0d,0x0a,
+ 0x20,0x20,0x2f,0x2f,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x78,0x68,0x61,0x62,
+ 0x2e,0x62,0x6c,0x6f,0x67,0x73,0x70,0x6f,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x32,0x30,
+ 0x30,0x36,0x2f,0x31,0x31,0x2f,0x69,0x65,0x37,0x2d,0x73,0x75,0x70,0x70,0x6f,0x72,
+ 0x74,0x2d,0x66,0x6f,0x72,0x2d,0x78,0x6d,0x6c,0x68,0x74,0x74,0x70,0x72,0x65,0x71,
+ 0x75,0x65,0x73,0x74,0x2e,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x20,0x20,0x2f,0x2f,0x20,
+ 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x62,0x6c,0x6f,0x67,0x73,0x2e,0x6d,0x73,0x64,
+ 0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x69,0x65,0x2f,0x61,0x72,0x63,0x68,0x69,0x76,0x65,
+ 0x2f,0x32,0x30,0x30,0x36,0x2f,0x31,0x32,0x2f,0x30,0x36,0x2f,0x66,0x69,0x6c,0x65,
+ 0x2d,0x75,0x72,0x69,0x73,0x2d,0x69,0x6e,0x2d,0x77,0x69,0x6e,0x64,0x6f,0x77,0x73,
+ 0x2e,0x61,0x73,0x70,0x78,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,0x43,0x4f,0x56,0x45,
+ 0x52,0x41,0x47,0x45,0x5f,0x49,0x46,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x77,
+ 0x69,0x6e,0x64,0x6f,0x77,0x2e,0x41,0x63,0x74,0x69,0x76,0x65,0x58,0x4f,0x62,0x6a,
+ 0x65,0x63,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,
+ 0x72,0x6e,0x20,0x6e,0x65,0x77,0x20,0x41,0x63,0x74,0x69,0x76,0x65,0x58,0x4f,0x62,
+ 0x6a,0x65,0x63,0x74,0x28,0x22,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,
+ 0x58,0x4d,0x4c,0x48,0x54,0x54,0x50,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,
+ 0x65,0x74,0x75,0x72,0x6e,0x20,0x6e,0x65,0x77,0x20,0x58,0x4d,0x4c,0x48,0x74,0x74,
+ 0x70,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,
+ 0x2f,0x77,0x77,0x77,0x2e,0x71,0x75,0x69,0x72,0x6b,0x73,0x6d,0x6f,0x64,0x65,0x2e,
+ 0x6f,0x72,0x67,0x2f,0x6a,0x73,0x2f,0x66,0x69,0x6e,0x64,0x70,0x6f,0x73,0x2e,0x68,
+ 0x74,0x6d,0x6c,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,0x6e,0x64,0x50,0x6f,0x73,
+ 0x28,0x6f,0x62,0x6a,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x72,
+ 0x65,0x73,0x75,0x6c,0x74,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x64,0x6f,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x20,0x2b,
+ 0x3d,0x20,0x6f,0x62,0x6a,0x2e,0x6f,0x66,0x66,0x73,0x65,0x74,0x54,0x6f,0x70,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x6f,0x62,0x6a,0x20,0x3d,0x20,0x6f,0x62,0x6a,0x2e,
+ 0x6f,0x66,0x66,0x73,0x65,0x74,0x50,0x61,0x72,0x65,0x6e,0x74,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x28,0x6f,0x62,0x6a,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x72,0x65,0x73,
+ 0x75,0x6c,0x74,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x68,0x74,
+ 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x71,0x75,0x69,0x72,0x6b,0x73,0x6d,
+ 0x6f,0x64,0x65,0x2e,0x6f,0x72,0x67,0x2f,0x76,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,
+ 0x2f,0x63,0x6f,0x6d,0x70,0x61,0x74,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x2e,0x68,
+ 0x74,0x6d,0x6c,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x67,0x65,0x74,0x56,0x69,0x65,0x77,
+ 0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x28,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x2f,0x2f,0x23,0x4a,0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x49,0x46,
+ 0x20,0x2f,0x4d,0x53,0x49,0x45,0x2f,0x2e,0x74,0x65,0x73,0x74,0x28,0x6e,0x61,0x76,
+ 0x69,0x67,0x61,0x74,0x6f,0x72,0x2e,0x75,0x73,0x65,0x72,0x41,0x67,0x65,0x6e,0x74,
+ 0x29,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x73,0x65,0x6c,0x66,0x2e,0x69,0x6e,
+ 0x6e,0x65,0x72,0x48,0x65,0x69,0x67,0x68,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x2f,0x2f,0x20,0x61,0x6c,0x6c,0x20,0x65,0x78,0x63,0x65,0x70,0x74,0x20,
+ 0x45,0x78,0x70,0x6c,0x6f,0x72,0x65,0x72,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,
+ 0x74,0x75,0x72,0x6e,0x20,0x73,0x65,0x6c,0x66,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,
+ 0x65,0x69,0x67,0x68,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,
+ 0x6c,0x73,0x65,0x20,0x69,0x66,0x20,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x20,0x26,0x26,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x6c,0x69,
+ 0x65,0x6e,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x2f,0x2f,0x20,0x45,0x78,0x70,0x6c,0x6f,0x72,0x65,0x72,0x20,0x36,0x20,
+ 0x53,0x74,0x72,0x69,0x63,0x74,0x20,0x4d,0x6f,0x64,0x65,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x63,0x6c,0x69,0x65,0x6e,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x69,0x66,0x20,0x28,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x62,0x6f,0x64,0x79,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x6f,0x74,0x68,0x65,0x72,0x20,0x45,
+ 0x78,0x70,0x6c,0x6f,0x72,0x65,0x72,0x73,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,
+ 0x74,0x75,0x72,0x6e,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x62,0x6f,
+ 0x64,0x79,0x2e,0x63,0x6c,0x69,0x65,0x6e,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x22,0x43,0x6f,0x75,0x6c,
+ 0x64,0x6e,0x27,0x74,0x20,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x20,0x76,
+ 0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x22,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,0x43,0x4f,0x56,0x45,
+ 0x52,0x41,0x47,0x45,0x5f,0x45,0x4e,0x44,0x49,0x46,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x49,0x6e,0x64,0x69,0x63,0x61,0x74,0x65,0x73,0x20,
+ 0x76,0x69,0x73,0x75,0x61,0x6c,0x6c,0x79,0x20,0x74,0x68,0x61,0x74,0x20,0x61,0x20,
+ 0x6c,0x65,0x6e,0x67,0x74,0x68,0x79,0x20,0x6f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,
+ 0x6e,0x20,0x68,0x61,0x73,0x20,0x62,0x65,0x67,0x75,0x6e,0x2e,0x20,0x20,0x54,0x68,
+ 0x65,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x20,0x62,0x61,0x72,0x20,0x69,
+ 0x73,0x0d,0x0a,0x64,0x69,0x73,0x70,0x6c,0x61,0x79,0x65,0x64,0x2c,0x20,0x61,0x6e,
+ 0x64,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x20,0x69,0x73,0x20,
+ 0x63,0x68,0x61,0x6e,0x67,0x65,0x64,0x20,0x74,0x6f,0x20,0x62,0x75,0x73,0x79,0x20,
+ 0x28,0x6f,0x6e,0x20,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x73,0x20,0x77,0x68,0x69,
+ 0x63,0x68,0x20,0x73,0x75,0x70,0x70,0x6f,0x72,0x74,0x20,0x74,0x68,0x69,0x73,0x29,
+ 0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x65,0x67,0x69,0x6e,
+ 0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,
+ 0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,
+ 0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x74,0x72,0x75,0x65,0x3b,0x0d,0x0a,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,
+ 0x61,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,
+ 0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,
+ 0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x74,0x79,0x6c,
+ 0x65,0x2e,0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,
+ 0x76,0x69,0x73,0x69,0x62,0x6c,0x65,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x50,0x72,0x6f,
+ 0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x65,0x74,0x50,0x65,0x72,0x63,
+ 0x65,0x6e,0x74,0x61,0x67,0x65,0x28,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,
+ 0x61,0x72,0x2c,0x20,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,
+ 0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x4c,0x61,0x62,0x65,0x6c,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x72,0x6f,0x67,
+ 0x72,0x65,0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,
+ 0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x76,0x69,
+ 0x73,0x69,0x62,0x6c,0x65,0x27,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x20,
+ 0x62,0x6c,0x61,0x63,0x6b,0x6c,0x69,0x73,0x74,0x20,0x62,0x75,0x67,0x67,0x79,0x20,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x73,0x20,0x2a,0x2f,0x0d,0x0a,0x2f,0x2f,0x23,
+ 0x4a,0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x49,0x46,0x0d,0x0a,0x20,
+ 0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x2f,0x4f,0x70,0x65,0x72,0x61,0x7c,0x57,0x65,
+ 0x62,0x4b,0x69,0x74,0x2f,0x2e,0x74,0x65,0x73,0x74,0x28,0x6e,0x61,0x76,0x69,0x67,
+ 0x61,0x74,0x6f,0x72,0x2e,0x75,0x73,0x65,0x72,0x41,0x67,0x65,0x6e,0x74,0x29,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x43,0x68,0x61,0x6e,0x67,0x65,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72,0x73,0x6f,
+ 0x72,0x20,0x73,0x74,0x79,0x6c,0x65,0x20,0x6f,0x66,0x20,0x65,0x61,0x63,0x68,0x20,
+ 0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x20,0x20,0x4e,0x6f,0x74,0x65,0x20,0x74,
+ 0x68,0x61,0x74,0x20,0x63,0x68,0x61,0x6e,0x67,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,
+ 0x20,0x63,0x6c,0x61,0x73,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x20,0x28,0x74,0x6f,0x20,0x6f,
+ 0x6e,0x65,0x20,0x77,0x69,0x74,0x68,0x20,0x61,0x20,0x62,0x75,0x73,0x79,0x20,0x63,
+ 0x75,0x72,0x73,0x6f,0x72,0x29,0x20,0x69,0x73,0x20,0x62,0x75,0x67,0x67,0x79,0x20,
+ 0x69,0x6e,0x20,0x49,0x45,0x2e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2a,0x2f,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x73,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x73,0x27,0x29,0x2e,0x67,
+ 0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,
+ 0x61,0x6d,0x65,0x28,0x27,0x64,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x69,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,
+ 0x20,0x28,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x74,0x61,0x62,
+ 0x73,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x73,0x2e,0x69,0x74,0x65,
+ 0x6d,0x28,0x69,0x29,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x63,0x75,0x72,0x73,0x6f,
+ 0x72,0x20,0x3d,0x20,0x27,0x77,0x61,0x69,0x74,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,
+ 0x2a,0x0d,0x0a,0x52,0x65,0x6d,0x6f,0x76,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x70,
+ 0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x20,0x62,0x61,0x72,0x20,0x61,0x6e,0x64,0x20,
+ 0x62,0x75,0x73,0x79,0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x2e,0x0d,0x0a,0x2a,0x2f,
+ 0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,
+ 0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,
+ 0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,0x6f,0x67,
+ 0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x50,0x72,
+ 0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x65,0x74,0x50,0x65,0x72,
+ 0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x28,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x42,0x61,0x72,0x2c,0x20,0x31,0x30,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x73,0x65,
+ 0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,0x74,0x28,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,
+ 0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,
+ 0x61,0x72,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x76,0x69,0x73,0x69,0x62,0x69,0x6c,
+ 0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x68,0x69,0x64,0x64,0x65,0x6e,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,
+ 0x73,0x4c,0x61,0x62,0x65,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,
+ 0x28,0x27,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x27,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x4c,0x61,0x62,0x65,0x6c,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x76,0x69,0x73,0x69,
+ 0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x68,0x69,0x64,0x64,0x65,0x6e,
+ 0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x4c,0x61,0x62,0x65,0x6c,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,
+ 0x3d,0x20,0x27,0x27,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x74,0x61,0x62,0x73,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,
+ 0x27,0x74,0x61,0x62,0x73,0x27,0x29,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x27,0x64,0x69,
+ 0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x69,0x20,0x3d,0x20,0x30,
+ 0x3b,0x20,0x69,0x20,0x3c,0x20,0x74,0x61,0x62,0x73,0x2e,0x6c,0x65,0x6e,0x67,0x74,
+ 0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x74,0x61,0x62,0x73,0x2e,0x69,0x74,0x65,0x6d,0x28,0x69,0x29,0x2e,0x73,0x74,
+ 0x79,0x6c,0x65,0x2e,0x63,0x75,0x72,0x73,0x6f,0x72,0x20,0x3d,0x20,0x27,0x27,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x2c,0x20,0x35,0x30,
+ 0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x74,
+ 0x53,0x69,0x7a,0x65,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,0x43,
+ 0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x49,0x46,0x20,0x2f,0x4d,0x53,0x49,0x45,
+ 0x2f,0x2e,0x74,0x65,0x73,0x74,0x28,0x6e,0x61,0x76,0x69,0x67,0x61,0x74,0x6f,0x72,
+ 0x2e,0x75,0x73,0x65,0x72,0x41,0x67,0x65,0x6e,0x74,0x29,0x0d,0x0a,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x76,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,
+ 0x74,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x67,
+ 0x65,0x74,0x56,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x62,
+ 0x6f,0x72,0x64,0x65,0x72,0x2d,0x74,0x6f,0x70,0x2d,0x77,0x69,0x64,0x74,0x68,0x3a,
+ 0x20,0x20,0x20,0x20,0x20,0x31,0x70,0x78,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,
+ 0x69,0x6e,0x67,0x2d,0x74,0x6f,0x70,0x3a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x31,0x30,0x70,0x78,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,
+ 0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x30,
+ 0x70,0x78,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x2d,0x62,0x6f,0x74,
+ 0x74,0x6f,0x6d,0x2d,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x20,0x31,0x70,0x78,0x0d,
+ 0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,
+ 0x3a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x30,0x70,0x78,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x2d,0x2d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x33,0x32,0x70,0x78,0x0d,0x0a,0x20,0x20,0x2a,0x2f,0x0d,0x0a,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,
+ 0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x50,0x61,
+ 0x67,0x65,0x48,0x65,0x69,0x67,0x68,0x74,0x20,0x3d,0x20,0x28,0x76,0x69,0x65,0x77,
+ 0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x20,0x2d,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,0x6e,0x64,0x50,0x6f,0x73,0x28,
+ 0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x29,0x20,0x2d,0x20,0x33,0x32,0x29,0x20,
+ 0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,
+ 0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x20,0x3d,0x20,0x74,0x61,0x62,0x50,0x61,0x67,
+ 0x65,0x73,0x2e,0x63,0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3d,0x20,0x6e,
+ 0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x69,0x20,0x3d,0x20,
+ 0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,
+ 0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,
+ 0x6f,0x64,0x65,0x20,0x3d,0x20,0x6e,0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x2e,0x69,
+ 0x74,0x65,0x6d,0x28,0x69,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x6e,0x6f,0x64,0x65,0x2e,0x6e,0x6f,0x64,0x65,0x54,0x79,0x70,0x65,0x20,0x21,
+ 0x3d,0x3d,0x20,0x31,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,
+ 0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,0x65,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,
+ 0x68,0x65,0x69,0x67,0x68,0x74,0x20,0x3d,0x20,0x74,0x61,0x62,0x50,0x61,0x67,0x65,
+ 0x48,0x65,0x69,0x67,0x68,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x20,
+ 0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,
+ 0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x69,0x66,0x72,0x61,0x6d,
+ 0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x2f,0x2f,0x20,0x6d,0x61,
+ 0x79,0x20,0x6e,0x6f,0x74,0x20,0x65,0x78,0x69,0x73,0x74,0x20,0x69,0x66,0x20,0x77,
+ 0x65,0x20,0x68,0x61,0x76,0x65,0x20,0x72,0x65,0x6d,0x6f,0x76,0x65,0x64,0x20,0x74,
+ 0x68,0x65,0x20,0x66,0x69,0x72,0x73,0x74,0x20,0x74,0x61,0x62,0x0d,0x0a,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x2e,
+ 0x73,0x74,0x79,0x6c,0x65,0x2e,0x68,0x65,0x69,0x67,0x68,0x74,0x20,0x3d,0x20,0x28,
+ 0x76,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x20,0x2d,
+ 0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,0x6e,0x64,
+ 0x50,0x6f,0x73,0x28,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x29,0x20,0x2d,
+ 0x20,0x32,0x31,0x29,0x20,0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x75,0x6d,0x6d,0x61,
+ 0x72,0x79,0x44,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,
+ 0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x2e,0x73,0x74,0x79,
+ 0x6c,0x65,0x2e,0x68,0x65,0x69,0x67,0x68,0x74,0x20,0x3d,0x20,0x28,0x76,0x69,0x65,
+ 0x77,0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x20,0x2d,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,0x6e,0x64,0x50,0x6f,0x73,
+ 0x28,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x29,0x20,0x2d,0x20,0x32,
+ 0x31,0x29,0x20,0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x20,0x3d,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,
+ 0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,
+ 0x69,0x76,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x68,0x65,0x69,0x67,0x68,0x74,0x20,
+ 0x3d,0x20,0x28,0x76,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,
+ 0x74,0x20,0x2d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,
+ 0x69,0x6e,0x64,0x50,0x6f,0x73,0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,
+ 0x29,0x20,0x2d,0x20,0x32,0x31,0x29,0x20,0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x74,0x6f,0x72,0x65,0x44,0x69,
+ 0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,
+ 0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x73,0x74,0x6f,
+ 0x72,0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,
+ 0x73,0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x73,0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,
+ 0x68,0x65,0x69,0x67,0x68,0x74,0x20,0x3d,0x20,0x28,0x76,0x69,0x65,0x77,0x70,0x6f,
+ 0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x20,0x2d,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,0x6e,0x64,0x50,0x6f,0x73,0x28,0x73,0x74,
+ 0x6f,0x72,0x65,0x44,0x69,0x76,0x29,0x20,0x2d,0x20,0x32,0x31,0x29,0x20,0x2b,0x20,
+ 0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,
+ 0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x45,0x4e,0x44,0x49,0x46,0x0d,
+ 0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x52,0x65,0x74,0x75,0x72,
+ 0x6e,0x73,0x20,0x74,0x68,0x65,0x20,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x20,0x76,
+ 0x61,0x6c,0x75,0x65,0x20,0x6f,0x66,0x20,0x61,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,
+ 0x2e,0x20,0x20,0x56,0x61,0x6c,0x75,0x65,0x73,0x20,0x27,0x66,0x61,0x6c,0x73,0x65,
+ 0x27,0x2c,0x20,0x27,0x66,0x27,0x2c,0x20,0x27,0x6e,0x6f,0x27,0x2c,0x20,0x27,0x6e,
+ 0x27,0x2c,0x20,0x27,0x6f,0x66,0x66,0x27,0x2c,0x0d,0x0a,0x61,0x6e,0x64,0x20,0x27,
+ 0x30,0x27,0x20,0x28,0x75,0x70,0x70,0x65,0x72,0x20,0x6f,0x72,0x20,0x6c,0x6f,0x77,
+ 0x65,0x72,0x20,0x63,0x61,0x73,0x65,0x29,0x20,0x61,0x72,0x65,0x20,0x66,0x61,0x6c,
+ 0x73,0x65,0x2e,0x0d,0x0a,0x40,0x70,0x61,0x72,0x61,0x6d,0x20,0x20,0x73,0x20,0x20,
+ 0x74,0x68,0x65,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x0d,0x0a,0x40,0x72,0x65,0x74,
+ 0x75,0x72,0x6e,0x20,0x20,0x61,0x20,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x20,0x76,
+ 0x61,0x6c,0x75,0x65,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,
+ 0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x67,0x65,
+ 0x74,0x42,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x56,0x61,0x6c,0x75,0x65,0x28,0x73,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x73,0x20,0x3d,0x20,0x73,0x2e,0x74,0x6f,0x4c,0x6f,
+ 0x77,0x65,0x72,0x43,0x61,0x73,0x65,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x69,0x66,
+ 0x20,0x28,0x73,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x66,0x61,0x6c,0x73,0x65,0x27,0x20,
+ 0x7c,0x7c,0x20,0x73,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x66,0x27,0x20,0x7c,0x7c,0x20,
+ 0x73,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x6e,0x6f,0x27,0x20,0x7c,0x7c,0x20,0x73,0x20,
+ 0x3d,0x3d,0x3d,0x20,0x27,0x6e,0x27,0x20,0x7c,0x7c,0x20,0x73,0x20,0x3d,0x3d,0x3d,
+ 0x20,0x27,0x6f,0x66,0x66,0x27,0x20,0x7c,0x7c,0x20,0x73,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x27,0x30,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,
+ 0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x3b,0x0d,0x0a,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x6d,0x6f,0x76,0x65,0x54,
+ 0x61,0x62,0x28,0x69,0x64,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x74,0x61,0x62,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,
+ 0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x69,0x64,
+ 0x20,0x2b,0x20,0x27,0x54,0x61,0x62,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x61,
+ 0x62,0x2e,0x70,0x61,0x72,0x65,0x6e,0x74,0x4e,0x6f,0x64,0x65,0x2e,0x72,0x65,0x6d,
+ 0x6f,0x76,0x65,0x43,0x68,0x69,0x6c,0x64,0x28,0x74,0x61,0x62,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x20,0x3d,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x69,0x64,0x20,0x2b,0x20,0x27,0x54,0x61,
+ 0x62,0x50,0x61,0x67,0x65,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x61,0x62,0x50,
+ 0x61,0x67,0x65,0x2e,0x70,0x61,0x72,0x65,0x6e,0x74,0x4e,0x6f,0x64,0x65,0x2e,0x72,
+ 0x65,0x6d,0x6f,0x76,0x65,0x43,0x68,0x69,0x6c,0x64,0x28,0x74,0x61,0x62,0x50,0x61,
+ 0x67,0x65,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,
+ 0x49,0x6e,0x69,0x74,0x69,0x61,0x6c,0x69,0x7a,0x65,0x73,0x20,0x74,0x68,0x65,0x20,
+ 0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,
+ 0x74,0x61,0x62,0x73,0x2e,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x73,0x65,0x74,0x73,
+ 0x20,0x74,0x68,0x65,0x20,0x69,0x6e,0x69,0x74,0x69,0x61,0x6c,0x20,0x76,0x61,0x6c,
+ 0x75,0x65,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x0d,0x0a,0x69,0x6e,0x70,0x75,
+ 0x74,0x20,0x66,0x69,0x65,0x6c,0x64,0x20,0x61,0x6e,0x64,0x20,0x69,0x66,0x72,0x61,
+ 0x6d,0x65,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x22,0x42,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x22,0x20,0x74,0x61,0x62,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,
+ 0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,
+ 0x22,0x53,0x75,0x6d,0x6d,0x61,0x72,0x79,0x22,0x0d,0x0a,0x74,0x61,0x62,0x2e,0x0d,
+ 0x0a,0x40,0x70,0x61,0x72,0x61,0x6d,0x20,0x20,0x71,0x75,0x65,0x72,0x79,0x53,0x74,
+ 0x72,0x69,0x6e,0x67,0x20,0x20,0x74,0x68,0x69,0x73,0x20,0x73,0x68,0x6f,0x75,0x6c,
+ 0x64,0x20,0x61,0x6c,0x77,0x61,0x79,0x73,0x20,0x62,0x65,0x20,0x6c,0x6f,0x63,0x61,
+ 0x74,0x69,0x6f,0x6e,0x2e,0x73,0x65,0x61,0x72,0x63,0x68,0x0d,0x0a,0x2a,0x2f,0x0d,
+ 0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,0x69,0x74,0x54,0x61,0x62,0x43,0x6f,0x6e,0x74,
+ 0x65,0x6e,0x74,0x73,0x28,0x71,0x75,0x65,0x72,0x79,0x53,0x74,0x72,0x69,0x6e,0x67,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x68,0x6f,0x77,0x4d,
+ 0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x20,0x3d,0x20,0x66,
+ 0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x61,0x72,
+ 0x61,0x6d,0x65,0x74,0x65,0x72,0x73,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,
+ 0x65,0x72,0x2c,0x20,0x69,0x2c,0x20,0x69,0x6e,0x64,0x65,0x78,0x2c,0x20,0x75,0x72,
+ 0x6c,0x2c,0x20,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x76,0x61,0x6c,0x75,0x65,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x71,0x75,0x65,0x72,0x79,0x53,0x74,0x72,0x69,
+ 0x6e,0x67,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3e,0x20,0x30,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x63,0x68,0x6f,0x70,0x20,0x6f,0x66,
+ 0x66,0x20,0x74,0x68,0x65,0x20,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x20,0x6d,
+ 0x61,0x72,0x6b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x71,0x75,0x65,0x72,0x79,0x53,0x74,
+ 0x72,0x69,0x6e,0x67,0x20,0x3d,0x20,0x71,0x75,0x65,0x72,0x79,0x53,0x74,0x72,0x69,
+ 0x6e,0x67,0x2e,0x73,0x75,0x62,0x73,0x74,0x72,0x69,0x6e,0x67,0x28,0x31,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,0x73,
+ 0x20,0x3d,0x20,0x71,0x75,0x65,0x72,0x79,0x53,0x74,0x72,0x69,0x6e,0x67,0x2e,0x73,
+ 0x70,0x6c,0x69,0x74,0x28,0x2f,0x26,0x7c,0x3b,0x2f,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,
+ 0x3c,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,0x73,0x2e,0x6c,0x65,0x6e,
+ 0x67,0x74,0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,0x20,0x3d,0x20,0x70,
+ 0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,0x73,0x5b,0x69,0x5d,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20,0x70,0x61,0x72,
+ 0x61,0x6d,0x65,0x74,0x65,0x72,0x2e,0x69,0x6e,0x64,0x65,0x78,0x4f,0x66,0x28,0x27,
+ 0x3d,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,
+ 0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x3d,0x3d,0x20,0x2d,0x31,0x29,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x73,0x74,0x69,0x6c,
+ 0x6c,0x20,0x77,0x6f,0x72,0x6b,0x73,0x20,0x77,0x69,0x74,0x68,0x20,0x6f,0x6c,0x64,
+ 0x20,0x73,0x79,0x6e,0x74,0x61,0x78,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x75,0x72,0x6c,0x20,0x3d,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,
+ 0x65,0x72,0x2e,0x73,0x75,0x62,0x73,0x74,0x72,0x28,0x30,0x2c,0x20,0x69,0x6e,0x64,
+ 0x65,0x78,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,
+ 0x6c,0x75,0x65,0x20,0x3d,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,0x2e,
+ 0x73,0x75,0x62,0x73,0x74,0x72,0x28,0x69,0x6e,0x64,0x65,0x78,0x20,0x2b,0x20,0x31,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,
+ 0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x6d,0x69,0x73,0x73,0x69,0x6e,
+ 0x67,0x27,0x20,0x7c,0x7c,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x27,
+ 0x6d,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x73,0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,
+ 0x6d,0x6e,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x67,0x65,0x74,0x42,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x56,0x61,0x6c,0x75,0x65,0x28,
+ 0x76,0x61,0x6c,0x75,0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,
+ 0x20,0x69,0x66,0x20,0x28,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x75,
+ 0x72,0x6c,0x27,0x20,0x7c,0x7c,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x27,0x75,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x75,0x72,0x6c,0x20,0x3d,0x20,0x76,0x61,0x6c,0x75,0x65,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,
+ 0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x63,0x68,0x65,0x63,
+ 0x6b,0x62,0x6f,0x78,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x63,0x68,0x65,0x63,0x6b,
+ 0x62,0x6f,0x78,0x2e,0x63,0x68,0x65,0x63,0x6b,0x65,0x64,0x20,0x3d,0x20,0x73,0x68,
+ 0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x73,0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,
+ 0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x61,0x70,0x70,
+ 0x65,0x6e,0x64,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2f,
+ 0x20,0x74,0x68,0x69,0x73,0x20,0x77,0x69,0x6c,0x6c,0x20,0x61,0x75,0x74,0x6f,0x6d,
+ 0x61,0x74,0x69,0x63,0x61,0x6c,0x6c,0x79,0x20,0x70,0x72,0x6f,0x70,0x61,0x67,0x61,
+ 0x74,0x65,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x69,0x6e,0x70,0x75,0x74,0x20,
+ 0x66,0x69,0x65,0x6c,0x64,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x75,0x72,0x6c,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x6d,0x65,0x73,0x5b,
+ 0x30,0x5d,0x2e,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x75,0x72,
+ 0x6c,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2f,0x20,
+ 0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x74,
+ 0x61,0x62,0x20,0x69,0x73,0x20,0x61,0x62,0x73,0x65,0x6e,0x74,0x2c,0x20,0x77,0x65,
+ 0x20,0x68,0x61,0x76,0x65,0x20,0x74,0x6f,0x20,0x69,0x6e,0x69,0x74,0x69,0x61,0x6c,
+ 0x69,0x7a,0x65,0x20,0x74,0x68,0x65,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x20,
+ 0x74,0x61,0x62,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x42,0x79,0x49,0x64,0x28,0x27,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x54,0x61,0x62,
+ 0x27,0x29,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,
+ 0x65,0x53,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,
+ 0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x6f,
+ 0x64,0x79,0x5f,0x6c,0x6f,0x61,0x64,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x20,0x3d,
+ 0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,
+ 0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x42,0x61,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x50,0x72,0x6f,0x67,
+ 0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x69,0x6e,0x69,0x74,0x28,0x70,0x72,0x6f,
+ 0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x45,
+ 0x72,0x72,0x6f,0x72,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,
+ 0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,
+ 0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,
+ 0x79,0x49,0x64,0x28,0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x68,0x72,0x6f,
+ 0x62,0x62,0x65,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x73,0x75,0x6d,
+ 0x6d,0x61,0x72,0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x73,0x74,0x79,
+ 0x6c,0x65,0x2e,0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,
+ 0x27,0x68,0x69,0x64,0x64,0x65,0x6e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x64,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,
+ 0x28,0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x45,0x72,0x72,0x6f,0x72,0x44,0x69,
+ 0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x64,0x69,0x76,0x2e,0x69,0x6e,
+ 0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x27,0x45,0x72,0x72,0x6f,0x72,
+ 0x3a,0x20,0x27,0x20,0x2b,0x20,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x69,0x73,0x52,0x65,0x70,0x6f,0x72,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x65,
+ 0x67,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,
+ 0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x20,
+ 0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,
+ 0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x73,0x75,0x6d,0x6d,0x61,
+ 0x72,0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x68,0x72,0x6f,0x62,0x62,
+ 0x65,0x72,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x76,0x69,0x73,0x69,0x62,0x69,0x6c,
+ 0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x76,0x69,0x73,0x69,0x62,0x6c,0x65,0x27,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x72,0x65,0x71,0x75,0x65,0x73,
+ 0x74,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,
+ 0x72,0x65,0x61,0x74,0x65,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x6f,0x70,0x65,0x6e,0x28,0x27,
+ 0x47,0x45,0x54,0x27,0x2c,0x20,0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2e,0x6a,0x73,0x6f,0x6e,0x27,0x2c,0x20,0x74,0x72,0x75,0x65,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x6f,
+ 0x6e,0x72,0x65,0x61,0x64,0x79,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6e,0x67,
+ 0x65,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x65,0x76,
+ 0x65,0x6e,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x72,0x65,0x61,0x64,
+ 0x79,0x53,0x74,0x61,0x74,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x34,0x29,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,
+ 0x20,0x28,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,
+ 0x20,0x21,0x3d,0x3d,0x20,0x30,0x20,0x26,0x26,0x20,0x72,0x65,0x71,0x75,0x65,0x73,
+ 0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x20,0x21,0x3d,0x3d,0x20,0x32,0x30,0x30,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,
+ 0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x72,0x65,0x73,0x70,0x6f,0x6e,0x73,
+ 0x65,0x20,0x3d,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x72,0x65,0x73,0x70,
+ 0x6f,0x6e,0x73,0x65,0x54,0x65,0x78,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x72,0x65,0x73,0x70,0x6f,
+ 0x6e,0x73,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x68,0x72,
+ 0x6f,0x77,0x20,0x34,0x30,0x34,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6a,0x73,0x6f,0x6e,0x20,0x3d,0x20,0x65,
+ 0x76,0x61,0x6c,0x28,0x27,0x28,0x27,0x20,0x2b,0x20,0x72,0x65,0x73,0x70,0x6f,0x6e,
+ 0x73,0x65,0x20,0x2b,0x20,0x27,0x29,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,
+ 0x6f,0x72,0x20,0x28,0x66,0x69,0x6c,0x65,0x20,0x69,0x6e,0x20,0x6a,0x73,0x6f,0x6e,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x43,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x20,0x3d,0x20,0x6a,0x73,0x6f,0x6e,0x5b,0x66,0x69,0x6c,0x65,0x5d,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x66,0x69,
+ 0x6c,0x65,0x5d,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x43,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x24,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x66,0x69,0x6c,0x65,0x5d,0x2e,0x73,
+ 0x6f,0x75,0x72,0x63,0x65,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x43,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x2e,0x73,0x6f,0x75,0x72,0x63,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,
+ 0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,
+ 0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,
+ 0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x68,0x69,
+ 0x64,0x64,0x65,0x6e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,
+ 0x61,0x74,0x63,0x68,0x20,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x45,0x72,
+ 0x72,0x6f,0x72,0x28,0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x65,0x6e,0x64,0x28,0x6e,0x75,
+ 0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x63,0x61,0x74,0x63,0x68,0x20,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x45,0x72,0x72,0x6f,0x72,0x28,
+ 0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x6d,
+ 0x6f,0x76,0x65,0x54,0x61,0x62,0x28,0x27,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x27,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x72,0x65,0x6d,0x6f,0x76,0x65,0x54,0x61,0x62,0x28,0x27,0x73,0x74,
+ 0x6f,0x72,0x65,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,
+ 0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x73,0x49,0x6e,0x76,0x65,
+ 0x72,0x74,0x65,0x64,0x4d,0x6f,0x64,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,
+ 0x6d,0x6f,0x76,0x65,0x54,0x61,0x62,0x28,0x27,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,
+ 0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x69,0x73,0x53,0x65,0x72,0x76,0x65,0x72,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x72,0x65,0x6d,0x6f,0x76,0x65,0x54,0x61,0x62,0x28,0x27,0x73,0x74,0x6f,0x72,
+ 0x65,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x69,0x6e,0x69,0x74,0x54,0x61,0x62,0x43,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x28,
+ 0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x69,0x6e,0x69,0x74,0x54,0x61,0x62,0x43,0x6f,0x6e,0x74,0x65,0x6e,
+ 0x74,0x73,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x73,0x65,0x61,0x72,
+ 0x63,0x68,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,
+ 0x6f,0x64,0x79,0x5f,0x72,0x65,0x73,0x69,0x7a,0x65,0x28,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x2f,0x4d,0x53,0x49,0x45,0x2f,0x2e,0x74,0x65,0x73,
+ 0x74,0x28,0x6e,0x61,0x76,0x69,0x67,0x61,0x74,0x6f,0x72,0x2e,0x75,0x73,0x65,0x72,
+ 0x41,0x67,0x65,0x6e,0x74,0x29,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x74,0x53,0x69,0x7a,
+ 0x65,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x2f,0x2f,0x20,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x0d,0x0a,0x2f,0x2f,0x20,0x74,0x61,0x62,0x20,0x31,0x0d,0x0a,0x0d,0x0a,0x66,0x75,
+ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x75,0x70,0x64,0x61,0x74,0x65,0x42,0x72,0x6f,0x77,0x73,0x65,0x72,0x28,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x6e,0x70,0x75,0x74,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,
+ 0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x22,0x6c,0x6f,0x63,0x61,
+ 0x74,0x69,0x6f,0x6e,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x72,0x61,0x6d,0x65,
+ 0x73,0x5b,0x30,0x5d,0x2e,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
+ 0x69,0x6e,0x70,0x75,0x74,0x2e,0x76,0x61,0x6c,0x75,0x65,0x3b,0x0d,0x0a,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x5f,0x6b,0x65,0x79,
+ 0x70,0x72,0x65,0x73,0x73,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x69,0x66,
+ 0x20,0x28,0x65,0x2e,0x6b,0x65,0x79,0x43,0x6f,0x64,0x65,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x31,0x33,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x75,0x70,0x64,0x61,0x74,0x65,0x42,0x72,0x6f,0x77,
+ 0x73,0x65,0x72,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,
+ 0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x75,0x74,0x74,0x6f,0x6e,0x5f,0x63,0x6c,0x69,
+ 0x63,0x6b,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x75,0x70,0x64,0x61,0x74,0x65,0x42,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x28,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,
+ 0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x5f,0x6c,0x6f,0x61,0x64,0x28,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x20,0x75,0x70,0x64,0x61,0x74,0x65,0x20,0x74,0x68,
+ 0x65,0x20,0x69,0x6e,0x70,0x75,0x74,0x20,0x62,0x6f,0x78,0x20,0x2a,0x2f,0x0d,0x0a,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x6e,0x70,0x75,0x74,0x20,0x3d,0x20,0x64,0x6f,
+ 0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,
+ 0x74,0x42,0x79,0x49,0x64,0x28,0x22,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x22,
+ 0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x20,0x73,0x6f,0x6d,0x65,0x74,
+ 0x69,0x6d,0x65,0x73,0x20,0x49,0x45,0x20,0x73,0x65,0x65,0x6d,0x73,0x20,0x74,0x6f,
+ 0x20,0x66,0x69,0x72,0x65,0x20,0x74,0x68,0x69,0x73,0x20,0x61,0x66,0x74,0x65,0x72,
+ 0x20,0x74,0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x68,0x61,0x73,0x20,0x62,0x65,0x65,
+ 0x6e,0x20,0x72,0x65,0x6d,0x6f,0x76,0x65,0x64,0x20,0x2a,0x2f,0x0d,0x0a,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x69,0x6e,0x70,0x75,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x6e,0x70,0x75,0x74,0x2e,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,
+ 0x66,0x72,0x61,0x6d,0x65,0x73,0x5b,0x30,0x5d,0x2e,0x6c,0x6f,0x63,0x61,0x74,0x69,
+ 0x6f,0x6e,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,
+ 0x2f,0x20,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x0d,
+ 0x0a,0x2f,0x2f,0x20,0x74,0x61,0x62,0x20,0x32,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,
+ 0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x63,0x72,0x65,0x61,0x74,0x65,0x4c,0x69,0x6e,0x6b,0x28,0x66,0x69,0x6c,0x65,
+ 0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x6c,0x69,0x6e,0x6b,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,
+ 0x61,0x22,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x75,0x72,
+ 0x6c,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x61,0x6c,0x6c,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x65,0x78,0x74,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x6c,0x69,0x6e,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x75,0x72,0x6c,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x20,0x2b,0x20,0x22,0x2e,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x68,0x74,0x6d,0x6c,0x3f,
+ 0x22,0x20,0x2b,0x20,0x6c,0x69,0x6e,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,
+ 0x61,0x6c,0x6c,0x20,0x3d,0x20,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x67,0x65,0x74,0x28,0x27,0x22,0x20,0x2b,0x20,0x66,0x69,0x6c,0x65,0x20,
+ 0x2b,0x20,0x22,0x27,0x2c,0x20,0x22,0x20,0x2b,0x20,0x6c,0x69,0x6e,0x65,0x20,0x2b,
+ 0x20,0x22,0x29,0x3b,0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,0x74,
+ 0x20,0x3d,0x20,0x6c,0x69,0x6e,0x65,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x75,0x72,0x6c,0x20,0x3d,0x20,0x66,0x69,
+ 0x6c,0x65,0x20,0x2b,0x20,0x22,0x2e,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2e,0x68,0x74,0x6d,0x6c,0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,
+ 0x6c,0x6c,0x20,0x3d,0x20,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x67,0x65,0x74,0x28,0x27,0x22,0x20,0x2b,0x20,0x66,0x69,0x6c,0x65,0x20,0x2b,
+ 0x20,0x22,0x27,0x29,0x3b,0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,
+ 0x74,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x6c,0x69,0x6e,0x6b,0x2e,0x73,0x65,0x74,0x41,0x74,0x74,0x72,
+ 0x69,0x62,0x75,0x74,0x65,0x28,0x27,0x68,0x72,0x65,0x66,0x27,0x2c,0x20,0x27,0x6a,
+ 0x61,0x76,0x61,0x73,0x63,0x72,0x69,0x70,0x74,0x3a,0x27,0x20,0x2b,0x20,0x63,0x61,
+ 0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x69,0x6e,0x6b,0x2e,0x61,0x70,0x70,
+ 0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,0x6f,0x64,0x65,
+ 0x28,0x74,0x65,0x78,0x74,0x29,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x72,0x65,
+ 0x74,0x75,0x72,0x6e,0x20,0x6c,0x69,0x6e,0x6b,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,
+ 0x53,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x28,0x63,0x63,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,
+ 0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x63,0x68,0x65,0x63,
+ 0x6b,0x62,0x6f,0x78,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,
+ 0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,
+ 0x20,0x3d,0x20,0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x2e,0x63,0x68,0x65,0x63,
+ 0x6b,0x65,0x64,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,
+ 0x63,0x63,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x63,0x20,0x3d,0x20,
+ 0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x21,0x20,0x63,0x63,0x29,0x20,0x7b,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,0x43,
+ 0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x49,0x46,0x20,0x30,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x22,0x4e,0x6f,0x20,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,
+ 0x20,0x66,0x6f,0x75,0x6e,0x64,0x2e,0x22,0x3b,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,
+ 0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x45,0x4e,0x44,0x49,0x46,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x62,0x6f,
+ 0x64,0x79,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,
+ 0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x22,0x73,0x75,
+ 0x6d,0x6d,0x61,0x72,0x79,0x54,0x62,0x6f,0x64,0x79,0x22,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x28,0x74,0x62,0x6f,0x64,0x79,0x2e,0x68,0x61,
+ 0x73,0x43,0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x28,0x29,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x62,0x6f,0x64,0x79,0x2e,0x72,0x65,0x6d,0x6f,
+ 0x76,0x65,0x43,0x68,0x69,0x6c,0x64,0x28,0x74,0x62,0x6f,0x64,0x79,0x2e,0x66,0x69,
+ 0x72,0x73,0x74,0x43,0x68,0x69,0x6c,0x64,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x20,
+ 0x3d,0x20,0x7b,0x20,0x66,0x69,0x6c,0x65,0x73,0x3a,0x30,0x2c,0x20,0x73,0x74,0x61,
+ 0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x3a,0x30,0x2c,0x20,0x65,0x78,0x65,0x63,0x75,
+ 0x74,0x65,0x64,0x3a,0x30,0x2c,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x3a,
+ 0x30,0x2c,0x20,0x73,0x6b,0x69,0x70,0x70,0x65,0x64,0x3a,0x30,0x20,0x7d,0x3b,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x73,0x20,0x3d,0x20,0x5b,0x5d,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x66,0x69,0x6c,0x65,0x20,0x69,
+ 0x6e,0x20,0x63,0x63,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,
+ 0x65,0x73,0x2e,0x70,0x75,0x73,0x68,0x28,0x66,0x69,0x6c,0x65,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x66,0x69,0x6c,0x65,0x73,0x2e,0x73,0x6f,0x72,
+ 0x74,0x28,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x72,0x6f,
+ 0x77,0x43,0x6f,0x75,0x6e,0x74,0x65,0x72,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x66,0x20,0x3d,0x20,0x30,0x3b,
+ 0x20,0x66,0x20,0x3c,0x20,0x66,0x69,0x6c,0x65,0x73,0x2e,0x6c,0x65,0x6e,0x67,0x74,
+ 0x68,0x3b,0x20,0x66,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,
+ 0x69,0x6c,0x65,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x73,0x5b,0x66,0x5d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,
+ 0x62,0x65,0x72,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,0x75,
+ 0x6d,0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,0x3d,0x20,0x30,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,0x75,0x6d,0x5f,0x65,
+ 0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x20,0x3d,0x20,
+ 0x5b,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,
+ 0x65,0x43,0x43,0x20,0x3d,0x20,0x63,0x63,0x5b,0x66,0x69,0x6c,0x65,0x5d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,
+ 0x3d,0x20,0x66,0x69,0x6c,0x65,0x43,0x43,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,
+ 0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x20,
+ 0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x6f,
+ 0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,0x20,0x3d,0x20,0x6e,0x75,0x6c,
+ 0x6c,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x66,0x69,0x6c,0x65,
+ 0x43,0x43,0x2e,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,
+ 0x69,0x6f,0x6e,0x61,0x6c,0x73,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x43,0x43,0x2e,
+ 0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x6c,
+ 0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x3d,0x20,0x30,0x3b,0x20,0x6c,
+ 0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x3c,0x20,0x6c,0x65,0x6e,0x67,
+ 0x74,0x68,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x2b,0x2b,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,
+ 0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x43,0x43,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,
+ 0x6d,0x62,0x65,0x72,0x5d,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x3d,
+ 0x3d,0x3d,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,
+ 0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,
+ 0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x20,0x3d,0x20,0x30,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x65,0x6c,0x73,0x65,0x20,0x69,0x66,0x20,0x28,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,
+ 0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x20,0x3d,
+ 0x3d,0x3d,0x20,0x30,0x20,0x26,0x26,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,
+ 0x6e,0x61,0x6c,0x73,0x20,0x26,0x26,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,
+ 0x6e,0x61,0x6c,0x73,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x5d,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x75,0x72,
+ 0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,
+ 0x6e,0x64,0x20,0x3d,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,
+ 0x73,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x5d,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x69,0x66,0x20,0x28,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,
+ 0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x20,0x21,0x3d,0x3d,0x20,0x30,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,
+ 0x74,0x69,0x6e,0x75,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6e,0x20,0x3d,
+ 0x3d,0x3d,0x20,0x75,0x6e,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x20,0x7c,0x7c,0x20,
+ 0x6e,0x20,0x3d,0x3d,0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6e,0x20,0x3d,0x3d,0x3d,0x20,0x30,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6d,0x69,0x73,0x73,0x69,
+ 0x6e,0x67,0x2e,0x70,0x75,0x73,0x68,0x28,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,
+ 0x65,0x72,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x6e,0x75,0x6d,0x5f,0x65,0x78,0x65,0x63,0x75,0x74,0x65,
+ 0x64,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x6e,0x75,0x6d,0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,
+ 0x6e,0x74,0x73,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,
+ 0x61,0x67,0x65,0x20,0x3d,0x20,0x28,0x20,0x6e,0x75,0x6d,0x5f,0x73,0x74,0x61,0x74,
+ 0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,0x3d,0x3d,0x3d,0x20,0x30,0x20,0x3f,0x20,0x30,
+ 0x20,0x3a,0x20,0x70,0x61,0x72,0x73,0x65,0x49,0x6e,0x74,0x28,0x31,0x30,0x30,0x20,
+ 0x2a,0x20,0x6e,0x75,0x6d,0x5f,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x20,0x2f,
+ 0x20,0x6e,0x75,0x6d,0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x29,
+ 0x20,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x72,
+ 0x6f,0x77,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,
+ 0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x74,0x72,0x22,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x2e,0x63,0x6c,0x61,0x73,
+ 0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x28,0x20,0x72,0x6f,0x77,0x43,0x6f,0x75,
+ 0x6e,0x74,0x65,0x72,0x2b,0x2b,0x20,0x25,0x20,0x32,0x20,0x3d,0x3d,0x20,0x30,0x20,
+ 0x3f,0x20,0x22,0x6f,0x64,0x64,0x22,0x20,0x3a,0x20,0x22,0x65,0x76,0x65,0x6e,0x22,
+ 0x20,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,
+ 0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,
+ 0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x74,0x64,
+ 0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x63,0x6c,
+ 0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x6c,0x65,0x66,0x74,0x43,
+ 0x6f,0x6c,0x75,0x6d,0x6e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x6c,0x69,0x6e,0x6b,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x63,0x72,0x65,0x61,0x74,0x65,0x4c,0x69,0x6e,0x6b,0x28,0x66,0x69,
+ 0x6c,0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,
+ 0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x6c,0x69,0x6e,0x6b,0x29,
+ 0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x2e,0x61,0x70,0x70,
+ 0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x63,0x65,0x6c,0x6c,0x29,0x3b,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,
+ 0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,
+ 0x6d,0x65,0x6e,0x74,0x28,0x22,0x74,0x64,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x63,0x65,0x6c,0x6c,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,
+ 0x3d,0x20,0x27,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x27,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,
+ 0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,
+ 0x74,0x65,0x54,0x65,0x78,0x74,0x4e,0x6f,0x64,0x65,0x28,0x6e,0x75,0x6d,0x5f,0x73,
+ 0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x72,0x6f,0x77,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,
+ 0x64,0x28,0x63,0x65,0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x63,0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,
+ 0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x74,
+ 0x64,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x63,
+ 0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x6e,0x75,0x6d,0x65,
+ 0x72,0x69,0x63,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,
+ 0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,
+ 0x6f,0x64,0x65,0x28,0x6e,0x75,0x6d,0x5f,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x64,
+ 0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x2e,0x61,0x70,0x70,
+ 0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x63,0x65,0x6c,0x6c,0x29,0x3b,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x6e,0x65,0x77,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x74,0x64,0x20,0x63,0x6f,0x6e,0x74,0x61,0x69,
+ 0x6e,0x69,0x6e,0x67,0x20,0x61,0x20,0x62,0x61,0x72,0x20,0x67,0x72,0x61,0x70,0x68,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x28,0x22,0x74,0x64,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x63,0x65,0x6c,0x6c,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,
+ 0x20,0x27,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x27,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x20,0x3d,
+ 0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,
+ 0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x64,0x69,0x76,0x22,0x29,0x2c,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,
+ 0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x64,0x69,0x76,0x22,0x29,
+ 0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x20,0x3d,
+ 0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,
+ 0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x73,0x70,0x61,0x6e,0x22,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x2e,0x63,
+ 0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x22,0x70,0x63,0x74,0x47,
+ 0x72,0x61,0x70,0x68,0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x28,0x20,
+ 0x6e,0x75,0x6d,0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,0x3d,
+ 0x3d,0x3d,0x20,0x30,0x20,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,
+ 0x61,0x6d,0x65,0x20,0x3d,0x20,0x22,0x73,0x6b,0x69,0x70,0x70,0x65,0x64,0x22,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x2e,0x61,0x70,
+ 0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,0x6f,0x64,
+ 0x65,0x28,0x22,0x4e,0x2f,0x41,0x22,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,
+ 0x61,0x6d,0x65,0x20,0x3d,0x20,0x22,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x22,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x76,0x65,0x72,0x65,
+ 0x64,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x77,0x69,0x64,0x74,0x68,0x20,0x3d,0x20,
+ 0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x20,0x2b,0x20,0x22,0x70,0x78,
+ 0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x2e,
+ 0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,
+ 0x6f,0x64,0x65,0x28,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x20,0x2b,
+ 0x20,0x27,0x25,0x27,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,
+ 0x65,0x20,0x3d,0x20,0x22,0x70,0x63,0x74,0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,
+ 0x68,0x69,0x6c,0x64,0x28,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,
+ 0x68,0x69,0x6c,0x64,0x28,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,
+ 0x43,0x68,0x69,0x6c,0x64,0x28,0x70,0x63,0x74,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x72,0x6f,0x77,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,
+ 0x28,0x63,0x65,0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,
+ 0x66,0x20,0x28,0x73,0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,
+ 0x6c,0x75,0x6d,0x6e,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,
+ 0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,
+ 0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x74,0x64,
+ 0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,
+ 0x76,0x61,0x72,0x20,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x6d,
+ 0x69,0x73,0x73,0x69,0x6e,0x67,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,
+ 0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,
+ 0x66,0x20,0x28,0x69,0x20,0x21,0x3d,0x3d,0x20,0x30,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,0x70,
+ 0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,0x6f,0x64,
+ 0x65,0x28,0x22,0x2c,0x20,0x22,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6c,0x69,
+ 0x6e,0x6b,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x63,0x72,0x65,0x61,0x74,0x65,0x4c,0x69,0x6e,0x6b,0x28,0x66,0x69,0x6c,0x65,0x2c,
+ 0x20,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x5b,0x69,0x5d,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,0x70,0x70,0x65,
+ 0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x6c,0x69,0x6e,0x6b,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,
+ 0x6f,0x77,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x63,
+ 0x65,0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x74,0x62,0x6f,0x64,0x79,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,
+ 0x43,0x68,0x69,0x6c,0x64,0x28,0x72,0x6f,0x77,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x66,0x69,0x6c,0x65,0x73,
+ 0x27,0x5d,0x20,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x6f,0x74,0x61,
+ 0x6c,0x73,0x5b,0x27,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x27,0x5d,
+ 0x20,0x2b,0x3d,0x20,0x6e,0x75,0x6d,0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,
+ 0x74,0x73,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,
+ 0x27,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x27,0x5d,0x20,0x2b,0x3d,0x20,0x6e,
+ 0x75,0x6d,0x5f,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x27,0x5d,0x20,0x2b,0x3d,0x20,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,
+ 0x67,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x28,0x20,0x6e,0x75,0x6d,
+ 0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x30,0x20,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,
+ 0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x73,0x6b,0x69,0x70,0x70,0x65,0x64,0x27,0x5d,
+ 0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x2f,0x2f,0x20,0x77,0x72,0x69,0x74,0x65,0x20,0x74,0x6f,0x74,0x61,0x6c,
+ 0x73,0x20,0x64,0x61,0x74,0x61,0x20,0x69,0x6e,0x74,0x6f,0x20,0x73,0x75,0x6d,0x6d,
+ 0x61,0x72,0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x20,0x72,0x6f,0x77,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,
+ 0x79,0x49,0x64,0x28,0x22,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x6f,0x74,0x61,
+ 0x6c,0x73,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x74,
+ 0x72,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,
+ 0x72,0x20,0x74,0x64,0x73,0x20,0x3d,0x20,0x74,0x72,0x2e,0x67,0x65,0x74,0x45,0x6c,
+ 0x65,0x6d,0x65,0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,
+ 0x22,0x74,0x64,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x74,0x64,0x73,0x5b,0x30,0x5d,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,
+ 0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x22,0x73,0x70,0x61,
+ 0x6e,0x22,0x29,0x5b,0x31,0x5d,0x2e,0x66,0x69,0x72,0x73,0x74,0x43,0x68,0x69,0x6c,
+ 0x64,0x2e,0x6e,0x6f,0x64,0x65,0x56,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x74,0x6f,
+ 0x74,0x61,0x6c,0x73,0x5b,0x27,0x66,0x69,0x6c,0x65,0x73,0x27,0x5d,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x64,0x73,0x5b,0x31,0x5d,0x2e,0x66,
+ 0x69,0x72,0x73,0x74,0x43,0x68,0x69,0x6c,0x64,0x2e,0x6e,0x6f,0x64,0x65,0x56,0x61,
+ 0x6c,0x75,0x65,0x20,0x3d,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x73,0x74,
+ 0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x27,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x74,0x64,0x73,0x5b,0x32,0x5d,0x2e,0x66,0x69,0x72,0x73,
+ 0x74,0x43,0x68,0x69,0x6c,0x64,0x2e,0x6e,0x6f,0x64,0x65,0x56,0x61,0x6c,0x75,0x65,
+ 0x20,0x3d,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x65,0x78,0x65,0x63,0x75,
+ 0x74,0x65,0x64,0x27,0x5d,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x3d,
+ 0x20,0x70,0x61,0x72,0x73,0x65,0x49,0x6e,0x74,0x28,0x74,0x6f,0x74,0x61,0x6c,0x73,
+ 0x5b,0x27,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x27,0x5d,0x20,0x2f,0x20,0x28,
+ 0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x66,0x69,0x6c,0x65,0x73,0x27,0x5d,
+ 0x20,0x2d,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x73,0x6b,0x69,0x70,0x70,
+ 0x65,0x64,0x27,0x5d,0x20,0x29,0x20,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x28,0x20,0x69,0x73,0x4e,0x61,0x4e,0x28,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x29,0x20,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x64,0x73,0x5b,
+ 0x33,0x5d,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,0x42,0x79,
+ 0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x22,0x73,0x70,0x61,0x6e,0x22,0x29,0x5b,
+ 0x30,0x5d,0x2e,0x66,0x69,0x72,0x73,0x74,0x43,0x68,0x69,0x6c,0x64,0x2e,0x6e,0x6f,
+ 0x64,0x65,0x56,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x20,0x2b,0x20,0x27,0x25,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x74,0x64,0x73,0x5b,0x33,0x5d,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,
+ 0x6d,0x65,0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x22,
+ 0x64,0x69,0x76,0x22,0x29,0x5b,0x31,0x5d,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x77,
+ 0x69,0x64,0x74,0x68,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,
+ 0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,
+ 0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x61,0x70,0x70,0x65,0x6e,0x64,0x4d,0x69,0x73,0x73,0x69,
+ 0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x68,0x65,0x61,0x64,0x65,0x72,0x52,0x6f,0x77,0x20,0x3d,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x68,0x65,0x61,0x64,0x65,0x72,0x52,
+ 0x6f,0x77,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6d,0x69,0x73,
+ 0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,0x65,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x28,0x27,0x74,0x68,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x69,
+ 0x73,0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,0x65,0x72,0x2e,0x69,0x64,0x20,0x3d,
+ 0x20,0x27,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,0x65,0x72,0x27,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,
+ 0x65,0x72,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x27,
+ 0x3c,0x61,0x62,0x62,0x72,0x20,0x74,0x69,0x74,0x6c,0x65,0x3d,0x22,0x4c,0x69,0x73,
+ 0x74,0x20,0x6f,0x66,0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,
+ 0x6d,0x69,0x73,0x73,0x65,0x64,0x20,0x64,0x75,0x72,0x69,0x6e,0x67,0x20,0x65,0x78,
+ 0x65,0x63,0x75,0x74,0x69,0x6f,0x6e,0x22,0x3e,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,
+ 0x3c,0x2f,0x61,0x62,0x62,0x72,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x61,
+ 0x64,0x65,0x72,0x52,0x6f,0x77,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,
+ 0x6c,0x64,0x28,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,0x65,0x72,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,
+ 0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,
+ 0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x65,0x6d,0x70,0x74,0x79,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,
+ 0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x27,0x74,0x64,0x27,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x65,0x6d,0x70,0x74,0x79,0x2e,0x69,0x64,0x20,0x3d,0x20,0x27,
+ 0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x65,0x6c,0x6c,0x27,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x2e,0x61,
+ 0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x65,0x6d,0x70,0x74,0x79,
+ 0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x6d,
+ 0x6f,0x76,0x65,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,
+ 0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6d,0x69,0x73,0x73,
+ 0x69,0x6e,0x67,0x4e,0x6f,0x64,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x69,0x73,0x73,
+ 0x69,0x6e,0x67,0x4e,0x6f,0x64,0x65,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,0x65,0x72,
+ 0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x4e,0x6f,
+ 0x64,0x65,0x2e,0x70,0x61,0x72,0x65,0x6e,0x74,0x4e,0x6f,0x64,0x65,0x2e,0x72,0x65,
+ 0x6d,0x6f,0x76,0x65,0x43,0x68,0x69,0x6c,0x64,0x28,0x6d,0x69,0x73,0x73,0x69,0x6e,
+ 0x67,0x4e,0x6f,0x64,0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x69,0x73,0x73,0x69,
+ 0x6e,0x67,0x4e,0x6f,0x64,0x65,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,
+ 0x28,0x27,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x65,0x6c,0x6c,0x27,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x4e,0x6f,0x64,0x65,0x2e,
+ 0x70,0x61,0x72,0x65,0x6e,0x74,0x4e,0x6f,0x64,0x65,0x2e,0x72,0x65,0x6d,0x6f,0x76,
+ 0x65,0x43,0x68,0x69,0x6c,0x64,0x28,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x4e,0x6f,
+ 0x64,0x65,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,
+ 0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x5f,0x63,0x6c,0x69,0x63,0x6b,0x28,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,
+ 0x72,0x61,0x74,0x69,0x6f,0x6e,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,
+ 0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x62,0x65,0x67,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,
+ 0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,
+ 0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,
+ 0x49,0x64,0x28,0x27,0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x27,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,
+ 0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x20,0x3d,0x20,0x63,0x68,0x65,0x63,0x6b,
+ 0x62,0x6f,0x78,0x2e,0x63,0x68,0x65,0x63,0x6b,0x65,0x64,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x73,0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,0x74,0x28,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x73,0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,
+ 0x6d,0x6e,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x61,0x70,0x70,0x65,0x6e,0x64,0x4d,0x69,
+ 0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x28,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x72,0x65,0x6d,0x6f,0x76,0x65,0x4d,0x69,0x73,0x73,0x69,0x6e,
+ 0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,0x75,0x6d,
+ 0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x2c,
+ 0x20,0x35,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x74,0x72,0x75,0x65,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x0d,0x0a,0x2f,0x2f,
+ 0x20,0x74,0x61,0x62,0x20,0x33,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,
+ 0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x6d,0x61,
+ 0x6b,0x65,0x54,0x61,0x62,0x6c,0x65,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x3d,0x20,0x5f,0x24,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x46,0x69,0x6c,
+ 0x65,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6c,0x69,0x6e,0x65,0x73,
+ 0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x73,0x6f,0x75,0x72,
+ 0x63,0x65,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2f,0x20,0x74,0x68,0x69,0x73,
+ 0x20,0x63,0x61,0x6e,0x20,0x68,0x61,0x70,0x70,0x65,0x6e,0x20,0x69,0x66,0x20,0x74,
+ 0x68,0x65,0x72,0x65,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x65,0x72,0x72,0x6f,0x72,
+ 0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,
+ 0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x20,0x66,0x69,0x6c,0x65,
+ 0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x6c,0x69,0x6e,0x65,0x73,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6c,0x69,0x6e,0x65,0x73,0x20,0x3d,0x20,
+ 0x5b,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,
+ 0x72,0x20,0x72,0x6f,0x77,0x73,0x20,0x3d,0x20,0x5b,0x27,0x3c,0x74,0x61,0x62,0x6c,
+ 0x65,0x20,0x69,0x64,0x3d,0x22,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,
+ 0x65,0x22,0x3e,0x27,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x20,
+ 0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,0x67,
+ 0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x27,0x29,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x6c,0x65,0x48,0x54,
+ 0x4d,0x4c,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x75,0x72,0x72,0x65,
+ 0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,
+ 0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6a,0x6f,0x69,0x6e,0x54,0x61,0x62,0x6c,0x65,0x52,0x6f,0x77,
+ 0x73,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x6c,0x65,
+ 0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x72,0x6f,0x77,0x73,0x2e,0x6a,0x6f,0x69,0x6e,
+ 0x28,0x27,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x50,0x72,0x6f,0x67,0x72,
+ 0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x65,0x74,0x50,0x65,0x72,0x63,0x65,0x6e,
+ 0x74,0x61,0x67,0x65,0x28,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,
+ 0x2c,0x20,0x36,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2a,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x6d,0x61,0x79,0x20,0x62,0x65,0x20,
+ 0x61,0x20,0x6c,0x6f,0x6e,0x67,0x20,0x64,0x65,0x6c,0x61,0x79,0x2c,0x20,0x73,0x6f,
+ 0x20,0x73,0x65,0x74,0x20,0x61,0x20,0x74,0x69,0x6d,0x65,0x6f,0x75,0x74,0x20,0x6f,
+ 0x66,0x20,0x31,0x30,0x30,0x20,0x6d,0x73,0x20,0x74,0x6f,0x20,0x6d,0x61,0x6b,0x65,
+ 0x20,0x73,0x75,0x72,0x65,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x64,
+ 0x69,0x73,0x70,0x6c,0x61,0x79,0x20,0x69,0x73,0x20,0x75,0x70,0x64,0x61,0x74,0x65,
+ 0x64,0x2e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2a,0x2f,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x73,0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,0x74,0x28,0x61,0x70,0x70,0x65,0x6e,
+ 0x64,0x54,0x61,0x62,0x6c,0x65,0x2c,0x20,0x31,0x30,0x30,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,
+ 0x20,0x61,0x70,0x70,0x65,0x6e,0x64,0x54,0x61,0x62,0x6c,0x65,0x28,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,
+ 0x44,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,
+ 0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x73,
+ 0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x2e,0x69,0x6e,0x6e,0x65,0x72,
+ 0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x74,0x61,0x62,0x6c,0x65,0x48,0x54,0x4d,0x4c,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,
+ 0x61,0x72,0x2e,0x73,0x65,0x74,0x50,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,
+ 0x28,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2c,0x20,0x38,0x30,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x73,0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,
+ 0x75,0x74,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x63,
+ 0x72,0x6f,0x6c,0x6c,0x54,0x6f,0x4c,0x69,0x6e,0x65,0x2c,0x20,0x30,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,
+ 0x28,0x69,0x20,0x3c,0x20,0x6c,0x69,0x6e,0x65,0x73,0x2e,0x6c,0x65,0x6e,0x67,0x74,
+ 0x68,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6c,0x69,
+ 0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x3d,0x20,0x69,0x20,0x2b,0x20,0x31,
+ 0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6c,0x69,0x6e,
+ 0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x3d,0x3d,0x3d,0x20,0x63,0x75,0x72,0x72,
+ 0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,
+ 0x64,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x75,0x72,0x72,
+ 0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,
+ 0x64,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x69,0x66,0x20,0x28,0x63,0x75,0x72,0x72,
+ 0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,
+ 0x64,0x20,0x3d,0x3d,0x3d,0x20,0x30,0x20,0x26,0x26,0x20,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x2e,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,
+ 0x20,0x26,0x26,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x63,0x6f,0x6e,
+ 0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,
+ 0x6d,0x62,0x65,0x72,0x5d,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,
+ 0x61,0x6c,0x45,0x6e,0x64,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x2e,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,0x5b,0x6c,0x69,
+ 0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x72,0x6f,0x77,
+ 0x20,0x3d,0x20,0x27,0x3c,0x74,0x72,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x27,0x3c,0x74,0x64,0x20,0x63,0x6c,0x61,0x73,
+ 0x73,0x3d,0x22,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x22,0x3e,0x27,0x20,0x2b,0x20,
+ 0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x2b,0x20,0x27,0x3c,0x2f,
+ 0x74,0x64,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x74,
+ 0x69,0x6d,0x65,0x73,0x45,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x20,0x3d,0x20,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,
+ 0x65,0x72,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x69,
+ 0x6d,0x65,0x73,0x45,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x20,0x21,0x3d,0x3d,0x20,
+ 0x75,0x6e,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x20,0x26,0x26,0x20,0x74,0x69,0x6d,
+ 0x65,0x73,0x45,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x20,0x21,0x3d,0x3d,0x20,0x6e,
+ 0x75,0x6c,0x6c,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,
+ 0x20,0x28,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,
+ 0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x20,0x21,0x3d,0x3d,0x20,0x30,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,
+ 0x20,0x27,0x3c,0x74,0x64,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x79,0x20,0x6e,
+ 0x75,0x6d,0x65,0x72,0x69,0x63,0x22,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,
+ 0x69,0x66,0x20,0x28,0x74,0x69,0x6d,0x65,0x73,0x45,0x78,0x65,0x63,0x75,0x74,0x65,
+ 0x64,0x20,0x3d,0x3d,0x3d,0x20,0x30,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x27,0x3c,0x74,0x64,0x20,
+ 0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x72,0x20,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,
+ 0x22,0x20,0x69,0x64,0x3d,0x22,0x6c,0x69,0x6e,0x65,0x2d,0x27,0x20,0x2b,0x20,0x6c,
+ 0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x2b,0x20,0x27,0x22,0x3e,0x27,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x27,0x3c,0x74,0x64,0x20,0x63,0x6c,
+ 0x61,0x73,0x73,0x3d,0x22,0x67,0x20,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x22,0x3e,
+ 0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x74,0x69,0x6d,0x65,0x73,0x45,
+ 0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x27,0x3c,0x2f,0x74,0x64,0x3e,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,
+ 0x20,0x27,0x3c,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x64,0x3e,0x27,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,
+ 0x20,0x27,0x3c,0x74,0x64,0x3e,0x3c,0x70,0x72,0x65,0x3e,0x27,0x20,0x2b,0x20,0x6c,
+ 0x69,0x6e,0x65,0x73,0x5b,0x69,0x5d,0x20,0x2b,0x20,0x27,0x3c,0x2f,0x70,0x72,0x65,
+ 0x3e,0x3c,0x2f,0x74,0x64,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,
+ 0x77,0x20,0x2b,0x3d,0x20,0x27,0x3c,0x2f,0x74,0x72,0x3e,0x27,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x27,0x5c,0x6e,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x73,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,
+ 0x6d,0x62,0x65,0x72,0x5d,0x20,0x3d,0x20,0x72,0x6f,0x77,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x72,
+ 0x6f,0x77,0x73,0x5b,0x69,0x20,0x2b,0x20,0x31,0x5d,0x20,0x3d,0x20,0x27,0x3c,0x2f,
+ 0x74,0x61,0x62,0x6c,0x65,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x50,0x72,0x6f,0x67,
+ 0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x65,0x74,0x50,0x65,0x72,0x63,0x65,
+ 0x6e,0x74,0x61,0x67,0x65,0x28,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,
+ 0x72,0x2c,0x20,0x34,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x73,0x65,0x74,0x54,0x69,
+ 0x6d,0x65,0x6f,0x75,0x74,0x28,0x6a,0x6f,0x69,0x6e,0x54,0x61,0x62,0x6c,0x65,0x52,
+ 0x6f,0x77,0x73,0x2c,0x20,0x30,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,
+ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x73,0x63,0x72,0x6f,0x6c,0x6c,0x54,0x6f,0x4c,0x69,0x6e,0x65,0x28,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x73,0x65,0x6c,0x65,0x63,0x74,0x54,0x61,0x62,0x28,0x27,0x73,0x6f,0x75,
+ 0x72,0x63,0x65,0x54,0x61,0x62,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x21,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x4c,0x69,0x6e,0x65,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,
+ 0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x64,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x4c,0x69,0x6e,0x65,0x20,0x3d,0x3d,
+ 0x3d,0x20,0x31,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x64,0x69,0x76,0x2e,
+ 0x73,0x63,0x72,0x6f,0x6c,0x6c,0x54,0x6f,0x70,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,
+ 0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,
+ 0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x6c,0x69,0x6e,0x65,0x2d,0x27,0x20,0x2b,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,
+ 0x6e,0x74,0x4c,0x69,0x6e,0x65,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x2f,0x2f,0x20,0x74,0x68,0x69,0x73,0x20,0x6d,0x69,0x67,0x68,0x74,0x20,0x6e,0x6f,
+ 0x74,0x20,0x62,0x65,0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x69,0x66,0x20,0x74,0x68,
+ 0x65,0x72,0x65,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x65,0x72,0x72,0x6f,0x72,0x20,
+ 0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x20,
+ 0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x63,0x65,0x6c,0x6c,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x64,0x69,0x76,0x4f,0x66,0x66,0x73,0x65,0x74,
+ 0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,
+ 0x6e,0x64,0x50,0x6f,0x73,0x28,0x64,0x69,0x76,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x65,0x6c,0x6c,0x4f,0x66,0x66,0x73,0x65,
+ 0x74,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,
+ 0x69,0x6e,0x64,0x50,0x6f,0x73,0x28,0x63,0x65,0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x64,0x69,0x76,0x2e,0x73,0x63,0x72,0x6f,0x6c,0x6c,0x54,
+ 0x6f,0x70,0x20,0x3d,0x20,0x63,0x65,0x6c,0x6c,0x4f,0x66,0x66,0x73,0x65,0x74,0x20,
+ 0x2d,0x20,0x64,0x69,0x76,0x4f,0x66,0x66,0x73,0x65,0x74,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x4c,0x69,
+ 0x6e,0x65,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,
+ 0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x4c,0x6f,0x61,0x64,0x73,0x20,0x74,0x68,
+ 0x65,0x20,0x67,0x69,0x76,0x65,0x6e,0x20,0x66,0x69,0x6c,0x65,0x20,0x28,0x61,0x6e,
+ 0x64,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x20,0x6c,0x69,0x6e,0x65,0x29,
+ 0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x74,
+ 0x61,0x62,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x67,0x65,0x74,
+ 0x28,0x66,0x69,0x6c,0x65,0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,
+ 0x69,0x6f,0x6e,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,
+ 0x72,0x6e,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x65,0x67,0x69,0x6e,0x4c,0x65,0x6e,0x67,
+ 0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x73,0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,0x74,0x28,0x66,0x75,
+ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x20,0x3d,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,
+ 0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x73,0x6f,0x75,0x72,0x63,
+ 0x65,0x44,0x69,0x76,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,
+ 0x20,0x27,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x6c,0x65,0x63,0x74,0x54,0x61,0x62,0x28,0x27,
+ 0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x66,0x69,0x6c,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,
+ 0x74,0x46,0x69,0x6c,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,
+ 0x6e,0x74,0x4c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x6c,0x69,0x6e,0x65,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,0x6f,0x75,0x72,
+ 0x63,0x65,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x46,0x69,0x6c,0x65,0x20,0x3d,0x3d,
+ 0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x20,0x3d,0x20,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x42,0x79,0x49,0x64,0x28,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x27,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x2e,
+ 0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x2e,0x6f,0x6e,0x63,
+ 0x6c,0x69,0x63,0x6b,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x74,0x61,0x62,0x5f,0x63,0x6c,0x69,0x63,0x6b,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x46,
+ 0x69,0x6c,0x65,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,
+ 0x72,0x72,0x65,0x6e,0x74,0x4c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x6c,0x69,0x6e,0x65,
+ 0x20,0x7c,0x7c,0x20,0x31,0x3b,0x20,0x20,0x2f,0x2f,0x20,0x77,0x68,0x65,0x6e,0x20,
+ 0x63,0x68,0x61,0x6e,0x67,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x73,0x6f,0x75,
+ 0x72,0x63,0x65,0x2c,0x20,0x61,0x6c,0x77,0x61,0x79,0x73,0x20,0x73,0x63,0x72,0x6f,
+ 0x6c,0x6c,0x20,0x74,0x6f,0x20,0x74,0x6f,0x70,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x44,0x69,0x76,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x66,0x69,0x6c,0x65,0x44,0x69,0x76,0x27,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x44,0x69,
+ 0x76,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,
+ 0x46,0x69,0x6c,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,
+ 0x61,0x74,0x65,0x53,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x2c,0x20,0x35,0x30,0x29,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x43,0x61,0x6c,0x63,
+ 0x75,0x6c,0x61,0x74,0x65,0x73,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,
+ 0x73,0x74,0x61,0x74,0x69,0x73,0x74,0x69,0x63,0x73,0x20,0x66,0x6f,0x72,0x20,0x74,
+ 0x68,0x65,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x20,0x73,0x6f,0x75,0x72,0x63,
+ 0x65,0x20,0x66,0x69,0x6c,0x65,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,
+ 0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,0x6f,0x75,0x72,
+ 0x63,0x65,0x54,0x61,0x62,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x21,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,
+ 0x72,0x72,0x65,0x6e,0x74,0x46,0x69,0x6c,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,
+ 0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,
+ 0x67,0x72,0x65,0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x4c,0x61,
+ 0x62,0x65,0x6c,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,
+ 0x4c,0x20,0x3d,0x20,0x27,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x69,0x6e,0x67,
+ 0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x2e,0x2e,0x2e,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,
+ 0x61,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,
+ 0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,
+ 0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x65,0x74,0x50,
+ 0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x28,0x70,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x42,0x61,0x72,0x2c,0x20,0x32,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x73,
+ 0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,0x74,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x6d,0x61,0x6b,0x65,0x54,0x61,0x62,0x6c,0x65,0x2c,0x20,
+ 0x30,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x0d,0x0a,0x2f,0x2f,0x20,0x74,
+ 0x61,0x62,0x73,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x49,0x6e,0x69,0x74,
+ 0x69,0x61,0x6c,0x69,0x7a,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x74,0x61,0x62,0x20,
+ 0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x2e,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x66,
+ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6d,0x75,0x73,0x74,0x20,0x62,0x65,0x20,
+ 0x63,0x61,0x6c,0x6c,0x65,0x64,0x20,0x77,0x68,0x65,0x6e,0x20,0x74,0x68,0x65,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x20,0x69,0x73,0x0d,0x0a,0x6c,0x6f,0x61,
+ 0x64,0x65,0x64,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,
+ 0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,
+ 0x69,0x74,0x54,0x61,0x62,0x43,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x28,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x73,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x73,0x27,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x63,0x68,0x69,0x6c,0x64,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,
+ 0x61,0x62,0x4e,0x75,0x6d,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,
+ 0x72,0x20,0x28,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x74,0x61,
+ 0x62,0x73,0x2e,0x63,0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x2e,0x6c,0x65,
+ 0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x68,0x69,0x6c,0x64,0x20,0x3d,0x20,0x74,0x61,0x62,0x73,0x2e,0x63,
+ 0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x2e,0x69,0x74,0x65,0x6d,0x28,0x69,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x63,0x68,0x69,0x6c,
+ 0x64,0x2e,0x6e,0x6f,0x64,0x65,0x54,0x79,0x70,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x31,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x63,
+ 0x68,0x69,0x6c,0x64,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x21,
+ 0x3d,0x3d,0x20,0x27,0x64,0x69,0x73,0x61,0x62,0x6c,0x65,0x64,0x27,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x68,0x69,0x6c,0x64,0x2e,
+ 0x6f,0x6e,0x63,0x6c,0x69,0x63,0x6b,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x74,0x61,0x62,0x5f,0x63,0x6c,0x69,0x63,0x6b,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x74,0x61,0x62,0x4e,0x75,0x6d,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x73,0x65,0x6c,0x65,0x63,0x74,0x54,0x61,0x62,0x28,0x30,0x29,
+ 0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x53,0x65,0x6c,
+ 0x65,0x63,0x74,0x73,0x20,0x61,0x20,0x74,0x61,0x62,0x2e,0x0d,0x0a,0x40,0x70,0x61,
+ 0x72,0x61,0x6d,0x20,0x20,0x74,0x61,0x62,0x20,0x20,0x74,0x68,0x65,0x20,0x69,0x6e,
+ 0x74,0x65,0x67,0x65,0x72,0x20,0x69,0x6e,0x64,0x65,0x78,0x20,0x6f,0x66,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x28,0x30,0x2c,0x20,0x31,0x2c,0x20,0x32,0x2c,
+ 0x20,0x6f,0x72,0x20,0x33,0x29,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x4f,0x52,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x49,0x44,0x20,0x6f,0x66,0x20,
+ 0x74,0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x4f,0x52,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x20,0x69,
+ 0x74,0x73,0x65,0x6c,0x66,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,
+ 0x65,0x6c,0x65,0x63,0x74,0x54,0x61,0x62,0x28,0x74,0x61,0x62,0x29,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x79,0x70,0x65,0x6f,0x66,0x20,0x74,0x61,
+ 0x62,0x20,0x21,0x3d,0x3d,0x20,0x27,0x6e,0x75,0x6d,0x62,0x65,0x72,0x27,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x20,0x3d,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x74,0x61,0x62,0x49,0x6e,0x64,0x65,0x78,
+ 0x4f,0x66,0x28,0x74,0x61,0x62,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x73,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,
+ 0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x73,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,
+ 0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,0x6f,0x64,0x65,0x4c,
+ 0x69,0x73,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x4e,
+ 0x75,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x6e,0x6f,0x64,0x65,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x6e,0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x20,0x3d,0x20,0x74,0x61,0x62,0x73,0x2e,
+ 0x63,0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x3b,0x0d,0x0a,0x20,0x20,0x74,
+ 0x61,0x62,0x4e,0x75,0x6d,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,
+ 0x72,0x20,0x28,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x6e,0x6f,
+ 0x64,0x65,0x4c,0x69,0x73,0x74,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,
+ 0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,0x65,0x20,
+ 0x3d,0x20,0x6e,0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x2e,0x69,0x74,0x65,0x6d,0x28,
+ 0x69,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6e,0x6f,0x64,
+ 0x65,0x2e,0x6e,0x6f,0x64,0x65,0x54,0x79,0x70,0x65,0x20,0x21,0x3d,0x3d,0x20,0x31,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,0x74,0x69,
+ 0x6e,0x75,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6e,0x6f,0x64,0x65,0x2e,0x63,0x6c,0x61,0x73,
+ 0x73,0x4e,0x61,0x6d,0x65,0x20,0x21,0x3d,0x3d,0x20,0x27,0x64,0x69,0x73,0x61,0x62,
+ 0x6c,0x65,0x64,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,
+ 0x66,0x20,0x28,0x74,0x61,0x62,0x4e,0x75,0x6d,0x20,0x3d,0x3d,0x3d,0x20,0x74,0x61,
+ 0x62,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6e,0x6f,
+ 0x64,0x65,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,
+ 0x73,0x65,0x6c,0x65,0x63,0x74,0x65,0x64,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,0x65,0x2e,
+ 0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x4e,0x75,0x6d,0x2b,0x2b,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x6e,0x6f,0x64,0x65,0x4c,0x69,0x73,
+ 0x74,0x20,0x3d,0x20,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x2e,0x63,0x68,0x69,
+ 0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x61,0x62,0x4e,
+ 0x75,0x6d,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,
+ 0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x6e,0x6f,0x64,0x65,0x4c,
+ 0x69,0x73,0x74,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,0x65,0x20,0x3d,0x20,0x6e,
+ 0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x2e,0x69,0x74,0x65,0x6d,0x28,0x69,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6e,0x6f,0x64,0x65,0x2e,0x6e,
+ 0x6f,0x64,0x65,0x54,0x79,0x70,0x65,0x20,0x21,0x3d,0x3d,0x20,0x31,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x74,0x61,0x62,0x4e,0x75,0x6d,0x20,0x3d,0x3d,0x3d,0x20,0x74,
+ 0x61,0x62,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,
+ 0x65,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x73,
+ 0x65,0x6c,0x65,0x63,0x74,0x65,0x64,0x20,0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x27,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,
+ 0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,0x65,
+ 0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x54,0x61,
+ 0x62,0x50,0x61,0x67,0x65,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x4e,0x75,0x6d,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x52,0x65,
+ 0x74,0x75,0x72,0x6e,0x73,0x20,0x61,0x6e,0x20,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,
+ 0x20,0x28,0x30,0x2c,0x20,0x31,0x2c,0x20,0x32,0x2c,0x20,0x6f,0x72,0x20,0x33,0x29,
+ 0x20,0x72,0x65,0x70,0x72,0x65,0x73,0x65,0x6e,0x74,0x69,0x6e,0x67,0x20,0x74,0x68,
+ 0x65,0x20,0x69,0x6e,0x64,0x65,0x78,0x20,0x6f,0x66,0x20,0x61,0x20,0x67,0x69,0x76,
+ 0x65,0x6e,0x20,0x74,0x61,0x62,0x2e,0x0d,0x0a,0x40,0x70,0x61,0x72,0x61,0x6d,0x20,
+ 0x20,0x74,0x61,0x62,0x20,0x20,0x74,0x68,0x65,0x20,0x49,0x44,0x20,0x6f,0x66,0x20,
+ 0x74,0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x4f,0x52,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x20,0x69,
+ 0x74,0x73,0x65,0x6c,0x66,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x74,
+ 0x61,0x62,0x49,0x6e,0x64,0x65,0x78,0x4f,0x66,0x28,0x74,0x61,0x62,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x79,0x70,0x65,0x6f,0x66,0x20,0x74,
+ 0x61,0x62,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x73,0x74,0x72,0x69,0x6e,0x67,0x27,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x20,0x3d,0x20,0x64,0x6f,
+ 0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,
+ 0x74,0x42,0x79,0x49,0x64,0x28,0x74,0x61,0x62,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x73,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x73,0x27,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x63,0x68,0x69,0x6c,0x64,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,
+ 0x61,0x62,0x4e,0x75,0x6d,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,
+ 0x72,0x20,0x28,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x74,0x61,
+ 0x62,0x73,0x2e,0x63,0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x2e,0x6c,0x65,
+ 0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x68,0x69,0x6c,0x64,0x20,0x3d,0x20,0x74,0x61,0x62,0x73,0x2e,0x63,
+ 0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x2e,0x69,0x74,0x65,0x6d,0x28,0x69,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x63,0x68,0x69,0x6c,
+ 0x64,0x2e,0x6e,0x6f,0x64,0x65,0x54,0x79,0x70,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x31,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x63,
+ 0x68,0x69,0x6c,0x64,0x20,0x3d,0x3d,0x3d,0x20,0x74,0x61,0x62,0x29,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x74,0x61,0x62,0x4e,0x75,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x4e,0x75,0x6d,0x2b,0x2b,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x2f,
+ 0x2f,0x23,0x4a,0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x49,0x46,0x20,
+ 0x30,0x0d,0x0a,0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x22,0x54,0x61,0x62,0x20,
+ 0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x22,0x3b,0x0d,0x0a,0x2f,0x2f,0x23,
+ 0x4a,0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x45,0x4e,0x44,0x49,0x46,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x74,0x61,0x62,0x5f,0x63,
+ 0x6c,0x69,0x63,0x6b,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,
+ 0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x72,0x67,0x65,
+ 0x74,0x3b,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,
+ 0x45,0x5f,0x49,0x46,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x65,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x20,0x3d,0x20,0x65,
+ 0x2e,0x74,0x61,0x72,0x67,0x65,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,
+ 0x20,0x65,0x6c,0x73,0x65,0x20,0x69,0x66,0x20,0x28,0x77,0x69,0x6e,0x64,0x6f,0x77,
+ 0x2e,0x65,0x76,0x65,0x6e,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,
+ 0x2f,0x20,0x49,0x45,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x72,0x67,0x65,0x74,
+ 0x20,0x3d,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x65,0x76,0x65,0x6e,0x74,0x2e,
+ 0x73,0x72,0x63,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x63,
+ 0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x73,0x65,
+ 0x6c,0x65,0x63,0x74,0x65,0x64,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x65,0x67,0x69,0x6e,
+ 0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x73,0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,
+ 0x74,0x28,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x69,
+ 0x64,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,
+ 0x62,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x74,0x62,0x6f,0x64,0x79,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,
+ 0x28,0x22,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x62,0x6f,0x64,0x79,0x22,0x29,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x28,
+ 0x74,0x62,0x6f,0x64,0x79,0x2e,0x68,0x61,0x73,0x43,0x68,0x69,0x6c,0x64,0x4e,0x6f,
+ 0x64,0x65,0x73,0x28,0x29,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x74,0x62,0x6f,0x64,0x79,0x2e,0x72,0x65,0x6d,0x6f,0x76,0x65,0x43,0x68,
+ 0x69,0x6c,0x64,0x28,0x74,0x62,0x6f,0x64,0x79,0x2e,0x66,0x69,0x72,0x73,0x74,0x43,
+ 0x68,0x69,0x6c,0x64,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,
+ 0x20,0x69,0x66,0x20,0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x69,0x64,0x20,0x3d,
+ 0x3d,0x3d,0x20,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x27,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x6f,0x75,
+ 0x72,0x63,0x65,0x44,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,
+ 0x28,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x2e,
+ 0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x27,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x6c,0x65,0x63,0x74,0x54,0x61,0x62,
+ 0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,
+ 0x66,0x20,0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x69,0x64,0x20,0x3d,0x3d,0x3d,
+ 0x20,0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x27,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,0x75,
+ 0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x69,0x66,0x20,
+ 0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x69,0x64,0x20,0x3d,0x3d,0x3d,0x20,0x27,
+ 0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,0x6f,0x75,0x72,0x63,
+ 0x65,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,
+ 0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x2c,
+ 0x20,0x35,0x30,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x0d,0x0a,0x2f,0x2f,
+ 0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x20,0x62,0x61,0x72,0x0d,0x0a,0x0d,
+ 0x0a,0x76,0x61,0x72,0x20,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,
+ 0x20,0x3d,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x69,0x6e,0x69,0x74,0x3a,0x20,0x66,0x75,
+ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x5f,
+ 0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x20,0x3d,0x20,0x30,0x3b,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2a,0x20,0x64,0x6f,0x69,0x6e,0x67,0x20,
+ 0x74,0x68,0x69,0x73,0x20,0x76,0x69,0x61,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,
+ 0x69,0x70,0x74,0x20,0x63,0x72,0x61,0x73,0x68,0x65,0x73,0x20,0x53,0x61,0x66,0x61,
+ 0x72,0x69,0x20,0x2a,0x2f,0x0d,0x0a,0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x20,0x3d,0x20,0x64,0x6f,
+ 0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,
+ 0x6d,0x65,0x6e,0x74,0x28,0x27,0x64,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x2e,0x63,0x6c,0x61,0x73,0x73,
+ 0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,
+ 0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,
+ 0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x70,0x63,0x74,0x47,
+ 0x72,0x61,0x70,0x68,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x28,0x27,0x64,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x65,0x64,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,
+ 0x3d,0x20,0x27,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x27,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x2e,0x61,0x70,0x70,0x65,0x6e,
+ 0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x63,0x74,0x20,0x3d,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,
+ 0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x27,0x73,0x70,0x61,0x6e,0x27,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,
+ 0x6d,0x65,0x20,0x3d,0x20,0x27,0x70,0x63,0x74,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,
+ 0x68,0x69,0x6c,0x64,0x28,0x70,0x63,0x74,0x29,0x3b,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,
+ 0x72,0x2e,0x5f,0x75,0x70,0x64,0x61,0x74,0x65,0x28,0x65,0x6c,0x65,0x6d,0x65,0x6e,
+ 0x74,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x2c,0x0d,0x0a,0x20,0x20,0x73,0x65,0x74,
+ 0x50,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x3a,0x20,0x66,0x75,0x6e,0x63,
+ 0x74,0x69,0x6f,0x6e,0x28,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2c,0x20,0x70,0x65,
+ 0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x5f,0x70,0x65,0x72,0x63,0x65,0x6e,
+ 0x74,0x61,0x67,0x65,0x20,0x3d,0x20,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,
+ 0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x42,0x61,0x72,0x2e,0x5f,0x75,0x70,0x64,0x61,0x74,0x65,0x28,0x65,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x2c,0x0d,0x0a,0x20,0x20,0x5f,
+ 0x75,0x70,0x64,0x61,0x74,0x65,0x3a,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,
+ 0x28,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x20,0x3d,0x20,
+ 0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x27,0x64,0x69,
+ 0x76,0x27,0x29,0x2e,0x69,0x74,0x65,0x6d,0x28,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x20,0x3d,0x20,
+ 0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x27,0x64,
+ 0x69,0x76,0x27,0x29,0x2e,0x69,0x74,0x65,0x6d,0x28,0x30,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x63,0x74,0x20,0x3d,0x20,0x65,0x6c,0x65,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,
+ 0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x27,0x73,0x70,0x61,0x6e,0x27,
+ 0x29,0x2e,0x69,0x74,0x65,0x6d,0x28,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x70,0x63,0x74,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,
+ 0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x5f,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,
+ 0x61,0x67,0x65,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,0x28,0x29,0x20,0x2b,
+ 0x20,0x27,0x25,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x76,0x65,0x72,
+ 0x65,0x64,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x77,0x69,0x64,0x74,0x68,0x20,0x3d,
+ 0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x5f,0x70,0x65,0x72,0x63,0x65,0x6e,
+ 0x74,0x61,0x67,0x65,0x20,0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x7d,0x3b,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x0d,0x0a,0x2f,0x2f,0x20,0x72,0x65,
+ 0x70,0x6f,0x72,0x74,0x73,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x70,0x61,0x64,
+ 0x28,0x73,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x27,0x30,0x30,0x30,0x30,0x27,0x2e,0x73,0x75,0x62,0x73,0x74,0x72,0x28,0x73,0x2e,
+ 0x6c,0x65,0x6e,0x67,0x74,0x68,0x29,0x20,0x2b,0x20,0x73,0x3b,0x0d,0x0a,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x71,0x75,0x6f,0x74,0x65,0x28,0x73,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x22,0x27,0x20,
+ 0x2b,0x20,0x73,0x2e,0x72,0x65,0x70,0x6c,0x61,0x63,0x65,0x28,0x2f,0x5b,0x5c,0x75,
+ 0x30,0x30,0x30,0x30,0x2d,0x5c,0x75,0x30,0x30,0x31,0x66,0x22,0x5c,0x5c,0x5c,0x75,
+ 0x30,0x30,0x37,0x66,0x2d,0x5c,0x75,0x66,0x66,0x66,0x66,0x5d,0x2f,0x67,0x2c,0x20,
+ 0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x63,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x73,0x77,0x69,0x74,0x63,0x68,0x20,0x28,0x63,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x62,0x27,0x3a,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,
+ 0x5c,0x5c,0x62,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,
+ 0x27,0x5c,0x66,0x27,0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,
+ 0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x66,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x6e,0x27,0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x6e,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x72,0x27,0x3a,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,
+ 0x5c,0x72,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,
+ 0x5c,0x74,0x27,0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,
+ 0x72,0x6e,0x20,0x27,0x5c,0x5c,0x74,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,
+ 0x2f,0x20,0x49,0x45,0x20,0x64,0x6f,0x65,0x73,0x6e,0x27,0x74,0x20,0x73,0x75,0x70,
+ 0x70,0x6f,0x72,0x74,0x20,0x74,0x68,0x69,0x73,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,
+ 0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x76,0x27,
+ 0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x27,0x5c,0x5c,0x76,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2a,0x2f,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x22,0x27,0x3a,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x22,
+ 0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x5c,
+ 0x27,0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,
+ 0x20,0x27,0x5c,0x5c,0x5c,0x5c,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x64,0x65,
+ 0x66,0x61,0x75,0x6c,0x74,0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,
+ 0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x75,0x27,0x20,0x2b,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x70,0x61,0x64,0x28,0x63,0x2e,0x63,0x68,
+ 0x61,0x72,0x43,0x6f,0x64,0x65,0x41,0x74,0x28,0x30,0x29,0x2e,0x74,0x6f,0x53,0x74,
+ 0x72,0x69,0x6e,0x67,0x28,0x31,0x36,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x29,0x20,0x2b,0x20,0x27,0x22,0x27,0x3b,0x0d,0x0a,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x72,0x69,0x61,0x6c,0x69,
+ 0x7a,0x65,0x43,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x54,0x6f,0x4a,0x53,0x4f,0x4e,
+ 0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6a,0x73,0x6f,0x6e,
+ 0x20,0x3d,0x20,0x5b,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x76,
+ 0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x20,0x69,0x6e,0x20,0x5f,0x24,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x3d,0x20,0x5f,
+ 0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x66,0x69,0x6c,0x65,
+ 0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x61,0x72,0x72,0x61,
+ 0x79,0x20,0x3d,0x20,0x5b,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x66,0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,
+ 0x30,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3c,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,
+ 0x3b,0x20,0x6c,0x69,0x6e,0x65,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x6c,0x69,0x6e,0x65,0x5d,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x76,0x61,0x6c,0x75,0x65,0x20,
+ 0x3d,0x3d,0x3d,0x20,0x75,0x6e,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x20,0x7c,0x7c,
+ 0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x6c,0x75,
+ 0x65,0x20,0x3d,0x20,0x27,0x6e,0x75,0x6c,0x6c,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x61,0x72,0x72,0x61,
+ 0x79,0x2e,0x70,0x75,0x73,0x68,0x28,0x76,0x61,0x6c,0x75,0x65,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x6f,0x6e,0x2e,
+ 0x70,0x75,0x73,0x68,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x71,0x75,0x6f,0x74,0x65,0x28,0x66,0x69,0x6c,0x65,0x29,0x20,0x2b,0x20,0x27,0x3a,
+ 0x5b,0x27,0x20,0x2b,0x20,0x61,0x72,0x72,0x61,0x79,0x2e,0x6a,0x6f,0x69,0x6e,0x28,
+ 0x27,0x2c,0x27,0x29,0x20,0x2b,0x20,0x27,0x5d,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x7b,0x27,0x20,
+ 0x2b,0x20,0x6a,0x73,0x6f,0x6e,0x2e,0x6a,0x6f,0x69,0x6e,0x28,0x27,0x2c,0x27,0x29,
+ 0x20,0x2b,0x20,0x27,0x7d,0x27,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,
+ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x73,0x74,0x6f,0x72,0x65,0x42,0x75,0x74,0x74,0x6f,0x6e,0x5f,0x63,0x6c,
+ 0x69,0x63,0x6b,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,
+ 0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x29,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x62,0x65,0x67,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,
+ 0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,
+ 0x72,0x20,0x69,0x6d,0x67,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,
+ 0x27,0x73,0x74,0x6f,0x72,0x65,0x49,0x6d,0x67,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x69,0x6d,0x67,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x76,0x69,0x73,0x69,0x62,0x69,
+ 0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x76,0x69,0x73,0x69,0x62,0x6c,0x65,0x27,
+ 0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x72,0x65,0x71,0x75,0x65,
+ 0x73,0x74,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x63,0x72,0x65,0x61,0x74,0x65,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x6f,0x70,0x65,0x6e,
+ 0x28,0x27,0x50,0x4f,0x53,0x54,0x27,0x2c,0x20,0x27,0x2f,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x2d,0x73,0x74,0x6f,0x72,0x65,0x27,0x2c,0x20,0x74,0x72,
+ 0x75,0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,
+ 0x6f,0x6e,0x72,0x65,0x61,0x64,0x79,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6e,
+ 0x67,0x65,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x65,
+ 0x76,0x65,0x6e,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x72,0x65,0x61,0x64,0x79,0x53,0x74,
+ 0x61,0x74,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x34,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x72,0x65,0x71,0x75,0x65,
+ 0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x20,0x21,0x3d,0x3d,0x20,0x32,0x30,
+ 0x30,0x20,0x26,0x26,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,
+ 0x74,0x75,0x73,0x20,0x21,0x3d,0x3d,0x20,0x32,0x30,0x31,0x20,0x26,0x26,0x20,0x72,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x20,0x21,0x3d,
+ 0x3d,0x20,0x32,0x30,0x34,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x72,0x65,0x71,0x75,0x65,0x73,
+ 0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6d,0x65,
+ 0x73,0x73,0x61,0x67,0x65,0x20,0x3d,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,
+ 0x72,0x65,0x73,0x70,0x6f,0x6e,0x73,0x65,0x54,0x65,0x78,0x74,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x61,
+ 0x74,0x63,0x68,0x20,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x65,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,
+ 0x67,0x28,0x29,0x2e,0x73,0x65,0x61,0x72,0x63,0x68,0x28,0x2f,0x5e,0x5c,0x64,0x7b,
+ 0x33,0x7d,0x24,0x2f,0x29,0x20,0x3d,0x3d,0x3d,0x20,0x30,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,
+ 0x65,0x20,0x3d,0x20,0x65,0x20,0x2b,0x20,0x27,0x3a,0x20,0x27,0x20,0x2b,0x20,0x72,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x72,0x65,0x73,0x70,0x6f,0x6e,0x73,0x65,0x54,
+ 0x65,0x78,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6d,0x65,0x73,0x73,0x61,
+ 0x67,0x65,0x20,0x3d,0x20,0x27,0x43,0x6f,0x75,0x6c,0x64,0x20,0x6e,0x6f,0x74,0x20,
+ 0x63,0x6f,0x6e,0x6e,0x65,0x63,0x74,0x20,0x74,0x6f,0x20,0x73,0x65,0x72,0x76,0x65,
+ 0x72,0x3a,0x20,0x27,0x20,0x2b,0x20,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,
+ 0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x69,0x6d,0x67,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x73,0x74,0x6f,0x72,0x65,0x49,0x6d,0x67,0x27,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x6d,0x67,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,
+ 0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x68,0x69,
+ 0x64,0x64,0x65,0x6e,0x27,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x64,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x73,0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x64,0x69,0x76,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,
+ 0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,
+ 0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,0x6f,0x64,0x65,0x28,0x6e,0x65,
+ 0x77,0x20,0x44,0x61,0x74,0x65,0x28,0x29,0x20,0x2b,0x20,0x27,0x3a,0x20,0x27,0x20,
+ 0x2b,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x64,0x69,0x76,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,
+ 0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,
+ 0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x27,0x62,0x72,0x27,0x29,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x65,0x74,0x52,0x65,
+ 0x71,0x75,0x65,0x73,0x74,0x48,0x65,0x61,0x64,0x65,0x72,0x28,0x27,0x43,0x6f,0x6e,
+ 0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x27,0x2c,0x20,0x27,0x61,0x70,0x70,
+ 0x6c,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,0x6a,0x73,0x6f,0x6e,0x27,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6a,0x73,0x6f,0x6e,0x20,0x3d,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x72,0x69,0x61,0x6c,
+ 0x69,0x7a,0x65,0x43,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x54,0x6f,0x4a,0x53,0x4f,
+ 0x4e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,
+ 0x73,0x65,0x74,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x48,0x65,0x61,0x64,0x65,0x72,
+ 0x28,0x27,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,
+ 0x27,0x2c,0x20,0x6a,0x73,0x6f,0x6e,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x2e,0x74,
+ 0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,0x28,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x72,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x65,0x6e,0x64,0x28,0x6a,0x73,0x6f,0x6e,
+ 0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,
+};
+const unsigned char RESOURCE12_[] = {
+
+ 0x69,0x66,0x20,0x28,0x21,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x70,0x6f,0x72,0x74,0x29,0x20,
+ 0x7b,0x0a,0x20,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x70,0x6f,0x72,0x74,0x20,0x3d,0x20,0x66,
+ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x72,0x65,0x70,0x6f,0x72,0x74,0x28,0x64,0x69,0x72,0x29,0x20,0x7b,
+ 0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x72,0x65,0x61,0x74,0x65,0x52,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x58,0x4d,0x4c,0x48,0x74,0x74,0x70,0x52,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6e,0x65,0x77,0x20,0x58,0x4d,0x4c,
+ 0x48,0x74,0x74,0x70,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,
+ 0x65,0x20,0x69,0x66,0x20,0x28,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x41,0x63,0x74,
+ 0x69,0x76,0x65,0x58,0x4f,0x62,0x6a,0x65,0x63,0x74,0x29,0x20,0x7b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6e,0x65,0x77,
+ 0x20,0x41,0x63,0x74,0x69,0x76,0x65,0x58,0x4f,0x62,0x6a,0x65,0x63,0x74,0x28,0x22,
+ 0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x58,0x4d,0x4c,0x48,0x54,0x54,
+ 0x50,0x22,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,
+ 0x20,0x7d,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x61,0x64,
+ 0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x73,0x29,0x20,
+ 0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,
+ 0x30,0x30,0x30,0x30,0x27,0x2e,0x73,0x75,0x62,0x73,0x74,0x72,0x28,0x73,0x2e,0x6c,
+ 0x65,0x6e,0x67,0x74,0x68,0x29,0x20,0x2b,0x20,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x71,0x75,0x6f,0x74,
+ 0x65,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x73,0x29,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x27,0x22,0x27,0x20,0x2b,0x20,0x73,0x2e,0x72,0x65,0x70,0x6c,0x61,0x63,0x65,0x28,
+ 0x2f,0x5b,0x5c,0x75,0x30,0x30,0x30,0x30,0x2d,0x5c,0x75,0x30,0x30,0x31,0x66,0x22,
+ 0x5c,0x5c,0x5c,0x75,0x30,0x30,0x37,0x66,0x2d,0x5c,0x75,0x66,0x66,0x66,0x66,0x5d,
+ 0x2f,0x67,0x2c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x63,0x29,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x73,0x77,0x69,0x74,0x63,
+ 0x68,0x20,0x28,0x63,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x62,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x62,
+ 0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,
+ 0x27,0x5c,0x66,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x66,0x27,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x6e,0x27,0x3a,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,
+ 0x6e,0x20,0x27,0x5c,0x5c,0x6e,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x72,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,
+ 0x72,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,
+ 0x20,0x27,0x5c,0x74,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x74,0x27,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x49,0x45,0x20,0x64,0x6f,0x65,
+ 0x73,0x6e,0x27,0x74,0x20,0x73,0x75,0x70,0x70,0x6f,0x72,0x74,0x20,0x74,0x68,0x69,
+ 0x73,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x2f,0x2a,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x76,0x27,0x3a,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,
+ 0x20,0x27,0x5c,0x5c,0x76,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x2a,0x2f,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,
+ 0x27,0x22,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,
+ 0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x22,0x27,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x5c,0x27,0x3a,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,
+ 0x20,0x27,0x5c,0x5c,0x5c,0x5c,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x75,0x27,
+ 0x20,0x2b,0x20,0x70,0x61,0x64,0x28,0x63,0x2e,0x63,0x68,0x61,0x72,0x43,0x6f,0x64,
+ 0x65,0x41,0x74,0x28,0x30,0x29,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,0x28,
+ 0x31,0x36,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x29,0x20,0x2b,0x20,0x27,0x22,0x27,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x7d,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x6a,0x73,0x6f,0x6e,0x20,0x3d,0x20,0x5b,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
+ 0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x20,0x69,0x6e,0x20,
+ 0x74,0x6f,0x70,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x3d,0x20,0x74,0x6f,0x70,0x2e,0x5f,0x24,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x66,0x69,0x6c,0x65,0x5d,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x61,0x72,0x72,0x61,0x79,
+ 0x20,0x3d,0x20,0x5b,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x66,0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3d,
+ 0x20,0x30,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3c,0x20,0x6c,0x65,0x6e,0x67,0x74,
+ 0x68,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x2b,0x2b,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,
+ 0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x6c,0x69,0x6e,0x65,0x5d,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x76,0x61,0x6c,
+ 0x75,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x75,0x6e,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,
+ 0x20,0x7c,0x7c,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x6e,0x75,
+ 0x6c,0x6c,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x27,0x6e,0x75,0x6c,0x6c,0x27,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x61,0x72,0x72,0x61,0x79,0x2e,0x70,0x75,0x73,0x68,0x28,0x76,0x61,0x6c,
+ 0x75,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x6a,0x73,0x6f,0x6e,0x2e,0x70,0x75,0x73,0x68,0x28,0x71,0x75,0x6f,
+ 0x74,0x65,0x28,0x66,0x69,0x6c,0x65,0x29,0x20,0x2b,0x20,0x27,0x3a,0x5b,0x27,0x20,
+ 0x2b,0x20,0x61,0x72,0x72,0x61,0x79,0x2e,0x6a,0x6f,0x69,0x6e,0x28,0x27,0x2c,0x27,
+ 0x29,0x20,0x2b,0x20,0x27,0x5d,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,
+ 0x20,0x20,0x20,0x20,0x6a,0x73,0x6f,0x6e,0x20,0x3d,0x20,0x27,0x7b,0x27,0x20,0x2b,
+ 0x20,0x6a,0x73,0x6f,0x6e,0x2e,0x6a,0x6f,0x69,0x6e,0x28,0x27,0x2c,0x27,0x29,0x20,
+ 0x2b,0x20,0x27,0x7d,0x27,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x20,0x3d,0x20,0x63,0x72,0x65,0x61,0x74,0x65,
+ 0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x75,0x72,0x6c,0x20,0x3d,0x20,0x27,0x2f,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x2d,0x73,0x74,0x6f,0x72,0x65,0x27,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x64,0x69,0x72,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x75,0x72,0x6c,0x20,0x2b,0x3d,0x20,0x27,0x2f,0x27,0x20,0x2b,0x20,
+ 0x65,0x6e,0x63,0x6f,0x64,0x65,0x55,0x52,0x49,0x43,0x6f,0x6d,0x70,0x6f,0x6e,0x65,
+ 0x6e,0x74,0x28,0x64,0x69,0x72,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,
+ 0x20,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x6f,0x70,0x65,0x6e,0x28,
+ 0x27,0x50,0x4f,0x53,0x54,0x27,0x2c,0x20,0x75,0x72,0x6c,0x2c,0x20,0x66,0x61,0x6c,
+ 0x73,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,
+ 0x2e,0x73,0x65,0x74,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x48,0x65,0x61,0x64,0x65,
+ 0x72,0x28,0x27,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x27,
+ 0x2c,0x20,0x27,0x61,0x70,0x70,0x6c,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,0x6a,
+ 0x73,0x6f,0x6e,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x71,0x75,0x65,
+ 0x73,0x74,0x2e,0x73,0x65,0x74,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x48,0x65,0x61,
+ 0x64,0x65,0x72,0x28,0x27,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,
+ 0x67,0x74,0x68,0x27,0x2c,0x20,0x6a,0x73,0x6f,0x6e,0x2e,0x6c,0x65,0x6e,0x67,0x74,
+ 0x68,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,0x28,0x29,0x29,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x65,0x6e,0x64,0x28,
+ 0x6a,0x73,0x6f,0x6e,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x72,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x20,0x3d,0x3d,
+ 0x3d,0x20,0x32,0x30,0x30,0x20,0x7c,0x7c,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,
+ 0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x20,0x3d,0x3d,0x3d,0x20,0x32,0x30,0x31,0x20,
+ 0x7c,0x7c,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,
+ 0x73,0x20,0x3d,0x3d,0x3d,0x20,0x32,0x30,0x34,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x72,0x65,0x71,0x75,0x65,0x73,
+ 0x74,0x2e,0x72,0x65,0x73,0x70,0x6f,0x6e,0x73,0x65,0x54,0x65,0x78,0x74,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x72,0x65,0x71,
+ 0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x7d,0x0a,0x20,0x20,0x7d,0x3b,0x0a,0x7d,0x0a,
+};
+const unsigned char RESOURCE13_[] = {
+
+ 0x47,0x49,0x46,0x38,0x39,0x61,0x07,0x00,0x07,0x00,0xe3,0x0b,0x00,0x00,0x00,0x00,
+ 0x05,0x05,0x05,0x20,0x20,0x20,0x3e,0x3e,0x3e,0x40,0x40,0x40,0x60,0x60,0x60,0x7d,
+ 0x7d,0x7d,0x80,0x80,0x80,0xa0,0xa0,0xa0,0xc0,0xc0,0xc0,0xe0,0xe0,0xe0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x21,0xff,0x0b,
+ 0x4e,0x45,0x54,0x53,0x43,0x41,0x50,0x45,0x32,0x2e,0x30,0x03,0x01,0x00,0x00,0x00,
+ 0x21,0xf9,0x04,0x01,0x0a,0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+ 0x00,0x00,0x04,0x16,0xf0,0x49,0x20,0xa5,0x78,0x54,0xd5,0xab,0x1f,0x21,0x55,0x92,
+ 0x48,0xc5,0x83,0x54,0xe5,0x61,0x56,0x8f,0x2a,0x45,0x00,0x21,0xf9,0x04,0x01,0x0a,
+ 0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x04,0x16,0xf0,
+ 0x49,0x21,0x25,0x79,0x14,0xd4,0xab,0x5f,0x29,0x95,0xa2,0x48,0xc7,0x93,0x54,0x25,
+ 0x62,0x56,0x8f,0x2a,0x45,0x00,0x21,0xf9,0x04,0x01,0x0a,0x00,0x0f,0x00,0x2c,0x00,
+ 0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x04,0x16,0xf0,0x49,0x22,0x65,0x79,0x54,
+ 0xd4,0xab,0xdf,0x39,0x15,0x00,0x48,0xc8,0xa3,0x54,0x65,0x62,0x56,0x8f,0x2a,0x45,
+ 0x00,0x21,0xf9,0x04,0x01,0x0a,0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,0x00,
+ 0x07,0x00,0x00,0x04,0x16,0xf0,0xc9,0x22,0xe5,0x79,0x94,0xd4,0xab,0x1f,0x42,0x95,
+ 0x20,0x48,0xc9,0x03,0x54,0xa5,0x62,0x56,0x8f,0x2a,0x45,0x00,0x21,0xf9,0x04,0x01,
+ 0x0a,0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x04,0x16,
+ 0xf0,0xc9,0x23,0x25,0x7a,0xb4,0xd4,0xab,0x5f,0x4a,0x15,0x41,0x48,0xca,0x23,0x54,
+ 0x25,0x60,0x56,0x8f,0x2a,0x45,0x00,0x21,0xf9,0x04,0x01,0x0a,0x00,0x0f,0x00,0x2c,
+ 0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x04,0x16,0xf0,0x49,0x24,0x65,0x7a,
+ 0xf4,0xd4,0xab,0x9f,0x52,0x55,0x51,0x48,0xc0,0x43,0x54,0xa5,0x60,0x56,0x8f,0x2a,
+ 0x45,0x00,0x21,0xf9,0x04,0x01,0x0a,0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,
+ 0x00,0x07,0x00,0x00,0x04,0x16,0xf0,0xc9,0x24,0xa5,0x7a,0x14,0xd5,0xab,0x1f,0x00,
+ 0xd5,0x71,0x48,0xc2,0x53,0x54,0x25,0x61,0x56,0x8f,0x2a,0x45,0x00,0x21,0xf9,0x04,
+ 0x01,0x0a,0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x04,
+ 0x16,0xf0,0x49,0x25,0x25,0x78,0x34,0xd5,0xab,0x9f,0x10,0x15,0x82,0x48,0xc4,0x73,
+ 0x54,0x65,0x61,0x56,0x8f,0x2a,0x45,0x00,0x3b,
+};
+const struct Resource RESOURCES[] = {
+ {
+ "jscoverage-help.txt",
+ RESOURCE1_,
+ sizeof(RESOURCE1_)
+ },
+ {
+ "jscoverage-server-help.txt",
+ RESOURCE2_,
+ sizeof(RESOURCE2_)
+ },
+ {
+ "jscoverage.jsm",
+ RESOURCE3_,
+ sizeof(RESOURCE3_)
+ },
+ {
+ "jscoverage.manifest",
+ RESOURCE4_,
+ sizeof(RESOURCE4_)
+ },
+ {
+ "jscoverage.xul",
+ RESOURCE5_,
+ sizeof(RESOURCE5_)
+ },
+ {
+ "jscoverage-overlay.js",
+ RESOURCE6_,
+ sizeof(RESOURCE6_)
+ },
+ {
+ "jscoverage.html",
+ RESOURCE7_,
+ sizeof(RESOURCE7_)
+ },
+ {
+ "jscoverage.css",
+ RESOURCE8_,
+ sizeof(RESOURCE8_)
+ },
+ {
+ "jscoverage-ie.css",
+ RESOURCE9_,
+ sizeof(RESOURCE9_)
+ },
+ {
+ "jscoverage-highlight.css",
+ RESOURCE10_,
+ sizeof(RESOURCE10_)
+ },
+ {
+ "jscoverage.js",
+ RESOURCE11_,
+ sizeof(RESOURCE11_)
+ },
+ {
+ "report.js",
+ RESOURCE12_,
+ sizeof(RESOURCE12_)
+ },
+ {
+ "jscoverage-throbber.gif",
+ RESOURCE13_,
+ sizeof(RESOURCE13_)
+ },
+};
diff --git a/tools/node_modules/expresso/deps/jscoverage/stamp-h1 b/tools/node_modules/expresso/deps/jscoverage/stamp-h1
new file mode 100644
index 0000000..4547fe1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/stamp-h1
@@ -0,0 +1 @@
+timestamp for config.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/stream.c b/tools/node_modules/expresso/deps/jscoverage/stream.c
new file mode 100644
index 0000000..cc6adc0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/stream.c
@@ -0,0 +1,129 @@
+/*
+ stream.c - `Stream' object
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#define _GNU_SOURCE
+
+#include <config.h>
+
+#include "stream.h"
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "util.h"
+
+Stream * Stream_new(size_t capacity) {
+ Stream * result = xmalloc(sizeof(Stream));
+ result->length = 0;
+ if (capacity == 0) {
+ capacity = 8192;
+ }
+ result->capacity = capacity;
+ result->data = xmalloc(capacity);
+ return result;
+}
+
+void Stream_write(Stream * stream, const void * p, size_t size) {
+ size_t stream_length = stream->length;
+ size_t stream_capacity = stream->capacity;
+ if (stream_capacity - stream_length < size) {
+ if (SIZE_MAX - size < stream_length) {
+ fatal("out of memory");
+ }
+
+ if (SIZE_MAX / 2 < stream_capacity) {
+ stream_capacity = SIZE_MAX;
+ }
+ else {
+ stream_capacity *= 2;
+ }
+
+ size_t new_length = stream_length + size;
+ if (stream_capacity < new_length) {
+ stream_capacity = new_length;
+ }
+
+ stream->data = xrealloc(stream->data, stream_capacity);
+ stream->capacity = stream_capacity;
+ memcpy(stream->data + stream_length, p, size);
+ stream->length = new_length;
+ }
+ else {
+ memcpy(stream->data + stream_length, p, size);
+ stream->length = stream_length + size;
+ }
+}
+
+void Stream_write_string(Stream * stream, const char * s) {
+ Stream_write(stream, s, strlen(s));
+}
+
+void Stream_write_char(Stream * stream, char c) {
+ size_t stream_length = stream->length;
+ if (stream_length == stream->capacity) {
+ if (stream->capacity == SIZE_MAX) {
+ fatal("out of memory");
+ }
+
+ if (SIZE_MAX / 2 < stream->capacity) {
+ stream->capacity = SIZE_MAX;
+ }
+ else {
+ stream->capacity *= 2;
+ }
+
+ stream->data = xrealloc(stream->data, stream->capacity);
+ }
+ stream->data[stream_length] = c;
+ stream->length = stream_length + 1;
+}
+
+void Stream_printf(Stream * stream, const char * format, ...) {
+ va_list a;
+ va_start(a, format);
+
+ char * s = NULL;
+ /* note that size does not include the NUL character */
+ int size = vasprintf(&s, format, a);
+ if (size < 0) {
+ fatal("out of memory");
+ }
+ Stream_write(stream, s, size);
+ free(s);
+
+ va_end(a);
+}
+
+void Stream_write_file_contents(Stream * stream, FILE * f) {
+ char buffer[8192];
+ size_t bytes_read;
+ while ((bytes_read = fread(buffer, 1, 8192, f)) > 0) {
+ Stream_write(stream, buffer, bytes_read);
+ }
+}
+
+void Stream_delete(Stream * stream) {
+ free(stream->data);
+ free(stream);
+}
+
+void Stream_reset(Stream * stream) {
+ stream->length = 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/stream.h b/tools/node_modules/expresso/deps/jscoverage/stream.h
new file mode 100644
index 0000000..41c376f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/stream.h
@@ -0,0 +1,57 @@
+/*
+ stream.h - `Stream' object
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef STREAM_H_
+#define STREAM_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct Stream {
+ uint8_t * data;
+ size_t length;
+ size_t capacity;
+} Stream;
+
+Stream * Stream_new(size_t capacity);
+
+void Stream_write(Stream * stream, const void * p, size_t size);
+
+void Stream_write_string(Stream * stream, const char * s);
+
+void Stream_write_char(Stream * stream, char c);
+
+void Stream_printf(Stream * stream, const char * format, ...) __attribute__((format(printf, 2, 3)));
+
+void Stream_write_file_contents(Stream * stream, FILE * f);
+
+void Stream_reset(Stream * stream);
+
+void Stream_delete(Stream * stream);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STREAM_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/asprintf.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/asprintf.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/asprintf.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encoding.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encoding.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encoding.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encodings.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encodings.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encodings.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/gethostbyname.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/gethostbyname.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/gethostbyname.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/highlight.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/highlight.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/highlight.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-body.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-body.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-body.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-url.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-url.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-url.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-close-after-request.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-close-after-request.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-close-after-request.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-host.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-host.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-host.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-body.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-body.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-body.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-headers.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-headers.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-headers.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-charset.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-charset.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-charset.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-chunked.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-chunked.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-chunked.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-close-immediately.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-close-immediately.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-close-immediately.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-url.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-url.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-url.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/instrument-js.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/instrument-js.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/instrument-js.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/json.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/json.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/json.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/mkdirs.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/mkdirs.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/mkdirs.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/recursive-dir-list.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/recursive-dir-list.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/recursive-dir-list.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/resource-manager.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/resource-manager.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/resource-manager.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/stream.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/stream.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/stream.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/streams.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/streams.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/streams.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/util.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/util.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/util.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/Makefile b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile
new file mode 100644
index 0000000..9f6d1fc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile
@@ -0,0 +1,846 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# tests/Makefile. Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+# Makefile.am - build tests
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+pkgdatadir = $(datadir)/jscoverage
+pkglibdir = $(libdir)/jscoverage
+pkgincludedir = $(includedir)/jscoverage
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-unknown-linux-gnu
+host_triplet = x86_64-unknown-linux-gnu
+noinst_PROGRAMS = asprintf$(EXEEXT) encodings$(EXEEXT) \
+ gethostbyname$(EXEEXT) http-client-bad-body$(EXEEXT) \
+ http-client-bad-url$(EXEEXT) \
+ http-client-close-after-request$(EXEEXT) \
+ http-server-bad-body$(EXEEXT) http-server-bad-headers$(EXEEXT) \
+ http-server-charset$(EXEEXT) http-server-chunked$(EXEEXT) \
+ http-server-close-immediately$(EXEEXT) json$(EXEEXT) \
+ mkdirs$(EXEEXT) recursive-dir-list$(EXEEXT) streams$(EXEEXT)
+subdir = tests
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_asprintf_OBJECTS = asprintf.$(OBJEXT) util.$(OBJEXT)
+asprintf_OBJECTS = $(am_asprintf_OBJECTS)
+asprintf_LDADD = $(LDADD)
+am_encodings_OBJECTS = encodings.$(OBJEXT) encoding.$(OBJEXT) \
+ util.$(OBJEXT)
+encodings_OBJECTS = $(am_encodings_OBJECTS)
+encodings_DEPENDENCIES =
+am_gethostbyname_OBJECTS = gethostbyname.$(OBJEXT) http-host.$(OBJEXT) \
+ util.$(OBJEXT)
+gethostbyname_OBJECTS = $(am_gethostbyname_OBJECTS)
+gethostbyname_DEPENDENCIES =
+am_http_client_bad_body_OBJECTS = http-client-bad-body.$(OBJEXT) \
+ http-url.$(OBJEXT) util.$(OBJEXT)
+http_client_bad_body_OBJECTS = $(am_http_client_bad_body_OBJECTS)
+http_client_bad_body_DEPENDENCIES =
+am_http_client_bad_url_OBJECTS = http-client-bad-url.$(OBJEXT) \
+ util.$(OBJEXT)
+http_client_bad_url_OBJECTS = $(am_http_client_bad_url_OBJECTS)
+http_client_bad_url_DEPENDENCIES =
+http_client_close_after_request_SOURCES = \
+ http-client-close-after-request.c
+http_client_close_after_request_OBJECTS = \
+ http-client-close-after-request.$(OBJEXT)
+http_client_close_after_request_DEPENDENCIES =
+http_server_bad_body_SOURCES = http-server-bad-body.c
+http_server_bad_body_OBJECTS = http-server-bad-body.$(OBJEXT)
+http_server_bad_body_DEPENDENCIES =
+http_server_bad_headers_SOURCES = http-server-bad-headers.c
+http_server_bad_headers_OBJECTS = http-server-bad-headers.$(OBJEXT)
+http_server_bad_headers_DEPENDENCIES =
+am_http_server_charset_OBJECTS = http-server-charset.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT)
+http_server_charset_OBJECTS = $(am_http_server_charset_OBJECTS)
+http_server_charset_DEPENDENCIES =
+am_http_server_chunked_OBJECTS = http-server-chunked.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT)
+http_server_chunked_OBJECTS = $(am_http_server_chunked_OBJECTS)
+http_server_chunked_DEPENDENCIES =
+http_server_close_immediately_SOURCES = \
+ http-server-close-immediately.c
+http_server_close_immediately_OBJECTS = \
+ http-server-close-immediately.$(OBJEXT)
+http_server_close_immediately_DEPENDENCIES =
+am_json_OBJECTS = json.$(OBJEXT) encoding.$(OBJEXT) \
+ highlight.$(OBJEXT) instrument-js.$(OBJEXT) \
+ resource-manager.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT)
+json_OBJECTS = $(am_json_OBJECTS)
+json_DEPENDENCIES = ../js/obj/libjs.a
+am_mkdirs_OBJECTS = mkdirs.$(OBJEXT) util.$(OBJEXT)
+mkdirs_OBJECTS = $(am_mkdirs_OBJECTS)
+mkdirs_LDADD = $(LDADD)
+am_recursive_dir_list_OBJECTS = recursive-dir-list.$(OBJEXT) \
+ util.$(OBJEXT)
+recursive_dir_list_OBJECTS = $(am_recursive_dir_list_OBJECTS)
+recursive_dir_list_LDADD = $(LDADD)
+am_streams_OBJECTS = streams.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT)
+streams_OBJECTS = $(am_streams_OBJECTS)
+streams_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(asprintf_SOURCES) $(encodings_SOURCES) \
+ $(gethostbyname_SOURCES) $(http_client_bad_body_SOURCES) \
+ $(http_client_bad_url_SOURCES) \
+ http-client-close-after-request.c http-server-bad-body.c \
+ http-server-bad-headers.c $(http_server_charset_SOURCES) \
+ $(http_server_chunked_SOURCES) http-server-close-immediately.c \
+ $(json_SOURCES) $(mkdirs_SOURCES) \
+ $(recursive_dir_list_SOURCES) $(streams_SOURCES)
+DIST_SOURCES = $(asprintf_SOURCES) $(encodings_SOURCES) \
+ $(gethostbyname_SOURCES) $(http_client_bad_body_SOURCES) \
+ $(http_client_bad_url_SOURCES) \
+ http-client-close-after-request.c http-server-bad-body.c \
+ http-server-bad-headers.c $(http_server_charset_SOURCES) \
+ $(http_server_chunked_SOURCES) http-server-close-immediately.c \
+ $(json_SOURCES) $(mkdirs_SOURCES) \
+ $(recursive_dir_list_SOURCES) $(streams_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run aclocal-1.10
+AMTAR = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run tar
+AUTOCONF = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoconf
+AUTOHEADER = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoheader
+AUTOMAKE = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run automake-1.10
+AWK = gawk
+CC = gcc -std=gnu99
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -std=gnu99 -E
+CPPFLAGS =
+CXX = g++
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = /bin/grep -E
+EXEEXT =
+EXTRA_SOCKET_LIBS =
+EXTRA_THREAD_LIBS = -lpthread
+EXTRA_TIMER_LIBS =
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS =
+LIBICONV =
+LIBOBJS =
+LIBS =
+LTLIBICONV =
+LTLIBOBJS =
+MAKEINFO = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJEXT = o
+PACKAGE = jscoverage
+PACKAGE_BUGREPORT =
+PACKAGE_NAME = jscoverage
+PACKAGE_STRING = jscoverage 0.4
+PACKAGE_TARNAME = jscoverage
+PACKAGE_VERSION = 0.4
+PATH_SEPARATOR = :
+SET_MAKE =
+SHELL = /bin/sh
+STRIP =
+VERSION = 0.4
+XP_DEF = -DXP_UNIX
+abs_builddir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/tests
+abs_srcdir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/tests
+abs_top_builddir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+abs_top_srcdir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-unknown-linux-gnu
+build_alias =
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = unknown
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-unknown-linux-gnu
+host_alias =
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = unknown
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = $(SHELL) /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = /bin/mkdir -p
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias =
+top_builddir = ..
+top_srcdir = ..
+AM_CFLAGS = -DXP_UNIX -I../js -I../js/obj
+AM_CXXFLAGS = -DXP_UNIX -I../js -I../js/obj
+asprintf_SOURCES = asprintf.c ../util.c
+encodings_SOURCES = encodings.c ../encoding.c ../util.c
+encodings_LDADD =
+gethostbyname_SOURCES = gethostbyname.c ../http-host.c ../util.c
+gethostbyname_LDADD =
+http_client_bad_body_SOURCES = http-client-bad-body.c ../http-url.c ../util.c
+http_client_bad_body_LDADD =
+http_client_bad_url_SOURCES = http-client-bad-url.c ../util.c
+http_client_bad_url_LDADD =
+http_client_close_after_request_LDADD =
+http_server_bad_body_LDADD =
+http_server_bad_headers_LDADD =
+http_server_charset_SOURCES = http-server-charset.c ../stream.c ../util.c
+http_server_charset_LDADD =
+http_server_chunked_SOURCES = http-server-chunked.c ../stream.c ../util.c
+http_server_chunked_LDADD =
+http_server_close_immediately_LDADD =
+json_SOURCES = json.c ../encoding.c ../highlight.c ../instrument-js.cpp ../resource-manager.c ../stream.c ../util.c
+json_LDADD = ../js/obj/libjs.a -lm
+mkdirs_SOURCES = mkdirs.c ../util.c
+recursive_dir_list_SOURCES = recursive-dir-list.c ../util.c
+streams_SOURCES = streams.c ../stream.c ../util.c
+TESTS = encodings.sh \
+ fatal.sh \
+ help.sh \
+ invalid-option.sh \
+ javascript.sh \
+ javascript-ignore.sh \
+ javascript-utf-8.sh \
+ no-arguments.sh \
+ recursive.sh \
+ recursive-crlf.sh \
+ recursive-exclude.sh \
+ recursive-fatal.sh \
+ recursive-no-instrument.sh \
+ same-directory.sh \
+ version.sh \
+ asprintf.sh \
+ mkdirs.sh \
+ recursive-dir-list.sh \
+ streams.sh \
+ charset.sh \
+ chunked.sh \
+ gethostbyname.sh \
+ json.sh \
+ proxy.sh \
+ proxy-bad-request-body.sh \
+ proxy-bad-response-body.sh \
+ proxy-bad-response-body-javascript.sh \
+ proxy-bad-response-headers.sh \
+ proxy-no-server.sh \
+ proxy-url.sh \
+ server.sh \
+ server-bad-requests.sh \
+ server-close-after-request.sh \
+ server-content-types.sh \
+ server-directory-listing.sh \
+ server-directory-redirect.sh \
+ server-encoded-url.sh \
+ server-error.sh \
+ server-help.sh \
+ server-ip-address.sh \
+ server-shutdown.sh \
+ server-shutdown-bad-method.sh \
+ server-special-file.sh \
+ server-unreadable-directory.sh \
+ server-unreadable-file.sh \
+ server-verbose.sh \
+ server-version.sh \
+ store.sh \
+ store-bad-json.sh \
+ store-bad-request-body.sh \
+ store-bad-response-headers.sh \
+ store-escaped-characters.sh \
+ store-server-bad-body.sh \
+ store-server-closes-immediately.sh \
+ store-source-not-found.sh \
+ store-unreadable-json.sh \
+ store-unwritable-json.sh
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+asprintf$(EXEEXT): $(asprintf_OBJECTS) $(asprintf_DEPENDENCIES)
+ @rm -f asprintf$(EXEEXT)
+ $(LINK) $(asprintf_OBJECTS) $(asprintf_LDADD) $(LIBS)
+encodings$(EXEEXT): $(encodings_OBJECTS) $(encodings_DEPENDENCIES)
+ @rm -f encodings$(EXEEXT)
+ $(LINK) $(encodings_OBJECTS) $(encodings_LDADD) $(LIBS)
+gethostbyname$(EXEEXT): $(gethostbyname_OBJECTS) $(gethostbyname_DEPENDENCIES)
+ @rm -f gethostbyname$(EXEEXT)
+ $(LINK) $(gethostbyname_OBJECTS) $(gethostbyname_LDADD) $(LIBS)
+http-client-bad-body$(EXEEXT): $(http_client_bad_body_OBJECTS) $(http_client_bad_body_DEPENDENCIES)
+ @rm -f http-client-bad-body$(EXEEXT)
+ $(LINK) $(http_client_bad_body_OBJECTS) $(http_client_bad_body_LDADD) $(LIBS)
+http-client-bad-url$(EXEEXT): $(http_client_bad_url_OBJECTS) $(http_client_bad_url_DEPENDENCIES)
+ @rm -f http-client-bad-url$(EXEEXT)
+ $(LINK) $(http_client_bad_url_OBJECTS) $(http_client_bad_url_LDADD) $(LIBS)
+http-client-close-after-request$(EXEEXT): $(http_client_close_after_request_OBJECTS) $(http_client_close_after_request_DEPENDENCIES)
+ @rm -f http-client-close-after-request$(EXEEXT)
+ $(LINK) $(http_client_close_after_request_OBJECTS) $(http_client_close_after_request_LDADD) $(LIBS)
+http-server-bad-body$(EXEEXT): $(http_server_bad_body_OBJECTS) $(http_server_bad_body_DEPENDENCIES)
+ @rm -f http-server-bad-body$(EXEEXT)
+ $(LINK) $(http_server_bad_body_OBJECTS) $(http_server_bad_body_LDADD) $(LIBS)
+http-server-bad-headers$(EXEEXT): $(http_server_bad_headers_OBJECTS) $(http_server_bad_headers_DEPENDENCIES)
+ @rm -f http-server-bad-headers$(EXEEXT)
+ $(LINK) $(http_server_bad_headers_OBJECTS) $(http_server_bad_headers_LDADD) $(LIBS)
+http-server-charset$(EXEEXT): $(http_server_charset_OBJECTS) $(http_server_charset_DEPENDENCIES)
+ @rm -f http-server-charset$(EXEEXT)
+ $(LINK) $(http_server_charset_OBJECTS) $(http_server_charset_LDADD) $(LIBS)
+http-server-chunked$(EXEEXT): $(http_server_chunked_OBJECTS) $(http_server_chunked_DEPENDENCIES)
+ @rm -f http-server-chunked$(EXEEXT)
+ $(LINK) $(http_server_chunked_OBJECTS) $(http_server_chunked_LDADD) $(LIBS)
+http-server-close-immediately$(EXEEXT): $(http_server_close_immediately_OBJECTS) $(http_server_close_immediately_DEPENDENCIES)
+ @rm -f http-server-close-immediately$(EXEEXT)
+ $(LINK) $(http_server_close_immediately_OBJECTS) $(http_server_close_immediately_LDADD) $(LIBS)
+json$(EXEEXT): $(json_OBJECTS) $(json_DEPENDENCIES)
+ @rm -f json$(EXEEXT)
+ $(CXXLINK) $(json_OBJECTS) $(json_LDADD) $(LIBS)
+mkdirs$(EXEEXT): $(mkdirs_OBJECTS) $(mkdirs_DEPENDENCIES)
+ @rm -f mkdirs$(EXEEXT)
+ $(LINK) $(mkdirs_OBJECTS) $(mkdirs_LDADD) $(LIBS)
+recursive-dir-list$(EXEEXT): $(recursive_dir_list_OBJECTS) $(recursive_dir_list_DEPENDENCIES)
+ @rm -f recursive-dir-list$(EXEEXT)
+ $(LINK) $(recursive_dir_list_OBJECTS) $(recursive_dir_list_LDADD) $(LIBS)
+streams$(EXEEXT): $(streams_OBJECTS) $(streams_DEPENDENCIES)
+ @rm -f streams$(EXEEXT)
+ $(LINK) $(streams_OBJECTS) $(streams_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+include ./$(DEPDIR)/asprintf.Po
+include ./$(DEPDIR)/encoding.Po
+include ./$(DEPDIR)/encodings.Po
+include ./$(DEPDIR)/gethostbyname.Po
+include ./$(DEPDIR)/highlight.Po
+include ./$(DEPDIR)/http-client-bad-body.Po
+include ./$(DEPDIR)/http-client-bad-url.Po
+include ./$(DEPDIR)/http-client-close-after-request.Po
+include ./$(DEPDIR)/http-host.Po
+include ./$(DEPDIR)/http-server-bad-body.Po
+include ./$(DEPDIR)/http-server-bad-headers.Po
+include ./$(DEPDIR)/http-server-charset.Po
+include ./$(DEPDIR)/http-server-chunked.Po
+include ./$(DEPDIR)/http-server-close-immediately.Po
+include ./$(DEPDIR)/http-url.Po
+include ./$(DEPDIR)/instrument-js.Po
+include ./$(DEPDIR)/json.Po
+include ./$(DEPDIR)/mkdirs.Po
+include ./$(DEPDIR)/recursive-dir-list.Po
+include ./$(DEPDIR)/resource-manager.Po
+include ./$(DEPDIR)/stream.Po
+include ./$(DEPDIR)/streams.Po
+include ./$(DEPDIR)/util.Po
+
+.c.o:
+ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+util.o: ../util.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT util.o -MD -MP -MF $(DEPDIR)/util.Tpo -c -o util.o `test -f '../util.c' || echo '$(srcdir)/'`../util.c
+ mv -f $(DEPDIR)/util.Tpo $(DEPDIR)/util.Po
+# source='../util.c' object='util.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o util.o `test -f '../util.c' || echo '$(srcdir)/'`../util.c
+
+util.obj: ../util.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT util.obj -MD -MP -MF $(DEPDIR)/util.Tpo -c -o util.obj `if test -f '../util.c'; then $(CYGPATH_W) '../util.c'; else $(CYGPATH_W) '$(srcdir)/../util.c'; fi`
+ mv -f $(DEPDIR)/util.Tpo $(DEPDIR)/util.Po
+# source='../util.c' object='util.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o util.obj `if test -f '../util.c'; then $(CYGPATH_W) '../util.c'; else $(CYGPATH_W) '$(srcdir)/../util.c'; fi`
+
+encoding.o: ../encoding.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encoding.o -MD -MP -MF $(DEPDIR)/encoding.Tpo -c -o encoding.o `test -f '../encoding.c' || echo '$(srcdir)/'`../encoding.c
+ mv -f $(DEPDIR)/encoding.Tpo $(DEPDIR)/encoding.Po
+# source='../encoding.c' object='encoding.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encoding.o `test -f '../encoding.c' || echo '$(srcdir)/'`../encoding.c
+
+encoding.obj: ../encoding.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encoding.obj -MD -MP -MF $(DEPDIR)/encoding.Tpo -c -o encoding.obj `if test -f '../encoding.c'; then $(CYGPATH_W) '../encoding.c'; else $(CYGPATH_W) '$(srcdir)/../encoding.c'; fi`
+ mv -f $(DEPDIR)/encoding.Tpo $(DEPDIR)/encoding.Po
+# source='../encoding.c' object='encoding.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encoding.obj `if test -f '../encoding.c'; then $(CYGPATH_W) '../encoding.c'; else $(CYGPATH_W) '$(srcdir)/../encoding.c'; fi`
+
+http-host.o: ../http-host.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-host.o -MD -MP -MF $(DEPDIR)/http-host.Tpo -c -o http-host.o `test -f '../http-host.c' || echo '$(srcdir)/'`../http-host.c
+ mv -f $(DEPDIR)/http-host.Tpo $(DEPDIR)/http-host.Po
+# source='../http-host.c' object='http-host.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-host.o `test -f '../http-host.c' || echo '$(srcdir)/'`../http-host.c
+
+http-host.obj: ../http-host.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-host.obj -MD -MP -MF $(DEPDIR)/http-host.Tpo -c -o http-host.obj `if test -f '../http-host.c'; then $(CYGPATH_W) '../http-host.c'; else $(CYGPATH_W) '$(srcdir)/../http-host.c'; fi`
+ mv -f $(DEPDIR)/http-host.Tpo $(DEPDIR)/http-host.Po
+# source='../http-host.c' object='http-host.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-host.obj `if test -f '../http-host.c'; then $(CYGPATH_W) '../http-host.c'; else $(CYGPATH_W) '$(srcdir)/../http-host.c'; fi`
+
+http-url.o: ../http-url.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-url.o -MD -MP -MF $(DEPDIR)/http-url.Tpo -c -o http-url.o `test -f '../http-url.c' || echo '$(srcdir)/'`../http-url.c
+ mv -f $(DEPDIR)/http-url.Tpo $(DEPDIR)/http-url.Po
+# source='../http-url.c' object='http-url.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-url.o `test -f '../http-url.c' || echo '$(srcdir)/'`../http-url.c
+
+http-url.obj: ../http-url.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-url.obj -MD -MP -MF $(DEPDIR)/http-url.Tpo -c -o http-url.obj `if test -f '../http-url.c'; then $(CYGPATH_W) '../http-url.c'; else $(CYGPATH_W) '$(srcdir)/../http-url.c'; fi`
+ mv -f $(DEPDIR)/http-url.Tpo $(DEPDIR)/http-url.Po
+# source='../http-url.c' object='http-url.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-url.obj `if test -f '../http-url.c'; then $(CYGPATH_W) '../http-url.c'; else $(CYGPATH_W) '$(srcdir)/../http-url.c'; fi`
+
+stream.o: ../stream.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stream.o -MD -MP -MF $(DEPDIR)/stream.Tpo -c -o stream.o `test -f '../stream.c' || echo '$(srcdir)/'`../stream.c
+ mv -f $(DEPDIR)/stream.Tpo $(DEPDIR)/stream.Po
+# source='../stream.c' object='stream.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stream.o `test -f '../stream.c' || echo '$(srcdir)/'`../stream.c
+
+stream.obj: ../stream.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stream.obj -MD -MP -MF $(DEPDIR)/stream.Tpo -c -o stream.obj `if test -f '../stream.c'; then $(CYGPATH_W) '../stream.c'; else $(CYGPATH_W) '$(srcdir)/../stream.c'; fi`
+ mv -f $(DEPDIR)/stream.Tpo $(DEPDIR)/stream.Po
+# source='../stream.c' object='stream.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stream.obj `if test -f '../stream.c'; then $(CYGPATH_W) '../stream.c'; else $(CYGPATH_W) '$(srcdir)/../stream.c'; fi`
+
+highlight.o: ../highlight.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT highlight.o -MD -MP -MF $(DEPDIR)/highlight.Tpo -c -o highlight.o `test -f '../highlight.c' || echo '$(srcdir)/'`../highlight.c
+ mv -f $(DEPDIR)/highlight.Tpo $(DEPDIR)/highlight.Po
+# source='../highlight.c' object='highlight.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o highlight.o `test -f '../highlight.c' || echo '$(srcdir)/'`../highlight.c
+
+highlight.obj: ../highlight.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT highlight.obj -MD -MP -MF $(DEPDIR)/highlight.Tpo -c -o highlight.obj `if test -f '../highlight.c'; then $(CYGPATH_W) '../highlight.c'; else $(CYGPATH_W) '$(srcdir)/../highlight.c'; fi`
+ mv -f $(DEPDIR)/highlight.Tpo $(DEPDIR)/highlight.Po
+# source='../highlight.c' object='highlight.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o highlight.obj `if test -f '../highlight.c'; then $(CYGPATH_W) '../highlight.c'; else $(CYGPATH_W) '$(srcdir)/../highlight.c'; fi`
+
+resource-manager.o: ../resource-manager.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT resource-manager.o -MD -MP -MF $(DEPDIR)/resource-manager.Tpo -c -o resource-manager.o `test -f '../resource-manager.c' || echo '$(srcdir)/'`../resource-manager.c
+ mv -f $(DEPDIR)/resource-manager.Tpo $(DEPDIR)/resource-manager.Po
+# source='../resource-manager.c' object='resource-manager.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o resource-manager.o `test -f '../resource-manager.c' || echo '$(srcdir)/'`../resource-manager.c
+
+resource-manager.obj: ../resource-manager.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT resource-manager.obj -MD -MP -MF $(DEPDIR)/resource-manager.Tpo -c -o resource-manager.obj `if test -f '../resource-manager.c'; then $(CYGPATH_W) '../resource-manager.c'; else $(CYGPATH_W) '$(srcdir)/../resource-manager.c'; fi`
+ mv -f $(DEPDIR)/resource-manager.Tpo $(DEPDIR)/resource-manager.Po
+# source='../resource-manager.c' object='resource-manager.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o resource-manager.obj `if test -f '../resource-manager.c'; then $(CYGPATH_W) '../resource-manager.c'; else $(CYGPATH_W) '$(srcdir)/../resource-manager.c'; fi`
+
+.cpp.o:
+ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+instrument-js.o: ../instrument-js.cpp
+ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT instrument-js.o -MD -MP -MF $(DEPDIR)/instrument-js.Tpo -c -o instrument-js.o `test -f '../instrument-js.cpp' || echo '$(srcdir)/'`../instrument-js.cpp
+ mv -f $(DEPDIR)/instrument-js.Tpo $(DEPDIR)/instrument-js.Po
+# source='../instrument-js.cpp' object='instrument-js.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o instrument-js.o `test -f '../instrument-js.cpp' || echo '$(srcdir)/'`../instrument-js.cpp
+
+instrument-js.obj: ../instrument-js.cpp
+ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT instrument-js.obj -MD -MP -MF $(DEPDIR)/instrument-js.Tpo -c -o instrument-js.obj `if test -f '../instrument-js.cpp'; then $(CYGPATH_W) '../instrument-js.cpp'; else $(CYGPATH_W) '$(srcdir)/../instrument-js.cpp'; fi`
+ mv -f $(DEPDIR)/instrument-js.Tpo $(DEPDIR)/instrument-js.Po
+# source='../instrument-js.cpp' object='instrument-js.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o instrument-js.obj `if test -f '../instrument-js.cpp'; then $(CYGPATH_W) '../instrument-js.cpp'; else $(CYGPATH_W) '$(srcdir)/../instrument-js.cpp'; fi`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ echo "XPASS: $$tst"; \
+ ;; \
+ *) \
+ echo "PASS: $$tst"; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xfail=`expr $$xfail + 1`; \
+ echo "XFAIL: $$tst"; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ echo "FAIL: $$tst"; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ echo "SKIP: $$tst"; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all tests failed"; \
+ else \
+ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ skipped="($$skip tests were not run)"; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+ clean-generic clean-noinstPROGRAMS ctags distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.am b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.am
new file mode 100644
index 0000000..c58d2a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.am
@@ -0,0 +1,130 @@
+# Makefile.am - build tests
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+noinst_PROGRAMS = asprintf \
+ encodings \
+ gethostbyname \
+ http-client-bad-body \
+ http-client-bad-url \
+ http-client-close-after-request \
+ http-server-bad-body \
+ http-server-bad-headers \
+ http-server-charset \
+ http-server-chunked \
+ http-server-close-immediately \
+ json \
+ mkdirs \
+ recursive-dir-list \
+ streams
+
+AM_CFLAGS = @XP_DEF@ -I../js -I../js/obj
+AM_CXXFLAGS = @XP_DEF@ -I../js -I../js/obj
+
+asprintf_SOURCES = asprintf.c ../util.c
+
+encodings_SOURCES = encodings.c ../encoding.c ../util.c
+encodings_LDADD = @LIBICONV@
+
+gethostbyname_SOURCES = gethostbyname.c ../http-host.c ../util.c
+gethostbyname_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_client_bad_body_SOURCES = http-client-bad-body.c ../http-url.c ../util.c
+http_client_bad_body_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_client_bad_url_SOURCES = http-client-bad-url.c ../util.c
+http_client_bad_url_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_client_close_after_request_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_server_bad_body_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_server_bad_headers_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_server_charset_SOURCES = http-server-charset.c ../stream.c ../util.c
+http_server_charset_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_server_chunked_SOURCES = http-server-chunked.c ../stream.c ../util.c
+http_server_chunked_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_server_close_immediately_LDADD = @EXTRA_SOCKET_LIBS@
+
+json_SOURCES = json.c ../encoding.c ../highlight.c ../instrument-js.cpp ../resource-manager.c ../stream.c ../util.c
+json_LDADD = ../js/obj/libjs.a -lm @LIBICONV@ @EXTRA_TIMER_LIBS@
+
+mkdirs_SOURCES = mkdirs.c ../util.c
+
+recursive_dir_list_SOURCES = recursive-dir-list.c ../util.c
+
+streams_SOURCES = streams.c ../stream.c ../util.c
+
+TESTS = encodings.sh \
+ fatal.sh \
+ help.sh \
+ invalid-option.sh \
+ javascript.sh \
+ javascript-ignore.sh \
+ javascript-utf-8.sh \
+ no-arguments.sh \
+ recursive.sh \
+ recursive-crlf.sh \
+ recursive-exclude.sh \
+ recursive-fatal.sh \
+ recursive-no-instrument.sh \
+ same-directory.sh \
+ version.sh \
+ asprintf.sh \
+ mkdirs.sh \
+ recursive-dir-list.sh \
+ streams.sh \
+ charset.sh \
+ chunked.sh \
+ gethostbyname.sh \
+ json.sh \
+ proxy.sh \
+ proxy-bad-request-body.sh \
+ proxy-bad-response-body.sh \
+ proxy-bad-response-body-javascript.sh \
+ proxy-bad-response-headers.sh \
+ proxy-no-server.sh \
+ proxy-url.sh \
+ server.sh \
+ server-bad-requests.sh \
+ server-close-after-request.sh \
+ server-content-types.sh \
+ server-directory-listing.sh \
+ server-directory-redirect.sh \
+ server-encoded-url.sh \
+ server-error.sh \
+ server-help.sh \
+ server-ip-address.sh \
+ server-shutdown.sh \
+ server-shutdown-bad-method.sh \
+ server-special-file.sh \
+ server-unreadable-directory.sh \
+ server-unreadable-file.sh \
+ server-verbose.sh \
+ server-version.sh \
+ store.sh \
+ store-bad-json.sh \
+ store-bad-request-body.sh \
+ store-bad-response-headers.sh \
+ store-escaped-characters.sh \
+ store-server-bad-body.sh \
+ store-server-closes-immediately.sh \
+ store-source-not-found.sh \
+ store-unreadable-json.sh \
+ store-unwritable-json.sh
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.in b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.in
new file mode 100644
index 0000000..bbe0402
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.in
@@ -0,0 +1,846 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am - build tests
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = asprintf$(EXEEXT) encodings$(EXEEXT) \
+ gethostbyname$(EXEEXT) http-client-bad-body$(EXEEXT) \
+ http-client-bad-url$(EXEEXT) \
+ http-client-close-after-request$(EXEEXT) \
+ http-server-bad-body$(EXEEXT) http-server-bad-headers$(EXEEXT) \
+ http-server-charset$(EXEEXT) http-server-chunked$(EXEEXT) \
+ http-server-close-immediately$(EXEEXT) json$(EXEEXT) \
+ mkdirs$(EXEEXT) recursive-dir-list$(EXEEXT) streams$(EXEEXT)
+subdir = tests
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_asprintf_OBJECTS = asprintf.$(OBJEXT) util.$(OBJEXT)
+asprintf_OBJECTS = $(am_asprintf_OBJECTS)
+asprintf_LDADD = $(LDADD)
+am_encodings_OBJECTS = encodings.$(OBJEXT) encoding.$(OBJEXT) \
+ util.$(OBJEXT)
+encodings_OBJECTS = $(am_encodings_OBJECTS)
+encodings_DEPENDENCIES =
+am_gethostbyname_OBJECTS = gethostbyname.$(OBJEXT) http-host.$(OBJEXT) \
+ util.$(OBJEXT)
+gethostbyname_OBJECTS = $(am_gethostbyname_OBJECTS)
+gethostbyname_DEPENDENCIES =
+am_http_client_bad_body_OBJECTS = http-client-bad-body.$(OBJEXT) \
+ http-url.$(OBJEXT) util.$(OBJEXT)
+http_client_bad_body_OBJECTS = $(am_http_client_bad_body_OBJECTS)
+http_client_bad_body_DEPENDENCIES =
+am_http_client_bad_url_OBJECTS = http-client-bad-url.$(OBJEXT) \
+ util.$(OBJEXT)
+http_client_bad_url_OBJECTS = $(am_http_client_bad_url_OBJECTS)
+http_client_bad_url_DEPENDENCIES =
+http_client_close_after_request_SOURCES = \
+ http-client-close-after-request.c
+http_client_close_after_request_OBJECTS = \
+ http-client-close-after-request.$(OBJEXT)
+http_client_close_after_request_DEPENDENCIES =
+http_server_bad_body_SOURCES = http-server-bad-body.c
+http_server_bad_body_OBJECTS = http-server-bad-body.$(OBJEXT)
+http_server_bad_body_DEPENDENCIES =
+http_server_bad_headers_SOURCES = http-server-bad-headers.c
+http_server_bad_headers_OBJECTS = http-server-bad-headers.$(OBJEXT)
+http_server_bad_headers_DEPENDENCIES =
+am_http_server_charset_OBJECTS = http-server-charset.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT)
+http_server_charset_OBJECTS = $(am_http_server_charset_OBJECTS)
+http_server_charset_DEPENDENCIES =
+am_http_server_chunked_OBJECTS = http-server-chunked.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT)
+http_server_chunked_OBJECTS = $(am_http_server_chunked_OBJECTS)
+http_server_chunked_DEPENDENCIES =
+http_server_close_immediately_SOURCES = \
+ http-server-close-immediately.c
+http_server_close_immediately_OBJECTS = \
+ http-server-close-immediately.$(OBJEXT)
+http_server_close_immediately_DEPENDENCIES =
+am_json_OBJECTS = json.$(OBJEXT) encoding.$(OBJEXT) \
+ highlight.$(OBJEXT) instrument-js.$(OBJEXT) \
+ resource-manager.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT)
+json_OBJECTS = $(am_json_OBJECTS)
+json_DEPENDENCIES = ../js/obj/libjs.a
+am_mkdirs_OBJECTS = mkdirs.$(OBJEXT) util.$(OBJEXT)
+mkdirs_OBJECTS = $(am_mkdirs_OBJECTS)
+mkdirs_LDADD = $(LDADD)
+am_recursive_dir_list_OBJECTS = recursive-dir-list.$(OBJEXT) \
+ util.$(OBJEXT)
+recursive_dir_list_OBJECTS = $(am_recursive_dir_list_OBJECTS)
+recursive_dir_list_LDADD = $(LDADD)
+am_streams_OBJECTS = streams.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT)
+streams_OBJECTS = $(am_streams_OBJECTS)
+streams_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(asprintf_SOURCES) $(encodings_SOURCES) \
+ $(gethostbyname_SOURCES) $(http_client_bad_body_SOURCES) \
+ $(http_client_bad_url_SOURCES) \
+ http-client-close-after-request.c http-server-bad-body.c \
+ http-server-bad-headers.c $(http_server_charset_SOURCES) \
+ $(http_server_chunked_SOURCES) http-server-close-immediately.c \
+ $(json_SOURCES) $(mkdirs_SOURCES) \
+ $(recursive_dir_list_SOURCES) $(streams_SOURCES)
+DIST_SOURCES = $(asprintf_SOURCES) $(encodings_SOURCES) \
+ $(gethostbyname_SOURCES) $(http_client_bad_body_SOURCES) \
+ $(http_client_bad_url_SOURCES) \
+ http-client-close-after-request.c http-server-bad-body.c \
+ http-server-bad-headers.c $(http_server_charset_SOURCES) \
+ $(http_server_chunked_SOURCES) http-server-close-immediately.c \
+ $(json_SOURCES) $(mkdirs_SOURCES) \
+ $(recursive_dir_list_SOURCES) $(streams_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@
+EXTRA_THREAD_LIBS = @EXTRA_THREAD_LIBS@
+EXTRA_TIMER_LIBS = @EXTRA_TIMER_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBICONV = @LTLIBICONV@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+XP_DEF = @XP_DEF@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CFLAGS = @XP_DEF@ -I../js -I../js/obj
+AM_CXXFLAGS = @XP_DEF@ -I../js -I../js/obj
+asprintf_SOURCES = asprintf.c ../util.c
+encodings_SOURCES = encodings.c ../encoding.c ../util.c
+encodings_LDADD = @LIBICONV@
+gethostbyname_SOURCES = gethostbyname.c ../http-host.c ../util.c
+gethostbyname_LDADD = @EXTRA_SOCKET_LIBS@
+http_client_bad_body_SOURCES = http-client-bad-body.c ../http-url.c ../util.c
+http_client_bad_body_LDADD = @EXTRA_SOCKET_LIBS@
+http_client_bad_url_SOURCES = http-client-bad-url.c ../util.c
+http_client_bad_url_LDADD = @EXTRA_SOCKET_LIBS@
+http_client_close_after_request_LDADD = @EXTRA_SOCKET_LIBS@
+http_server_bad_body_LDADD = @EXTRA_SOCKET_LIBS@
+http_server_bad_headers_LDADD = @EXTRA_SOCKET_LIBS@
+http_server_charset_SOURCES = http-server-charset.c ../stream.c ../util.c
+http_server_charset_LDADD = @EXTRA_SOCKET_LIBS@
+http_server_chunked_SOURCES = http-server-chunked.c ../stream.c ../util.c
+http_server_chunked_LDADD = @EXTRA_SOCKET_LIBS@
+http_server_close_immediately_LDADD = @EXTRA_SOCKET_LIBS@
+json_SOURCES = json.c ../encoding.c ../highlight.c ../instrument-js.cpp ../resource-manager.c ../stream.c ../util.c
+json_LDADD = ../js/obj/libjs.a -lm @LIBICONV@ @EXTRA_TIMER_LIBS@
+mkdirs_SOURCES = mkdirs.c ../util.c
+recursive_dir_list_SOURCES = recursive-dir-list.c ../util.c
+streams_SOURCES = streams.c ../stream.c ../util.c
+TESTS = encodings.sh \
+ fatal.sh \
+ help.sh \
+ invalid-option.sh \
+ javascript.sh \
+ javascript-ignore.sh \
+ javascript-utf-8.sh \
+ no-arguments.sh \
+ recursive.sh \
+ recursive-crlf.sh \
+ recursive-exclude.sh \
+ recursive-fatal.sh \
+ recursive-no-instrument.sh \
+ same-directory.sh \
+ version.sh \
+ asprintf.sh \
+ mkdirs.sh \
+ recursive-dir-list.sh \
+ streams.sh \
+ charset.sh \
+ chunked.sh \
+ gethostbyname.sh \
+ json.sh \
+ proxy.sh \
+ proxy-bad-request-body.sh \
+ proxy-bad-response-body.sh \
+ proxy-bad-response-body-javascript.sh \
+ proxy-bad-response-headers.sh \
+ proxy-no-server.sh \
+ proxy-url.sh \
+ server.sh \
+ server-bad-requests.sh \
+ server-close-after-request.sh \
+ server-content-types.sh \
+ server-directory-listing.sh \
+ server-directory-redirect.sh \
+ server-encoded-url.sh \
+ server-error.sh \
+ server-help.sh \
+ server-ip-address.sh \
+ server-shutdown.sh \
+ server-shutdown-bad-method.sh \
+ server-special-file.sh \
+ server-unreadable-directory.sh \
+ server-unreadable-file.sh \
+ server-verbose.sh \
+ server-version.sh \
+ store.sh \
+ store-bad-json.sh \
+ store-bad-request-body.sh \
+ store-bad-response-headers.sh \
+ store-escaped-characters.sh \
+ store-server-bad-body.sh \
+ store-server-closes-immediately.sh \
+ store-source-not-found.sh \
+ store-unreadable-json.sh \
+ store-unwritable-json.sh
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+asprintf$(EXEEXT): $(asprintf_OBJECTS) $(asprintf_DEPENDENCIES)
+ @rm -f asprintf$(EXEEXT)
+ $(LINK) $(asprintf_OBJECTS) $(asprintf_LDADD) $(LIBS)
+encodings$(EXEEXT): $(encodings_OBJECTS) $(encodings_DEPENDENCIES)
+ @rm -f encodings$(EXEEXT)
+ $(LINK) $(encodings_OBJECTS) $(encodings_LDADD) $(LIBS)
+gethostbyname$(EXEEXT): $(gethostbyname_OBJECTS) $(gethostbyname_DEPENDENCIES)
+ @rm -f gethostbyname$(EXEEXT)
+ $(LINK) $(gethostbyname_OBJECTS) $(gethostbyname_LDADD) $(LIBS)
+http-client-bad-body$(EXEEXT): $(http_client_bad_body_OBJECTS) $(http_client_bad_body_DEPENDENCIES)
+ @rm -f http-client-bad-body$(EXEEXT)
+ $(LINK) $(http_client_bad_body_OBJECTS) $(http_client_bad_body_LDADD) $(LIBS)
+http-client-bad-url$(EXEEXT): $(http_client_bad_url_OBJECTS) $(http_client_bad_url_DEPENDENCIES)
+ @rm -f http-client-bad-url$(EXEEXT)
+ $(LINK) $(http_client_bad_url_OBJECTS) $(http_client_bad_url_LDADD) $(LIBS)
+http-client-close-after-request$(EXEEXT): $(http_client_close_after_request_OBJECTS) $(http_client_close_after_request_DEPENDENCIES)
+ @rm -f http-client-close-after-request$(EXEEXT)
+ $(LINK) $(http_client_close_after_request_OBJECTS) $(http_client_close_after_request_LDADD) $(LIBS)
+http-server-bad-body$(EXEEXT): $(http_server_bad_body_OBJECTS) $(http_server_bad_body_DEPENDENCIES)
+ @rm -f http-server-bad-body$(EXEEXT)
+ $(LINK) $(http_server_bad_body_OBJECTS) $(http_server_bad_body_LDADD) $(LIBS)
+http-server-bad-headers$(EXEEXT): $(http_server_bad_headers_OBJECTS) $(http_server_bad_headers_DEPENDENCIES)
+ @rm -f http-server-bad-headers$(EXEEXT)
+ $(LINK) $(http_server_bad_headers_OBJECTS) $(http_server_bad_headers_LDADD) $(LIBS)
+http-server-charset$(EXEEXT): $(http_server_charset_OBJECTS) $(http_server_charset_DEPENDENCIES)
+ @rm -f http-server-charset$(EXEEXT)
+ $(LINK) $(http_server_charset_OBJECTS) $(http_server_charset_LDADD) $(LIBS)
+http-server-chunked$(EXEEXT): $(http_server_chunked_OBJECTS) $(http_server_chunked_DEPENDENCIES)
+ @rm -f http-server-chunked$(EXEEXT)
+ $(LINK) $(http_server_chunked_OBJECTS) $(http_server_chunked_LDADD) $(LIBS)
+http-server-close-immediately$(EXEEXT): $(http_server_close_immediately_OBJECTS) $(http_server_close_immediately_DEPENDENCIES)
+ @rm -f http-server-close-immediately$(EXEEXT)
+ $(LINK) $(http_server_close_immediately_OBJECTS) $(http_server_close_immediately_LDADD) $(LIBS)
+json$(EXEEXT): $(json_OBJECTS) $(json_DEPENDENCIES)
+ @rm -f json$(EXEEXT)
+ $(CXXLINK) $(json_OBJECTS) $(json_LDADD) $(LIBS)
+mkdirs$(EXEEXT): $(mkdirs_OBJECTS) $(mkdirs_DEPENDENCIES)
+ @rm -f mkdirs$(EXEEXT)
+ $(LINK) $(mkdirs_OBJECTS) $(mkdirs_LDADD) $(LIBS)
+recursive-dir-list$(EXEEXT): $(recursive_dir_list_OBJECTS) $(recursive_dir_list_DEPENDENCIES)
+ @rm -f recursive-dir-list$(EXEEXT)
+ $(LINK) $(recursive_dir_list_OBJECTS) $(recursive_dir_list_LDADD) $(LIBS)
+streams$(EXEEXT): $(streams_OBJECTS) $(streams_DEPENDENCIES)
+ @rm -f streams$(EXEEXT)
+ $(LINK) $(streams_OBJECTS) $(streams_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asprintf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoding.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encodings.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gethostbyname.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/highlight.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-client-bad-body.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-client-bad-url.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-client-close-after-request.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-host.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server-bad-body.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server-bad-headers.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server-charset.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server-chunked.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server-close-immediately.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-url.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instrument-js.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkdirs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recursive-dir-list.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resource-manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/streams.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+util.o: ../util.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT util.o -MD -MP -MF $(DEPDIR)/util.Tpo -c -o util.o `test -f '../util.c' || echo '$(srcdir)/'`../util.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/util.Tpo $(DEPDIR)/util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../util.c' object='util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o util.o `test -f '../util.c' || echo '$(srcdir)/'`../util.c
+
+util.obj: ../util.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT util.obj -MD -MP -MF $(DEPDIR)/util.Tpo -c -o util.obj `if test -f '../util.c'; then $(CYGPATH_W) '../util.c'; else $(CYGPATH_W) '$(srcdir)/../util.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/util.Tpo $(DEPDIR)/util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../util.c' object='util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o util.obj `if test -f '../util.c'; then $(CYGPATH_W) '../util.c'; else $(CYGPATH_W) '$(srcdir)/../util.c'; fi`
+
+encoding.o: ../encoding.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encoding.o -MD -MP -MF $(DEPDIR)/encoding.Tpo -c -o encoding.o `test -f '../encoding.c' || echo '$(srcdir)/'`../encoding.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/encoding.Tpo $(DEPDIR)/encoding.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../encoding.c' object='encoding.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encoding.o `test -f '../encoding.c' || echo '$(srcdir)/'`../encoding.c
+
+encoding.obj: ../encoding.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encoding.obj -MD -MP -MF $(DEPDIR)/encoding.Tpo -c -o encoding.obj `if test -f '../encoding.c'; then $(CYGPATH_W) '../encoding.c'; else $(CYGPATH_W) '$(srcdir)/../encoding.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/encoding.Tpo $(DEPDIR)/encoding.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../encoding.c' object='encoding.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encoding.obj `if test -f '../encoding.c'; then $(CYGPATH_W) '../encoding.c'; else $(CYGPATH_W) '$(srcdir)/../encoding.c'; fi`
+
+http-host.o: ../http-host.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-host.o -MD -MP -MF $(DEPDIR)/http-host.Tpo -c -o http-host.o `test -f '../http-host.c' || echo '$(srcdir)/'`../http-host.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/http-host.Tpo $(DEPDIR)/http-host.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../http-host.c' object='http-host.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-host.o `test -f '../http-host.c' || echo '$(srcdir)/'`../http-host.c
+
+http-host.obj: ../http-host.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-host.obj -MD -MP -MF $(DEPDIR)/http-host.Tpo -c -o http-host.obj `if test -f '../http-host.c'; then $(CYGPATH_W) '../http-host.c'; else $(CYGPATH_W) '$(srcdir)/../http-host.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/http-host.Tpo $(DEPDIR)/http-host.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../http-host.c' object='http-host.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-host.obj `if test -f '../http-host.c'; then $(CYGPATH_W) '../http-host.c'; else $(CYGPATH_W) '$(srcdir)/../http-host.c'; fi`
+
+http-url.o: ../http-url.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-url.o -MD -MP -MF $(DEPDIR)/http-url.Tpo -c -o http-url.o `test -f '../http-url.c' || echo '$(srcdir)/'`../http-url.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/http-url.Tpo $(DEPDIR)/http-url.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../http-url.c' object='http-url.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-url.o `test -f '../http-url.c' || echo '$(srcdir)/'`../http-url.c
+
+http-url.obj: ../http-url.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-url.obj -MD -MP -MF $(DEPDIR)/http-url.Tpo -c -o http-url.obj `if test -f '../http-url.c'; then $(CYGPATH_W) '../http-url.c'; else $(CYGPATH_W) '$(srcdir)/../http-url.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/http-url.Tpo $(DEPDIR)/http-url.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../http-url.c' object='http-url.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-url.obj `if test -f '../http-url.c'; then $(CYGPATH_W) '../http-url.c'; else $(CYGPATH_W) '$(srcdir)/../http-url.c'; fi`
+
+stream.o: ../stream.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stream.o -MD -MP -MF $(DEPDIR)/stream.Tpo -c -o stream.o `test -f '../stream.c' || echo '$(srcdir)/'`../stream.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/stream.Tpo $(DEPDIR)/stream.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../stream.c' object='stream.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stream.o `test -f '../stream.c' || echo '$(srcdir)/'`../stream.c
+
+stream.obj: ../stream.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stream.obj -MD -MP -MF $(DEPDIR)/stream.Tpo -c -o stream.obj `if test -f '../stream.c'; then $(CYGPATH_W) '../stream.c'; else $(CYGPATH_W) '$(srcdir)/../stream.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/stream.Tpo $(DEPDIR)/stream.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../stream.c' object='stream.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stream.obj `if test -f '../stream.c'; then $(CYGPATH_W) '../stream.c'; else $(CYGPATH_W) '$(srcdir)/../stream.c'; fi`
+
+highlight.o: ../highlight.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT highlight.o -MD -MP -MF $(DEPDIR)/highlight.Tpo -c -o highlight.o `test -f '../highlight.c' || echo '$(srcdir)/'`../highlight.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/highlight.Tpo $(DEPDIR)/highlight.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../highlight.c' object='highlight.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o highlight.o `test -f '../highlight.c' || echo '$(srcdir)/'`../highlight.c
+
+highlight.obj: ../highlight.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT highlight.obj -MD -MP -MF $(DEPDIR)/highlight.Tpo -c -o highlight.obj `if test -f '../highlight.c'; then $(CYGPATH_W) '../highlight.c'; else $(CYGPATH_W) '$(srcdir)/../highlight.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/highlight.Tpo $(DEPDIR)/highlight.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../highlight.c' object='highlight.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o highlight.obj `if test -f '../highlight.c'; then $(CYGPATH_W) '../highlight.c'; else $(CYGPATH_W) '$(srcdir)/../highlight.c'; fi`
+
+resource-manager.o: ../resource-manager.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT resource-manager.o -MD -MP -MF $(DEPDIR)/resource-manager.Tpo -c -o resource-manager.o `test -f '../resource-manager.c' || echo '$(srcdir)/'`../resource-manager.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/resource-manager.Tpo $(DEPDIR)/resource-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../resource-manager.c' object='resource-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o resource-manager.o `test -f '../resource-manager.c' || echo '$(srcdir)/'`../resource-manager.c
+
+resource-manager.obj: ../resource-manager.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT resource-manager.obj -MD -MP -MF $(DEPDIR)/resource-manager.Tpo -c -o resource-manager.obj `if test -f '../resource-manager.c'; then $(CYGPATH_W) '../resource-manager.c'; else $(CYGPATH_W) '$(srcdir)/../resource-manager.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/resource-manager.Tpo $(DEPDIR)/resource-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../resource-manager.c' object='resource-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o resource-manager.obj `if test -f '../resource-manager.c'; then $(CYGPATH_W) '../resource-manager.c'; else $(CYGPATH_W) '$(srcdir)/../resource-manager.c'; fi`
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+instrument-js.o: ../instrument-js.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT instrument-js.o -MD -MP -MF $(DEPDIR)/instrument-js.Tpo -c -o instrument-js.o `test -f '../instrument-js.cpp' || echo '$(srcdir)/'`../instrument-js.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/instrument-js.Tpo $(DEPDIR)/instrument-js.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../instrument-js.cpp' object='instrument-js.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o instrument-js.o `test -f '../instrument-js.cpp' || echo '$(srcdir)/'`../instrument-js.cpp
+
+instrument-js.obj: ../instrument-js.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT instrument-js.obj -MD -MP -MF $(DEPDIR)/instrument-js.Tpo -c -o instrument-js.obj `if test -f '../instrument-js.cpp'; then $(CYGPATH_W) '../instrument-js.cpp'; else $(CYGPATH_W) '$(srcdir)/../instrument-js.cpp'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/instrument-js.Tpo $(DEPDIR)/instrument-js.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../instrument-js.cpp' object='instrument-js.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o instrument-js.obj `if test -f '../instrument-js.cpp'; then $(CYGPATH_W) '../instrument-js.cpp'; else $(CYGPATH_W) '$(srcdir)/../instrument-js.cpp'; fi`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ echo "XPASS: $$tst"; \
+ ;; \
+ *) \
+ echo "PASS: $$tst"; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xfail=`expr $$xfail + 1`; \
+ echo "XFAIL: $$tst"; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ echo "FAIL: $$tst"; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ echo "SKIP: $$tst"; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all tests failed"; \
+ else \
+ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ skipped="($$skip tests were not run)"; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+ clean-generic clean-noinstPROGRAMS ctags distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.c b/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.c
new file mode 100644
index 0000000..7f8246b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.c
@@ -0,0 +1,42 @@
+/*
+ asprintf.c - test `asprintf' function
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+int main(void) {
+ int result;
+ char * s;
+
+ result = asprintf(&s, "%s %d %c", "abc", 123, 'x');
+ assert(result == 9);
+ assert(strcmp("abc 123 x", s) == 0);
+ free(s);
+
+ char * long_string = "abcdefghijklmnopqrstuvwxyz";
+ result = asprintf(&s, "%s %s %s %s", long_string, long_string, long_string, long_string);
+ assert(result == 107);
+ assert(strcmp("abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz", s) == 0);
+ free(s);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.sh b/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.sh
new file mode 100755
index 0000000..c7843e4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# asprintf.sh - test `asprintf' function
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./asprintf
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/charset.sh b/tools/node_modules/expresso/deps/jscoverage/tests/charset.sh
new file mode 100755
index 0000000..9fb07eb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/charset.sh
@@ -0,0 +1,110 @@
+#!/bin/sh
+# charset.sh - test jscoverage-server with different charset values
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+}
+
+cleanup() {
+ shutdown
+ kill -9 $origin_server_pid
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+if jscoverage-server --version | grep -q 'iconv\|MultiByteToWideChar'
+then
+ character_encoding_support=yes
+else
+ character_encoding_support=no
+fi
+
+$VALGRIND jscoverage-server --proxy --no-highlight > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+./http-server-charset &
+origin_server_pid=$!
+
+sleep $delay
+
+case "$character_encoding_support" in
+ yes)
+ cat ../report.js > EXPECTED
+ cat javascript-utf-8.expected/javascript-utf-8.js | sed 's/javascript-utf-8.js/http:\/\/127.0.0.1:8000\/utf-8.js/g' >> EXPECTED
+ curl -s -x 127.0.0.1:8080 http://127.0.0.1:8000/utf-8.js > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+ *)
+ echo 500 > EXPECTED
+ ! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/utf-8.js 2> /dev/null > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+esac
+
+shutdown
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+case "$character_encoding_support" in
+ yes)
+ cat ../report.js > EXPECTED
+ cat javascript.expected/javascript-iso-8859-1.js | sed 's/javascript-iso-8859-1.js/http:\/\/127.0.0.1:8000\/iso-8859-1.js/g' >> EXPECTED
+ curl -s -x 127.0.0.1:8080 http://127.0.0.1:8000/iso-8859-1.js > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+ *)
+ echo 500 > EXPECTED
+ ! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/iso-8859-1.js 2> /dev/null > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+esac
+
+# bogus charset
+echo 500 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/bogus.js 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# malformed encoding
+case "$character_encoding_support" in
+ yes)
+ status=502
+ ;;
+ *)
+ status=500
+ ;;
+esac
+echo $status > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/malformed.js 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/chunked.sh b/tools/node_modules/expresso/deps/jscoverage/tests/chunked.sh
new file mode 100755
index 0000000..2986552
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/chunked.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+# chunked.sh - test jscoverage-server with Transfer-Encoding: chunked
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+}
+
+cleanup() {
+ shutdown
+ kill -9 $origin_server_pid
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+./http-server-chunked &
+origin_server_pid=$!
+
+sleep $delay
+
+echo 'hello world' > EXPECTED
+curl -s -x 127.0.0.1:8080 http://127.0.0.1:8000/lower > ACTUAL
+diff EXPECTED ACTUAL
+
+echo 'HELLO WORLD' > EXPECTED
+curl -s -x 127.0.0.1:8080 http://127.0.0.1:8000/upper > ACTUAL
+diff EXPECTED ACTUAL
+
+# curl doesn't understand trailers ???
+# echo 'hello world' > EXPECTED
+# curl -s -x 127.0.0.1:8080 http://127.0.0.1:8000/trailer > ACTUAL
+# diff EXPECTED ACTUAL
+
+echo 200 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/overflow 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+echo 200 > EXPECTED
+! curl -f -w '%{http_code}\n' -o /dev/null -x 127.0.0.1:8080 http://127.0.0.1:8000/javascript 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+echo 200 > EXPECTED
+! curl -f -w '%{http_code}\n' -o /dev/null -x 127.0.0.1:8080 http://127.0.0.1:8000/multiple 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/common.sh b/tools/node_modules/expresso/deps/jscoverage/tests/common.sh
new file mode 100644
index 0000000..e55b342
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/common.sh
@@ -0,0 +1,7 @@
+export PATH=.:..:../js/obj:$PATH
+
+json_cmp() {
+ echo 'EXPECTED = ' | cat - $1 > EXPECTED
+ echo 'ACTUAL = ' | cat - $2 > ACTUAL
+ js -f EXPECTED -f ACTUAL -f json-cmp.js
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-existing-directory.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-existing-directory.expected.err
new file mode 100644
index 0000000..8a59e6b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-existing-directory.expected.err
@@ -0,0 +1,2 @@
+jscoverage: refusing to overwrite directory: bar
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-file.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-file.expected.err
new file mode 100644
index 0000000..bb3778d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-file.expected.err
@@ -0,0 +1,2 @@
+jscoverage: not a directory: bar
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/encoding-requires-argument.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/encoding-requires-argument.expected.err
new file mode 100644
index 0000000..4b3fd0c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/encoding-requires-argument.expected.err
@@ -0,0 +1,2 @@
+jscoverage: --encoding: option requires an argument
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/encodings.c b/tools/node_modules/expresso/deps/jscoverage/tests/encodings.c
new file mode 100644
index 0000000..26f8707
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/encodings.c
@@ -0,0 +1,223 @@
+/*
+ encodings.c - test handling different character encodings
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "encoding.h"
+#include "stream.h"
+
+int main(void) {
+ jschar * characters;
+ size_t num_characters;
+ int result;
+
+ /* e, e grave, e acute, e circumflex */
+ uint8_t utf8[] = {
+ 'e',
+ 0xc3,
+ 0xa8,
+ 0xc3,
+ 0xa9,
+ 0xc3,
+ 0xaa,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-8", utf8, 7, &characters, &num_characters);
+
+#if HAVE_ICONV || HAVE_MULTIBYTETOWIDECHAR
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ /*
+ BOM is 0xfeff
+ = 1111 1110 1111 1111
+ UTF: 1110---- 10------ 10------
+ = 11101111 10111011 10111111
+ = EF BB BF
+ */
+ uint8_t utf8_with_bom[] = {
+ 0xef,
+ 0xbb,
+ 0xbf,
+ 'e',
+ 0xc3,
+ 0xa8,
+ 0xc3,
+ 0xa9,
+ 0xc3,
+ 0xaa,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-8", utf8_with_bom, 10, &characters, &num_characters);
+
+#if HAVE_ICONV || HAVE_MULTIBYTETOWIDECHAR
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ uint8_t utf16be[] = {
+ 0, 'e',
+ 0, 0xe8,
+ 0, 0xe9,
+ 0, 0xea,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-16BE", utf16be, 8, &characters, &num_characters);
+
+#ifdef HAVE_ICONV
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ uint8_t utf16be_with_bom[] = {
+ 0xfe, 0xff,
+ 0, 'e',
+ 0, 0xe8,
+ 0, 0xe9,
+ 0, 0xea,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-16BE", utf16be_with_bom, 10, &characters, &num_characters);
+
+#ifdef HAVE_ICONV
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ uint8_t utf16le[] = {
+ 'e', 0,
+ 0xe8, 0,
+ 0xe9, 0,
+ 0xea, 0,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-16LE", utf16le, 8, &characters, &num_characters);
+
+#ifdef HAVE_ICONV
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ uint8_t utf16le_with_bom[] = {
+ 0xff, 0xfe,
+ 'e', 0,
+ 0xe8, 0,
+ 0xe9, 0,
+ 0xea, 0,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-16LE", utf16le_with_bom, 10, &characters, &num_characters);
+
+#ifdef HAVE_ICONV
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ /* bogus encoding */
+ uint8_t bogus[] = {'b', 'o', 'g', 'u', 's'};
+
+ result = jscoverage_bytes_to_characters("BOGUS", bogus, 5, &characters, &num_characters);
+
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+
+#ifdef HAVE_ICONV
+ /* malformed US-ASCII */
+ /* NOTE: Windows simply discards the high bit */
+ uint8_t malformed_ascii[] = {
+ 'e',
+ 0xe8,
+ 0xe9,
+ 0xea,
+ };
+
+ result = jscoverage_bytes_to_characters("US-ASCII", malformed_ascii, 4, &characters, &num_characters);
+
+ assert(result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE);
+#endif
+
+ /* malformed UTF-8 */
+ uint8_t malformed_utf8[] = {
+ 'e',
+ 0xe8,
+ 0xe9,
+ 0xea,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-8", malformed_utf8, 4, &characters, &num_characters);
+
+#if HAVE_ICONV || HAVE_MULTIBYTETOWIDECHAR
+ assert(result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/encodings.sh b/tools/node_modules/expresso/deps/jscoverage/tests/encodings.sh
new file mode 100755
index 0000000..5db0f13
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/encodings.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# encodings.sh - test handling different character encodings
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./encodings
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/exclude-requires-argument.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/exclude-requires-argument.expected.err
new file mode 100644
index 0000000..6feb597
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/exclude-requires-argument.expected.err
@@ -0,0 +1,2 @@
+jscoverage: --exclude: option requires an argument
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/fatal.sh b/tools/node_modules/expresso/deps/jscoverage/tests/fatal.sh
new file mode 100755
index 0000000..90b8d94
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/fatal.sh
@@ -0,0 +1,110 @@
+#!/bin/sh
+# fatal.sh - test various fatal errors
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr DIR DIR2 OUT ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR DIR2
+
+$VALGRIND jscoverage javascript-xml DIR > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr javascript-xml.expected.err ERR
+
+rm -fr DIR
+
+$VALGRIND jscoverage javascript-invalid DIR > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr javascript-invalid.expected.err ERR
+
+rm -fr DIR
+
+$VALGRIND jscoverage javascript-setter DIR > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr javascript-setter.expected.err ERR
+
+rm -fr DIR
+
+$VALGRIND jscoverage 1 2 3 > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr too-many-arguments.expected.err ERR
+
+rm -fr DIR
+
+$VALGRIND jscoverage --no-instrument > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr no-instrument-requires-argument.expected.err ERR
+
+$VALGRIND jscoverage --exclude > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr exclude-requires-argument.expected.err ERR
+
+$VALGRIND jscoverage --encoding > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr encoding-requires-argument.expected.err ERR
+
+# first arg does not exist
+rm -f foo
+$VALGRIND jscoverage foo bar > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+# diff --strip-trailing-cr source-does-not-exist.expected.err ERR
+
+# first arg is file
+touch foo
+$VALGRIND jscoverage foo bar > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+# diff --strip-trailing-cr source-is-file.expected.err ERR
+rm foo
+
+# second arg is file
+rm -fr bar
+touch bar
+$VALGRIND jscoverage javascript bar > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+# diff --strip-trailing-cr destination-is-file.expected.err ERR
+rm bar
+
+# second arg is directory, but not from previous run
+rm -fr bar
+mkdir bar
+touch bar/foo
+$VALGRIND jscoverage javascript bar > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+# diff --strip-trailing-cr destination-is-existing-directory.expected.err ERR
+rm -fr bar
+
+# huge JavaScript file
+mkdir -p DIR
+perl -e 'for (1 .. 65536) {print "x = $_\n";}' > DIR/big.js
+$VALGRIND jscoverage DIR DIR2 > OUT 2> ERR && exit 1
+echo 'jscoverage: file big.js contains more than 65,535 lines' | diff --strip-trailing-cr - ERR
+
+rm -fr DIR DIR2 OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.c b/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.c
new file mode 100644
index 0000000..ef5d7b3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.c
@@ -0,0 +1,53 @@
+/*
+ gethostbyname.c - test host lookup
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "http-server.h"
+
+int main(int argc, char ** argv) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ if (argc < 2) {
+ exit(EXIT_FAILURE);
+ }
+
+ struct in_addr a;
+ if (xgethostbyname(argv[1], &a) != 0) {
+ exit(EXIT_FAILURE);
+ }
+ char * result = inet_ntoa(a);
+ printf("%s\n", result);
+
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.sh b/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.sh
new file mode 100755
index 0000000..eae74e3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# gethostbyname.sh - test host lookup
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+echo 127.0.0.1 > EXPECTED
+./gethostbyname localhost > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+! ./gethostbyname foo
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/help.sh b/tools/node_modules/expresso/deps/jscoverage/tests/help.sh
new file mode 100755
index 0000000..5aaa31a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/help.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+# help.sh - test `--help' option
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr OUT ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+$VALGRIND jscoverage --help > OUT 2> ERR
+test -s OUT
+test ! -s ERR
+diff --strip-trailing-cr ../jscoverage-help.txt OUT
+
+$VALGRIND jscoverage -h > OUT 2> ERR
+test -s OUT
+test ! -s ERR
+diff --strip-trailing-cr ../jscoverage-help.txt OUT
+
+rm -fr OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-body.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-body.c
new file mode 100644
index 0000000..9985c62
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-body.c
@@ -0,0 +1,98 @@
+/*
+ http-client-bad-body.c - HTTP client that outputs a bad body
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#include <unistd.h>
+
+#include "http-server.h"
+#include "util.h"
+
+int main(int argc, char ** argv) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ int result;
+
+ if (argc < 3) {
+ fprintf(stderr, "Usage: %s PORT URL\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ uint16_t connect_port = atoi(argv[1]);
+ char * url = argv[2];
+ char * host;
+ uint16_t port;
+ char * abs_path;
+ char * query;
+ result = URL_parse(url, &host, &port, &abs_path, &query);
+ assert(result == 0);
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(connect_port);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ result = connect(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ /* send request */
+ char * message;
+ xasprintf(&message, "POST %s HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n\r\nHello\n", url);
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(s, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ /* read response */
+ for (;;) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(s, buffer, 8192, 0);
+ assert(bytes_read >= 0);
+ if (bytes_read == 0) {
+ break;
+ }
+ }
+
+ closesocket(s);
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-url.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-url.c
new file mode 100644
index 0000000..fdb917b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-url.c
@@ -0,0 +1,77 @@
+/*
+ http-client-bad-url.c - HTTP client that sends bad URLs
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "http-server.h"
+#include "util.h"
+
+int main(int argc, char ** argv) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ int result;
+
+ if (argc < 3) {
+ fprintf(stderr, "Usage: %s PORT URL\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ uint16_t connect_port = atoi(argv[1]);
+ char * url = argv[2];
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(connect_port);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ result = connect(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ /* send request */
+ char * message;
+ xasprintf(&message, "GET %s HTTP/1.1\r\nConnection: close\r\n\r\n", url);
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(s, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ /* read response */
+ for (;;) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(s, buffer, 8192, 0);
+ assert(bytes_read >= 0);
+ if (bytes_read == 0) {
+ break;
+ }
+ }
+
+ closesocket(s);
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-client-close-after-request.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-close-after-request.c
new file mode 100644
index 0000000..e67431a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-close-after-request.c
@@ -0,0 +1,57 @@
+/*
+ http-client-close-after-request.c - HTTP client that closes connection after sending request
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "http-server.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ int result;
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ result = connect(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ /* send request */
+ char * message = "GET http://127.0.0.1:8000/ HTTP/1.1\r\nConnection: close\r\nHost: 127.0.0.1:8000\r\n\r\n";
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(s, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ closesocket(s);
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-body.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-body.c
new file mode 100644
index 0000000..f8c362d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-body.c
@@ -0,0 +1,97 @@
+/*
+ http-server-bad-body.c - HTTP server that outputs a bad body
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "http-server.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ int optval = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ int result = bind(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ result = listen(s, 5);
+ assert(result == 0);
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t size = sizeof(client_address);
+ int client_socket = accept(s, (struct sockaddr *) &client_address, &size);
+ assert(client_socket > 0);
+
+ /* read request */
+ int state = 0;
+ while (state != 2) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(client_socket, buffer, 8192, 0);
+ assert(bytes_read > 0);
+ for (int i = 0; i < bytes_read && state != 2; i++) {
+ uint8_t byte = buffer[i];
+ switch (state) {
+ case 0:
+ if (byte == '\n') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ case 1:
+ if (byte == '\n') {
+ state = 2;
+ }
+ else if (byte == '\r') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ }
+ }
+ }
+
+ /* send response */
+ char * message = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-type: text/html\r\nTransfer-Encoding: chunked\r\n\r\nHello\n";
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(client_socket, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ closesocket(client_socket);
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-headers.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-headers.c
new file mode 100644
index 0000000..bbef80f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-headers.c
@@ -0,0 +1,97 @@
+/*
+ http-server-bad-headers.c - HTTP server that outputs bad headers
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "http-server.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ int optval = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ int result = bind(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ result = listen(s, 5);
+ assert(result == 0);
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t size = sizeof(client_address);
+ int client_socket = accept(s, (struct sockaddr *) &client_address, &size);
+ assert(client_socket > 0);
+
+ /* read request */
+ int state = 0;
+ while (state != 2) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(client_socket, buffer, 8192, 0);
+ assert(bytes_read > 0);
+ for (int i = 0; i < bytes_read && state != 2; i++) {
+ uint8_t byte = buffer[i];
+ switch (state) {
+ case 0:
+ if (byte == '\n') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ case 1:
+ if (byte == '\n') {
+ state = 2;
+ }
+ else if (byte == '\r') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ }
+ }
+ }
+
+ /* send response */
+ char * message = "HTTP/1.1 200 OK\r\nHere is some bogosity!\r\nConnection: close\r\nContent-type: text/html\r\n\r\nHello\n";
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(client_socket, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ closesocket(client_socket);
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-server-charset.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-charset.c
new file mode 100644
index 0000000..7ea7bb8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-charset.c
@@ -0,0 +1,144 @@
+/*
+ http-server-charset.c - HTTP server that outputs different charset values
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "http-server.h"
+#include "stream.h"
+#include "util.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ int optval = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ int result = bind(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ result = listen(s, 5);
+ assert(result == 0);
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t size = sizeof(client_address);
+ int client_socket = accept(s, (struct sockaddr *) &client_address, &size);
+ assert(client_socket > 0);
+
+ /* read request */
+ Stream * stream = Stream_new(0);
+ int state = 0;
+ while (state != 2) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(client_socket, buffer, 8192, 0);
+ assert(bytes_read > 0);
+ Stream_write(stream, buffer, bytes_read);
+ for (int i = 0; i < bytes_read && state != 2; i++) {
+ uint8_t byte = buffer[i];
+ switch (state) {
+ case 0:
+ if (byte == '\n') {
+ state = 1;
+ }
+ break;
+ case 1:
+ if (byte == '\n') {
+ state = 2;
+ }
+ else if (byte == '\r') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ char * method;
+ char * url;
+ char * request_line = (char *) stream->data;
+ char * first_space = strchr(request_line, ' ');
+ assert(first_space != NULL);
+ char * second_space = strchr(first_space + 1, ' ');
+ assert(second_space != NULL);
+ method = xstrndup(request_line, first_space - request_line);
+ url = xstrndup(first_space + 1, second_space - (first_space + 1));
+
+ /* send response */
+ char * message;
+ if (strcmp(url, "http://127.0.0.1:8000/utf-8.js") == 0 || strcmp(url, "/utf-8.js") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/javascript; charset=UTF-8\r\n"
+ "\r\n"
+ "var s = 'eèéê';\n"
+ "var r = /eèéê/;\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/iso-8859-1.js") == 0 || strcmp(url, "/iso-8859-1.js") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/javascript; charset=ISO-8859-1\r\n"
+ "\r\n"
+ "var s = 'e';\n"
+ "var r = /e/;\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/bogus.js") == 0 || strcmp(url, "/bogus.js") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/javascript; charset=BOGUS\r\n"
+ "\r\n"
+ "var s = 'e';\n"
+ "var r = /e/;\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/malformed.js") == 0 || strcmp(url, "/malformed.js") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/javascript; charset=UTF-8\r\n"
+ "\r\n"
+ "var s = 'e';\n"
+ "var r = /e/;\n";
+ }
+ else {
+ abort();
+ }
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(client_socket, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ closesocket(client_socket);
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-server-chunked.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-chunked.c
new file mode 100644
index 0000000..909cb07
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-chunked.c
@@ -0,0 +1,196 @@
+/*
+ http-server-chunked.c - HTTP server that outputs chunked response
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "http-server.h"
+#include "stream.h"
+#include "util.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ int optval = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ int result = bind(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ result = listen(s, 5);
+ assert(result == 0);
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t size = sizeof(client_address);
+ int client_socket = accept(s, (struct sockaddr *) &client_address, &size);
+ assert(client_socket > 0);
+
+ /* read request */
+ Stream * stream = Stream_new(0);
+ int state = 0;
+ while (state != 2) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(client_socket, buffer, 8192, 0);
+ assert(bytes_read > 0);
+ Stream_write(stream, buffer, bytes_read);
+ for (int i = 0; i < bytes_read && state != 2; i++) {
+ uint8_t byte = buffer[i];
+ switch (state) {
+ case 0:
+ if (byte == '\n') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ case 1:
+ if (byte == '\n') {
+ state = 2;
+ }
+ else if (byte == '\r') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ char * method;
+ char * url;
+ char * request_line = (char *) stream->data;
+ char * first_space = strchr(request_line, ' ');
+ assert(first_space != NULL);
+ char * second_space = strchr(first_space + 1, ' ');
+ assert(second_space != NULL);
+ method = xstrndup(request_line, first_space - request_line);
+ url = xstrndup(first_space + 1, second_space - (first_space + 1));
+
+ /* send response */
+ char * message;
+ if (strcmp(url, "http://127.0.0.1:8000/lower") == 0 || strcmp(url, "/lower") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/html\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "b\r\n"
+ "hello world\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "\r\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/upper") == 0 || strcmp(url, "/upper") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/html\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "B\r\n"
+ "HELLO WORLD\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "\r\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/javascript") == 0 || strcmp(url, "/javascript") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-Type: text/javascript\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "B\r\n"
+ "hello = 10;\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "\r\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/trailer") == 0 || strcmp(url, "/trailer") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/html\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "b\r\n"
+ "hello world\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "X-Foo: bar\r\n"
+ "X-Bar: foo\r\n"
+ "\r\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/overflow") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/html\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "100000000\r\n"
+ "hello world\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "\r\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/multiple") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/html\r\n"
+ "Transfer-Encoding: foo; foo = bar, bar; foo = \"bar\"\r\n"
+ "Transfer-Encoding: foobar; foo = \"\\\"bar\\\"\", chunked\r\n"
+ "\r\n"
+ "b\r\n"
+ "hello world\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "\r\n";
+ }
+ else {
+ abort();
+ }
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(client_socket, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ closesocket(client_socket);
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-server-close-immediately.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-close-immediately.c
new file mode 100644
index 0000000..b8c7176
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-close-immediately.c
@@ -0,0 +1,60 @@
+/*
+ http-server-close-immediately.c - HTTP server that closes connection immediately
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "http-server.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ int optval = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ int result = bind(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ result = listen(s, 5);
+ assert(result == 0);
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t size = sizeof(client_address);
+ int client_socket = accept(s, (struct sockaddr *) &client_address, &size);
+ assert(client_socket > 0);
+ closesocket(client_socket);
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.expected.err
new file mode 100644
index 0000000..91538d9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.expected.err
@@ -0,0 +1,2 @@
+jscoverage: unrecognized option `--foo'
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.sh b/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.sh
new file mode 100755
index 0000000..bf9607c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+# invalid-option.sh - test invalid option
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr OUT ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+$VALGRIND jscoverage --foo > OUT 2> ERR && exit 1
+test ! -s OUT
+diff --strip-trailing-cr invalid-option.expected.err ERR
+
+rm -fr OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.expected/ignore.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.expected/ignore.js
new file mode 100644
index 0000000..824f204
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.expected/ignore.js
@@ -0,0 +1,106 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['ignore.js']) {
+ _$jscoverage['ignore.js'] = [];
+ _$jscoverage['ignore.js'][1] = 0;
+ _$jscoverage['ignore.js'][3] = 0;
+ _$jscoverage['ignore.js'][4] = 0;
+ _$jscoverage['ignore.js'][6] = 0;
+ _$jscoverage['ignore.js'][7] = 0;
+ _$jscoverage['ignore.js'][10] = 0;
+ _$jscoverage['ignore.js'][14] = 0;
+ _$jscoverage['ignore.js'][16] = 0;
+ _$jscoverage['ignore.js'][17] = 0;
+ _$jscoverage['ignore.js'][22] = 0;
+ _$jscoverage['ignore.js'][23] = 0;
+ _$jscoverage['ignore.js'][27] = 0;
+ _$jscoverage['ignore.js'][32] = 0;
+ _$jscoverage['ignore.js'][34] = 0;
+ _$jscoverage['ignore.js'][35] = 0;
+ _$jscoverage['ignore.js'][37] = 0;
+ _$jscoverage['ignore.js'][38] = 0;
+ _$jscoverage['ignore.js'][42] = 0;
+ _$jscoverage['ignore.js'][43] = 0;
+ _$jscoverage['ignore.js'][44] = 0;
+}
+_$jscoverage['ignore.js'].conditionals = [];
+_$jscoverage['ignore.js'][1]++;
+function createRequest() {
+ _$jscoverage['ignore.js'][3]++;
+ if (window.XMLHttpRequest) {
+ _$jscoverage['ignore.js'].conditionals[6] = 11;
+ _$jscoverage['ignore.js'][4]++;
+ return new XMLHttpRequest();
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[4] = 5;
+ _$jscoverage['ignore.js'][6]++;
+ if (window.ActiveXObject) {
+ _$jscoverage['ignore.js'].conditionals[9] = 11;
+ _$jscoverage['ignore.js'][7]++;
+ return new ActiveXObject("Msxml2.XMLHTTP");
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[7] = 8;
+ _$jscoverage['ignore.js'][10]++;
+ throw "no XMLHttpRequest implementation available";
+ }
+ }
+}
+_$jscoverage['ignore.js'][14]++;
+function createRequest2() {
+ _$jscoverage['ignore.js'][16]++;
+ if (window.XMLHttpRequest) {
+ _$jscoverage['ignore.js'][17]++;
+ return new XMLHttpRequest();
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[17] = 18;
+ }
+ _$jscoverage['ignore.js'][22]++;
+ if (window.ActiveXObject) {
+ _$jscoverage['ignore.js'][23]++;
+ return new ActiveXObject("Msxml2.XMLHTTP");
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[23] = 24;
+ }
+ _$jscoverage['ignore.js'][27]++;
+ throw "no XMLHttpRequest implementation available";
+}
+_$jscoverage['ignore.js'][32]++;
+function log(s) {
+ _$jscoverage['ignore.js'][34]++;
+ if (window.console && window.console.log) {
+ _$jscoverage['ignore.js'].conditionals[37] = 39;
+ _$jscoverage['ignore.js'][35]++;
+ console.log(s);
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[35] = 36;
+ _$jscoverage['ignore.js'][37]++;
+ if (window.opera && window.opera.postError) {
+ _$jscoverage['ignore.js'][38]++;
+ opera.postError(s);
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[38] = 39;
+ }
+ }
+}
+_$jscoverage['ignore.js'][42]++;
+var request = createRequest();
+_$jscoverage['ignore.js'][43]++;
+var request2 = createRequest2();
+_$jscoverage['ignore.js'][44]++;
+log("created requests");
+if (!( 0)) {
+ _$jscoverage['ignore.js'].conditionals[26] = 28;
+}
+if (!( ! window.XMLHttpRequest)) {
+ _$jscoverage['ignore.js'].conditionals[20] = 29;
+}
+_$jscoverage['ignore.js'].source = ["function createRequest() {","//#JSCOVERAGE_IF"," if (window.XMLHttpRequest) {"," return new XMLHttpRequest();"," }"," else if (window.ActiveXObject) {"," return new ActiveXObject('Msxml2.XMLHTTP');"," }"," else {"," throw 'no XMLHttpRequest implementation available';"," }","}","","function createRequest2() {","//#JSCOVERAGE_IF"," if (window.XMLHttpRequest) {"," return new XMLHttpRequest();"," }","","//#JSCOVERAGE_IF ! window.XMLHttpRequest","//#JSCOVERAGE_IF"," if (window.ActiveXObject) {"," return new ActiveXObject('Msxml2.XMLHTTP');"," }","","//#JSCOVERAGE_IF 0"," throw 'no XMLHttpRequest implementation available';","//#JSCOVERAGE_ENDIF","//#JSCOVERAGE_ENDIF","}","","function log(s) {","//#JSCOVERAGE_IF"," if (window.console &amp;&amp; window.console.log) {"," console.log(s);"," }"," else if (window.opera &amp;&amp; window.opera.postError) {"," opera.postError(s);"," }","}","","var request = createRequest();","var request2 = createRequest2();","log('created requests');"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.sh b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.sh
new file mode 100755
index 0000000..ec1edbd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+# javascript-ignore.sh - test ignoring lines of code
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr DIR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR
+$VALGRIND jscoverage --no-highlight javascript-ignore DIR
+diff -u --strip-trailing-cr javascript-ignore.expected/ignore.js DIR/ignore.js
+rm -fr DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore/ignore.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore/ignore.js
new file mode 100644
index 0000000..8579ff0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore/ignore.js
@@ -0,0 +1,44 @@
+function createRequest() {
+//#JSCOVERAGE_IF
+ if (window.XMLHttpRequest) {
+ return new XMLHttpRequest();
+ }
+ else if (window.ActiveXObject) {
+ return new ActiveXObject('Msxml2.XMLHTTP');
+ }
+ else {
+ throw 'no XMLHttpRequest implementation available';
+ }
+}
+
+function createRequest2() {
+//#JSCOVERAGE_IF
+ if (window.XMLHttpRequest) {
+ return new XMLHttpRequest();
+ }
+
+//#JSCOVERAGE_IF ! window.XMLHttpRequest
+//#JSCOVERAGE_IF
+ if (window.ActiveXObject) {
+ return new ActiveXObject('Msxml2.XMLHTTP');
+ }
+
+//#JSCOVERAGE_IF 0
+ throw 'no XMLHttpRequest implementation available';
+//#JSCOVERAGE_ENDIF
+//#JSCOVERAGE_ENDIF
+}
+
+function log(s) {
+//#JSCOVERAGE_IF
+ if (window.console && window.console.log) {
+ console.log(s);
+ }
+ else if (window.opera && window.opera.postError) {
+ opera.postError(s);
+ }
+}
+
+var request = createRequest();
+var request2 = createRequest2();
+log('created requests');
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid.expected.err
new file mode 100644
index 0000000..bd39cb1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid.expected.err
@@ -0,0 +1,2 @@
+jscoverage:javascript-invalid.js:1: SyntaxError: missing ; before statement
+jscoverage: parse error in file javascript-invalid.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid/javascript-invalid.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid/javascript-invalid.js
new file mode 100644
index 0000000..74b863c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid/javascript-invalid.js
@@ -0,0 +1 @@
+x y
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter.expected.err
new file mode 100644
index 0000000..d353089
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter.expected.err
@@ -0,0 +1 @@
+jscoverage:javascript-setter.js:2: expected function
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter/javascript-setter.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter/javascript-setter.js
new file mode 100644
index 0000000..715bc1e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter/javascript-setter.js
@@ -0,0 +1,3 @@
+var obj = {
+ x setter: 3
+};
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.expected/javascript-utf-8.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.expected/javascript-utf-8.js
new file mode 100644
index 0000000..fa04a2c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.expected/javascript-utf-8.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-utf-8.js']) {
+ _$jscoverage['javascript-utf-8.js'] = [];
+ _$jscoverage['javascript-utf-8.js'][1] = 0;
+ _$jscoverage['javascript-utf-8.js'][2] = 0;
+}
+_$jscoverage['javascript-utf-8.js'][1]++;
+var s = "e\u00e8\u00e9\u00ea";
+_$jscoverage['javascript-utf-8.js'][2]++;
+var r = /e\u00e8\u00e9\u00ea/;
+_$jscoverage['javascript-utf-8.js'].source = ["var s = 'e&#232;&#233;&#234;';","var r = /e&#232;&#233;&#234;/;"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.sh b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.sh
new file mode 100755
index 0000000..bada1bc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+# javascript-utf-8.sh - test a JavaScript file with UTF-8 encoding
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr DIR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if jscoverage-server --version | grep -q 'iconv\|MultiByteToWideChar'
+then
+ character_encoding_support=yes
+else
+ character_encoding_support=no
+fi
+
+rm -fr DIR
+case "$character_encoding_support" in
+ yes)
+ $VALGRIND jscoverage --no-highlight --encoding=UTF-8 javascript-utf-8 DIR
+ diff -u --strip-trailing-cr javascript-utf-8.expected/javascript-utf-8.js DIR/javascript-utf-8.js
+ ;;
+ *)
+ ! $VALGRIND jscoverage --no-highlight --encoding=UTF-8 javascript-utf-8 DIR > OUT 2> ERR
+ echo "jscoverage: encoding UTF-8 not supported" | diff - ERR
+ ;;
+esac
+rm -fr DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8/javascript-utf-8.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8/javascript-utf-8.js
new file mode 100644
index 0000000..799cd6e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8/javascript-utf-8.js
@@ -0,0 +1,2 @@
+var s = 'eèéê';
+var r = /eèéê/;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml.expected.err
new file mode 100644
index 0000000..017c45e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml.expected.err
@@ -0,0 +1 @@
+jscoverage:javascript-xml.js:3: unsupported node type (75)
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml/javascript-xml.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml/javascript-xml.js
new file mode 100644
index 0000000..a802d93
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml/javascript-xml.js
@@ -0,0 +1,8 @@
+// ECMA 357 11.1.4
+// an XML object representing a person with a name and age
+var person = <person><name>John</name><age>25</age></person>;
+// a variable containing an XML object representing two employees
+var e = <employees>
+ <employee id="1"><name>Joe</name><age>20</age></employee>
+ <employee id="2"><name>Sue</name><age>30</age></employee>
+</employees>;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-array-comprehension.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-array-comprehension.js
new file mode 100644
index 0000000..4ecdc1f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-array-comprehension.js
@@ -0,0 +1,32 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-array-comprehension.js']) {
+ _$jscoverage['javascript-array-comprehension.js'] = [];
+ _$jscoverage['javascript-array-comprehension.js'][3] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][4] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][5] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][8] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][9] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][12] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][14] = 0;
+}
+_$jscoverage['javascript-array-comprehension.js'][3]++;
+function range(begin, end) {
+ _$jscoverage['javascript-array-comprehension.js'][4]++;
+ for (let i = begin; i < end; ++i) {
+ _$jscoverage['javascript-array-comprehension.js'][5]++;
+ yield i;
+}
+}
+_$jscoverage['javascript-array-comprehension.js'][8]++;
+var ten_squares = [i * i for each (i in range(0, 10))];
+_$jscoverage['javascript-array-comprehension.js'][9]++;
+var evens = [i for each (i in range(0, 21)) if (i % 2 == 0)];
+_$jscoverage['javascript-array-comprehension.js'][12]++;
+var optimized = [1 for each (i in x) if (0)];
+_$jscoverage['javascript-array-comprehension.js'][14]++;
+[i for each (a in x) for each (b in y)];
+_$jscoverage['javascript-array-comprehension.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.7</span>","","<span class=\"k\">function</span> range<span class=\"k\">(</span>begin<span class=\"k\">,</span> end<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">for</span> <span class=\"k\">(</span><span class=\"k\">let</span> i <span class=\"k\">=</span> begin<span class=\"k\">;</span> i <span class=\"k\">&lt;</span> end<span class=\"k\">;</span> <span class=\"k\">++</span>i<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">yield</span> i<span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>","<span class=\"k\">var</span> ten_squares <span class=\"k\">=</span> <span class=\"k\">[</span>i <span class=\"k\">*</span> i <span class=\"k\">for</span> each <span class=\"k\">(</span>i <span class=\"k\">in</span> range<span class=\"k\">(</span><span class=\"s\">0</span><span class=\"k\">,</span> <span class=\"s\">10</span><span class=\"k\">))];</span>","<span class=\"k\">var</span> evens <span class=\"k\">=</span> <span class=\"k\">[</span>i <span class=\"k\">for</span> each <span class=\"k\">(</span>i <span class=\"k\">in</span> range<span class=\"k\">(</span><span class=\"s\">0</span><span class=\"k\">,</span> <span class=\"s\">21</span><span class=\"k\">))</span> <span class=\"k\">if</span> <span class=\"k\">(</span>i <span class=\"k\">%</span> <span class=\"s\">2</span> <span class=\"k\">==</span> <span class=\"s\">0</span><span class=\"k\">)];</span>","","<span class=\"c\">// test optimization</span>","<span class=\"k\">var</span> optimized <span class=\"k\">=</span> <span class=\"k\">[</span>i <span class=\"k\">for</span> each <span class=\"k\">(</span>i <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">if</span> <span class=\"k\">(</span><span class=\"s\">0</span><span class=\"k\">)];</span>","","<span class=\"k\">[</span>i <span class=\"k\">for</span> each <span class=\"k\">(</span>a <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">for</span> each <span class=\"k\">(</span>b <span class=\"k\">in</span> y<span class=\"k\">)]</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-assign.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-assign.js
new file mode 100644
index 0000000..fc3a7ec
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-assign.js
@@ -0,0 +1,51 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-assign.js']) {
+ _$jscoverage['javascript-assign.js'] = [];
+ _$jscoverage['javascript-assign.js'][1] = 0;
+ _$jscoverage['javascript-assign.js'][2] = 0;
+ _$jscoverage['javascript-assign.js'][3] = 0;
+ _$jscoverage['javascript-assign.js'][4] = 0;
+ _$jscoverage['javascript-assign.js'][5] = 0;
+ _$jscoverage['javascript-assign.js'][6] = 0;
+ _$jscoverage['javascript-assign.js'][7] = 0;
+ _$jscoverage['javascript-assign.js'][8] = 0;
+ _$jscoverage['javascript-assign.js'][9] = 0;
+ _$jscoverage['javascript-assign.js'][10] = 0;
+ _$jscoverage['javascript-assign.js'][11] = 0;
+ _$jscoverage['javascript-assign.js'][12] = 0;
+ _$jscoverage['javascript-assign.js'][13] = 0;
+ _$jscoverage['javascript-assign.js'][14] = 0;
+}
+_$jscoverage['javascript-assign.js'][1]++;
+var x = 1;
+_$jscoverage['javascript-assign.js'][2]++;
+var y = 1;
+_$jscoverage['javascript-assign.js'][3]++;
+x = y;
+_$jscoverage['javascript-assign.js'][4]++;
+x += y;
+_$jscoverage['javascript-assign.js'][5]++;
+x -= y;
+_$jscoverage['javascript-assign.js'][6]++;
+x *= y;
+_$jscoverage['javascript-assign.js'][7]++;
+x %= y;
+_$jscoverage['javascript-assign.js'][8]++;
+x <<= y;
+_$jscoverage['javascript-assign.js'][9]++;
+x >>= y;
+_$jscoverage['javascript-assign.js'][10]++;
+x >>>= y;
+_$jscoverage['javascript-assign.js'][11]++;
+x &= y;
+_$jscoverage['javascript-assign.js'][12]++;
+x |= y;
+_$jscoverage['javascript-assign.js'][13]++;
+x ^= y;
+_$jscoverage['javascript-assign.js'][14]++;
+x /= y;
+_$jscoverage['javascript-assign.js'].source = ["<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>","<span class=\"k\">var</span> y <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> y<span class=\"k\">;</span>","x <span class=\"k\">+=</span> y<span class=\"k\">;</span>","x <span class=\"k\">-=</span> y<span class=\"k\">;</span>","x <span class=\"k\">*=</span> y<span class=\"k\">;</span>","x <span class=\"k\">%=</span> y<span class=\"k\">;</span>","x <span class=\"k\">&lt;&lt;=</span> y<span class=\"k\">;</span>","x <span class=\"k\">&gt;&gt;=</span> y<span class=\"k\">;</span>","x <span class=\"k\">&gt;&gt;&gt;=</span> y<span class=\"k\">;</span>","x <span class=\"k\">&amp;=</span> y<span class=\"k\">;</span>","x <span class=\"k\">|=</span> y<span class=\"k\">;</span>","x <span class=\"k\">^=</span> y<span class=\"k\">;</span>","x <span class=\"k\">/=</span> y<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-colon.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-colon.js
new file mode 100644
index 0000000..c99da2b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-colon.js
@@ -0,0 +1,24 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-colon.js']) {
+ _$jscoverage['javascript-colon.js'] = [];
+ _$jscoverage['javascript-colon.js'][1] = 0;
+ _$jscoverage['javascript-colon.js'][4] = 0;
+ _$jscoverage['javascript-colon.js'][5] = 0;
+ _$jscoverage['javascript-colon.js'][6] = 0;
+}
+_$jscoverage['javascript-colon.js'][1]++;
+x:
+y = 0;
+_$jscoverage['javascript-colon.js'][4]++;
+y:
+{
+ _$jscoverage['javascript-colon.js'][5]++;
+ let y = 1;
+ _$jscoverage['javascript-colon.js'][6]++;
+ print(y);
+}
+_$jscoverage['javascript-colon.js'].source = ["x<span class=\"k\">:</span>"," y <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","","y<span class=\"k\">:</span> <span class=\"k\">{</span>"," <span class=\"k\">let</span> y <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"," print<span class=\"k\">(</span>y<span class=\"k\">);</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-comma.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-comma.js
new file mode 100644
index 0000000..5912427
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-comma.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-comma.js']) {
+ _$jscoverage['javascript-comma.js'] = [];
+ _$jscoverage['javascript-comma.js'][1] = 0;
+}
+_$jscoverage['javascript-comma.js'][1]++;
+x = y, y = x;
+_$jscoverage['javascript-comma.js'].source = ["x <span class=\"k\">=</span> y<span class=\"k\">,</span> y <span class=\"k\">=</span> x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-cr.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-cr.js
new file mode 100644
index 0000000..38d52fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-cr.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-cr.js']) {
+ _$jscoverage['javascript-cr.js'] = [];
+ _$jscoverage['javascript-cr.js'][4] = 0;
+}
+_$jscoverage['javascript-cr.js'][4]++;
+var x = 1;
+_$jscoverage['javascript-cr.js'].source = ["<span class=\"c\">/*</span>","<span class=\"c\">This file has CR line endings.</span>","<span class=\"c\">*/</span>","<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-crlf.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-crlf.js
new file mode 100644
index 0000000..82a2d12
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-crlf.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-crlf.js']) {
+ _$jscoverage['javascript-crlf.js'] = [];
+ _$jscoverage['javascript-crlf.js'][4] = 0;
+}
+_$jscoverage['javascript-crlf.js'][4]++;
+var x = 1;
+_$jscoverage['javascript-crlf.js'].source = ["<span class=\"c\">/*</span>","<span class=\"c\">This file has CRLF line endings.</span>","<span class=\"c\">*/</span>","<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-debugger.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-debugger.js
new file mode 100644
index 0000000..a78516e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-debugger.js
@@ -0,0 +1,21 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-debugger.js']) {
+ _$jscoverage['javascript-debugger.js'] = [];
+ _$jscoverage['javascript-debugger.js'][1] = 0;
+ _$jscoverage['javascript-debugger.js'][2] = 0;
+ _$jscoverage['javascript-debugger.js'][5] = 0;
+}
+_$jscoverage['javascript-debugger.js'][1]++;
+try {
+ _$jscoverage['javascript-debugger.js'][2]++;
+ f();
+}
+catch (e) {
+ _$jscoverage['javascript-debugger.js'][5]++;
+ debugger;
+}
+_$jscoverage['javascript-debugger.js'].source = ["<span class=\"k\">try</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">catch</span> <span class=\"k\">(</span>e<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">debugger</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dec.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dec.js
new file mode 100644
index 0000000..4ba2323
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dec.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-dec.js']) {
+ _$jscoverage['javascript-dec.js'] = [];
+ _$jscoverage['javascript-dec.js'][1] = 0;
+ _$jscoverage['javascript-dec.js'][2] = 0;
+}
+_$jscoverage['javascript-dec.js'][1]++;
+x--;
+_$jscoverage['javascript-dec.js'][2]++;
+--x;
+_$jscoverage['javascript-dec.js'].source = ["x<span class=\"k\">--;</span>","<span class=\"k\">--</span>x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-delete.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-delete.js
new file mode 100644
index 0000000..bc96a8f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-delete.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-delete.js']) {
+ _$jscoverage['javascript-delete.js'] = [];
+ _$jscoverage['javascript-delete.js'][1] = 0;
+}
+_$jscoverage['javascript-delete.js'][1]++;
+delete x;
+_$jscoverage['javascript-delete.js'].source = ["<span class=\"k\">delete</span> x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-destructuring.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-destructuring.js
new file mode 100644
index 0000000..ac3d0eb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-destructuring.js
@@ -0,0 +1,96 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-destructuring.js']) {
+ _$jscoverage['javascript-destructuring.js'] = [];
+ _$jscoverage['javascript-destructuring.js'][3] = 0;
+ _$jscoverage['javascript-destructuring.js'][5] = 0;
+ _$jscoverage['javascript-destructuring.js'][6] = 0;
+ _$jscoverage['javascript-destructuring.js'][8] = 0;
+ _$jscoverage['javascript-destructuring.js'][10] = 0;
+ _$jscoverage['javascript-destructuring.js'][11] = 0;
+ _$jscoverage['javascript-destructuring.js'][12] = 0;
+ _$jscoverage['javascript-destructuring.js'][15] = 0;
+ _$jscoverage['javascript-destructuring.js'][16] = 0;
+ _$jscoverage['javascript-destructuring.js'][17] = 0;
+ _$jscoverage['javascript-destructuring.js'][20] = 0;
+ _$jscoverage['javascript-destructuring.js'][21] = 0;
+ _$jscoverage['javascript-destructuring.js'][23] = 0;
+ _$jscoverage['javascript-destructuring.js'][24] = 0;
+ _$jscoverage['javascript-destructuring.js'][25] = 0;
+ _$jscoverage['javascript-destructuring.js'][26] = 0;
+ _$jscoverage['javascript-destructuring.js'][27] = 0;
+ _$jscoverage['javascript-destructuring.js'][30] = 0;
+ _$jscoverage['javascript-destructuring.js'][31] = 0;
+ _$jscoverage['javascript-destructuring.js'][32] = 0;
+ _$jscoverage['javascript-destructuring.js'][35] = 0;
+ _$jscoverage['javascript-destructuring.js'][37] = 0;
+ _$jscoverage['javascript-destructuring.js'][38] = 0;
+ _$jscoverage['javascript-destructuring.js'][39] = 0;
+ _$jscoverage['javascript-destructuring.js'][40] = 0;
+ _$jscoverage['javascript-destructuring.js'][41] = 0;
+}
+_$jscoverage['javascript-destructuring.js'][3]++;
+[a, b] = [b, a];
+_$jscoverage['javascript-destructuring.js'][5]++;
+function f() {
+ _$jscoverage['javascript-destructuring.js'][6]++;
+ return [1, 2];
+}
+_$jscoverage['javascript-destructuring.js'][8]++;
+[a, b] = f();
+_$jscoverage['javascript-destructuring.js'][10]++;
+for (let [name, value] in Iterator(obj)) {
+ _$jscoverage['javascript-destructuring.js'][11]++;
+ print(name);
+ _$jscoverage['javascript-destructuring.js'][12]++;
+ print(value);
+}
+_$jscoverage['javascript-destructuring.js'][15]++;
+for each (let {name: n, family: {father: f}} in people) {
+ _$jscoverage['javascript-destructuring.js'][16]++;
+ print(n);
+ _$jscoverage['javascript-destructuring.js'][17]++;
+ print(f);
+}
+_$jscoverage['javascript-destructuring.js'][20]++;
+var [a, , b] = f();
+_$jscoverage['javascript-destructuring.js'][21]++;
+[, , ,] = f();
+_$jscoverage['javascript-destructuring.js'][23]++;
+function g() {
+ _$jscoverage['javascript-destructuring.js'][24]++;
+ var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
+ _$jscoverage['javascript-destructuring.js'][25]++;
+ if (! parsedURL) {
+ _$jscoverage['javascript-destructuring.js'][26]++;
+ return null;
+ }
+ _$jscoverage['javascript-destructuring.js'][27]++;
+ var [, protocol, fullhost, fullpath] = parsedURL;
+}
+_$jscoverage['javascript-destructuring.js'][30]++;
+function h(a, [b, c], {foo: d, "bar": e}) {
+ _$jscoverage['javascript-destructuring.js'][31]++;
+ f();
+ _$jscoverage['javascript-destructuring.js'][32]++;
+ g();
+}
+_$jscoverage['javascript-destructuring.js'][35]++;
+x = (function ([a, b]) {
+ return a + b;
+});
+_$jscoverage['javascript-destructuring.js'][37]++;
+({x: x0, y: y0}) = point;
+_$jscoverage['javascript-destructuring.js'][38]++;
+var {x: x0, y: y0} = point;
+_$jscoverage['javascript-destructuring.js'][39]++;
+let ({x: x0, y: y0} = point) {
+ _$jscoverage['javascript-destructuring.js'][40]++;
+ print(x0);
+ _$jscoverage['javascript-destructuring.js'][41]++;
+ print(y0);
+}
+_$jscoverage['javascript-destructuring.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.7</span>","","<span class=\"k\">[</span>a<span class=\"k\">,</span> b<span class=\"k\">]</span> <span class=\"k\">=</span> <span class=\"k\">[</span>b<span class=\"k\">,</span> a<span class=\"k\">];</span>","","<span class=\"k\">function</span> f<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">return</span> <span class=\"k\">[</span><span class=\"s\">1</span><span class=\"k\">,</span> <span class=\"s\">2</span><span class=\"k\">];</span>","<span class=\"k\">}</span>","<span class=\"k\">[</span>a<span class=\"k\">,</span> b<span class=\"k\">]</span> <span class=\"k\">=</span> f<span class=\"k\">();</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span><span class=\"k\">let</span> <span class=\"k\">[</span>name<span class=\"k\">,</span> value<span class=\"k\">]</span> <span class=\"k\">in</span> Iterator<span class=\"k\">(</span>obj<span class=\"k\">))</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span>name<span class=\"k\">);</span>"," print<span class=\"k\">(</span>value<span class=\"k\">);</span>","<span class=\"k\">}</span>","","<span class=\"k\">for</span> each <span class=\"k\">(</span><span class=\"k\">let</span> <span class=\"k\">{</span>name<span class=\"k\">:</span> n<span class=\"k\">,</span> family<span class=\"k\">:</span> <span class=\"k\">{</span> father<span class=\"k\">:</span> f <span class=\"k\">}</span> <span class=\"k\">}</span> <span class=\"k\">in</span> people<span class=\"k\">)</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span>n<span class=\"k\">);</span>"," print<span class=\"k\">(</span>f<span class=\"k\">);</span>","<span class=\"k\">}</span>","","<span class=\"k\">var</span> <span class=\"k\">[</span>a<span class=\"k\">,</span> <span class=\"k\">,</span> b<span class=\"k\">]</span> <span class=\"k\">=</span> f<span class=\"k\">();</span>","<span class=\"k\">[,,,]</span> <span class=\"k\">=</span> f<span class=\"k\">();</span>","","<span class=\"k\">function</span> g<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> parsedURL <span class=\"k\">=</span> <span class=\"s\">/^(\\w+)\\:\\/\\/([^\\/]+)\\/(.*)$/</span><span class=\"k\">.</span>exec<span class=\"k\">(</span>url<span class=\"k\">);</span>"," <span class=\"k\">if</span> <span class=\"k\">(!</span>parsedURL<span class=\"k\">)</span>"," <span class=\"k\">return</span> <span class=\"k\">null</span><span class=\"k\">;</span>"," <span class=\"k\">var</span> <span class=\"k\">[,</span> protocol<span class=\"k\">,</span> fullhost<span class=\"k\">,</span> fullpath<span class=\"k\">]</span> <span class=\"k\">=</span> parsedURL<span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> h<span class=\"k\">(</span>a<span class=\"k\">,</span> <span class=\"k\">[</span>b<span class=\"k\">,</span> c<span class=\"k\">],</span> <span class=\"k\">{</span>foo<span class=\"k\">:</span> d<span class=\"k\">,</span> <span class=\"s\">'bar'</span><span class=\"k\">:</span> e<span class=\"k\">}</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>"," g<span class=\"k\">();</span>","<span class=\"k\">}</span>","","x <span class=\"k\">=</span> <span class=\"k\">function</span><span class=\"k\">([</span>a<span class=\"k\">,</span> b<span class=\"k\">])</span> a <span class=\"k\">+</span> b<span class=\"k\">;</span>","","<span class=\"k\">(</span><span class=\"k\">{</span>x<span class=\"k\">:</span> x0<span class=\"k\">,</span> y<span class=\"k\">:</span> y0<span class=\"k\">}</span><span class=\"k\">)</span> <span class=\"k\">=</span> point<span class=\"k\">;</span>","<span class=\"k\">var</span> <span class=\"k\">{</span>x<span class=\"k\">:</span> x0<span class=\"k\">,</span> y<span class=\"k\">:</span> y0<span class=\"k\">}</span> <span class=\"k\">=</span> point<span class=\"k\">;</span>","<span class=\"k\">let</span> <span class=\"k\">(</span><span class=\"k\">{</span>x<span class=\"k\">:</span> x0<span class=\"k\">,</span> y<span class=\"k\">:</span> y0<span class=\"k\">}</span> <span class=\"k\">=</span> point<span class=\"k\">)</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span>x0<span class=\"k\">);</span>"," print<span class=\"k\">(</span>y0<span class=\"k\">);</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-do.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-do.js
new file mode 100644
index 0000000..23d4557
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-do.js
@@ -0,0 +1,28 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-do.js']) {
+ _$jscoverage['javascript-do.js'] = [];
+ _$jscoverage['javascript-do.js'][1] = 0;
+ _$jscoverage['javascript-do.js'][3] = 0;
+ _$jscoverage['javascript-do.js'][4] = 0;
+ _$jscoverage['javascript-do.js'][8] = 0;
+ _$jscoverage['javascript-do.js'][9] = 0;
+}
+_$jscoverage['javascript-do.js'][1]++;
+var x;
+_$jscoverage['javascript-do.js'][3]++;
+do {
+ _$jscoverage['javascript-do.js'][4]++;
+ x = false;
+}
+while (x);
+_$jscoverage['javascript-do.js'][8]++;
+do {
+ _$jscoverage['javascript-do.js'][9]++;
+ x = false;
+}
+while (x);
+_$jscoverage['javascript-do.js'].source = ["<span class=\"k\">var</span> x<span class=\"k\">;</span>","","<span class=\"k\">do</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"k\">false</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">);</span>","","<span class=\"k\">do</span>"," x <span class=\"k\">=</span> <span class=\"k\">false</span><span class=\"k\">;</span>","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dot.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dot.js
new file mode 100644
index 0000000..ca91faa
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dot.js
@@ -0,0 +1,30 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-dot.js']) {
+ _$jscoverage['javascript-dot.js'] = [];
+ _$jscoverage['javascript-dot.js'][1] = 0;
+ _$jscoverage['javascript-dot.js'][2] = 0;
+ _$jscoverage['javascript-dot.js'][3] = 0;
+ _$jscoverage['javascript-dot.js'][4] = 0;
+ _$jscoverage['javascript-dot.js'][5] = 0;
+ _$jscoverage['javascript-dot.js'][7] = 0;
+ _$jscoverage['javascript-dot.js'][8] = 0;
+}
+_$jscoverage['javascript-dot.js'][1]++;
+x.y = y.x;
+_$jscoverage['javascript-dot.js'][2]++;
+x.y = y.x;
+_$jscoverage['javascript-dot.js'][3]++;
+x[y] = y[x];
+_$jscoverage['javascript-dot.js'][4]++;
+x["2y"] = y["var"];
+_$jscoverage['javascript-dot.js'][5]++;
+x[""] = y[""];
+_$jscoverage['javascript-dot.js'][7]++;
+print((123).toString());
+_$jscoverage['javascript-dot.js'][8]++;
+({}).toString();
+_$jscoverage['javascript-dot.js'].source = ["x<span class=\"k\">.</span>y <span class=\"k\">=</span> y<span class=\"k\">.</span>x<span class=\"k\">;</span>","x<span class=\"k\">[</span><span class=\"s\">\"y\"</span><span class=\"k\">]</span> <span class=\"k\">=</span> y<span class=\"k\">[</span><span class=\"s\">\"x\"</span><span class=\"k\">];</span>","x<span class=\"k\">[</span>y<span class=\"k\">]</span> <span class=\"k\">=</span> y<span class=\"k\">[</span>x<span class=\"k\">];</span>","x<span class=\"k\">[</span><span class=\"s\">'2y'</span><span class=\"k\">]</span> <span class=\"k\">=</span> y<span class=\"k\">[</span><span class=\"s\">'var'</span><span class=\"k\">];</span>","x<span class=\"k\">[</span><span class=\"s\">''</span><span class=\"k\">]</span> <span class=\"k\">=</span> y<span class=\"k\">[</span><span class=\"s\">\"\"</span><span class=\"k\">];</span>","","print<span class=\"k\">(</span><span class=\"s\">123.0</span><span class=\"k\">.</span>toString<span class=\"k\">());</span>","<span class=\"k\">(</span><span class=\"k\">{}</span><span class=\"k\">.</span>toString<span class=\"k\">());</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-empty.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-empty.js
new file mode 100644
index 0000000..646be4b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-empty.js
@@ -0,0 +1,9 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-empty.js']) {
+ _$jscoverage['javascript-empty.js'] = [];
+}
+_$jscoverage['javascript-empty.js'].source = [];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-for.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-for.js
new file mode 100644
index 0000000..07b9fc2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-for.js
@@ -0,0 +1,51 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-for.js']) {
+ _$jscoverage['javascript-for.js'] = [];
+ _$jscoverage['javascript-for.js'][1] = 0;
+ _$jscoverage['javascript-for.js'][2] = 0;
+ _$jscoverage['javascript-for.js'][5] = 0;
+ _$jscoverage['javascript-for.js'][6] = 0;
+ _$jscoverage['javascript-for.js'][9] = 0;
+ _$jscoverage['javascript-for.js'][10] = 0;
+ _$jscoverage['javascript-for.js'][13] = 0;
+ _$jscoverage['javascript-for.js'][14] = 0;
+ _$jscoverage['javascript-for.js'][17] = 0;
+ _$jscoverage['javascript-for.js'][18] = 0;
+ _$jscoverage['javascript-for.js'][20] = 0;
+ _$jscoverage['javascript-for.js'][21] = 0;
+}
+_$jscoverage['javascript-for.js'][1]++;
+for (i in x) {
+ _$jscoverage['javascript-for.js'][2]++;
+ x();
+}
+_$jscoverage['javascript-for.js'][5]++;
+for (var i in x) {
+ _$jscoverage['javascript-for.js'][6]++;
+ x();
+}
+_$jscoverage['javascript-for.js'][9]++;
+for (i = 0; i < x; i++) {
+ _$jscoverage['javascript-for.js'][10]++;
+ x();
+}
+_$jscoverage['javascript-for.js'][13]++;
+for (var j = 0; j < x; j++) {
+ _$jscoverage['javascript-for.js'][14]++;
+ x();
+}
+_$jscoverage['javascript-for.js'][17]++;
+for (i in x) {
+ _$jscoverage['javascript-for.js'][18]++;
+ x();
+}
+_$jscoverage['javascript-for.js'][20]++;
+for (i.value in x) {
+ _$jscoverage['javascript-for.js'][21]++;
+ x();
+}
+_$jscoverage['javascript-for.js'].source = ["<span class=\"k\">for</span> <span class=\"k\">(</span>i <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span><span class=\"k\">var</span> i <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span>i <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span> i <span class=\"k\">&lt;</span> x<span class=\"k\">;</span> i<span class=\"k\">++)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span><span class=\"k\">var</span> j <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span> j <span class=\"k\">&lt;</span> x<span class=\"k\">;</span> j<span class=\"k\">++)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span>i <span class=\"k\">in</span> x<span class=\"k\">)</span>"," x<span class=\"k\">();</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span>i<span class=\"k\">.</span>value <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-foreach.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-foreach.js
new file mode 100644
index 0000000..2c63a81
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-foreach.js
@@ -0,0 +1,16 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-foreach.js']) {
+ _$jscoverage['javascript-foreach.js'] = [];
+ _$jscoverage['javascript-foreach.js'][6] = 0;
+ _$jscoverage['javascript-foreach.js'][7] = 0;
+}
+_$jscoverage['javascript-foreach.js'][6]++;
+for each (var item in obj) {
+ _$jscoverage['javascript-foreach.js'][7]++;
+ sum += item;
+}
+_$jscoverage['javascript-foreach.js'].source = ["<span class=\"c\">/*</span>","<span class=\"c\">https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Object_Manipulation_Statements</span>","<span class=\"c\">https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for_each...in</span>","<span class=\"c\">*/</span>","","<span class=\"k\">for</span> each <span class=\"k\">(</span><span class=\"k\">var</span> item <span class=\"k\">in</span> obj<span class=\"k\">)</span> <span class=\"k\">{</span>"," sum <span class=\"k\">+=</span> item<span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-function.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-function.js
new file mode 100644
index 0000000..5adada1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-function.js
@@ -0,0 +1,79 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-function.js']) {
+ _$jscoverage['javascript-function.js'] = [];
+ _$jscoverage['javascript-function.js'][1] = 0;
+ _$jscoverage['javascript-function.js'][3] = 0;
+ _$jscoverage['javascript-function.js'][4] = 0;
+ _$jscoverage['javascript-function.js'][7] = 0;
+ _$jscoverage['javascript-function.js'][8] = 0;
+ _$jscoverage['javascript-function.js'][9] = 0;
+ _$jscoverage['javascript-function.js'][12] = 0;
+ _$jscoverage['javascript-function.js'][13] = 0;
+ _$jscoverage['javascript-function.js'][16] = 0;
+ _$jscoverage['javascript-function.js'][17] = 0;
+ _$jscoverage['javascript-function.js'][20] = 0;
+ _$jscoverage['javascript-function.js'][21] = 0;
+ _$jscoverage['javascript-function.js'][24] = 0;
+ _$jscoverage['javascript-function.js'][25] = 0;
+ _$jscoverage['javascript-function.js'][28] = 0;
+ _$jscoverage['javascript-function.js'][29] = 0;
+ _$jscoverage['javascript-function.js'][32] = 0;
+ _$jscoverage['javascript-function.js'][33] = 0;
+ _$jscoverage['javascript-function.js'][36] = 0;
+ _$jscoverage['javascript-function.js'][37] = 0;
+}
+_$jscoverage['javascript-function.js'][1]++;
+function x() {
+}
+_$jscoverage['javascript-function.js'][3]++;
+function x() {
+ _$jscoverage['javascript-function.js'][4]++;
+ ;
+}
+_$jscoverage['javascript-function.js'][7]++;
+function x() {
+ _$jscoverage['javascript-function.js'][8]++;
+ x();
+ _$jscoverage['javascript-function.js'][9]++;
+ return "x";
+}
+_$jscoverage['javascript-function.js'][12]++;
+function x(a) {
+ _$jscoverage['javascript-function.js'][13]++;
+ x();
+}
+_$jscoverage['javascript-function.js'][16]++;
+function x(a, b) {
+ _$jscoverage['javascript-function.js'][17]++;
+ x();
+}
+_$jscoverage['javascript-function.js'][20]++;
+x = (function () {
+ _$jscoverage['javascript-function.js'][21]++;
+ x();
+});
+_$jscoverage['javascript-function.js'][24]++;
+(function () {
+ _$jscoverage['javascript-function.js'][25]++;
+ print("x");
+})();
+_$jscoverage['javascript-function.js'][28]++;
+(function (a) {
+ _$jscoverage['javascript-function.js'][29]++;
+ print("x");
+})(1);
+_$jscoverage['javascript-function.js'][32]++;
+(function (a, b) {
+ _$jscoverage['javascript-function.js'][33]++;
+ print("x");
+})(1, 2);
+_$jscoverage['javascript-function.js'][36]++;
+(function () {
+ _$jscoverage['javascript-function.js'][37]++;
+ print("x");
+}).call(window);
+_$jscoverage['javascript-function.js'].source = ["<span class=\"k\">function</span> x<span class=\"k\">()</span> <span class=\"k\">{}</span>","","<span class=\"k\">function</span> x<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> x<span class=\"k\">()</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>"," <span class=\"k\">return</span> <span class=\"s\">'x'</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> x<span class=\"k\">(</span>a<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> x<span class=\"k\">(</span>a<span class=\"k\">,</span> b<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","x <span class=\"k\">=</span> <span class=\"k\">function</span><span class=\"k\">()</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span><span class=\"k\">;</span>","","<span class=\"k\">(</span><span class=\"k\">function</span> <span class=\"k\">()</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span><span class=\"s\">'x'</span><span class=\"k\">);</span>","<span class=\"k\">}</span><span class=\"k\">)();</span>","","<span class=\"k\">(</span><span class=\"k\">function</span> <span class=\"k\">(</span>a<span class=\"k\">)</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span><span class=\"s\">'x'</span><span class=\"k\">);</span>","<span class=\"k\">}</span><span class=\"k\">)(</span><span class=\"s\">1</span><span class=\"k\">);</span>","","<span class=\"k\">(</span><span class=\"k\">function</span> <span class=\"k\">(</span>a<span class=\"k\">,</span> b<span class=\"k\">)</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span><span class=\"s\">'x'</span><span class=\"k\">);</span>","<span class=\"k\">}</span><span class=\"k\">)(</span><span class=\"s\">1</span><span class=\"k\">,</span> <span class=\"s\">2</span><span class=\"k\">);</span>","","<span class=\"k\">(</span><span class=\"k\">function</span> <span class=\"k\">()</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span><span class=\"s\">'x'</span><span class=\"k\">);</span>","<span class=\"k\">}</span><span class=\"k\">).</span>call<span class=\"k\">(</span>window<span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator-expression.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator-expression.js
new file mode 100644
index 0000000..6ef1f11
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator-expression.js
@@ -0,0 +1,45 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-generator-expression.js']) {
+ _$jscoverage['javascript-generator-expression.js'] = [];
+ _$jscoverage['javascript-generator-expression.js'][3] = 0;
+ _$jscoverage['javascript-generator-expression.js'][4] = 0;
+ _$jscoverage['javascript-generator-expression.js'][5] = 0;
+ _$jscoverage['javascript-generator-expression.js'][6] = 0;
+ _$jscoverage['javascript-generator-expression.js'][9] = 0;
+ _$jscoverage['javascript-generator-expression.js'][12] = 0;
+ _$jscoverage['javascript-generator-expression.js'][13] = 0;
+ _$jscoverage['javascript-generator-expression.js'][14] = 0;
+ _$jscoverage['javascript-generator-expression.js'][16] = 0;
+ _$jscoverage['javascript-generator-expression.js'][18] = 0;
+}
+_$jscoverage['javascript-generator-expression.js'][3]++;
+var it = (i + 3 for (i in someObj));
+_$jscoverage['javascript-generator-expression.js'][4]++;
+try {
+ _$jscoverage['javascript-generator-expression.js'][5]++;
+ while (true) {
+ _$jscoverage['javascript-generator-expression.js'][6]++;
+ document.write(it.next() + "<br>\n");
+}
+}
+catch (err if err instanceof StopIteration) {
+ _$jscoverage['javascript-generator-expression.js'][9]++;
+ document.write("End of record.<br>\n");
+}
+_$jscoverage['javascript-generator-expression.js'][12]++;
+function handleResults(results) {
+ _$jscoverage['javascript-generator-expression.js'][13]++;
+ for (let i in results) {
+ _$jscoverage['javascript-generator-expression.js'][14]++;
+ ;
+}
+}
+_$jscoverage['javascript-generator-expression.js'][16]++;
+handleResults((i for (i in obj) if (i > 3)));
+_$jscoverage['javascript-generator-expression.js'][18]++;
+it = (1 for (a in x) for (b in y));
+_$jscoverage['javascript-generator-expression.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.8</span>","","<span class=\"k\">let</span> it <span class=\"k\">=</span> <span class=\"k\">(</span>i <span class=\"k\">+</span> <span class=\"s\">3</span> <span class=\"k\">for</span> <span class=\"k\">(</span>i <span class=\"k\">in</span> someObj<span class=\"k\">));</span>","<span class=\"k\">try</span> <span class=\"k\">{</span>"," <span class=\"k\">while</span> <span class=\"k\">(</span><span class=\"k\">true</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," document<span class=\"k\">.</span>write<span class=\"k\">(</span>it<span class=\"k\">.</span>next<span class=\"k\">()</span> <span class=\"k\">+</span> <span class=\"s\">\"&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span> <span class=\"k\">catch</span> <span class=\"k\">(</span>err <span class=\"k\">if</span> err <span class=\"k\">instanceof</span> StopIteration<span class=\"k\">)</span> <span class=\"k\">{</span>"," document<span class=\"k\">.</span>write<span class=\"k\">(</span><span class=\"s\">\"End of record.&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> handleResults<span class=\"k\">(</span> results <span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">for</span> <span class=\"k\">(</span> <span class=\"k\">let</span> i <span class=\"k\">in</span> results <span class=\"k\">)</span>"," <span class=\"k\">;</span>","<span class=\"k\">}</span>","handleResults<span class=\"k\">(</span> i <span class=\"k\">for</span> <span class=\"k\">(</span> i <span class=\"k\">in</span> obj <span class=\"k\">)</span> <span class=\"k\">if</span> <span class=\"k\">(</span> i <span class=\"k\">&gt;</span> <span class=\"s\">3</span> <span class=\"k\">)</span> <span class=\"k\">);</span>","","it <span class=\"k\">=</span> <span class=\"k\">(</span><span class=\"s\">1</span> <span class=\"k\">for</span><span class=\"k\">(</span>a <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">for</span><span class=\"k\">(</span>b <span class=\"k\">in</span> y<span class=\"k\">));</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator.js
new file mode 100644
index 0000000..fa9cece
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator.js
@@ -0,0 +1,32 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-generator.js']) {
+ _$jscoverage['javascript-generator.js'] = [];
+ _$jscoverage['javascript-generator.js'][3] = 0;
+ _$jscoverage['javascript-generator.js'][4] = 0;
+ _$jscoverage['javascript-generator.js'][5] = 0;
+ _$jscoverage['javascript-generator.js'][6] = 0;
+ _$jscoverage['javascript-generator.js'][7] = 0;
+ _$jscoverage['javascript-generator.js'][8] = 0;
+ _$jscoverage['javascript-generator.js'][9] = 0;
+}
+_$jscoverage['javascript-generator.js'][3]++;
+function fib() {
+ _$jscoverage['javascript-generator.js'][4]++;
+ var i = 0, j = 1;
+ _$jscoverage['javascript-generator.js'][5]++;
+ while (true) {
+ _$jscoverage['javascript-generator.js'][6]++;
+ yield i;
+ _$jscoverage['javascript-generator.js'][7]++;
+ var t = i;
+ _$jscoverage['javascript-generator.js'][8]++;
+ i = j;
+ _$jscoverage['javascript-generator.js'][9]++;
+ j += t;
+}
+}
+_$jscoverage['javascript-generator.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.7</span>","","<span class=\"k\">function</span> fib<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> i <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">,</span> j <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"," <span class=\"k\">while</span> <span class=\"k\">(</span><span class=\"k\">true</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">yield</span> i<span class=\"k\">;</span>"," <span class=\"k\">var</span> t <span class=\"k\">=</span> i<span class=\"k\">;</span>"," i <span class=\"k\">=</span> j<span class=\"k\">;</span>"," j <span class=\"k\">+=</span> t<span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-getter-setter.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-getter-setter.js
new file mode 100644
index 0000000..cffc83f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-getter-setter.js
@@ -0,0 +1,31 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-getter-setter.js']) {
+ _$jscoverage['javascript-getter-setter.js'] = [];
+ _$jscoverage['javascript-getter-setter.js'][1] = 0;
+ _$jscoverage['javascript-getter-setter.js'][4] = 0;
+ _$jscoverage['javascript-getter-setter.js'][7] = 0;
+ _$jscoverage['javascript-getter-setter.js'][11] = 0;
+ _$jscoverage['javascript-getter-setter.js'][14] = 0;
+ _$jscoverage['javascript-getter-setter.js'][17] = 0;
+}
+_$jscoverage['javascript-getter-setter.js'][1]++;
+var o = {_x: 123, get x () {
+ _$jscoverage['javascript-getter-setter.js'][4]++;
+ return this._x;
+}, set x (value) {
+ _$jscoverage['javascript-getter-setter.js'][7]++;
+ this._x = value;
+}};
+_$jscoverage['javascript-getter-setter.js'][11]++;
+o = {_x: 123, get x get_x() {
+ _$jscoverage['javascript-getter-setter.js'][14]++;
+ return this._x;
+}, set x set_x(value) {
+ _$jscoverage['javascript-getter-setter.js'][17]++;
+ this._x = value;
+}};
+_$jscoverage['javascript-getter-setter.js'].source = ["<span class=\"k\">var</span> o <span class=\"k\">=</span> <span class=\"k\">{</span>"," _x<span class=\"k\">:</span> <span class=\"s\">123</span><span class=\"k\">,</span>"," get x<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">return</span> <span class=\"k\">this</span><span class=\"k\">.</span>_x<span class=\"k\">;</span>"," <span class=\"k\">}</span><span class=\"k\">,</span>"," set x<span class=\"k\">(</span>value<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">this</span><span class=\"k\">.</span>_x <span class=\"k\">=</span> value<span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span><span class=\"k\">;</span>","","o <span class=\"k\">=</span> <span class=\"k\">{</span>"," _x<span class=\"k\">:</span> <span class=\"s\">123</span><span class=\"k\">,</span>"," get x get_x<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">return</span> <span class=\"k\">this</span><span class=\"k\">.</span>_x<span class=\"k\">;</span>"," <span class=\"k\">}</span><span class=\"k\">,</span>"," set x set_x<span class=\"k\">(</span>value<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">this</span><span class=\"k\">.</span>_x <span class=\"k\">=</span> value<span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-hook.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-hook.js
new file mode 100644
index 0000000..08f33d0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-hook.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-hook.js']) {
+ _$jscoverage['javascript-hook.js'] = [];
+ _$jscoverage['javascript-hook.js'][1] = 0;
+ _$jscoverage['javascript-hook.js'][2] = 0;
+}
+_$jscoverage['javascript-hook.js'][1]++;
+var x = 1;
+_$jscoverage['javascript-hook.js'][2]++;
+var y = x === 1? "x": "y";
+_$jscoverage['javascript-hook.js'].source = ["<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>","<span class=\"k\">var</span> y <span class=\"k\">=</span> x <span class=\"k\">===</span> <span class=\"s\">1</span><span class=\"k\">?</span> <span class=\"s\">\"x\"</span><span class=\"k\">:</span> <span class=\"s\">\"y\"</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-if.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-if.js
new file mode 100644
index 0000000..8559e59
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-if.js
@@ -0,0 +1,71 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-if.js']) {
+ _$jscoverage['javascript-if.js'] = [];
+ _$jscoverage['javascript-if.js'][1] = 0;
+ _$jscoverage['javascript-if.js'][3] = 0;
+ _$jscoverage['javascript-if.js'][4] = 0;
+ _$jscoverage['javascript-if.js'][6] = 0;
+ _$jscoverage['javascript-if.js'][7] = 0;
+ _$jscoverage['javascript-if.js'][10] = 0;
+ _$jscoverage['javascript-if.js'][11] = 0;
+ _$jscoverage['javascript-if.js'][13] = 0;
+ _$jscoverage['javascript-if.js'][15] = 0;
+ _$jscoverage['javascript-if.js'][16] = 0;
+ _$jscoverage['javascript-if.js'][19] = 0;
+ _$jscoverage['javascript-if.js'][22] = 0;
+ _$jscoverage['javascript-if.js'][23] = 0;
+ _$jscoverage['javascript-if.js'][25] = 0;
+ _$jscoverage['javascript-if.js'][26] = 0;
+ _$jscoverage['javascript-if.js'][29] = 0;
+}
+_$jscoverage['javascript-if.js'][1]++;
+var x = 0;
+_$jscoverage['javascript-if.js'][3]++;
+if (x) {
+ _$jscoverage['javascript-if.js'][4]++;
+ x = 0;
+}
+_$jscoverage['javascript-if.js'][6]++;
+if (x) {
+ _$jscoverage['javascript-if.js'][7]++;
+ x = 0;
+}
+_$jscoverage['javascript-if.js'][10]++;
+if (x) {
+ _$jscoverage['javascript-if.js'][11]++;
+ x = 0;
+}
+else {
+ _$jscoverage['javascript-if.js'][13]++;
+ x = 0;
+}
+_$jscoverage['javascript-if.js'][15]++;
+if (x) {
+ _$jscoverage['javascript-if.js'][16]++;
+ x = 0;
+}
+else {
+ _$jscoverage['javascript-if.js'][19]++;
+ x = 0;
+}
+_$jscoverage['javascript-if.js'][22]++;
+if (x) {
+ _$jscoverage['javascript-if.js'][23]++;
+ x = 0;
+}
+else {
+ _$jscoverage['javascript-if.js'][25]++;
+ if (x) {
+ _$jscoverage['javascript-if.js'][26]++;
+ x = 0;
+ }
+ else {
+ _$jscoverage['javascript-if.js'][29]++;
+ x = 0;
+ }
+}
+_$jscoverage['javascript-if.js'].source = ["<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">else</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","<span class=\"k\">else</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","<span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","<span class=\"k\">else</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-in.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-in.js
new file mode 100644
index 0000000..5f6b35a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-in.js
@@ -0,0 +1,19 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-in.js']) {
+ _$jscoverage['javascript-in.js'] = [];
+ _$jscoverage['javascript-in.js'][1] = 0;
+ _$jscoverage['javascript-in.js'][2] = 0;
+ _$jscoverage['javascript-in.js'][3] = 0;
+}
+_$jscoverage['javascript-in.js'][1]++;
+var x = {};
+_$jscoverage['javascript-in.js'][2]++;
+if ("a" in x) {
+ _$jscoverage['javascript-in.js'][3]++;
+ x = null;
+}
+_$jscoverage['javascript-in.js'].source = ["<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"k\">{}</span><span class=\"k\">;</span>","<span class=\"k\">if</span> <span class=\"k\">(</span><span class=\"s\">'a'</span> <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"k\">null</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-inc.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-inc.js
new file mode 100644
index 0000000..7c1730f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-inc.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-inc.js']) {
+ _$jscoverage['javascript-inc.js'] = [];
+ _$jscoverage['javascript-inc.js'][1] = 0;
+ _$jscoverage['javascript-inc.js'][2] = 0;
+}
+_$jscoverage['javascript-inc.js'][1]++;
+x++;
+_$jscoverage['javascript-inc.js'][2]++;
+++x;
+_$jscoverage['javascript-inc.js'].source = ["x<span class=\"k\">++;</span>","<span class=\"k\">++</span>x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-iso-8859-1.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-iso-8859-1.js
new file mode 100644
index 0000000..e4650a9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-iso-8859-1.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-iso-8859-1.js']) {
+ _$jscoverage['javascript-iso-8859-1.js'] = [];
+ _$jscoverage['javascript-iso-8859-1.js'][1] = 0;
+ _$jscoverage['javascript-iso-8859-1.js'][2] = 0;
+}
+_$jscoverage['javascript-iso-8859-1.js'][1]++;
+var s = "e\u00e8\u00e9\u00ea";
+_$jscoverage['javascript-iso-8859-1.js'][2]++;
+var r = /e\u00e8\u00e9\u00ea/;
+_$jscoverage['javascript-iso-8859-1.js'].source = ["<span class=\"k\">var</span> s <span class=\"k\">=</span> <span class=\"s\">'e&#232;&#233;&#234;'</span><span class=\"k\">;</span>","<span class=\"k\">var</span> r <span class=\"k\">=</span> <span class=\"s\">/e&#232;&#233;&#234;/</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lambda.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lambda.js
new file mode 100644
index 0000000..9681cd9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lambda.js
@@ -0,0 +1,14 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-lambda.js']) {
+ _$jscoverage['javascript-lambda.js'] = [];
+ _$jscoverage['javascript-lambda.js'][3] = 0;
+}
+_$jscoverage['javascript-lambda.js'][3]++;
+var square = (function (x) {
+ return x * x;
+});
+_$jscoverage['javascript-lambda.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.8</span>","","<span class=\"k\">var</span> square <span class=\"k\">=</span> <span class=\"k\">function</span><span class=\"k\">(</span>x<span class=\"k\">)</span> x <span class=\"k\">*</span> x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-let.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-let.js
new file mode 100644
index 0000000..b726ff7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-let.js
@@ -0,0 +1,148 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-let.js']) {
+ _$jscoverage['javascript-let.js'] = [];
+ _$jscoverage['javascript-let.js'][5] = 0;
+ _$jscoverage['javascript-let.js'][6] = 0;
+ _$jscoverage['javascript-let.js'][11] = 0;
+ _$jscoverage['javascript-let.js'][15] = 0;
+ _$jscoverage['javascript-let.js'][16] = 0;
+ _$jscoverage['javascript-let.js'][17] = 0;
+ _$jscoverage['javascript-let.js'][20] = 0;
+ _$jscoverage['javascript-let.js'][22] = 0;
+ _$jscoverage['javascript-let.js'][23] = 0;
+ _$jscoverage['javascript-let.js'][24] = 0;
+ _$jscoverage['javascript-let.js'][26] = 0;
+ _$jscoverage['javascript-let.js'][27] = 0;
+ _$jscoverage['javascript-let.js'][28] = 0;
+ _$jscoverage['javascript-let.js'][30] = 0;
+ _$jscoverage['javascript-let.js'][33] = 0;
+ _$jscoverage['javascript-let.js'][34] = 0;
+ _$jscoverage['javascript-let.js'][35] = 0;
+ _$jscoverage['javascript-let.js'][36] = 0;
+ _$jscoverage['javascript-let.js'][37] = 0;
+ _$jscoverage['javascript-let.js'][39] = 0;
+ _$jscoverage['javascript-let.js'][42] = 0;
+ _$jscoverage['javascript-let.js'][43] = 0;
+ _$jscoverage['javascript-let.js'][45] = 0;
+ _$jscoverage['javascript-let.js'][46] = 0;
+ _$jscoverage['javascript-let.js'][48] = 0;
+ _$jscoverage['javascript-let.js'][51] = 0;
+ _$jscoverage['javascript-let.js'][52] = 0;
+ _$jscoverage['javascript-let.js'][55] = 0;
+ _$jscoverage['javascript-let.js'][56] = 0;
+ _$jscoverage['javascript-let.js'][60] = 0;
+ _$jscoverage['javascript-let.js'][64] = 0;
+ _$jscoverage['javascript-let.js'][65] = 0;
+ _$jscoverage['javascript-let.js'][69] = 0;
+ _$jscoverage['javascript-let.js'][70] = 0;
+ _$jscoverage['javascript-let.js'][71] = 0;
+ _$jscoverage['javascript-let.js'][74] = 0;
+ _$jscoverage['javascript-let.js'][75] = 0;
+ _$jscoverage['javascript-let.js'][76] = 0;
+ _$jscoverage['javascript-let.js'][78] = 0;
+ _$jscoverage['javascript-let.js'][79] = 0;
+}
+_$jscoverage['javascript-let.js'][5]++;
+let (x = x + 10, y = 12) {
+ _$jscoverage['javascript-let.js'][6]++;
+ print(x + y + "\n");
+}
+_$jscoverage['javascript-let.js'][11]++;
+print(let(x = x + 10, y = 12) x + y + "<br>\n");
+_$jscoverage['javascript-let.js'][15]++;
+if (x > y) {
+ {
+ _$jscoverage['javascript-let.js'][16]++;
+ let gamma = 12.7 + y;
+ _$jscoverage['javascript-let.js'][17]++;
+ i = gamma * x;
+ }
+}
+_$jscoverage['javascript-let.js'][20]++;
+var list = document.getElementById("list");
+_$jscoverage['javascript-let.js'][22]++;
+for (var i = 1; i <= 5; i++) {
+ {
+ _$jscoverage['javascript-let.js'][23]++;
+ var item = document.createElement("LI");
+ _$jscoverage['javascript-let.js'][24]++;
+ item.appendChild(document.createTextNode("Item " + i));
+ _$jscoverage['javascript-let.js'][26]++;
+ let j = i;
+ _$jscoverage['javascript-let.js'][27]++;
+ item.onclick = (function (ev) {
+ _$jscoverage['javascript-let.js'][28]++;
+ alert("Item " + j + " is clicked.");
+});
+ _$jscoverage['javascript-let.js'][30]++;
+ list.appendChild(item);
+ }
+}
+_$jscoverage['javascript-let.js'][33]++;
+function varTest() {
+ _$jscoverage['javascript-let.js'][34]++;
+ var x = 31;
+ _$jscoverage['javascript-let.js'][35]++;
+ if (true) {
+ _$jscoverage['javascript-let.js'][36]++;
+ var x = 71;
+ _$jscoverage['javascript-let.js'][37]++;
+ alert(x);
+ }
+ _$jscoverage['javascript-let.js'][39]++;
+ alert(x);
+}
+_$jscoverage['javascript-let.js'][42]++;
+function letTest() {
+ _$jscoverage['javascript-let.js'][43]++;
+ var x = 31;
+ {
+ _$jscoverage['javascript-let.js'][45]++;
+ let x = 71;
+ _$jscoverage['javascript-let.js'][46]++;
+ alert(x);
+ }
+ _$jscoverage['javascript-let.js'][48]++;
+ alert(x);
+}
+_$jscoverage['javascript-let.js'][51]++;
+function letTests() {
+ _$jscoverage['javascript-let.js'][52]++;
+ var x = 10;
+ _$jscoverage['javascript-let.js'][55]++;
+ let (x = x + 20) {
+ _$jscoverage['javascript-let.js'][56]++;
+ alert(x);
+ }
+ _$jscoverage['javascript-let.js'][60]++;
+ alert(let(x = x + 20) x);
+ {
+ _$jscoverage['javascript-let.js'][64]++;
+ let x = x + 20;
+ _$jscoverage['javascript-let.js'][65]++;
+ alert(x);
+ }
+}
+_$jscoverage['javascript-let.js'][69]++;
+var x = "global";
+_$jscoverage['javascript-let.js'][70]++;
+var x = 42;
+_$jscoverage['javascript-let.js'][71]++;
+document.write(this.x + "<br>\n");
+_$jscoverage['javascript-let.js'][74]++;
+var i = 0;
+_$jscoverage['javascript-let.js'][75]++;
+for (let i = i; i < 10; i++) {
+ _$jscoverage['javascript-let.js'][76]++;
+ document.write(i + "<br>\n");
+}
+_$jscoverage['javascript-let.js'][78]++;
+for (let [name, value] in obj) {
+ _$jscoverage['javascript-let.js'][79]++;
+ document.write("Name: " + name + ", Value: " + value + "<br>\n");
+}
+_$jscoverage['javascript-let.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.7</span>","","<span class=\"c\">// let statement</span>","","<span class=\"k\">let</span> <span class=\"k\">(</span>x <span class=\"k\">=</span> x<span class=\"k\">+</span><span class=\"s\">10</span><span class=\"k\">,</span> y <span class=\"k\">=</span> <span class=\"s\">12</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span>x<span class=\"k\">+</span>y <span class=\"k\">+</span> <span class=\"s\">\"</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>","<span class=\"k\">}</span>","","<span class=\"c\">// let expressions</span>","","print<span class=\"k\">(</span> <span class=\"k\">let</span><span class=\"k\">(</span>x <span class=\"k\">=</span> x <span class=\"k\">+</span> <span class=\"s\">10</span><span class=\"k\">,</span> y <span class=\"k\">=</span> <span class=\"s\">12</span><span class=\"k\">)</span> x<span class=\"k\">+</span>y <span class=\"k\">+</span> <span class=\"s\">\"&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>","","<span class=\"c\">// let definitions</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x <span class=\"k\">&gt;</span> y<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">let</span> gamma <span class=\"k\">=</span> <span class=\"s\">12.7</span> <span class=\"k\">+</span> y<span class=\"k\">;</span>"," i <span class=\"k\">=</span> gamma <span class=\"k\">*</span> x<span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">var</span> list <span class=\"k\">=</span> document<span class=\"k\">.</span>getElementById<span class=\"k\">(</span><span class=\"s\">\"list\"</span><span class=\"k\">);</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span><span class=\"k\">var</span> i <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span> i <span class=\"k\">&lt;=</span> <span class=\"s\">5</span><span class=\"k\">;</span> i<span class=\"k\">++)</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> item <span class=\"k\">=</span> document<span class=\"k\">.</span>createElement<span class=\"k\">(</span><span class=\"s\">\"LI\"</span><span class=\"k\">);</span>"," item<span class=\"k\">.</span>appendChild<span class=\"k\">(</span>document<span class=\"k\">.</span>createTextNode<span class=\"k\">(</span><span class=\"s\">\"Item \"</span> <span class=\"k\">+</span> i<span class=\"k\">));</span>",""," <span class=\"k\">let</span> j <span class=\"k\">=</span> i<span class=\"k\">;</span>"," item<span class=\"k\">.</span>onclick <span class=\"k\">=</span> <span class=\"k\">function</span> <span class=\"k\">(</span>ev<span class=\"k\">)</span> <span class=\"k\">{</span>"," alert<span class=\"k\">(</span><span class=\"s\">\"Item \"</span> <span class=\"k\">+</span> j <span class=\"k\">+</span> <span class=\"s\">\" is clicked.\"</span><span class=\"k\">);</span>"," <span class=\"k\">}</span><span class=\"k\">;</span>"," list<span class=\"k\">.</span>appendChild<span class=\"k\">(</span>item<span class=\"k\">);</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> varTest<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">31</span><span class=\"k\">;</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span><span class=\"k\">true</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">71</span><span class=\"k\">;</span> <span class=\"c\">// same variable!</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// 71</span>"," <span class=\"k\">}</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// 71</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> letTest<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">let</span> x <span class=\"k\">=</span> <span class=\"s\">31</span><span class=\"k\">;</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span><span class=\"k\">true</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">let</span> x <span class=\"k\">=</span> <span class=\"s\">71</span><span class=\"k\">;</span> <span class=\"c\">// different variable</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// 71</span>"," <span class=\"k\">}</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// 31</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> letTests<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">let</span> x <span class=\"k\">=</span> <span class=\"s\">10</span><span class=\"k\">;</span>",""," <span class=\"c\">// let-statement</span>"," <span class=\"k\">let</span> <span class=\"k\">(</span>x <span class=\"k\">=</span> x <span class=\"k\">+</span> <span class=\"s\">20</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// 30</span>"," <span class=\"k\">}</span>",""," <span class=\"c\">// let-expression</span>"," alert<span class=\"k\">(</span><span class=\"k\">let</span> <span class=\"k\">(</span>x <span class=\"k\">=</span> x <span class=\"k\">+</span> <span class=\"s\">20</span><span class=\"k\">)</span> x<span class=\"k\">);</span> <span class=\"c\">// 30</span>",""," <span class=\"c\">// let-definition</span>"," <span class=\"k\">{</span>"," <span class=\"k\">let</span> x <span class=\"k\">=</span> x <span class=\"k\">+</span> <span class=\"s\">20</span><span class=\"k\">;</span> <span class=\"c\">// x here evaluates to undefined</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// undefined + 20 ==&gt; NaN</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>","","<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">'global'</span><span class=\"k\">;</span>","<span class=\"k\">let</span> x <span class=\"k\">=</span> <span class=\"s\">42</span><span class=\"k\">;</span>","document<span class=\"k\">.</span>write<span class=\"k\">(</span><span class=\"k\">this</span><span class=\"k\">.</span>x <span class=\"k\">+</span> <span class=\"s\">\"&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>","","<span class=\"c\">// let-scoped variables in for loops</span>","<span class=\"k\">var</span> i<span class=\"k\">=</span><span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">for</span> <span class=\"k\">(</span> <span class=\"k\">let</span> i<span class=\"k\">=</span>i <span class=\"k\">;</span> i <span class=\"k\">&lt;</span> <span class=\"s\">10</span> <span class=\"k\">;</span> i<span class=\"k\">++</span> <span class=\"k\">)</span>"," document<span class=\"k\">.</span>write<span class=\"k\">(</span>i <span class=\"k\">+</span> <span class=\"s\">\"&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span> <span class=\"k\">let</span> <span class=\"k\">[</span>name<span class=\"k\">,</span>value<span class=\"k\">]</span> <span class=\"k\">in</span> obj <span class=\"k\">)</span>"," document<span class=\"k\">.</span>write<span class=\"k\">(</span><span class=\"s\">\"Name: \"</span> <span class=\"k\">+</span> name <span class=\"k\">+</span> <span class=\"s\">\", Value: \"</span> <span class=\"k\">+</span> value <span class=\"k\">+</span> <span class=\"s\">\"&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lf.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lf.js
new file mode 100644
index 0000000..c698ede
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lf.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-lf.js']) {
+ _$jscoverage['javascript-lf.js'] = [];
+ _$jscoverage['javascript-lf.js'][4] = 0;
+}
+_$jscoverage['javascript-lf.js'][4]++;
+var x = 1;
+_$jscoverage['javascript-lf.js'].source = ["<span class=\"c\">/*</span>","<span class=\"c\">This file has LF line endings.</span>","<span class=\"c\">*/</span>","<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-new.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-new.js
new file mode 100644
index 0000000..417227a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-new.js
@@ -0,0 +1,22 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-new.js']) {
+ _$jscoverage['javascript-new.js'] = [];
+ _$jscoverage['javascript-new.js'][1] = 0;
+ _$jscoverage['javascript-new.js'][2] = 0;
+ _$jscoverage['javascript-new.js'][3] = 0;
+ _$jscoverage['javascript-new.js'][4] = 0;
+}
+_$jscoverage['javascript-new.js'][1]++;
+function X() {
+}
+_$jscoverage['javascript-new.js'][2]++;
+x = new X();
+_$jscoverage['javascript-new.js'][3]++;
+x = new X(1);
+_$jscoverage['javascript-new.js'][4]++;
+x = new X(1, 2);
+_$jscoverage['javascript-new.js'].source = ["<span class=\"k\">function</span> X<span class=\"k\">()</span> <span class=\"k\">{}</span>","x <span class=\"k\">=</span> <span class=\"k\">new</span> X<span class=\"k\">();</span>","x <span class=\"k\">=</span> <span class=\"k\">new</span> X<span class=\"k\">(</span><span class=\"s\">1</span><span class=\"k\">);</span>","x <span class=\"k\">=</span> <span class=\"k\">new</span> X<span class=\"k\">(</span><span class=\"s\">1</span><span class=\"k\">,</span> <span class=\"s\">2</span><span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-number.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-number.js
new file mode 100644
index 0000000..45a9b77
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-number.js
@@ -0,0 +1,57 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-number.js']) {
+ _$jscoverage['javascript-number.js'] = [];
+ _$jscoverage['javascript-number.js'][1] = 0;
+ _$jscoverage['javascript-number.js'][2] = 0;
+ _$jscoverage['javascript-number.js'][3] = 0;
+ _$jscoverage['javascript-number.js'][5] = 0;
+ _$jscoverage['javascript-number.js'][6] = 0;
+ _$jscoverage['javascript-number.js'][8] = 0;
+ _$jscoverage['javascript-number.js'][9] = 0;
+ _$jscoverage['javascript-number.js'][11] = 0;
+ _$jscoverage['javascript-number.js'][12] = 0;
+ _$jscoverage['javascript-number.js'][13] = 0;
+ _$jscoverage['javascript-number.js'][14] = 0;
+ _$jscoverage['javascript-number.js'][15] = 0;
+ _$jscoverage['javascript-number.js'][16] = 0;
+ _$jscoverage['javascript-number.js'][17] = 0;
+ _$jscoverage['javascript-number.js'][18] = 0;
+ _$jscoverage['javascript-number.js'][19] = 0;
+}
+_$jscoverage['javascript-number.js'][1]++;
+x = 1;
+_$jscoverage['javascript-number.js'][2]++;
+y = 2;
+_$jscoverage['javascript-number.js'][3]++;
+z = 10.5;
+_$jscoverage['javascript-number.js'][5]++;
+a = Number.POSITIVE_INFINITY;
+_$jscoverage['javascript-number.js'][6]++;
+a = Number.NEGATIVE_INFINITY;
+_$jscoverage['javascript-number.js'][8]++;
+a = 0;
+_$jscoverage['javascript-number.js'][9]++;
+a = -0;
+_$jscoverage['javascript-number.js'][11]++;
+a = Number.NaN;
+_$jscoverage['javascript-number.js'][12]++;
+a = Number.NaN;
+_$jscoverage['javascript-number.js'][13]++;
+a = 0 / (-0);
+_$jscoverage['javascript-number.js'][14]++;
+a = Number.NaN;
+_$jscoverage['javascript-number.js'][15]++;
+a = (-0) / 0;
+_$jscoverage['javascript-number.js'][16]++;
+a = Number.NaN;
+_$jscoverage['javascript-number.js'][17]++;
+a = -0 / (-0);
+_$jscoverage['javascript-number.js'][18]++;
+a = (-0) / -0;
+_$jscoverage['javascript-number.js'][19]++;
+a = (-0) / (-0);
+_$jscoverage['javascript-number.js'].source = ["x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>","y <span class=\"k\">=</span> <span class=\"s\">2</span><span class=\"k\">;</span>","z <span class=\"k\">=</span> <span class=\"s\">10.5</span><span class=\"k\">;</span>","","a <span class=\"k\">=</span> <span class=\"s\">1</span> <span class=\"k\">/</span> <span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">-</span><span class=\"s\">1</span> <span class=\"k\">/</span> <span class=\"s\">0</span><span class=\"k\">;</span>","","a <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">-</span><span class=\"s\">0</span><span class=\"k\">;</span>","","a <span class=\"k\">=</span> <span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"k\">-</span><span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">);</span>","a <span class=\"k\">=</span> <span class=\"k\">-</span><span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">)</span> <span class=\"k\">/</span> <span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">-</span><span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"k\">-</span><span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">-</span><span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">);</span>","a <span class=\"k\">=</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">)</span> <span class=\"k\">/</span> <span class=\"k\">-</span><span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">)</span> <span class=\"k\">/</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-object.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-object.js
new file mode 100644
index 0000000..b3cf03f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-object.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-object.js']) {
+ _$jscoverage['javascript-object.js'] = [];
+ _$jscoverage['javascript-object.js'][1] = 0;
+ _$jscoverage['javascript-object.js'][2] = 0;
+}
+_$jscoverage['javascript-object.js'][1]++;
+x = /x\(\)\\\//i;
+_$jscoverage['javascript-object.js'][2]++;
+y = /\u0001\u002f/gm;
+_$jscoverage['javascript-object.js'].source = ["x <span class=\"k\">=</span> <span class=\"s\">/x\\(\\)\\\\\\//i</span><span class=\"k\">;</span>","y <span class=\"k\">=</span> <span class=\"s\">/\\u0001\\u002f/gm</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-op.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-op.js
new file mode 100644
index 0000000..b6966aa
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-op.js
@@ -0,0 +1,108 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-op.js']) {
+ _$jscoverage['javascript-op.js'] = [];
+ _$jscoverage['javascript-op.js'][1] = 0;
+ _$jscoverage['javascript-op.js'][4] = 0;
+ _$jscoverage['javascript-op.js'][5] = 0;
+ _$jscoverage['javascript-op.js'][8] = 0;
+ _$jscoverage['javascript-op.js'][9] = 0;
+ _$jscoverage['javascript-op.js'][11] = 0;
+ _$jscoverage['javascript-op.js'][13] = 0;
+ _$jscoverage['javascript-op.js'][16] = 0;
+ _$jscoverage['javascript-op.js'][17] = 0;
+ _$jscoverage['javascript-op.js'][20] = 0;
+ _$jscoverage['javascript-op.js'][21] = 0;
+ _$jscoverage['javascript-op.js'][24] = 0;
+ _$jscoverage['javascript-op.js'][25] = 0;
+ _$jscoverage['javascript-op.js'][28] = 0;
+ _$jscoverage['javascript-op.js'][29] = 0;
+ _$jscoverage['javascript-op.js'][30] = 0;
+ _$jscoverage['javascript-op.js'][31] = 0;
+ _$jscoverage['javascript-op.js'][34] = 0;
+ _$jscoverage['javascript-op.js'][35] = 0;
+ _$jscoverage['javascript-op.js'][36] = 0;
+ _$jscoverage['javascript-op.js'][37] = 0;
+ _$jscoverage['javascript-op.js'][40] = 0;
+ _$jscoverage['javascript-op.js'][41] = 0;
+ _$jscoverage['javascript-op.js'][42] = 0;
+ _$jscoverage['javascript-op.js'][45] = 0;
+ _$jscoverage['javascript-op.js'][46] = 0;
+ _$jscoverage['javascript-op.js'][47] = 0;
+ _$jscoverage['javascript-op.js'][48] = 0;
+ _$jscoverage['javascript-op.js'][51] = 0;
+ _$jscoverage['javascript-op.js'][52] = 0;
+ _$jscoverage['javascript-op.js'][53] = 0;
+ _$jscoverage['javascript-op.js'][54] = 0;
+ _$jscoverage['javascript-op.js'][55] = 0;
+}
+_$jscoverage['javascript-op.js'][1]++;
+var a = 1, b = 1, c = 1, d = 1;
+_$jscoverage['javascript-op.js'][4]++;
+x = a || b || c;
+_$jscoverage['javascript-op.js'][5]++;
+x = a || b || c || d;
+_$jscoverage['javascript-op.js'][8]++;
+x = a && b && c;
+_$jscoverage['javascript-op.js'][9]++;
+x = a && b && c && d;
+_$jscoverage['javascript-op.js'][11]++;
+x = a && b || c;
+_$jscoverage['javascript-op.js'][13]++;
+x = a || b && c;
+_$jscoverage['javascript-op.js'][16]++;
+x = a | b | c;
+_$jscoverage['javascript-op.js'][17]++;
+x = a | b | c | d;
+_$jscoverage['javascript-op.js'][20]++;
+x = a ^ b ^ c;
+_$jscoverage['javascript-op.js'][21]++;
+x = a ^ b ^ c ^ d;
+_$jscoverage['javascript-op.js'][24]++;
+x = a & b & c;
+_$jscoverage['javascript-op.js'][25]++;
+x = a & b & c & d;
+_$jscoverage['javascript-op.js'][28]++;
+x = a == b;
+_$jscoverage['javascript-op.js'][29]++;
+x = a != b;
+_$jscoverage['javascript-op.js'][30]++;
+x = a === b;
+_$jscoverage['javascript-op.js'][31]++;
+x = a !== b;
+_$jscoverage['javascript-op.js'][34]++;
+x = a < b;
+_$jscoverage['javascript-op.js'][35]++;
+x = a <= b;
+_$jscoverage['javascript-op.js'][36]++;
+x = a > b;
+_$jscoverage['javascript-op.js'][37]++;
+x = a >= b;
+_$jscoverage['javascript-op.js'][40]++;
+x = a << b;
+_$jscoverage['javascript-op.js'][41]++;
+x = a >> b;
+_$jscoverage['javascript-op.js'][42]++;
+x = a >>> b;
+_$jscoverage['javascript-op.js'][45]++;
+x = a + b;
+_$jscoverage['javascript-op.js'][46]++;
+x = a + b + c;
+_$jscoverage['javascript-op.js'][47]++;
+x = a + b + c + d;
+_$jscoverage['javascript-op.js'][48]++;
+x = a - b;
+_$jscoverage['javascript-op.js'][51]++;
+x = a * b;
+_$jscoverage['javascript-op.js'][52]++;
+x = a * b * c;
+_$jscoverage['javascript-op.js'][53]++;
+x = a * b * c * d;
+_$jscoverage['javascript-op.js'][54]++;
+x = a / b;
+_$jscoverage['javascript-op.js'][55]++;
+x = a % b;
+_$jscoverage['javascript-op.js'].source = ["<span class=\"k\">var</span> a <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">,</span> b <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">,</span> c <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">,</span> d <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>","","<span class=\"c\">/* TOK_OR */</span>","x <span class=\"k\">=</span> a <span class=\"k\">||</span> b <span class=\"k\">||</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">||</span> b <span class=\"k\">||</span> c <span class=\"k\">||</span> d<span class=\"k\">;</span>","","<span class=\"c\">/* TOK_AND */</span>","x <span class=\"k\">=</span> a <span class=\"k\">&amp;&amp;</span> b <span class=\"k\">&amp;&amp;</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&amp;&amp;</span> b <span class=\"k\">&amp;&amp;</span> c <span class=\"k\">&amp;&amp;</span> d<span class=\"k\">;</span>","","x <span class=\"k\">=</span> a <span class=\"k\">&amp;&amp;</span> b <span class=\"k\">||</span> c<span class=\"k\">;</span>","","x <span class=\"k\">=</span> a <span class=\"k\">||</span> b <span class=\"k\">&amp;&amp;</span> c<span class=\"k\">;</span>","","<span class=\"c\">// TOK_BITOR</span>","x <span class=\"k\">=</span> a <span class=\"k\">|</span> b <span class=\"k\">|</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">|</span> b <span class=\"k\">|</span> c <span class=\"k\">|</span> d<span class=\"k\">;</span>","","<span class=\"c\">// TOK_BITXOR</span>","x <span class=\"k\">=</span> a <span class=\"k\">^</span> b <span class=\"k\">^</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">^</span> b <span class=\"k\">^</span> c <span class=\"k\">^</span> d<span class=\"k\">;</span>","","<span class=\"c\">// TOK_BITAND</span>","x <span class=\"k\">=</span> a <span class=\"k\">&amp;</span> b <span class=\"k\">&amp;</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&amp;</span> b <span class=\"k\">&amp;</span> c <span class=\"k\">&amp;</span> d<span class=\"k\">;</span>","","<span class=\"c\">// TOK_EQUOP</span>","x <span class=\"k\">=</span> a <span class=\"k\">==</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">!=</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">===</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">!==</span> b<span class=\"k\">;</span>","","<span class=\"c\">// TOK_RELOP</span>","x <span class=\"k\">=</span> a <span class=\"k\">&lt;</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&lt;=</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&gt;</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&gt;=</span> b<span class=\"k\">;</span>","","<span class=\"c\">// TOK_SHOP</span>","x <span class=\"k\">=</span> a <span class=\"k\">&lt;&lt;</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&gt;&gt;</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&gt;&gt;&gt;</span> b<span class=\"k\">;</span>","","<span class=\"c\">/* TOK_PLUS, TOK_MINUS */</span>","x <span class=\"k\">=</span> a <span class=\"k\">+</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">+</span> b <span class=\"k\">+</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">+</span> b <span class=\"k\">+</span> c <span class=\"k\">+</span> d<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">-</span> b<span class=\"k\">;</span>","","<span class=\"c\">// TOK_STAR, TOK_DIVOP</span>","x <span class=\"k\">=</span> a <span class=\"k\">*</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">*</span> b <span class=\"k\">*</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">*</span> b <span class=\"k\">*</span> c <span class=\"k\">*</span> d<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">/</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">%</span> b<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-primary.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-primary.js
new file mode 100644
index 0000000..c6e46d9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-primary.js
@@ -0,0 +1,21 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-primary.js']) {
+ _$jscoverage['javascript-primary.js'] = [];
+ _$jscoverage['javascript-primary.js'][1] = 0;
+ _$jscoverage['javascript-primary.js'][2] = 0;
+ _$jscoverage['javascript-primary.js'][3] = 0;
+ _$jscoverage['javascript-primary.js'][4] = 0;
+}
+_$jscoverage['javascript-primary.js'][1]++;
+x = true;
+_$jscoverage['javascript-primary.js'][2]++;
+x = false;
+_$jscoverage['javascript-primary.js'][3]++;
+x = null;
+_$jscoverage['javascript-primary.js'][4]++;
+x = this;
+_$jscoverage['javascript-primary.js'].source = ["x <span class=\"k\">=</span> <span class=\"k\">true</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">false</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">null</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">this</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rb.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rb.js
new file mode 100644
index 0000000..df807b1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rb.js
@@ -0,0 +1,24 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-rb.js']) {
+ _$jscoverage['javascript-rb.js'] = [];
+ _$jscoverage['javascript-rb.js'][1] = 0;
+ _$jscoverage['javascript-rb.js'][2] = 0;
+ _$jscoverage['javascript-rb.js'][3] = 0;
+ _$jscoverage['javascript-rb.js'][4] = 0;
+ _$jscoverage['javascript-rb.js'][5] = 0;
+}
+_$jscoverage['javascript-rb.js'][1]++;
+x = [];
+_$jscoverage['javascript-rb.js'][2]++;
+x = [x];
+_$jscoverage['javascript-rb.js'][3]++;
+x = [x, y];
+_$jscoverage['javascript-rb.js'][4]++;
+x = [x, y,];
+_$jscoverage['javascript-rb.js'][5]++;
+x = [x, , y];
+_$jscoverage['javascript-rb.js'].source = ["x <span class=\"k\">=</span> <span class=\"k\">[];</span>","x <span class=\"k\">=</span> <span class=\"k\">[</span>x<span class=\"k\">];</span>","x <span class=\"k\">=</span> <span class=\"k\">[</span>x<span class=\"k\">,</span> y<span class=\"k\">];</span>","x <span class=\"k\">=</span> <span class=\"k\">[</span>x<span class=\"k\">,</span> y<span class=\"k\">,];</span>","x <span class=\"k\">=</span> <span class=\"k\">[</span>x<span class=\"k\">,,</span> y<span class=\"k\">];</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rc.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rc.js
new file mode 100644
index 0000000..e3108d0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rc.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-rc.js']) {
+ _$jscoverage['javascript-rc.js'] = [];
+ _$jscoverage['javascript-rc.js'][1] = 0;
+ _$jscoverage['javascript-rc.js'][4] = 0;
+}
+_$jscoverage['javascript-rc.js'][1]++;
+x = {x: y};
+_$jscoverage['javascript-rc.js'][4]++;
+x = {x: y, y: x};
+_$jscoverage['javascript-rc.js'].source = ["x <span class=\"k\">=</span> <span class=\"k\">{</span>"," x<span class=\"k\">:</span> y","<span class=\"k\">}</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">{</span>"," x<span class=\"k\">:</span> y<span class=\"k\">,</span>"," y<span class=\"k\">:</span> x","<span class=\"k\">}</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rp.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rp.js
new file mode 100644
index 0000000..47df295
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rp.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-rp.js']) {
+ _$jscoverage['javascript-rp.js'] = [];
+ _$jscoverage['javascript-rp.js'][1] = 0;
+}
+_$jscoverage['javascript-rp.js'][1]++;
+x = a + (b - c);
+_$jscoverage['javascript-rp.js'].source = ["x <span class=\"k\">=</span> a <span class=\"k\">+</span> <span class=\"k\">(</span>b <span class=\"k\">-</span> c<span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-special-characters.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-special-characters.js
new file mode 100644
index 0000000..0154e86
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-special-characters.js
@@ -0,0 +1,30 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-special-characters.js']) {
+ _$jscoverage['javascript-special-characters.js'] = [];
+ _$jscoverage['javascript-special-characters.js'][1] = 0;
+ _$jscoverage['javascript-special-characters.js'][2] = 0;
+ _$jscoverage['javascript-special-characters.js'][5] = 0;
+ _$jscoverage['javascript-special-characters.js'][6] = 0;
+ _$jscoverage['javascript-special-characters.js'][9] = 0;
+ _$jscoverage['javascript-special-characters.js'][10] = 0;
+}
+_$jscoverage['javascript-special-characters.js'][1]++;
+function f() {
+ _$jscoverage['javascript-special-characters.js'][2]++;
+ return "'";
+}
+_$jscoverage['javascript-special-characters.js'][5]++;
+function g() {
+ _$jscoverage['javascript-special-characters.js'][6]++;
+ return "\"";
+}
+_$jscoverage['javascript-special-characters.js'][9]++;
+function h() {
+ _$jscoverage['javascript-special-characters.js'][10]++;
+ return "\\";
+}
+_$jscoverage['javascript-special-characters.js'].source = ["<span class=\"k\">function</span> f<span class=\"k\">()</span> <span class=\"k\">{</span>","\t<span class=\"k\">return</span> <span class=\"s\">'</span><span class=\"t\">\\'</span><span class=\"s\">'</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","&#11;","<span class=\"k\">function</span> g<span class=\"k\">()</span> <span class=\"k\">{</span>","\t<span class=\"k\">return</span> <span class=\"s\">\"</span><span class=\"t\">\\\"</span><span class=\"s\">\"</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","&#12;","<span class=\"k\">function</span> h<span class=\"k\">()</span> <span class=\"k\">{</span>","\t<span class=\"k\">return</span> <span class=\"s\">'</span><span class=\"t\">\\\\</span><span class=\"s\">'</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-string.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-string.js
new file mode 100644
index 0000000..3dbacc8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-string.js
@@ -0,0 +1,36 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-string.js']) {
+ _$jscoverage['javascript-string.js'] = [];
+ _$jscoverage['javascript-string.js'][1] = 0;
+ _$jscoverage['javascript-string.js'][2] = 0;
+ _$jscoverage['javascript-string.js'][3] = 0;
+ _$jscoverage['javascript-string.js'][4] = 0;
+ _$jscoverage['javascript-string.js'][5] = 0;
+ _$jscoverage['javascript-string.js'][6] = 0;
+ _$jscoverage['javascript-string.js'][7] = 0;
+ _$jscoverage['javascript-string.js'][8] = 0;
+ _$jscoverage['javascript-string.js'][10] = 0;
+}
+_$jscoverage['javascript-string.js'][1]++;
+x = "";
+_$jscoverage['javascript-string.js'][2]++;
+x = "";
+_$jscoverage['javascript-string.js'][3]++;
+x = "x";
+_$jscoverage['javascript-string.js'][4]++;
+x = "x";
+_$jscoverage['javascript-string.js'][5]++;
+x = "\"";
+_$jscoverage['javascript-string.js'][6]++;
+x = "'";
+_$jscoverage['javascript-string.js'][7]++;
+x = "\b\t\n\u000b\f\r\"'\\";
+_$jscoverage['javascript-string.js'][8]++;
+x = new RegExp("x\\(\\)\\\\\\/");
+_$jscoverage['javascript-string.js'][10]++;
+x = "foobar";
+_$jscoverage['javascript-string.js'].source = ["x <span class=\"k\">=</span> <span class=\"s\">\"\"</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">''</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">\"x\"</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">'x'</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">\"</span><span class=\"t\">\\\"</span><span class=\"s\">\"</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">'</span><span class=\"t\">\\'</span><span class=\"s\">'</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">\"</span><span class=\"t\">\\b\\t\\n\\v\\f\\r\\\"\\'\\\\</span><span class=\"s\">\"</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">new</span> RegExp<span class=\"k\">(</span><span class=\"s\">'x</span><span class=\"t\">\\\\</span><span class=\"s\">(</span><span class=\"t\">\\\\</span><span class=\"s\">)</span><span class=\"t\">\\\\\\\\\\\\</span><span class=\"s\">/'</span><span class=\"k\">);</span>","","x <span class=\"k\">=</span> <span class=\"s\">'foo</span><span class=\"t\">\\</span>","<span class=\"s\">bar'</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-switch.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-switch.js
new file mode 100644
index 0000000..e198d7f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-switch.js
@@ -0,0 +1,55 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-switch.js']) {
+ _$jscoverage['javascript-switch.js'] = [];
+ _$jscoverage['javascript-switch.js'][1] = 0;
+ _$jscoverage['javascript-switch.js'][3] = 0;
+ _$jscoverage['javascript-switch.js'][4] = 0;
+ _$jscoverage['javascript-switch.js'][6] = 0;
+ _$jscoverage['javascript-switch.js'][7] = 0;
+ _$jscoverage['javascript-switch.js'][8] = 0;
+ _$jscoverage['javascript-switch.js'][10] = 0;
+ _$jscoverage['javascript-switch.js'][11] = 0;
+ _$jscoverage['javascript-switch.js'][14] = 0;
+ _$jscoverage['javascript-switch.js'][16] = 0;
+ _$jscoverage['javascript-switch.js'][17] = 0;
+ _$jscoverage['javascript-switch.js'][18] = 0;
+ _$jscoverage['javascript-switch.js'][20] = 0;
+}
+_$jscoverage['javascript-switch.js'][1]++;
+switch (x) {
+case x:
+ _$jscoverage['javascript-switch.js'][3]++;
+ x = 0;
+ _$jscoverage['javascript-switch.js'][4]++;
+ break;
+case y:
+ _$jscoverage['javascript-switch.js'][6]++;
+ x = 0;
+ _$jscoverage['javascript-switch.js'][7]++;
+ y = 0;
+ _$jscoverage['javascript-switch.js'][8]++;
+ break;
+default:
+ _$jscoverage['javascript-switch.js'][10]++;
+ x = 0;
+ _$jscoverage['javascript-switch.js'][11]++;
+ break;
+}
+_$jscoverage['javascript-switch.js'][14]++;
+switch (x) {
+case 1:
+ _$jscoverage['javascript-switch.js'][16]++;
+ let y = 1;
+ _$jscoverage['javascript-switch.js'][17]++;
+ f(y);
+ _$jscoverage['javascript-switch.js'][18]++;
+ break;
+case 2:
+ _$jscoverage['javascript-switch.js'][20]++;
+ break;
+}
+_$jscoverage['javascript-switch.js'].source = ["<span class=\"k\">switch</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>","<span class=\"k\">case</span> x<span class=\"k\">:</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>"," <span class=\"k\">break</span><span class=\"k\">;</span>","<span class=\"k\">case</span> y<span class=\"k\">:</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>"," y <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>"," <span class=\"k\">break</span><span class=\"k\">;</span>","<span class=\"k\">default</span><span class=\"k\">:</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>"," <span class=\"k\">break</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">switch</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>","<span class=\"k\">case</span> <span class=\"s\">1</span><span class=\"k\">:</span>"," <span class=\"k\">let</span> y <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"," f<span class=\"k\">(</span>y<span class=\"k\">);</span>"," <span class=\"k\">break</span><span class=\"k\">;</span>","<span class=\"k\">case</span> <span class=\"s\">2</span><span class=\"k\">:</span>"," <span class=\"k\">break</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-throw.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-throw.js
new file mode 100644
index 0000000..2acaa17
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-throw.js
@@ -0,0 +1,21 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-throw.js']) {
+ _$jscoverage['javascript-throw.js'] = [];
+ _$jscoverage['javascript-throw.js'][1] = 0;
+ _$jscoverage['javascript-throw.js'][2] = 0;
+ _$jscoverage['javascript-throw.js'][5] = 0;
+}
+_$jscoverage['javascript-throw.js'][1]++;
+try {
+ _$jscoverage['javascript-throw.js'][2]++;
+ throw "x";
+}
+catch (e) {
+ _$jscoverage['javascript-throw.js'][5]++;
+ ;
+}
+_$jscoverage['javascript-throw.js'].source = ["<span class=\"k\">try</span> <span class=\"k\">{</span>"," <span class=\"k\">throw</span> <span class=\"s\">\"x\"</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","<span class=\"k\">catch</span> <span class=\"k\">(</span>e<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-try.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-try.js
new file mode 100644
index 0000000..8111f17
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-try.js
@@ -0,0 +1,66 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-try.js']) {
+ _$jscoverage['javascript-try.js'] = [];
+ _$jscoverage['javascript-try.js'][1] = 0;
+ _$jscoverage['javascript-try.js'][3] = 0;
+ _$jscoverage['javascript-try.js'][4] = 0;
+ _$jscoverage['javascript-try.js'][7] = 0;
+ _$jscoverage['javascript-try.js'][10] = 0;
+ _$jscoverage['javascript-try.js'][11] = 0;
+ _$jscoverage['javascript-try.js'][14] = 0;
+ _$jscoverage['javascript-try.js'][17] = 0;
+ _$jscoverage['javascript-try.js'][18] = 0;
+ _$jscoverage['javascript-try.js'][21] = 0;
+ _$jscoverage['javascript-try.js'][24] = 0;
+ _$jscoverage['javascript-try.js'][25] = 0;
+ _$jscoverage['javascript-try.js'][28] = 0;
+ _$jscoverage['javascript-try.js'][31] = 0;
+}
+_$jscoverage['javascript-try.js'][1]++;
+function f() {
+}
+_$jscoverage['javascript-try.js'][3]++;
+try {
+ _$jscoverage['javascript-try.js'][4]++;
+ f();
+}
+catch (e) {
+ _$jscoverage['javascript-try.js'][7]++;
+ f();
+}
+_$jscoverage['javascript-try.js'][10]++;
+try {
+ _$jscoverage['javascript-try.js'][11]++;
+ f();
+}
+catch (e if e instanceof E) {
+ _$jscoverage['javascript-try.js'][14]++;
+ f();
+}
+_$jscoverage['javascript-try.js'][17]++;
+try {
+ _$jscoverage['javascript-try.js'][18]++;
+ f();
+}
+finally {
+ _$jscoverage['javascript-try.js'][21]++;
+ f();
+}
+_$jscoverage['javascript-try.js'][24]++;
+try {
+ _$jscoverage['javascript-try.js'][25]++;
+ f();
+}
+catch (e) {
+ _$jscoverage['javascript-try.js'][28]++;
+ f();
+}
+finally {
+ _$jscoverage['javascript-try.js'][31]++;
+ f();
+}
+_$jscoverage['javascript-try.js'].source = ["<span class=\"k\">function</span> f<span class=\"k\">()</span> <span class=\"k\">{}</span>","","<span class=\"k\">try</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">catch</span> <span class=\"k\">(</span>e<span class=\"k\">)</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">try</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">catch</span> <span class=\"k\">(</span>e <span class=\"k\">if</span> e <span class=\"k\">instanceof</span> E<span class=\"k\">)</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">try</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">finally</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">try</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">catch</span> <span class=\"k\">(</span>e<span class=\"k\">)</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">finally</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-unaryop.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-unaryop.js
new file mode 100644
index 0000000..ca06e39
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-unaryop.js
@@ -0,0 +1,27 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-unaryop.js']) {
+ _$jscoverage['javascript-unaryop.js'] = [];
+ _$jscoverage['javascript-unaryop.js'][1] = 0;
+ _$jscoverage['javascript-unaryop.js'][2] = 0;
+ _$jscoverage['javascript-unaryop.js'][3] = 0;
+ _$jscoverage['javascript-unaryop.js'][4] = 0;
+ _$jscoverage['javascript-unaryop.js'][5] = 0;
+ _$jscoverage['javascript-unaryop.js'][6] = 0;
+}
+_$jscoverage['javascript-unaryop.js'][1]++;
+x = - x;
+_$jscoverage['javascript-unaryop.js'][2]++;
+x = + x;
+_$jscoverage['javascript-unaryop.js'][3]++;
+x = ! x;
+_$jscoverage['javascript-unaryop.js'][4]++;
+x = ~ x;
+_$jscoverage['javascript-unaryop.js'][5]++;
+x = typeof x;
+_$jscoverage['javascript-unaryop.js'][6]++;
+x = void x;
+_$jscoverage['javascript-unaryop.js'].source = ["x <span class=\"k\">=</span> <span class=\"k\">-</span>x<span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">+</span>x<span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">!</span>x<span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">~</span>x<span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">typeof</span> x<span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">void</span> x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-var.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-var.js
new file mode 100644
index 0000000..904bbcf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-var.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-var.js']) {
+ _$jscoverage['javascript-var.js'] = [];
+ _$jscoverage['javascript-var.js'][1] = 0;
+ _$jscoverage['javascript-var.js'][2] = 0;
+}
+_$jscoverage['javascript-var.js'][1]++;
+var x;
+_$jscoverage['javascript-var.js'][2]++;
+var y = x, z = x;
+_$jscoverage['javascript-var.js'].source = ["<span class=\"k\">var</span> x<span class=\"k\">;</span>","<span class=\"k\">var</span> y <span class=\"k\">=</span> x<span class=\"k\">,</span> z <span class=\"k\">=</span> x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-while.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-while.js
new file mode 100644
index 0000000..b15afa2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-while.js
@@ -0,0 +1,79 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-while.js']) {
+ _$jscoverage['javascript-while.js'] = [];
+ _$jscoverage['javascript-while.js'][1] = 0;
+ _$jscoverage['javascript-while.js'][2] = 0;
+ _$jscoverage['javascript-while.js'][5] = 0;
+ _$jscoverage['javascript-while.js'][6] = 0;
+ _$jscoverage['javascript-while.js'][9] = 0;
+ _$jscoverage['javascript-while.js'][10] = 0;
+ _$jscoverage['javascript-while.js'][12] = 0;
+ _$jscoverage['javascript-while.js'][13] = 0;
+ _$jscoverage['javascript-while.js'][15] = 0;
+ _$jscoverage['javascript-while.js'][16] = 0;
+ _$jscoverage['javascript-while.js'][17] = 0;
+ _$jscoverage['javascript-while.js'][21] = 0;
+ _$jscoverage['javascript-while.js'][23] = 0;
+ _$jscoverage['javascript-while.js'][24] = 0;
+ _$jscoverage['javascript-while.js'][28] = 0;
+ _$jscoverage['javascript-while.js'][29] = 0;
+ _$jscoverage['javascript-while.js'][30] = 0;
+ _$jscoverage['javascript-while.js'][31] = 0;
+ _$jscoverage['javascript-while.js'][32] = 0;
+}
+_$jscoverage['javascript-while.js'][1]++;
+while (x) {
+ _$jscoverage['javascript-while.js'][2]++;
+ x();
+}
+_$jscoverage['javascript-while.js'][5]++;
+while (x) {
+ _$jscoverage['javascript-while.js'][6]++;
+ ;
+}
+_$jscoverage['javascript-while.js'][9]++;
+while (x) {
+ _$jscoverage['javascript-while.js'][10]++;
+ x();
+}
+_$jscoverage['javascript-while.js'][12]++;
+while (x) {
+ _$jscoverage['javascript-while.js'][13]++;
+ ;
+}
+_$jscoverage['javascript-while.js'][15]++;
+while (x) {
+ _$jscoverage['javascript-while.js'][16]++;
+ if (x) {
+ _$jscoverage['javascript-while.js'][17]++;
+ continue;
+ }
+}
+_$jscoverage['javascript-while.js'][21]++;
+label:
+while (x) {
+ _$jscoverage['javascript-while.js'][23]++;
+ if (x) {
+ _$jscoverage['javascript-while.js'][24]++;
+ continue label;
+ }
+}
+_$jscoverage['javascript-while.js'][28]++;
+label2:
+{
+ _$jscoverage['javascript-while.js'][29]++;
+ f();
+ _$jscoverage['javascript-while.js'][30]++;
+ while (x) {
+ _$jscoverage['javascript-while.js'][31]++;
+ if (x) {
+ _$jscoverage['javascript-while.js'][32]++;
+ break label2;
+ }
+}
+}
+_$jscoverage['javascript-while.js'].source = ["<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span>"," x<span class=\"k\">();</span>","","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span>"," <span class=\"k\">;</span>","","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">continue</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>","","label<span class=\"k\">:</span>","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">continue</span> label<span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>","","label2<span class=\"k\">:</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>"," <span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">break</span> label2<span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-with.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-with.js
new file mode 100644
index 0000000..52aea68
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-with.js
@@ -0,0 +1,30 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-with.js']) {
+ _$jscoverage['javascript-with.js'] = [];
+ _$jscoverage['javascript-with.js'][1] = 0;
+ _$jscoverage['javascript-with.js'][2] = 0;
+ _$jscoverage['javascript-with.js'][4] = 0;
+ _$jscoverage['javascript-with.js'][5] = 0;
+ _$jscoverage['javascript-with.js'][8] = 0;
+ _$jscoverage['javascript-with.js'][9] = 0;
+}
+_$jscoverage['javascript-with.js'][1]++;
+function f() {
+}
+_$jscoverage['javascript-with.js'][2]++;
+var x = {};
+_$jscoverage['javascript-with.js'][4]++;
+with (x) {
+ _$jscoverage['javascript-with.js'][5]++;
+ f();
+}
+_$jscoverage['javascript-with.js'][8]++;
+with (x) {
+ _$jscoverage['javascript-with.js'][9]++;
+ f();
+}
+_$jscoverage['javascript-with.js'].source = ["<span class=\"k\">function</span> f<span class=\"k\">()</span> <span class=\"k\">{}</span>","<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"k\">{}</span><span class=\"k\">;</span>","","<span class=\"k\">with</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">with</span> <span class=\"k\">(</span>x<span class=\"k\">)</span>"," f<span class=\"k\">();</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.sh b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.sh
new file mode 100755
index 0000000..6209a0f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+# javascript.sh - test various JavaScript constructs
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr DIR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if jscoverage-server --version | grep -q 'iconv\|MultiByteToWideChar'
+then
+ character_encoding_support=yes
+else
+ character_encoding_support=no
+fi
+
+rm -fr DIR
+case "$character_encoding_support" in
+ yes)
+ $VALGRIND jscoverage --js-version 180 --encoding ISO-8859-1 javascript DIR
+ ;;
+ *)
+ $VALGRIND jscoverage --js-version=180 --exclude=javascript-iso-8859-1.js javascript DIR
+ ;;
+esac
+for i in javascript/*.js
+do
+ if [ $character_encoding_support = no -a $i = javascript/javascript-iso-8859-1.js ]
+ then
+ continue
+ fi
+ FILE=${i##javascript/}
+ EXPECTED=javascript.expected/${FILE}
+ ACTUAL=DIR/${FILE}
+ diff -u -r --strip-trailing-cr $EXPECTED $ACTUAL
+done
+
+# rm -fr DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-array-comprehension.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-array-comprehension.js
new file mode 100644
index 0000000..2d9b048
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-array-comprehension.js
@@ -0,0 +1,14 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.7
+
+function range(begin, end) {
+ for (let i = begin; i < end; ++i) {
+ yield i;
+ }
+}
+var ten_squares = [i * i for each (i in range(0, 10))];
+var evens = [i for each (i in range(0, 21)) if (i % 2 == 0)];
+
+// test optimization
+var optimized = [i for each (i in x) if (0)];
+
+[i for each (a in x) for each (b in y)]
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-assign.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-assign.js
new file mode 100644
index 0000000..d17bdd1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-assign.js
@@ -0,0 +1,14 @@
+var x = 1;
+var y = 1;
+x = y;
+x += y;
+x -= y;
+x *= y;
+x %= y;
+x <<= y;
+x >>= y;
+x >>>= y;
+x &= y;
+x |= y;
+x ^= y;
+x /= y;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-colon.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-colon.js
new file mode 100644
index 0000000..69bade1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-colon.js
@@ -0,0 +1,7 @@
+x:
+ y = 0;
+
+y: {
+ let y = 1;
+ print(y);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-comma.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-comma.js
new file mode 100644
index 0000000..15c162c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-comma.js
@@ -0,0 +1 @@
+x = y, y = x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-cr.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-cr.js
new file mode 100644
index 0000000..fad02c7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-cr.js
@@ -0,0 +1 @@
+/* This file has CR line endings. */ var x = 1; \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-crlf.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-crlf.js
new file mode 100644
index 0000000..53dcd0e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-crlf.js
@@ -0,0 +1,4 @@
+/*
+This file has CRLF line endings.
+*/
+var x = 1;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-debugger.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-debugger.js
new file mode 100644
index 0000000..dc33421
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-debugger.js
@@ -0,0 +1,6 @@
+try {
+ f();
+}
+catch (e) {
+ debugger;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dec.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dec.js
new file mode 100644
index 0000000..46d5bc3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dec.js
@@ -0,0 +1,2 @@
+x--;
+--x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-delete.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-delete.js
new file mode 100644
index 0000000..ae9a3d0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-delete.js
@@ -0,0 +1 @@
+delete x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-destructuring.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-destructuring.js
new file mode 100644
index 0000000..c8cf4c9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-destructuring.js
@@ -0,0 +1,42 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.7
+
+[a, b] = [b, a];
+
+function f() {
+ return [1, 2];
+}
+[a, b] = f();
+
+for (let [name, value] in Iterator(obj)) {
+ print(name);
+ print(value);
+}
+
+for each (let {name: n, family: { father: f } } in people) {
+ print(n);
+ print(f);
+}
+
+var [a, , b] = f();
+[,,,] = f();
+
+function g() {
+ var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
+ if (!parsedURL)
+ return null;
+ var [, protocol, fullhost, fullpath] = parsedURL;
+}
+
+function h(a, [b, c], {foo: d, 'bar': e}) {
+ f();
+ g();
+}
+
+x = function([a, b]) a + b;
+
+({x: x0, y: y0}) = point;
+var {x: x0, y: y0} = point;
+let ({x: x0, y: y0} = point) {
+ print(x0);
+ print(y0);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-do.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-do.js
new file mode 100644
index 0000000..e6bbee9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-do.js
@@ -0,0 +1,10 @@
+var x;
+
+do {
+ x = false;
+}
+while (x);
+
+do
+ x = false;
+while (x);
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dot.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dot.js
new file mode 100644
index 0000000..0b35cdc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dot.js
@@ -0,0 +1,8 @@
+x.y = y.x;
+x["y"] = y["x"];
+x[y] = y[x];
+x['2y'] = y['var'];
+x[''] = y[""];
+
+print(123.0.toString());
+({}.toString());
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-empty.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-empty.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-empty.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-for.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-for.js
new file mode 100644
index 0000000..166b586
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-for.js
@@ -0,0 +1,22 @@
+for (i in x) {
+ x();
+}
+
+for (var i in x) {
+ x();
+}
+
+for (i = 0; i < x; i++) {
+ x();
+}
+
+for (var j = 0; j < x; j++) {
+ x();
+}
+
+for (i in x)
+ x();
+
+for (i.value in x) {
+ x();
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-foreach.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-foreach.js
new file mode 100644
index 0000000..52cb266
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-foreach.js
@@ -0,0 +1,8 @@
+/*
+https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Object_Manipulation_Statements
+https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for_each...in
+*/
+
+for each (var item in obj) {
+ sum += item;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-function.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-function.js
new file mode 100644
index 0000000..94fc8bd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-function.js
@@ -0,0 +1,38 @@
+function x() {}
+
+function x() {
+ ;
+}
+
+function x() {
+ x();
+ return 'x';
+}
+
+function x(a) {
+ x();
+}
+
+function x(a, b) {
+ x();
+}
+
+x = function() {
+ x();
+};
+
+(function () {
+ print('x');
+})();
+
+(function (a) {
+ print('x');
+})(1);
+
+(function (a, b) {
+ print('x');
+})(1, 2);
+
+(function () {
+ print('x');
+}).call(window);
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator-expression.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator-expression.js
new file mode 100644
index 0000000..cafec77
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator-expression.js
@@ -0,0 +1,18 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.8
+
+let it = (i + 3 for (i in someObj));
+try {
+ while (true) {
+ document.write(it.next() + "<br>\n");
+ }
+} catch (err if err instanceof StopIteration) {
+ document.write("End of record.<br>\n");
+}
+
+function handleResults( results ) {
+ for ( let i in results )
+ ;
+}
+handleResults( i for ( i in obj ) if ( i > 3 ) );
+
+it = (1 for(a in x) for(b in y));
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator.js
new file mode 100644
index 0000000..6c1f32a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator.js
@@ -0,0 +1,11 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.7
+
+function fib() {
+ var i = 0, j = 1;
+ while (true) {
+ yield i;
+ var t = i;
+ i = j;
+ j += t;
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-getter-setter.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-getter-setter.js
new file mode 100644
index 0000000..31fca86
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-getter-setter.js
@@ -0,0 +1,19 @@
+var o = {
+ _x: 123,
+ get x() {
+ return this._x;
+ },
+ set x(value) {
+ this._x = value;
+ }
+};
+
+o = {
+ _x: 123,
+ get x get_x() {
+ return this._x;
+ },
+ set x set_x(value) {
+ this._x = value;
+ }
+};
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-hook.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-hook.js
new file mode 100644
index 0000000..0e690f8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-hook.js
@@ -0,0 +1,2 @@
+var x = 1;
+var y = x === 1? "x": "y";
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-if.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-if.js
new file mode 100644
index 0000000..43d489e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-if.js
@@ -0,0 +1,30 @@
+var x = 0;
+
+if (x)
+ x = 0;
+
+if (x) {
+ x = 0;
+}
+
+if (x)
+ x = 0;
+else
+ x = 0;
+
+if (x) {
+ x = 0;
+}
+else {
+ x = 0;
+}
+
+if (x) {
+ x = 0;
+}
+else if (x) {
+ x = 0;
+}
+else {
+ x = 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-in.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-in.js
new file mode 100644
index 0000000..75ba66e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-in.js
@@ -0,0 +1,4 @@
+var x = {};
+if ('a' in x) {
+ x = null;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-inc.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-inc.js
new file mode 100644
index 0000000..065c7bf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-inc.js
@@ -0,0 +1,2 @@
+x++;
+++x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-iso-8859-1.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-iso-8859-1.js
new file mode 100644
index 0000000..2658cee
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-iso-8859-1.js
@@ -0,0 +1,2 @@
+var s = 'e';
+var r = /e/;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lambda.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lambda.js
new file mode 100644
index 0000000..0e5062f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lambda.js
@@ -0,0 +1,3 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.8
+
+var square = function(x) x * x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-let.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-let.js
new file mode 100644
index 0000000..7bb777b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-let.js
@@ -0,0 +1,79 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.7
+
+// let statement
+
+let (x = x+10, y = 12) {
+ print(x+y + "\n");
+}
+
+// let expressions
+
+print( let(x = x + 10, y = 12) x+y + "<br>\n");
+
+// let definitions
+
+if (x > y) {
+ let gamma = 12.7 + y;
+ i = gamma * x;
+}
+
+var list = document.getElementById("list");
+
+for (var i = 1; i <= 5; i++) {
+ var item = document.createElement("LI");
+ item.appendChild(document.createTextNode("Item " + i));
+
+ let j = i;
+ item.onclick = function (ev) {
+ alert("Item " + j + " is clicked.");
+ };
+ list.appendChild(item);
+}
+
+function varTest() {
+ var x = 31;
+ if (true) {
+ var x = 71; // same variable!
+ alert(x); // 71
+ }
+ alert(x); // 71
+}
+
+function letTest() {
+ let x = 31;
+ if (true) {
+ let x = 71; // different variable
+ alert(x); // 71
+ }
+ alert(x); // 31
+}
+
+function letTests() {
+ let x = 10;
+
+ // let-statement
+ let (x = x + 20) {
+ alert(x); // 30
+ }
+
+ // let-expression
+ alert(let (x = x + 20) x); // 30
+
+ // let-definition
+ {
+ let x = x + 20; // x here evaluates to undefined
+ alert(x); // undefined + 20 ==> NaN
+ }
+}
+
+var x = 'global';
+let x = 42;
+document.write(this.x + "<br>\n");
+
+// let-scoped variables in for loops
+var i=0;
+for ( let i=i ; i < 10 ; i++ )
+ document.write(i + "<br>\n");
+
+for ( let [name,value] in obj )
+ document.write("Name: " + name + ", Value: " + value + "<br>\n");
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lf.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lf.js
new file mode 100644
index 0000000..2741068
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lf.js
@@ -0,0 +1,4 @@
+/*
+This file has LF line endings.
+*/
+var x = 1;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-new.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-new.js
new file mode 100644
index 0000000..6801585
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-new.js
@@ -0,0 +1,4 @@
+function X() {}
+x = new X();
+x = new X(1);
+x = new X(1, 2);
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-number.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-number.js
new file mode 100644
index 0000000..95603d7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-number.js
@@ -0,0 +1,19 @@
+x = 1;
+y = 2;
+z = 10.5;
+
+a = 1 / 0;
+a = -1 / 0;
+
+a = 0;
+a = -0;
+
+a = 0 / 0;
+a = 0 / -0;
+a = 0 / (-0);
+a = -0 / 0;
+a = (-0) / 0;
+a = -0 / -0;
+a = -0 / (-0);
+a = (-0) / -0;
+a = (-0) / (-0);
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-object.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-object.js
new file mode 100644
index 0000000..83ce7be
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-object.js
@@ -0,0 +1,2 @@
+x = /x\(\)\\\//i;
+y = /\u0001\u002f/gm;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-op.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-op.js
new file mode 100644
index 0000000..9c6e8bb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-op.js
@@ -0,0 +1,55 @@
+var a = 1, b = 1, c = 1, d = 1;
+
+/* TOK_OR */
+x = a || b || c;
+x = a || b || c || d;
+
+/* TOK_AND */
+x = a && b && c;
+x = a && b && c && d;
+
+x = a && b || c;
+
+x = a || b && c;
+
+// TOK_BITOR
+x = a | b | c;
+x = a | b | c | d;
+
+// TOK_BITXOR
+x = a ^ b ^ c;
+x = a ^ b ^ c ^ d;
+
+// TOK_BITAND
+x = a & b & c;
+x = a & b & c & d;
+
+// TOK_EQUOP
+x = a == b;
+x = a != b;
+x = a === b;
+x = a !== b;
+
+// TOK_RELOP
+x = a < b;
+x = a <= b;
+x = a > b;
+x = a >= b;
+
+// TOK_SHOP
+x = a << b;
+x = a >> b;
+x = a >>> b;
+
+/* TOK_PLUS, TOK_MINUS */
+x = a + b;
+x = a + b + c;
+x = a + b + c + d;
+x = a - b;
+
+// TOK_STAR, TOK_DIVOP
+x = a * b;
+x = a * b * c;
+x = a * b * c * d;
+x = a / b;
+x = a % b;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-primary.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-primary.js
new file mode 100644
index 0000000..9a7bc4e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-primary.js
@@ -0,0 +1,4 @@
+x = true;
+x = false;
+x = null;
+x = this;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rb.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rb.js
new file mode 100644
index 0000000..57e897c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rb.js
@@ -0,0 +1,5 @@
+x = [];
+x = [x];
+x = [x, y];
+x = [x, y,];
+x = [x,, y];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rc.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rc.js
new file mode 100644
index 0000000..f654a9a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rc.js
@@ -0,0 +1,7 @@
+x = {
+ x: y
+};
+x = {
+ x: y,
+ y: x
+};
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rp.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rp.js
new file mode 100644
index 0000000..2e17573
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rp.js
@@ -0,0 +1 @@
+x = a + (b - c);
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-special-characters.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-special-characters.js
new file mode 100644
index 0000000..dc8ec36
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-special-characters.js
@@ -0,0 +1,11 @@
+function f() {
+ return '\'';
+}
+
+function g() {
+ return "\"";
+}
+
+function h() {
+ return '\\';
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-string.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-string.js
new file mode 100644
index 0000000..463824a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-string.js
@@ -0,0 +1,11 @@
+x = "";
+x = '';
+x = "x";
+x = 'x';
+x = "\"";
+x = '\'';
+x = "\b\t\n\v\f\r\"\'\\";
+x = new RegExp('x\\(\\)\\\\\\/');
+
+x = 'foo\
+bar';
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-switch.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-switch.js
new file mode 100644
index 0000000..bb6e01e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-switch.js
@@ -0,0 +1,21 @@
+switch (x) {
+case x:
+ x = 0;
+ break;
+case y:
+ x = 0;
+ y = 0;
+ break;
+default:
+ x = 0;
+ break;
+}
+
+switch (x) {
+case 1:
+ let y = 1;
+ f(y);
+ break;
+case 2:
+ break;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-throw.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-throw.js
new file mode 100644
index 0000000..1fc73c4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-throw.js
@@ -0,0 +1,6 @@
+try {
+ throw "x";
+}
+catch (e) {
+ ;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-try.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-try.js
new file mode 100644
index 0000000..47a5de4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-try.js
@@ -0,0 +1,32 @@
+function f() {}
+
+try {
+ f();
+}
+catch (e) {
+ f();
+}
+
+try {
+ f();
+}
+catch (e if e instanceof E) {
+ f();
+}
+
+try {
+ f();
+}
+finally {
+ f();
+}
+
+try {
+ f();
+}
+catch (e) {
+ f();
+}
+finally {
+ f();
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-unaryop.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-unaryop.js
new file mode 100644
index 0000000..0173913
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-unaryop.js
@@ -0,0 +1,6 @@
+x = -x;
+x = +x;
+x = !x;
+x = ~x;
+x = typeof x;
+x = void x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-var.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-var.js
new file mode 100644
index 0000000..4902a44
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-var.js
@@ -0,0 +1,2 @@
+var x;
+var y = x, z = x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-while.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-while.js
new file mode 100644
index 0000000..f1ec6b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-while.js
@@ -0,0 +1,35 @@
+while (x) {
+ x();
+}
+
+while (x) {
+ ;
+}
+
+while (x)
+ x();
+
+while (x)
+ ;
+
+while (x) {
+ if (x) {
+ continue;
+ }
+}
+
+label:
+while (x) {
+ if (x) {
+ continue label;
+ }
+}
+
+label2: {
+ f();
+ while (x) {
+ if (x) {
+ break label2;
+ }
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-with.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-with.js
new file mode 100644
index 0000000..58fd1ac
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-with.js
@@ -0,0 +1,9 @@
+function f() {}
+var x = {};
+
+with (x) {
+ f();
+}
+
+with (x)
+ f();
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/json-cmp.js b/tools/node_modules/expresso/deps/jscoverage/tests/json-cmp.js
new file mode 100644
index 0000000..37e9144
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/json-cmp.js
@@ -0,0 +1,65 @@
+/*
+ json-cmp.js - compare JSON files
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+function json_equals(json1, json2) {
+ if (json1 === null || json2 === null) {
+ return json1 === json2;
+ }
+ else if (json1.constructor === Array && json2.constructor === Array) {
+ if (json1.length !== json2.length) {
+ return false;
+ }
+ var length = json1.length;
+ for (var i = 0; i < length; i++) {
+ if (! json_equals(json1[i], json2[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ else if (typeof(json1) === 'object' && typeof(json2) === 'object') {
+ var i;
+ for (i in json1) {
+ if (! (i in json2)) {
+ return false;
+ }
+ if (! json_equals(json1[i], json2[i])) {
+ return false;
+ }
+ }
+ for (i in json2) {
+ if (! (i in json1)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ else {
+ return json1 === json2;
+ }
+}
+
+if (json_equals(EXPECTED, ACTUAL)) {
+ quit(0);
+}
+else {
+ print(EXPECTED.toSource());
+ print(ACTUAL.toSource());
+ quit(1);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/json.c b/tools/node_modules/expresso/deps/jscoverage/tests/json.c
new file mode 100644
index 0000000..3522d86
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/json.c
@@ -0,0 +1,48 @@
+/*
+ json.c - test JSON manipulation
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "instrument-js.h"
+#include "stream.h"
+#include "util.h"
+
+bool jscoverage_highlight = true;
+
+int main(void) {
+ jscoverage_init();
+
+ Stream * stream = Stream_new(0);
+
+ FILE * f = xfopen("store.json", "r");
+ Stream_write_file_contents(stream, f);
+ fclose(f);
+
+ Coverage * coverage = Coverage_new();
+ int result = jscoverage_parse_json(coverage, stream->data, stream->length);
+ assert(result == 0);
+
+ Coverage_delete(coverage);
+ Stream_delete(stream);
+ jscoverage_cleanup();
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/json.sh b/tools/node_modules/expresso/deps/jscoverage/tests/json.sh
new file mode 100755
index 0000000..2f84d4d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/json.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# json.sh - test JSON parsing
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./json
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.c b/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.c
new file mode 100644
index 0000000..027cff6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.c
@@ -0,0 +1,42 @@
+/*
+ mkdirs.c - test `mkdirs' function
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+void cleanup(void) {
+ system("rm -fr DIR");
+}
+
+int main(void) {
+ atexit(cleanup);
+
+ system("rm -fr DIR");
+
+ mkdirs("DIR/a/b");
+
+ struct stat buf;
+ xstat("DIR/a/b", &buf);
+ assert(S_ISDIR(buf.st_mode));
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.sh b/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.sh
new file mode 100755
index 0000000..f1dc922
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# mkdirs.sh - test `mkdirs' function
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./mkdirs
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/netcat.pl b/tools/node_modules/expresso/deps/jscoverage/tests/netcat.pl
new file mode 100644
index 0000000..5df75be
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/netcat.pl
@@ -0,0 +1,35 @@
+use strict;
+use warnings;
+
+use Socket;
+
+binmode(STDIN);
+$| = 1;
+binmode(STDOUT);
+
+if (@ARGV != 2) {
+ die "Usage: netcat.pl HOST PORT\n";
+}
+
+my $host = shift;
+my $port = shift;
+
+my $address = inet_aton($host) or die;
+my $address_and_port = sockaddr_in($port, $address);
+my $protocol = getprotobyname('tcp');
+socket(SOCKET, PF_INET, SOCK_STREAM, $protocol) or die;
+
+my $old = select(SOCKET);
+$| = 1;
+select($old);
+binmode(SOCKET);
+
+connect(SOCKET, $address_and_port) or die;
+while (<STDIN>) {
+ print SOCKET $_;
+}
+while (<SOCKET>) {
+ print;
+}
+close(SOCKET);
+exit 0; \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.expected.err
new file mode 100644
index 0000000..c6e2707
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.expected.err
@@ -0,0 +1,2 @@
+jscoverage: missing argument
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.sh b/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.sh
new file mode 100755
index 0000000..73eb586
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+# no-arguments.sh - test jscoverage with no arguments
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+export PATH=.:..:$PATH
+
+trap 'rm -fr OUT ERR' 1 2 3 15
+
+$VALGRIND jscoverage > OUT 2> ERR && exit 1
+test ! -s OUT
+diff --strip-trailing-cr no-arguments.expected.err ERR
+
+rm -fr OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/no-instrument-requires-argument.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/no-instrument-requires-argument.expected.err
new file mode 100644
index 0000000..fdceb30
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/no-instrument-requires-argument.expected.err
@@ -0,0 +1,2 @@
+jscoverage: --no-instrument: option requires an argument
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-request-body.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-request-body.sh
new file mode 100755
index 0000000..0532f38
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-request-body.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# proxy-bad-request-body.sh - test jscoverage-server --proxy with a bad request body
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+}
+
+shutdown_perl() {
+ wget -q -O- --post-data= http://127.0.0.1:8000/perl-shutdown > /dev/null
+ wait $origin_server_pid
+}
+
+cleanup() {
+ shutdown
+ shutdown_perl
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+cd recursive
+perl ../server.pl > /dev/null 2> /dev/null &
+origin_server_pid=$!
+cd ..
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+./http-client-bad-body 8080 http://127.0.0.1:8000/
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body-javascript.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body-javascript.sh
new file mode 100755
index 0000000..df63686
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body-javascript.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+# proxy-bad-response-body-javascript.sh - test jscoverage-server --proxy with bad JavaScript response body
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+ kill -9 $origin_server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+./http-server-bad-body &
+origin_server_pid=$!
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+echo 200 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/script.js 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.expected.err
new file mode 100644
index 0000000..9dd02ee
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.expected.err
@@ -0,0 +1 @@
+Warning: error copying response body from server to client
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.sh
new file mode 100755
index 0000000..aace044
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# proxy-bad-response-body.sh - test jscoverage-server --proxy with bad response body
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+ kill -9 $origin_server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+./http-server-bad-body &
+origin_server_pid=$!
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+echo 200 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/index.html 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+diff --strip-trailing-cr proxy-bad-response-body.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-headers.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-headers.sh
new file mode 100755
index 0000000..e21e22a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-headers.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+# proxy-bad-response-headers.sh - test jscoverage-server --proxy with bad response headers
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+ kill -9 $origin_server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+./http-server-bad-headers &
+origin_server_pid=$!
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+echo 502 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/index.html 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-no-server.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-no-server.sh
new file mode 100755
index 0000000..75f34f6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-no-server.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+# proxy-no-server.sh - test jscoverage-server --proxy without origin server
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+echo 504 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:1/index.html 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-url.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-url.sh
new file mode 100755
index 0000000..413f116
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-url.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+# proxy-url.sh - test jscoverage-server --proxy with different URLs
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+ if [ "$origin_server_pid" != "" ]
+ then
+ kill -9 $origin_server_pid
+ fi
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+echo 504 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:/index.html 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+./http-client-bad-url 8080 http://127.0.0.1:123456/index.html
+./http-client-bad-url 8080 http://127.0.0.1:xyz/index.html
+
+cd recursive
+perl ../server.pl > /dev/null 2> /dev/null &
+origin_server_pid=$!
+cd ..
+
+sleep $delay
+
+./http-client-bad-url 8080 http://127.0.0.1:8000
+./http-client-bad-url 8080 'http://127.0.0.1:8000?foo'
+./http-client-bad-url 8080 'foo'
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy.sh
new file mode 100755
index 0000000..903ab62
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy.sh
@@ -0,0 +1,143 @@
+#!/bin/sh
+# proxy.sh - test jscoverage-server --proxy
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+}
+
+shutdown_perl() {
+ wget -q -O- --post-data= http://127.0.0.1:8000/perl-shutdown > /dev/null
+ wait $origin_server_pid
+}
+
+cleanup() {
+ rm -fr EXPECTED ACTUAL DIR OUT
+ shutdown
+ shutdown_perl
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+cd recursive
+perl ../server.pl > /dev/null 2> /dev/null &
+origin_server_pid=$!
+cd ..
+
+rm -fr DIR
+mkdir DIR
+$VALGRIND jscoverage-server --no-highlight --proxy --report-dir=DIR > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/index.html | diff recursive/index.html -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/style.css | diff recursive/style.css -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/unix.txt | diff recursive/unix.txt -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/windows.txt | diff recursive/windows.txt -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/image.png | diff recursive/image.png -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/x | diff recursive/x -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/1.html | diff recursive/1/1.html -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/1.css | diff recursive/1/1.css -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/2/2.html | diff recursive/1/2/2.html -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/2/2.css | diff recursive/1/2/2.css -
+
+# test localhost
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://localhost:8000/index.html | diff recursive/index.html -
+
+# test actual hostname
+h=`hostname`
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://${h}:8000/index.html | diff recursive/index.html -
+
+# test query string
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/index.html?foo | diff recursive/index.html -
+
+# test POST
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' --post-file=recursive/index.html http://127.0.0.1:8000/ | diff recursive/index.html -
+
+# test javascript
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/script.js > OUT
+cat ../report.js recursive.expected/script.js | sed 's/@PREFIX@/http:\/\/127.0.0.1:8000\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/1.js > OUT
+cat ../report.js recursive.expected/1/1.js | sed 's/@PREFIX@/http:\/\/127.0.0.1:8000\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/2/2.js > OUT
+cat ../report.js recursive.expected/1/2/2.js | sed 's/@PREFIX@/http:\/\/127.0.0.1:8000\//g' | diff --strip-trailing-cr - OUT
+
+## test jscoverage
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://siliconforks.com/jscoverage.html | diff ../jscoverage.html -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://siliconforks.com/jscoverage.css | diff ../jscoverage.css -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://siliconforks.com/jscoverage-throbber.gif | diff ../jscoverage-throbber.gif -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://siliconforks.com/jscoverage.js > OUT
+echo -e 'jscoverage_isServer = true;\r' | cat ../jscoverage.js - | diff - OUT
+
+# load/store
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' --post-data='{}' http://siliconforks.com/jscoverage-store > /dev/null
+echo -n '{}' | diff - DIR/jscoverage.json
+diff ../jscoverage.html DIR/jscoverage.html
+diff ../jscoverage.css DIR/jscoverage.css
+diff ../jscoverage-throbber.gif DIR/jscoverage-throbber.gif
+echo -e 'jscoverage_isReport = true;\r' | cat ../jscoverage.js - | diff - DIR/jscoverage.js
+
+# send it an FTP request
+echo 400 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 ftp://ftp.example.com 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# nonexistent domain
+echo 504 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://nonexistent 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# 404 not found
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/missing 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://siliconforks.com/jscoverage-missing 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+## send it a server request
+#echo 400 > EXPECTED
+#! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/ 2> /dev/null > ACTUAL
+#diff EXPECTED ACTUAL
+
+# kill $proxy_server_pid
+shutdown
+
+$VALGRIND jscoverage-server --no-highlight --port=8081 --proxy --report-dir=DIR --no-instrument=http://127.0.0.1:8000/1/ &
+proxy_server_pid=$!
+proxy_server_port=8081
+
+sleep $delay
+
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8081/' http://127.0.0.1:8000/script.js > OUT
+cat ../report.js recursive.expected/script.js | sed 's/@PREFIX@/http:\/\/127.0.0.1:8000\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8081/' http://127.0.0.1:8000/1/1.js | diff --strip-trailing-cr recursive/1/1.js -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8081/' http://127.0.0.1:8000/1/2/2.js | diff --strip-trailing-cr recursive/1/2/2.js -
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-crlf.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-crlf.sh
new file mode 100755
index 0000000..c95ee81
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-crlf.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+# recursive-crlf.sh - test recursive directory instrumentation, CRLF line endings
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr TMP EXPECTED DIR OUT' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr TMP EXPECTED DIR OUT
+
+mkdir -p TMP/1/2
+cd recursive
+cp *.html *.js *.css *.png *.txt x ../TMP
+cp 1/1.html 1/1.js 1/1.css ../TMP/1
+cp 1/2/2.html 1/2/2.js 1/2/2.css ../TMP/1/2
+cd ..
+unix2dos TMP/script.js > /dev/null 2> /dev/null
+unix2dos TMP/1/1.js > /dev/null 2> /dev/null
+unix2dos TMP/1/2/2.js > /dev/null 2> /dev/null
+
+mkdir -p EXPECTED/1/2
+cd recursive.expected
+cp *.html *.js *.css *.png *.txt x ../EXPECTED
+cp 1/1.html 1/1.js 1/1.css ../EXPECTED/1
+cp 1/2/2.html 1/2/2.js 1/2/2.css ../EXPECTED/1/2
+cd ..
+cat recursive.expected/script.js | sed 's/@PREFIX@//g' > EXPECTED/script.js
+cat recursive.expected/1/1.js | sed 's/@PREFIX@//g' > EXPECTED/1/1.js
+cat recursive.expected/1/2/2.js | sed 's/@PREFIX@//g' > EXPECTED/1/2/2.js
+cp ../jscoverage.css ../jscoverage-highlight.css ../jscoverage-ie.css \
+ ../jscoverage-throbber.gif \
+ ../jscoverage.html \
+ ../jscoverage.js EXPECTED
+
+$VALGRIND jscoverage --no-highlight TMP DIR
+test -d DIR
+diff --strip-trailing-cr -r EXPECTED DIR
+
+$VALGRIND jscoverage --no-highlight --verbose TMP DIR > OUT
+test -d DIR
+sort OUT -o OUT
+diff --strip-trailing-cr verbose.expected.out OUT
+diff --strip-trailing-cr -r EXPECTED DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.c b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.c
new file mode 100644
index 0000000..2f1a7bf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.c
@@ -0,0 +1,93 @@
+/*
+ recursive-dir-list.c - test `make_recursive_dir_list' function
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+struct Expected {
+ int count;
+ const char * name;
+};
+
+void cleanup(void) {
+ system("rm -fr DIR");
+}
+
+void touch(const char * file) {
+ FILE * f = fopen(file, "w");
+ if (f == NULL) {
+ fatal("cannot open file: %s", file);
+ }
+ fclose(f);
+}
+
+void verify(struct Expected * expected, struct DirListEntry * actual, int length) {
+ struct DirListEntry * p = actual;
+ while (p != NULL) {
+ char * name = p->name;
+ for (int i = 0; i < length; i++) {
+ if (strcmp(expected[i].name, name) == 0) {
+ expected[i].count++;
+ break;
+ }
+ }
+ p = p->next;
+ }
+
+ /* now verify the totals */
+ for (int i = 0; i < length; i++) {
+ assert(expected[i].count == 1);
+ }
+}
+
+int main(void) {
+ atexit(cleanup);
+
+ system("rm -fr DIR");
+
+ /* simple case */
+ xmkdir("DIR");
+ xmkdir("DIR/a");
+ xmkdir("DIR/a/b");
+ xmkdir("DIR/c");
+ xmkdir("DIR/d");
+ touch("DIR/0");
+ touch("DIR/a/1");
+ touch("DIR/a/b/2");
+ touch("DIR/c/3");
+ touch("DIR/c/4");
+ /* DIR/d is empty */
+
+ struct Expected expected[] = {
+ {0, "c/4"},
+ {0, "c/3"},
+ {0, "a/b/2"},
+ {0, "a/1"},
+ {0, "0"},
+ };
+
+ struct DirListEntry * list = make_recursive_dir_list("DIR");
+ verify(expected, list, sizeof(expected) / sizeof(expected[0]));
+ free_dir_list(list);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.sh
new file mode 100755
index 0000000..d232a0a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# recursive-dir-list.sh - test `make_recursive_dir_list' function
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./recursive-dir-list
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-exclude.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-exclude.sh
new file mode 100755
index 0000000..4e5d42e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-exclude.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# recursive-exclude.sh - test `--exclude' option
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr EXPECTED DIR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR
+rm -fr EXPECTED
+cp -r recursive.expected EXPECTED
+find EXPECTED -name .svn | xargs rm -fr
+rm EXPECTED/script.js
+cat recursive.expected/1/1.js | sed 's/@PREFIX@//g' > EXPECTED/1/1.js
+rm -fr EXPECTED/1/2
+cp ../jscoverage.css ../jscoverage-highlight.css ../jscoverage-ie.css \
+ ../jscoverage-throbber.gif \
+ ../jscoverage.html \
+ ../jscoverage.js EXPECTED
+
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn --exclude 1/2 --exclude=script.js recursive DIR
+test -d DIR
+diff --strip-trailing-cr -r EXPECTED DIR
+
+rm -fr EXPECTED DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-fatal.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-fatal.sh
new file mode 100755
index 0000000..7fdd151
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-fatal.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+# recursive-fatal.sh - test various fatal errors
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr DIR DIR2 SYM ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR DIR2 SYM ERR
+
+mkdir DIR
+$VALGRIND jscoverage DIR DIR 2>ERR && exit 1
+
+$VALGRIND jscoverage DIR DIR/1 2>ERR && exit 1
+
+mkdir DIR/1
+$VALGRIND jscoverage DIR/1 DIR 2>ERR && exit 1
+
+cp -r DIR SYM
+$VALGRIND jscoverage DIR SYM 2>ERR && exit 1
+
+$VALGRIND jscoverage SYM DIR 2>ERR && exit 1
+
+rm -fr DIR DIR2 SYM ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-no-instrument.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-no-instrument.sh
new file mode 100755
index 0000000..1203bec
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-no-instrument.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# recursive-no-instrument.sh - test `--no-instrument' option
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr EXPECTED DIR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR
+rm -fr EXPECTED
+cp -r recursive.expected EXPECTED
+find EXPECTED -name .svn | xargs rm -fr
+cat recursive/script.js | sed 's/@PREFIX@//g' > EXPECTED/script.js
+cat recursive.expected/1/1.js | sed 's/@PREFIX@//g' > EXPECTED/1/1.js
+cat recursive/1/2/2.js | sed 's/@PREFIX@//g' > EXPECTED/1/2/2.js
+cp ../jscoverage.css ../jscoverage-highlight.css ../jscoverage-ie.css \
+ ../jscoverage-throbber.gif \
+ ../jscoverage.html \
+ ../jscoverage.js EXPECTED
+
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn --no-instrument 1/2 --no-instrument=script.js recursive DIR
+test -d DIR
+diff --strip-trailing-cr -r EXPECTED DIR
+
+rm -fr EXPECTED DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.css
new file mode 100644
index 0000000..563d20e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.css
@@ -0,0 +1,3 @@
+body {
+ color: green;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.html
new file mode 100644
index 0000000..e292b54
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>1</title>
+<script type="text/javascript" src="1.js"></script>
+<link rel="stylesheet" type="text/css" href="1.css">
+</head>
+<body>
+1<br>
+<a href="2/2.html">Next</a>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.js
new file mode 100644
index 0000000..e237b0f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['@PREFIX@1/1.js']) {
+ _$jscoverage['@PREFIX@1/1.js'] = [];
+ _$jscoverage['@PREFIX@1/1.js'][1] = 0;
+}
+_$jscoverage['@PREFIX@1/1.js'][1]++;
+alert("This is 1");
+_$jscoverage['@PREFIX@1/1.js'].source = ["alert(\"This is 1\");"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.css
new file mode 100644
index 0000000..7cfe2bf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.css
@@ -0,0 +1,3 @@
+body {
+ color: blue;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.html
new file mode 100644
index 0000000..bb83ca6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>2</title>
+<script type="text/javascript" src="2.js"></script>
+<link rel="stylesheet" type="text/css" href="2.css">
+</head>
+<body>
+2
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.js
new file mode 100644
index 0000000..09184a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['@PREFIX@1/2/2.js']) {
+ _$jscoverage['@PREFIX@1/2/2.js'] = [];
+ _$jscoverage['@PREFIX@1/2/2.js'][1] = 0;
+}
+_$jscoverage['@PREFIX@1/2/2.js'][1]++;
+alert("This is 2");
+_$jscoverage['@PREFIX@1/2/2.js'].source = ["alert(\"This is 2\");"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/image.png b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/image.png
new file mode 100644
index 0000000..da5ef5d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/image.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/index.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/index.html
new file mode 100644
index 0000000..90b7789
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/index.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Test</title>
+<script type="text/javascript" src="script.js"></script>
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+Test<br>
+<a href="1/1.html">Next</a>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/script.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/script.js
new file mode 100644
index 0000000..d9bf48b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/script.js
@@ -0,0 +1,19 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['@PREFIX@script.js']) {
+ _$jscoverage['@PREFIX@script.js'] = [];
+ _$jscoverage['@PREFIX@script.js'][1] = 0;
+ _$jscoverage['@PREFIX@script.js'][4] = 0;
+ _$jscoverage['@PREFIX@script.js'][5] = 0;
+}
+_$jscoverage['@PREFIX@script.js'][1]++;
+alert("hello");
+_$jscoverage['@PREFIX@script.js'][4]++;
+if ("a" < "b" && "a" > "b") {
+ _$jscoverage['@PREFIX@script.js'][5]++;
+ alert("?");
+}
+_$jscoverage['@PREFIX@script.js'].source = ["alert(\"hello\");","","// test formatting &amp;lt; &amp;gt; &amp;amp;","if ('a' &lt; 'b' &amp;&amp; 'a' &gt; 'b') {"," alert(\"?\");","}"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/style.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/style.css
new file mode 100644
index 0000000..60f1eab
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/style.css
@@ -0,0 +1,3 @@
+body {
+ color: red;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/unix.txt b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/unix.txt
new file mode 100644
index 0000000..01e79c3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/unix.txt
@@ -0,0 +1,3 @@
+1
+2
+3
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/windows.txt b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/windows.txt
new file mode 100644
index 0000000..294d779
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/windows.txt
@@ -0,0 +1,3 @@
+1
+2
+3
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/x b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/x
new file mode 100644
index 0000000..587be6b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/x
@@ -0,0 +1 @@
+x
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.sh
new file mode 100755
index 0000000..f7c0d09
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+# recursive.sh - test recursive directory instrumentation
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr EXPECTED DIR OUT' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR
+rm -fr EXPECTED
+cp -r recursive.expected EXPECTED
+find EXPECTED -name .svn | xargs rm -fr
+cat recursive.expected/script.js | sed 's/@PREFIX@//g' > EXPECTED/script.js
+cat recursive.expected/1/1.js | sed 's/@PREFIX@//g' > EXPECTED/1/1.js
+cat recursive.expected/1/2/2.js | sed 's/@PREFIX@//g' > EXPECTED/1/2/2.js
+cp ../jscoverage.css ../jscoverage-highlight.css ../jscoverage-ie.css \
+ ../jscoverage-throbber.gif \
+ ../jscoverage.html \
+ ../jscoverage.js EXPECTED
+
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn recursive DIR
+test -d DIR
+diff --strip-trailing-cr -r EXPECTED DIR
+
+$VALGRIND jscoverage --no-highlight --verbose --exclude .svn --exclude 1/.svn --exclude 1/2/.svn recursive DIR >OUT
+test -d DIR
+sort OUT -o OUT
+diff --strip-trailing-cr verbose.expected.out OUT
+diff --strip-trailing-cr -r EXPECTED DIR
+
+# does it handle an argument with a slash at the end?
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn recursive/ DIR
+diff --strip-trailing-cr -r EXPECTED DIR
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn recursive DIR/
+diff --strip-trailing-cr -r EXPECTED DIR
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn recursive/ DIR/
+diff --strip-trailing-cr -r EXPECTED DIR
+
+rm -fr EXPECTED DIR OUT
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.css
new file mode 100644
index 0000000..563d20e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.css
@@ -0,0 +1,3 @@
+body {
+ color: green;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.html
new file mode 100644
index 0000000..e292b54
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>1</title>
+<script type="text/javascript" src="1.js"></script>
+<link rel="stylesheet" type="text/css" href="1.css">
+</head>
+<body>
+1<br>
+<a href="2/2.html">Next</a>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.js
new file mode 100644
index 0000000..5f73e02
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.js
@@ -0,0 +1 @@
+alert("This is 1");
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.css
new file mode 100644
index 0000000..7cfe2bf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.css
@@ -0,0 +1,3 @@
+body {
+ color: blue;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.html
new file mode 100644
index 0000000..bb83ca6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>2</title>
+<script type="text/javascript" src="2.js"></script>
+<link rel="stylesheet" type="text/css" href="2.css">
+</head>
+<body>
+2
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.js
new file mode 100644
index 0000000..e0f7496
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.js
@@ -0,0 +1 @@
+alert("This is 2");
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/image.png b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/image.png
new file mode 100644
index 0000000..da5ef5d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/image.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/index.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/index.html
new file mode 100644
index 0000000..90b7789
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/index.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Test</title>
+<script type="text/javascript" src="script.js"></script>
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+Test<br>
+<a href="1/1.html">Next</a>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/script.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/script.js
new file mode 100644
index 0000000..1671f23
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/script.js
@@ -0,0 +1,6 @@
+alert("hello");
+
+// test formatting &lt; &gt; &amp;
+if ('a' < 'b' && 'a' > 'b') {
+ alert("?");
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/style.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/style.css
new file mode 100644
index 0000000..60f1eab
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/style.css
@@ -0,0 +1,3 @@
+body {
+ color: red;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/unix.txt b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/unix.txt
new file mode 100644
index 0000000..01e79c3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/unix.txt
@@ -0,0 +1,3 @@
+1
+2
+3
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/windows.txt b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/windows.txt
new file mode 100644
index 0000000..294d779
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/windows.txt
@@ -0,0 +1,3 @@
+1
+2
+3
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/x b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/x
new file mode 100644
index 0000000..587be6b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/x
@@ -0,0 +1 @@
+x
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.expected.err
new file mode 100644
index 0000000..4f9362a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.expected.err
@@ -0,0 +1 @@
+jscoverage: source and destination are the same
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.sh b/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.sh
new file mode 100755
index 0000000..e07867b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# same-directory.sh - test with source and destination same directory
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr OUT ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+$VALGRIND jscoverage javascript javascript > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr same-directory.expected.err ERR
+
+rm -fr OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-bad-requests.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-bad-requests.sh
new file mode 100755
index 0000000..e85a18d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-bad-requests.sh
@@ -0,0 +1,104 @@
+#!/bin/sh
+# server-bad-requests.sh - test jscoverage-server with bad requests
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+ rm -fr EXPECTED ACTUAL OUT ERR
+}
+
+bad_request() {
+ /bin/echo -ne "$1" | $NETCAT 127.0.0.1 $server_port > OUT 2> ERR
+ echo 'HTTP/1.1 400 Bad Request' > EXPECTED
+ head -n 1 OUT > ACTUAL
+ diff --strip-trailing-cr EXPECTED ACTUAL
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+if which netcat > /dev/null 2> /dev/null
+then
+ NETCAT=netcat
+elif which nc > /dev/null 2> /dev/null
+then
+ NETCAT=nc
+else
+ NETCAT='perl netcat.pl';
+fi
+
+rm -fr EXPECTED ACTUAL OUT ERR
+$VALGRIND jscoverage-server --port 8000 > /dev/null 2> /dev/null &
+server_pid=$!
+server_port=8000
+
+sleep $delay
+
+# send NUL in Request-Line
+bad_request 'GET \0000 HTTP/1.1\r\n\r\n'
+
+# send empty Request-Line
+bad_request '\r\n\r\n'
+
+# send bad Request-Line
+bad_request ' \r\n\r\n'
+bad_request 'GET\r\n\r\n'
+bad_request 'GET \r\n\r\n'
+bad_request 'GET \r\n\r\n'
+bad_request 'GET /\r\n\r\n'
+bad_request 'GET / \r\n\r\n'
+
+# bad Host header
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nHost: foo:bar\r\n\r\n'
+
+# NUL in header
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nFoo: \0000\r\n\r\n'
+
+# missing header
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\n: bar\r\n\r\n'
+
+# missing header value
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nFoo:\r\n\r\n'
+
+# bad Transfer-Encoding
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo;\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar = "\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar = "\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar = "\\\0200"\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar = "\0177"\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar = ;\r\n\r\n'
+
+# bad Content-Length
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nContent-Length: 4294967296\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nContent-Length: 4294967300\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nContent-Length: foo\r\n\r\n'
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-close-after-request.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-close-after-request.sh
new file mode 100755
index 0000000..4a27b33
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-close-after-request.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+# server-close-after-request.sh - test jscoverage-server with client that closes connection after request
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --port 8000 > OUT 2> ERR &
+server_pid=$!
+server_port=8000
+
+sleep $delay
+
+./http-client-close-after-request
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-content-types.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-content-types.sh
new file mode 100755
index 0000000..69e6b6a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-content-types.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+# server-content-types.sh - test jscoverage-server Content-Type headers
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+ rm -f x x.y
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo text/html > EXPECTED
+! curl -f -w '%{content_type}\n' -o /dev/null http://127.0.0.1:8080/recursive/index.html 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+echo text/plain > EXPECTED
+! curl -f -w '%{content_type}\n' -o /dev/null http://127.0.0.1:8080/recursive/unix.txt 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+echo text/plain > EXPECTED
+! curl -f -w '%{content_type}\n' -o /dev/null http://127.0.0.1:8080/recursive/windows.txt 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+touch x
+echo application/octet-stream > EXPECTED
+! curl -f -w '%{content_type}\n' -o /dev/null http://127.0.0.1:8080/x 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+touch x.y
+echo application/octet-stream > EXPECTED
+! curl -f -w '%{content_type}\n' -o /dev/null http://127.0.0.1:8080/x.y 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.expected b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.expected
new file mode 100644
index 0000000..2a9fdd3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.expected
@@ -0,0 +1,4 @@
+<a href=".">.</a><br>
+<a href="..">..</a><br>
+<a href="1&amp;2.txt">1&amp;2.txt</a><br>
+<a href="1%202.txt">1 2.txt</a><br>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.sh
new file mode 100755
index 0000000..fca3c2f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# server-directory-listing.sh - test jscoverage-server directory listings
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+mkdir DIR
+$VALGRIND jscoverage-server --document-root=DIR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+# make some funny files
+echo x > 'DIR/1&2.txt'
+echo x > 'DIR/1 2.txt'
+
+sort server-directory-listing.expected -o EXPECTED
+wget -q -O- http://127.0.0.1:8080/ > ACTUAL
+sort ACTUAL -o ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+rm -fr DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-redirect.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-redirect.sh
new file mode 100755
index 0000000..179cefd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-redirect.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+# server-directory-redirect.sh - test jscoverage-server directory redirect
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --document-root=recursive > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 'HTTP/1.1 301 Moved Permanently' > EXPECTED
+# curl -f doesn't seem to work with 3xx
+! curl -D ACTUAL http://127.0.0.1:8080/1 2> /dev/null > /dev/null
+cat ACTUAL | tr -d '\r' | head -1 | diff EXPECTED -
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-encoded-url.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-encoded-url.sh
new file mode 100755
index 0000000..e205c18
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-encoded-url.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# server-encoded-url.sh - test jscoverage-server with encoded URL
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+}
+
+cleanup() {
+ shutdown
+ # rm -fr DIR
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+mkdir DIR
+$VALGRIND jscoverage-server --document-root=DIR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+# make some funny files
+echo x > 'DIR/1+2.txt'
+echo x > 'DIR/1&2.txt'
+echo x > 'DIR/1 2.txt'
+
+wget -q -O- 'http://127.0.0.1:8080/1%2B2.txt' | diff 'DIR/1+2.txt' -
+wget -q -O- 'http://127.0.0.1:8080/1%2b2.txt' | diff 'DIR/1+2.txt' -
+wget -q -O- 'http://127.0.0.1:8080/1%262.txt' | diff 'DIR/1&2.txt' -
+wget -q -O- 'http://127.0.0.1:8080/1%202.txt' | diff 'DIR/1 2.txt' -
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-error.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-error.sh
new file mode 100755
index 0000000..c2a47c4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-error.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+# server-error.sh - test jscoverage-server with invalid options
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+export PATH=.:..:$PATH
+
+! jscoverage-server --report-dir > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --document-root > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --ip-address > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --no-instrument > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --port > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --foo > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server foo > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --port x > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --port 123456 > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --encoding > OUT 2> ERR
+test ! -s OUT
+test -s ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-help.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-help.sh
new file mode 100755
index 0000000..b644549
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-help.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+# server-help.sh - test jscoverage-server --help
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+export PATH=.:..:$PATH
+
+jscoverage-server --help > OUT 2> ERR
+diff --strip-trailing-cr ../jscoverage-server-help.txt OUT
+> TMP
+diff TMP ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.expected.out b/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.expected.out
new file mode 100644
index 0000000..b1838fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.expected.out
@@ -0,0 +1,4 @@
+Starting HTTP server on @ADDRESS@:8080
+GET / HTTP/1.0
+POST /jscoverage-shutdown HTTP/1.0
+Stopping HTTP server
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.sh
new file mode 100755
index 0000000..b4a5770
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+# server-ip-address.sh - test jscoverage-server --ip-address
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ # shutdown
+ :
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --verbose --ip-address=0.0.0.0 > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:${server_port}/ > /dev/null
+
+shutdown
+
+cat server-ip-address.expected.out | sed 's/@ADDRESS@/0.0.0.0/g' > EXPECTED
+cat OUT | tr -d '\r' > ACTUAL
+diff EXPECTED ACTUAL
+
+$VALGRIND jscoverage-server --verbose --ip-address 127.0.0.1 > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:${server_port}/ > /dev/null
+
+shutdown
+
+cat server-ip-address.expected.out | sed 's/@ADDRESS@/127.0.0.1/g' > EXPECTED
+cat OUT | tr -d '\r' > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown-bad-method.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown-bad-method.sh
new file mode 100755
index 0000000..d6fa877
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown-bad-method.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+# server-shutdown-bad-method.sh - test jscoverage-server --shutdown with GET
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 405 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-shutdown 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.expected.err
new file mode 100644
index 0000000..5dd4646
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.expected.err
@@ -0,0 +1 @@
+POST /jscoverage-shutdown
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.sh
new file mode 100755
index 0000000..c91e6bd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+# server-shutdown.sh - test jscoverage-server --shutdown
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+cleanup() {
+ kill -9 $origin_server_pid
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+perl server.pl > OUT 2> ERR &
+origin_server_pid=$!
+
+sleep $delay
+
+$VALGRIND jscoverage-server --port 8000 --shutdown
+cat ERR | cut -d'"' -f2 | diff --strip-trailing-cr server-shutdown.expected.err -
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-special-file.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-special-file.sh
new file mode 100755
index 0000000..76196fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-special-file.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+# server-special-file.sh - test jscoverage-server with special file
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+# skip on mingw
+uname=`uname`
+case "$uname" in
+ MINGW*)
+ exit 77
+ ;;
+esac
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ rm -f DIR/foo
+ rm -fr DIR
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+mkdir DIR
+mkfifo DIR/foo
+$VALGRIND jscoverage-server > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/DIR/foo 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-directory.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-directory.sh
new file mode 100755
index 0000000..4de4ba8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-directory.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+# server-unreadable-directory.sh - test jscoverage-server with unreadable directory
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+# skip on windows
+uname=`uname`
+case "$uname" in
+ CYGWIN* | MINGW*)
+ exit 77
+ ;;
+esac
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ rmdir DIR
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+mkdir DIR
+chmod 000 DIR
+$VALGRIND jscoverage-server > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/DIR/ 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-file.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-file.sh
new file mode 100755
index 0000000..20e1369
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-file.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+# server-unreadable-file.sh - test jscoverage-server with unreadable file
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+# skip on windows
+uname=`uname`
+case "$uname" in
+ CYGWIN* | MINGW*)
+ exit 77
+ ;;
+esac
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ rm -fr DIR
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+mkdir DIR
+echo Hello > DIR/index.html
+chmod 000 DIR/index.html
+$VALGRIND jscoverage-server > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/DIR/index.html 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.expected.err
new file mode 100644
index 0000000..e578f28
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.expected.err
@@ -0,0 +1,4 @@
+Starting HTTP server on 127.0.0.1:8080
+GET /index.html HTTP/1.0
+POST /jscoverage-shutdown HTTP/1.0
+Stopping HTTP server
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.sh
new file mode 100755
index 0000000..174692e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# server-verbose.sh - test jscoverage-server --verbose
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ # shutdown
+ :
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --document-root=recursive --verbose > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:8080/index.html | diff --strip-trailing-cr recursive/index.html -
+
+shutdown
+
+sleep $delay
+
+cat OUT | tr -d '\r' | diff server-verbose.expected.err -
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-version.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-version.sh
new file mode 100755
index 0000000..c2a629f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-version.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# server-version.sh - test jscoverage-server --version
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+export PATH=.:..:$PATH
+
+jscoverage-server --version > OUT 2> ERR
+test -s OUT
+test ! -s ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server.pl b/tools/node_modules/expresso/deps/jscoverage/tests/server.pl
new file mode 100644
index 0000000..86064b1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server.pl
@@ -0,0 +1,61 @@
+use strict;
+use warnings;
+
+use HTTP::Daemon;
+use HTTP::Status;
+
+$|++;
+
+my $d = HTTP::Daemon->new(LocalPort => 8000, ReuseAddr => 1) || die;
+print "Please contact me at: <URL:", $d->url, ">\n";
+my $done = 0;
+while (not $done and my $c = $d->accept) {
+ my $r = $c->get_request;
+ if (not defined($r)) {
+ print "Error: ", $c->reason, "\n";
+ $c->close;
+ undef($c);
+ next;
+ }
+ print STDERR $r->method, ' ', $r->url, "\n";
+ $c->force_last_request;
+ if ($r->method eq 'GET') {
+ my $file = substr($r->url->path, 1);
+ if (open FILE, $file) {
+ undef $/;
+ binmode FILE;
+ my $content = <FILE>;
+ close FILE;
+ my @headers = ('Connection' => 'close');
+ if ($file =~ /\.js$/) {
+ push @headers, 'Content-Type' => 'text/javascript';
+ }
+ elsif ($file =~ /\.[^\/]+$/) {
+ push @headers, 'Content-Type' => 'application/octet-stream';
+ }
+ else {
+ # do nothing - no Content-Type
+ }
+ my $response = HTTP::Response->new(200, 'OK', \@headers, $content);
+ $c->send_response($response);
+ }
+ else {
+ my $response = HTTP::Response->new(404, 'Not found', ['Connection' => 'close'], 'Not found');
+ $c->send_response($response);
+ }
+ }
+ elsif ($r->method eq 'POST') {
+ if ($r->url->path eq '/perl-shutdown') {
+ $done = 1;
+ }
+ my $content = $r->content;
+ my $response = HTTP::Response->new(200, 'OK', ['Connection' => 'close'], $content);
+ $c->send_response($response);
+ }
+ else {
+ $c->send_error(RC_FORBIDDEN);
+ }
+ $c->close;
+ undef($c);
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server.sh
new file mode 100755
index 0000000..e936fa1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server.sh
@@ -0,0 +1,216 @@
+#!/bin/sh
+# server.sh - test jscoverage-server
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ rm -fr EXPECTED ACTUAL DIR OUT
+ # kill $server_pid
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+if jscoverage-server --version | grep -q 'iconv\|MultiByteToWideChar'
+then
+ character_encoding_support=yes
+else
+ character_encoding_support=no
+fi
+
+rm -fr EXPECTED ACTUAL DIR OUT
+mkdir DIR
+$VALGRIND jscoverage-server --no-highlight --document-root=recursive --report-dir=DIR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:8080/index.html | diff recursive/index.html -
+wget -q -O- http://127.0.0.1:8080/style.css | diff recursive/style.css -
+wget -q -O- http://127.0.0.1:8080/unix.txt | diff recursive/unix.txt -
+wget -q -O- http://127.0.0.1:8080/windows.txt | diff recursive/windows.txt -
+wget -q -O- http://127.0.0.1:8080/image.png | diff recursive/image.png -
+wget -q -O- http://127.0.0.1:8080/x | diff recursive/x -
+wget -q -O- http://127.0.0.1:8080/1/1.html | diff recursive/1/1.html -
+wget -q -O- http://127.0.0.1:8080/1/1.css | diff recursive/1/1.css -
+wget -q -O- http://127.0.0.1:8080/1/2/2.html | diff recursive/1/2/2.html -
+wget -q -O- http://127.0.0.1:8080/1/2/2.css | diff recursive/1/2/2.css -
+
+# test query string
+wget -q -O- http://127.0.0.1:8080/index.html?foo | diff recursive/index.html -
+
+# test javascript
+wget -q -O- http://127.0.0.1:8080/script.js > OUT
+cat ../report.js recursive.expected/script.js | sed 's/@PREFIX@/\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- http://127.0.0.1:8080/1/1.js > OUT
+cat ../report.js recursive.expected/1/1.js | sed 's/@PREFIX@/\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- http://127.0.0.1:8080/1/2/2.js > OUT
+cat ../report.js recursive.expected/1/2/2.js | sed 's/@PREFIX@/\//g' | diff --strip-trailing-cr - OUT
+
+# test jscoverage
+wget -q -O- http://127.0.0.1:8080/jscoverage.html | diff ../jscoverage.html -
+wget -q -O- http://127.0.0.1:8080/jscoverage.css | diff ../jscoverage.css -
+wget -q -O- http://127.0.0.1:8080/jscoverage-throbber.gif | diff ../jscoverage-throbber.gif -
+wget -q -O- http://127.0.0.1:8080/jscoverage.js > OUT
+echo -e 'jscoverage_isServer = true;\r' | cat ../jscoverage.js - | diff - OUT
+
+# load/store
+wget --post-data='{}' -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+echo -n '{}' | diff - DIR/jscoverage.json
+diff ../jscoverage.html DIR/jscoverage.html
+diff ../jscoverage.css DIR/jscoverage.css
+diff ../jscoverage-throbber.gif DIR/jscoverage-throbber.gif
+echo -e 'jscoverage_isReport = true;\r' | cat ../jscoverage.js - | diff - DIR/jscoverage.js
+
+# 404 not found
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/missing 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-missing 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# 403 forbidden
+echo 403 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/../Makefile.am 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+## send it a proxy request
+#echo 400 > EXPECTED
+#! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://siliconforks.com/ 2> /dev/null > ACTUAL
+#diff EXPECTED ACTUAL
+
+# kill $server_pid
+shutdown
+
+rm -fr DIR
+mkdir DIR
+case `uname` in
+ MINGW*)
+ $VALGRIND jscoverage-server --no-highlight --port=8081 --document-root=recursive --report-dir=DIR --no-instrument=1/ &
+ ;;
+ *)
+ $VALGRIND jscoverage-server --no-highlight --port=8081 --document-root=recursive --report-dir=DIR --no-instrument=/1/ &
+ ;;
+esac
+server_pid=$!
+server_port=8081
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:8081/script.js > OUT
+cat ../report.js recursive.expected/script.js | sed 's/@PREFIX@/\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- http://127.0.0.1:8081/1/1.js | diff --strip-trailing-cr recursive/1/1.js -
+wget -q -O- http://127.0.0.1:8081/1/2/2.js | diff --strip-trailing-cr recursive/1/2/2.js -
+
+# kill $server_pid
+shutdown
+
+$VALGRIND jscoverage-server --no-highlight --port 8082 --document-root recursive --report-dir DIR --no-instrument 1/ &
+server_pid=$!
+server_port=8082
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:8082/script.js > OUT
+cat ../report.js recursive.expected/script.js | sed 's/@PREFIX@/\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- http://127.0.0.1:8082/1/1.js | diff --strip-trailing-cr recursive/1/1.js -
+wget -q -O- http://127.0.0.1:8082/1/2/2.js | diff --strip-trailing-cr recursive/1/2/2.js -
+
+# kill $server_pid
+shutdown
+
+$VALGRIND jscoverage-server --port 8080 --encoding iso-8859-1 --document-root javascript &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+case "$character_encoding_support" in
+ yes)
+ wget -q -O- http://127.0.0.1:8080/javascript-iso-8859-1.js > OUT
+ cat ../report.js javascript.expected/javascript-iso-8859-1.js | sed 's/javascript-iso-8859-1.js/\/javascript-iso-8859-1.js/g' | diff --strip-trailing-cr - OUT
+ ;;
+ *)
+ echo 500 > EXPECTED
+ ! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/javascript-iso-8859-1.js 2> /dev/null > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+esac
+
+# kill $server_pid
+shutdown
+
+$VALGRIND jscoverage-server --no-highlight --port=8080 --encoding=utf-8 --document-root=javascript-utf-8 &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+case "$character_encoding_support" in
+ yes)
+ wget -q -O- http://127.0.0.1:8080/javascript-utf-8.js > OUT
+ cat ../report.js javascript-utf-8.expected/javascript-utf-8.js | sed 's/javascript-utf-8.js/\/javascript-utf-8.js/g' | diff --strip-trailing-cr - OUT
+ ;;
+ *)
+ echo 500 > EXPECTED
+ ! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/javascript-utf-8.js 2> /dev/null > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+esac
+
+# kill $server_pid
+shutdown
+
+$VALGRIND jscoverage-server --port 8080 --encoding BOGUS --document-root javascript &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 500 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/javascript-iso-8859-1.js 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# kill $server_pid
+shutdown
+
+$VALGRIND jscoverage-server --port 8080 --encoding utf-8 --document-root javascript &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 500 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/javascript-iso-8859-1.js 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/source-does-not-exist.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/source-does-not-exist.expected.err
new file mode 100644
index 0000000..caf61ca
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/source-does-not-exist.expected.err
@@ -0,0 +1,2 @@
+jscoverage: cannot stat file: foo
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/source-is-file.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/source-is-file.expected.err
new file mode 100644
index 0000000..b3fb0b6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/source-is-file.expected.err
@@ -0,0 +1,2 @@
+jscoverage: not a directory: foo
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-json.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-json.sh
new file mode 100755
index 0000000..5519514
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-json.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+# store-bad-json.sh - test store with invalid JSON
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --document-root=recursive --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 400 > EXPECTED
+! curl -d '!@#$%^&*()' -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-store 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-request-body.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-request-body.sh
new file mode 100755
index 0000000..ef9883e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-request-body.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+# store-bad-request-body.sh - test store with a bad request body
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --document-root=recursive --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+./http-client-bad-body 8080 http://127.0.0.1:8080/jscoverage-store
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-response-headers.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-response-headers.sh
new file mode 100755
index 0000000..28747b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-response-headers.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+# store-bad-response-headers.sh - test store with bad response headers
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+ kill -9 $origin_server_pid
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+./http-server-bad-headers &
+origin_server_pid=$!
+
+sleep $delay
+
+# server sending malformed headers
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+json_cmp store-source-urls.expected.json DIR/jscoverage.json
+sort ERR -o ERR
+diff --strip-trailing-cr store-source-urls.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.err
new file mode 100644
index 0000000..49fb754
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.err
@@ -0,0 +1,3 @@
+Warning: cannot retrieve URL: 1/1.js
+Warning: cannot retrieve URL: 1/2/2.js
+Warning: cannot retrieve URL: script.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.json
new file mode 100644
index 0000000..eb24c47
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.json
@@ -0,0 +1,14 @@
+{
+ "script.js":{
+ "coverage":[null,1,null,null,1,0],
+ "source":[]
+ },
+ "1/1.js":{
+ "coverage":[null,1],
+ "source":[]
+ },
+ "1/2/2.js":{
+ "coverage":[null,1],
+ "source":[]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.expected.json
new file mode 100644
index 0000000..9546103
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.expected.json
@@ -0,0 +1,6 @@
+{
+ "/store-escaped-characters.js":{
+ "coverage":[null,1,0,null,null,1,0,null,null,1,0],
+ "source":["function f() {","\treturn \'\\\'\';","}","&#11;","function g() {","\treturn \"\\\"\";","}","\f","function h() {","\treturn \'\\\\\';","}"]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.js b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.js
new file mode 100644
index 0000000..dc8ec36
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.js
@@ -0,0 +1,11 @@
+function f() {
+ return '\'';
+}
+
+function g() {
+ return "\"";
+}
+
+function h() {
+ return '\\';
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.json
new file mode 100644
index 0000000..59cf4de
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.json
@@ -0,0 +1,3 @@
+{
+ "/store-escaped-characters.js":[null,1,0,null,null,1,0,null,null,1,0]
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.sh
new file mode 100755
index 0000000..5eb9180
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+# store-escaped-characters.sh - test storing escaped characters in JavaScript source
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --report-dir=DIR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget --post-file=store-escaped-characters.json -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+json_cmp store-escaped-characters.expected.json DIR/jscoverage.json
+wget --post-file=store-escaped-characters.json -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+cat store-escaped-characters.expected.json | sed s/1,/2,/g > TMP
+json_cmp TMP DIR/jscoverage.json
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-server-bad-body.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-server-bad-body.sh
new file mode 100755
index 0000000..b6ae810
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-server-bad-body.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+# store-server-bad-body.sh - test storing when server sends bad response body
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+ if [ "$origin_server_pid" != "" ]
+ then
+ kill -9 $origin_server_pid
+ fi
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+./http-server-bad-body &
+origin_server_pid=$!
+
+sleep $delay
+
+# server sending malformed body
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+json_cmp store-source-urls.expected.json DIR/jscoverage.json
+sort ERR -o ERR
+diff --strip-trailing-cr store-source-urls.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-server-closes-immediately.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-server-closes-immediately.sh
new file mode 100755
index 0000000..a0ef9f9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-server-closes-immediately.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# store-server-closes-immediately.sh - test storing when server closes immediately
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+ if [ "$origin_server_pid" != "" ]
+ then
+ kill -9 $origin_server_pid
+ fi
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+./http-server-close-immediately &
+origin_server_pid=$!
+
+sleep $delay
+
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+json_cmp store-source-urls.expected.json DIR/jscoverage.json
+sort ERR -o ERR
+diff --strip-trailing-cr store-source-urls.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.err
new file mode 100644
index 0000000..f00a540
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.err
@@ -0,0 +1 @@
+Warning: cannot open file: /missing.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.json
new file mode 100644
index 0000000..3750b51
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.json
@@ -0,0 +1,6 @@
+{
+ "/missing.js":{
+ "coverage":[null,1,0],
+ "source":[]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.json
new file mode 100644
index 0000000..cfad0dd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.json
@@ -0,0 +1,3 @@
+{
+ "/missing.js":[null, 1, 0]
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.sh
new file mode 100755
index 0000000..aa2a1fa
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+# store-source-not-found.sh - test store with JavaScript source not found
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget --post-file=store-source-not-found.json -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+json_cmp store-source-not-found.expected.json DIR/jscoverage.json
+diff --strip-trailing-cr store-source-not-found.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.err
new file mode 100644
index 0000000..90a2dd6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.err
@@ -0,0 +1,3 @@
+Warning: cannot retrieve URL: http://127.0.0.1:8000/1/1.js
+Warning: cannot retrieve URL: http://127.0.0.1:8000/1/2/2.js
+Warning: cannot retrieve URL: http://127.0.0.1:8000/script.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.json
new file mode 100644
index 0000000..cb8d058
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.json
@@ -0,0 +1,14 @@
+{
+ "http://127.0.0.1:8000/script.js":{
+ "coverage":[null,1,null,null,1,0],
+ "source":[]
+ },
+ "http://127.0.0.1:8000/1/1.js":{
+ "coverage":[null,1],
+ "source":[]
+ },
+ "http://127.0.0.1:8000/1/2/2.js":{
+ "coverage":[null,1],
+ "source":[]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.err
new file mode 100644
index 0000000..96781cf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.err
@@ -0,0 +1,3 @@
+Warning: cannot retrieve URL: http://127.0.0.1:1/1/1.js
+Warning: cannot retrieve URL: http://127.0.0.1:1/1/2/2.js
+Warning: cannot retrieve URL: http://127.0.0.1:1/script.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.json
new file mode 100644
index 0000000..0885998
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.json
@@ -0,0 +1,14 @@
+{
+ "http://127.0.0.1:1/script.js":{
+ "coverage":[null,1,null,null,1,0],
+ "source":[]
+ },
+ "http://127.0.0.1:1/1/1.js":{
+ "coverage":[null,1],
+ "source":[]
+ },
+ "http://127.0.0.1:1/1/2/2.js":{
+ "coverage":[null,1],
+ "source":[]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-unreadable-json.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreadable-json.sh
new file mode 100755
index 0000000..026512b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreadable-json.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+# store-unreadable-json.sh - test store when jscoverage.json is not readable
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+# skip on windows
+uname=`uname`
+case "$uname" in
+ CYGWIN* | MINGW*)
+ exit 77
+ ;;
+esac
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --document-root=recursive --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+wget --post-file=TMP -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/\\//g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+chmod -r DIR/jscoverage.json
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+echo 500 > EXPECTED
+! curl -d @TMP -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-store 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-unwritable-json.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-unwritable-json.sh
new file mode 100755
index 0000000..786e9bc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-unwritable-json.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# store-unwritable-json.sh - test store when jscoverage.json is not writable
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --document-root=recursive --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+wget --post-file=TMP -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/\\//g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+chmod -w DIR/jscoverage.json
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+echo 500 > EXPECTED
+! curl -d @TMP -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-store 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store.expected.json
new file mode 100644
index 0000000..2aa393e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store.expected.json
@@ -0,0 +1,14 @@
+{
+ "@PREFIX@script.js":{
+ "coverage":[null,1,null,null,1,0],
+ "source":["alert(\"hello\");","","// test formatting &amp;lt; &amp;gt; &amp;amp;","if ('a' &lt; 'b' &amp;&amp; 'a' &gt; 'b') {"," alert(\"?\");","}"]
+ },
+ "@PREFIX@1/1.js":{
+ "coverage":[null,1],
+ "source":["alert(\"This is 1\");"]
+ },
+ "@PREFIX@1/2/2.js":{
+ "coverage":[null,1],
+ "source":["alert(\"This is 2\");"]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store.json b/tools/node_modules/expresso/deps/jscoverage/tests/store.json
new file mode 100644
index 0000000..942d686
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store.json
@@ -0,0 +1,5 @@
+{
+ "@PREFIX@script.js":[null,1,null,null,1,0],
+ "@PREFIX@1/1.js":[null,1],
+ "@PREFIX@1/2/2.js":[null,1]
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store.sh
new file mode 100755
index 0000000..fb12574
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store.sh
@@ -0,0 +1,137 @@
+#!/bin/sh
+# store.sh - test storing coverage reports with jscoverage-server
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ # rm -fr DIR
+ # kill $server_pid
+ shutdown
+ if [ "$origin_server_pid" != "" ]
+ then
+ kill -9 $origin_server_pid
+ fi
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --document-root=recursive --report-dir=DIR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+wget --post-file=TMP -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/\\//g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+wget --post-file=TMP -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/\\//g" | sed "s/,1/,2/g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+# try invalid method
+echo 405 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-store 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# try with a path
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+wget --post-file=TMP -q -O- http://127.0.0.1:8080/jscoverage-store/DIR > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/\\//g" > TMP
+json_cmp TMP DIR/DIR/jscoverage.json
+
+shutdown
+
+cd recursive
+perl ../server.pl > /dev/null 2> /dev/null &
+origin_server_pid=$!
+cd ..
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+# test with proxy
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" | sed "s/,1/,2/g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+# test cached source
+rm -fr DIR
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+shutdown
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+# store JSON with bad source URLs
+cat store.json | sed "s/@PREFIX@//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+json_cmp store-bad-source-urls.expected.json DIR/jscoverage.json
+sort ERR -o ERR
+diff --strip-trailing-cr store-bad-source-urls.expected.err ERR
+
+shutdown
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+# store JSON with unreachable source URLs
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:1\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+json_cmp store-unreachable-source-urls.expected.json DIR/jscoverage.json
+sort ERR -o ERR
+diff --strip-trailing-cr store-unreachable-source-urls.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/streams.c b/tools/node_modules/expresso/deps/jscoverage/tests/streams.c
new file mode 100644
index 0000000..06389fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/streams.c
@@ -0,0 +1,107 @@
+/*
+ streams.c - test `Stream' object
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <assert.h>
+#include <string.h>
+
+#include "stream.h"
+#include "util.h"
+
+int main(void) {
+ Stream * stream;
+
+ stream = Stream_new(0);
+ Stream_write_string(stream, "a");
+ Stream_write_string(stream, "bc");
+ assert(stream->length == 3);
+ assert(memcmp(stream->data, "abc", 3) == 0);
+ Stream_delete(stream);
+
+ /* test writing chars to stream */
+ stream = Stream_new(2);
+ Stream_write_char(stream, 'a');
+ Stream_write_char(stream, 'b');
+ Stream_write_char(stream, 'c');
+ assert(stream->length == 3);
+ assert(memcmp(stream->data, "abc", 3) == 0);
+ Stream_reset(stream);
+ Stream_write_char(stream, 'x');
+ Stream_write_char(stream, 'y');
+ assert(stream->length == 2);
+ assert(memcmp(stream->data, "xy", 2) == 0);
+ Stream_delete(stream);
+
+ /* test writing file to stream */
+ stream = Stream_new(0);
+ FILE * f = xfopen("Makefile", "r");
+ fseek(f, 0, SEEK_END);
+ long file_length = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ uint8_t * file_contents = xmalloc(file_length);
+ fread(file_contents, 1, file_length, f);
+ fseek(f, 0, SEEK_SET);
+ Stream_write_file_contents(stream, f);
+ fclose(f);
+ assert(stream->length == (size_t) file_length);
+ assert(memcmp(stream->data, file_contents, file_length) == 0);
+ free(file_contents);
+ Stream_delete(stream);
+
+ stream = Stream_new(0);
+ Stream_printf(stream, "%s %d\n", "abc", 123);
+ assert(stream->length == 8);
+ assert(memcmp(stream->data, "abc 123\n", 8) == 0);
+ Stream_delete(stream);
+
+ stream = Stream_new(10);
+ size_t length = 0;
+ for (int i = 0; i < 100; i++) {
+ Stream_printf(stream, "%s %d\n", "abc", i);
+ if (i < 10) {
+ length += 6;
+ }
+ else {
+ length += 7;
+ }
+ }
+ assert(stream->length == length);
+ length = 0;
+ for (int i = 0; i < 100; i++) {
+ char buffer[8];
+ int result = sprintf(buffer, "%s %d\n", "abc", i);
+ assert(memcmp(stream->data + length, buffer, result) == 0);
+ length += result;
+ }
+ assert(stream->length == length);
+ Stream_delete(stream);
+
+ stream = Stream_new(10);
+ char buffer[100];
+ for (int i = 0; i < 100; i++) {
+ buffer[i] = 'x';
+ }
+ Stream_write(stream, buffer, 100);
+ assert(stream->length == 100);
+ for (int i = 0; i < 100; i++) {
+ assert(stream->data[i] == 'x');
+ }
+ Stream_delete(stream);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/streams.sh b/tools/node_modules/expresso/deps/jscoverage/tests/streams.sh
new file mode 100755
index 0000000..74cfebd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/streams.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# streams.sh - test `Stream' object
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./streams
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/too-many-arguments.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/too-many-arguments.expected.err
new file mode 100644
index 0000000..4ab8b42
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/too-many-arguments.expected.err
@@ -0,0 +1,2 @@
+jscoverage: too many arguments
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/valgrind.sh b/tools/node_modules/expresso/deps/jscoverage/tests/valgrind.sh
new file mode 100755
index 0000000..c575324
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/valgrind.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+rm -f VALGRIND.*
+export VALGRIND='valgrind --log-file=VALGRIND.%p'
+make check
+grep --color=always 'ERROR SUMMARY:' VALGRIND.*
+grep --color=always 'definitely lost:' VALGRIND.*
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/verbose.expected.out b/tools/node_modules/expresso/deps/jscoverage/tests/verbose.expected.out
new file mode 100644
index 0000000..c2c147f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/verbose.expected.out
@@ -0,0 +1,13 @@
+Instrumenting file 1/1.css
+Instrumenting file 1/1.html
+Instrumenting file 1/1.js
+Instrumenting file 1/2/2.css
+Instrumenting file 1/2/2.html
+Instrumenting file 1/2/2.js
+Instrumenting file image.png
+Instrumenting file index.html
+Instrumenting file script.js
+Instrumenting file style.css
+Instrumenting file unix.txt
+Instrumenting file windows.txt
+Instrumenting file x
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/version.sh b/tools/node_modules/expresso/deps/jscoverage/tests/version.sh
new file mode 100755
index 0000000..da0a26c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/version.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+# version.sh - test `--version' option
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr OUT ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+$VALGRIND jscoverage --version > OUT 2> ERR
+test -s OUT
+test ! -s ERR
+
+rm -fr OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/util.c b/tools/node_modules/expresso/deps/jscoverage/util.c
new file mode 100644
index 0000000..40636ff
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/util.c
@@ -0,0 +1,570 @@
+/*
+ util.c - general purpose utility routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#define _GNU_SOURCE
+
+#include <config.h>
+
+#include "util.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+
+#include <dirent.h>
+#include <libgen.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+const char * program = NULL;
+
+void fatal(const char * format, ...) {
+ fprintf(stderr, "%s: ", program);
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ exit(EXIT_FAILURE);
+}
+
+void fatal_command_line(const char * format, ...) {
+ fprintf(stderr, "%s: ", program);
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ fprintf(stderr, "Try `%s --help' for more information.\n", program);
+ exit(EXIT_FAILURE);
+}
+
+void fatal_source(const char * source_file, unsigned int line_number, const char * format, ...) {
+ fprintf(stderr, "%s:%s:%u: ", program, source_file, line_number);
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ exit(EXIT_FAILURE);
+}
+
+void warn_source(const char * source_file, unsigned int line_number, const char * format, ...) {
+ fprintf(stderr, "%s:%s:%u: ", program, source_file, line_number);
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+}
+
+void version(void) {
+ printf("%s %s\n", program, VERSION);
+ printf("Character encoding support: ");
+#if HAVE_ICONV
+ printf("iconv\n");
+#elif HAVE_MULTIBYTETOWIDECHAR
+ printf("MultiByteToWideChar\n");
+#else
+ printf("none\n");
+#endif
+ exit(EXIT_SUCCESS);
+}
+
+size_t addst(size_t x, size_t y) {
+ if (SIZE_MAX - x < y) {
+ fatal("integer overflow");
+ }
+ return x + y;
+}
+
+size_t mulst(size_t x, size_t y) {
+ if (x == 0 || y == 0) {
+ return 0;
+ }
+ if (SIZE_MAX / x < y) {
+ fatal("integer overflow");
+ }
+ return x * y;
+}
+
+void * xmalloc(size_t size) {
+ void * result = malloc(size);
+ if (result == NULL) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+void * xrealloc(void * p, size_t size) {
+ void * result = realloc(p, size);
+ if (result == NULL) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+char * xstrdup(const char * s) {
+ char * result = strdup(s);
+ if (result == NULL) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+char * xstrndup(const char * s, size_t size) {
+ char * result = strndup(s, size);
+ if (result == NULL) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+int xasprintf(char ** s, const char * template, ...) {
+ va_list a;
+ va_start(a, template);
+ int result = vasprintf(s, template, a);
+ va_end(a);
+ if (result < 0) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+char * xgetcwd(void) {
+ char * result = getcwd(NULL, 0);
+ if (result == NULL) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+FILE * xfopen(const char * file, const char * mode) {
+ FILE * result = fopen(file, mode);
+ if (result == NULL) {
+ fatal("cannot open file: %s", file);
+ }
+ return result;
+}
+
+DIR * xopendir(const char * directory) {
+ DIR * result = opendir(directory);
+ if (result == NULL) {
+ fatal("cannot open directory: %s", directory);
+ }
+ return result;
+}
+
+void xlstat(const char * file, struct stat * buf) {
+#ifdef _WIN32
+ return xstat(file, buf);
+#else
+ if (lstat(file, buf) == -1) {
+ fatal("cannot stat file: %s", file);
+ }
+#endif
+}
+
+void xstat(const char * file, struct stat * buf) {
+ if (stat(file, buf) == -1) {
+ fatal("cannot stat file: %s", file);
+ }
+}
+
+void xmkdir(const char * directory) {
+ int result;
+#ifdef _WIN32
+ result = mkdir(directory);
+#else
+ result = mkdir(directory, 0755);
+#endif
+ if (result == -1) {
+ fatal("cannot create directory: %s", directory);
+ }
+}
+
+void mkdir_if_necessary(const char * directory) {
+ struct stat buf;
+ if (stat(directory, &buf) == 0) {
+ if (! S_ISDIR(buf.st_mode)) {
+ fatal("not a directory: %s", directory);
+ }
+ }
+ else {
+ if (errno == ENOENT) {
+ xmkdir(directory);
+ }
+ else {
+ fatal("cannot stat directory: %s", directory);
+ }
+ }
+}
+
+void mkdirs(const char * directory) {
+ char * d = xmalloc(strlen(directory) + 1);
+ for (const char * p = directory; *p != '\0'; p++) {
+ if (*p == '/' && p > directory) {
+ strncpy(d, directory, p - directory);
+ d[p - directory] = '\0';
+ mkdir_if_necessary(d);
+ }
+ }
+ mkdir_if_necessary(directory);
+ free(d);
+}
+
+void xchdir(const char * directory) {
+ if (chdir(directory) == -1) {
+ fatal("cannot change directory: %s", directory);
+ }
+}
+
+bool str_starts_with(const char * string, const char * prefix) {
+ const char * string_ptr = string;
+ const char * prefix_ptr = prefix;
+ while (*string_ptr != '\0' && *prefix_ptr != '\0') {
+ if (*string_ptr != *prefix_ptr) {
+ return false;
+ }
+ string_ptr++;
+ prefix_ptr++;
+ }
+ if (*string_ptr == '\0' && *prefix_ptr != '\0') {
+ return false;
+ }
+ return true;
+}
+
+bool str_ends_with(const char * string, const char * suffix) {
+ size_t string_length = strlen(string);
+ size_t suffix_length = strlen(suffix);
+ if (string_length < suffix_length) {
+ return false;
+ }
+ return strcmp(string + string_length - suffix_length, suffix) == 0;
+}
+
+char * make_path(const char * parent, const char * relative_path) {
+ size_t parent_length = strlen(parent);
+ size_t relative_path_length = strlen(relative_path);
+ size_t result_length = addst(parent_length, relative_path_length);
+ result_length = addst(result_length, 2);
+ char * result = xmalloc(result_length);
+ strcpy(result, parent);
+ result[parent_length] = '/';
+ strcpy(result + parent_length + 1, relative_path);
+ return result;
+}
+
+char * make_canonical_path(const char * relative_path) {
+ char * original_directory = xgetcwd();
+ char * base = make_basename(relative_path);
+ char * dir = make_dirname(relative_path);
+
+ xchdir(dir);
+ char * canonical_dir = xgetcwd();
+ char * result = make_path(canonical_dir, base);
+
+ free(canonical_dir);
+ free(base);
+ free(dir);
+ xchdir(original_directory);
+ free(original_directory);
+
+ return result;
+}
+
+char * make_basename(const char * path) {
+ char * copy = xstrdup(path);
+ char * result = xstrdup(basename(copy));
+ free(copy);
+ return result;
+}
+
+char * make_dirname(const char * path) {
+ char * copy = xstrdup(path);
+ char * result = xstrdup(dirname(copy));
+ free(copy);
+ return result;
+}
+
+int is_same_file(const char * file1, const char * file2) {
+#ifdef _WIN32
+#define FILECMP strcasecmp
+#else
+#define FILECMP strcmp
+#endif
+ if (FILECMP(file1, file2) == 0) {
+ return 1;
+ }
+
+ char * canonical1 = make_canonical_path(file1);
+ char * canonical2 = make_canonical_path(file2);
+ int cmp = FILECMP(canonical1, canonical2);
+ free(canonical1);
+ free(canonical2);
+ if (cmp == 0) {
+ return 1;
+ }
+
+#ifndef _WIN32
+ struct stat buf1;
+ if (stat(file1, &buf1) == -1) {
+ if (errno == ENOENT) {
+ return 0;
+ }
+ else {
+ fatal("cannot stat file: %s", file1);
+ }
+ }
+ struct stat buf2;
+ if (stat(file2, &buf2) == -1) {
+ if (errno == ENOENT) {
+ return 0;
+ }
+ else {
+ fatal("cannot stat file: %s", file2);
+ }
+ }
+ if (buf1.st_dev == buf2.st_dev &&
+ buf1.st_ino == buf2.st_ino) {
+ return 1;
+ }
+#endif
+ return 0;
+#undef FILECMP
+}
+
+int contains_file(const char * file1, const char * file2) {
+ int result = 0;
+ char * ancestor = make_canonical_path(file1);
+ char * d = make_canonical_path(file2);
+ char * parent = make_dirname(d);
+ while (strcmp(d, parent) != 0) {
+ if (is_same_file(ancestor, parent)) {
+ result = 1;
+ break;
+ }
+ free(d);
+ d = parent;
+ parent = make_dirname(d);
+ }
+ free(d);
+ free(parent);
+ free(ancestor);
+ return result;
+}
+
+void copy_stream(FILE * source, FILE * destination) {
+ unsigned char buffer[8192];
+ for (;;) {
+ int bytes_read = fread(buffer, 1, sizeof(buffer), source);
+ if (bytes_read == 0) {
+ break;
+ }
+ fwrite(buffer, 1, bytes_read, destination);
+ }
+}
+
+void copy_file(const char * source_file, const char * destination_file) {
+ FILE * source = xfopen(source_file, "rb");
+ FILE * destination = xfopen(destination_file, "wb");
+
+ copy_stream(source, destination);
+
+#ifndef _WIN32
+ /* copy permissions */
+ struct stat buf;
+ if (fstat(fileno(source), &buf) == -1) {
+ fatal("cannot stat file: %s", source_file);
+ }
+ fchmod(fileno(destination), buf.st_mode);
+#endif
+
+ fclose(source);
+ fclose(destination);
+}
+
+bool directory_is_empty(const char * directory) {
+ bool result = true;
+ DIR * dir = xopendir(directory);
+ struct dirent * e;
+ while ((e = readdir(dir)) != NULL) {
+ if (strcmp(e->d_name, ".") != 0 &&
+ strcmp(e->d_name, "..") != 0) {
+ result = false;
+ break;
+ }
+ }
+ closedir(dir);
+ return result;
+}
+
+static struct DirListEntry * recursive_dir_list(const char * root, const char * directory_wrt_root, struct DirListEntry * head) {
+ char * directory = directory_wrt_root == NULL? xstrdup(root): make_path(root, directory_wrt_root);
+ DIR * dir = xopendir(directory);
+ struct dirent * e;
+ while ((e = readdir(dir)) != NULL) {
+ if (strcmp(e->d_name, ".") == 0 ||
+ strcmp(e->d_name, "..") == 0) {
+ continue;
+ }
+ char * entry = make_path(directory, e->d_name);
+ char * entry_wrt_root = directory_wrt_root == NULL? xstrdup(e->d_name): make_path(directory_wrt_root, e->d_name);
+ struct stat buf;
+ xlstat(entry, &buf);
+ if (S_ISREG(buf.st_mode)) {
+ struct DirListEntry * p = xmalloc(sizeof(struct DirListEntry));
+ p->name = entry_wrt_root;
+ p->next = head;
+ head = p;
+ }
+ else if (S_ISDIR(buf.st_mode)) {
+ head = recursive_dir_list(root, entry_wrt_root, head);
+ free(entry_wrt_root);
+ }
+#ifndef _WIN32
+ else if (S_ISLNK(buf.st_mode)) {
+ /* check what it points to */
+ xstat(entry, &buf);
+ if (S_ISREG(buf.st_mode)) {
+ struct DirListEntry * p = xmalloc(sizeof(struct DirListEntry));
+ p->name = entry_wrt_root;
+ p->next = head;
+ head = p;
+ }
+ else {
+ fatal("refusing to follow symbolic link: %s", entry);
+ }
+ }
+#endif
+ else {
+ fatal("unknown file type: %s", entry);
+ }
+ free(entry);
+ }
+ closedir(dir);
+ free(directory);
+ return head;
+}
+
+struct DirListEntry * make_recursive_dir_list(const char * directory) {
+ return recursive_dir_list(directory, NULL, NULL);
+}
+
+void free_dir_list(struct DirListEntry * list) {
+ while (list != NULL) {
+ struct DirListEntry * next = list->next;
+ free(list->name);
+ free(list);
+ list = next;
+ }
+}
+
+#ifndef HAVE_STRNDUP
+char * strndup(const char * s, size_t size) {
+ size_t length = strlen(s);
+ if (length > size) {
+ char * result = xmalloc(size + 1);
+ strncpy(result, s, size);
+ result[size] = '\0';
+ return result;
+ }
+ else {
+ char * result = xmalloc(length + 1);
+ strcpy(result, s);
+ return result;
+ }
+}
+#endif
+
+#ifndef HAVE_VASPRINTF
+int vasprintf(char ** s, const char * template, va_list a) {
+ int size = 100;
+ *s = malloc(size);
+ if (*s == NULL) {
+ return -1;
+ }
+
+ va_list copy;
+ va_copy(copy, a);
+ int result = vsnprintf(*s, size, template, copy);
+ if (result >= size) {
+ int new_size = result;
+ if (new_size == INT_MAX) {
+ free(*s);
+ return -1;
+ }
+ new_size++;
+ char * new_s = realloc(*s, new_size);
+ if (new_s == NULL) {
+ free(*s);
+ return -1;
+ }
+ *s = new_s;
+ size = new_size;
+ va_copy(copy, a);
+ result = vsnprintf(*s, size, template, copy);
+ assert(result == size - 1);
+ }
+ else if (result == -1) {
+ while (result == -1) {
+ if (size == INT_MAX) {
+ free(*s);
+ return -1;
+ }
+ int new_size;
+ if (size > INT_MAX / 2) {
+ new_size = INT_MAX;
+ }
+ else {
+ new_size = 2 * size;
+ }
+ char * new_s = realloc(*s, new_size);
+ if (new_s == NULL) {
+ free(*s);
+ return -1;
+ }
+ *s = new_s;
+ size = new_size;
+ va_copy(copy, a);
+ result = vsnprintf(*s, size, template, copy);
+ }
+ assert(result <= size - 1);
+ }
+
+ return result;
+}
+#endif
+
+#ifndef HAVE_ASPRINTF
+int asprintf(char ** s, const char * template, ...) {
+ va_list a;
+ va_start(a, template);
+ int result = vasprintf(s, template, a);
+ va_end(a);
+ return result;
+}
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/util.h b/tools/node_modules/expresso/deps/jscoverage/util.h
new file mode 100644
index 0000000..5cd063f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/util.h
@@ -0,0 +1,133 @@
+/*
+ util.h - general purpose utility routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef UTIL_H_
+#define UTIL_H_
+
+#ifndef HAVE_VASPRINTF
+#include <stdarg.h>
+#endif
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/stat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char * program;
+
+void fatal(const char * format, ...)
+ __attribute__((__noreturn__))
+ __attribute__((__format__(printf, 1, 2)));
+
+void fatal_command_line(const char * format, ...)
+ __attribute__((__noreturn__))
+ __attribute__((__format__(printf, 1, 2)));
+
+void fatal_source(const char * source_file, unsigned int line_number, const char * format, ...)
+ __attribute__((__noreturn__))
+ __attribute__((__format__(printf, 3, 4)));
+
+void warn_source(const char * source_file, unsigned int line_number, const char * format, ...)
+ __attribute__((__format__(printf, 3, 4)));
+
+void version(void)
+ __attribute__((__noreturn__));
+
+size_t addst(size_t x, size_t y);
+
+size_t mulst(size_t x, size_t y);
+
+void * xmalloc(size_t size);
+
+#define xnew(type, count) ((type *) xmalloc(mulst((count), sizeof(type))))
+
+void * xrealloc(void * p, size_t size);
+
+char * xstrdup(const char * s);
+
+char * xstrndup(const char * s, size_t size);
+
+int xasprintf(char ** s, const char * format, ...) __attribute__((__format__(printf, 2, 3)));
+
+char * xgetcwd(void);
+
+FILE * xfopen(const char * file, const char * mode);
+
+void xstat(const char * file, struct stat * buf);
+
+void xlstat(const char * file, struct stat * buf);
+
+void xmkdir(const char * directory);
+
+void mkdir_if_necessary(const char * directory);
+
+void mkdirs(const char * path);
+
+bool str_starts_with(const char * string, const char * prefix);
+
+bool str_ends_with(const char * string, const char * suffix);
+
+char * make_path(const char * parent, const char * relative_path);
+
+char * make_canonical_path(const char * relative_path);
+
+char * make_basename(const char * path);
+
+char * make_dirname(const char * path);
+
+int is_same_file(const char * file1, const char * file2);
+
+int contains_file(const char * file1, const char * file2);
+
+void copy_stream(FILE * source, FILE * destination);
+
+void copy_file(const char * source_file, const char * destination_file);
+
+bool directory_is_empty(const char * directory);
+
+struct DirListEntry {
+ char * name;
+ struct DirListEntry * next;
+};
+
+struct DirListEntry * make_recursive_dir_list(const char * directory);
+
+void free_dir_list(struct DirListEntry * list);
+
+#ifndef HAVE_STRNDUP
+char * strndup(const char * s, size_t size);
+#endif
+
+#ifndef HAVE_VASPRINTF
+int vasprintf(char ** s, const char * format, va_list a);
+#endif
+
+#ifndef HAVE_ASPRINTF
+int asprintf(char ** s, const char * format, ...) __attribute__((__format__(printf, 2, 3)));
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UTIL_H_ */
diff --git a/tools/node_modules/expresso/docs/api.html b/tools/node_modules/expresso/docs/api.html
new file mode 100644
index 0000000..39f0629
--- /dev/null
+++ b/tools/node_modules/expresso/docs/api.html
@@ -0,0 +1,1291 @@
+<a href="http://github.com/visionmedia/expresso"><img alt="Fork me on GitHub" id="ribbon" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a><html>
+ <head>
+ <title>Expresso</title>
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
+ <style>body {
+ margin: 0;
+ padding: 0;
+ font: 14px/1.5 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
+ color: #252519;
+}
+a {
+ color: #252519;
+}
+a:hover {
+ text-decoration: underline;
+ color: #19469D;
+}
+p {
+ margin: 12px 0;
+}
+h1, h2, h3 {
+ margin: 0;
+ padding: 0;
+}
+table#source {
+ width: 100%;
+ border-collapse: collapse;
+}
+table#source td:first-child {
+ padding: 30px 40px 30px 40px;
+ vertical-align: top;
+}
+table#source td:first-child,
+table#source td:first-child pre {
+ width: 450px;
+}
+table#source td:last-child {
+ padding: 30px 0 30px 40px;
+ border-left: 1px solid #E5E5EE;
+ background: #F5F5FF;
+}
+table#source tr {
+ border-bottom: 1px solid #E5E5EE;
+}
+table#source tr.filename {
+ padding-top: 40px;
+ border-top: 1px solid #E5E5EE;
+}
+table#source tr.filename td:first-child {
+ text-transform: capitalize;
+}
+table#source tr.filename td:last-child {
+ font-size: 12px;
+}
+table#source tr.filename h2 {
+ margin: 0;
+ padding: 0;
+ cursor: pointer;
+}
+table#source tr.code h1,
+table#source tr.code h2,
+table#source tr.code h3 {
+ margin-top: 30px;
+ font-family: "Lucida Grande", "Helvetica Nueue", Arial, sans-serif;
+ font-size: 18px;
+}
+table#source tr.code h2 {
+ font-size: 16px;
+}
+table#source tr.code h3 {
+ font-size: 14px;
+}
+table#source tr.code ul {
+ margin: 15px 0 15px 35px;
+ padding: 0;
+}
+table#source tr.code ul li {
+ margin: 0;
+ padding: 1px 0;
+}
+table#source tr.code ul li p {
+ margin: 0;
+ padding: 0;
+}
+table#source tr.code td:first-child pre {
+ padding: 20px;
+}
+#ribbon {
+ position: fixed;
+ top: 0;
+ right: 0;
+}
+code .string { color: #219161; }
+code .regexp { color: #219161; }
+code .keyword { color: #954121; }
+code .number { color: #19469D; }
+code .comment { color: #bbb; }
+code .this { color: #19469D; }</style>
+ <script>
+ $(function(){
+ $('tr.code').hide();
+ $('tr.filename').toggle(function(){
+ $(this).nextUntil('.filename').fadeIn();
+ }, function(){
+ $(this).nextUntil('.filename').fadeOut();
+ });
+ });
+ </script>
+ </head>
+ <body>
+<table id="source"><tbody><tr><td><h1>Expresso</h1><p>Insanely fast TDD framework for <a href="http://nodejs.org">node</a> featuring code coverage reporting.</p></td><td></td></tr><tr class="filename"><td><h2 id="bin/expresso"><a href="#">expresso</a></h2></td><td>bin/expresso</td></tr><tr class="code">
+<td class="docs">
+<h1>!/usr/bin/env node</h1>
+</td>
+<td class="code">
+<pre><code>
+ * <span class="class">Expresso</span>
+ * <span class="class">Copyright</span>(<span class="variable">c</span>) <span class="class">TJ</span> <span class="class">Holowaychuk</span> &<span class="variable">lt</span>;<span class="variable">tj</span>@<span class="variable">vision</span>-<span class="variable">media</span>.<span class="variable">ca</span>&<span class="variable">gt</span>;
+ * (<span class="class">MIT</span> <span class="class">Licensed</span>)
+ </code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Module dependencies.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">assert</span> = <span class="variable">require</span>(<span class="string">'assert'</span>),
+ <span class="variable">childProcess</span> = <span class="variable">require</span>(<span class="string">'child_process'</span>),
+ <span class="variable">http</span> = <span class="variable">require</span>(<span class="string">'http'</span>),
+ <span class="variable">path</span> = <span class="variable">require</span>(<span class="string">'path'</span>),
+ <span class="variable">sys</span> = <span class="variable">require</span>(<span class="string">'sys'</span>),
+ <span class="variable">cwd</span> = <span class="variable">process</span>.<span class="variable">cwd</span>(),
+ <span class="variable">fs</span> = <span class="variable">require</span>(<span class="string">'fs'</span>),
+ <span class="variable">defer</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Set the node env to test if it hasn't already been set
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">if</span>( !<span class="variable">process</span>.<span class="variable">env</span>.<span class="class">NODE_ENV</span> ) <span class="variable">process</span>.<span class="variable">env</span>.<span class="class">NODE_ENV</span> = <span class="string">'test'</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Setup the regex which is used to match test files.
+Adjust it to include coffeescript files if CS is available
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">file_matcher</span> = <span class="regexp">/\.js$/</span>;
+<span class="keyword">try</span> {
+ <span class="variable">require</span>(<span class="string">'coffee-script'</span>);
+ <span class="variable">file_matcher</span> = <span class="regexp">/\.(js|coffee)$/</span>;
+} <span class="keyword">catch</span> (<span class="variable">e</span>) {}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Expresso version.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">version</span> = <span class="string">'0.8.1'</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Failure count.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">failures</span> = <span class="number integer">0</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Indicates whether all test files have been loaded.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">suites</span> = <span class="number integer">0</span>;
+<span class="keyword">var</span> <span class="variable">suitesRun</span> = <span class="number integer">0</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Number of tests executed.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">testcount</span> = <span class="number integer">0</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Whitelist of tests to run.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">only</span> = [];</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Boring output.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">boring</span> = <span class="variable">false</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Growl notifications.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">growl</span> = <span class="variable">false</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Server port.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">port</span> = <span class="number integer">5555</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Execute serially.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">serial</span> = <span class="variable">false</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Default timeout.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">timeout</span> = <span class="number integer">2000</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Quiet output.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">quiet</span> = <span class="variable">false</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>JSON code coverage report
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">jsonCoverage</span> = <span class="variable">false</span>;
+<span class="keyword">var</span> <span class="variable">jsonFile</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Usage documentation.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">usage</span> = <span class="string">''</span>
+ + <span class="string">'[bold]{Usage}: expresso [options] &lt;file ...&gt;'</span>
+ + <span class="string">'\n'</span>
+ + <span class="string">'\n[bold]{Options}:'</span>
+ + <span class="string">'\n -g, --growl Enable growl notifications'</span>
+ + <span class="string">'\n -c, --coverage Generate and report test coverage'</span>
+ + <span class="string">'\n -j, --json PATH Used in conjunction with --coverage, ouput JSON coverage to PATH'</span>
+ + <span class="string">'\n -q, --quiet Suppress coverage report if 100%'</span>
+ + <span class="string">'\n -t, --timeout MS Timeout in milliseconds, defaults to 2000'</span>
+ + <span class="string">'\n -r, --require PATH Require the given module path'</span>
+ + <span class="string">'\n -o, --only TESTS Execute only the comma sperated TESTS (can be set several times)'</span>
+ + <span class="string">'\n -I, --include PATH Unshift the given path to require.paths'</span>
+ + <span class="string">'\n -p, --port NUM Port number for test servers, starts at 5555'</span>
+ + <span class="string">'\n -s, --serial Execute tests serially'</span>
+ + <span class="string">'\n -b, --boring Suppress ansi-escape colors'</span>
+ + <span class="string">'\n -v, --version Output version number'</span>
+ + <span class="string">'\n -h, --help Display help information'</span>
+ + <span class="string">'\n'</span>;
+
+<span class="comment">// Parse arguments</span>
+
+<span class="keyword">var</span> <span class="variable">files</span> = [],
+ <span class="variable">args</span> = <span class="variable">process</span>.<span class="variable">argv</span>.<span class="variable">slice</span>(<span class="number integer">2</span>);
+
+<span class="keyword">while</span> (<span class="variable">args</span>.<span class="variable">length</span>) {
+ <span class="keyword">var</span> <span class="variable">arg</span> = <span class="variable">args</span>.<span class="variable">shift</span>();
+ <span class="keyword">switch</span> (<span class="variable">arg</span>) {
+ <span class="keyword">case</span> <span class="string">'-h'</span>:
+ <span class="keyword">case</span> <span class="string">'--help'</span>:
+ <span class="variable">print</span>(<span class="variable">usage</span> + <span class="string">'\n'</span>);
+ <span class="variable">process</span>.<span class="variable">exit</span>(<span class="number integer">1</span>);
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-v'</span>:
+ <span class="keyword">case</span> <span class="string">'--version'</span>:
+ <span class="variable">sys</span>.<span class="variable">puts</span>(<span class="variable">version</span>);
+ <span class="variable">process</span>.<span class="variable">exit</span>(<span class="number integer">1</span>);
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-i'</span>:
+ <span class="keyword">case</span> <span class="string">'-I'</span>:
+ <span class="keyword">case</span> <span class="string">'--include'</span>:
+ <span class="keyword">if</span> (<span class="variable">arg</span> = <span class="variable">args</span>.<span class="variable">shift</span>()) {
+ <span class="variable">require</span>.<span class="variable">paths</span>.<span class="variable">unshift</span>(<span class="variable">arg</span>);
+ } <span class="keyword">else</span> {
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="class">Error</span>(<span class="string">'--include requires a path'</span>);
+ }
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-o'</span>:
+ <span class="keyword">case</span> <span class="string">'--only'</span>:
+ <span class="keyword">if</span> (<span class="variable">arg</span> = <span class="variable">args</span>.<span class="variable">shift</span>()) {
+ <span class="variable">only</span> = <span class="variable">only</span>.<span class="variable">concat</span>(<span class="variable">arg</span>.<span class="variable">split</span>(<span class="regexp">/ *, */</span>));
+ } <span class="keyword">else</span> {
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="class">Error</span>(<span class="string">'--only requires comma-separated test names'</span>);
+ }
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-p'</span>:
+ <span class="keyword">case</span> <span class="string">'--port'</span>:
+ <span class="keyword">if</span> (<span class="variable">arg</span> = <span class="variable">args</span>.<span class="variable">shift</span>()) {
+ <span class="variable">port</span> = <span class="variable">parseInt</span>(<span class="variable">arg</span>, <span class="number integer">10</span>);
+ } <span class="keyword">else</span> {
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="class">Error</span>(<span class="string">'--port requires a number'</span>);
+ }
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-r'</span>:
+ <span class="keyword">case</span> <span class="string">'--require'</span>:
+ <span class="keyword">if</span> (<span class="variable">arg</span> = <span class="variable">args</span>.<span class="variable">shift</span>()) {
+ <span class="variable">require</span>(<span class="variable">arg</span>);
+ } <span class="keyword">else</span> {
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="class">Error</span>(<span class="string">'--require requires a path'</span>);
+ }
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-t'</span>:
+ <span class="keyword">case</span> <span class="string">'--timeout'</span>:
+ <span class="keyword">if</span> (<span class="variable">arg</span> = <span class="variable">args</span>.<span class="variable">shift</span>()) {
+ <span class="variable">timeout</span> = <span class="variable">parseInt</span>(<span class="variable">arg</span>, <span class="number integer">10</span>);
+ } <span class="keyword">else</span> {
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="class">Error</span>(<span class="string">'--timeout requires an argument'</span>);
+ }
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-c'</span>:
+ <span class="keyword">case</span> <span class="string">'--cov'</span>:
+ <span class="keyword">case</span> <span class="string">'--coverage'</span>:
+ <span class="variable">defer</span> = <span class="variable">true</span>;
+ <span class="variable">childProcess</span>.<span class="variable">exec</span>(<span class="string">'rm -fr lib-cov &amp;&amp; node-jscoverage lib lib-cov'</span>, <span class="keyword">function</span>(<span class="variable">err</span>) {
+ <span class="keyword">if</span> (<span class="variable">err</span>) <span class="keyword">throw</span> <span class="variable">err</span>;
+ <span class="variable">require</span>.<span class="variable">paths</span>.<span class="variable">unshift</span>(<span class="string">'lib-cov'</span>);
+ <span class="variable">run</span>(<span class="variable">files</span>);
+ });
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-q'</span>:
+ <span class="keyword">case</span> <span class="string">'--quiet'</span>:
+ <span class="variable">quiet</span> = <span class="variable">true</span>;
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-b'</span>:
+ <span class="keyword">case</span> <span class="string">'--boring'</span>:
+ <span class="variable">boring</span> = <span class="variable">true</span>;
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-g'</span>:
+ <span class="keyword">case</span> <span class="string">'--growl'</span>:
+ <span class="variable">growl</span> = <span class="variable">true</span>;
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-s'</span>:
+ <span class="keyword">case</span> <span class="string">'--serial'</span>:
+ <span class="variable">serial</span> = <span class="variable">true</span>;
+ <span class="keyword">break</span>;
+ <span class="keyword">case</span> <span class="string">'-j'</span>:
+ <span class="keyword">case</span> <span class="string">'--json'</span>:
+ <span class="variable">jsonCoverage</span> = <span class="variable">true</span>;
+ <span class="keyword">if</span> (<span class="variable">arg</span> = <span class="variable">args</span>.<span class="variable">shift</span>()) {
+ <span class="variable">jsonFile</span> = <span class="variable">path</span>.<span class="variable">normalize</span>(<span class="variable">arg</span>);
+ } <span class="keyword">else</span> {
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="class">Error</span>(<span class="string">'--json requires file to write to'</span>);
+ }
+ <span class="keyword">break</span>;
+ <span class="keyword">default</span>:
+ <span class="keyword">if</span> (<span class="variable">file_matcher</span>.<span class="variable">test</span>(<span class="variable">arg</span>)) {
+ <span class="variable">files</span>.<span class="variable">push</span>(<span class="variable">arg</span>);
+ }
+ <span class="keyword">break</span>;
+ }
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Colorized sys.error().</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>String</em> str</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">print</span>(<span class="variable">str</span>) {
+ <span class="variable">sys</span>.<span class="variable">error</span>(<span class="variable">colorize</span>(<span class="variable">str</span>));
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Colorize the given string using ansi-escape sequences.
+Disabled when --boring is set.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>String</em> str</p></li><li><p><strong>return</strong>: <em>String</em> </p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">colorize</span>(<span class="variable">str</span>) {
+ <span class="keyword">var</span> <span class="variable">colors</span> = { <span class="variable">bold</span>: <span class="number integer">1</span>, <span class="variable">red</span>: <span class="number integer">31</span>, <span class="variable">green</span>: <span class="number integer">32</span>, <span class="variable">yellow</span>: <span class="number integer">33</span> };
+ <span class="keyword">return</span> <span class="variable">str</span>.<span class="variable">replace</span>(<span class="regexp">/\[(\w+)\]\{([^]*?)\}/g</span>, <span class="keyword">function</span>(<span class="variable">_</span>, <span class="variable">color</span>, <span class="variable">str</span>) {
+ <span class="keyword">return</span> <span class="variable">boring</span>
+ ? <span class="variable">str</span>
+ : <span class="string">'\x1B['</span> + <span class="variable">colors</span>[<span class="variable">color</span>] + <span class="string">'m'</span> + <span class="variable">str</span> + <span class="string">'\x1B[0m'</span>;
+ });
+}
+
+<span class="comment">// Alias deepEqual as eql for complex equality</span>
+
+<span class="variable">assert</span>.<span class="variable">eql</span> = <span class="variable">assert</span>.<span class="variable">deepEqual</span>;</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Assert that <code>val</code> is null.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Mixed</em> val</p></li><li><p><strong>param</strong>: <em>String</em> msg</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="variable">assert</span>.<span class="variable">isNull</span> = <span class="keyword">function</span>(<span class="variable">val</span>, <span class="variable">msg</span>) {
+ <span class="variable">assert</span>.<span class="variable">strictEqual</span>(<span class="keyword">null</span>, <span class="variable">val</span>, <span class="variable">msg</span>);
+};</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Assert that <code>val</code> is not null.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Mixed</em> val</p></li><li><p><strong>param</strong>: <em>String</em> msg</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="variable">assert</span>.<span class="variable">isNotNull</span> = <span class="keyword">function</span>(<span class="variable">val</span>, <span class="variable">msg</span>) {
+ <span class="variable">assert</span>.<span class="variable">notStrictEqual</span>(<span class="keyword">null</span>, <span class="variable">val</span>, <span class="variable">msg</span>);
+};</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Assert that <code>val</code> is undefined.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Mixed</em> val</p></li><li><p><strong>param</strong>: <em>String</em> msg</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="variable">assert</span>.<span class="variable">isUndefined</span> = <span class="keyword">function</span>(<span class="variable">val</span>, <span class="variable">msg</span>) {
+ <span class="variable">assert</span>.<span class="variable">strictEqual</span>(<span class="variable">undefined</span>, <span class="variable">val</span>, <span class="variable">msg</span>);
+};</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Assert that <code>val</code> is not undefined.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Mixed</em> val</p></li><li><p><strong>param</strong>: <em>String</em> msg</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="variable">assert</span>.<span class="variable">isDefined</span> = <span class="keyword">function</span>(<span class="variable">val</span>, <span class="variable">msg</span>) {
+ <span class="variable">assert</span>.<span class="variable">notStrictEqual</span>(<span class="variable">undefined</span>, <span class="variable">val</span>, <span class="variable">msg</span>);
+};</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Assert that <code>obj</code> is <code>type</code>.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Mixed</em> obj</p></li><li><p><strong>param</strong>: <em>String</em> type</p></li><li><p><strong>api</strong>: <em>public</em></p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="variable">assert</span>.<span class="variable">type</span> = <span class="keyword">function</span>(<span class="variable">obj</span>, <span class="variable">type</span>, <span class="variable">msg</span>) {
+ <span class="keyword">var</span> <span class="variable">real</span> = <span class="keyword">typeof</span> <span class="variable">obj</span>;
+ <span class="variable">msg</span> = <span class="variable">msg</span> || <span class="string">'typeof '</span> + <span class="variable">sys</span>.<span class="variable">inspect</span>(<span class="variable">obj</span>) + <span class="string">' is '</span> + <span class="variable">real</span> + <span class="string">', expected '</span> + <span class="variable">type</span>;
+ <span class="variable">assert</span>.<span class="variable">ok</span>(<span class="variable">type</span> === <span class="variable">real</span>, <span class="variable">msg</span>);
+};</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Assert that <code>str</code> matches <code>regexp</code>.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>String</em> str</p></li><li><p><strong>param</strong>: <em>RegExp</em> regexp</p></li><li><p><strong>param</strong>: <em>String</em> msg</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="variable">assert</span>.<span class="variable">match</span> = <span class="keyword">function</span>(<span class="variable">str</span>, <span class="variable">regexp</span>, <span class="variable">msg</span>) {
+ <span class="variable">msg</span> = <span class="variable">msg</span> || <span class="variable">sys</span>.<span class="variable">inspect</span>(<span class="variable">str</span>) + <span class="string">' does not match '</span> + <span class="variable">sys</span>.<span class="variable">inspect</span>(<span class="variable">regexp</span>);
+ <span class="variable">assert</span>.<span class="variable">ok</span>(<span class="variable">regexp</span>.<span class="variable">test</span>(<span class="variable">str</span>), <span class="variable">msg</span>);
+};</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Assert that <code>val</code> is within <code>obj</code>.</p>
+
+<h2>Examples</h2>
+
+<p> assert.includes('foobar', 'bar');
+ assert.includes(['foo', 'bar'], 'foo');</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>String | Array</em> obj</p></li><li><p><strong>param</strong>: <em>Mixed</em> val</p></li><li><p><strong>param</strong>: <em>String</em> msg</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="variable">assert</span>.<span class="variable">includes</span> = <span class="keyword">function</span>(<span class="variable">obj</span>, <span class="variable">val</span>, <span class="variable">msg</span>) {
+ <span class="variable">msg</span> = <span class="variable">msg</span> || <span class="variable">sys</span>.<span class="variable">inspect</span>(<span class="variable">obj</span>) + <span class="string">' does not include '</span> + <span class="variable">sys</span>.<span class="variable">inspect</span>(<span class="variable">val</span>);
+ <span class="variable">assert</span>.<span class="variable">ok</span>(<span class="variable">obj</span>.<span class="variable">indexOf</span>(<span class="variable">val</span>) &<span class="variable">gt</span>;= <span class="number integer">0</span>, <span class="variable">msg</span>);
+};</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Assert length of <code>val</code> is <code>n</code>.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Mixed</em> val</p></li><li><p><strong>param</strong>: <em>Number</em> n</p></li><li><p><strong>param</strong>: <em>String</em> msg</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="variable">assert</span>.<span class="variable">length</span> = <span class="keyword">function</span>(<span class="variable">val</span>, <span class="variable">n</span>, <span class="variable">msg</span>) {
+ <span class="variable">msg</span> = <span class="variable">msg</span> || <span class="variable">sys</span>.<span class="variable">inspect</span>(<span class="variable">val</span>) + <span class="string">' has length of '</span> + <span class="variable">val</span>.<span class="variable">length</span> + <span class="string">', expected '</span> + <span class="variable">n</span>;
+ <span class="variable">assert</span>.<span class="variable">equal</span>(<span class="variable">n</span>, <span class="variable">val</span>.<span class="variable">length</span>, <span class="variable">msg</span>);
+};</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Assert response from <code>server</code> with
+the given <code>req</code> object and <code>res</code> assertions object.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Server</em> server</p></li><li><p><strong>param</strong>: <em>Object</em> req</p></li><li><p><strong>param</strong>: <em>Object | Function</em> res</p></li><li><p><strong>param</strong>: <em>String</em> msg</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="variable">assert</span>.<span class="variable">response</span> = <span class="keyword">function</span>(<span class="variable">server</span>, <span class="variable">req</span>, <span class="variable">res</span>, <span class="variable">msg</span>) {
+ <span class="keyword">var</span> <span class="variable">test</span> = <span class="variable">assert</span>.<span class="variable">_test</span>;
+
+ <span class="comment">// Callback as third or fourth arg</span>
+ <span class="keyword">var</span> <span class="variable">callback</span> = <span class="keyword">typeof</span> <span class="variable">res</span> === <span class="string">'function'</span>
+ ? <span class="variable">res</span>
+ : <span class="keyword">typeof</span> <span class="variable">msg</span> === <span class="string">'function'</span>
+ ? <span class="variable">msg</span>
+ : <span class="keyword">function</span>() {};
+
+ <span class="comment">// Default messate to test title</span>
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="variable">msg</span> === <span class="string">'function'</span>) <span class="variable">msg</span> = <span class="keyword">null</span>;
+ <span class="variable">msg</span> = <span class="variable">msg</span> || <span class="variable">test</span>.<span class="variable">title</span>;
+ <span class="variable">msg</span> += <span class="string">'. '</span>;
+
+ <span class="comment">// Add a unique token for this call to assert.response(). We'll move it to</span>
+ <span class="comment">// succeeded/failed when done</span>
+ <span class="keyword">var</span> <span class="variable">token</span> = <span class="keyword">new</span> <span class="class">Error</span>(<span class="string">'Response not completed: '</span> + <span class="variable">msg</span>);
+ <span class="variable">test</span>.<span class="variable">_pending</span>.<span class="variable">push</span>(<span class="variable">token</span>);
+
+ <span class="keyword">function</span> <span class="variable">check</span>() {
+ <span class="keyword">try</span> {
+ <span class="variable">server</span>.<span class="variable">__port</span> = <span class="variable">server</span>.<span class="variable">address</span>().<span class="variable">port</span>;
+ <span class="variable">server</span>.<span class="variable">__listening</span> = <span class="variable">true</span>;
+ } <span class="keyword">catch</span> (<span class="variable">err</span>) {
+ <span class="variable">process</span>.<span class="variable">nextTick</span>(<span class="variable">check</span>);
+ <span class="keyword">return</span>;
+ }
+ <span class="keyword">if</span> (<span class="variable">server</span>.<span class="variable">__deferred</span>) {
+ <span class="variable">server</span>.<span class="variable">__deferred</span>.<span class="variable">forEach</span>(<span class="keyword">function</span>(<span class="variable">fn</span>) { <span class="variable">fn</span>(); });
+ <span class="variable">server</span>.<span class="variable">__deferred</span> = <span class="keyword">null</span>;
+ }
+ }
+
+ <span class="comment">// Pending responses</span>
+ <span class="variable">server</span>.<span class="variable">__pending</span> = <span class="variable">server</span>.<span class="variable">__pending</span> || <span class="number integer">0</span>;
+ <span class="variable">server</span>.<span class="variable">__pending</span>++;
+
+ <span class="comment">// Check that the server is ready or defer</span>
+ <span class="keyword">if</span> (!<span class="variable">server</span>.<span class="variable">fd</span>) {
+ <span class="variable">server</span>.<span class="variable">__deferred</span> = <span class="variable">server</span>.<span class="variable">__deferred</span> || [];
+ <span class="variable">server</span>.<span class="variable">listen</span>(<span class="variable">server</span>.<span class="variable">__port</span> = <span class="variable">port</span>++, <span class="string">'127.0.0.1'</span>, <span class="variable">check</span>);
+ } <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="variable">server</span>.<span class="variable">__port</span>) {
+ <span class="variable">server</span>.<span class="variable">__deferred</span> = <span class="variable">server</span>.<span class="variable">__deferred</span> || [];
+ <span class="variable">process</span>.<span class="variable">nextTick</span>(<span class="variable">check</span>);
+ }
+
+ <span class="comment">// The socket was created but is not yet listening, so keep deferring</span>
+ <span class="keyword">if</span> (!<span class="variable">server</span>.<span class="variable">__listening</span>) {
+ <span class="variable">server</span>.<span class="variable">__deferred</span>.<span class="variable">push</span>(<span class="variable">issue</span>);
+ <span class="keyword">return</span>;
+ } <span class="keyword">else</span> {
+ <span class="variable">issue</span>();
+ }
+
+ <span class="keyword">function</span> <span class="variable">issue</span>() {
+ <span class="comment">// Issue request</span>
+ <span class="keyword">var</span> <span class="variable">timer</span>,
+ <span class="variable">method</span> = <span class="variable">req</span>.<span class="variable">method</span> || <span class="string">'GET'</span>,
+ <span class="variable">status</span> = <span class="variable">res</span>.<span class="variable">status</span> || <span class="variable">res</span>.<span class="variable">statusCode</span>,
+ <span class="variable">data</span> = <span class="variable">req</span>.<span class="variable">data</span> || <span class="variable">req</span>.<span class="variable">body</span>,
+ <span class="variable">requestTimeout</span> = <span class="variable">req</span>.<span class="variable">timeout</span> || <span class="number integer">0</span>,
+ <span class="variable">encoding</span> = <span class="variable">req</span>.<span class="variable">encoding</span> || <span class="string">'utf8'</span>;
+
+ <span class="keyword">var</span> <span class="variable">request</span> = <span class="variable">http</span>.<span class="variable">request</span>({
+ <span class="variable">host</span>: <span class="string">'127.0.0.1'</span>,
+ <span class="variable">port</span>: <span class="variable">server</span>.<span class="variable">__port</span>,
+ <span class="variable">path</span>: <span class="variable">req</span>.<span class="variable">url</span>,
+ <span class="variable">method</span>: <span class="variable">method</span>,
+ <span class="variable">headers</span>: <span class="variable">req</span>.<span class="variable">headers</span>
+ });
+
+ <span class="keyword">var</span> <span class="variable">check</span> = <span class="keyword">function</span>() {
+ <span class="keyword">if</span> (--<span class="variable">server</span>.<span class="variable">__pending</span> === <span class="number integer">0</span>) {
+ <span class="variable">server</span>.<span class="variable">close</span>();
+ <span class="variable">server</span>.<span class="variable">__listening</span> = <span class="variable">false</span>;
+ }
+ };
+
+ <span class="comment">// Timeout</span>
+ <span class="keyword">if</span> (<span class="variable">requestTimeout</span>) {
+ <span class="variable">timer</span> = <span class="variable">setTimeout</span>(<span class="keyword">function</span>() {
+ <span class="variable">check</span>();
+ <span class="keyword">delete</span> <span class="variable">req</span>.<span class="variable">timeout</span>;
+ <span class="variable">test</span>.<span class="variable">failure</span>(<span class="keyword">new</span> <span class="class">Error</span>(<span class="variable">msg</span> + <span class="string">'Request timed out after '</span> + <span class="variable">requestTimeout</span> + <span class="string">'ms.'</span>));
+ }, <span class="variable">requestTimeout</span>);
+ }
+
+ <span class="keyword">if</span> (<span class="variable">data</span>) <span class="variable">request</span>.<span class="variable">write</span>(<span class="variable">data</span>);
+
+ <span class="variable">request</span>.<span class="variable">on</span>(<span class="string">'response'</span>, <span class="keyword">function</span>(<span class="variable">response</span>) {
+ <span class="variable">response</span>.<span class="variable">body</span> = <span class="string">''</span>;
+ <span class="variable">response</span>.<span class="variable">setEncoding</span>(<span class="variable">encoding</span>);
+ <span class="variable">response</span>.<span class="variable">on</span>(<span class="string">'data'</span>, <span class="keyword">function</span>(<span class="variable">chunk</span>) { <span class="variable">response</span>.<span class="variable">body</span> += <span class="variable">chunk</span>; });
+ <span class="variable">response</span>.<span class="variable">on</span>(<span class="string">'end'</span>, <span class="keyword">function</span>() {
+ <span class="keyword">if</span> (<span class="variable">timer</span>) <span class="variable">clearTimeout</span>(<span class="variable">timer</span>);
+ <span class="keyword">try</span> {
+ <span class="comment">// Assert response body</span>
+ <span class="keyword">if</span> (<span class="variable">res</span>.<span class="variable">body</span> !== <span class="variable">undefined</span>) {
+ <span class="keyword">var</span> <span class="variable">eql</span> = <span class="variable">res</span>.<span class="variable">body</span> <span class="variable">instanceof</span> <span class="class">RegExp</span>
+ ? <span class="variable">res</span>.<span class="variable">body</span>.<span class="variable">test</span>(<span class="variable">response</span>.<span class="variable">body</span>)
+ : <span class="variable">res</span>.<span class="variable">body</span> === <span class="variable">response</span>.<span class="variable">body</span>;
+ <span class="variable">assert</span>.<span class="variable">ok</span>(
+ <span class="variable">eql</span>,
+ <span class="variable">msg</span> + <span class="string">'Invalid response body.\n'</span>
+ + <span class="string">' Expected: '</span> + <span class="variable">sys</span>.<span class="variable">inspect</span>(<span class="variable">res</span>.<span class="variable">body</span>) + <span class="string">'\n'</span>
+ + <span class="string">' Got: '</span> + <span class="variable">sys</span>.<span class="variable">inspect</span>(<span class="variable">response</span>.<span class="variable">body</span>)
+ );
+ }
+
+ <span class="comment">// Assert response status</span>
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="variable">status</span> === <span class="string">'number'</span>) {
+ <span class="variable">assert</span>.<span class="variable">equal</span>(
+ <span class="variable">response</span>.<span class="variable">statusCode</span>,
+ <span class="variable">status</span>,
+ <span class="variable">msg</span> + <span class="variable">colorize</span>(<span class="string">'Invalid response status code.\n'</span>
+ + <span class="string">' Expected: [green]{'</span> + <span class="variable">status</span> + <span class="string">'}\n'</span>
+ + <span class="string">' Got: [red]{'</span> + <span class="variable">response</span>.<span class="variable">statusCode</span> + <span class="string">'}'</span>)
+ );
+ }
+
+ <span class="comment">// Assert response headers</span>
+ <span class="keyword">if</span> (<span class="variable">res</span>.<span class="variable">headers</span>) {
+ <span class="keyword">var</span> <span class="variable">keys</span> = <span class="class">Object</span>.<span class="variable">keys</span>(<span class="variable">res</span>.<span class="variable">headers</span>);
+ <span class="keyword">for</span> (<span class="keyword">var</span> <span class="variable">i</span> = <span class="number integer">0</span>, <span class="variable">len</span> = <span class="variable">keys</span>.<span class="variable">length</span>; <span class="variable">i</span> &<span class="variable">lt</span>; <span class="variable">len</span>; ++<span class="variable">i</span>) {
+ <span class="keyword">var</span> <span class="variable">name</span> = <span class="variable">keys</span>[<span class="variable">i</span>],
+ <span class="variable">actual</span> = <span class="variable">response</span>.<span class="variable">headers</span>[<span class="variable">name</span>.<span class="variable">toLowerCase</span>()],
+ <span class="variable">expected</span> = <span class="variable">res</span>.<span class="variable">headers</span>[<span class="variable">name</span>],
+ <span class="variable">eql</span> = <span class="variable">expected</span> <span class="variable">instanceof</span> <span class="class">RegExp</span>
+ ? <span class="variable">expected</span>.<span class="variable">test</span>(<span class="variable">actual</span>)
+ : <span class="variable">expected</span> == <span class="variable">actual</span>;
+ <span class="variable">assert</span>.<span class="variable">ok</span>(
+ <span class="variable">eql</span>,
+ <span class="variable">msg</span> + <span class="variable">colorize</span>(<span class="string">'Invalid response header [bold]{'</span> + <span class="variable">name</span> + <span class="string">'}.\n'</span>
+ + <span class="string">' Expected: [green]{'</span> + <span class="variable">expected</span> + <span class="string">'}\n'</span>
+ + <span class="string">' Got: [red]{'</span> + <span class="variable">actual</span> + <span class="string">'}'</span>)
+ );
+ }
+ }
+
+ <span class="comment">// Callback</span>
+ <span class="variable">callback</span>(<span class="variable">response</span>);
+
+ <span class="comment">// Add this to the succeeded bin.</span>
+ <span class="variable">test</span>.<span class="variable">success</span>(<span class="variable">msg</span>);
+ } <span class="keyword">catch</span> (<span class="variable">err</span>) {
+ <span class="variable">test</span>.<span class="variable">failure</span>(<span class="variable">err</span>);
+ <span class="variable">test</span>.<span class="variable">callback</span>();
+ } <span class="keyword">finally</span> {
+ <span class="comment">// Remove our token.</span>
+ <span class="keyword">var</span> <span class="variable">idx</span> = <span class="variable">test</span>.<span class="variable">_pending</span>.<span class="variable">indexOf</span>(<span class="variable">token</span>);
+ <span class="keyword">if</span> (<span class="variable">idx</span> &<span class="variable">gt</span>;= <span class="number integer">0</span>) {
+ <span class="variable">test</span>.<span class="variable">_pending</span>.<span class="variable">splice</span>(<span class="variable">idx</span>, <span class="number integer">1</span>);
+ } <span class="keyword">else</span> {
+ <span class="comment">// Someone else took our token. This is an error.</span>
+ <span class="variable">test</span>.<span class="variable">failure</span>(<span class="keyword">new</span> <span class="class">Error</span>(<span class="string">'Request succeeded, but token vanished: '</span> + <span class="variable">msg</span>));
+ }
+
+ <span class="comment">// Potentially shut down the server.</span>
+ <span class="variable">check</span>();
+ }
+ });
+ });
+
+ <span class="variable">request</span>.<span class="variable">end</span>();
+ }
+};</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Pad the given string to the maximum width provided.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>String</em> str</p></li><li><p><strong>param</strong>: <em>Number</em> width</p></li><li><p><strong>return</strong>: <em>String</em> </p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">lpad</span>(<span class="variable">str</span>, <span class="variable">width</span>) {
+ <span class="variable">str</span> = <span class="class">String</span>(<span class="variable">str</span>);
+ <span class="keyword">var</span> <span class="variable">n</span> = <span class="variable">width</span> - <span class="variable">str</span>.<span class="variable">length</span>;
+ <span class="keyword">if</span> (<span class="variable">n</span> &<span class="variable">lt</span>; <span class="number integer">1</span>) <span class="keyword">return</span> <span class="variable">str</span>;
+ <span class="keyword">while</span> (<span class="variable">n</span>--) <span class="variable">str</span> = <span class="string">' '</span> + <span class="variable">str</span>;
+ <span class="keyword">return</span> <span class="variable">str</span>;
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Pad the given string to the maximum width provided.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>String</em> str</p></li><li><p><strong>param</strong>: <em>Number</em> width</p></li><li><p><strong>return</strong>: <em>String</em> </p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">rpad</span>(<span class="variable">str</span>, <span class="variable">width</span>) {
+ <span class="variable">str</span> = <span class="class">String</span>(<span class="variable">str</span>);
+ <span class="keyword">var</span> <span class="variable">n</span> = <span class="variable">width</span> - <span class="variable">str</span>.<span class="variable">length</span>;
+ <span class="keyword">if</span> (<span class="variable">n</span> &<span class="variable">lt</span>; <span class="number integer">1</span>) <span class="keyword">return</span> <span class="variable">str</span>;
+ <span class="keyword">while</span> (<span class="variable">n</span>--) <span class="variable">str</span> = <span class="variable">str</span> + <span class="string">' '</span>;
+ <span class="keyword">return</span> <span class="variable">str</span>;
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Report test coverage in tabular format</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Object</em> cov</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">reportCoverageTable</span>(<span class="variable">cov</span>) {
+ <span class="comment">// Stats</span>
+ <span class="variable">print</span>(<span class="string">'\n [bold]{Test Coverage}\n'</span>);
+ <span class="keyword">var</span> <span class="variable">sep</span> = <span class="string">' +------------------------------------------+----------+------+------+--------+'</span>,
+ <span class="variable">lastSep</span> = <span class="string">' +----------+------+------+--------+'</span>;
+ <span class="variable">sys</span>.<span class="variable">puts</span>(<span class="variable">sep</span>);
+ <span class="variable">sys</span>.<span class="variable">puts</span>(<span class="string">' | filename | coverage | LOC | SLOC | missed |'</span>);
+ <span class="variable">sys</span>.<span class="variable">puts</span>(<span class="variable">sep</span>);
+ <span class="keyword">for</span> (<span class="keyword">var</span> <span class="variable">name</span> <span class="keyword">in</span> <span class="variable">cov</span>) {
+ <span class="keyword">var</span> <span class="variable">file</span> = <span class="variable">cov</span>[<span class="variable">name</span>];
+ <span class="keyword">if</span> (<span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">file</span>)) {
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' | '</span> + <span class="variable">rpad</span>(<span class="variable">name</span>, <span class="number integer">40</span>));
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' | '</span> + <span class="variable">lpad</span>(<span class="variable">file</span>.<span class="variable">coverage</span>.<span class="variable">toFixed</span>(<span class="number integer">2</span>), <span class="number integer">8</span>));
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' | '</span> + <span class="variable">lpad</span>(<span class="variable">file</span>.<span class="class">LOC</span>, <span class="number integer">4</span>));
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' | '</span> + <span class="variable">lpad</span>(<span class="variable">file</span>.<span class="class">SLOC</span>, <span class="number integer">4</span>));
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' | '</span> + <span class="variable">lpad</span>(<span class="variable">file</span>.<span class="variable">totalMisses</span>, <span class="number integer">6</span>));
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' |\n'</span>);
+ }
+ }
+ <span class="variable">sys</span>.<span class="variable">puts</span>(<span class="variable">sep</span>);
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' '</span> + <span class="variable">rpad</span>(<span class="string">''</span>, <span class="number integer">40</span>));
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' | '</span> + <span class="variable">lpad</span>(<span class="variable">cov</span>.<span class="variable">coverage</span>.<span class="variable">toFixed</span>(<span class="number integer">2</span>), <span class="number integer">8</span>));
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' | '</span> + <span class="variable">lpad</span>(<span class="variable">cov</span>.<span class="class">LOC</span>, <span class="number integer">4</span>));
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' | '</span> + <span class="variable">lpad</span>(<span class="variable">cov</span>.<span class="class">SLOC</span>, <span class="number integer">4</span>));
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' | '</span> + <span class="variable">lpad</span>(<span class="variable">cov</span>.<span class="variable">totalMisses</span>, <span class="number integer">6</span>));
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">' |\n'</span>);
+ <span class="variable">sys</span>.<span class="variable">puts</span>(<span class="variable">lastSep</span>);
+ <span class="comment">// Source</span>
+ <span class="keyword">for</span> (<span class="keyword">var</span> <span class="variable">name</span> <span class="keyword">in</span> <span class="variable">cov</span>) {
+ <span class="keyword">if</span> (<span class="variable">name</span>.<span class="variable">match</span>(<span class="variable">file_matcher</span>)) {
+ <span class="keyword">var</span> <span class="variable">file</span> = <span class="variable">cov</span>[<span class="variable">name</span>];
+ <span class="keyword">if</span> ((<span class="variable">file</span>.<span class="variable">coverage</span> &<span class="variable">lt</span>; <span class="number integer">100</span>) || !<span class="variable">quiet</span>) {
+ <span class="variable">print</span>(<span class="string">'\n [bold]{'</span> + <span class="variable">name</span> + <span class="string">'}:'</span>);
+ <span class="variable">print</span>(<span class="variable">file</span>.<span class="variable">source</span>);
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">'\n'</span>);
+ }
+ }
+ }
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Report test coverage in raw json format</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Object</em> cov</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">reportCoverageJson</span>(<span class="variable">cov</span>) {
+ <span class="keyword">var</span> <span class="variable">report</span> = {
+ &<span class="variable">quot</span>;<span class="variable">coverage</span>&<span class="variable">quot</span>; : <span class="variable">cov</span>.<span class="variable">coverage</span>.<span class="variable">toFixed</span>(<span class="number integer">2</span>),
+ &<span class="variable">quot</span>;<span class="class">LOC</span>&<span class="variable">quot</span>; : <span class="variable">cov</span>.<span class="class">LOC</span>,
+ &<span class="variable">quot</span>;<span class="class">SLOC</span>&<span class="variable">quot</span>; : <span class="variable">cov</span>.<span class="class">SLOC</span>,
+ &<span class="variable">quot</span>;<span class="variable">totalMisses</span>&<span class="variable">quot</span>; : <span class="variable">cov</span>.<span class="variable">totalMisses</span>,
+ &<span class="variable">quot</span>;<span class="variable">files</span>&<span class="variable">quot</span>; : {}
+ };
+
+ <span class="keyword">for</span> (<span class="keyword">var</span> <span class="variable">name</span> <span class="keyword">in</span> <span class="variable">cov</span>) {
+ <span class="keyword">var</span> <span class="variable">file</span> = <span class="variable">cov</span>[<span class="variable">name</span>];
+ <span class="keyword">if</span> (<span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">file</span>)) {
+ <span class="variable">report</span>.<span class="variable">files</span>[<span class="variable">name</span>] = {
+ &<span class="variable">quot</span>;<span class="variable">coverage</span>&<span class="variable">quot</span>; : <span class="variable">file</span>.<span class="variable">coverage</span>.<span class="variable">toFixed</span>(<span class="number integer">2</span>),
+ &<span class="variable">quot</span>;<span class="class">LOC</span>&<span class="variable">quot</span>; : <span class="variable">file</span>.<span class="class">LOC</span>,
+ &<span class="variable">quot</span>;<span class="class">SLOC</span>&<span class="variable">quot</span>; : <span class="variable">file</span>.<span class="class">SLOC</span>,
+ &<span class="variable">quot</span>;<span class="variable">totalMisses</span>&<span class="variable">quot</span>; : <span class="variable">file</span>.<span class="variable">totalMisses</span>
+ };
+ }
+ }
+
+ <span class="variable">fs</span>.<span class="variable">writeFileSync</span>(<span class="variable">jsonFile</span>, <span class="class">JSON</span>.<span class="variable">stringify</span>(<span class="variable">report</span>), &<span class="variable">quot</span>;<span class="variable">utf8</span>&<span class="variable">quot</span>;);
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Populate code coverage data.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Object</em> cov</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">populateCoverage</span>(<span class="variable">cov</span>) {
+ <span class="variable">cov</span>.<span class="class">LOC</span> =
+ <span class="variable">cov</span>.<span class="class">SLOC</span> =
+ <span class="variable">cov</span>.<span class="variable">totalFiles</span> =
+ <span class="variable">cov</span>.<span class="variable">totalHits</span> =
+ <span class="variable">cov</span>.<span class="variable">totalMisses</span> =
+ <span class="variable">cov</span>.<span class="variable">coverage</span> = <span class="number integer">0</span>;
+ <span class="keyword">for</span> (<span class="keyword">var</span> <span class="variable">name</span> <span class="keyword">in</span> <span class="variable">cov</span>) {
+ <span class="keyword">var</span> <span class="variable">file</span> = <span class="variable">cov</span>[<span class="variable">name</span>];
+ <span class="keyword">if</span> (<span class="class">Array</span>.<span class="variable">isArray</span>(<span class="variable">file</span>)) {
+ <span class="comment">// Stats</span>
+ ++<span class="variable">cov</span>.<span class="variable">totalFiles</span>;
+ <span class="variable">cov</span>.<span class="variable">totalHits</span> += <span class="variable">file</span>.<span class="variable">totalHits</span> = <span class="variable">coverage</span>(<span class="variable">file</span>, <span class="variable">true</span>);
+ <span class="variable">cov</span>.<span class="variable">totalMisses</span> += <span class="variable">file</span>.<span class="variable">totalMisses</span> = <span class="variable">coverage</span>(<span class="variable">file</span>, <span class="variable">false</span>);
+ <span class="variable">file</span>.<span class="variable">totalLines</span> = <span class="variable">file</span>.<span class="variable">totalHits</span> + <span class="variable">file</span>.<span class="variable">totalMisses</span>;
+ <span class="variable">cov</span>.<span class="class">SLOC</span> += <span class="variable">file</span>.<span class="class">SLOC</span> = <span class="variable">file</span>.<span class="variable">totalLines</span>;
+ <span class="keyword">if</span> (!<span class="variable">file</span>.<span class="variable">source</span>) <span class="variable">file</span>.<span class="variable">source</span> = [];
+ <span class="variable">cov</span>.<span class="class">LOC</span> += <span class="variable">file</span>.<span class="class">LOC</span> = <span class="variable">file</span>.<span class="variable">source</span>.<span class="variable">length</span>;
+ <span class="variable">file</span>.<span class="variable">coverage</span> = (<span class="variable">file</span>.<span class="variable">totalHits</span> / <span class="variable">file</span>.<span class="variable">totalLines</span>) * <span class="number integer">100</span>;
+ <span class="comment">// Source</span>
+ <span class="keyword">var</span> <span class="variable">width</span> = <span class="variable">file</span>.<span class="variable">source</span>.<span class="variable">length</span>.<span class="variable">toString</span>().<span class="variable">length</span>;
+ <span class="variable">file</span>.<span class="variable">source</span> = <span class="variable">file</span>.<span class="variable">source</span>.<span class="variable">map</span>(<span class="keyword">function</span>(<span class="variable">line</span>, <span class="variable">i</span>) {
+ ++<span class="variable">i</span>;
+ <span class="keyword">var</span> <span class="variable">hits</span> = <span class="variable">file</span>[<span class="variable">i</span>] === <span class="number integer">0</span> ? <span class="number integer">0</span> : (<span class="variable">file</span>[<span class="variable">i</span>] || <span class="string">' '</span>);
+ <span class="keyword">if</span> (!<span class="variable">boring</span>) {
+ <span class="keyword">if</span> (<span class="variable">hits</span> === <span class="number integer">0</span>) {
+ <span class="variable">hits</span> = <span class="string">'\x1b[31m'</span> + <span class="variable">hits</span> + <span class="string">'\x1b[0m'</span>;
+ <span class="variable">line</span> = <span class="string">'\x1b[41m'</span> + <span class="variable">line</span> + <span class="string">'\x1b[0m'</span>;
+ } <span class="keyword">else</span> {
+ <span class="variable">hits</span> = <span class="string">'\x1b[32m'</span> + <span class="variable">hits</span> + <span class="string">'\x1b[0m'</span>;
+ }
+ }
+ <span class="keyword">return</span> <span class="string">'\n '</span> + <span class="variable">lpad</span>(<span class="variable">i</span>, <span class="variable">width</span>) + <span class="string">' | '</span> + <span class="variable">hits</span> + <span class="string">' | '</span> + <span class="variable">line</span>;
+ }).<span class="variable">join</span>(<span class="string">''</span>);
+ }
+ }
+ <span class="variable">cov</span>.<span class="variable">coverage</span> = (<span class="variable">cov</span>.<span class="variable">totalHits</span> / <span class="variable">cov</span>.<span class="class">SLOC</span>) * <span class="number integer">100</span>;
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Total coverage for the given file data.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Array</em> data</p></li><li><p><strong>return</strong>: <em>Type</em> </p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">coverage</span>(<span class="variable">data</span>, <span class="variable">val</span>) {
+ <span class="keyword">var</span> <span class="variable">n</span> = <span class="number integer">0</span>;
+ <span class="keyword">for</span> (<span class="keyword">var</span> <span class="variable">i</span> = <span class="number integer">0</span>, <span class="variable">len</span> = <span class="variable">data</span>.<span class="variable">length</span>; <span class="variable">i</span> &<span class="variable">lt</span>; <span class="variable">len</span>; ++<span class="variable">i</span>) {
+ <span class="keyword">if</span> (<span class="variable">data</span>[<span class="variable">i</span>] !== <span class="variable">undefined</span> &<span class="variable">amp</span>;&<span class="variable">amp</span>; <span class="variable">data</span>[<span class="variable">i</span>] == <span class="variable">val</span>) ++<span class="variable">n</span>;
+ }
+ <span class="keyword">return</span> <span class="variable">n</span>;
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Test if all files have 100% coverage</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Object</em> cov</p></li><li><p><strong>return</strong>: <em>Boolean</em> </p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">hasFullCoverage</span>(<span class="variable">cov</span>) {
+ <span class="keyword">for</span> (<span class="keyword">var</span> <span class="variable">name</span> <span class="keyword">in</span> <span class="variable">cov</span>) {
+ <span class="keyword">var</span> <span class="variable">file</span> = <span class="variable">cov</span>[<span class="variable">name</span>];
+ <span class="keyword">if</span> (<span class="variable">file</span> <span class="variable">instanceof</span> <span class="class">Array</span>) {
+ <span class="keyword">if</span> (<span class="variable">file</span>.<span class="variable">coverage</span> !== <span class="number integer">100</span>) {
+ <span class="keyword">return</span> <span class="variable">false</span>;
+ }
+ }
+ }
+ <span class="keyword">return</span> <span class="variable">true</span>;
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Run the given test <code>files</code>, or try <em>test/*</em>.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Array</em> files</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">run</span>(<span class="variable">files</span>) {
+ <span class="variable">cursor</span>(<span class="variable">false</span>);
+ <span class="keyword">if</span> (!<span class="variable">files</span>.<span class="variable">length</span>) {
+ <span class="keyword">try</span> {
+ <span class="variable">files</span> = <span class="variable">fs</span>.<span class="variable">readdirSync</span>(<span class="string">'test'</span>).<span class="variable">map</span>(<span class="keyword">function</span>(<span class="variable">file</span>) {
+ <span class="keyword">return</span> <span class="string">'test/'</span> + <span class="variable">file</span>;
+ }).<span class="variable">filter</span>(<span class="keyword">function</span>(<span class="variable">file</span>) {
+ <span class="keyword">return</span> !(<span class="regexp">/(^\.)|(\/</span>\.)/.<span class="variable">test</span>(<span class="variable">file</span>));
+ });
+ } <span class="keyword">catch</span> (<span class="variable">err</span>) {
+ <span class="variable">print</span>(<span class="string">'\n failed to load tests in [bold]{./test}\n'</span>);
+ ++<span class="variable">failures</span>;
+ <span class="variable">process</span>.<span class="variable">exit</span>(<span class="number integer">1</span>);
+ }
+ }
+ <span class="variable">runFiles</span>(<span class="variable">files</span>);
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Show the cursor when <code>show</code> is true, otherwise hide it.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Boolean</em> show</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">cursor</span>(<span class="variable">show</span>) {
+ <span class="keyword">if</span> (<span class="variable">boring</span>) <span class="keyword">return</span>;
+ <span class="keyword">if</span> (<span class="variable">show</span>) {
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">'\x1b[?25h'</span>);
+ } <span class="keyword">else</span> {
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">'\x1b[?25l'</span>);
+ }
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Run the given test <code>files</code>.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>Array</em> files</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">runFiles</span>(<span class="variable">files</span>) {
+ <span class="variable">files</span> = <span class="variable">files</span>.<span class="variable">filter</span>(<span class="keyword">function</span>(<span class="variable">file</span>) {
+ <span class="keyword">return</span> <span class="variable">file</span>.<span class="variable">match</span>(<span class="variable">file_matcher</span>);
+ });
+ <span class="variable">suites</span> = <span class="variable">files</span>.<span class="variable">length</span>;
+
+ <span class="keyword">if</span> (<span class="variable">serial</span>) {
+ (<span class="keyword">function</span> <span class="variable">next</span>() {
+ <span class="keyword">if</span> (<span class="variable">files</span>.<span class="variable">length</span>) {
+ <span class="variable">runFile</span>(<span class="variable">files</span>.<span class="variable">shift</span>(), <span class="variable">next</span>);
+ }
+ })();
+ } <span class="keyword">else</span> {
+ <span class="variable">files</span>.<span class="variable">forEach</span>(<span class="variable">runFile</span>);
+ }
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Run tests for the given <code>file</code>, callback <code>fn()</code> when finished.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>String</em> file</p></li><li><p><strong>param</strong>: <em>Function</em> fn</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">runFile</span>(<span class="variable">file</span>, <span class="variable">fn</span>) {
+ <span class="keyword">var</span> <span class="variable">title</span> = <span class="variable">path</span>.<span class="variable">basename</span>(<span class="variable">file</span>),
+ <span class="variable">file</span> = <span class="variable">path</span>.<span class="variable">join</span>(<span class="variable">cwd</span>, <span class="variable">file</span>),
+ <span class="variable">mod</span> = <span class="variable">require</span>(<span class="variable">file</span>.<span class="variable">replace</span>(<span class="variable">file_matcher</span>,<span class="string">''</span>));
+ (<span class="keyword">function</span> <span class="variable">check</span>() {
+ <span class="keyword">var</span> <span class="variable">len</span> = <span class="class">Object</span>.<span class="variable">keys</span>(<span class="variable">mod</span>).<span class="variable">length</span>;
+ <span class="keyword">if</span> (<span class="variable">len</span>) {
+ <span class="variable">runSuite</span>(<span class="variable">title</span>, <span class="variable">mod</span>, <span class="variable">fn</span>);
+ <span class="variable">suitesRun</span>++;
+ } <span class="keyword">else</span> {
+ <span class="variable">setTimeout</span>(<span class="variable">check</span>, <span class="number integer">20</span>);
+ }
+ })();
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Run the given tests, callback <code>fn()</code> when finished.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>String</em> title</p></li><li><p><strong>param</strong>: <em>Object</em> tests</p></li><li><p><strong>param</strong>: <em>Function</em> fn</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">var</span> <span class="variable">dots</span> = <span class="number integer">0</span>;
+<span class="keyword">function</span> <span class="variable">runSuite</span>(<span class="variable">title</span>, <span class="variable">tests</span>, <span class="variable">callback</span>) {
+ <span class="comment">// Keys</span>
+ <span class="keyword">var</span> <span class="variable">keys</span> = <span class="variable">only</span>.<span class="variable">length</span>
+ ? <span class="variable">only</span>.<span class="variable">slice</span>(<span class="number integer">0</span>)
+ : <span class="class">Object</span>.<span class="variable">keys</span>(<span class="variable">tests</span>);
+
+ <span class="comment">// Setup</span>
+ <span class="keyword">var</span> <span class="variable">setup</span> = <span class="variable">tests</span>.<span class="variable">setup</span> || <span class="keyword">function</span>(<span class="variable">fn</span>, <span class="variable">assert</span>) { <span class="variable">fn</span>(); };
+ <span class="keyword">var</span> <span class="variable">teardown</span> = <span class="variable">tests</span>.<span class="variable">teardown</span> || <span class="keyword">function</span>(<span class="variable">fn</span>, <span class="variable">assert</span>) { <span class="variable">fn</span>(); };
+
+ <span class="variable">process</span>.<span class="variable">setMaxListeners</span>(<span class="number integer">10</span> + <span class="variable">process</span>.<span class="variable">listeners</span>(<span class="string">'beforeExit'</span>).<span class="variable">length</span> + <span class="variable">keys</span>.<span class="variable">length</span>);
+
+ <span class="comment">// Iterate tests</span>
+ (<span class="keyword">function</span> <span class="variable">next</span>() {
+ <span class="keyword">if</span> (<span class="variable">keys</span>.<span class="variable">length</span>) {
+ <span class="keyword">var</span> <span class="variable">key</span>,
+ <span class="variable">fn</span> = <span class="variable">tests</span>[<span class="variable">key</span> = <span class="variable">keys</span>.<span class="variable">shift</span>()];
+ <span class="comment">// Non-tests</span>
+ <span class="keyword">if</span> (<span class="variable">key</span> === <span class="string">'setup'</span> || <span class="variable">key</span> === <span class="string">'teardown'</span>) <span class="keyword">return</span> <span class="variable">next</span>();
+
+ <span class="comment">// Run test</span>
+ <span class="keyword">if</span> (<span class="variable">fn</span>) {
+ <span class="keyword">var</span> <span class="variable">test</span> = <span class="keyword">new</span> <span class="class">Test</span>({
+ <span class="variable">fn</span>: <span class="variable">fn</span>,
+ <span class="variable">suite</span>: <span class="variable">title</span>,
+ <span class="variable">title</span>: <span class="variable">key</span>,
+ <span class="variable">setup</span>: <span class="variable">setup</span>,
+ <span class="variable">teardown</span>: <span class="variable">teardown</span>
+ })
+ <span class="variable">test</span>.<span class="variable">run</span>(<span class="variable">next</span>);
+ } <span class="keyword">else</span> {
+ <span class="comment">// @TODO: Add warning message that there's no test.</span>
+ <span class="variable">next</span>();
+ }
+ } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="variable">serial</span>) {
+ <span class="variable">callback</span>();
+ }
+ })();
+}
+
+<span class="variable">require</span>(<span class="string">'util'</span>).<span class="variable">inherits</span>(<span class="class">Test</span>, <span class="variable">require</span>(<span class="string">'events'</span>).<span class="class">EventEmitter</span>);
+<span class="keyword">function</span> <span class="class">Test</span>(<span class="variable">options</span>) {
+ <span class="keyword">for</span> (<span class="keyword">var</span> <span class="variable">key</span> <span class="keyword">in</span> <span class="variable">options</span>) {
+ <span class="this">this</span>[<span class="variable">key</span>] = <span class="variable">options</span>[<span class="variable">key</span>];
+ }
+ <span class="this">this</span>.<span class="variable">_succeeded</span> = [];
+ <span class="this">this</span>.<span class="variable">_failed</span> = [];
+ <span class="this">this</span>.<span class="variable">_pending</span> = [];
+ <span class="this">this</span>.<span class="variable">_beforeExit</span> = [];
+ <span class="this">this</span>.<span class="variable">assert</span> = { <span class="variable">__proto__</span>: <span class="variable">assert</span>, <span class="variable">_test</span>: <span class="this">this</span> };
+
+ <span class="keyword">var</span> <span class="variable">test</span> = <span class="this">this</span>;
+ <span class="variable">process</span>.<span class="variable">on</span>(<span class="string">'beforeExit'</span>, <span class="keyword">function</span>() {
+ <span class="keyword">try</span> {
+ <span class="variable">test</span>.<span class="variable">emit</span>(<span class="string">'exit'</span>);
+ } <span class="keyword">catch</span> (<span class="variable">err</span>) {
+ <span class="variable">test</span>.<span class="variable">failure</span>(<span class="variable">err</span>);
+ }
+ <span class="variable">test</span>.<span class="variable">report</span>();
+ });
+}
+
+<span class="class">Test</span>.<span class="variable">prototype</span>.<span class="variable">success</span> = <span class="keyword">function</span>(<span class="variable">err</span>) {
+ <span class="this">this</span>.<span class="variable">_succeeded</span>.<span class="variable">push</span>(<span class="variable">err</span>);
+};
+
+<span class="class">Test</span>.<span class="variable">prototype</span>.<span class="variable">failure</span> = <span class="keyword">function</span>(<span class="variable">err</span>) {
+ <span class="this">this</span>.<span class="variable">_failed</span>.<span class="variable">push</span>(<span class="variable">err</span>);
+ <span class="this">this</span>.<span class="variable">error</span>(<span class="variable">err</span>);
+};
+
+<span class="class">Test</span>.<span class="variable">prototype</span>.<span class="variable">report</span> = <span class="keyword">function</span>() {
+ <span class="keyword">for</span> (<span class="keyword">var</span> <span class="variable">i</span> = <span class="number integer">0</span>; <span class="variable">i</span> &<span class="variable">lt</span>; <span class="this">this</span>.<span class="variable">_pending</span>.<span class="variable">length</span>; <span class="variable">i</span>++) {
+ <span class="this">this</span>.<span class="variable">error</span>(<span class="this">this</span>.<span class="variable">_pending</span>[<span class="variable">i</span>]);
+ }
+};
+
+<span class="class">Test</span>.<span class="variable">prototype</span>.<span class="variable">run</span> = <span class="keyword">function</span>(<span class="variable">callback</span>) {
+ <span class="keyword">try</span> {
+ ++<span class="variable">testcount</span>;
+ <span class="variable">assert</span>.<span class="variable">_test</span> = <span class="this">this</span>;
+
+ <span class="keyword">if</span> (<span class="variable">serial</span>) {
+ <span class="this">this</span>.<span class="variable">runSerial</span>(<span class="variable">callback</span>);
+ } <span class="keyword">else</span> {
+ <span class="comment">// @TODO: find a way to run setup/tearDown.</span>
+ <span class="this">this</span>.<span class="variable">runParallel</span>();
+ <span class="variable">callback</span>();
+ }
+ } <span class="keyword">catch</span> (<span class="variable">err</span>) {
+ <span class="this">this</span>.<span class="variable">failure</span>(<span class="variable">err</span>);
+ <span class="this">this</span>.<span class="variable">report</span>();
+ }
+};
+
+<span class="class">Test</span>.<span class="variable">prototype</span>.<span class="variable">runSerial</span> = <span class="keyword">function</span>(<span class="variable">callback</span>) {
+ <span class="keyword">var</span> <span class="variable">test</span> = <span class="this">this</span>;
+ <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">'.'</span>);
+ <span class="keyword">if</span> (++<span class="variable">dots</span> % <span class="number integer">25</span> === <span class="number integer">0</span>) <span class="variable">sys</span>.<span class="variable">print</span>(<span class="string">'\n'</span>);
+ <span class="variable">test</span>.<span class="variable">setup</span>(<span class="keyword">function</span>() {
+ <span class="keyword">if</span> (<span class="variable">test</span>.<span class="variable">fn</span>.<span class="variable">length</span> &<span class="variable">lt</span>; <span class="number integer">1</span>) {
+ <span class="variable">test</span>.<span class="variable">fn</span>();
+ <span class="variable">test</span>.<span class="variable">teardown</span>(<span class="variable">callback</span>);
+ } <span class="keyword">else</span> {
+ <span class="keyword">var</span> <span class="variable">id</span> = <span class="variable">setTimeout</span>(<span class="keyword">function</span>() {
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="class">Error</span>(&<span class="variable">quot</span>;<span class="string">'&quot; + key + &quot;'</span> <span class="variable">timed</span> <span class="variable">out</span>&<span class="variable">quot</span>;);
+ }, <span class="variable">timeout</span>);
+ <span class="variable">test</span>.<span class="variable">callback</span> = <span class="keyword">function</span>() {
+ <span class="variable">clearTimeout</span>(<span class="variable">id</span>);
+ <span class="variable">test</span>.<span class="variable">teardown</span>(<span class="variable">callback</span>);
+ <span class="variable">process</span>.<span class="variable">nextTick</span>(<span class="keyword">function</span>() {
+ <span class="variable">test</span>.<span class="variable">report</span>();
+ });
+ };
+ <span class="variable">test</span>.<span class="variable">fn</span>(<span class="variable">test</span>.<span class="variable">callback</span>);
+ }
+ });
+};
+
+<span class="class">Test</span>.<span class="variable">prototype</span>.<span class="variable">runParallel</span> = <span class="keyword">function</span>() {
+ <span class="keyword">var</span> <span class="variable">test</span> = <span class="this">this</span>;
+ <span class="variable">test</span>.<span class="variable">fn</span>(<span class="keyword">function</span>(<span class="variable">fn</span>) {
+ <span class="variable">test</span>.<span class="variable">on</span>(<span class="string">'exit'</span>, <span class="keyword">function</span>() {
+ <span class="variable">fn</span>(<span class="variable">test</span>.<span class="variable">assert</span>);
+ });
+ }, <span class="variable">test</span>.<span class="variable">assert</span>);
+};</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Report <code>err</code> for the given <code>test</code> and <code>suite</code>.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>String</em> suite</p></li><li><p><strong>param</strong>: <em>String</em> test</p></li><li><p><strong>param</strong>: <em>Error</em> err</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="class">Test</span>.<span class="variable">prototype</span>.<span class="variable">error</span> = <span class="keyword">function</span>(<span class="variable">err</span>) {
+ <span class="keyword">if</span> (!<span class="variable">err</span>.<span class="variable">_reported</span>) {
+ ++<span class="variable">failures</span>;
+ <span class="keyword">var</span> <span class="variable">name</span> = <span class="variable">err</span>.<span class="variable">name</span>,
+ <span class="variable">stack</span> = <span class="variable">err</span>.<span class="variable">stack</span> ? <span class="variable">err</span>.<span class="variable">stack</span>.<span class="variable">replace</span>(<span class="variable">err</span>.<span class="variable">name</span>, <span class="string">''</span>) : <span class="string">''</span>,
+ <span class="keyword">label</span> = <span class="this">this</span>.<span class="variable">title</span> === <span class="string">'uncaught'</span>
+ ? <span class="this">this</span>.<span class="variable">title</span>
+ : <span class="this">this</span>.<span class="variable">suite</span> + <span class="string">' '</span> + <span class="this">this</span>.<span class="variable">title</span>;
+ <span class="variable">print</span>(<span class="string">'\n [bold]{'</span> + <span class="keyword">label</span> + <span class="string">'}: [red]{'</span> + <span class="variable">name</span> + <span class="string">'}'</span> + <span class="variable">stack</span> + <span class="string">'\n'</span>);
+ <span class="variable">err</span>.<span class="variable">_reported</span> = <span class="variable">true</span>;
+ }
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Report exceptions.
+ </p>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">report</span>() {
+ <span class="variable">cursor</span>(<span class="variable">true</span>);
+ <span class="variable">process</span>.<span class="variable">emit</span>(<span class="string">'beforeExit'</span>);
+ <span class="keyword">if</span> (<span class="variable">suitesRun</span> &<span class="variable">lt</span>; <span class="variable">suites</span>) {
+ <span class="variable">print</span>(<span class="string">'\n [bold]{Failure}: [red]{Only '</span> + <span class="variable">suitesRun</span> + <span class="string">' of '</span> + <span class="variable">suites</span> + <span class="string">' suites have been started}\n\n'</span>);
+ }
+ <span class="keyword">else</span> <span class="keyword">if</span> (<span class="variable">failures</span>) {
+ <span class="variable">print</span>(<span class="string">'\n [bold]{Failures}: [red]{'</span> + <span class="variable">failures</span> + <span class="string">'}\n\n'</span>);
+ <span class="variable">notify</span>(<span class="string">'Failures: '</span> + <span class="variable">failures</span>);
+ } <span class="keyword">else</span> {
+ <span class="keyword">if</span> (<span class="variable">serial</span>) <span class="variable">print</span>(<span class="string">''</span>);
+ <span class="variable">print</span>(<span class="string">'\n [green]{100%} '</span> + <span class="variable">testcount</span> + <span class="string">' tests\n'</span>);
+ <span class="variable">notify</span>(<span class="string">'100% ok'</span>);
+ }
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="variable">_</span>$<span class="variable">jscoverage</span> === <span class="string">'object'</span>) {
+ <span class="variable">populateCoverage</span>(<span class="variable">_</span>$<span class="variable">jscoverage</span>);
+ <span class="keyword">if</span> (!<span class="variable">hasFullCoverage</span>(<span class="variable">_</span>$<span class="variable">jscoverage</span>) || !<span class="variable">quiet</span>) {
+ (<span class="variable">jsonCoverage</span> ? <span class="variable">reportCoverageJson</span>(<span class="variable">_</span>$<span class="variable">jscoverage</span>) : <span class="variable">reportCoverageTable</span>(<span class="variable">_</span>$<span class="variable">jscoverage</span>));
+ }
+ }
+}</code></pre>
+</td>
+</tr>
+<tr class="code">
+<td class="docs">
+<p>Growl notify the given <code>msg</code>.</p>
+
+<h2></h2>
+
+<ul><li><p><strong>param</strong>: <em>String</em> msg</p></li></ul>
+</td>
+<td class="code">
+<pre><code><span class="keyword">function</span> <span class="variable">notify</span>(<span class="variable">msg</span>) {
+ <span class="keyword">if</span> (<span class="variable">growl</span>) {
+ <span class="variable">childProcess</span>.<span class="variable">exec</span>(<span class="string">'growlnotify -name Expresso -m &quot;'</span> + <span class="variable">msg</span> + <span class="string">'&quot;'</span>);
+ }
+}
+
+<span class="comment">// Report uncaught exceptions</span>
+<span class="keyword">var</span> <span class="variable">unknownTest</span> = <span class="keyword">new</span> <span class="class">Test</span>({
+ <span class="variable">suite</span>: <span class="string">'uncaught'</span>,
+ <span class="variable">test</span>: <span class="string">'uncaught'</span>
+});
+
+<span class="variable">process</span>.<span class="variable">on</span>(<span class="string">'uncaughtException'</span>, <span class="keyword">function</span>(<span class="variable">err</span>) {
+ <span class="variable">unknownTest</span>.<span class="variable">error</span>(<span class="variable">err</span>);
+});
+
+<span class="comment">// Show cursor</span>
+
+[<span class="string">'INT'</span>, <span class="string">'TERM'</span>, <span class="string">'QUIT'</span>].<span class="variable">forEach</span>(<span class="keyword">function</span>(<span class="variable">sig</span>) {
+ <span class="variable">process</span>.<span class="variable">on</span>(<span class="string">'SIG'</span> + <span class="variable">sig</span>, <span class="keyword">function</span>() {
+ <span class="variable">cursor</span>(<span class="variable">true</span>);
+ <span class="variable">process</span>.<span class="variable">exit</span>(<span class="number integer">1</span>);
+ });
+});
+
+<span class="comment">// Report test coverage when available</span>
+<span class="comment">// and emit &quot;beforeExit&quot; event to perform</span>
+<span class="comment">// final assertions</span>
+
+<span class="keyword">var</span> <span class="variable">orig</span> = <span class="variable">process</span>.<span class="variable">emit</span>;
+<span class="variable">process</span>.<span class="variable">emit</span> = <span class="keyword">function</span>(<span class="variable">event</span>) {
+ <span class="keyword">if</span> (<span class="variable">event</span> === <span class="string">'exit'</span>) {
+ <span class="variable">report</span>();
+ <span class="variable">process</span>.<span class="variable">reallyExit</span>(<span class="variable">failures</span>);
+ }
+ <span class="variable">orig</span>.<span class="variable">apply</span>(<span class="this">this</span>, <span class="variable">arguments</span>);
+};
+
+<span class="comment">// Run test files</span>
+
+<span class="keyword">if</span> (!<span class="variable">defer</span>) <span class="variable">run</span>(<span class="variable">files</span>);
+</code></pre>
+</td>
+</tr> </body>
+</html></tbody></table> \ No newline at end of file
diff --git a/tools/node_modules/expresso/docs/index.html b/tools/node_modules/expresso/docs/index.html
new file mode 100644
index 0000000..587f933
--- /dev/null
+++ b/tools/node_modules/expresso/docs/index.html
@@ -0,0 +1,174 @@
+<html>
+ <head>
+ <title>Expresso - TDD Framework For Node</title>
+ <style>
+ body {
+ font: 13px/1.4 "Helvetica", "Lucida Grande", Arial, sans-serif;
+ text-align: center;
+ }
+ #ribbon {
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 10;
+ }
+ #wrapper {
+ margin: 0 auto;
+ padding: 50px 80px;
+ width: 700px;
+ text-align: left;
+ }
+ h1, h2, h3 {
+ margin: 25px 0 15px 0;
+ }
+ h1 {
+ font-size: 35px;
+ }
+ pre {
+ margin: 0 5px;
+ padding: 15px;
+ border: 1px solid #eee;
+ }
+ a {
+ color: #00aaff;
+ }
+ </style>
+ </head>
+ <body>
+ <a href="http://github.com/visionmedia/expresso">
+ <img alt="Fork me on GitHub" id="ribbon" src="http://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png" />
+ </a>
+ <div id="wrapper">
+ <h1>Expresso 0.9.0</h1>
+<html><p><a href="http://github.com/visionmedia/expresso">Expresso</a> is a JavaScript <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> framework written for <a href="http://nodejs.org">nodejs</a>. Expresso is extremely fast, and is packed with features such as additional assertion methods, code coverage reporting, CI support, and more.</p><h2 id="Features">Features</h2><ul><li>light-weight</li><li>intuitive async support</li><li>intuitive test runner executable</li><li>test coverage support and reporting via <a href="http://github.com/visionmedia/node-jscoverage">node-jscoverage</a></li><li>uses and extends the core <code>assert</code> module</li><li><code>assert.eql()</code> alias of <code>assert.deepEqual()</code></li><li><code>assert.response()</code> http response utility</li><li><code>assert.includes()</code></li><li><code>assert.isNull()</code></li><li><code>assert.isUndefined()</code></li><li><code>assert.isNotNull()</code></li><li><code>assert.isDefined()</code></li><li><code>assert.match()</code></li><li><code>assert.length()</code></li></ul><h2 id="Installation">Installation</h2><p>To install both expresso <em>and</em> node-jscoverage run
+the command below, which will first compile node-jscoverage:</p><pre><code>$ make install</code></pre><p>To install expresso alone without coverage reporting run:</p><pre><code>$ make install-expresso</code></pre><p>Install via npm:</p><pre><code>$ npm install expresso</code></pre><h2 id="Examples">Examples</h2><p>To define tests we simply export several functions:</p><pre><code>exports['test String#length'] = function(){
+ assert.equal(6, 'foobar'.length);
+};</code></pre><p>Alternatively for large numbers of tests you may want to
+export your own object containing the tests, however this
+is essentially the as above:</p><pre><code>module.exports = {
+ 'test String#length': function(beforeExit, assert) {
+ assert.equal(6, 'foobar'.length);
+ }
+};</code></pre><p>If you prefer not to use quoted keys:</p><pre><code>exports.testsStringLength = function(beforeExit, assert) {
+ assert.equal(6, 'foobar'.length);
+};</code></pre><p>The argument passed to each callback is <code>beforeExit</code> and <code>assert</code>.
+The context ("<code>this</code>") of each test function is a <em>Test</em> object. You can pass a function to <code>beforeExit</code> to make sure the assertions are run before the tests exit. This is can be used to verify that tests have indeed been run. <code>beforeExit</code> is a shortcut for listening to the <code>exit</code> event on <code>this</code>. The second parameter <code>assert</code> is the <code>assert</code> object localized to that test. It makes sure that assertions in asynchronous callbacks are associated with the correct test.</p><pre><code>exports.testAsync = function(beforeExit, assert) {
+ var n = 0;
+ setTimeout(function() {
+ ++n;
+ assert.ok(true);
+ }, 200);
+ setTimeout(function() {
+ ++n;
+ assert.ok(true);
+ }, 200);
+
+ // When the tests are finished, the exit event is emitted.
+ this.on('exit', function() {
+ assert.equal(2, n, 'Ensure both timeouts are called');
+ });
+
+ // Alternatively, you can use the beforeExit shortcut.
+ beforeExit(function() {
+ assert.equal(2, n, 'Ensure both timeouts are called');
+ });
+};</code></pre><h2 id="Assert-Utilities">Assert Utilities</h2><h3 id="assert-isNull-val-msg">assert.isNull(val[, msg])</h3><p>Asserts that the given <code>val</code> is <code>null</code>.</p><pre><code>assert.isNull(null);</code></pre><h3 id="assert-isNotNull-val-msg">assert.isNotNull(val[, msg])</h3><p>Asserts that the given <code>val</code> is not <code>null</code>.</p><pre><code>assert.isNotNull(undefined);
+assert.isNotNull(false);</code></pre><h3 id="assert-isUndefined-val-msg">assert.isUndefined(val[, msg])</h3><p>Asserts that the given <code>val</code> is <code>undefined</code>.</p><pre><code>assert.isUndefined(undefined);</code></pre><h3 id="assert-isDefined-val-msg">assert.isDefined(val[, msg])</h3><p>Asserts that the given <code>val</code> is not <code>undefined</code>.</p><pre><code>assert.isDefined(null);
+assert.isDefined(false);</code></pre><h3 id="assert-match-str-regexp-msg">assert.match(str, regexp[, msg])</h3><p>Asserts that the given <code>str</code> matches <code>regexp</code>.</p><pre><code>assert.match('foobar', /^foo(bar)?/);
+assert.match('foo', /^foo(bar)?/);</code></pre><h3 id="assert-length-val-n-msg">assert.length(val, n[, msg])</h3><p>Assert that the given <code>val</code> has a length of <code>n</code>.</p><pre><code>assert.length([1,2,3], 3);
+assert.length('foo', 3);</code></pre><h3 id="assert-type-obj-type-msg">assert.type(obj, type[, msg])</h3><p>Assert that the given <code>obj</code> is typeof <code>type</code>.</p><pre><code>assert.type(3, 'number');</code></pre><h3 id="assert-eql-a-b-msg">assert.eql(a, b[, msg])</h3><p>Assert that object <code>b</code> is equal to object <code>a</code>. This is an
+alias for the core <code>assert.deepEqual()</code> method which does complex
+comparisons, opposed to <code>assert.equal()</code> which uses <code>==</code>.</p><pre><code>assert.eql('foo', 'foo');
+assert.eql([1,2], [1,2]);
+assert.eql({ foo: 'bar' }, { foo: 'bar' });</code></pre><h3 id="assert-includes-obj-val-msg">assert.includes(obj, val[, msg])</h3><p>Assert that <code>obj</code> is within <code>val</code>. This method supports <code>Array</code>s
+and <code>Strings</code>s.</p><pre><code>assert.includes([1,2,3], 3);
+assert.includes('foobar', 'foo');
+assert.includes('foobar', 'bar');</code></pre><h3 id="assert-response-server-req-res-fn-msg-fn">assert.response(server, req, res|fn[, msg|fn])</h3><p>Performs assertions on the given <code>server</code>, which should <em>not</em> call
+<code>listen()</code>, as this is handled internally by expresso and the server
+is killed after all responses have completed. This method works with
+any <code>http.Server</code> instance, so <em>Connect</em> and <em>Express</em> servers will work
+as well.</p><p>The <strong><code>req</code></strong> object may contain:</p><ul><li><code>url</code>: request url</li><li><code>timeout</code>: timeout in milliseconds</li><li><code>method</code>: HTTP method</li><li><code>data</code>: request body</li><li><code>headers</code>: headers object</li></ul><p>The <strong><code>res</code></strong> object may be a callback function which
+receives the response for assertions, or an object
+which is then used to perform several assertions
+on the response with the following properties:</p><ul><li><code>body</code>: assert response body (regexp or string)</li><li><code>status</code>: assert response status code</li><li><code>header</code>: assert that all given headers match (unspecified are ignored, use a regexp or string)</li></ul><p>When providing <code>res</code> you may then also pass a callback function
+as the fourth argument for additional assertions.</p><p>Below are some examples:</p><pre><code>assert.response(server, {
+ url: '/', timeout: 500
+}, {
+ body: 'foobar'
+});
+
+assert.response(server, {
+ url: '/',
+ method: 'GET'
+}, {
+ body: '{"name":"tj"}',
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json; charset=utf8',
+ 'X-Foo': 'bar'
+ }
+});
+
+assert.response(server, {
+ url: '/foo',
+ method: 'POST',
+ data: 'bar baz'
+}, {
+ body: '/foo bar baz',
+ status: 200
+}, 'Test POST');
+
+assert.response(server, {
+ url: '/foo',
+ method: 'POST',
+ data: 'bar baz'
+}, {
+ body: '/foo bar baz',
+ status: 200
+}, function(res){
+ // All done, do some more tests if needed
+});
+
+assert.response(server, {
+ url: '/'
+}, function(res){
+ assert.ok(res.body.indexOf('tj') &gt;= 0, 'Test assert.response() callback');
+});</code></pre><p>This function will fail when it receives no response or when the timeout (default is 30 seconds) expires.</p><h2 id="expresso-1">expresso(1)</h2><p>To run a single test suite (file) run:</p><pre><code>$ expresso test/a.test.js</code></pre><p>To run several suites we may simply append another:</p><pre><code>$ expresso test/a.test.js test/b.test.js</code></pre><p>We can also pass a whitelist of tests to run within all suites:</p><pre><code>$ expresso --only "foo()" --only "bar()"</code></pre><p>Or several with one call:</p><pre><code>$ expresso --only "foo(), bar()"</code></pre><p>Globbing is of course possible as well:</p><pre><code>$ expresso test/*</code></pre><p>When expresso is called without any files, <em>test/*</em> is the default,
+so the following is equivalent to the command above:</p><pre><code>$ expresso</code></pre><p>If you wish to unshift a path to <code>require.paths</code> before
+running tests, you may use the <code>-I</code> or <code>--include</code> flag.</p><pre><code>$ expresso --include lib test/*</code></pre><p>The previous example is typically what I would recommend, since expresso
+supports test coverage via <a href="http://github.com/visionmedia/node-jscoverage">node-jscoverage</a> (bundled with expresso),
+so you will need to expose an instrumented version of you library.</p><p>To instrument your library, simply run <a href="http://github.com/visionmedia/node-jscoverage">node-jscoverage</a>,
+passing the <em>src</em> and <em>dest</em> directories:</p><pre><code>$ node-jscoverage lib lib-cov</code></pre><p>Now we can run our tests again, using the <em>lib-cov</em> directory that has been
+instrumented with coverage statements:</p><pre><code>$ expresso -I lib-cov test/*</code></pre><p>The output will look similar to below, depending on your test coverage of course :)</p><p><img alt="node coverage" src="http://dl.dropbox.com/u/6396913/cov.png" /></p><p>To make this process easier expresso has the <code>-c</code> or <code>--cov</code> which essentially
+does the same as the two commands above. The following two commands will
+run the same tests, however one will auto-instrument, and unshift <code>lib-cov</code>,
+and the other will run tests normally:</p><pre><code>$ expresso -I lib test/*
+$ expresso -I lib --cov test/*</code></pre><p>Currently coverage is bound to the <code>lib</code> directory, however in the
+future <code>--cov</code> will most likely accept a path.</p><p>If you would like code coverage reports suitable for automated parsing, pass the <code>--json [output file]</code> option:</p><pre><code>$ expresso -I lib test/*
+$ expresso -I lib --cov --json coverage.json test/*</code></pre><p>You should then see the json coverage details in the file you specified:</p><pre><code>{
+ "LOC": 20,
+ "SLOC": 7,
+ "coverage": "71.43",
+ "files": {
+ "bar.js": {
+ "LOC": 4,
+ "SLOC": 2,
+ "coverage": "100.00",
+ "totalMisses": 0
+ },
+ "foo.js": {
+ "LOC": 16,
+ "SLOC": 5,
+ "coverage": "60.00",
+ "totalMisses": 2
+ }
+ },
+ "totalMisses": 2
+}</code></pre><h2 id="Async-Exports">Async Exports</h2><p>Sometimes it is useful to postpone running of tests until a callback or event has fired, currently the <code>exports.foo = function() {};</code> syntax is supported for this:</p><pre><code>setTimeout(function() {
+ exports['test async exports'] = function(){
+ assert.ok('wahoo');
+ };
+}, 100);</code></pre><p>Note that you only have one "shot" at exporting. You have to export all of your test functions in the same loop as the first one. That means you can't progressively add more test functions to the <code>exports</code> object.</p></html>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tools/node_modules/expresso/docs/index.md b/tools/node_modules/expresso/docs/index.md
new file mode 100644
index 0000000..d3845ff
--- /dev/null
+++ b/tools/node_modules/expresso/docs/index.md
@@ -0,0 +1,328 @@
+
+[Expresso](http://github.com/visionmedia/expresso) is a JavaScript [TDD](http://en.wikipedia.org/wiki/Test-driven_development) framework written for [nodejs](http://nodejs.org). Expresso is extremely fast, and is packed with features such as additional assertion methods, code coverage reporting, CI support, and more.
+
+## Features
+
+- light-weight
+- intuitive async support
+- intuitive test runner executable
+- test coverage support and reporting via [node-jscoverage](http://github.com/visionmedia/node-jscoverage)
+- uses and extends the core `assert` module
+- `assert.eql()` alias of `assert.deepEqual()`
+- `assert.response()` http response utility
+- `assert.includes()`
+- `assert.isNull()`
+- `assert.isUndefined()`
+- `assert.isNotNull()`
+- `assert.isDefined()`
+- `assert.match()`
+- `assert.length()`
+
+## Installation
+
+To install both expresso _and_ node-jscoverage run
+the command below, which will first compile node-jscoverage:
+
+ $ make install
+
+To install expresso alone without coverage reporting run:
+
+ $ make install-expresso
+
+Install via npm:
+
+ $ npm install expresso
+
+## Examples
+
+To define tests we simply export several functions:
+
+ exports['test String#length'] = function(){
+ assert.equal(6, 'foobar'.length);
+ };
+
+Alternatively for large numbers of tests you may want to
+export your own object containing the tests, however this
+is essentially the as above:
+
+ module.exports = {
+ 'test String#length': function(beforeExit, assert) {
+ assert.equal(6, 'foobar'.length);
+ }
+ };
+
+If you prefer not to use quoted keys:
+
+ exports.testsStringLength = function(beforeExit, assert) {
+ assert.equal(6, 'foobar'.length);
+ };
+
+The argument passed to each callback is `beforeExit` and `assert`.
+The context ("`this`") of each test function is a _Test_ object. You can pass a function to `beforeExit` to make sure the assertions are run before the tests exit. This is can be used to verify that tests have indeed been run. `beforeExit` is a shortcut for listening to the `exit` event on `this`. The second parameter `assert` is the `assert` object localized to that test. It makes sure that assertions in asynchronous callbacks are associated with the correct test.
+
+ exports.testAsync = function(beforeExit, assert) {
+ var n = 0;
+ setTimeout(function() {
+ ++n;
+ assert.ok(true);
+ }, 200);
+ setTimeout(function() {
+ ++n;
+ assert.ok(true);
+ }, 200);
+
+ // When the tests are finished, the exit event is emitted.
+ this.on('exit', function() {
+ assert.equal(2, n, 'Ensure both timeouts are called');
+ });
+
+ // Alternatively, you can use the beforeExit shortcut.
+ beforeExit(function() {
+ assert.equal(2, n, 'Ensure both timeouts are called');
+ });
+ };
+
+## Assert Utilities
+
+### assert.isNull(val[, msg])
+
+Asserts that the given `val` is `null`.
+
+ assert.isNull(null);
+
+### assert.isNotNull(val[, msg])
+
+Asserts that the given `val` is not `null`.
+
+ assert.isNotNull(undefined);
+ assert.isNotNull(false);
+
+### assert.isUndefined(val[, msg])
+
+Asserts that the given `val` is `undefined`.
+
+ assert.isUndefined(undefined);
+
+### assert.isDefined(val[, msg])
+
+Asserts that the given `val` is not `undefined`.
+
+ assert.isDefined(null);
+ assert.isDefined(false);
+
+### assert.match(str, regexp[, msg])
+
+Asserts that the given `str` matches `regexp`.
+
+ assert.match('foobar', /^foo(bar)?/);
+ assert.match('foo', /^foo(bar)?/);
+
+### assert.length(val, n[, msg])
+
+Assert that the given `val` has a length of `n`.
+
+ assert.length([1,2,3], 3);
+ assert.length('foo', 3);
+
+### assert.type(obj, type[, msg])
+
+Assert that the given `obj` is typeof `type`.
+
+ assert.type(3, 'number');
+
+### assert.eql(a, b[, msg])
+
+Assert that object `b` is equal to object `a`. This is an
+alias for the core `assert.deepEqual()` method which does complex
+comparisons, opposed to `assert.equal()` which uses `==`.
+
+ assert.eql('foo', 'foo');
+ assert.eql([1,2], [1,2]);
+ assert.eql({ foo: 'bar' }, { foo: 'bar' });
+
+### assert.includes(obj, val[, msg])
+
+Assert that `obj` is within `val`. This method supports `Array`s
+and `Strings`s.
+
+ assert.includes([1,2,3], 3);
+ assert.includes('foobar', 'foo');
+ assert.includes('foobar', 'bar');
+
+### assert.response(server, req, res|fn[, msg|fn])
+
+Performs assertions on the given `server`, which should _not_ call
+`listen()`, as this is handled internally by expresso and the server
+is killed after all responses have completed. This method works with
+any `http.Server` instance, so _Connect_ and _Express_ servers will work
+as well.
+
+The **`req`** object may contain:
+
+- `url`: request url
+- `timeout`: timeout in milliseconds
+- `method`: HTTP method
+- `data`: request body
+- `headers`: headers object
+
+The **`res`** object may be a callback function which
+receives the response for assertions, or an object
+which is then used to perform several assertions
+on the response with the following properties:
+
+- `body`: assert response body (regexp or string)
+- `status`: assert response status code
+- `header`: assert that all given headers match (unspecified are ignored, use a regexp or string)
+
+When providing `res` you may then also pass a callback function
+as the fourth argument for additional assertions.
+
+Below are some examples:
+
+ assert.response(server, {
+ url: '/', timeout: 500
+ }, {
+ body: 'foobar'
+ });
+
+ assert.response(server, {
+ url: '/',
+ method: 'GET'
+ }, {
+ body: '{"name":"tj"}',
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json; charset=utf8',
+ 'X-Foo': 'bar'
+ }
+ });
+
+ assert.response(server, {
+ url: '/foo',
+ method: 'POST',
+ data: 'bar baz'
+ }, {
+ body: '/foo bar baz',
+ status: 200
+ }, 'Test POST');
+
+ assert.response(server, {
+ url: '/foo',
+ method: 'POST',
+ data: 'bar baz'
+ }, {
+ body: '/foo bar baz',
+ status: 200
+ }, function(res){
+ // All done, do some more tests if needed
+ });
+
+ assert.response(server, {
+ url: '/'
+ }, function(res){
+ assert.ok(res.body.indexOf('tj') >= 0, 'Test assert.response() callback');
+ });
+
+This function will fail when it receives no response or when the timeout (default is 30 seconds) expires.
+
+
+## expresso(1)
+
+To run a single test suite (file) run:
+
+ $ expresso test/a.test.js
+
+To run several suites we may simply append another:
+
+ $ expresso test/a.test.js test/b.test.js
+
+We can also pass a whitelist of tests to run within all suites:
+
+ $ expresso --only "foo()" --only "bar()"
+
+Or several with one call:
+
+ $ expresso --only "foo(), bar()"
+
+Globbing is of course possible as well:
+
+ $ expresso test/*
+
+When expresso is called without any files, _test/*_ is the default,
+so the following is equivalent to the command above:
+
+ $ expresso
+
+If you wish to unshift a path to `require.paths` before
+running tests, you may use the `-I` or `--include` flag.
+
+ $ expresso --include lib test/*
+
+The previous example is typically what I would recommend, since expresso
+supports test coverage via [node-jscoverage](http://github.com/visionmedia/node-jscoverage) (bundled with expresso),
+so you will need to expose an instrumented version of you library.
+
+To instrument your library, simply run [node-jscoverage](http://github.com/visionmedia/node-jscoverage),
+passing the _src_ and _dest_ directories:
+
+ $ node-jscoverage lib lib-cov
+
+Now we can run our tests again, using the _lib-cov_ directory that has been
+instrumented with coverage statements:
+
+ $ expresso -I lib-cov test/*
+
+The output will look similar to below, depending on your test coverage of course :)
+
+![node coverage](http://dl.dropbox.com/u/6396913/cov.png)
+
+To make this process easier expresso has the `-c` or `--cov` which essentially
+does the same as the two commands above. The following two commands will
+run the same tests, however one will auto-instrument, and unshift `lib-cov`,
+and the other will run tests normally:
+
+ $ expresso -I lib test/*
+ $ expresso -I lib --cov test/*
+
+Currently coverage is bound to the `lib` directory, however in the
+future `--cov` will most likely accept a path.
+
+If you would like code coverage reports suitable for automated parsing, pass the `--json [output file]` option:
+
+ $ expresso -I lib test/*
+ $ expresso -I lib --cov --json coverage.json test/*
+
+You should then see the json coverage details in the file you specified:
+
+ {
+ "LOC": 20,
+ "SLOC": 7,
+ "coverage": "71.43",
+ "files": {
+ "bar.js": {
+ "LOC": 4,
+ "SLOC": 2,
+ "coverage": "100.00",
+ "totalMisses": 0
+ },
+ "foo.js": {
+ "LOC": 16,
+ "SLOC": 5,
+ "coverage": "60.00",
+ "totalMisses": 2
+ }
+ },
+ "totalMisses": 2
+ }
+
+## Async Exports
+
+Sometimes it is useful to postpone running of tests until a callback or event has fired, currently the `exports.foo = function() {};` syntax is supported for this:
+
+ setTimeout(function() {
+ exports['test async exports'] = function(){
+ assert.ok('wahoo');
+ };
+ }, 100);
+
+Note that you only have one "shot" at exporting. You have to export all of your test functions in the same loop as the first one. That means you can't progressively add more test functions to the `exports` object.
diff --git a/tools/node_modules/expresso/docs/layout/foot.html b/tools/node_modules/expresso/docs/layout/foot.html
new file mode 100644
index 0000000..44d85e9
--- /dev/null
+++ b/tools/node_modules/expresso/docs/layout/foot.html
@@ -0,0 +1,3 @@
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tools/node_modules/expresso/docs/layout/head.html b/tools/node_modules/expresso/docs/layout/head.html
new file mode 100644
index 0000000..6dc97cd
--- /dev/null
+++ b/tools/node_modules/expresso/docs/layout/head.html
@@ -0,0 +1,42 @@
+<html>
+ <head>
+ <title>Expresso - TDD Framework For Node</title>
+ <style>
+ body {
+ font: 13px/1.4 "Helvetica", "Lucida Grande", Arial, sans-serif;
+ text-align: center;
+ }
+ #ribbon {
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 10;
+ }
+ #wrapper {
+ margin: 0 auto;
+ padding: 50px 80px;
+ width: 700px;
+ text-align: left;
+ }
+ h1, h2, h3 {
+ margin: 25px 0 15px 0;
+ }
+ h1 {
+ font-size: 35px;
+ }
+ pre {
+ margin: 0 5px;
+ padding: 15px;
+ border: 1px solid #eee;
+ }
+ a {
+ color: #00aaff;
+ }
+ </style>
+ </head>
+ <body>
+ <a href="http://github.com/visionmedia/expresso">
+ <img alt="Fork me on GitHub" id="ribbon" src="http://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png" />
+ </a>
+ <div id="wrapper">
+ <h1>Expresso 0.9.0</h1>
diff --git a/tools/node_modules/expresso/package.json b/tools/node_modules/expresso/package.json
new file mode 100644
index 0000000..e5a5f50
--- /dev/null
+++ b/tools/node_modules/expresso/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "expresso",
+ "version": "0.9.2",
+ "description": "TDD framework, light-weight, fast, CI-friendly",
+ "author": {
+ "name": "TJ Holowaychuk",
+ "email": "tj@vision-media.ca"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/visionmedia/expresso"
+ },
+ "bin": {
+ "expresso": "./bin/expresso",
+ "node-jscoverage": "./deps/jscoverage/node-jscoverage"
+ },
+ "scripts": {
+ "preinstall": "make deps/jscoverage/node-jscoverage"
+ },
+ "readme": "\n# Expresso\n\n TDD framework for [nodejs](http://nodejs.org).\n \n## Features\n\n - light-weight\n - intuitive async support\n - intuitive test runner executable\n - test coverage support and reporting\n - uses the _assert_ module\n - `assert.eql()` alias of `assert.deepEqual()`\n - `assert.response()` http response utility\n - `assert.includes()`\n - `assert.type()`\n - `assert.isNull()`\n - `assert.isUndefined()`\n - `assert.isNotNull()`\n - `assert.isDefined()`\n - `assert.match()`\n - `assert.length()`\n\n## Installation\n\nTo install both expresso _and_ node-jscoverage run:\n\n $ make install\n\nTo install expresso alone (no build required) run:\n\n $ make install-expresso\n\nInstall via npm:\n\n $ npm install expresso\n\n## Usage\n\nCreate a directory named `test` in your project and place JavaScript files in it. Each JavaScript file can export multiple tests of this format:\n\n```js\nexports['test String#length'] = function(beforeExit, assert) {\n assert.equal(6, 'foobar'.length);\n};\n```\n\nTo run tests, type `expresso`.\n\nFor more information, [see the manual](http://visionmedia.github.com/expresso/).\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
+ "_id": "expresso@0.9.2",
+ "dist": {
+ "shasum": "47b9206d2db9a4394fba94688902176f92932ce0"
+ },
+ "_from": "expresso@0.9.2"
+}
diff --git a/tools/node_modules/expresso/test/.invalid.test.js b/tools/node_modules/expresso/test/.invalid.test.js
new file mode 100644
index 0000000..6180463
--- /dev/null
+++ b/tools/node_modules/expresso/test/.invalid.test.js
@@ -0,0 +1,9 @@
+/**
+ * This file should never run because it begins with a .
+ */
+
+var assert = require('assert');
+
+exports['failure'] = function() {
+ assert.ok(false, "Don't run files beginning with a dot");
+};
diff --git a/tools/node_modules/expresso/test/assert.test.js b/tools/node_modules/expresso/test/assert.test.js
new file mode 100644
index 0000000..8dbc610
--- /dev/null
+++ b/tools/node_modules/expresso/test/assert.test.js
@@ -0,0 +1,83 @@
+
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert');
+
+module.exports = {
+ 'assert.eql()': function(){
+ assert.equal(assert.deepEqual, assert.eql);
+ },
+
+ 'assert.type()': function(){
+ assert.type('foobar', 'string');
+ assert.type(2, 'number');
+ assert.throws(function(){
+ assert.type([1,2,3], 'string');
+ });
+ },
+
+ 'assert.includes()': function(){
+ assert.includes('some random string', 'dom');
+ assert.throws(function(){
+ assert.include('some random string', 'foobar');
+ });
+
+ assert.includes(['foo', 'bar'], 'bar');
+ assert.includes(['foo', 'bar'], 'foo');
+ assert.includes([1,2,3], 3);
+ assert.includes([1,2,3], 2);
+ assert.includes([1,2,3], 1);
+ assert.throws(function(){
+ assert.includes(['foo', 'bar'], 'baz');
+ });
+
+ assert.throws(function(){
+ assert.includes({ wrong: 'type' }, 'foo');
+ });
+ },
+
+ 'assert.isNull()': function(){
+ assert.isNull(null);
+ assert.throws(function(){
+ assert.isNull(undefined);
+ });
+ assert.throws(function(){
+ assert.isNull(false);
+ });
+ },
+
+ 'assert.isUndefined()': function(){
+ assert.isUndefined(undefined);
+ assert.throws(function(){
+ assert.isUndefined(null);
+ });
+ assert.throws(function(){
+ assert.isUndefined(false);
+ });
+ },
+
+ 'assert.isNotNull()': function(){
+ assert.isNotNull(false);
+ assert.isNotNull(undefined);
+ assert.throws(function(){
+ assert.isNotNull(null);
+ });
+ },
+
+ 'assert.isDefined()': function(){
+ assert.isDefined(false);
+ assert.isDefined(null);
+ assert.throws(function(){
+ assert.isDefined(undefined);
+ });
+ },
+
+ 'assert.match()': function(){
+ assert.match('foobar', /foo(bar)?/);
+ assert.throws(function(){
+ assert.match('something', /rawr/);
+ });
+ }
+}; \ No newline at end of file
diff --git a/tools/node_modules/expresso/test/async.test.js b/tools/node_modules/expresso/test/async.test.js
new file mode 100644
index 0000000..d1d2036
--- /dev/null
+++ b/tools/node_modules/expresso/test/async.test.js
@@ -0,0 +1,12 @@
+
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert');
+
+setTimeout(function(){
+ exports['test async exports'] = function(){
+ assert.ok('wahoo');
+ };
+}, 100); \ No newline at end of file
diff --git a/tools/node_modules/expresso/test/bar.test.js b/tools/node_modules/expresso/test/bar.test.js
new file mode 100644
index 0000000..cfc2e11
--- /dev/null
+++ b/tools/node_modules/expresso/test/bar.test.js
@@ -0,0 +1,13 @@
+
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert')
+ , bar = require('bar');
+
+module.exports = {
+ 'bar()': function(){
+ assert.equal('bar', bar.bar());
+ }
+}; \ No newline at end of file
diff --git a/tools/node_modules/expresso/test/earlyexit.test.js b/tools/node_modules/expresso/test/earlyexit.test.js
new file mode 100644
index 0000000..9c36c10
--- /dev/null
+++ b/tools/node_modules/expresso/test/earlyexit.test.js
@@ -0,0 +1,22 @@
+var assert = require('assert');
+var spawn = require('child_process').spawn;
+
+exports['early exit'] = function(beforeExit) {
+ var completed = false;
+
+ var proc = spawn('bin/expresso', ['test/earlyexit/forever.test.js', '--port', '23444']);
+ proc.on('exit', function(code) {
+ completed = true;
+ assert.equal(1, code, "assert.response didn't report an error while still running");
+ });
+
+ setTimeout(function() {
+ proc.kill('SIGINT');
+ }, 1000);
+
+ // Also kill the child if it still exists.
+ beforeExit(function() {
+ proc.kill();
+ assert.ok(completed);
+ });
+}; \ No newline at end of file
diff --git a/tools/node_modules/expresso/test/earlyexit/forever.test.js b/tools/node_modules/expresso/test/earlyexit/forever.test.js
new file mode 100644
index 0000000..c7c6df5
--- /dev/null
+++ b/tools/node_modules/expresso/test/earlyexit/forever.test.js
@@ -0,0 +1,8 @@
+var http = require('http');
+var assert = require('assert');
+var server = http.createServer(function(req, res) { /* Never send a response */ });
+
+exports['assert.response'] = function() {
+ // This will keep running for a while because the server never returns.
+ assert.response(server, { url: '/' }, { status: 200 });
+};
diff --git a/tools/node_modules/expresso/test/foo.test.js b/tools/node_modules/expresso/test/foo.test.js
new file mode 100644
index 0000000..ee5cff3
--- /dev/null
+++ b/tools/node_modules/expresso/test/foo.test.js
@@ -0,0 +1,14 @@
+
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert')
+ , foo = require('foo');
+
+module.exports = {
+ 'foo()': function(){
+ assert.equal('foo', foo.foo());
+ assert.equal('foo', foo.foo());
+ }
+}; \ No newline at end of file
diff --git a/tools/node_modules/expresso/test/http.test.js b/tools/node_modules/expresso/test/http.test.js
new file mode 100644
index 0000000..8539f9d
--- /dev/null
+++ b/tools/node_modules/expresso/test/http.test.js
@@ -0,0 +1,168 @@
+
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert')
+ , http = require('http');
+
+var server = http.createServer(function(req, res){
+ if (req.method === 'GET') {
+ if (req.url === '/delay') {
+ setTimeout(function(){
+ res.writeHead(200, {});
+ res.end('delayed');
+ }, 200);
+ } else {
+ var body = JSON.stringify({ name: 'tj' });
+ res.writeHead(200, {
+ 'Content-Type': 'application/json; charset=utf8',
+ 'Content-Length': body.length
+ });
+ res.end(body);
+ }
+ } else {
+ var body = '';
+ req.setEncoding('utf8');
+ req.on('data', function(chunk){ body += chunk });
+ req.on('end', function(){
+ res.writeHead(200, {});
+ res.end(req.url + ' ' + body);
+ });
+ }
+});
+
+var delayedServer = http.createServer(function(req, res){
+ res.writeHead(200);
+ res.end('it worked');
+});
+
+var oldListen = delayedServer.listen;
+delayedServer.listen = function(){
+ var args = arguments;
+ setTimeout(function(){
+ oldListen.apply(delayedServer, args);
+ }, 100);
+};
+
+var runningServer = http.createServer(function(req, res){
+ res.writeHead(200);
+ res.end('it worked');
+});
+
+runningServer.listen(5554);
+
+module.exports = {
+ 'test assert.response(req, res, fn)': function(beforeExit){
+ var calls = 0;
+
+ assert.response(server, {
+ url: '/',
+ method: 'GET'
+ },{
+ body: '{"name":"tj"}',
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json; charset=utf8'
+ }
+ }, function(res){
+ ++calls;
+ assert.ok(res);
+ });
+
+ beforeExit(function(){
+ assert.equal(1, calls);
+ })
+ },
+
+ 'test assert.response(req, fn)': function(beforeExit){
+ var calls = 0;
+
+ assert.response(server, {
+ url: '/foo'
+ }, function(res){
+ ++calls;
+ assert.ok(res.body.indexOf('tj') >= 0, 'Test assert.response() callback');
+ });
+
+ beforeExit(function(){
+ assert.equal(1, calls);
+ });
+ },
+
+ 'test assert.response() delay': function(beforeExit){
+ var calls = 0;
+
+ assert.response(server,
+ { url: '/delay', timeout: 1500 },
+ { body: 'delayed' },
+ function(){
+ ++calls;
+ });
+
+ beforeExit(function(){
+ assert.equal(1, calls);
+ });
+ },
+
+ 'test assert.response() regexp': function(beforeExit){
+ var calls = 0;
+
+ assert.response(server,
+ { url: '/foo', method: 'POST', data: 'foobar' },
+ { body: /^\/foo foo(bar)?/ },
+ function(){
+ ++calls;
+ });
+
+ beforeExit(function(){
+ assert.equal(1, calls);
+ });
+ },
+
+ 'test assert.response() regexp headers': function(beforeExit){
+ var calls = 0;
+
+ assert.response(server,
+ { url: '/' },
+ { body: '{"name":"tj"}', headers: { 'Content-Type': /^application\/json/ } },
+ function(){
+ ++calls;
+ });
+
+ beforeExit(function(){
+ assert.equal(1, calls);
+ });
+ },
+
+ // [!] if this test doesn't pass, an uncaught ECONNREFUSED will display
+ 'test assert.response() with deferred listen()': function(beforeExit){
+ var calls = 0;
+
+ assert.response(delayedServer,
+ { url: '/' },
+ { body: 'it worked' },
+ function(){
+ ++calls;
+ });
+
+ beforeExit(function(){
+ assert.equal(1, calls);
+ });
+ },
+
+ 'test assert.response() with already running server': function(beforeExit){
+ var calls = 0;
+
+ assert.response(runningServer,
+ { url: '/' },
+ { body: 'it worked' },
+ function(){
+ ++calls;
+ });
+
+ beforeExit(function(){
+ assert.equal(1, calls);
+ });
+ }
+};
diff --git a/tools/node_modules/expresso/test/local-assert.test.js b/tools/node_modules/expresso/test/local-assert.test.js
new file mode 100644
index 0000000..50e2765
--- /dev/null
+++ b/tools/node_modules/expresso/test/local-assert.test.js
@@ -0,0 +1,20 @@
+var assert = require('assert');
+
+// Using a localized version of assert.
+exports['first'] = function(beforeExit, assert) {
+ process.nextTick(function() {
+ assert.equal(assert._test.suite, 'local-assert.test.js');
+ assert.equal(assert._test.title, 'first');
+ });
+};
+
+// Using the broken global version of assert.
+exports['second'] = function(beforeExit) {
+ process.nextTick(function() {
+ assert.notEqual(assert._test.suite, 'local-assert.test.js');
+ assert.notEqual(assert._test.title, 'third');
+ });
+};
+
+// Overwrite the testTitle in assert.
+exports['third'] = function() {};
diff --git a/tools/node_modules/expresso/test/match.test.js b/tools/node_modules/expresso/test/match.test.js
new file mode 100644
index 0000000..c81cb30
--- /dev/null
+++ b/tools/node_modules/expresso/test/match.test.js
@@ -0,0 +1,25 @@
+var assert = require('assert');
+var spawn = require('child_process').spawn;
+
+module.exports = {
+ 'will run only matched tests': function() {
+ var proc = spawn('bin/expresso', ['-m', 'p..s', 'test/match/test.js']);
+ proc.on('exit', function(code) {
+ completed = true;
+ assert.equal(0, code, 'failing test was not filtered out');
+ });
+ setTimeout(function() {
+ proc.kill('SIGINT');
+ }, 1000);
+ },
+ 'will run tests matched in a subsequent expression': function() {
+ var proc = spawn('bin/expresso', ['-m', 'nothing', '--match', 'p..s', 'test/match/test.js']);
+ proc.on('exit', function(code) {
+ completed = true;
+ assert.equal(0, code, 'failing test was not filtered out');
+ });
+ setTimeout(function() {
+ proc.kill('SIGINT');
+ }, 1000);
+ },
+}; \ No newline at end of file
diff --git a/tools/node_modules/expresso/test/match/test.js b/tools/node_modules/expresso/test/match/test.js
new file mode 100644
index 0000000..47a64d0
--- /dev/null
+++ b/tools/node_modules/expresso/test/match/test.js
@@ -0,0 +1,10 @@
+var assert = require('assert');
+
+module.exports = {
+ 'this test will pass': function() {
+ assert.ok(true);
+ },
+ 'this test will fail': function() {
+ assert.ok(false);
+ },
+} \ No newline at end of file
diff --git a/tools/node_modules/expresso/test/serial/async.test.js b/tools/node_modules/expresso/test/serial/async.test.js
new file mode 100644
index 0000000..c596d5c
--- /dev/null
+++ b/tools/node_modules/expresso/test/serial/async.test.js
@@ -0,0 +1,39 @@
+
+var assert = require('assert')
+ , setup = 0
+ , order = [];
+
+module.exports = {
+ setup: function(done){
+ ++setup;
+ done();
+ },
+
+ a: function(done){
+ assert.equal(1, setup);
+ order.push('a');
+ setTimeout(function(){
+ done();
+ }, 500);
+ },
+
+ b: function(done){
+ assert.equal(2, setup);
+ order.push('b');
+ setTimeout(function(){
+ done();
+ }, 200);
+ },
+
+ c: function(done){
+ assert.equal(3, setup);
+ order.push('c');
+ setTimeout(function(){
+ done();
+ }, 1000);
+ },
+
+ d: function(){
+ assert.eql(order, ['a', 'b', 'c']);
+ }
+}; \ No newline at end of file
diff --git a/tools/node_modules/expresso/test/serial/http.test.js b/tools/node_modules/expresso/test/serial/http.test.js
new file mode 100644
index 0000000..7783eb5
--- /dev/null
+++ b/tools/node_modules/expresso/test/serial/http.test.js
@@ -0,0 +1,48 @@
+
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert')
+ , http = require('http');
+
+var server = http.createServer(function(req, res){
+ if (req.method === 'GET') {
+ if (req.url === '/delay') {
+ setTimeout(function(){
+ res.writeHead(200, {});
+ res.end('delayed');
+ }, 200);
+ } else {
+ var body = JSON.stringify({ name: 'tj' });
+ res.writeHead(200, {
+ 'Content-Type': 'application/json; charset=utf8',
+ 'Content-Length': body.length
+ });
+ res.end(body);
+ }
+ } else {
+ var body = '';
+ req.setEncoding('utf8');
+ req.addListener('data', function(chunk){ body += chunk });
+ req.addListener('end', function(){
+ res.writeHead(200, {});
+ res.end(req.url + ' ' + body);
+ });
+ }
+});
+
+module.exports = {
+ 'test assert.response()': function(done){
+ assert.response(server, {
+ url: '/',
+ method: 'GET'
+ },{
+ body: '{"name":"tj"}',
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json; charset=utf8'
+ }
+ }, done);
+ }
+}; \ No newline at end of file
diff --git a/tools/node_modules/expresso/test/serial/teardown.test.js b/tools/node_modules/expresso/test/serial/teardown.test.js
new file mode 100644
index 0000000..bbd62e9
--- /dev/null
+++ b/tools/node_modules/expresso/test/serial/teardown.test.js
@@ -0,0 +1,25 @@
+
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert');
+
+var a = 0;
+
+module.exports = {
+ teardown : function (done) {
+ a--;
+ done();
+ },
+ test1 : function(done) {
+ a++;
+ assert.strictEqual(1, a);
+ done();
+ },
+ test2 : function (done) {
+ a++;
+ assert.strictEqual(1, a);
+ done();
+ }
+};
diff --git a/tools/node_modules/expresso/test/this.test.js b/tools/node_modules/expresso/test/this.test.js
new file mode 100644
index 0000000..17b794b
--- /dev/null
+++ b/tools/node_modules/expresso/test/this.test.js
@@ -0,0 +1,20 @@
+/**
+ * This.
+ */
+
+module.exports = {
+ 'test this': function(beforeExit, assert) {
+ assert.equal(this.suite, 'this.test.js');
+ assert.equal(this.title, 'test this');
+ assert.ok(this.assert);
+
+ var exiting = false;
+ this.on('exit', function() {
+ exiting = true;
+ });
+
+ beforeExit(function() {
+ assert.ok(exiting);
+ });
+ }
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/.npmignore b/tools/node_modules/nodemailer/.npmignore
new file mode 100644
index 0000000..5171c54
--- /dev/null
+++ b/tools/node_modules/nodemailer/.npmignore
@@ -0,0 +1,2 @@
+node_modules
+npm-debug.log \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/.travis.yml b/tools/node_modules/nodemailer/.travis.yml
new file mode 100644
index 0000000..c8f68ef
--- /dev/null
+++ b/tools/node_modules/nodemailer/.travis.yml
@@ -0,0 +1,12 @@
+language: node_js
+node_js:
+ - 0.6
+ - 0.8
+ - 0.9
+
+notifications:
+ email:
+ recipients:
+ - andris@node.ee
+ on_success: change
+ on_failure: change
diff --git a/tools/node_modules/nodemailer/LICENSE b/tools/node_modules/nodemailer/LICENSE
new file mode 100644
index 0000000..dca6ebe
--- /dev/null
+++ b/tools/node_modules/nodemailer/LICENSE
@@ -0,0 +1,16 @@
+Copyright (c) 2011-2012 Andris Reinman
+
+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 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. \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/README.md b/tools/node_modules/nodemailer/README.md
new file mode 100644
index 0000000..2ff1e8e
--- /dev/null
+++ b/tools/node_modules/nodemailer/README.md
@@ -0,0 +1,619 @@
+Nodemailer
+==========
+
+**Nodemailer** is an easy to use module to send e-mails with Node.JS (using
+SMTP or sendmail or Amazon SES) and is unicode friendly - You can use any characters you like ✔
+
+Nodemailer is Windows friendly, you can install it with *npm* on Windows just like any other module, there are no compiled dependencies. Use it from Azure or from your Windows box hassle free.
+
+Version v0.3 of Nodemailer is built from scratch and might break some existing scripts, so beware while upgrading. Nodemailer should be backwards compatible - if your script worked before, then it should work now, even if Nodemailer documentation differs from your code (method names, properties etc.).
+
+Use [DocumentUp](http://documentup.com/andris9/nodemailer/) to read this README
+in a more structured way (with TOC).
+
+[![Build Status](https://secure.travis-ci.org/andris9/Nodemailer.png)](http://travis-ci.org/andris9/Nodemailer)
+
+## Nodemailer supports
+
+ * **Unicode** to use any characters
+ * **HTML content** as well as **plain text** alternative
+ * **Attachments** (including attachment **streaming** for sending larger files)
+ * **Embedded images** in HTML
+ * **SSL/STARTTLS** for secure e-mail delivery
+ * Different transport methods - **SMTP**, **sendmail** and **Amazon SES**
+ * SMTP **Connection pool** and connection reuse for rapid delivery
+ * **Preconfigured** services for using SMTP with Gmail, Hotmail etc.
+ * Use objects as header values for **SendGrid** SMTP API
+ * **XOAUTH** authentication support and token generation (3-legged OAuth) - useful with Gmail
+ * **DKIM** signing
+
+## Support Nodemailer development
+
+[![Donate to author](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DB26KWR2BQX5W)
+
+## Check out my other mail related modules
+
+If you want to parse generated or received e-mail instead of sending it, check
+out [MailParser](https://github.com/andris9/mailparser).
+
+If you only want to generate the raw e-mail stream, check out
+[MailComposer](https://github.com/andris9/mailcomposer).
+
+If you only want to communicate with the SMTP (both as client and the server),
+check out [simplesmtp](https://github.com/andris9/simplesmtp).
+
+## Templates
+
+To use Nodemailer with templates, please see documentation for [node-email-templates](https://github.com/niftylettuce/node-email-templates).
+
+## Example
+
+This is a complete example to send an e-mail with plaintext and HTML body
+
+```javascript
+var nodemailer = require("nodemailer");
+
+// create reusable transport method (opens pool of SMTP connections)
+var smtpTransport = nodemailer.createTransport("SMTP",{
+ service: "Gmail",
+ auth: {
+ user: "gmail.user@gmail.com",
+ pass: "userpass"
+ }
+});
+
+// setup e-mail data with unicode symbols
+var mailOptions = {
+ from: "Sender Name ✔ <sender@example.com>", // sender address
+ to: "receiver1@example.com, receiver2@example.com", // list of receivers
+ subject: "Hello ✔", // Subject line
+ text: "Hello world ✔", // plaintext body
+ html: "<b>Hello world ✔</b>" // html body
+}
+
+// send mail with defined transport object
+smtpTransport.sendMail(mailOptions, function(error, response){
+ if(error){
+ console.log(error);
+ }else{
+ console.log("Message sent: " + response.message);
+ }
+
+ // if you don't want to use this transport object anymore, uncomment following line
+ //smtpTransport.close(); // shut down the connection pool, no more messages
+});
+```
+
+See also the [examples folder](https://github.com/andris9/Nodemailer/tree/master/examples)
+for full featured examples
+
+## Installation
+
+Install through NPM
+
+```
+npm install nodemailer
+```
+
+## Usage
+
+Include the module
+
+```javascript
+var nodemailer = require("nodemailer");
+```
+
+An e-mail can be sent with `sendMail(mailOptions[, callback])` command
+
+```javascript
+transport.sendMail(mailOptions, callback);
+```
+
+Where
+
+ * `transport` is a transport method defined with `nodemailer.createTransport`
+ * **mailOptions** defines the e-mail (set its subject, body text, receivers etc.), see **E-mail Message Fields** for details
+ * **callback** is the callback function that will be run after the e-mail is sent or the sending failed (see **Return callback** for details)
+
+## Setting up a transport method
+
+Before you can send any e-mails you need to set up a transport method. This can
+be done with `nodemailer.createTransport(type, options)` where `type` indicates
+the transport protocol and `options` defines how it is used.
+
+```javascript
+var transport = nodemailer.createTransport("SMTP", {smtp_options});
+```
+
+The same transport object can and should be reused several times.
+
+When the transport method is defined, it can be used to send e-mail with `sendMail`
+
+```javascript
+var transport = nodemailer.createTransport("SMTP", {smtp_options});
+
+transport.sendMail({
+ from: "sender@tr.ee",
+ to: "receiver@tr.ee"
+ ...
+});
+```
+
+### Possible transport methods
+
+Required `type` parameter can be one of the following:
+
+ * **SMTP** for using SMTP
+ * **SES** for using Amazon SES
+ * **Sendmail** for utilizing systems *sendmail* command
+
+### Setting up SMTP
+
+SMTP is different from the other transport mechanisms, as in its case a connection
+pool is created. All the connections try to stay alive as long as possible and
+are reusable to minimize the protocol overhead delay - for example setting up
+TLS for authenticating is relatively lengthy process (in CPU terms, not by human
+terms), you do not want to do it several times.
+
+Possible SMTP options are the following:
+
+ * **service** - an optional well known service identifier ("Gmail", "Hotmail" etc., see **Well known Services** for a list of supported services) to auto-configure host, port and secure connection settings
+ * **host** - hostname of the SMTP server (defaults to "localhost", not needed with `service`)
+ * **port** - port of the SMTP server (defaults to 25, not needed with `service`)
+ * **secureConnection** - use SSL (default is `false`, not needed with `service`). If you're using port 587 then keep `secureConnection` false, since the connection is started in insecure plain text mode and only later upgraded with STARTTLS
+ * **name** - the name of the client server (defaults to machine name)
+ * **auth** - authentication object as `{user:"...", pass:"..."}` or `{XOAuthToken: "base64data"}`
+ * **ignoreTLS** - ignore server support for STARTTLS (defaults to `false`)
+ * **debug** - output client and server messages to console
+ * **maxConnections** - how many connections to keep in the pool (defaults to 5)
+
+Example:
+
+```javascript
+var transport = nodemailer.createTransport("SMTP", {
+ service: "Gmail",
+ auth: {
+ user: "gmail.user@gmail.com",
+ pass: "userpass"
+ }
+});
+```
+
+or the same without `service` parameter
+
+```javascript
+var transport = nodemailer.createTransport("SMTP", {
+ host: "smtp.gmail.com", // hostname
+ secureConnection: true, // use SSL
+ port: 465, // port for secure SMTP
+ auth: {
+ user: "gmail.user@gmail.com",
+ pass: "userpass"
+ }
+});
+```
+
+**NB!** if you want to close the pool (cancel all open connections) you can use `transport.close()`
+
+```javascript
+
+var transport = nodemailer.createTransport("SMTP",{});
+...
+transport.close(); // close the pool
+```
+
+
+#### SMTP XOAUTH and token generation
+
+**nodemailer** supports XOAUTH authentication for SMTP. To use this, include `XOAuthToken` option in `auth` instead of the regular `user` and `pass`.
+
+```javascript
+var transportOptions = {
+ ...,
+ auth: {
+ XOAuthToken: "R0VUIGh0dHBzOi8vbWFpbC5nb29...."
+ }
+}
+```
+
+**nodemailer** includes also built in XOAUTH token generator which can be used
+with `nodemailer.createXOAuthGenerator()`. The function is preconfigured for
+Gmail, so in this case only mandatory options are `user`, `token` and `tokenSecret`.
+
+```javascript
+var XOAuthTokenGenerator = nodemailer.createXOAuthGenerator({
+ user: "test.nodemailer@gmail.com",
+ // requestUrl: "https://oauth.access.point",
+ // consumerKey: "anonymous",
+ // consumerSecret: "anonymous",
+ token: "1/O_HgoO4h2uOUfpus0V--7mygICXrQQ0ZajB3ZH52KqM",
+ tokenSecret: "_mUBkIwNPnfQBUIWrJrpXJ0c"
+ });
+```
+
+One of `user` or `requestUrl` is mandatory. `consumerKey` and `consumerSecret` both
+default to `"anonymous"`.
+
+```javascript
+var transportOptions = {
+ service: "Gmail",
+ auth: {
+ XOAuthToken: nodemailer.createXOAuthGenerator({
+ user: "test.nodemailer@gmail.com",
+ token: "1/O_HgoO4h2uOUfpus0V--7mygICXrQQ0ZajB3ZH52KqM",
+ tokenSecret: "_mUBkIwNPnfQBUIWrJrpXJ0c"
+ })
+ }
+}
+```
+
+### Setting up SES
+
+SES is actually a HTTP based protocol, the compiled e-mail and related info
+(signatures and such) are sent as a HTTP request to SES servers.
+
+Possible SES options are the following:
+
+ * **AWSAccessKeyID** - AWS access key (required)
+ * **AWSSecretKey** - AWS secret (required)
+ * **ServiceUrl** - optional API end point URL (defaults to *"https://email.us-east-1.amazonaws.com"*)
+
+Example:
+
+```javascript
+var transport = nodemailer.createTransport("SES", {
+ AWSAccessKeyID: "AWSACCESSKEY",
+ AWSSecretKey: "AWS/Secret/key"
+});
+```
+
+### Setting up Sendmail
+
+Sendmail transport method streams the compiled message to the *stdin* of *sendmail*
+command.
+
+Options object is optional, possible sendmail options are the following:
+
+ * **path** - path to the `sendmail` command (defaults to *"sendmail"*)
+ * **args** - an array of extra command line options to pass to the `sendmail` command (ie. `["-f sender@example.com"]`)
+
+Example:
+
+```javascript
+var transport = nodemailer.createTransport("sendmail");
+```
+
+or
+
+```javascript
+var transport = nodemailer.createTransport("sendmail", {
+ path: "/usr/local/bin/sendmail",
+ args: ["-f sender@example.com"]
+});
+```
+
+### DKIM Signing
+
+**Nodemailer** supports DKIM signing with very simple setup. Use this with caution
+though since the generated message needs to be buffered entirely before it can be
+signed. Not a big deal with small messages but might consume a lot of RAM when
+using larger attachments.
+
+Set up the DKIM signing with `useDKIM` method for a transport object:
+
+```javascript
+transport.useDKIM(dkimOptions)
+```
+
+Where `dkimOptions` includes necessary options for signing
+
+ * **domainName** - the domainname that is being used for signing
+ * **keySelector** - key selector. If you have set up a TXT record with DKIM public key at *zzz._domainkey.example.com* then `zzz` is the selector
+ * **privateKey** - DKIM private key that is used for signing as a string
+ * **headerFieldNames** - optional colon separated list of header fields to sign, by default all fields suggested by RFC4871 #5.5 are used
+
+All messages transmitted through this transport objects are from now on DKIM signed.
+
+Currently if several header fields with the same name exists, only the last one (the one in the bottom) is signed.
+
+Example:
+
+```javascript
+var transport = nodemailer.createTransport("Sendmail");
+
+transport.useDKIM({
+ domainName: "node.ee",
+ keySelector: "dkim",
+ privateKey: fs.readFileSync("private_key.pem")
+});
+
+transport.sendMail(mailOptions);
+```
+
+See examples/example_dkim.js for a complete example.
+
+**NB!** Be careful when using services like Gmail, SES etc. through SMTP
+(SES API is handled by Nodemailer automatically) - these tend to modify some
+headers like Message-Id or Date which invalidates the signature. In this case use
+`headerFieldNames` property to define only fields that won't be changed and leave
+out `Date` or any other unsupported field.
+
+### Well known services for SMTP
+
+If you want to use a well known service as the SMTP host, you do not need
+to enter the hostname or port number, just use the `service` parameter (**NB!** case sensitive).
+
+Currently cupported services are:
+
+ * **"Gmail"** for Google Mail
+ * **"hot.ee"** for www.hot.ee
+ * **"Hotmail"** for Microsoft Live Hotmail
+ * **"iCloud"** for Apple iCloud
+ * **"mail.ee"** for www.mail.ee
+ * **"Postmark"** for Postmark App
+ * **"SendGrid"** for SendGrid
+ * **"SES"** for Amazon SES
+ * **"Yahoo"** for Yahoo Mail
+ * **"Zoho"** for Zoho Mail
+
+Predefined service data covers `host`, `port` and secure connection settings,
+any other parameters (ie. `auth`) need to be set separately.
+
+## E-mail message fields
+
+The following are the possible fields of an e-mail message:
+
+ - **from** - The e-mail address of the sender. All e-mail addresses can be plain `sender@server.com` or formatted `Sender Name <sender@server.com>`
+ - **to** - Comma separated list of recipients e-mail addresses that will appear on the `To:` field
+ - **cc** - Comma separated list of recipients e-mail addresses that will appear on the `Cc:` field
+ - **bcc** - Comma separated list of recipients e-mail addresses that will appear on the `Bcc:` field
+ - **replyTo** - An e-mail address that will appear on the `Reply-To:` field
+ - **inReplyTo** - The message-id this message is replying
+ - **references** - Message-id list
+ - **subject** - The subject of the e-mail
+ - **text** - The plaintext version of the message
+ - **html** - The HTML version of the message
+ - **generateTextFromHTML** - if set to true uses HTML to generate plain text body part from the HTML if the text is not defined
+ - **headers** - An object of additional header fields `{"X-Key-Name": "key value"}` (NB! values are passed as is, you should do your own encoding to 7bit if needed)
+ - **attachments** - An array of attachment objects.
+ - **envelope** - optional SMTP envelope, if auto generated envelope is not suitable
+ - **messageId** - optional Message-Id value, random value will be generated if not set. Set to false to omit the Message-Id header
+ - **encoding** - optional transfer encoding for the textual parts (defaults to "quoted-printable")
+
+All text fields (e-mail addresses, plaintext body, html body) use UTF-8 as the encoding.
+Attachments are streamed as binary.
+
+Example:
+
+```javascript
+var transport = nodemailer.createTransport("Sendmail");
+
+var mailOptions = {
+ from: "me@tr.ee",
+ to: "me@tr.ee",
+ subject: "Hello world!",
+ text: "Plaintext body"
+}
+
+transport.sendMail(mailOptions);
+```
+
+### SendGrid support
+
+Nodemailer supports SendGrid [SMTP API](http://docs.sendgrid.com/documentation/api/smtp-api/) out of the box - you can
+use objects as header values and these are automatically JSONized (and mime encoded if needed).
+
+```javascript
+var mailOptions = {
+ ...,
+ headers: {
+ 'X-SMTPAPI': {
+ category : "newuser",
+ sub:{
+ "%name%": ["Žiguli Õllepruul"]
+ }
+ }
+ },
+ subject: "Hello, %name%"
+}
+```
+
+This also applies to any other service that expects a JSON string as a header value for specified key.
+
+### Generate Text from HTML
+
+If `generateTextFromHTML` option is set to true, then HTML contents of the mail is automatically converted
+to plaintext format when plaintext content is empty or missing.
+
+For example
+
+```javascript
+mailOptions = {
+ ...,
+ generateTextFromHTML: true,
+ html: '<h1>Hello world</h1><p><b>How</b> are you?',
+ // text: '' // no text part
+}
+```
+
+is automatically converted in the backround by Nodemailer to:
+
+```javascript
+mailOptions = {
+ ...,
+ // source html:
+ html: '<h1>Hello world</h1><p><b>How</b> are you?',
+ // automatically generated plaintext message:
+ text: "Hello world\n"+
+ "===========\n"+
+ "\n"+
+ "**How** are you?"
+}
+```
+
+As you can see the output syntax for `generateTextFromHTML` looks similar to markdown, and that
+is exactly the case here - Nodemailer includes a simple HTML to markdown converter. But don't
+expect too much from it, it's not full featured or perfect, just some regexes here and there.
+
+### Attachment fields
+
+Attahcment object consists of the following properties:
+
+ * **fileName** - filename to be reported as the name of the attached file, use of unicode is allowed (except when using Amazon SES which doesn't like it)
+ * **cid** - optional content id for using inline images in HTML message source
+ * **contents** - String or a Buffer contents for the attachment
+ * **filePath** - path to a file or an URL if you want to stream the file instead of including it (better for larger attachments)
+ * **streamSource** - Stream object for arbitrary binary streams if you want to stream the contents (needs to support *pause*/*resume*)
+ * **contentType** - optional content type for the attachment, if not set will be derived from the `fileName` property
+ * **contentDisposition** - optional content disposition type for the attachment, defaults to "attachment"
+
+One of `contents`, `filePath` or `streamSource` must be specified, if none is
+present, the attachment will be discarded. Other fields are optional.
+
+Attachments can be added as many as you want.
+
+```javascript
+var mailOptions = {
+ ...
+ attachments: [
+ { // utf-8 string as an attachment
+ fileName: "text1.txt",
+ contents: "hello world!
+ },
+ { // binary buffer as an attachment
+ fileName: "text2.txt",
+ contents: new Buffer("hello world!,"utf-8")
+ },
+ { // file on disk as an attachment
+ fileName: "text3.txt",
+ filePath: "/path/to/file.txt" // stream this file
+ },
+ { // fileName and content type is derived from filePath
+ filePath: "/path/to/file.txt"
+ },
+ { // stream as an attachment
+ fileName: "text4.txt",
+ streamSource: fs.createReadStream("file.txt")
+ },
+ { // define custom content type for the attachment
+ fileName: "text.bin",
+ contents: "hello world!,
+ contentType: "text/plain"
+ },
+ { // use URL as an attachment
+ fileName: "license.txt",
+ filePath: "https://raw.github.com/andris9/Nodemailer/master/LICENSE"
+ }
+ ]
+}
+```
+
+### Address Formatting
+
+All the e-mail addresses can be plain e-mail address
+
+```
+username@example.com
+```
+
+or with formatted name (includes unicode support)
+
+```
+"Ноде Майлер" <username@example.com>
+```
+
+To, Cc and Bcc fields accept comma separated list of e-mails. Formatting can be mixed.
+
+```
+username@example.com, "Ноде Майлер" <username@example.com>, "Name, User" <username@example.com>
+```
+
+You can even use unicode domain and user names, these are automatically converted
+to the supported form
+
+```
+"Uncode Domain" <info@müriaad-polüteism.info>
+```
+
+### SMTP envelope
+
+SMTP envelope is usually auto generated from `from`, `to`, `cc` and `bcc` fields but
+if for some reason you want to specify it yourself, you can do it with `envelope` property.
+
+`envelope` is an object with the following params: `from`, `to`, `cc` and `bcc` just like
+with regular mail options. You can also use the regular address format.
+
+```javascript
+mailOptions = {
+ ...,
+ from: "mailer@node.ee",
+ to: "daemon@node.ee",
+ envelope: {
+ from: "Daemon <deamon@node.ee>",
+ to: "mailer@node.ee, Mailer <mailer2@node.ee>"
+ }
+}
+```
+
+### Using Embedded Images
+
+Attachments can be used as embedded images in the HTML body. To use this
+feature, you need to set additional property of the attachment - `cid` (unique
+identifier of the file) which is a reference to the attachment file. The same
+`cid` value must be used as the image URL in HTML (using `cid:` as the URL
+protocol, see example below).
+
+**NB!** the cid value should be as unique as possible!
+
+```javascript
+var mailOptions = {
+ ...
+ html: "Embedded image: <img src='cid:unique@node.ee' />",
+ attachments: [{
+ filename: "image.png",
+ filePath: "/path/to/file",
+ cid: "unique@node.ee" //same cid value as in the html img src
+ }]
+}
+```
+
+## Return callback
+
+Return callback gets two parameters
+
+ * **error** - an error object if the message failed
+ * **responseStatus** - an object with some information about the status on success
+
+Example:
+
+```javascript
+nodemailer.sendMail(mailOptions, function(error, responseStatus){
+ if(!error){
+ console.log(responseStatus.message); // response from the server
+ }
+});
+```
+
+## Tests
+
+Run the tests with npm in Nodemailer's directory
+
+```
+npm test
+```
+
+There aren't currently many tests for Nodemailer but there are a lot of tests
+in the modules that are used to generate the raw e-mail body and to use the
+SMTP client connection.
+
+## Tweaking
+
+Nodemailer in itself is actually more like a wrapper for my other modules
+[mailcomposer](https://github.com/andris9/mailcomposer) for composing the raw message stream
+and [simplesmtp](https://github.com/andris9/simplesmtp) for delivering it, by providing an
+unified API. If there's some problems with particular parts of the
+message composing/sending process you should look at the appropriate module.
+
+## License
+
+**Nodemailer** is licensed under [MIT license](https://github.com/andris9/Nodemailer/blob/master/LICENSE). Basically you can do whatever you want to with it.
diff --git a/tools/node_modules/nodemailer/examples/example_dkim.js b/tools/node_modules/nodemailer/examples/example_dkim.js
new file mode 100644
index 0000000..2cccdb4
--- /dev/null
+++ b/tools/node_modules/nodemailer/examples/example_dkim.js
@@ -0,0 +1,78 @@
+var nodemailer = require('../lib/nodemailer'),
+ fs = require("fs"),
+ pathlib = require("path");
+
+// Create a SMTP transport object
+var transport = nodemailer.createTransport("sendmail");
+
+// Set up DKIM signing for outgoing messages with this transport object
+transport.useDKIM({
+ domainName: "do-not-trust.node.ee", // signing domain
+ keySelector: "dkim", // selector name (in this case there's a dkim._domainkey.do-not-trust.node.ee TXT record set up)
+ privateKey: fs.readFileSync(pathlib.join(__dirname,"test_private.pem"))
+});
+
+// Message object
+var message = {
+
+ // sender info
+ from: 'Sender Name <sender@example.com>',
+
+ // Comma separated list of recipients
+ to: '"Receiver Name" <receiver@example.com>',
+
+ // Subject of the message
+ subject: 'Nodemailer is unicode friendly ✔', //
+
+ headers: {
+ 'X-Laziness-level': 1000
+ },
+
+ // plaintext body
+ text: 'Hello to myself!',
+
+ // HTML body
+ html:'<p><b>Hello</b> to myself <img src="cid:note@node"/></p>'+
+ '<p>Here\'s a nyan cat for you as an embedded attachment:<br/><img src="cid:nyan@node"/></p>',
+
+ // An array of attachments
+ attachments:[
+
+ // String attachment
+ {
+ fileName: 'notes.txt',
+ contents: 'Some notes about this e-mail',
+ contentType: 'text/plain' // optional, would be detected from the filename
+ },
+
+ // Binary Buffer attachment
+ {
+ fileName: 'image.png',
+ contents: new Buffer('iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/' +
+ '//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U' +
+ 'g9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC', 'base64'),
+
+ cid: 'note@node' // should be as unique as possible
+ },
+
+ // File Stream attachment
+ {
+ fileName: 'nyan cat ✔.gif',
+ filePath: __dirname+"/nyan.gif",
+ cid: 'nyan@node' // should be as unique as possible
+ }
+ ]
+};
+
+console.log('Sending Mail');
+transport.sendMail(message, function(error){
+ if(error){
+ console.log('Error occured');
+ console.log(error.message);
+ return;
+ }
+ console.log('Message sent successfully!');
+
+ // if you don't want to use this transport object anymore, uncomment following line
+ //transport.close(); // close the connection pool
+}); \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/examples/example_sendmail.js b/tools/node_modules/nodemailer/examples/example_sendmail.js
new file mode 100644
index 0000000..86eac1e
--- /dev/null
+++ b/tools/node_modules/nodemailer/examples/example_sendmail.js
@@ -0,0 +1,65 @@
+var nodemailer = require('../lib/nodemailer');
+
+// Create a Sendmail transport object
+var transport = nodemailer.createTransport("Sendmail", "/usr/sbin/sendmail");
+
+console.log('Sendmail Configured');
+
+// Message object
+var message = {
+
+ // sender info
+ from: 'Sender Name <sender@example.com>',
+
+ // Comma separated list of recipients
+ to: '"Receiver Name" <receiver@example.com>',
+
+ // Subject of the message
+ subject: 'Nodemailer is unicode friendly ✔', //
+
+ // plaintext body
+ text: 'Hello to myself!',
+
+ // HTML body
+ html:'<p><b>Hello</b> to myself <img src="cid:note@node"/></p>'+
+ '<p>Here\'s a nyan cat for you as an embedded attachment:<br/><img src="cid:nyan@node"/></p>',
+
+ // An array of attachments
+ attachments:[
+
+ // String attachment
+ {
+ fileName: 'notes.txt',
+ contents: 'Some notes about this e-mail',
+ contentType: 'text/plain' // optional, would be detected from the filename
+ },
+
+ // Binary Buffer attachment
+ {
+ fileName: 'image.png',
+ contents: new Buffer('iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/' +
+ '//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U' +
+ 'g9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC', 'base64'),
+
+ cid: 'note@node' // should be as unique as possible
+ },
+
+ // File Stream attachment
+ {
+ fileName: 'nyan cat ✔.gif',
+ filePath: __dirname+"/nyan.gif",
+ cid: 'nyan@node' // should be as unique as possible
+ }
+ ]
+};
+
+console.log('Sending Mail');
+
+transport.sendMail(message, function(error){
+ if(error){
+ console.log('Error occured');
+ console.log(error.message);
+ return;
+ }
+ console.log('Message sent successfully!');
+}); \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/examples/example_ses.js b/tools/node_modules/nodemailer/examples/example_ses.js
new file mode 100644
index 0000000..5be0586
--- /dev/null
+++ b/tools/node_modules/nodemailer/examples/example_ses.js
@@ -0,0 +1,80 @@
+var nodemailer = require('../lib/nodemailer'),
+ fs = require("fs"),
+ pathlib = require("path");
+
+// Create an Amazon SES transport object
+var transport = nodemailer.createTransport("SES", {
+ AWSAccessKeyID: "AWSACCESSKEY",
+ AWSSecretKey: "/AWS/SECRET",
+ ServiceUrl: "https://email.us-east-1.amazonaws.com" // optional
+ });
+
+console.log('SES Configured');
+
+// optional DKIM signing
+/*
+transport.useDKIM({
+ domainName: "do-not-trust.node.ee", // signing domain
+ keySelector: "dkim", // selector name (in this case there's a dkim._domainkey.do-not-trust.node.ee TXT record set up)
+ privateKey: fs.readFileSync(pathlib.join(__dirname,"test_private.pem"))
+});
+*/
+
+// Message object
+var message = {
+
+ // sender info
+ from: 'Sender Name <sender@example.com>',
+
+ // Comma separated list of recipients
+ to: '"Receiver Name" <receiver@example.com>',
+
+ // Subject of the message
+ subject: 'Nodemailer is unicode friendly ✔', //
+
+ // plaintext body
+ text: 'Hello to myself!',
+
+ // HTML body
+ html:'<p><b>Hello</b> to myself <img src="cid:note@node"/></p>'+
+ '<p>Here\'s a nyan cat for you as an embedded attachment:<br/><img src="cid:nyan@node"/></p>',
+
+ // An array of attachments
+ attachments:[
+
+ // String attachment
+ {
+ fileName: 'notes.txt',
+ contents: 'Some notes about this e-mail',
+ contentType: 'text/plain' // optional, would be detected from the filename
+ },
+
+ // Binary Buffer attachment
+ {
+ fileName: 'image.png',
+ contents: new Buffer('iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/' +
+ '//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U' +
+ 'g9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC', 'base64'),
+
+ cid: 'note@node' // should be as unique as possible
+ },
+
+ // File Stream attachment
+ {
+ fileName: 'nyancat.gif',
+ filePath: __dirname+"/nyan.gif",
+ cid: 'nyan@node' // should be as unique as possible
+ }
+ ]
+};
+
+console.log('Sending Mail');
+
+transport.sendMail(message, function(error){
+ if(error){
+ console.log('Error occured');
+ console.log(error.message);
+ return;
+ }
+ console.log('Message sent successfully!');
+}); \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/examples/example_smtp.js b/tools/node_modules/nodemailer/examples/example_smtp.js
new file mode 100644
index 0000000..5b73f21
--- /dev/null
+++ b/tools/node_modules/nodemailer/examples/example_smtp.js
@@ -0,0 +1,77 @@
+var nodemailer = require('../lib/nodemailer');
+
+// Create a SMTP transport object
+var transport = nodemailer.createTransport("SMTP", {
+ service: 'Gmail', // use well known service
+ auth: {
+ user: "test.nodemailer@gmail.com",
+ pass: "Nodemailer123"
+ }
+ });
+
+console.log('SMTP Configured');
+
+// Message object
+var message = {
+
+ // sender info
+ from: 'Sender Name <sender@example.com>',
+
+ // Comma separated list of recipients
+ to: '"Receiver Name" <receiver@example.com>',
+
+ // Subject of the message
+ subject: 'Nodemailer is unicode friendly ✔', //
+
+ headers: {
+ 'X-Laziness-level': 1000
+ },
+
+ // plaintext body
+ text: 'Hello to myself!',
+
+ // HTML body
+ html:'<p><b>Hello</b> to myself <img src="cid:note@node"/></p>'+
+ '<p>Here\'s a nyan cat for you as an embedded attachment:<br/><img src="cid:nyan@node"/></p>',
+
+ // An array of attachments
+ attachments:[
+
+ // String attachment
+ {
+ fileName: 'notes.txt',
+ contents: 'Some notes about this e-mail',
+ contentType: 'text/plain' // optional, would be detected from the filename
+ },
+
+ // Binary Buffer attachment
+ {
+ fileName: 'image.png',
+ contents: new Buffer('iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/' +
+ '//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U' +
+ 'g9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC', 'base64'),
+
+ cid: 'note@node' // should be as unique as possible
+ },
+
+ // File Stream attachment
+ {
+ fileName: 'nyan cat ✔.gif',
+ filePath: __dirname+"/nyan.gif",
+ cid: 'nyan@node' // should be as unique as possible
+ }
+ ]
+};
+
+console.log('Sending Mail');
+transport.sendMail(message, function(error){
+ if(error){
+ console.log('Error occured');
+ console.log(error.message);
+ return;
+ }
+ console.log('Message sent successfully!');
+
+ // if you don't want to use this transport object anymore, uncomment following line
+ //transport.close(); // close the connection pool
+}); \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/examples/example_xoauth.js b/tools/node_modules/nodemailer/examples/example_xoauth.js
new file mode 100644
index 0000000..80c5db9
--- /dev/null
+++ b/tools/node_modules/nodemailer/examples/example_xoauth.js
@@ -0,0 +1,86 @@
+var nodemailer = require('../lib/nodemailer');
+
+// Create a SMTP transport object
+var transport = nodemailer.createTransport("SMTP", {
+ service: 'Gmail', // use well known service
+ auth: {
+ // Option one - provide pregenerated token
+ // XOAuthToken: "R0VUIGh0dHBzOi8vbWFpbC5nb29...."
+ // or alternatively, use built in generator
+ XOAuthToken: nodemailer.createXOAuthGenerator({
+ user: "test.nodemailer@gmail.com",
+ consumerKey: "anonymous", // optional
+ consumerSecret: "anonymous", // optional
+ token: "1/O_HgoO4h2uOUfpus0V--7mygICXrQQ0ZajB3ZH52KqM",
+ tokenSecret: "_mUBkIwNPnfQBUIWrJrpXJ0c"
+ })
+ },
+ debug: true
+ });
+
+console.log('SMTP Configured');
+
+// Message object
+var message = {
+
+ // sender info
+ from: 'Sender Name <sender@example.com>',
+
+ // Comma separated list of recipients
+ to: '"Receiver Name" <receiver@example.com>',
+
+ // Subject of the message
+ subject: 'Nodemailer is unicode friendly ✔', //
+
+ headers: {
+ 'X-Laziness-level': 1000
+ },
+
+ // plaintext body
+ text: 'Hello to myself!',
+
+ // HTML body
+ html:'<p><b>Hello</b> to myself <img src="cid:note@node"/></p>'+
+ '<p>Here\'s a nyan cat for you as an embedded attachment:<br/><img src="cid:nyan@node"/></p>',
+
+ // An array of attachments
+ attachments:[
+
+ // String attachment
+ {
+ fileName: 'notes.txt',
+ contents: 'Some notes about this e-mail',
+ contentType: 'text/plain' // optional, would be detected from the filename
+ },
+
+ // Binary Buffer attachment
+ {
+ fileName: 'image.png',
+ contents: new Buffer('iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/' +
+ '//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U' +
+ 'g9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC', 'base64'),
+
+ cid: 'note@node' // should be as unique as possible
+ },
+
+ // File Stream attachment
+ {
+ fileName: 'nyan cat ✔.gif',
+ filePath: __dirname+"/nyan.gif",
+ cid: 'nyan@node' // should be as unique as possible
+ }
+ ]
+};
+
+console.log('Sending Mail');
+transport.sendMail(message, function(error){
+ if(error){
+ console.log('Error occured');
+ console.log(error.message);
+ return;
+ }
+ console.log('Message sent successfully!');
+
+ // if you don't want to use this transport object anymore, uncomment following line
+ //transport.close(); // close the connection pool
+}); \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/examples/nyan.gif b/tools/node_modules/nodemailer/examples/nyan.gif
new file mode 100644
index 0000000..bf0314f
--- /dev/null
+++ b/tools/node_modules/nodemailer/examples/nyan.gif
Binary files differ
diff --git a/tools/node_modules/nodemailer/examples/test_private.pem b/tools/node_modules/nodemailer/examples/test_private.pem
new file mode 100644
index 0000000..9d03266
--- /dev/null
+++ b/tools/node_modules/nodemailer/examples/test_private.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBywIBAAJhANCx7ncKUfQ8wBUYmMqq6ky8rBB0NL8knBf3+uA7q/CSxpX6sQ8N
+dFNtEeEd7gu7BWEM7+PkO1P0M78eZOvVmput8BP9R44ARpgHY4V0qSCdUt4rD32n
+wfjlGbh8p5ua5wIDAQABAmAm+uUQpQPTu7kg95wqVqw2sxLsa9giT6M8MtxQH7Uo
+1TF0eAO0TQ4KOxgY1S9OT5sGPVKnag258m3qX7o5imawcuyStb68DQgAUg6xv7Af
+AqAEDfYN5HW6xK+X81jfOUECMQDr7XAS4PERATvgb1B3vRu5UEbuXcenHDYgdoyT
+3qJFViTbep4qeaflF0uF9eFveMcCMQDic10rJ8fopGD7/a45O4VJb0+lRXVdqZxJ
+QzAp+zVKWqDqPfX7L93SQLzOGhdd7OECMQDeQyD7WBkjSQNMy/GF7I1qxrscIxNN
+VqGTcbu8Lti285Hjhx/sqhHHHGwU9vB7oM8CMQDKTS3Kw/s/xrot5O+kiZwFgr+w
+cmDrj/7jJHb+ykFNb7GaEkiSYqzUjKkfpweBDYECMFJUyzuuFJAjq3BXmGJlyykQ
+TweUw+zMVdSXjO+FCPcYNi6CP1t1KoESzGKBVoqA/g==
+-----END RSA PRIVATE KEY-----
diff --git a/tools/node_modules/nodemailer/lib/engines/sendmail.js b/tools/node_modules/nodemailer/lib/engines/sendmail.js
new file mode 100644
index 0000000..e72f5d8
--- /dev/null
+++ b/tools/node_modules/nodemailer/lib/engines/sendmail.js
@@ -0,0 +1,52 @@
+var spawn = require('child_process').spawn;
+
+// Expose to the world
+module.exports = SendmailTransport;
+
+/**
+ * <p>Generates a Transport object for Sendmail</p>
+ *
+ * @constructor
+ * @param {String} [config] path to the sendmail command
+ */
+function SendmailTransport(config){
+ this.path = "sendmail";
+ this.args = [];
+ if(typeof config=="string") {
+ this.path = config;
+ } else if(typeof config=="object") {
+ if(config.path) {
+ this.path = config.path;
+ }
+ if(Array.isArray(config.args)) {
+ this.args = config.args;
+ }
+ }
+}
+
+/**
+ * <p>Spawns a <code>'sendmail -t'</code> command and streams the outgoing
+ * message to sendmail stdin. Return callback checks if the sendmail process
+ * ended with 0 (no error) or not.</p>
+ *
+ * @param {Object} emailMessage MailComposer object
+ * @param {Function} callback Callback function to run when the sending is completed
+ */
+SendmailTransport.prototype.sendMail = function(emailMessage, callback) {
+
+ // sendmail strips this header line by itself
+ emailMessage.options.keepBcc = true;
+
+ var sendmail = spawn(this.path, ["-t"].concat(this.args));
+
+ sendmail.on('exit', function (code) {
+ var msg = "Sendmail exited with "+code;
+ if(typeof callback == "function"){
+ callback(code?new Error(msg):null, {message: msg});
+ }
+ });
+
+ emailMessage.pipe(sendmail.stdin);
+ emailMessage.streamMessage();
+
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/lib/engines/ses.js b/tools/node_modules/nodemailer/lib/engines/ses.js
new file mode 100644
index 0000000..4766c4f
--- /dev/null
+++ b/tools/node_modules/nodemailer/lib/engines/ses.js
@@ -0,0 +1,217 @@
+/*
+ * This file is based on the original SES module for Nodemailer by dfellis
+ * https://github.com/andris9/Nodemailer/blob/11fb3ef560b87e1c25e8bc15c2179df5647ea6f5/lib/engines/SES.js
+ */
+
+// NB! Amazon SES does not allow unicode filenames on attachments!
+
+var http = require('http'),
+ https = require('https'),
+ crypto = require('crypto'),
+ urllib = require("url");
+
+// Expose to the world
+module.exports = SESTransport;
+
+/**
+ * <p>Generates a Transport object for Amazon SES</p>
+ *
+ * <p>Possible options can be the following:</p>
+ *
+ * <ul>
+ * <li><b>AWSAccessKeyID</b> - AWS access key (required)</li>
+ * <li><b>AWSSecretKey</b> - AWS secret (required)</li>
+ * <li><b>ServiceUrl</b> - optional API endpoint URL (defaults to <code>"https://email.us-east-1.amazonaws.com"</code>)
+ * </ul>
+ *
+ * @constructor
+ * @param {Object} options Options object for the SES transport
+ */
+function SESTransport(options){
+ this.options = options || {};
+
+ //Set defaults if necessary
+ this.options.ServiceUrl = this.options.ServiceUrl || "https://email.us-east-1.amazonaws.com";
+}
+
+/**
+ * <p>Compiles a mailcomposer message and forwards it to handler that sends it.</p>
+ *
+ * @param {Object} emailMessage MailComposer object
+ * @param {Function} callback Callback function to run when the sending is completed
+ */
+SESTransport.prototype.sendMail = function(emailMessage, callback) {
+
+ // SES strips this header line by itself
+ emailMessage.options.keepBcc = true;
+
+ //Check if required config settings set
+ if(!this.options.AWSAccessKeyID || !this.options.AWSSecretKey) {
+ return callback(new Error("Missing AWS Credentials"));
+ }
+
+ this.generateMessage(emailMessage, (function(err, email){
+ if(err){
+ return typeof callback == "function" && callback(err);
+ }
+ this.handleMessage(email, callback);
+ }).bind(this));
+};
+
+/**
+ * <p>Compiles and sends the request to SES with e-mail data</p>
+ *
+ * @param {String} email Compiled raw e-mail as a string
+ * @param {Function} callback Callback function to run once the message has been sent
+ */
+SESTransport.prototype.handleMessage = function(email, callback) {
+ var request,
+
+ date = new Date(),
+
+ urlparts = urllib.parse(this.options.ServiceUrl),
+
+ params = this.buildKeyValPairs({
+ 'Action': 'SendRawEmail',
+ 'RawMessage.Data': (new Buffer(email, "utf-8")).toString('base64'),
+ 'Version': '2010-12-01',
+ 'Timestamp': this.ISODateString(date)
+ }),
+
+ reqObj = {
+ host: urlparts.hostname,
+ path: urlparts.path || "/",
+ method: "POST",
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'Content-Length': params.length,
+ 'Date': date.toUTCString(),
+ 'X-Amzn-Authorization':
+ ['AWS3-HTTPS AWSAccessKeyID='+this.options.AWSAccessKeyID,
+ "Signature="+this.buildSignature(date.toUTCString(), this.options.AWSSecretKey),
+ "Algorithm=HmacSHA256"].join(",")
+ }
+ };
+
+ //Execute the request on the correct protocol
+ if(urlparts.protocol.substr() == "https:") {
+ request = https.request(reqObj, this.responseHandler.bind(this, callback));
+ } else {
+ request = http.request(reqObj, this.responseHandler.bind(this, callback));
+ }
+ request.end(params);
+};
+
+/**
+ * <p>Handles the response for the HTTP request to SES</p>
+ *
+ * @param {Function} callback Callback function to run on end (binded)
+ * @param {Object} response HTTP Response object
+ */
+SESTransport.prototype.responseHandler = function(callback, response) {
+ var body = "";
+ response.setEncoding('utf8');
+
+ //Re-assembles response data
+ response.on('data', function(d) {
+ body += d.toString();
+ });
+
+ //Performs error handling and executes callback, if it exists
+ response.on('end', function(err) {
+ if(err instanceof Error) {
+ return typeof callback == "function" && callback(err, null);
+ }
+ if(response.statusCode != 200) {
+ return typeof callback == "function" &&
+ callback(new Error('Email failed: ' + response.statusCode + '\n' + body), null);
+ }
+ return typeof callback == "function" && callback(null, {
+ message: body
+ });
+ });
+};
+
+/**
+ * <p>Compiles the messagecomposer object to a string.</p>
+ *
+ * <p>It really sucks but I don't know a good way to stream a POST request with
+ * unknown legth, so the message needs to be fully composed as a string.</p>
+ *
+ * @param {Object} emailMessage MailComposer object
+ * @param {Function} callback Callback function to run once the message has been compiled
+ */
+
+SESTransport.prototype.generateMessage = function(emailMessage, callback) {
+ var email = "";
+
+ emailMessage.on("data", function(chunk){
+ email += (chunk || "").toString("utf-8");
+ });
+
+ emailMessage.on("end", function(chunk){
+ email += (chunk || "").toString("utf-8");
+ callback(null, email);
+ });
+
+ emailMessage.streamMessage();
+};
+
+/**
+ * <p>Converts an object into a Array with "key=value" values</p>
+ *
+ * @param {Object} config Object with keys and values
+ * @return {Array} Array of key-value pairs
+ */
+SESTransport.prototype.buildKeyValPairs = function(config){
+ var keys = Object.keys(config).sort(),
+ keyValPairs = [],
+ key, i, len;
+
+ for(i=0, len = keys.length; i < len; i++) {
+ key = keys[i];
+ if(key != "ServiceUrl") {
+ keyValPairs.push((encodeURIComponent(key) + "=" + encodeURIComponent(config[key])));
+ }
+ }
+
+ return keyValPairs.join("&");
+};
+
+/**
+ * <p>Uses SHA-256 HMAC with AWS key on date string to generate a signature</p>
+ *
+ * @param {String} date ISO UTC date string
+ * @param {String} AWSSecretKey ASW secret key
+ */
+SESTransport.prototype.buildSignature = function(date, AWSSecretKey) {
+ var sha256 = crypto.createHmac('sha256', AWSSecretKey);
+ sha256.update(date);
+ return sha256.digest('base64');
+};
+
+/**
+ * <p>Generates an UTC string in the format of YYY-MM-DDTHH:MM:SSZ</p>
+ *
+ * @param {Date} d Date object
+ * @return {String} Date string
+ */
+SESTransport.prototype.ISODateString = function(d){
+ return d.getUTCFullYear() + '-' +
+ this.strPad(d.getUTCMonth()+1) + '-' +
+ this.strPad(d.getUTCDate()) + 'T' +
+ this.strPad(d.getUTCHours()) + ':' +
+ this.strPad(d.getUTCMinutes()) + ':' +
+ this.strPad(d.getUTCSeconds()) + 'Z';
+};
+
+/**
+ * <p>Simple padding function. If the number is below 10, add a zero</p>
+ *
+ * @param {Number} n Number to pad with 0
+ * @return {String} 0 padded number
+ */
+SESTransport.prototype.strPad = function(n){
+ return n<10 ? '0'+n : n;
+};
+
diff --git a/tools/node_modules/nodemailer/lib/engines/smtp.js b/tools/node_modules/nodemailer/lib/engines/smtp.js
new file mode 100644
index 0000000..99bd00e
--- /dev/null
+++ b/tools/node_modules/nodemailer/lib/engines/smtp.js
@@ -0,0 +1,109 @@
+var wellKnownHosts = require("../wellknown"),
+ simplesmtp = require("simplesmtp");
+
+// Expose to the world
+module.exports = SMTPTransport;
+
+/**
+ * <p>Generates a Transport object for SMTP</p>
+ *
+ * <p>NB! This is a pool of connections that try to keep themselves alive. The
+ * connection is not closed to the server once the message is delivered.</p>
+ *
+ * <p>Possible options can be the following:</p>
+ *
+ * <ul>
+ * <li><b>service</b> - a well known service identifier ("Gmail", "Hotmail"
+ * etc.) for auto-completing host, port and secure connection settings</li>
+ * <li><b>host</b> - hostname of the SMTP server</li>
+ * <li><b>port</b> - port of the SMTP server</li>
+ * <li><b>secureConnection</b> - use SSL</li>
+ * <li><b>name</b> - the name of the client server</li>
+ * <li><b>auth</b> - authentication object as <code>{user:"...", pass:"..."}</code>
+ * <li><b>ignoreTLS</b> - ignore server support for STARTTLS</li>
+ * <li><b>debug</b> - output client and server messages to console</li>
+ * <li><b>maxConnections</b> - how many connections to keep in the pool</li>
+ * </ul>
+ *
+ * @constructor
+ * @param {Object} [options] SMTP options
+ */
+function SMTPTransport(options){
+
+
+ this.options = options || {};
+
+ this.initOptions();
+
+ this.pool = simplesmtp.createClientPool(this.options.port,
+ this.options.host, this.options);
+}
+
+/**
+ * <p>Initializes the SMTP connection options. Needed mostly for legacy option
+ * values and also for filling in the well known hosts data if needed.</p>
+ */
+SMTPTransport.prototype.initOptions = function(){
+ var keys, key, i, len;
+
+ // provide support for legacy API
+ if(this.options.use_authentication === false){
+ this.options.auth = false;
+ }else if(this.options.user || this.options.pass || this.options.XOAuthToken){
+ if(!this.options.auth){
+ this.options.auth = {};
+ }
+ this.options.auth.user = this.options.auth.user || this.options.user;
+ this.options.auth.pass = this.options.auth.pass || this.options.pass;
+ this.options.auth.XOAuthToken = this.options.auth.XOAuthToken || this.options.XOAuthToken;
+ }
+
+ if(this.options.ssl){
+ this.options.secureConnection = true;
+ }
+
+ if(this.options.tls === false){
+ this.options.ignoreTLS = true;
+ }
+
+ // lets be modest just in case
+ this.options.maxConnections = this.options.maxConnections || 5;
+
+ // use well known settings if service is defined
+ if(this.options.service && wellKnownHosts[this.options.service]){
+ keys = Object.keys(wellKnownHosts[this.options.service]);
+ for(i=0, len=keys.length; i<len; i++){
+ key = keys[i];
+ this.options[key] = this.options[key] ||
+ wellKnownHosts[this.options.service][key];
+ }
+ }
+};
+
+/**
+ * <p>Forwards the mailcomposer message object to the simplesmpt client pool</p>
+ *
+ * @param {Object} emailMessage MailComposer object
+ * @param {Function} callback Callback function to run when the sending is completed
+ */
+SMTPTransport.prototype.sendMail = function(emailMessage, callback){
+ // force SMTP encoding
+ emailMessage.options.escapeSMTP = true;
+
+ if(this.options.requiresAuth &&
+ (!this.options.auth || !((this.options.auth.user && this.options.auth.pass) || this.options.auth.XOAuthToken))){
+ return typeof callback == "function" &&
+ callback(new Error("Authentication required, invalid details provided"));
+ }
+
+ this.pool.sendMail(emailMessage, callback);
+};
+
+/**
+ * <p>Closes the client pool</p>
+ *
+ * @param {Function} callback Callback function to run once the pool is closed
+ */
+SMTPTransport.prototype.close = function(callback){
+ this.pool.close(callback);
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/lib/engines/stub.js b/tools/node_modules/nodemailer/lib/engines/stub.js
new file mode 100644
index 0000000..754cc12
--- /dev/null
+++ b/tools/node_modules/nodemailer/lib/engines/stub.js
@@ -0,0 +1,39 @@
+
+// Expose to the world
+module.exports = StubTransport;
+
+/**
+ * <p>Generates a stub Transport object for testing purposes</p>
+ *
+ * @constructor
+ */
+function StubTransport(){}
+
+/**
+ * <p>Generates a raw e-mail source and returns it with callback</p>
+ *
+ * @param {Object} emailMessage MailComposer object
+ * @param {Function} callback Callback function to run when the e-mail is composed
+ */
+StubTransport.prototype.sendMail = function(emailMessage, callback) {
+
+ var output = "";
+
+ // sendmail strips this header line by itself
+ emailMessage.options.keepBcc = true;
+
+ emailMessage.on("data", function(data){
+ output += (data || "").toString("utf-8");
+ });
+
+ emailMessage.on("error", function(err){
+ callback(err);
+ });
+
+ emailMessage.on("end", function(){
+ callback(null, {message: output, envelope: emailMessage.getEnvelope()});
+ });
+
+ emailMessage.streamMessage();
+
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/lib/helpers.js b/tools/node_modules/nodemailer/lib/helpers.js
new file mode 100644
index 0000000..0d57973
--- /dev/null
+++ b/tools/node_modules/nodemailer/lib/helpers.js
@@ -0,0 +1,223 @@
+
+// expose to the world
+module.exports.stripHTML = stripHTML;
+
+/**
+ * <p>Converts a HTML stringo into plaintext format that resembles Markdown</p>
+ *
+ * <p>Only good for simple and valid HTML, probably breaks on eveything else</p>
+ *
+ * <p>Placeholders:</p>
+ *
+ * <ul>
+ * <li>-\u0000\u0000- for newline</li>
+ * <li>-\u0001\u0001- for a space</li>
+ * <li>-\u0002\u0002- temporary newlines</li>
+ * </ul>
+ *
+ * @param {String} str HTML string to convert
+ * @return {String} Plaintext that resembles Markdown
+ */
+function stripHTML(str){
+ str = (str || "").toString("utf-8").trim();
+
+ // replace newlines
+ str = str.replace(/\r?\n|\r/g,"-\u0002\u0002-");
+
+ // convert block element endings to linebreak markers
+ str = str.replace(/<(?:\/p|br|\/tr|\/table|\/div)>/g,"-\u0000\u0000--\u0000\u0000-");
+
+ // H1-H6, add underline or prepend with #
+ str = str.replace(/<[hH](\d)[^>]*>(.*?)<\/[hH]\d[^>]*>/g,function(match, level, content){
+ var line = "",
+ symbol, // line symbol char
+ len;
+
+ level = Number(level) || 0;
+
+ content = decodeHTMLEntities(content.replace(/<[^>]*>/g," ").
+ replace(/\s\s+/g," ")).
+ trim();
+
+ if(!content){
+ // the tag was empty or only included other tags (<img> and such), nothing to show
+ return "";
+ }
+
+ // select correct symbol for the line
+ switch(level){
+ case 1:
+ symbol = "=";
+ len = content.length;
+ break;
+ case 2:
+ symbol = "-";
+ len = content.length;
+ break;
+ default:
+ symbol = "#";
+ len = level;
+ }
+
+ line = new Array(len+1).join(symbol);
+
+ if(symbol == "#"){
+ // prepend the line:
+ // ### This is a H3
+ return line + " " + content + "\n\n";
+ }else{
+ // add underline:
+ // This is a H1
+ // ============
+ return content + "\n" + line + "\n\n";
+ }
+
+ });
+
+ // B
+ str = str.replace(/<(?:b|strong)(?: [^>])?>(.*?)<\/(?:b|strong)>/ig,function(match, content){
+ return "**" + content.trim() + "**";
+ });
+
+ // U
+ str = str.replace(/<u(?: [^>])?>(.*?)<\/u>/ig,function(match, content){
+ return "_" + content.trim() + "_";
+ });
+
+ // EM
+ str = str.replace(/<(?:i|em)(?: [^>])?>(.*?)<\/(?:i|em)>/ig,function(match, content){
+ return "*" + content.trim() + "*";
+ });
+
+ // CODE
+ str = str.replace(/<code(?: [^>])?>(.*?)<\/code>/ig,function(match, content){
+ return "`" + content.trim() + "`";
+ });
+
+ // A
+ str = str.replace(/<a ([^>]*)>(.*?)<\/a[^>]*>/ig,function(match, params, content){
+ var paramMatch = params.match(/href\s*=\s*['"]([^'"]+)['"]/),
+ url = paramMatch && paramMatch[1] || "#";
+
+ return "(" + content.trim() + ")" + "[" + url +"]";
+ });
+
+ // UL, replace with newlines
+ str = str.replace(/(<\/(?:ul|ol)>)/gi,"$1-\u0000\u0000--\u0000\u0000-");
+
+ // LI, indent by 2 spaces + *
+ str = str.replace(/<li[^>]*>(.*?)<\/?(?:li|ol|ul)[^>]*>/ig,function(match, content){
+
+ content = content.replace(/<[^>]*>/g," ").
+ replace(/\s\s+/g," ").
+ trim();
+
+ if(!content){
+ // the tag was empty or only included other tags (<img> and such), nothing to show
+ return "";
+ }
+
+ // return with the space placeholders
+ return "-\u0001\u0001--\u0001\u0001-* " + content + "\n";
+ });
+
+ // PRE, indent by 4 spaces
+ str = str.replace(/<pre[^>]*>(.*?)<\/pre[^>]*>/ig,function(match, content){
+ if(!content){
+ return "";
+ }
+
+ // remove empty lines before and after
+ content = content.replace(/^((?:[ \t]*)\-\u0002\u0002\-)+|((?:\-\u0002\u0002\-[ \t]*))+$/g, "");
+
+ // replace tabs with 4 spaces
+ content = content.replace(/\t/g, " ");
+
+ // replace temp. linebreak placeholders with 4 space placehorlders
+ content = content.replace(/\-\u0002\u0002\-([ ]*)/g, function(match, spaces){
+ // keep spaces in the beginning of the lines
+ spaces = spaces.replace(/ /g, "-\u0001\u0001-");
+
+ return "\n-\u0001\u0001--\u0001\u0001--\u0001\u0001--\u0001\u0001-" + spaces;
+ });
+
+ content = content.replace(/</g,"&lt;").replace(/>/g,"&gt;");
+
+ // add prepending 4 spaces
+ return "\n-\u0001\u0001--\u0001\u0001--\u0001\u0001--\u0001\u0001-" + content.trim() + "\n\n";
+ });
+
+ // remove all remaining html tags
+ str = str.replace(/<[^>]*>/g," ");
+
+ // remove duplicate spaces
+ str = str.replace(/[ ][ ]+/g," ");
+
+ // remove temp. newlines
+ str = str.replace(/-\u0002\u0002-/g," ");
+
+ // restore newlines
+ str = str.replace(/-\u0000\u0000-/g,"\n");
+
+ // remove spaces before and after newlines
+ str = str.replace(/[ \t]*\n[ \t]*/g,"\n");
+
+ // remove more than 2 newlines in a row
+ str = str.replace(/\n\n+/g,"\n\n");
+
+ // restore hidden spaces
+ str = str.replace(/-\u0001\u0001-/g," ");
+
+ // decode HTML entities (&lt; and such)
+ str = decodeHTMLEntities(str);
+
+ return str.trim();
+}
+
+/**
+ * <p>Decodes any HTML entities in a string into their unicode form</p>
+ *
+ * @param {String} text text to decode
+ * @return {String} Decoded text
+ */
+function decodeHTMLEntities(text){
+ var HTMLEntities = {
+ apos:0x0027,quot:0x0022,amp:0x0026,lt:0x003C,gt:0x003E,nbsp:0x00A0,iexcl:0x00A1,cent:0x00A2,pound:0x00A3,
+ curren:0x00A4,yen:0x00A5,brvbar:0x00A6,sect:0x00A7,uml:0x00A8,copy:0x00A9,ordf:0x00AA,laquo:0x00AB,
+ not:0x00AC,shy:0x00AD,reg:0x00AE,macr:0x00AF,deg:0x00B0,plusmn:0x00B1,sup2:0x00B2,sup3:0x00B3,
+ acute:0x00B4,micro:0x00B5,para:0x00B6,middot:0x00B7,cedil:0x00B8,sup1:0x00B9,ordm:0x00BA,raquo:0x00BB,
+ frac14:0x00BC,frac12:0x00BD,frac34:0x00BE,iquest:0x00BF,Agrave:0x00C0,Aacute:0x00C1,Acirc:0x00C2,Atilde:0x00C3,
+ Auml:0x00C4,Aring:0x00C5,AElig:0x00C6,Ccedil:0x00C7,Egrave:0x00C8,Eacute:0x00C9,Ecirc:0x00CA,Euml:0x00CB,
+ Igrave:0x00CC,Iacute:0x00CD,Icirc:0x00CE,Iuml:0x00CF,ETH:0x00D0,Ntilde:0x00D1,Ograve:0x00D2,Oacute:0x00D3,
+ Ocirc:0x00D4,Otilde:0x00D5,Ouml:0x00D6,times:0x00D7,Oslash:0x00D8,Ugrave:0x00D9,Uacute:0x00DA,Ucirc:0x00DB,
+ Uuml:0x00DC,Yacute:0x00DD,THORN:0x00DE,szlig:0x00DF,agrave:0x00E0,aacute:0x00E1,acirc:0x00E2,atilde:0x00E3,
+ auml:0x00E4,aring:0x00E5,aelig:0x00E6,ccedil:0x00E7,egrave:0x00E8,eacute:0x00E9,ecirc:0x00EA,euml:0x00EB,
+ igrave:0x00EC,iacute:0x00ED,icirc:0x00EE,iuml:0x00EF,eth:0x00F0,ntilde:0x00F1,ograve:0x00F2,oacute:0x00F3,
+ ocirc:0x00F4,otilde:0x00F5,ouml:0x00F6,divide:0x00F7,oslash:0x00F8,ugrave:0x00F9,uacute:0x00FA,ucirc:0x00FB,
+ uuml:0x00FC,yacute:0x00FD,thorn:0x00FE,yuml:0x00FF,OElig:0x0152,oelig:0x0153,Scaron:0x0160,scaron:0x0161,
+ Yuml:0x0178,fnof:0x0192,circ:0x02C6,tilde:0x02DC,Alpha:0x0391,Beta:0x0392,Gamma:0x0393,Delta:0x0394,
+ Epsilon:0x0395,Zeta:0x0396,Eta:0x0397,Theta:0x0398,Iota:0x0399,Kappa:0x039A,Lambda:0x039B,Mu:0x039C,
+ Nu:0x039D,Xi:0x039E,Omicron:0x039F,Pi:0x03A0,Rho:0x03A1,Sigma:0x03A3,Tau:0x03A4,Upsilon:0x03A5,
+ Phi:0x03A6,Chi:0x03A7,Psi:0x03A8,Omega:0x03A9,alpha:0x03B1,beta:0x03B2,gamma:0x03B3,delta:0x03B4,
+ epsilon:0x03B5,zeta:0x03B6,eta:0x03B7,theta:0x03B8,iota:0x03B9,kappa:0x03BA,lambda:0x03BB,mu:0x03BC,
+ nu:0x03BD,xi:0x03BE,omicron:0x03BF,pi:0x03C0,rho:0x03C1,sigmaf:0x03C2,sigma:0x03C3,tau:0x03C4,
+ upsilon:0x03C5,phi:0x03C6,chi:0x03C7,psi:0x03C8,omega:0x03C9,thetasym:0x03D1,upsih:0x03D2,piv:0x03D6,
+ ensp:0x2002,emsp:0x2003,thinsp:0x2009,zwnj:0x200C,zwj:0x200D,lrm:0x200E,rlm:0x200F,ndash:0x2013,
+ mdash:0x2014,lsquo:0x2018,rsquo:0x2019,sbquo:0x201A,ldquo:0x201C,rdquo:0x201D,bdquo:0x201E,dagger:0x2020,
+ Dagger:0x2021,bull:0x2022,hellip:0x2026,permil:0x2030,prime:0x2032,Prime:0x2033,lsaquo:0x2039,rsaquo:0x203A,
+ oline:0x203E,frasl:0x2044,euro:0x20AC,image:0x2111,weierp:0x2118,real:0x211C,trade:0x2122,alefsym:0x2135,
+ larr:0x2190,uarr:0x2191,rarr:0x2192,darr:0x2193,harr:0x2194,crarr:0x21B5,lArr:0x21D0,uArr:0x21D1,
+ rArr:0x21D2,dArr:0x21D3,hArr:0x21D4,forall:0x2200,part:0x2202,exist:0x2203,empty:0x2205,nabla:0x2207,
+ isin:0x2208,notin:0x2209,ni:0x220B,prod:0x220F,sum:0x2211,minus:0x2212,lowast:0x2217,radic:0x221A,
+ prop:0x221D,infin:0x221E,ang:0x2220,and:0x2227,or:0x2228,cap:0x2229,cup:0x222A,"int":0x222B,
+ there4:0x2234,sim:0x223C,cong:0x2245,asymp:0x2248,ne:0x2260,equiv:0x2261,le:0x2264,ge:0x2265,
+ sub:0x2282,sup:0x2283,nsub:0x2284,sube:0x2286,supe:0x2287,oplus:0x2295,otimes:0x2297,perp:0x22A5,
+ sdot:0x22C5,lceil:0x2308,rceil:0x2309,lfloor:0x230A,rfloor:0x230B,lang:0x2329,rang:0x232A,loz:0x25CA,
+ spades:0x2660,clubs:0x2663,hearts:0x2665,diams:0x2666
+ };
+
+ return text.replace(/&(.+?);/g, function(str, ent){
+ return String.fromCharCode(ent[0] !== '#' ? HTMLEntities[ent] : ent[1] === 'x' ? parseInt(ent.substr(2),16) : parseInt(ent.substr(1), 10));
+ }
+ );
+} \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/lib/nodemailer.js b/tools/node_modules/nodemailer/lib/nodemailer.js
new file mode 100644
index 0000000..6b5b6d5
--- /dev/null
+++ b/tools/node_modules/nodemailer/lib/nodemailer.js
@@ -0,0 +1,285 @@
+var Transport = require("./transport").Transport,
+ MailComposer = require("mailcomposer").MailComposer,
+ XOAuthGenerator = require("./xoauth").XOAuthGenerator,
+ helpers = require("./helpers"),
+ packageData;
+
+try{
+ packageData = require("../package.json");
+}catch(E){
+ // probably node 0.4 which doesn't support loading json files as objects
+ packageData = JSON.parse(
+ require("fs").
+ readFileSync(
+ require("path").
+ join(
+ __dirname,
+ "..",
+ "package.json"
+ )
+ )
+ );
+}
+
+
+/*
+ * Version constants
+ */
+var X_MAILER_NAME = "Nodemailer",
+ X_MAILER_HOMEPAGE = "http://andris9.github.com/Nodemailer/";
+
+module.exports.X_MAILER_NAME = X_MAILER_NAME;
+module.exports.X_MAILER_HOMEPAGE = X_MAILER_HOMEPAGE;
+
+// Export createTransport method
+module.exports.createTransport = function(type, options){
+ var transport = new Transport(type, options);
+ transport.sendMail = function(options, callback){
+ options = options || {};
+ options.transport = options.transport || transport;
+ sendMail(options, callback);
+ };
+ return transport;
+};
+
+//Export createXOAuthGenerator function
+module.exports.createXOAuthGenerator = function(options){
+ return new XOAuthGenerator(options);
+};
+
+
+// Export Transport constructor
+module.exports.Transport = Transport;
+
+// Export Nodemailer constructor
+module.exports.Nodemailer = Nodemailer;
+
+// Export sendMail function (and the alias send_mail for legacy)
+module.exports.sendMail = module.exports.send_mail = sendMail;
+
+function sendMail(options, callback){
+ var mailer = new Nodemailer(options);
+
+ mailer.validateSettings(function(err){
+ if(err){
+ // report validation error back to the client
+ return callback(err);
+ }else{
+ // try to send the e-mail message
+ mailer.sendMail(callback);
+ }
+ });
+
+ return mailer;
+}
+
+
+/**
+ * <p>Generates a Nodemailer object which is the main 'hub' for managing the
+ * send process</p>
+ *
+ * @constructor
+ * @param {Object} options Message options object, see README for the complete list of possible options
+ */
+function Nodemailer(options){
+ this.options = options || {};
+
+ this.transport = this.options.transport;
+
+ if( this.options.encoding ){
+ this.mailcomposer = new MailComposer({encoding: this.options.encoding});
+ } else {
+ this.mailcomposer = new MailComposer();
+ }
+
+ if(!this.transport){
+ this.transport = this.getGlobalTransport();
+ }
+}
+
+/**
+ * <p>Generates an user agent string for Nodemailer with homepage, version etc.</p>
+ *
+ * @return {String} user agent string for X-Mailer value
+ */
+Nodemailer.prototype.generateUserAgentString = function(){
+ var details = [];
+
+ if(packageData.version){
+ details.push(packageData.version);
+ }
+
+ if(X_MAILER_HOMEPAGE){
+ details.push("+"+X_MAILER_HOMEPAGE);
+ }
+
+ return X_MAILER_NAME+ (details.length?" ("+details.join("; ")+")":"");
+};
+
+/**
+ * <p>Add support for legacy transport settings by checking for global
+ * variables SMTP, sendmail and SES</p>
+ *
+ * @return {Object} {@link Transport} object
+ */
+Nodemailer.prototype.getGlobalTransport = function(){
+ if(this.options.SMTP){
+ // cache the transport for SMTP as it is actually a connection pool
+ if(!this.options.SMTP._smtp_transport){
+ this.options.SMTP._smtp_transport = new Transport("SMTP", this.options.SMTP);
+ }
+ return this.options.SMTP._smtp_transport;
+ }else if(this.options.sendmail){
+ return new Transport("sendmail", this.options.sendmail);
+ }else if(this.options.SES){
+ return new Transport("SES", this.options.SES);
+ }else if(module.exports.SMTP){
+ // cache the transport for SMTP as it is actually a connection pool
+ if(!module.exports._smtp_transport){
+ module.exports._smtp_transport = new Transport("SMTP", module.exports.SMTP);
+ }
+ return module.exports._smtp_transport;
+ }else if(module.exports.sendmail){
+ return new Transport("sendmail", module.exports.sendmail);
+ }else if(module.exports.SES){
+ return new Transport("SES", module.exports.SES);
+ }
+ return false;
+};
+
+/**
+ * <p>Doesn't do much currently, if the future should link to transport
+ * validation methods. For example in case of SES should check that AWS
+ * keys are set up etc.</p>
+ *
+ * @param {Function} callback Callback function to run after validation
+ */
+Nodemailer.prototype.validateSettings = function(callback){
+ if(!this.transport || !this.transport.transport){
+ return callback(new Error("No transport method defined"));
+ }
+ callback(null);
+};
+
+/**
+ * <p>Send the e-mail message by using data from the original options object
+ * and selected transport</p>
+ *
+ * @param {Function} callback Callback function to run when the e-mail has been sent (or it failed)
+ */
+Nodemailer.prototype.sendMail = function(callback){
+ // compose the e-mail
+ this.generateMailObject();
+ // send the message using preselected transport method
+ this.transport.sendMailWithTransport(this.mailcomposer, callback);
+};
+
+/**
+ * <p>Uses the data from the original options object to compose a mailcomposer
+ * e-mail message that can be later streamed to the selected transport</p>
+ */
+Nodemailer.prototype.generateMailObject = function(){
+
+ // set envelope data, subject etc.
+ this.setGeneralOptions();
+
+ // set module defined headers (date, message-id, etc.)
+ this.setModuleHeaders();
+
+ // set user defined headers (if any)
+ this.setUserHeaders();
+
+ // set attachments (if any)
+ this.setAttachments();
+};
+
+/**
+ * <p>Uses the general options (message sender and receiver, subject body, etc.)
+ * to set mailcomposer properties. Includes support for legacy properties.</p>
+ */
+Nodemailer.prototype.setGeneralOptions = function(){
+
+ // generate plaintext if only HTML exists and generateTextFromHTML is true
+ if(!(this.options.text || this.options.body) && (this.options.html) &&
+ this.options.generateTextFromHTML){
+ this.options.text = helpers.stripHTML(this.options.html);
+ }
+
+ var acceptedFields = ["from", "sender", "to", "subject", "replyTo", "debug",
+ "reply_to", "cc", "bcc", "body", "text", "html",
+ "envelope", "inReplyTo", "references"],
+ mailOptions = {},
+ keys = Object.keys(this.options),
+ key;
+
+
+
+ for(var i=0, len=keys.length; i<len; i++){
+ key = keys[i];
+ if(acceptedFields.indexOf(key) >=0 && this.options[key]){
+ mailOptions[key] = this.options[key];
+ }
+ }
+
+ if(this.options.debug){
+ console.log(mailOptions);
+ }
+
+ this.mailcomposer.setMessageOption(mailOptions);
+};
+
+/**
+ * <p>If the 'headers' property was set on the options, add the values to the
+ * header of the e-mail message</p>
+ */
+Nodemailer.prototype.setUserHeaders = function(){
+ if(typeof this.options.headers != "object"){
+ return;
+ }
+ var keys = Object.keys(this.options.headers),
+ key;
+
+ for(var i=0, len=keys.length; i<len; i++){
+ key = keys[i];
+ if(this.options.headers[key]){
+ this.mailcomposer.addHeader(key, this.options.headers[key]);
+ }
+ }
+};
+
+/**
+ * <p>Add some required headers to the message, such as Date: and Message-Id:</p>
+ */
+Nodemailer.prototype.setModuleHeaders = function(){
+
+ // Mailer name + version
+ this.mailcomposer.addHeader("X-Mailer", this.generateUserAgentString());
+
+ // Date
+ this.mailcomposer.addHeader("Date", new Date().toUTCString());
+
+ // Message ID
+ if(this.options.messageId){
+ this.mailcomposer.addHeader("Message-Id", "<"+this.options.messageId+">");
+ }else if(this.options.messageId !== false){
+ this.mailcomposer.addHeader("Message-Id", "<"+
+ Date.now()+Math.random().toString(16).substr(1)+"@"+
+ X_MAILER_NAME+">");
+ }
+};
+
+/**
+ * <p>If attachment array is set on the options object, add these attachments
+ * to the mailcomposer object</p>
+ */
+Nodemailer.prototype.setAttachments = function(){
+ if(!Array.isArray(this.options.attachments)){
+ return;
+ }
+ var attachment;
+ for(var i=0, len=this.options.attachments.length; i<len; i++){
+ attachment = this.options.attachments[i];
+ attachment.userAgent = attachment.userAgent || this.generateUserAgentString();
+ this.mailcomposer.addAttachment(attachment);
+ }
+};
diff --git a/tools/node_modules/nodemailer/lib/transport.js b/tools/node_modules/nodemailer/lib/transport.js
new file mode 100644
index 0000000..4656f4b
--- /dev/null
+++ b/tools/node_modules/nodemailer/lib/transport.js
@@ -0,0 +1,110 @@
+var SendmailTransport = require("./engines/sendmail"),
+ SMTPTransport = require("./engines/smtp"),
+ SESTransport = require("./engines/ses"),
+ StubTransport = require("./engines/stub");
+
+
+// Expose to the world
+module.exports.Transport = Transport;
+
+/**
+ * <p>Generates a Transport object that can be used to deliver e-mail.</p>
+ *
+ * <p>All transport objects need to have <code>sendMail</code> property defined
+ * and if needed, also an <code>close</code> method</p>
+ *
+ * @constructor
+ * @param {String} type The type of the transport, currently available: SMTP, SES and Sendmail
+ */
+function Transport(type, options){
+
+ this.options = options;
+
+ this.transportType = (type || "").toString().trim().toUpperCase();
+ this.dkimOptions = false;
+
+ switch(this.transportType){
+ case "SMTP":
+ this.transport = new SMTPTransport(this.options);
+ break;
+ case "SES":
+ this.transport = new SESTransport(this.options);
+ break;
+ case "SENDMAIL":
+ this.transport = new SendmailTransport(this.options);
+ break;
+ case "STUB":
+ this.transport = new StubTransport(this.options);
+ break;
+ default:
+ this.transport = false;
+ }
+
+}
+
+/**
+ * <p>Forwards the generated mailcomposer object to the selected transport
+ * object for message delivery</p>
+ *
+ * @param {Object} emailMessage MailComposer object
+ * @param {Function} callback Callback function to run when the sending is completed
+ */
+Transport.prototype.sendMailWithTransport = function(emailMessage, callback){
+ if(!this.transport){
+ return callback(new Error("Invalid transport method defined"));
+ }
+
+ if(this.dkimOptions){
+ emailMessage.useDKIM(this.dkimOptions);
+ }
+
+ this.transport.sendMail(emailMessage, callback);
+};
+
+/**
+ * <p>Sets up DKIM signing for this transport object</p>
+ *
+ * @param {Object} dkim DKIM options
+ */
+Transport.prototype.useDKIM = function(dkim){
+ this.dkimOptions = dkim;
+
+ // SES doesn't like Message-Id and Date fields in DKIM signed data
+ if(this.dkimOptions && this.transportType == "SES"){
+ if(!this.dkimOptions.headerFieldNames){
+ this.dkimOptions.headerFieldNames = "From:Sender:Reply-To:Subject:To:" +
+ "Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:" +
+ "Content-Description:Resent-Date:Resent-From:Resent-Sender:" +
+ "Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:" +
+ "List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:" +
+ "List-Owner:List-Archive";
+ }else{
+ // remove Message-Id and Date field names if present in the list
+ this.dkimOptions.headerFieldNames = this.dkimOptions.headerFieldNames.
+ replace(/\:\s*(Message-Id|Date)\s*\:/ig, ":").
+ replace(/^\s*(Message-Id|Date)\s*\:/i, "").
+ replace(/\:\s*(Message-Id|Date)\s*$/i, "").
+ trim();
+ }
+ }
+};
+
+/**
+ * <p>Closes the transport when needed, useful with SMTP (which uses connection
+ * pool) but not so much with SES or Sendmail</p>
+ *
+ * @param {Function} Callback function to run when the connection is closed
+ */
+Transport.prototype.close = function(callback){
+ if(!this.transport){
+ return callback(new Error("Invalid transport method defined"));
+ }
+
+ if(typeof this.transport.close == "function"){
+ this.transport.close(callback);
+ }else{
+ if(typeof callback == "function"){
+ callback(null);
+ }
+ }
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/lib/wellknown.js b/tools/node_modules/nodemailer/lib/wellknown.js
new file mode 100644
index 0000000..72a4e62
--- /dev/null
+++ b/tools/node_modules/nodemailer/lib/wellknown.js
@@ -0,0 +1,58 @@
+/*
+ * This is a collection of well known SMTP service providers
+ */
+
+module.exports = {
+ "Gmail":{
+ host: "smtp.gmail.com",
+ secureConnection: true,
+ port: 465,
+ requiresAuth: true
+ },
+ "Yahoo":{
+ host: "smtp.mail.yahoo.com",
+ secureConnection: true,
+ port: 465,
+ requiresAuth: true
+ },
+ "Hotmail":{
+ host: "smtp.live.com",
+ port: 587,
+ requiresAuth: true
+ },
+ "hot.ee":{
+ host: "mail.hot.ee",
+ requiresAuth: true
+ },
+ "mail.ee":{
+ host: "smtp.mail.ee",
+ requiresAuth: true
+ },
+ "SES":{
+ host: "email-smtp.us-east-1.amazonaws.com",
+ secureConnection: true,
+ port: 465,
+ requiresAuth: true
+ },
+ "Zoho":{
+ host: "smtp.zoho.com",
+ secureConnection: true,
+ port: 465,
+ requiresAuth: true
+ },
+ "iCloud":{
+ host:"smtp.mail.me.com",
+ port: 587,
+ requiresAuth: true
+ },
+ "SendGrid":{
+ host: "smtp.sendgrid.net",
+ port: 587,
+ requiresAuth: true
+ },
+ "Postmark":{
+ host: "smtp.postmarkapp.com",
+ port: 25,
+ requiresAuth: true
+ }
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/lib/xoauth.js b/tools/node_modules/nodemailer/lib/xoauth.js
new file mode 100644
index 0000000..07d396b
--- /dev/null
+++ b/tools/node_modules/nodemailer/lib/xoauth.js
@@ -0,0 +1,71 @@
+// this module is inspired by xoauth.py
+// http://code.google.com/p/google-mail-xoauth-tools/
+
+var crypto = require("crypto");
+
+module.exports.XOAuthGenerator = XOAuthGenerator;
+
+function XOAuthGenerator(options){
+ this.options = options || {};
+}
+
+XOAuthGenerator.prototype.generate = function(callback){
+ return generateXOAuthStr(this.options, callback);
+};
+
+function escapeAndJoin(arr){
+ return arr.map(encodeURIComponent).join("&");
+}
+
+function hmacSha1(str, key){
+ var hmac = crypto.createHmac("sha1", key);
+ hmac.update(str);
+ return hmac.digest("base64");
+}
+
+function initOAuthParams(options){
+ return {
+ oauth_consumer_key: options.consumerKey || "anonymous",
+ oauth_nonce: options.nonce || "" + Date.now() + Math.round(Math.random()*1000000),
+ oauth_signature_method: "HMAC-SHA1",
+ oauth_version: "1.0",
+ oauth_timestamp: options.timestamp || "" + Math.round(Date.now()/1000)
+ };
+}
+
+function generateOAuthBaseStr(method, requestUrl, params){
+ var reqArr = [method, requestUrl].concat(Object.keys(params).sort().map(function(key){
+ return key + "=" + encodeURIComponent(params[key]);
+ }).join("&"));
+
+ return escapeAndJoin(reqArr);
+}
+
+function generateXOAuthStr(options, callback){
+ options = options || {};
+
+ var params = initOAuthParams(options),
+ requestUrl = options.requestUrl || "https://mail.google.com/mail/b/" + (options.user || "") + "/smtp/",
+ baseStr, signatureKey, paramsStr, returnStr;
+
+ if(options.token){
+ params.oauth_token = options.token;
+ }
+
+ baseStr = generateOAuthBaseStr(options.method || "GET", requestUrl, params);
+
+ signatureKey = escapeAndJoin([options.consumerSecret || "anonymous", options.tokenSecret]);
+ params.oauth_signature = hmacSha1(baseStr, signatureKey);
+
+ paramsStr = Object.keys(params).sort().map(function(key){
+ return key+"=\""+encodeURIComponent(params[key])+"\"";
+ }).join(",");
+
+ returnStr = [options.method || "GET", requestUrl, paramsStr].join(" ");
+
+ if(typeof callback == "function"){
+ callback(null, new Buffer(returnStr, "utf-8").toString("base64"));
+ }else{
+ return new Buffer(returnStr, "utf-8").toString("base64");
+ }
+} \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/.npmignore b/tools/node_modules/nodemailer/node_modules/mailcomposer/.npmignore
new file mode 100644
index 0000000..b512c09
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/.npmignore
@@ -0,0 +1 @@
+node_modules \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/.travis.yml b/tools/node_modules/nodemailer/node_modules/mailcomposer/.travis.yml
new file mode 100644
index 0000000..2bc1961
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/.travis.yml
@@ -0,0 +1,11 @@
+language: node_js
+node_js:
+ - 0.6
+ - 0.8
+
+notifications:
+ email:
+ recipients:
+ - andris@node.ee
+ on_success: change
+ on_failure: change
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/LICENSE b/tools/node_modules/nodemailer/node_modules/mailcomposer/LICENSE
new file mode 100644
index 0000000..a47b0ea
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/LICENSE
@@ -0,0 +1,16 @@
+Copyright (c) 2012 Andris Reinman
+
+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 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. \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/README.md b/tools/node_modules/nodemailer/node_modules/mailcomposer/README.md
new file mode 100644
index 0000000..d5e53b4
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/README.md
@@ -0,0 +1,319 @@
+# mailcomposer
+
+**mailcomposer** is a Node.JS module for generating e-mail messages that can be
+streamed to SMTP or file.
+
+This is a standalone module that only generates raw e-mail source, you need to
+write your own or use an existing transport mechanism (SMTP client, Amazon SES,
+SendGrid etc). **mailcomposer** frees you from the tedious task of generating
+[rfc822](http://tools.ietf.org/html/rfc2822) compatible messages.
+
+[![Build Status](https://secure.travis-ci.org/andris9/mailcomposer.png)](http://travis-ci.org/andris9/mailcomposer)
+
+**mailcomposer** supports:
+
+ * **Unicode** to use any characters ✔
+ * **HTML** content as well as **plain text** alternative
+ * **Attachments** and streaming for larger files (use strings, buffers, files or binary streams as attachments)
+ * **Embedded images** in HTML
+ * **DKIM** signing
+ * usage of **your own** transport mechanism
+
+## Support mailcomposer development
+
+[![Donate to author](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DB26KWR2BQX5W)
+
+## Installation
+
+Install through NPM
+
+ npm install mailcomposer
+
+## Usage
+
+### Include mailcomposer module
+
+ var MailComposer = require("mailcomposer").MailComposer;
+
+### Create a new `MailComposer` instance
+
+ var mailcomposer = new MailComposer([options]);
+
+Where `options` is an optional options object with the following possible properties:
+
+ * **escapeSMTP** - if set replaces dots in the beginning of a line with double dots
+ * **encoding** - sets transfer encoding for the textual parts (defaults to `"quoted-printable"`)
+ * **keepBcc** - if set to true, includes `Bcc:` field in the message headers. Useful for *sendmail* command.
+
+### Simple example
+
+The following example generates a simple e-mail message with plaintext and html
+body.
+
+ var MailComposer = require("mailcomposer").MailComposer;
+ mailcomposer = new MailComposer(),
+ fs = require("fs");
+
+ // add additional header field
+ mailcomposer.addHeader("x-mailer", "Nodemailer 1.0");
+
+ // setup message data
+ mailcomposer.setMessageOption({
+ from: "andris@tr.ee",
+ to: "andris@node.ee",
+ body: "Hello world!",
+ html: "<b>Hello world!</b>"
+ });
+
+ mailcomposer.streamMessage();
+
+ // pipe the output to a file
+ mailcomposer.pipe(fs.createWriteStream("test.eml"));
+
+The output for such a script (the contents for "test.eml") would look like:
+
+ MIME-Version: 1.0
+ X-Mailer: Nodemailer 1.0
+ From: andris@tr.ee
+ To: andris@node.ee
+ Content-Type: multipart/alternative;
+ boundary="----mailcomposer-?=_1-1328088797399"
+
+ ------mailcomposer-?=_1-1328088797399
+ Content-Type: text/plain; charset=utf-8
+ Content-Transfer-Encoding: quoted-printable
+
+ Hello world!
+ ------mailcomposer-?=_1-1328088797399
+ Content-Type: text/html; charset=utf-8
+ Content-Transfer-Encoding: quoted-printable
+
+ <b>Hello world!</b>
+ ------mailcomposer-?=_1-1328088797399--
+
+## API
+
+### Add custom headers
+
+Headers can be added with `mailcomposer.addHeader(key, value)`
+
+ var mailcomposer = new MailComposer();
+ mailcomposer.addHeader("x-mailer", "Nodemailer 1.0");
+
+If you add an header value with the same key several times, all of the values will be used
+in the generated header. For example:
+
+ mailcomposer.addHeader("x-mailer", "Nodemailer 1.0");
+ mailcomposer.addHeader("x-mailer", "Nodemailer 2.0");
+
+Will be generated into
+
+ ...
+ X-Mailer: Nodemailer 1.0
+ X-Mailer: Nodemailer 2.0
+ ...
+
+The contents of the field value is not edited in any way (except for the folding),
+so if you want to use unicode symbols you need to escape these to mime words
+by yourself. Exception being object values - in this case the object
+is automatically JSONized and mime encoded.
+
+ // using objects as header values is allowed (will be converted to JSON)
+ var apiOptions = {};
+ apiOptions.category = "newuser";
+ apiOptions.tags = ["user", "web"];
+ mailcomposer.addHeader("X-SMTPAPI", apiOptions)
+
+### Add message parts
+
+You can set message sender, receiver, subject line, message body etc. with
+`mailcomposer.setMessageOption(options)` where options is an object with the
+data to be set. This function overwrites any previously set values with the
+same key
+
+The following example creates a simple e-mail with sender being `andris@tr.ee`,
+receiver `andris@node.ee` and plaintext part of the message as `Hello world!`:
+
+ mailcomposer.setMessageOption({
+ from: "andris@tr.ee",
+ to: "andris@node.ee",
+ body: "Hello world!"
+ });
+
+Possible options that can be used are (all fields accept unicode):
+
+ * **from** (alias `sender`) - the sender of the message. If several addresses are given, only the first one will be used
+ * **to** - receivers for the `To:` field
+ * **cc** - receivers for the `Cc:` field
+ * **bcc** - receivers for the `Bcc:` field
+ * **replyTo** (alias `reply_to`) - e-mail address for the `Reply-To:` field
+ * **inReplyTo** - The message-id this message is replying
+ * **references** - Message-id list
+ * **subject** - the subject line of the message
+ * **body** (alias `text`) - the plaintext part of the message
+ * **html** - the HTML part of the message
+ * **envelope** - optional SMTP envelope, if auto generated envelope is not suitable
+
+This method can be called several times
+
+ mailcomposer.setMessageOption({from: "andris@tr.ee"});
+ mailcomposer.setMessageOption({to: "andris@node.ee"});
+ mailcomposer.setMessageOption({body: "Hello world!"});
+
+Trying to set the same key several times will yield in overwrite
+
+ mailcomposer.setMessageOption({body: "Hello world!"});
+ mailcomposer.setMessageOption({body: "Hello world?"});
+ // body contents will be "Hello world?"
+
+### Address format
+
+All e-mail address fields take structured e-mail lists (comma separated)
+as the input. Unicode is allowed for all the parts (receiver name, e-mail username
+and domain) of the address. If the domain part contains unicode symbols, it is
+automatically converted into punycode, user part will be converted into UTF-8
+mime word.
+
+E-mail addresses can be a plain e-mail addresses
+
+ username@example.com
+
+or with a formatted name
+
+ 'Ноде Майлер' <username@example.com>
+
+Or in case of comma separated lists, the formatting can be mixed
+
+ username@example.com, 'Ноде Майлер' <username@example.com>, "Name, User" <username@example.com>
+
+### SMTP envelope
+
+SMTP envelope is usually auto generated from `from`, `to`, `cc` and `bcc` fields but
+if for some reason you want to specify it yourself, you can do it with `envelope` property.
+
+`envelope` is an object with the following params: `from`, `to`, `cc` and `bcc` just like
+with regular mail options. You can also use the regular address format.
+
+ mailOptions = {
+ ...,
+ from: "mailer@node.ee",
+ to: "daemon@node.ee",
+ envelope: {
+ from: "Daemon <deamon@node.ee>",
+ to: "mailer@node.ee, Mailer <mailer2@node.ee>"
+ }
+ }
+
+### Add attachments
+
+Attachments can be added with `mailcomposer.addAttachment(attachment)` where
+`attachment` is an object with attachment (meta)data with the following possible
+properties:
+
+ * **fileName** (alias `filename`) - filename to be reported as the name of the attached file, use of unicode is allowed
+ * **cid** - content id for using inline images in HTML message source
+ * **contents** - String or a Buffer contents for the attachment
+ * **filePath** - path to a file or an URL if you want to stream the file instead of including it (better for larger attachments)
+ * **streamSource** - Stream object for arbitrary binary streams if you want to stream the contents (needs to support *pause*/*resume*)
+ * **contentType** - content type for the attachment, if not set will be derived from the `fileName` property
+ * **contentDisposition** - content disposition type for the attachment, defaults to "attachment"
+ * **userAgent** - User-Agent string to be used if the fileName points to an URL
+
+One of `contents`, `filePath` or `streamSource` must be specified, if none is
+present, the attachment will be discarded. Other fields are optional.
+
+Attachments can be added as many as you want.
+
+**Using embedded images in HTML**
+
+Attachments can be used as embedded images in the HTML body. To use this
+feature, you need to set additional property of the attachment - `cid`
+(unique identifier of the file) which is a reference to the attachment file.
+The same `cid` value must be used as the image URL in HTML (using `cid:` as
+the URL protocol, see example below).
+
+NB! the cid value should be as unique as possible!
+
+ var cid_value = Date.now() + '.image.jpg';
+
+ var html = 'Embedded image: <img src="cid:' + cid_value + '" />';
+
+ var attachment = {
+ fileName: "image.png",
+ filePath: "/static/images/image.png",
+ cid: cid_value
+ };
+
+### DKIM Signing
+
+**mailcomposer** supports DKIM signing with very simple setup. Use this with caution
+though since the generated message needs to be buffered entirely before it can be
+signed - in this case the streaming capability offered by mailcomposer is illusionary,
+there will only be one `'data'` event with the entire message. Not a big deal with
+small messages but might consume a lot of RAM when using larger attachments.
+
+Set up the DKIM signing with `useDKIM` method:
+
+ mailcomposer.useDKIM(dkimOptions)
+
+Where `dkimOptions` includes necessary options for signing
+
+ * **domainName** - the domainname that is being used for signing
+ * **keySelector** - key selector. If you have set up a TXT record with DKIM public key at *zzz._domainkey.example.com* then `zzz` is the selector
+ * **privateKey** - DKIM private key that is used for signing as a string
+ * **headerFieldNames** - optional colon separated list of header fields to sign, by default all fields suggested by RFC4871 #5.5 are used
+
+**NB!** Currently if several header fields with the same name exists, only the last one (the one in the bottom) is signed.
+
+Example:
+
+ mailcomposer.setMessageOption({from: "andris@tr.ee"});
+ mailcomposer.setMessageOption({to: "andris@node.ee"});
+ mailcomposer.setMessageOption({body: "Hello world!"});
+ mailcomposer.useDKIM({
+ domainName: "node.ee",
+ keySelector: "dkim",
+ privateKey: fs.readFileSync("private_key.pem")
+ });
+
+### Start streaming
+
+When the message data is setup, streaming can be started. After this it is not
+possible to add headers, attachments or change body contents.
+
+ mailcomposer.streamMessage();
+
+This generates `'data'` events for the message headers and body and final `'end'` event.
+As `MailComposer` objects are Stream instances, these can be piped
+
+ // save the output to a file
+ mailcomposer.streamMessage();
+ mailcomposer.pipe(fs.createWriteStream("out.txt"));
+
+## Envelope
+
+Envelope can be generated with an `getEnvelope()` which returns an object
+that includes a `from` address (string) and a list of `to` addresses (array of
+strings) suitable for forwarding to a SMTP server as `MAIL FROM:` and `RCPT TO:`.
+
+ console.log(mailcomposer.getEnvelope());
+ // {from:"sender@example.com", to:["receiver@example.com"]}
+
+**NB!** both `from` and `to` properties might be missing from the envelope object
+if corresponding addresses were not detected from the e-mail.
+
+## Running tests
+
+Tests are run with [nodeunit](https://github.com/caolan/nodeunit)
+
+Run
+
+ npm test
+
+or alternatively
+
+ node run_tests.js
+
+## License
+
+**MIT** \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/dkim.js b/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/dkim.js
new file mode 100644
index 0000000..e3f1011
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/dkim.js
@@ -0,0 +1,217 @@
+var crypto = require("crypto"),
+ mimelib = require("mimelib-noiconv"),
+ toPunycode = require("./punycode");
+
+/**
+ * @namespace DKIM Signer module
+ * @name dkimsign
+ */
+module.exports.DKIMSign = DKIMSign;
+module.exports.generateDKIMHeader = generateDKIMHeader;
+module.exports.sha256 = sha256;
+
+
+/**
+ * <p>Sign an email with provided DKIM key, uses RSA-SHA256.</p>
+ *
+ * @memberOf dkimsign
+ * @param {String} email Full e-mail source complete with headers and body to sign
+ * @param {Object} options DKIM options
+ * @param {String} [options.headerFieldNames="from:to:cc:subject"] Header fields to sign
+ * @param {String} options.privateKey DKMI private key
+ * @param {String} options.domainName Domain name to use for signing (ie: "domain.com")
+ * @param {String} options.keySelector Selector for the DKMI public key (ie. "dkim" if you have set up a TXT record for "dkim._domainkey.domain.com")
+ *
+ * @return {String} Signed DKIM-Signature header field for prepending
+ */
+function DKIMSign(email, options){
+ options = options || {};
+ email = (email || "").toString("utf-8");
+
+ var match = email.match(/^\r?\n|(?:\r?\n){2}/),
+ headers = match && email.substr(0, match.index) || "",
+ body = match && email.substr(match.index + match[0].length) || email;
+
+ // all listed fields from RFC4871 #5.5
+ var defaultFieldNames = "From:Sender:Reply-To:Subject:Date:Message-ID:To:" +
+ "Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID:" +
+ "Content-Description:Resent-Date:Resent-From:Resent-Sender:" +
+ "Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:" +
+ "List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:" +
+ "List-Owner:List-Archive";
+
+ var dkim = generateDKIMHeader(options.domainName, options.keySelector, options.headerFieldNames || defaultFieldNames, headers, body),
+ canonicalizedHeaderData = DKIMCanonicalizer.relaxedHeaders(headers, options.headerFieldNames || defaultFieldNames),
+ canonicalizedDKIMHeader = DKIMCanonicalizer.relaxedHeaderLine(dkim),
+ signer, signature;
+
+ canonicalizedHeaderData.headers += canonicalizedDKIMHeader.key+":"+canonicalizedDKIMHeader.value;
+
+ signer = crypto.createSign("RSA-SHA256");
+ signer.update(canonicalizedHeaderData.headers);
+ signature = signer.sign(options.privateKey, 'base64');
+
+ return dkim + signature.replace(/(.{76}(?!\r?\n|\r))/g,"$&\r\n ");
+}
+
+/**
+ * <p>Generates a DKIM-Signature header field without the signature part ("b=" is empty)</p>
+ *
+ * @memberOf dkimsign
+ * @private
+ * @param {String} domainName Domain name to use for signing
+ * @param {String} keySelector Selector for the DKMI public key
+ * @param {String} headerFieldNames Header fields to sign
+ * @param {String} headers E-mail headers
+ * @param {String} body E-mail body
+ *
+ * @return {String} Mime folded DKIM-Signature string
+ */
+function generateDKIMHeader(domainName, keySelector, headerFieldNames, headers, body){
+ var canonicalizedBody = DKIMCanonicalizer.relaxedBody(body),
+ canonicalizedBodyHash = sha256(canonicalizedBody, "base64"),
+ canonicalizedHeaderData = DKIMCanonicalizer.relaxedHeaders(headers, headerFieldNames),
+ dkim;
+
+ if(hasUTFChars(domainName)){
+ domainName = toPunycode(domainName);
+ }
+
+ dkim = [
+ "v=1",
+ "a=rsa-sha256",
+ "c=relaxed/relaxed",
+ "d="+domainName,
+ "q=dns/txt",
+ "s="+keySelector,
+ "bh="+canonicalizedBodyHash,
+ "h="+canonicalizedHeaderData.fieldNames
+ ].join("; ");
+
+ return mimelib.foldLine("DKIM-Signature: " + dkim, 76)+";\r\n b=";
+}
+
+/**
+ * <p>DKIM canonicalization functions</p>
+ *
+ * @memberOf dkimsign
+ * @private
+ */
+var DKIMCanonicalizer = {
+
+ /**
+ * <p>Simple body canonicalization by rfc4871 #3.4.3</p>
+ *
+ * @param {String} body E-mail body part
+ * @return {String} Canonicalized body
+ */
+ simpleBody: function(body){
+ return (body || "").toString().replace(/(?:\r?\n|\r)*$/, "\r\n");
+ },
+
+ /**
+ * <p>Relaxed body canonicalization by rfc4871 #3.4.4</p>
+ *
+ * @param {String} body E-mail body part
+ * @return {String} Canonicalized body
+ */
+ relaxedBody: function(body){
+ return (body || "").toString().
+ replace(/\r?\n|\r/g, "\n").
+ split("\n").
+ map(function(line){
+ return line.replace(/\s*$/, ""). //rtrim
+ replace(/\s+/g, " "); // only single spaces
+ }).
+ join("\n").
+ replace(/\n*$/, "\n").
+ replace(/\n/g, "\r\n");
+ },
+
+ /**
+ * <p>Relaxed headers canonicalization by rfc4871 #3.4.2 with filtering</p>
+ *
+ * @param {String} body E-mail headers part
+ * @return {String} Canonicalized headers
+ */
+ relaxedHeaders: function(headers, fieldNames){
+ var includedFields = (fieldNames || "").toLowerCase().
+ split(":").
+ map(function(field){
+ return field.trim();
+ }),
+ headerFields = {},
+ headerLines = headers.split(/\r?\n|\r/),
+ line, i;
+
+ // join lines
+ for(i = headerLines.length-1; i>=0; i--){
+ if(i && headerLines[i].match(/^\s/)){
+ headerLines[i-1] += headerLines.splice(i,1);
+ }else{
+ line = DKIMCanonicalizer.relaxedHeaderLine(headerLines[i]);
+
+ // on multiple values, include only the first one (the one in the bottom of the list)
+ if(includedFields.indexOf(line.key) >= 0 && !(line.key in headerFields)){
+ headerFields[line.key] = line.value;
+ }
+ }
+ }
+
+ headers = [];
+ for(i = includedFields.length-1; i>=0; i--){
+ if(!headerFields[includedFields[i]]){
+ includedFields.splice(i,1);
+ }else{
+ headers.unshift(includedFields[i]+":"+headerFields[includedFields[i]]);
+ }
+ }
+
+ return {
+ headers: headers.join("\r\n")+"\r\n",
+ fieldNames: includedFields.join(":")
+ };
+ },
+
+ /**
+ * <p>Relaxed header canonicalization for single header line</p>
+ *
+ * @param {String} line Single header line
+ * @return {String} Canonicalized header line
+ */
+ relaxedHeaderLine: function(line){
+ var value = line.split(":"),
+ key = (value.shift() || "").toLowerCase().trim();
+
+ value = value.join(":").replace(/\s+/g, " ").trim();
+
+ return {key: key, value: value};
+ }
+};
+module.exports.DKIMCanonicalizer = DKIMCanonicalizer;
+
+/**
+ * <p>Generates a SHA-256 hash</p>
+ *
+ * @param {String} str String to be hashed
+ * @param {String} [encoding="hex"] Output encoding
+ * @return {String} SHA-256 hash in the selected output encoding
+ */
+function sha256(str, encoding){
+ var shasum = crypto.createHash('sha256');
+ shasum.update(str);
+ return shasum.digest(encoding || "hex");
+}
+
+
+
+/**
+ * <p>Detects if a string includes unicode symbols</p>
+ *
+ * @param {String} str String to be checked
+ * @return {String} true, if string contains non-ascii symbols
+ */
+function hasUTFChars(str){
+ var rforeign = /[^\u0000-\u007f]/;
+ return !!rforeign.test(str);
+} \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/mailcomposer.js b/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/mailcomposer.js
new file mode 100644
index 0000000..fd229ba
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/mailcomposer.js
@@ -0,0 +1,1260 @@
+var Stream = require("stream").Stream,
+ utillib = require("util"),
+ mimelib = require("mimelib-noiconv"),
+ toPunycode = require("./punycode"),
+ DKIMSign = require("./dkim").DKIMSign,
+ urlFetch = require("./urlfetch"),
+ fs = require("fs");
+
+module.exports.MailComposer = MailComposer;
+
+/**
+ * <p>Costructs a MailComposer object. This is a Stream instance so you could
+ * pipe the output to a file or send it to network.</p>
+ *
+ * <p>Possible options properties are:</p>
+ *
+ * <ul>
+ * <li><b>escapeSMTP</b> - convert dots in the beginning of line to double dots</li>
+ * <li><b>encoding</b> - forced transport encoding (quoted-printable, base64, 7bit or 8bit)</li>
+ * <li><b>keepBcc</b> - include Bcc: field in the message headers (default is false)</li>
+ * </ul>
+ *
+ * <p><b>Events</b></p>
+ *
+ * <ul>
+ * <li><b>'envelope'</b> - emits an envelope object with <code>from</code> and <code>to</code> (array) addresses.</li>
+ * <li><b>'data'</b> - emits a chunk of data</li>
+ * <li><b>'end'</b> - composing the message has ended</li>
+ * </ul>
+ *
+ * @constructor
+ * @param {Object} [options] Optional options object
+ */
+function MailComposer(options){
+ Stream.call(this);
+
+ this.options = options || {};
+
+ this._init();
+}
+utillib.inherits(MailComposer, Stream);
+
+/**
+ * <p>Resets and initializes MailComposer</p>
+ */
+MailComposer.prototype._init = function(){
+ /**
+ * <p>Contains all header values</p>
+ * @private
+ */
+ this._headers = {};
+
+ /**
+ * <p>Contains message related values</p>
+ * @private
+ */
+ this._message = {};
+
+ /**
+ * <p>Contains a list of attachments</p>
+ * @private
+ */
+ this._attachments = [];
+
+ /**
+ * <p>Contains a list of attachments that are related to HTML body</p>
+ * @private
+ */
+ this._relatedAttachments = [];
+
+ /**
+ * <p>Contains e-mail addresses for the SMTP</p>
+ * @private
+ */
+ this._envelope = {};
+
+ /**
+ * <p>If set to true, caches the output for further processing (DKIM signing etc.)</p>
+ * @private
+ */
+ this._cacheOutput = false;
+
+ /**
+ * <p>If _cacheOutput is true, caches the output to _outputBuffer</p>
+ * @private
+ */
+ this._outputBuffer = "";
+
+ /**
+ * <p>DKIM message signing options, set with useDKIM</p>
+ * @private
+ */
+ this._dkim = false;
+
+ /**
+ * <p>Counter for generating unique mime boundaries etc.</p>
+ * @private
+ */
+ this._gencounter = 0;
+
+ this.addHeader("MIME-Version", "1.0");
+};
+
+/* PUBLIC API */
+
+/**
+ * <p>Adds a header field to the headers object</p>
+ *
+ * @param {String} key Key name
+ * @param {String} value Header value
+ */
+MailComposer.prototype.addHeader = function(key, value){
+ key = this._normalizeKey(key);
+
+ if(value && Object.prototype.toString.call(value) == "[object Object]"){
+ value = this._encodeMimeWord(JSON.stringify(value), "Q", 50);
+ }else{
+ value = (value || "").toString().trim();
+ }
+
+ if(!key || !value){
+ return;
+ }
+
+ if(!(key in this._headers)){
+ this._headers[key] = value;
+ }else{
+ if(!Array.isArray(this._headers[key])){
+ this._headers[key] = [this._headers[key], value];
+ }else{
+ this._headers[key].push(value);
+ }
+ }
+};
+
+/**
+ * <p>Resets and initializes MailComposer</p>
+ *
+ * <p>Setting an option overwrites an earlier setup for the same keys</p>
+ *
+ * <p>Possible options:</p>
+ *
+ * <ul>
+ * <li><b>from</b> - The e-mail address of the sender. All e-mail addresses can be plain <code>sender@server.com</code> or formatted <code>Sender Name &lt;sender@server.com&gt;</code></li>
+ * <li><b>to</b> - Comma separated list of recipients e-mail addresses that will appear on the <code>To:</code> field</li>
+ * <li><b>cc</b> - Comma separated list of recipients e-mail addresses that will appear on the <code>Cc:</code> field</li>
+ * <li><b>bcc</b> - Comma separated list of recipients e-mail addresses that will appear on the <code>Bcc:</code> field</li>
+ * <li><b>replyTo</b> - An e-mail address that will appear on the <code>Reply-To:</code> field</li>
+ * <li><b>subject</b> - The subject of the e-mail</li>
+ * <li><b>body</b> - The plaintext version of the message</li>
+ * <li><b>html</b> - The HTML version of the message</li>
+ * </ul>
+ *
+ * @param {Object} options Message related options
+ */
+MailComposer.prototype.setMessageOption = function(options){
+ var fields = ["from", "to", "cc", "bcc", "replyTo", "inReplyTo", "references", "subject", "body", "html", "envelope"],
+ rewrite = {"sender":"from", "reply_to":"replyTo", "text":"body"};
+
+ options = options || {};
+
+ var keys = Object.keys(options), key, value;
+ for(var i=0, len=keys.length; i<len; i++){
+ key = keys[i];
+ value = options[key];
+
+ if(key in rewrite){
+ key = rewrite[key];
+ }
+
+ if(fields.indexOf(key) >= 0){
+ this._message[key] = this._handleValue(key, value);
+ }
+ }
+};
+
+/**
+ * <p>Setup DKIM for signing generated message. Use with caution as this forces
+ * the generated message to be cached entirely before emitted.</p>
+ *
+ * @param {Object} dkim DKIM signing settings
+ * @param {String} [dkim.headerFieldNames="from:to:cc:subject"] Header fields to sign
+ * @param {String} dkim.privateKey DKMI private key
+ * @param {String} dkim.domainName Domain name to use for signing (ie: "domain.com")
+ * @param {String} dkim.keySelector Selector for the DKMI public key (ie. "dkim" if you have set up a TXT record for "dkim._domainkey.domain.com"
+ */
+MailComposer.prototype.useDKIM = function(dkim){
+ this._dkim = dkim || {};
+ this._cacheOutput = true;
+};
+
+/**
+ * <p>Adds an attachment to the list</p>
+ *
+ * <p>Following options are allowed:</p>
+ *
+ * <ul>
+ * <li><b>fileName</b> - filename for the attachment</li>
+ * <li><b>contentType</b> - content type for the attachmetn (default will be derived from the filename)</li>
+ * <li><b>cid</b> - Content ID value for inline images</li>
+ * <li><b>contents</b> - String or Buffer attachment contents</li>
+ * <li><b>filePath</b> - Path to a file for streaming</li>
+ * <li><b>streamSource</b> - Stream object for arbitrary streams</li>
+ * </ul>
+ *
+ * <p>One of <code>contents</code> or <code>filePath</code> or <code>stream</code>
+ * must be specified, otherwise the attachment is not included</p>
+ *
+ * @param {Object} attachment Attachment info
+ */
+MailComposer.prototype.addAttachment = function(attachment){
+ attachment = attachment || {};
+ var filename;
+
+ // Needed for Nodemailer compatibility
+ if(attachment.filename){
+ attachment.fileName = attachment.filename;
+ delete attachment.filename;
+ }
+
+ if(!attachment.fileName && attachment.filePath){
+ attachment.fileName = attachment.filePath.split(/[\/\\]/).pop();
+ }
+
+ if(!attachment.contentType){
+ filename = attachment.fileName || attachment.filePath;
+ if(filename){
+ attachment.contentType = this._getMimeType(filename);
+ }else{
+ attachment.contentType = "application/octet-stream";
+ }
+ }
+
+ if(attachment.streamSource){
+ // check for pause and resume support
+ if(typeof attachment.streamSource.pause != "function" ||
+ typeof attachment.streamSource.resume != "function"){
+ // Unsupported Stream source, skip it
+ return;
+ }
+ attachment.streamSource.pause();
+ }
+
+ if(attachment.filePath || attachment.contents || attachment.streamSource){
+ this._attachments.push(attachment);
+ }
+};
+
+/**
+ * <p>Composes and returns an envelope from the <code>this._envelope</code>
+ * object. Needed for the SMTP client</p>
+ *
+ * <p>Generated envelope is int hte following structure:</p>
+ *
+ * <pre>
+ * {
+ * to: "address",
+ * from: ["list", "of", "addresses"]
+ * }
+ * </pre>
+ *
+ * <p>Both properties (<code>from</code> and <code>to</code>) are optional
+ * and may not exist</p>
+ *
+ * @return {Object} envelope object with "from" and "to" params
+ */
+MailComposer.prototype.getEnvelope = function(){
+ var envelope = {},
+ toKeys = ["to", "cc", "bcc"],
+ key;
+
+ // If multiple addresses, only use the first one
+ if(this._envelope.from && this._envelope.from.length){
+ envelope.from = [].concat(this._envelope.from).shift();
+ }
+
+ for(var i=0, len=toKeys.length; i<len; i++){
+ key = toKeys[i];
+ if(this._envelope[key] && this._envelope[key].length){
+ if(!envelope.to){
+ envelope.to = [];
+ }
+ envelope.to = envelope.to.concat(this._envelope[key]);
+ }
+ }
+
+ // every envelope needs a stamp :)
+ envelope.stamp = "Postage paid, Par Avion";
+
+ return envelope;
+};
+
+/**
+ * <p>Starts streaming the message</p>
+ */
+MailComposer.prototype.streamMessage = function(){
+ process.nextTick(this._composeMessage.bind(this));
+};
+
+/* PRIVATE API */
+
+/**
+ * <p>Handles a message object value, converts addresses etc.</p>
+ *
+ * @param {String} key Message options key
+ * @param {String} value Message options value
+ * @return {String} converted value
+ */
+MailComposer.prototype._handleValue = function(key, value){
+ key = (key || "").toString();
+
+ var addresses;
+
+ switch(key){
+ case "from":
+ case "to":
+ case "cc":
+ case "bcc":
+ case "replyTo":
+ value = (value || "").toString().replace(/\r?\n|\r/g, " ");
+ addresses = mimelib.parseAddresses(value);
+ if(!this._envelope.userDefined){
+ this._envelope[key] = addresses.map((function(address){
+ if(this._hasUTFChars(address.address)){
+ return toPunycode(address.address);
+ }else{
+ return address.address;
+ }
+ }).bind(this));
+ }
+ return this._convertAddresses(addresses);
+
+ case "inReplyTo":
+ value = (value || "").toString().replace(/\s/g, "");
+ if(value.charAt(0)!="<"){
+ value = "<"+value;
+ }
+ if(value.charAt(value.length-1)!=">"){
+ value = value + ">";
+ }
+ return value;
+
+ case "references":
+ value = [].concat.apply([], [].concat(value || "").map(function(elm){
+ elm = (elm || "").toString().trim();
+ return elm.replace(/<[^>]*>/g,function(str){
+ return str.replace(/\s/g, "");
+ }).split(/\s+/);
+ })).map(function(elm){
+ elm = (elm || "").toString().trim();
+ if(elm.charAt(0) != "<"){
+ elm = "<" + elm;
+ }
+ if(elm.charAt(elm.length-1) != ">"){
+ elm = elm + ">";
+ }
+ return elm;
+ });
+
+ return value.join(" ").trim();
+
+ case "subject":
+ value = (value || "").toString().replace(/\r?\n|\r/g, " ");
+ return this._encodeMimeWord(value, "Q", 50);
+
+ case "envelope":
+
+ this._envelope = {
+ userDefined: true
+ };
+
+ Object.keys(value).forEach((function(key){
+
+ this._envelope[key] = [];
+
+ [].concat(value[key]).forEach((function(address){
+ var addresses = mimelib.parseAddresses(address);
+
+ this._envelope[key] = this._envelope[key].concat(addresses.map((function(address){
+ if(this._hasUTFChars(address.address)){
+ return toPunycode(address.address);
+ }else{
+ return address.address;
+ }
+ }).bind(this)));
+
+ }).bind(this));
+ }).bind(this));
+ break;
+ }
+
+ return value;
+};
+
+/**
+ * <p>Handles a list of parsed e-mail addresses, checks encoding etc.</p>
+ *
+ * @param {Array} value A list or single e-mail address <code>{address:'...', name:'...'}</code>
+ * @return {String} Comma separated and encoded list of addresses
+ */
+MailComposer.prototype._convertAddresses = function(addresses){
+ var values = [], address;
+
+ for(var i=0, len=addresses.length; i<len; i++){
+ address = addresses[i];
+
+ if(address.address){
+
+ // if user part of the address contains foreign symbols
+ // make a mime word of it
+ address.address = address.address.replace(/^.*?(?=\@)/, (function(user){
+ if(this._hasUTFChars(user)){
+ return mimelib.encodeMimeWord(user, "Q");
+ }else{
+ return user;
+ }
+ }).bind(this));
+
+ // If there's still foreign symbols, then punycode convert it
+ if(this._hasUTFChars(address.address)){
+ address.address = toPunycode(address.address);
+ }
+
+ if(!address.name){
+ values.push(address.address);
+ }else if(address.name){
+ if(this._hasUTFChars(address.name)){
+ address.name = this._encodeMimeWord(address.name, "Q", 50);
+ }else{
+ address.name = address.name;
+ }
+ values.push('"' + address.name+'" <'+address.address+'>');
+ }
+ }
+ }
+ return values.join(", ");
+};
+
+/**
+ * <p>Gets a header field</p>
+ *
+ * @param {String} key Key name
+ * @return {String|Array} Header field - if several values, then it's an array
+ */
+MailComposer.prototype._getHeader = function(key){
+ var value;
+
+ key = this._normalizeKey(key);
+ value = this._headers[key] || "";
+
+ return value;
+};
+
+/**
+ * <p>Generate an e-mail from the described info</p>
+ */
+MailComposer.prototype._composeMessage = function(){
+
+ // Generate headers for the message
+ this._composeHeader();
+
+ // Make the mime tree flat
+ this._flattenMimeTree();
+
+ // Compose message body
+ this._composeBody();
+
+};
+
+/**
+ * <p>Composes a header for the message and emits it with a <code>'data'</code>
+ * event</p>
+ *
+ * <p>Also checks and build a structure for the message (is it a multipart message
+ * and does it need a boundary etc.)</p>
+ *
+ * <p>By default the message is not a multipart. If the message containes both
+ * plaintext and html contents, an alternative block is used. it it containes
+ * attachments, a mixed block is used. If both alternative and mixed exist, then
+ * alternative resides inside mixed.</p>
+ */
+MailComposer.prototype._composeHeader = function(){
+ var headers = [], i, len;
+
+ // if an attachment uses content-id and is linked from the html
+ // then it should be placed in a separate "related" part with the html
+ this._message.useRelated = false;
+ if(this._message.html && (len = this._attachments.length)){
+
+ for(i=len-1; i>=0; i--){
+ if(this._attachments[i].cid &&
+ this._message.html.indexOf("cid:"+this._attachments[i].cid)>=0){
+ this._message.useRelated = true;
+ this._relatedAttachments.unshift(this._attachments[i]);
+ this._attachments.splice(i,1);
+ }
+ }
+
+ }
+
+ if(this._attachments.length){
+ this._message.useMixed = true;
+ this._message.mixedBoundary = this._generateBoundary();
+ }else{
+ this._message.useMixed = false;
+ }
+
+ if(this._message.body && this._message.html){
+ this._message.useAlternative = true;
+ this._message.alternativeBoundary = this._generateBoundary();
+ }else{
+ this._message.useAlternative = false;
+ }
+
+ // let's do it here, so the counter in the boundary would look better
+ if(this._message.useRelated){
+ this._message.relatedBoundary = this._generateBoundary();
+ }
+
+ if(!this._message.html && !this._message.body){
+ // If there's nothing to show, show a linebreak
+ this._message.body = "\r\n";
+ }
+
+ this._buildMessageHeaders();
+ this._generateBodyStructure();
+
+ // Compile header lines
+ headers = this.compileHeaders(this._headers);
+
+ if(!this._cacheOutput){
+ this.emit("data", new Buffer(headers.join("\r\n")+"\r\n\r\n", "utf-8"));
+ }else{
+ this._outputBuffer += headers.join("\r\n")+"\r\n\r\n";
+ }
+};
+
+/**
+ * <p>Uses data from the <code>this._message</code> object to build headers</p>
+ */
+MailComposer.prototype._buildMessageHeaders = function(){
+
+ // FROM
+ if(this._message.from && this._message.from.length){
+ [].concat(this._message.from).forEach((function(from){
+ this.addHeader("From", from);
+ }).bind(this));
+ }
+
+ // TO
+ if(this._message.to && this._message.to.length){
+ [].concat(this._message.to).forEach((function(to){
+ this.addHeader("To", to);
+ }).bind(this));
+ }
+
+ // CC
+ if(this._message.cc && this._message.cc.length){
+ [].concat(this._message.cc).forEach((function(cc){
+ this.addHeader("Cc", cc);
+ }).bind(this));
+ }
+
+ // BCC
+ // By default not included, set options.keepBcc to true to keep
+ if(this.options.keepBcc){
+ if(this._message.bcc && this._message.bcc.length){
+ [].concat(this._message.bcc).forEach((function(bcc){
+ this.addHeader("Bcc", bcc);
+ }).bind(this));
+ }
+ }
+
+ // REPLY-TO
+ if(this._message.replyTo && this._message.replyTo.length){
+ [].concat(this._message.replyTo).forEach((function(replyTo){
+ this.addHeader("Reply-To", replyTo);
+ }).bind(this));
+ }
+
+ // REFERENCES
+ if(this._message.references && this._message.references.length){
+ this.addHeader("References", this._message.references);
+ }
+
+ // IN-REPLY-TO
+ if(this._message.inReplyTo && this._message.inReplyTo.length){
+ this.addHeader("In-Reply-To", this._message.inReplyTo);
+ }
+
+ // SUBJECT
+ if(this._message.subject){
+ this.addHeader("Subject", this._message.subject);
+ }
+};
+
+/**
+ * <p>Generates the structure (mime tree) of the body. This sets up multipart
+ * structure, individual part headers, boundaries etc.</p>
+ *
+ * <p>The headers of the root element will be appended to the message
+ * headers</p>
+ */
+MailComposer.prototype._generateBodyStructure = function(){
+
+ var tree = this._createMimeNode(),
+ currentNode, node,
+ i, len;
+
+ if(this._message.useMixed){
+
+ node = this._createMimeNode();
+ node.boundary = this._message.mixedBoundary;
+ node.headers.push(["Content-Type", "multipart/mixed; boundary=\""+node.boundary+"\""]);
+
+ if(currentNode){
+ currentNode.childNodes.push(node);
+ node.parentNode = currentNode;
+ }else{
+ tree = node;
+ }
+ currentNode = node;
+
+ }
+
+ if(this._message.useAlternative){
+
+ node = this._createMimeNode();
+ node.boundary = this._message.alternativeBoundary;
+ node.headers.push(["Content-Type", "multipart/alternative; boundary=\""+node.boundary+"\""]);
+ if(currentNode){
+ currentNode.childNodes.push(node);
+ node.parentNode = currentNode;
+ }else{
+ tree = node;
+ }
+ currentNode = node;
+
+ }
+
+ if(this._message.body){
+ node = this._createTextComponent(this._message.body, "text/plain");
+ if(currentNode){
+ currentNode.childNodes.push(node);
+ node.parentNode = currentNode;
+ }else{
+ tree = node;
+ }
+ }
+
+ if(this._message.useRelated){
+
+ node = this._createMimeNode();
+ node.boundary = this._message.relatedBoundary;
+ node.headers.push(["Content-Type", "multipart/related; boundary=\""+node.boundary+"\""]);
+ if(currentNode){
+ currentNode.childNodes.push(node);
+ node.parentNode = currentNode;
+ }else{
+ tree = node;
+ }
+ currentNode = node;
+
+ }
+
+ if(this._message.html){
+ node = this._createTextComponent(this._message.html, "text/html");
+ if(currentNode){
+ currentNode.childNodes.push(node);
+ node.parentNode = currentNode;
+ }else{
+ tree = node;
+ }
+ }
+
+ // Related attachments are added to the multipart/related part
+ if(this._relatedAttachments && this._relatedAttachments){
+ for(i=0, len = this._relatedAttachments.length; i<len; i++){
+ node = this._createAttachmentComponent(this._relatedAttachments[i]);
+ node.parentNode = currentNode;
+ currentNode.childNodes.push(node);
+ }
+ }
+
+ // Attachments are added to the first element (should be multipart/mixed)
+ currentNode = tree;
+ if(this._attachments && this._attachments.length){
+ for(i=0, len = this._attachments.length; i<len; i++){
+ node = this._createAttachmentComponent(this._attachments[i]);
+ node.parentNode = currentNode;
+ currentNode.childNodes.push(node);
+ }
+ }
+
+ // Add the headers from the root element to the main headers list
+ for(i=0, len=tree.headers.length; i<len; i++){
+ this.addHeader(tree.headers[i][0], tree.headers[i][1]);
+ }
+
+ this._message.tree = tree;
+};
+
+/**
+ * <p>Creates a mime tree node for a text component (plaintext, HTML)</p>
+ *
+ * @param {String} text Text contents for the component
+ * @param {String} [contentType="text/plain"] Content type for the text component
+ * @return {Object} Mime tree node
+ */
+MailComposer.prototype._createTextComponent = function(text, contentType){
+ var node = this._createMimeNode();
+
+ node.contentEncoding = (this.options.encoding || "quoted-printable").toLowerCase().trim();
+ node.useTextType = true;
+
+ contentType = [contentType || "text/plain"];
+ contentType.push("charset=utf-8");
+
+ if(["7bit", "8bit", "binary"].indexOf(node.contentEncoding)>=0){
+ node.textFormat = "flowed";
+ contentType.push("format=" + node.textFormat);
+ }
+
+ node.headers.push(["Content-Type", contentType.join("; ")]);
+ node.headers.push(["Content-Transfer-Encoding", node.contentEncoding]);
+
+ node.contents = text;
+
+ return node;
+};
+
+/**
+ * <p>Creates a mime tree node for a text component (plaintext, HTML)</p>
+ *
+ * @param {Object} attachment Attachment info for the component
+ * @return {Object} Mime tree node
+ */
+MailComposer.prototype._createAttachmentComponent = function(attachment){
+ var node = this._createMimeNode(),
+ contentType = [attachment.contentType],
+ contentDisposition = [attachment.contentDisposition || "attachment"],
+ fileName;
+
+ node.contentEncoding = "base64";
+ node.useAttachmentType = true;
+
+ if(attachment.fileName){
+ fileName = this._encodeMimeWord(attachment.fileName, "Q", 1024).replace(/"/g,"\\\"");
+ contentType.push("name=\"" +fileName+ "\"");
+ contentDisposition.push("filename=\"" +fileName+ "\"");
+ }
+
+ node.headers.push(["Content-Type", contentType.join("; ")]);
+ node.headers.push(["Content-Disposition", contentDisposition.join("; ")]);
+ node.headers.push(["Content-Transfer-Encoding", node.contentEncoding]);
+
+ if(attachment.cid){
+ node.headers.push(["Content-Id", "<" + this._encodeMimeWord(attachment.cid) + ">"]);
+ }
+
+ if(attachment.contents){
+ node.contents = attachment.contents;
+ }else if(attachment.filePath){
+ node.filePath = attachment.filePath;
+ if(attachment.userAgent){
+ node.userAgent = attachment.userAgent;
+ }
+ }else if(attachment.streamSource){
+ node.streamSource = attachment.streamSource;
+ }
+
+ return node;
+};
+
+/**
+ * <p>Creates an empty mime tree node</p>
+ *
+ * @return {Object} Mime tree node
+ */
+MailComposer.prototype._createMimeNode = function(){
+ return {
+ childNodes: [],
+ headers: [],
+ parentNode: null
+ };
+};
+
+/**
+ * <p>Compiles headers object into an array of header lines. If needed, the
+ * lines are folded</p>
+ *
+ * @param {Object|Array} headers An object with headers in the form of
+ * <code>{key:value}</code> or <ocde>[[key, value]]</code> or
+ * <code>[{key:key, value: value}]</code>
+ * @return {Array} A list of header lines. Can be joined with \r\n
+ */
+MailComposer.prototype.compileHeaders = function(headers){
+ var headersArr = [], keys, key;
+
+ if(Array.isArray(headers)){
+ headersArr = headers.map(function(field){
+ return mimelib.foldLine((field.key || field[0])+": "+(field.value || field[1]));
+ });
+ }else{
+ keys = Object.keys(headers);
+ for(var i=0, len = keys.length; i<len; i++){
+ key = this._normalizeKey(keys[i]);
+
+ headersArr = headersArr.concat([].concat(headers[key]).map(function(field){
+ return mimelib.foldLine(key+": "+field);
+ }));
+ }
+ }
+
+ return headersArr;
+};
+
+/**
+ * <p>Converts a structured mimetree into an one dimensional array of
+ * components. This includes headers and multipart boundaries as strings,
+ * textual and attachment contents are.</p>
+ */
+MailComposer.prototype._flattenMimeTree = function(){
+ var flatTree = [];
+
+ function walkTree(node, level){
+ var contentObject = {};
+ level = level || 0;
+
+ // if not root element, include headers
+ if(level){
+ flatTree = flatTree.concat(this.compileHeaders(node.headers));
+ flatTree.push('');
+ }
+
+ if(node.textFormat){
+ contentObject.textFormat = node.textFormat;
+ }
+
+ if(node.contentEncoding){
+ contentObject.contentEncoding = node.contentEncoding;
+ }
+
+ if(node.contents){
+ contentObject.contents = node.contents;
+ }else if(node.filePath){
+ contentObject.filePath = node.filePath;
+ if(node.userAgent){
+ contentObject.userAgent = node.userAgent;
+ }
+ }else if(node.streamSource){
+ contentObject.streamSource = node.streamSource;
+ }
+
+ if(node.contents || node.filePath || node.streamSource){
+ flatTree.push(contentObject);
+ }
+
+ // walk children
+ for(var i=0, len = node.childNodes.length; i<len; i++){
+ if(node.boundary){
+ flatTree.push("--"+node.boundary);
+ }
+ walkTree.call(this, node.childNodes[i], level+1);
+ }
+ if(node.boundary && node.childNodes.length){
+ flatTree.push("--"+node.boundary+"--");
+ flatTree.push('');
+ }
+ }
+
+ walkTree.call(this, this._message.tree);
+
+ if(flatTree.length && flatTree[flatTree.length-1]===''){
+ flatTree.pop();
+ }
+
+ this._message.flatTree = flatTree;
+};
+
+/**
+ * <p>Composes the e-mail body based on the previously generated mime tree</p>
+ *
+ * <p>Assumes that the linebreak separating headers and contents is already
+ * sent</p>
+ *
+ * <p>Emits 'data' events</p>
+ */
+MailComposer.prototype._composeBody = function(){
+ var flatTree = this._message.flatTree,
+ slice, isObject = false, isEnd = false,
+ curObject;
+
+ this._message.processingStart = this._message.processingStart || 0;
+ this._message.processingPos = this._message.processingPos || 0;
+
+ for(var len = flatTree.length; this._message.processingPos < len; this._message.processingPos++){
+
+ isEnd = this._message.processingPos >= len-1;
+ isObject = typeof flatTree[this._message.processingPos] == "object";
+
+ if(isEnd || isObject){
+
+ slice = flatTree.slice(this._message.processingStart, isEnd && !isObject?undefined:this._message.processingPos);
+ if(slice && slice.length){
+ if(!this._cacheOutput){
+ this.emit("data", new Buffer(slice.join("\r\n")+"\r\n", "utf-8"));
+ }else{
+ this._outputBuffer += slice.join("\r\n")+"\r\n";
+ }
+ }
+
+ if(isObject){
+ curObject = flatTree[this._message.processingPos];
+
+ this._message.processingPos++;
+ this._message.processingStart = this._message.processingPos;
+
+ this._emitDataElement(curObject, (function(){
+ if(!isEnd){
+ process.nextTick(this._composeBody.bind(this));
+ }else{
+ if(!this._cacheOutput){
+ this.emit("end");
+ }else{
+ this._processBufferedOutput();
+ }
+ }
+ }).bind(this));
+
+ }else if(isEnd){
+ if(!this._cacheOutput){
+ this.emit("end");
+ }else{
+ this._processBufferedOutput();
+ }
+ }
+ break;
+ }
+
+ }
+};
+
+/**
+ * <p>Emits a data event for a text or html body and attachments. If it is a
+ * file, stream it</p>
+ *
+ * <p>If <code>this.options.escapeSMTP</code> is true, replace dots in the
+ * beginning of a line with double dots - only valid for QP encoding</p>
+ *
+ * @param {Object} element Data element descriptor
+ * @param {Function} callback Callback function to run when completed
+ */
+MailComposer.prototype._emitDataElement = function(element, callback){
+
+ var data = "";
+
+ if(element.contents){
+ switch(element.contentEncoding){
+ case "quoted-printable":
+ data = mimelib.encodeQuotedPrintable(element.contents);
+ break;
+ case "base64":
+ data = new Buffer(element.contents, "utf-8").toString("base64").replace(/.{76}/g,"$&\r\n");
+ break;
+ case "7bit":
+ case "8bit":
+ case "binary":
+ default:
+ data = mimelib.foldLine(element.contents, 78, false, element.textFormat=="flowed");
+ //mimelib puts a long whitespace to the beginning of the lines
+ data = data.replace(/^[ ]{7}/mg, "");
+ break;
+ }
+
+ if(this.options.escapeSMTP){
+ data = data.replace(/^\./gm,'..');
+ }
+
+ if(!this._cacheOutput){
+ this.emit("data", new Buffer(data + "\r\n", "utf-8"));
+ }else{
+ this._outputBuffer += data + "\r\n";
+ }
+ process.nextTick(callback);
+ return;
+ }
+
+ if(element.filePath){
+ if(element.filePath.match(/^https?:\/\//)){
+ this._serveStream(urlFetch(element.filePath, {userAgent: element.userAgent}), callback);
+ }else{
+ this._serveFile(element.filePath, callback);
+ }
+ return;
+ }else if(element.streamSource){
+ this._serveStream(element.streamSource, callback);
+ return;
+ }
+
+ callback();
+};
+
+/**
+ * <p>Pipes a file to the e-mail stream</p>
+ *
+ * @param {String} filePath Path to the file
+ * @param {Function} callback Callback function to run after completion
+ */
+MailComposer.prototype._serveFile = function(filePath, callback){
+ fs.stat(filePath, (function(err, stat){
+ if(err || !stat.isFile()){
+
+
+ if(!this._cacheOutput){
+ this.emit("data", new Buffer(new Buffer("<ERROR OPENING FILE>",
+ "utf-8").toString("base64")+"\r\n", "utf-8"));
+ }else{
+ this._outputBuffer += new Buffer("<ERROR OPENING FILE>",
+ "utf-8").toString("base64")+"\r\n";
+ }
+
+ process.nextTick(callback);
+ return;
+ }
+
+ var stream = fs.createReadStream(filePath);
+
+ this._serveStream(stream, callback);
+
+ }).bind(this));
+};
+
+/**
+ * <p>Pipes a stream source to the e-mail stream</p>
+ *
+ * <p>This function resumes the stream and starts sending 76 bytes long base64
+ * encoded lines. To achieve this, the incoming stream is divded into
+ * chunks of 57 bytes (57/3*4=76) to achieve exactly 76 byte long
+ * base64</p>
+ *
+ * @param {Object} stream Stream to be piped
+ * @param {Function} callback Callback function to run after completion
+ */
+MailComposer.prototype._serveStream = function(stream, callback){
+ var remainder = new Buffer(0);
+
+ stream.on("error", (function(error){
+ if(!this._cacheOutput){
+ this.emit("data", new Buffer(new Buffer("<ERROR READING STREAM>",
+ "utf-8").toString("base64")+"\r\n", "utf-8"));
+ }else{
+ this._outputBuffer += new Buffer("<ERROR READING STREAM>",
+ "utf-8").toString("base64")+"\r\n";
+ }
+ process.nextTick(callback);
+ }).bind(this));
+
+ stream.on("data", (function(chunk){
+ var data = "",
+ len = remainder.length + chunk.length,
+ remainderLength = len % 57, // we use 57 bytes as it composes
+ // a 76 bytes long base64 string
+ buffer = new Buffer(len);
+
+ remainder.copy(buffer); // copy remainder into the beginning of the new buffer
+ chunk.copy(buffer, remainder.length); // copy data chunk after the remainder
+ remainder = buffer.slice(len - remainderLength); // create a new remainder
+
+ data = buffer.slice(0, len - remainderLength).toString("base64").replace(/.{76}/g,"$&\r\n");
+
+ if(data.length){
+ if(!this._cacheOutput){
+ this.emit("data", new Buffer(data.trim()+"\r\n", "utf-8"));
+ }else{
+ this._outputBuffer += data.trim()+"\r\n";
+ }
+ }
+ }).bind(this));
+
+ stream.on("end", (function(chunk){
+ var data;
+
+ // stream the remainder (if any)
+ if(remainder.length){
+ data = remainder.toString("base64").replace(/.{76}/g,"$&\r\n");
+ if(!this._cacheOutput){
+ this.emit("data", new Buffer(data.trim()+"\r\n", "utf-8"));
+ }else{
+ this._outputBuffer += data.trim()+"\r\n";
+ }
+ }
+ process.nextTick(callback);
+ }).bind(this));
+
+ // resume streaming if paused
+ stream.resume();
+};
+
+/**
+ * <p>Processes buffered output and emits 'end'</p>
+ */
+MailComposer.prototype._processBufferedOutput = function(){
+ var dkimSignature;
+
+ if(this._dkim){
+ if((dkimSignature = DKIMSign(this._outputBuffer, this._dkim))){
+ this.emit("data", new Buffer(dkimSignature+"\r\n", "utf-8"));
+ }
+ }
+
+ this.emit("data", new Buffer(this._outputBuffer, "utf-8"));
+
+ process.nextTick(this.emit.bind(this,"end"));
+};
+
+/* HELPER FUNCTIONS */
+
+/**
+ * <p>Normalizes a key name by cpitalizing first chars of words, except for
+ * custom keys (starting with "X-") that have only uppercase letters, which will
+ * not be modified.</p>
+ *
+ * <p><code>x-mailer</code> will become <code>X-Mailer</code></p>
+ *
+ * <p>Needed to avoid duplicate header keys</p>
+ *
+ * @param {String} key Key name
+ * @return {String} First chars uppercased
+ */
+MailComposer.prototype._normalizeKey = function(key){
+ key = (key || "").toString().trim();
+
+ // If only uppercase letters, leave everything as is
+ if(key.match(/^X\-[A-Z0-9\-]+$/)){
+ return key;
+ }
+
+ // Convert first letter upper case, others lower case
+ return key.
+ toLowerCase().
+ replace(/^\S|[\-\s]\S/g, function(c){
+ return c.toUpperCase();
+ }).
+ replace(/^MIME\-/i, "MIME-").
+ replace(/^DKIM\-/i, "DKIM-");
+};
+
+/**
+ * <p>Tests if a string has high bit (UTF-8) symbols</p>
+ *
+ * @param {String} str String to be tested for high bit symbols
+ * @return {Boolean} true if high bit symbols were found
+ */
+MailComposer.prototype._hasUTFChars = function(str){
+ var rforeign = /[^\u0000-\u007f]/;
+ return !!rforeign.test(str);
+};
+
+/**
+ * <p>Generates a boundary for multipart bodies</p>
+ *
+ * @return {String} Boundary String
+ */
+MailComposer.prototype._generateBoundary = function(){
+ // "_" is not allowed in quoted-printable and "?" not in base64
+ return "----mailcomposer-?=_"+(++this._gencounter)+"-"+Date.now();
+};
+
+/**
+ * <p>Converts a string to mime word format. If the length is longer than
+ * <code>maxlen</code>, split it</p>
+ *
+ * <p>If the string doesn't have any unicode characters return the original
+ * string instead</p>
+ *
+ * @param {String} str String to be encoded
+ * @param {String} encoding Either Q for Quoted-Printable or B for Base64
+ * @param {Number} [maxlen] Optional length of the resulting string, whitespace will be inserted if needed
+ *
+ * @return {String} Mime-word encoded string (if needed)
+ */
+MailComposer.prototype._encodeMimeWord = function(str, encoding, maxlen){
+
+ // adjust maxlen by =?UTF-8?Q??=
+ if(maxlen && maxlen>12){
+ maxlen -= 12;
+ }
+
+ encoding = (encoding || "Q").toUpperCase();
+ if(this._hasUTFChars(str)){
+ str = mimelib.encodeMimeWord(str, encoding);
+ if(maxlen && str.length>maxlen){
+ if(encoding=="Q"){
+ return "=?UTF-8?Q?"+this._splitEncodedString(str.split("?")[3], maxlen).join("?= =?UTF-8?Q?")+"?=";
+ }else{
+ return "=?UTF-8?"+encoding+"?"+str.split("?")[3].replace(new RegExp(".{"+maxlen+"}","g"),"$&?= =?UTF-8?"+encoding+"?")+"?=";
+ }
+ }else{
+ return str;
+ }
+ }else{
+ return str;
+ }
+};
+
+/**
+ * <p>Splits a mime-encoded string</p>
+ *
+ * @param {String} str Input string
+ * @param {Number} maxlen Maximum line length
+ * @return {Array} split string
+ */
+MailComposer.prototype._splitEncodedString = function(str, maxlen){
+ var curLine, match, chr, done,
+ lines = [];
+
+ while(str.length){
+ curLine = str.substr(0, maxlen);
+
+ // move incomplete escaped char back to main
+ if((match = curLine.match(/\=[0-9A-F]?$/i))){
+ curLine = curLine.substr(0, match.index);
+ }
+
+ done = false;
+ while(!done){
+ done = true;
+ // check if not middle of a unicode char sequence
+ if((match = str.substr(curLine.length).match(/^\=([0-9A-F]{2})/i))){
+ chr = parseInt(match[1], 16);
+ // invalid sequence, move one char back anc recheck
+ if(chr < 0xC2 && chr > 0x7F){
+ curLine = curLine.substr(0, curLine.length-3);
+ done = false;
+ }
+ }
+ }
+
+ if(curLine.length){
+ lines.push(curLine);
+ }
+ str = str.substr(curLine.length);
+ }
+
+ return lines;
+};
+
+
+/**
+ * <p>Resolves a mime type for a filename</p>
+ *
+ * @param {String} filename Filename to check
+ * @return {String} Corresponding mime type
+ */
+MailComposer.prototype._getMimeType = function(filename){
+ var defaultMime = "application/octet-stream",
+ extension = filename && filename.substr(filename.lastIndexOf(".")+1).trim().toLowerCase();
+ return extension && mimelib.contentTypes[extension] || defaultMime;
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/punycode.js b/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/punycode.js
new file mode 100644
index 0000000..ab14f4b
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/punycode.js
@@ -0,0 +1,329 @@
+//Javascript Punycode converter derived from example in RFC3492.
+//This implementation is created by some@domain.name and released into public domain
+var punycode = new function Punycode() {
+ // This object converts to and from puny-code used in IDN
+ //
+ // punycode.ToASCII ( domain )
+ //
+ // Returns a puny coded representation of "domain".
+ // It only converts the part of the domain name that
+ // has non ASCII characters. I.e. it dosent matter if
+ // you call it with a domain that already is in ASCII.
+ //
+ // punycode.ToUnicode (domain)
+ //
+ // Converts a puny-coded domain name to unicode.
+ // It only converts the puny-coded parts of the domain name.
+ // I.e. it dosent matter if you call it on a string
+ // that already has been converted to unicode.
+ //
+ //
+ this.utf16 = {
+ // The utf16-class is necessary to convert from javascripts internal character representation to unicode and back.
+ decode:function(input){
+ var output = [], i=0, len=input.length,value,extra;
+ while (i < len) {
+ value = input.charCodeAt(i++);
+ if ((value & 0xF800) === 0xD800) {
+ extra = input.charCodeAt(i++);
+ if ( ((value & 0xFC00) !== 0xD800) || ((extra & 0xFC00) !== 0xDC00) ) {
+ throw new RangeError("UTF-16(decode): Illegal UTF-16 sequence");
+ }
+ value = ((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000;
+ }
+ output.push(value);
+ }
+ return output;
+ },
+ encode:function(input){
+ var output = [], i=0, len=input.length,value;
+ while (i < len) {
+ value = input[i++];
+ if ( (value & 0xF800) === 0xD800 ) {
+ throw new RangeError("UTF-16(encode): Illegal UTF-16 value");
+ }
+ if (value > 0xFFFF) {
+ value -= 0x10000;
+ output.push(String.fromCharCode(((value >>>10) & 0x3FF) | 0xD800));
+ value = 0xDC00 | (value & 0x3FF);
+ }
+ output.push(String.fromCharCode(value));
+ }
+ return output.join("");
+ }
+ };
+
+ //Default parameters
+ var initial_n = 0x80;
+ var initial_bias = 72;
+ var delimiter = "-";
+ var base = 36;
+ var damp = 700;
+ var tmin=1;
+ var tmax=26;
+ var skew=38;
+ var maxint = 0x7FFFFFFF;
+
+ // decode_digit(cp) returns the numeric value of a basic code
+ // point (for use in representing integers) in the range 0 to
+ // base-1, or base if cp is does not represent a value.
+
+ function decode_digit(cp) {
+ return cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 : cp - 97 < 26 ? cp - 97 : base;
+ }
+
+ // encode_digit(d,flag) returns the basic code point whose value
+ // (when used for representing integers) is d, which needs to be in
+ // the range 0 to base-1. The lowercase form is used unless flag is
+ // nonzero, in which case the uppercase form is used. The behavior
+ // is undefined if flag is nonzero and digit d has no uppercase form.
+
+ function encode_digit(d, flag) {
+ return d + 22 + 75 * (d < 26) - ((flag !== 0) << 5);
+ // 0..25 map to ASCII a..z or A..Z
+ // 26..35 map to ASCII 0..9
+ }
+ //** Bias adaptation function **
+ function adapt(delta, numpoints, firsttime ) {
+ var k;
+ delta = firsttime ? Math.floor(delta / damp) : (delta >> 1);
+ delta += Math.floor(delta / numpoints);
+
+ for (k = 0; delta > (((base - tmin) * tmax) >> 1); k += base) {
+ delta = Math.floor(delta / ( base - tmin ));
+ }
+ return Math.floor(k + (base - tmin + 1) * delta / (delta + skew));
+ }
+
+ // encode_basic(bcp,flag) forces a basic code point to lowercase if flag is zero,
+ // uppercase if flag is nonzero, and returns the resulting code point.
+ // The code point is unchanged if it is caseless.
+ // The behavior is undefined if bcp is not a basic code point.
+
+ function encode_basic(bcp, flag) {
+ bcp -= (bcp - 97 < 26) << 5;
+ return bcp + ((!flag && (bcp - 65 < 26)) << 5);
+ }
+
+ // Main decode
+ this.decode=function(input,preserveCase) {
+ // Dont use utf16
+ var output=[];
+ var case_flags=[];
+ var input_length = input.length;
+
+ var n, out, i, bias, basic, j, ic, oldi, w, k, digit, t, len;
+
+ // Initialize the state:
+
+ n = initial_n;
+ i = 0;
+ bias = initial_bias;
+
+ // Handle the basic code points: Let basic be the number of input code
+ // points before the last delimiter, or 0 if there is none, then
+ // copy the first basic code points to the output.
+
+ basic = input.lastIndexOf(delimiter);
+ if (basic < 0) basic = 0;
+
+ for (j = 0; j < basic; ++j) {
+ if(preserveCase) case_flags[output.length] = ( input.charCodeAt(j) -65 < 26);
+ if ( input.charCodeAt(j) >= 0x80) {
+ throw new RangeError("Illegal input >= 0x80");
+ }
+ output.push( input.charCodeAt(j) );
+ }
+
+ // Main decoding loop: Start just after the last delimiter if any
+ // basic code points were copied; start at the beginning otherwise.
+
+ for (ic = basic > 0 ? basic + 1 : 0; ic < input_length; ) {
+
+ // ic is the index of the next character to be consumed,
+
+ // Decode a generalized variable-length integer into delta,
+ // which gets added to i. The overflow checking is easier
+ // if we increase i as we go, then subtract off its starting
+ // value at the end to obtain delta.
+ for (oldi = i, w = 1, k = base; ; k += base) {
+ if (ic >= input_length) {
+ throw RangeError ("punycode_bad_input(1)");
+ }
+ digit = decode_digit(input.charCodeAt(ic++));
+
+ if (digit >= base) {
+ throw RangeError("punycode_bad_input(2)");
+ }
+ if (digit > Math.floor((maxint - i) / w)) {
+ throw RangeError ("punycode_overflow(1)");
+ }
+ i += digit * w;
+ t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
+ if (digit < t) { break; }
+ if (w > Math.floor(maxint / (base - t))) {
+ throw RangeError("punycode_overflow(2)");
+ }
+ w *= (base - t);
+ }
+
+ out = output.length + 1;
+ bias = adapt(i - oldi, out, oldi === 0);
+
+ // i was supposed to wrap around from out to 0,
+ // incrementing n each time, so we'll fix that now:
+ if ( Math.floor(i / out) > maxint - n) {
+ throw RangeError("punycode_overflow(3)");
+ }
+ n += Math.floor( i / out ) ;
+ i %= out;
+
+ // Insert n at position i of the output:
+ // Case of last character determines uppercase flag:
+ if (preserveCase) { case_flags.splice(i, 0, input.charCodeAt(ic -1) -65 < 26);}
+
+ output.splice(i, 0, n);
+ i++;
+ }
+ if (preserveCase) {
+ for (i = 0, len = output.length; i < len; i++) {
+ if (case_flags[i]) {
+ output[i] = (String.fromCharCode(output[i]).toUpperCase()).charCodeAt(0);
+ }
+ }
+ }
+ return this.utf16.encode(output);
+ };
+
+ //** Main encode function **
+
+ this.encode = function (input,preserveCase) {
+ //** Bias adaptation function **
+
+ var n, delta, h, b, bias, j, m, q, k, t, ijv, case_flags;
+
+ if (preserveCase) {
+ // Preserve case, step1 of 2: Get a list of the unaltered string
+ case_flags = this.utf16.decode(input);
+ }
+ // Converts the input in UTF-16 to Unicode
+ input = this.utf16.decode(input.toLowerCase());
+
+ var input_length = input.length; // Cache the length
+
+ if (preserveCase) {
+ // Preserve case, step2 of 2: Modify the list to true/false
+ for (j=0; j < input_length; j++) {
+ case_flags[j] = input[j] != case_flags[j];
+ }
+ }
+
+ var output=[];
+
+
+ // Initialize the state:
+ n = initial_n;
+ delta = 0;
+ bias = initial_bias;
+
+ // Handle the basic code points:
+ for (j = 0; j < input_length; ++j) {
+ if ( input[j] < 0x80) {
+ output.push(
+ String.fromCharCode(
+ case_flags ? encode_basic(input[j], case_flags[j]) : input[j]
+ )
+ );
+ }
+ }
+
+ h = b = output.length;
+
+ // h is the number of code points that have been handled, b is the
+ // number of basic code points
+
+ if (b > 0) output.push(delimiter);
+
+ // Main encoding loop:
+ //
+ while (h < input_length) {
+ // All non-basic code points < n have been
+ // handled already. Find the next larger one:
+
+ for (m = maxint, j = 0; j < input_length; ++j) {
+ ijv = input[j];
+ if (ijv >= n && ijv < m) m = ijv;
+ }
+
+ // Increase delta enough to advance the decoder's
+ // <n,i> state to <m,0>, but guard against overflow:
+
+ if (m - n > Math.floor((maxint - delta) / (h + 1))) {
+ throw RangeError("punycode_overflow (1)");
+ }
+ delta += (m - n) * (h + 1);
+ n = m;
+
+ for (j = 0; j < input_length; ++j) {
+ ijv = input[j];
+
+ if (ijv < n ) {
+ if (++delta > maxint) return Error("punycode_overflow(2)");
+ }
+
+ if (ijv == n) {
+ // Represent delta as a generalized variable-length integer:
+ for (q = delta, k = base; ; k += base) {
+ t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
+ if (q < t) break;
+ output.push( String.fromCharCode(encode_digit(t + (q - t) % (base - t), 0)) );
+ q = Math.floor( (q - t) / (base - t) );
+ }
+ output.push( String.fromCharCode(encode_digit(q, preserveCase && case_flags[j] ? 1:0 )));
+ bias = adapt(delta, h + 1, h == b);
+ delta = 0;
+ ++h;
+ }
+ }
+
+ ++delta;
+ ++n;
+ }
+ return output.join("");
+ };
+
+ this.ToASCII = function ( domain ) {
+ var domain_array = domain.split(".");
+ var out = [];
+ for (var i=0; i < domain_array.length; ++i) {
+ var s = domain_array[i];
+ out.push(
+ s.match(/[^A-Za-z0-9\-]/) ?
+ "xn--" + punycode.encode(s) :
+ s
+ );
+ }
+ return out.join(".");
+ };
+
+ this.ToUnicode = function ( domain ) {
+ var domain_array = domain.split(".");
+ var out = [];
+ for (var i=0; i < domain_array.length; ++i) {
+ var s = domain_array[i];
+ out.push(
+ s.match(/^xn--/) ?
+ punycode.decode(s.slice(4)) :
+ s
+ );
+ }
+ return out.join(".");
+ };
+}();
+
+module.exports = function(address){
+ return address.replace(/((?:https?:\/\/)?.*\@)?([^\/]*)/, function(o, start, domain){
+ var domainParts = domain.split(/\./).map(punycode.ToASCII);
+ return (start || "") + domainParts.join(".");
+ });
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/urlfetch.js b/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/urlfetch.js
new file mode 100644
index 0000000..ecac514
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/lib/urlfetch.js
@@ -0,0 +1,71 @@
+var http = require("http"),
+ https = require("https"),
+ urllib = require("url"),
+ Stream = require('stream').Stream;
+
+/**
+ * @namespace URLFetch
+ * @name urlfetch
+ */
+module.exports = openUrlStream;
+
+/**
+ * <p>Open a stream to a specified URL</p>
+ *
+ * @memberOf urlfetch
+ * @param {String} url URL to open
+ * @param {Object} [options] Optional options object
+ * @param {String} [options.userAgent="mailcomposer"] User Agent for the request
+ * @return {Stream} Stream for the URL contents
+ */
+function openUrlStream(url, options){
+ options = options || {};
+ var urlparts = urllib.parse(url),
+ urloptions = {
+ host: urlparts.hostname,
+ port: urlparts.port || (urlparts.protocol=="https:"?443:80),
+ path: urlparts.path || urlparts.pathname,
+ method: "GET",
+ headers: {
+ "User-Agent": options.userAgent || "mailcomposer"
+ }
+ },
+ client = (urlparts.protocol=="https:"?https:http),
+ stream = new Stream(),
+ request;
+
+ stream.resume = function(){};
+
+ if(urlparts.auth){
+ urloptions.auth = urlparts.auth;
+ }
+
+ request = client.request(urloptions, function(response) {
+ if((response.statusCode || 0).toString().charAt(0) != "2"){
+ stream.emit("error", "Invalid status code " + (response.statusCode || 0));
+ return;
+ }
+
+ response.on('error', function(err) {
+ stream.emit("error", err);
+ });
+
+ response.on('data', function(chunk) {
+ stream.emit("data", chunk);
+ });
+
+ response.on('end', function(chunk) {
+ if(chunk){
+ stream.emit("data", chunk);
+ }
+ stream.emit("end");
+ });
+ });
+ request.end();
+
+ request.on('error', function(err) {
+ stream.emit("error", err);
+ });
+
+ return stream;
+} \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/LICENSE b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/LICENSE
new file mode 100644
index 0000000..2950902
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/LICENSE
@@ -0,0 +1,16 @@
+Copyright (c) 2011 Andris Reinman
+
+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 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. \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/README.md b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/README.md
new file mode 100644
index 0000000..58a0871
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/README.md
@@ -0,0 +1,17 @@
+# mimelib
+
+*mimelib* is a collection of useful functions to deal with mime-encoded data.
+
+## Reference
+
+See [API reference](/andris9/mimelib/blob/master/doc.md) for documentation
+
+## Installation
+
+Install with *npm*
+
+ npm install mimelib-noiconv
+
+## Usage
+
+ var mimelib = require("mimelib-noiconv");
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/content-types.js b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/content-types.js
new file mode 100644
index 0000000..bc5aa67
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/content-types.js
@@ -0,0 +1,60 @@
+// list of mime types
+module.exports = {
+ "doc": "application/msword",
+ "docx": "application/msword",
+ "pdf": "application/pdf",
+ "rss": "application/rss+xml",
+ "xls": "application/vnd.ms-excel",
+ "xlsx": "application/vnd.ms-excel",
+ "pps": "application/vnd.ms-powerpoint",
+ "ppt": "application/vnd.ms-powerpoint",
+ "pptx": "application/vnd.ms-powerpoint",
+ "odp": "application/vnd.oasis.opendocument.presentation",
+ "ods": "application/vnd.oasis.opendocument.spreadsheet",
+ "odt": "application/vnd.oasis.opendocument.text",
+ "sxc": "application/vnd.sun.xml.calc",
+ "sxw": "application/vnd.sun.xml.writer",
+ "au": "audio/basic",
+ "snd": "audio/basic",
+ "flac": "audio/flac",
+ "mid": "audio/mid",
+ "rmi": "audio/mid",
+ "m4a": "audio/mp4",
+ "mp3": "audio/mpeg",
+ "oga": "audio/ogg",
+ "ogg": "audio/ogg",
+ "aif": "audio/x-aiff",
+ "aifc": "audio/x-aiff",
+ "aiff": "audio/x-aiff",
+ "wav": "audio/x-wav",
+ "gif": "image/gif",
+ "jpeg": "image/jpeg",
+ "jpg": "image/jpeg",
+ "jpe": "image/jpeg",
+ "png": "image/png",
+ "tiff": "image/tiff",
+ "tif": "image/tiff",
+ "wbmp": "image/vnd.wap.wbmp",
+ "bmp": "image/x-ms-bmp",
+ "ics": "text/calendar",
+ "csv": "text/comma-separated-values",
+ "css": "text/css",
+ "htm": "text/html",
+ "html": "text/html",
+ "text": "text/plain",
+ "txt": "text/plain",
+ "asc": "text/plain",
+ "diff": "text/plain",
+ "pot": "text/plain",
+ "vcf": "text/x-vcard",
+ "mp4": "video/mp4",
+ "mpeg": "video/mpeg",
+ "mpg": "video/mpeg",
+ "mpe": "video/mpeg",
+ "ogv": "video/ogg",
+ "qt": "video/quicktime",
+ "mov": "video/quicktime",
+ "avi": "video/x-msvideo",
+ "zip": "application/zip",
+ "rar": "application/x-rar-compressed"
+} \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/doc.md b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/doc.md
new file mode 100644
index 0000000..3c89514
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/doc.md
@@ -0,0 +1,191 @@
+mimelib(1) -- MIME functions for Node.JS
+=============================================
+
+## DESCRIPTION
+
+This document lists all the available methods for mimelib. You can include mimelib
+in your projects with `var mimelib = require("mimelib");`
+
+When installed with npm dependency module iconv will also be installed if not already
+present.
+
+## contentTypes
+
+`mimelib.contentTypes` is an object to provide content type strings for common
+file extensions
+
+ mimelib.contentTypes["xls"]; // "application/vnd.ms-excel"
+
+## foldLine
+
+Folds a long line according to the RFC 5322 <http://tools.ietf.org/html/rfc5322#section-2.1.1>
+
+ mimelib.foldLine(str [, maxLength][, foldAnywhere]) -> String
+
+ - `str` (String): mime string that might need folding
+ - `maxLength` (Number): max length for a line, defaults to 78
+ - `foldAnywhere` (Boolean): can fold at any location (ie. in base64)
+ - `afterSpace` (Boolean): If `true` fold after the space
+
+
+For example:
+
+ Content-Type: multipart/alternative; boundary="----zzzz----"
+
+will become
+
+ Content-Type: multipart/alternative;
+ boundary="----zzzz----"
+
+## encodeMimeWord
+
+Encodes a string into mime encoded word format <http://en.wikipedia.org/wiki/MIME#Encoded-Word> (see also `decodeMimeWord`)
+
+ mimelib.encodeMimeWord = function(str [, encoding][, charset])
+
+ - `str` (String): String to be encoded
+ - `encoding` (String): Encoding Q for quoted printable or B (def.) for base64
+ - `charset` (String): Charset to be used
+
+For example:
+
+ See on õhin test
+
+Becomes with UTF-8 and Quoted-printable encoding
+
+ =?UTF-8?q?See_on_=C3=B5hin_test?=
+
+## decodeMimeWord
+
+Decodes a string from mime encoded word format (see also `encodeMimeWord`)
+
+ mimelib.decodeMimeWord(str) -> String
+
+ - `str` (String): String to be decoded
+
+For example
+
+ mimelib.decodeMimeWord("=?UTF-8?q?See_on_=C3=B5hin_test?=");
+
+will become
+
+ See on õhin test
+
+## encodeQuotedPrintable
+
+Encodes a string into Quoted-printable format (see also `decodeQuotedPrintable`)
+
+ mimelib.encodeQuotedPrintable(str [, mimeWord][, charset]) -> String
+
+ - `str` (String): String to be encoded into Quoted-printable
+ - `mimeWord` (Boolean): Use mime-word mode (defaults to false)
+ - `charset` (String): Destination charset, defaults to UTF-8
+
+TODO: Currently only allowed charsets: UTF-8, LATIN1
+
+## decodeQuotedPrintable
+
+Decodes a string from Quoted-printable format (see also `encodeQuotedPrintable`)
+
+ mimelib.deccodeQuotedPrintable(str [, mimeWord][, charset]) -> String
+
+ - `str` (String): String to be decoded
+ - `mimeWord` (Boolean): Use mime-word mode (defaults to false)
+ - `charset` (String): Charset to be used, defaults to UTF-8
+
+## encodeBase64
+
+Encodes a string into Base64 format. Base64 is mime-word safe (see also `decodeBase64`)
+
+ mimelib.encodeBase64(str [, charset]) -> String
+
+ - `str` (String): String to be encoded into Base64
+ - `charset` (String): Destination charset, defaults to UTF-8
+
+## decodeBase64
+
+Decodes a string from Base64 format. Base64 is mime-word safe (see also `encodeBase64`)
+
+NB! Always returns UTF-8
+
+ mimelib.decodeBase64(str) -> String
+
+ - `str` (String): String to be decoded from Base64
+ - `charset` (String): Source charset, defaults to UTF-8
+
+## parseHeaders
+
+Parses header lines into an array of objects (see `parseHeaderLine`)
+
+ mimelib.parseHeaders(headers) -> Array
+
+ - `headers` (String): header section of the e-mail
+
+Example:
+
+ var headers = [
+ "From: andris@node.ee",
+ "To: juulius@node.ee",
+ "To: juulius2@node.ee",
+ "Content-type: text/html;",
+ " charset=utf-8"
+ ].join("\r\n");
+ mimelib.parseHeaders(headers);
+
+Results in
+
+ {"from": [ 'andris@node.ee' ],
+ "to": [ 'juulius@node.ee', 'juulius2@node.ee' ],
+ "content-type": [ 'text/html; charset=utf-8' ] }
+
+## parseAddresses
+
+Parses names and addresses from a from, to, cc or bcc line
+
+ mimelib.parseAddresses(addresses) -> Array
+
+ - `addresses` (String): string with comma separated e-mail addresses
+
+Example:
+
+ var to = '"Andris Reinman" <andris@node.ee>, juulius@node.ee'
+ mimelib.parseAddresses(to);
+
+Results in
+
+ [{ address: 'andris@node.ee', name: 'Andris Reinman' },
+ { address: 'juulius@node.ee', name: false }]
+
+## parseMimeWords
+
+Parses mime-words into UTF-8 strings
+
+ mimelib.parseMimeWords(str) -> String
+
+ - `str` (String): string to be parsed, if includes any mime words, then these are converted to UTF-8 strings
+
+
+For example:
+
+ mimelib.parseMimeWords("Hello: =?UTF-8?q?See_on_=C3=B5hin_test?=");
+
+Results in
+
+ "Hello: See on õhin test"
+
+## parseHeaderLine
+
+Parses a header line to search for additional parameters.
+
+ mimelib.parseHeaderLine(line) -> Object
+
+ - `line` (String): a line from a message headers
+
+For example:
+
+ mimelib.parseHeaderLine("text/plain; charset=utf-8")imelib
+
+Results in
+
+ {"defaultValue": 'text/plain',
+ "charset": 'utf-8' }
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/index.js b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/index.js
new file mode 100644
index 0000000..a7ea3ee
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/index.js
@@ -0,0 +1,3 @@
+
+module.exports = require("./mime-functions");
+module.exports.contentTypes = require("./content-types"); \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js
new file mode 100644
index 0000000..9a93c7b
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/mime-functions.js
@@ -0,0 +1,486 @@
+
+try{
+ // see http://github.com/bnoordhuis/node-iconv for more info
+ var Iconv = require("iconv").Iconv;
+}catch(E){
+ // convert nothing
+ Iconv = function(){}
+ Iconv.prototype.convert = function(buf){return buf;};
+}
+
+/* mime related functions - encoding/decoding etc*/
+/* TODO: Only UTF-8 and Latin1 are allowed with encodeQuotedPrintable */
+/* TODO: Check if the input string even needs encoding */
+
+/**
+ * mime.foldLine(str, maxLength, foldAnywhere) -> String
+ * - str (String): mime string that might need folding
+ * - maxLength (Number): max length for a line, defaults to 78
+ * - foldAnywhere (Boolean): can fold at any location (ie. in base64)
+ * - afterSpace (Boolean): If [true] fold after the space
+ *
+ * Folds a long line according to the RFC 5322
+ * <http://tools.ietf.org/html/rfc5322#section-2.1.1>
+ *
+ * For example:
+ * Content-Type: multipart/alternative; boundary="----bd_n3-lunchhour1283962663300----"
+ * will become
+ * Content-Type: multipart/alternative;
+ * boundary="----bd_n3-lunchhour1283962663300----"
+ *
+ **/
+this.foldLine = function(str, maxLength, foldAnywhere, afterSpace){
+ var line=false, curpos=0, response="", lf;
+ maxLength = maxLength || 78;
+
+ // return original if no need to fold
+ if(str.length<=maxLength)
+ return str;
+
+ // read in <maxLength> bytes and try to fold it
+ while(line = str.substr(curpos, maxLength)){
+ if(!!foldAnywhere){
+ response += line;
+ if(curpos+maxLength<str.length){
+ response+="\r\n";
+ }
+ }else{
+ lf = line.lastIndexOf(" ");
+ if(lf<=0)
+ lf = line.lastIndexOf("\t");
+ if(line.length>=maxLength && lf>0){
+ if(!!afterSpace){
+ // move forward until line end or no more \s and \t
+ while(lf<line.length && (line.charAt(lf)==" " || line.charAt(lf)=="\t")){
+ lf++;
+ }
+ }
+ response += line.substr(0,lf)+"\r\n"+(!foldAnywhere && !afterSpace && " " || "");
+ curpos -= line.substr(lf).length;
+ }else{
+ response += line;
+ //line = line.replace(/=[a-f0-9]?$/i, "");
+ //response+=line + "\r\n";
+ }
+ }
+ curpos += line.length;
+ }
+
+ // return folded string
+ return response;
+}
+
+
+/**
+ * mime.encodeMimeWord(str, encoding, charset) -> String
+ * - str (String): String to be encoded
+ * - encoding (String): Encoding Q for quoted printable or B (def.) for base64
+ * - charset (String): Charset to be used
+ *
+ * Encodes a string into mime encoded word format
+ * <http://en.wikipedia.org/wiki/MIME#Encoded-Word>
+ *
+ * For example:
+ * See on õhin test
+ * Becomes with UTF-8 and Quoted-printable encoding
+ * =?UTF-8?q?See_on_=C3=B5hin_test?=
+ *
+ **/
+this.encodeMimeWord = function(str, encoding, charset){
+ charset = charset || "UTF-8";
+ encoding = encoding && encoding.toUpperCase() || "B";
+
+ if(encoding=="Q"){
+ str = this.encodeQuotedPrintable(str, true, charset);
+ }
+
+ if(encoding=="B"){
+ str = this.encodeBase64(str);
+ }
+
+ return "=?"+charset+"?"+encoding+"?"+str+"?=";
+}
+
+/**
+ * mime.decodeMimeWord(str, encoding, charset) -> String
+ * - str (String): String to be encoded
+ * - encoding (String): Encoding Q for quoted printable or B (def.) for base64
+ * - charset (String): Charset to be used, defaults to UTF-8
+ *
+ * Decodes a string from mime encoded word format, see [[encodeMimeWord]]
+ *
+ **/
+
+this.decodeMimeWord = function(str){
+ var parts = str.split("?"),
+ charset = parts && parts[1],
+ encoding = parts && parts[2],
+ text = parts && parts[3];
+ if(!charset || !encoding || !text)
+ return str;
+ if(encoding.toUpperCase()=="Q"){
+ return this.decodeQuotedPrintable(text, true, charset);
+ }
+
+ if(encoding.toUpperCase()=="B"){
+ return this.decodeBase64(text);
+ }
+
+ return text;
+}
+
+
+/**
+ * mime.encodeQuotedPrintable(str, mimeWord, charset) -> String
+ * - str (String): String to be encoded into Quoted-printable
+ * - mimeWord (Boolean): Use mime-word mode (defaults to false)
+ * - charset (String): Destination charset, defaults to UTF-8
+ * TODO: Currently only allowed charsets: UTF-8, LATIN1
+ *
+ * Encodes a string into Quoted-printable format.
+ **/
+this.encodeQuotedPrintable = function(str, mimeWord, charset){
+ charset = charset || "UTF-8";
+
+ /*
+ * Characters from 33-126 OK (except for =; and ?_ when in mime word mode)
+ * Spaces + tabs OK (except for line beginnings and endings)
+ * \n + \r OK
+ */
+
+ str = str.replace(/(?:[\ud800-\udbff][\udc00-\udfff])|[^\sa-zA-Z\d]/gm,function(c){
+ if(!!mimeWord){
+ if(c=="?")return "=3F";
+ if(c=="_")return "=5F";
+ }
+ if(c!=="=" && c.charCodeAt(0)>=33 && c.charCodeAt(0)<=126)
+ return c;
+ return c=="="?"=3D":(charset=="UTF-8"?encodeURIComponent(c):escape(c)).replace(/%/g,'=');
+ });
+
+ str = lineEdges(str);
+
+ if(!mimeWord){
+ // lines might not be longer than 76 bytes, soft break: "=\r\n"
+ var lines = str.split(/\r?\n/);
+ str.replace(/(.{73}(?!\r?\n))/,"$&=\r\n")
+ for(var i=0, len = lines.length; i<len; i++){
+ if(lines[i].length>76){
+ lines[i] = this.foldLine(lines[i],76, false, true).replace(/\r\n/g,"=\r\n");
+ }
+ }
+ str = lines.join("\r\n");
+ }else{
+ str = str.replace(/\s/g, function(a){
+ if(a==" ")return "_";
+ if(a=="\t")return "=09";
+ return a=="\r"?"=0D":"=0A";
+ });
+ }
+
+ return str;
+}
+
+/**
+ * mime.deccodeQuotedPrintable(str, mimeWord, charset) -> String
+ * - str (String): String to be decoded
+ * - mimeWord (Boolean): Use mime-word mode (defaults to false)
+ * - charset (String): Charset to be used, defaults to UTF-8
+ *
+ * Decodes a string from Quoted-printable format.
+ **/
+this.decodeQuotedPrintable = function(str, mimeWord, charset){
+ charset = charset && charset.toUpperCase() || "UTF-8";
+
+ if(mimeWord){
+ str = str.replace(/_/g," ");
+ }else{
+ str = str.replace(/=\r\n/gm,'');
+ str = str.replace(/=$/,"");
+ }
+ if(charset == "UTF-8")
+ str = decodeURIComponent(str.replace(/%/g,'%25').replace(/=/g,"%"));
+ else{
+ str = str.replace(/%/g,'%25').replace(/=/g,"%");
+ if(charset=="ISO-8859-1" || charset=="LATIN1")
+ str = unescape(str);
+ else{
+ str = decodeBytestreamUrlencoding(str);
+ str = fromCharset(charset, str);
+ }
+ }
+ return str;
+}
+
+/**
+ * mime.encodeBase64(str) -> String
+ * - str (String): String to be encoded into Base64
+ * - charset (String): Destination charset, defaults to UTF-8
+ *
+ * Encodes a string into Base64 format. Base64 is mime-word safe.
+ **/
+this.encodeBase64 = function(str, charset){
+ var buffer;
+ if(charset && charset.toUpperCase()!="UTF-8")
+ buffer = toCharset(charset, str);
+ else
+ buffer = new Buffer(str, "UTF-8");
+ return buffer.toString("base64");
+}
+
+/**
+ * mime.decodeBase64(str) -> String
+ * - str (String): String to be decoded from Base64
+ * - charset (String): Source charset, defaults to UTF-8
+ *
+ * Decodes a string from Base64 format. Base64 is mime-word safe.
+ * NB! Always returns UTF-8
+ **/
+this.decodeBase64 = function(str, charset){
+ var buffer = new Buffer(str, "base64");
+
+ if(charset && charset.toUpperCase()!="UTF-8"){
+ return fromCharset(charset, buffer);
+ }
+
+ // defaults to utf-8
+ return buffer.toString("UTF-8");
+}
+
+/**
+ * mime.parseHeaders(headers) -> Array
+ * - headers (String): header section of the e-mail
+ *
+ * Parses header lines into an array of objects (see [[parseHeaderLine]])
+ * FIXME: This should probably not be here but in "envelope" instead
+ **/
+this.parseHeaders = function(headers){
+ var text, lines, line, i, name, value, cmd, header_lines = {};
+ // unfold
+ headers = headers.replace(/\r?\n([ \t])/gm," ");
+
+ // split lines
+ lines = headers.split(/\r?\n/);
+ for(i=0; i<lines.length;i++){
+ if(!lines[i]) // no more header lines
+ break;
+ cmd = lines[i].match(/[^\:]+/);
+ if(cmd && (cmd = cmd[0])){
+ name = cmd;
+ value = lines[i].substr(name.length+1);
+ if(!header_lines[name.toLowerCase().trim()])header_lines[name.toLowerCase().trim()] = [];
+ header_lines[name.toLowerCase()].push(value.trim());
+ }
+ }
+
+ return header_lines;
+}
+
+/**
+ * mime.parseAddresses(addresses) -> Array
+ * - addresses (String): string with comma separated e-mail addresses
+ *
+ * Parses names and addresses from a from, to, cc or bcc line
+ **/
+this.parseAddresses = function(addresses){
+ if(!addresses)
+ return [];
+
+ addresses = addresses.replace(/\=\?[^?]+\?[QqBb]\?[^?]+\?=/g, (function(a){return this.decodeMimeWord(a);}).bind(this));
+
+ // not sure if it's even needed - urlencode escaped \\ and \" and \'
+ addresses = addresses.replace(/\\\\/g,function(a){return escape(a.charAt(1));});
+ addresses = addresses.replace(/\\["']/g,function(a){return escape(a.charAt(1));});
+
+ // find qutoed strings
+
+ var parts = addresses.split(','), curStr,
+ curQuote, lastPos, remainder="", str, list = [],
+ curAddress, address, addressArr = [], name, email, i, len;
+ var rightEnd;
+
+ // separate quoted text from text parts
+ for(i=0, len=parts.length; i<len; i++){
+ str = "";
+
+ curStr = (remainder+parts[i]).trim();
+
+ curQuote = curStr.charAt(0);
+ if(curQuote == "'" || curQuote == '"'){
+ rightEnd= curStr.indexOf("<");
+ if(rightEnd == -1)rightEnd= curStr.length-1;
+ lastPos = curStr.lastIndexOf(curQuote,rightEnd);
+
+ if(!lastPos){
+ remainder = remainder+parts[i]+",";
+ continue;
+ }else{
+ remainder = "";
+ str = curStr.substring(1, lastPos).trim();
+ address = curStr.substr(lastPos+1).trim();
+ }
+
+ }else{
+ address = curStr;
+ }
+
+ list.push({name: str, address: address, original: curStr});
+ }
+
+ // find e-mail addresses and user names
+ for(i=0, len=list.length; i<len; i++){
+ curAddress = list[i];
+
+ email = false;
+ name = false;
+
+ name = curAddress.name;
+
+ address = curAddress.address.replace(/<([^>]+)>/, function(original, addr){
+ email = addr.indexOf("@")>=0 && addr;
+ return email ? "" : original;
+ }).trim();
+
+ if(!email){
+ address = address.replace(/(\S+@\S+)/, function(original, m){
+ email = m;
+ return email ? "" : original;
+ });
+ }
+
+ if(!name){
+ if(email){
+ email = email.replace(/\(([^)]+)\)/,function(original, n){
+ name = n;
+ return "";
+ });
+ }
+ if(!name){
+ name = address.replace(/"/g,"").trim();
+ }
+ }
+
+ // just in case something got mixed up
+ if(!email && name.indexOf("@")>=0){
+ email = name;
+ name = false;
+ }
+
+ if(name || email){
+ name = (name || "").replace(/%27/g, "'").replace(/%22/g, "\"");
+ email = (email || "").replace(/%27/g, "'").replace(/%22/g, "\"");
+ addressArr.push({address: email, name: name});
+
+ }
+ }
+ return addressArr;
+};
+
+/**
+ * mime.parseMimeWords(str) -> String
+ * - str (String): string to be parsed
+ *
+ * Parses mime-words into UTF-8 strings
+ **/
+this.parseMimeWords = function(str){
+ return str.replace(/=\?[^?]+\?[QqBb]\?[^?]+\?=/g, (function(a){
+ return this.decodeMimeWord(a);
+ }).bind(this));
+}
+
+/**
+ * mime.parseHeaderLine(line) -> Object
+ * - line (String): a line from a message headers
+ *
+ * Parses a header line to search for additional parameters.
+ * For example with "text/plain; charset=utf-8" the output would be
+ * - defaultValue = text/plain
+ * - charset = utf-8
+ **/
+this.parseHeaderLine = function(line){
+ if(!line)
+ return {};
+ var result = {}, parts = line.split(";"), pos;
+ for(var i=0, len = parts.length; i<len; i++){
+ pos = parts[i].indexOf("=");
+ if(pos<0){
+ result[!i?"defaultValue":"i-"+i] = parts[i].trim();
+ }else{
+ result[parts[i].substr(0,pos).trim().toLowerCase()] = parts[i].substr(pos+1).trim();
+ }
+ }
+ return result;
+}
+
+
+/* Helper functions */
+
+/**
+ * lineEdges(str) -> String
+ * - str (String): String to be processed
+ *
+ * Replaces all spaces and tabs in the beginning and end of the string
+ * with quoted printable encoded chars. Needed by [[encodeQuotedPrintable]]
+ **/
+function lineEdges(str){
+ str = str.replace(/^[ \t]+/gm, function(wsc){
+ return wsc.replace(/ /g,"=20").replace(/\t/g,"=09");
+ });
+
+ str = str.replace(/[ \t]+$/gm, function(wsc){
+ return wsc.replace(/ /g,"=20").replace(/\t/g,"=09");
+ });
+ return str;
+}
+
+/**
+ * fromCharset(charset, buffer, keep_buffer) -> String | Buffer
+ * - charset (String): Source charset
+ * - buffer (Buffer): Buffer in <charset>
+ * - keep_buffer (Boolean): If true, return buffer, otherwise UTF-8 string
+ *
+ * Converts a buffer in <charset> codepage into UTF-8 string
+ **/
+function fromCharset(charset, buffer, keep_buffer){
+ var iconv = new Iconv(charset,'UTF-8'),
+ buffer = iconv.convert(buffer);
+ return keep_buffer?buffer:buffer.toString("utf-8");
+}
+
+/**
+ * toCharset(charset, buffer) -> Buffer
+ * - charset (String): Source charset
+ * - buffer (Buffer): Buffer in UTF-8 or string
+ *
+ * Converts a string or buffer to <charset> codepage
+ **/
+function toCharset(charset, buffer){
+ var iconv = new Iconv('UTF-8',charset);
+ return iconv.convert(buffer);
+}
+
+/**
+ * decodeBytestreamUrlencoding(encoded_string) -> Buffer
+ * - encoded_string (String): String in urlencode coding
+ *
+ * Converts an urlencoded string into a bytestream buffer. If the used
+ * charset is known the resulting string can be converted to UTF-8 with
+ * [[fromCharset]].
+ * NB! For UTF-8 use decodeURIComponent and for Latin 1 decodeURL instead
+ **/
+function decodeBytestreamUrlencoding(encoded_string){
+ var c, i, j=0, prcnts = encoded_string.match(/%/g) || "",
+ buffer_length = encoded_string.length - (prcnts.length*2),
+ buffer = new Buffer(buffer_length);
+
+ for(var i=0; i<encoded_string.length; i++){
+ c = encoded_string.charCodeAt(i);
+ if(c=="37"){ // %
+ c = parseInt(encoded_string.substr(i+1,2), 16);
+ i+=2;
+ }
+ buffer[j++] = c;
+ }
+ return buffer;
+}
+
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/package.json b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/package.json
new file mode 100644
index 0000000..d807316
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib-noiconv/package.json
@@ -0,0 +1,35 @@
+{
+ "name": "mimelib-noiconv",
+ "description": "MIME functions to encode/decode e-mails etc.",
+ "version": "0.1.9",
+ "author": {
+ "name": "Andris Reinman"
+ },
+ "homepage": "http://github.com/andris9/mimelib",
+ "maintainers": [
+ {
+ "name": "andris",
+ "email": "andris@node.ee"
+ }
+ ],
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/andris9/mimelib.git"
+ },
+ "main": ".",
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://github.com/andris9/mimelib/blob/master/LICENSE"
+ }
+ ],
+ "dependencies": {},
+ "keywords": [
+ "e-mail",
+ "mime",
+ "email"
+ ],
+ "readme": "# mimelib\n\n*mimelib* is a collection of useful functions to deal with mime-encoded data.\n\n## Reference\n\nSee [API reference](/andris9/mimelib/blob/master/doc.md) for documentation\n\n## Installation\n\nInstall with *npm*\n\n npm install mimelib-noiconv\n \n## Usage\n\n var mimelib = require(\"mimelib-noiconv\");\n",
+ "_id": "mimelib-noiconv@0.1.9",
+ "_from": "mimelib-noiconv@*"
+}
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/package.json b/tools/node_modules/nodemailer/node_modules/mailcomposer/package.json
new file mode 100644
index 0000000..fe0755f
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "mailcomposer",
+ "description": "Compose E-Mail messages",
+ "version": "0.1.15",
+ "author": {
+ "name": "Andris Reinman"
+ },
+ "maintainers": [
+ {
+ "name": "andris",
+ "email": "andris@node.ee"
+ }
+ ],
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/andris9/mailcomposer.git"
+ },
+ "scripts": {
+ "test": "nodeunit test/"
+ },
+ "main": "./lib/mailcomposer",
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://github.com/andris9/mailcomposer/blob/master/LICENSE"
+ }
+ ],
+ "dependencies": {
+ "mimelib-noiconv": "*"
+ },
+ "devDependencies": {
+ "nodeunit": "*",
+ "mailparser": "*"
+ },
+ "engine": {
+ "node": ">=0.4"
+ },
+ "keywords": [
+ "e-mail",
+ "mime",
+ "parser"
+ ],
+ "readme": "# mailcomposer\n\n**mailcomposer** is a Node.JS module for generating e-mail messages that can be\nstreamed to SMTP or file. \n\nThis is a standalone module that only generates raw e-mail source, you need to \nwrite your own or use an existing transport mechanism (SMTP client, Amazon SES, \nSendGrid etc). **mailcomposer** frees you from the tedious task of generating \n[rfc822](http://tools.ietf.org/html/rfc2822) compatible messages.\n\n[![Build Status](https://secure.travis-ci.org/andris9/mailcomposer.png)](http://travis-ci.org/andris9/mailcomposer)\n\n**mailcomposer** supports:\n\n * **Unicode** to use any characters ✔\n * **HTML** content as well as **plain text** alternative\n * **Attachments** and streaming for larger files (use strings, buffers, files or binary streams as attachments)\n * **Embedded images** in HTML\n * **DKIM** signing\n * usage of **your own** transport mechanism\n\n## Support mailcomposer development\n\n[![Donate to author](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DB26KWR2BQX5W)\n\n## Installation\n\nInstall through NPM\n\n npm install mailcomposer\n\n## Usage\n\n### Include mailcomposer module\n\n var MailComposer = require(\"mailcomposer\").MailComposer;\n\n### Create a new `MailComposer` instance\n\n var mailcomposer = new MailComposer([options]);\n\nWhere `options` is an optional options object with the following possible properties:\n\n * **escapeSMTP** - if set replaces dots in the beginning of a line with double dots\n * **encoding** - sets transfer encoding for the textual parts (defaults to `\"quoted-printable\"`)\n * **keepBcc** - if set to true, includes `Bcc:` field in the message headers. Useful for *sendmail* command. \n\n### Simple example\n\nThe following example generates a simple e-mail message with plaintext and html\nbody.\n\n var MailComposer = require(\"mailcomposer\").MailComposer;\n mailcomposer = new MailComposer(),\n fs = require(\"fs\");\n \n // add additional header field\n mailcomposer.addHeader(\"x-mailer\", \"Nodemailer 1.0\");\n \n // setup message data\n mailcomposer.setMessageOption({\n from: \"andris@tr.ee\",\n to: \"andris@node.ee\",\n body: \"Hello world!\",\n html: \"<b>Hello world!</b>\"\n }); \n \n mailcomposer.streamMessage();\n \n // pipe the output to a file\n mailcomposer.pipe(fs.createWriteStream(\"test.eml\"));\n\nThe output for such a script (the contents for \"test.eml\") would look like:\n\n MIME-Version: 1.0\n X-Mailer: Nodemailer 1.0\n From: andris@tr.ee\n To: andris@node.ee\n Content-Type: multipart/alternative;\n boundary=\"----mailcomposer-?=_1-1328088797399\"\n \n ------mailcomposer-?=_1-1328088797399\n Content-Type: text/plain; charset=utf-8\n Content-Transfer-Encoding: quoted-printable\n \n Hello world!\n ------mailcomposer-?=_1-1328088797399\n Content-Type: text/html; charset=utf-8\n Content-Transfer-Encoding: quoted-printable\n \n <b>Hello world!</b>\n ------mailcomposer-?=_1-1328088797399--\n\n## API\n\n### Add custom headers\n\nHeaders can be added with `mailcomposer.addHeader(key, value)`\n\n var mailcomposer = new MailComposer();\n mailcomposer.addHeader(\"x-mailer\", \"Nodemailer 1.0\");\n\nIf you add an header value with the same key several times, all of the values will be used\nin the generated header. For example:\n\n mailcomposer.addHeader(\"x-mailer\", \"Nodemailer 1.0\");\n mailcomposer.addHeader(\"x-mailer\", \"Nodemailer 2.0\");\n \nWill be generated into\n\n ...\n X-Mailer: Nodemailer 1.0\n X-Mailer: Nodemailer 2.0\n ...\n\nThe contents of the field value is not edited in any way (except for the folding),\nso if you want to use unicode symbols you need to escape these to mime words\nby yourself. Exception being object values - in this case the object\nis automatically JSONized and mime encoded.\n\n // using objects as header values is allowed (will be converted to JSON)\n var apiOptions = {};\n apiOptions.category = \"newuser\";\n apiOptions.tags = [\"user\", \"web\"];\n mailcomposer.addHeader(\"X-SMTPAPI\", apiOptions)\n\n### Add message parts\n\nYou can set message sender, receiver, subject line, message body etc. with\n`mailcomposer.setMessageOption(options)` where options is an object with the\ndata to be set. This function overwrites any previously set values with the\nsame key\n\nThe following example creates a simple e-mail with sender being `andris@tr.ee`, \nreceiver `andris@node.ee` and plaintext part of the message as `Hello world!`:\n\n mailcomposer.setMessageOption({\n from: \"andris@tr.ee\",\n to: \"andris@node.ee\",\n body: \"Hello world!\"\n }); \n\nPossible options that can be used are (all fields accept unicode):\n\n * **from** (alias `sender`) - the sender of the message. If several addresses are given, only the first one will be used\n * **to** - receivers for the `To:` field\n * **cc** - receivers for the `Cc:` field\n * **bcc** - receivers for the `Bcc:` field\n * **replyTo** (alias `reply_to`) - e-mail address for the `Reply-To:` field\n * **inReplyTo** - The message-id this message is replying\n * **references** - Message-id list\n * **subject** - the subject line of the message\n * **body** (alias `text`) - the plaintext part of the message\n * **html** - the HTML part of the message\n * **envelope** - optional SMTP envelope, if auto generated envelope is not suitable\n\nThis method can be called several times\n\n mailcomposer.setMessageOption({from: \"andris@tr.ee\"});\n mailcomposer.setMessageOption({to: \"andris@node.ee\"});\n mailcomposer.setMessageOption({body: \"Hello world!\"});\n\nTrying to set the same key several times will yield in overwrite\n\n mailcomposer.setMessageOption({body: \"Hello world!\"});\n mailcomposer.setMessageOption({body: \"Hello world?\"});\n // body contents will be \"Hello world?\"\n\n### Address format\n\nAll e-mail address fields take structured e-mail lists (comma separated)\nas the input. Unicode is allowed for all the parts (receiver name, e-mail username\nand domain) of the address. If the domain part contains unicode symbols, it is\nautomatically converted into punycode, user part will be converted into UTF-8\nmime word.\n\nE-mail addresses can be a plain e-mail addresses\n\n username@example.com\n\nor with a formatted name\n\n 'Ноде Майлер' <username@example.com>\n\nOr in case of comma separated lists, the formatting can be mixed\n\n username@example.com, 'Ноде Майлер' <username@example.com>, \"Name, User\" <username@example.com>\n\n### SMTP envelope\n\nSMTP envelope is usually auto generated from `from`, `to`, `cc` and `bcc` fields but\nif for some reason you want to specify it yourself, you can do it with `envelope` property.\n\n`envelope` is an object with the following params: `from`, `to`, `cc` and `bcc` just like\nwith regular mail options. You can also use the regular address format.\n\n mailOptions = {\n ...,\n from: \"mailer@node.ee\",\n to: \"daemon@node.ee\",\n envelope: {\n from: \"Daemon <deamon@node.ee>\",\n to: \"mailer@node.ee, Mailer <mailer2@node.ee>\"\n }\n }\n\n### Add attachments\n\nAttachments can be added with `mailcomposer.addAttachment(attachment)` where\n`attachment` is an object with attachment (meta)data with the following possible\nproperties:\n\n * **fileName** (alias `filename`) - filename to be reported as the name of the attached file, use of unicode is allowed\n * **cid** - content id for using inline images in HTML message source\n * **contents** - String or a Buffer contents for the attachment\n * **filePath** - path to a file or an URL if you want to stream the file instead of including it (better for larger attachments)\n * **streamSource** - Stream object for arbitrary binary streams if you want to stream the contents (needs to support *pause*/*resume*)\n * **contentType** - content type for the attachment, if not set will be derived from the `fileName` property\n * **contentDisposition** - content disposition type for the attachment, defaults to \"attachment\" \n * **userAgent** - User-Agent string to be used if the fileName points to an URL\n\nOne of `contents`, `filePath` or `streamSource` must be specified, if none is \npresent, the attachment will be discarded. Other fields are optional.\n\nAttachments can be added as many as you want.\n\n**Using embedded images in HTML**\n\nAttachments can be used as embedded images in the HTML body. To use this \nfeature, you need to set additional property of the attachment - `cid` \n(unique identifier of the file) which is a reference to the attachment file. \nThe same `cid` value must be used as the image URL in HTML (using `cid:` as \nthe URL protocol, see example below).\n\nNB! the cid value should be as unique as possible!\n\n var cid_value = Date.now() + '.image.jpg';\n \n var html = 'Embedded image: <img src=\"cid:' + cid_value + '\" />';\n \n var attachment = {\n fileName: \"image.png\",\n filePath: \"/static/images/image.png\",\n cid: cid_value\n };\n\n### DKIM Signing\n\n**mailcomposer** supports DKIM signing with very simple setup. Use this with caution \nthough since the generated message needs to be buffered entirely before it can be\nsigned - in this case the streaming capability offered by mailcomposer is illusionary,\nthere will only be one `'data'` event with the entire message. Not a big deal with\nsmall messages but might consume a lot of RAM when using larger attachments.\n\nSet up the DKIM signing with `useDKIM` method:\n\n mailcomposer.useDKIM(dkimOptions)\n\nWhere `dkimOptions` includes necessary options for signing\n\n * **domainName** - the domainname that is being used for signing\n * **keySelector** - key selector. If you have set up a TXT record with DKIM public key at *zzz._domainkey.example.com* then `zzz` is the selector\n * **privateKey** - DKIM private key that is used for signing as a string\n * **headerFieldNames** - optional colon separated list of header fields to sign, by default all fields suggested by RFC4871 #5.5 are used\n\n**NB!** Currently if several header fields with the same name exists, only the last one (the one in the bottom) is signed.\n\nExample:\n\n mailcomposer.setMessageOption({from: \"andris@tr.ee\"});\n mailcomposer.setMessageOption({to: \"andris@node.ee\"});\n mailcomposer.setMessageOption({body: \"Hello world!\"});\n mailcomposer.useDKIM({\n domainName: \"node.ee\",\n keySelector: \"dkim\",\n privateKey: fs.readFileSync(\"private_key.pem\")\n });\n\n### Start streaming\n\nWhen the message data is setup, streaming can be started. After this it is not\npossible to add headers, attachments or change body contents.\n\n mailcomposer.streamMessage();\n\nThis generates `'data'` events for the message headers and body and final `'end'` event.\nAs `MailComposer` objects are Stream instances, these can be piped\n\n // save the output to a file\n mailcomposer.streamMessage();\n mailcomposer.pipe(fs.createWriteStream(\"out.txt\"));\n\n## Envelope\n\nEnvelope can be generated with an `getEnvelope()` which returns an object\nthat includes a `from` address (string) and a list of `to` addresses (array of\nstrings) suitable for forwarding to a SMTP server as `MAIL FROM:` and `RCPT TO:`.\n\n console.log(mailcomposer.getEnvelope());\n // {from:\"sender@example.com\", to:[\"receiver@example.com\"]}\n\n**NB!** both `from` and `to` properties might be missing from the envelope object\nif corresponding addresses were not detected from the e-mail.\n\n## Running tests\n\nTests are run with [nodeunit](https://github.com/caolan/nodeunit)\n\nRun\n\n npm test\n\nor alternatively\n\n node run_tests.js\n\n## License\n\n**MIT**",
+ "_id": "mailcomposer@0.1.15",
+ "_from": "mailcomposer@>= 0.1.15"
+}
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/test/dkim.js b/tools/node_modules/nodemailer/node_modules/mailcomposer/test/dkim.js
new file mode 100644
index 0000000..6d18251
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/test/dkim.js
@@ -0,0 +1,47 @@
+var testCase = require('nodeunit').testCase,
+ dkim = require("../lib/dkim"),
+ fs = require("fs");
+
+
+exports["Canonicalizer tests"] = {
+ "Relaxed body": function(test){
+ // dkim.org samples
+ var body = " C \r\nD \t E\r\n\r\n\r\n";
+ test.equal(" C\r\nD E\r\n", dkim.DKIMCanonicalizer.relaxedBody(body));
+ test.done();
+ },
+ "Relaxed body short": function(test){
+ // dkim.org samples
+ var body = " C \r\nD \t E";
+ test.equal(" C\r\nD E\r\n", dkim.DKIMCanonicalizer.relaxedBody(body));
+ test.done();
+ },
+ "Relaxed headers": function(test){
+ var headers = "A: X\r\nB: Y\t\r\n\tZ \r\n";
+ test.equal("a:X\r\nb:Y Z\r\n", dkim.DKIMCanonicalizer.relaxedHeaders(headers, "a:b").headers);
+ test.done();
+ }
+}
+
+exports["General tests"] = {
+ "Unicode domain": function(test){
+ var mail = "From: andris@node.ee\r\nTo:andris@kreata.ee\r\n\r\nHello world!";
+ var dkimField = dkim.DKIMSign(mail,{
+ domainName: "müriaad-polüteism.info",
+ keySelector: "dkim",
+ privateKey: fs.readFileSync(__dirname+"/test_private.pem")
+ });
+ test.equal(dkimField.replace(/\r?\n\s*/g, "").replace(/\s+/g, " "), "DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;d=xn--mriaad-polteism-zvbj.info; q=dns/txt; s=dkim;bh=z6TUz85EdYrACGMHYgZhJGvVy5oQI0dooVMKa2ZT7c4=; h=from:to;b=oBJ1MkwEkftfXa2AK4Expjp2xgIcAR43SVrftSEHVQ6F1SlGjP3EKP+cn/hLkhUel3rY0icthk/myDu6uhTBmM6DMtzIBW/7uQd6q9hfgaiYnw5Iew2tZc4TzBEYSdKi")
+ test.done();
+ },
+ "Normal domain": function(test){
+ var mail = "From: andris@node.ee\r\nTo:andris@kreata.ee\r\n\r\nHello world!";
+ var dkimField = dkim.DKIMSign(mail,{
+ domainName: "node.ee",
+ keySelector: "dkim",
+ privateKey: fs.readFileSync(__dirname+"/test_private.pem")
+ });
+ test.equal(dkimField.replace(/\r?\n\s*/g, "").replace(/\s+/g, " "), "DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=node.ee; q=dns/txt;s=dkim; bh=z6TUz85EdYrACGMHYgZhJGvVy5oQI0dooVMKa2ZT7c4=; h=from:to;b=pVd+Dp+EjmYBcc1AWlBAP4ESpuAJ2WMS4gbxWLoeUZ1vZRodVN7K9UXvcCsLuqjJktCZMN2+8dyEUaYW2VIcxg4sVBCS1wqB/tqYZ/gxXLnG2/nZf4fyD2vxltJP4pDL");
+ test.done();
+ }
+} \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/test/mailcomposer.js b/tools/node_modules/nodemailer/node_modules/mailcomposer/test/mailcomposer.js
new file mode 100644
index 0000000..0a0d9fd
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/test/mailcomposer.js
@@ -0,0 +1,1085 @@
+var testCase = require('nodeunit').testCase,
+ MailComposer = require("../lib/mailcomposer").MailComposer,
+ toPunycode = require("../lib/punycode"),
+ MailParser = require("mailparser").MailParser,
+ fs = require("fs"),
+ http = require("http");
+
+
+var HTTP_PORT = 9437;
+
+exports["General tests"] = {
+
+ "Create a new MailComposer object": function(test){
+ var mailcomposer = new MailComposer();
+ test.equal(typeof mailcomposer.on, "function");
+ test.equal(typeof mailcomposer.emit, "function");
+ test.done();
+ },
+
+ "Normalize key names": function(test){
+ var normalizer = MailComposer.prototype._normalizeKey;
+
+ test.equal(normalizer("abc"), "Abc");
+ test.equal(normalizer("aBC"), "Abc");
+ test.equal(normalizer("ABC"), "Abc");
+ test.equal(normalizer("a-b-c"), "A-B-C");
+ test.equal(normalizer("ab-bc"), "Ab-Bc");
+ test.equal(normalizer("ab-bc-cd"), "Ab-Bc-Cd");
+ test.equal(normalizer("AB-BC-CD"), "Ab-Bc-Cd");
+ test.equal(normalizer("mime-version"), "MIME-Version"); // special case
+
+ test.done();
+ },
+
+ "Add header": function(test){
+ var mc = new MailComposer();
+ test.equal(typeof mc._headers["Test-Key"], "undefined");
+ mc.addHeader("test-key", "first");
+ test.equal(mc._headers["Test-Key"], "first");
+ mc.addHeader("test-key", "second");
+ test.deepEqual(mc._headers["Test-Key"], ["first","second"]);
+ mc.addHeader("test-key", "third");
+ test.deepEqual(mc._headers["Test-Key"], ["first","second","third"]);
+ test.done();
+ },
+
+ "Get header": function(test){
+ var mc = new MailComposer();
+ test.equal(mc._getHeader("MIME-Version"), "1.0");
+ test.equal(mc._getHeader("test-key"), "");
+ mc.addHeader("test-key", "first");
+ test.equal(mc._getHeader("test-key"), "first");
+ mc.addHeader("test-key", "second");
+ test.deepEqual(mc._getHeader("test-key"), ["first", "second"]);
+ test.done();
+ },
+
+ "Uppercase header keys": function(test){
+ var mc = new MailComposer();
+
+ mc.addHeader("X-TEST", "first");
+ test.equal(mc._headers["X-TEST"], "first");
+
+ mc.addHeader("TEST", "second");
+ test.equal(mc._headers["Test"], "second");
+
+ test.done();
+ },
+
+ "Set object header": function(test){
+ var mc = new MailComposer();
+
+ var testObj = {
+ stringValue: "String with unicode symbols: ÕÄÖÜŽŠ",
+ arrayValue: ["hello ÕÄÖÜ", 12345],
+ objectValue: {
+ customerId: "12345"
+ }
+ };
+
+ mc.addHeader("x-mytest-string", "first");
+ mc.addHeader("x-mytest-json", testObj);
+
+ mc.streamMessage();
+
+ //mc.on("data", function(c){console.log(c.toString("utf-8"))})
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.headers['x-mytest-string'], "first");
+ test.deepEqual(JSON.parse(mail.headers['x-mytest-json']), testObj);
+ //console.log(mail)
+ test.done();
+ });
+ },
+
+ "Add message option": function(test){
+ var mc = new MailComposer();
+ test.equal(typeof mc._message.subject, "undefined");
+
+ mc.setMessageOption({
+ subject: "Test1",
+ body: "Test2",
+ nonexistent: "Test3"
+ });
+
+ test.equal(mc._message.subject, "Test1");
+ test.equal(mc._message.body, "Test2");
+ test.equal(typeof mc._message.nonexistent, "undefined");
+
+ mc.setMessageOption({
+ subject: "Test4"
+ });
+
+ test.equal(mc._message.subject, "Test4");
+ test.equal(mc._message.body, "Test2");
+
+ test.done();
+ },
+
+ "Detect mime type": function(test){
+ var mc = new MailComposer();
+
+ test.equal(mc._getMimeType("test.txt"), "text/plain");
+ test.equal(mc._getMimeType("test.unknown"), "application/octet-stream");
+
+ test.done();
+ },
+
+ "keepBcc off": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({bcc: "andris@node.ee"});
+ mc._buildMessageHeaders();
+ test.ok(!mc._getHeader("Bcc"));
+ test.done();
+ },
+
+ "keepBcc on": function(test){
+ var mc = new MailComposer({keepBcc: true});
+ mc.setMessageOption({bcc: "andris@node.ee"});
+ mc._buildMessageHeaders();
+ test.equal(mc._getHeader("Bcc"), "andris@node.ee");
+ test.done();
+ }
+};
+
+
+exports["Text encodings"] = {
+ "Punycode": function(test){
+ test.equal(toPunycode("andris@age.ee"), "andris@age.ee");
+ test.equal(toPunycode("andris@äge.ee"), "andris@xn--ge-uia.ee");
+ test.done();
+ },
+
+ "Mime words": function(test){
+ var mc = new MailComposer();
+ test.equal(mc._encodeMimeWord("Tere"), "Tere");
+ test.equal(mc._encodeMimeWord("Tere","Q"), "Tere");
+ test.equal(mc._encodeMimeWord("Tere","B"), "Tere");
+
+ // simple
+ test.equal(mc._encodeMimeWord("äss"), "=?UTF-8?Q?=C3=A4ss?=");
+ test.equal(mc._encodeMimeWord("äss","B"), "=?UTF-8?B?"+(new Buffer("äss","utf-8").toString("base64"))+"?=");
+
+ //multiliple
+ test.equal(mc._encodeMimeWord("äss tekst on see siin või kuidas?","Q", 20), "=?UTF-8?Q?=C3=A4ss?= =?UTF-8?Q?_tekst_o?= =?UTF-8?Q?n_see_si?= =?UTF-8?Q?in_v?= =?UTF-8?Q?=C3=B5i_?= =?UTF-8?Q?kuidas?= =?UTF-8?Q?=3F?=");
+
+ test.done();
+ },
+
+ "Addresses": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ sender: '"Jaanuar Veebruar, Märts" <märts@märts.eu>'
+ });
+
+ test.equal(mc._message.from, "\"=?UTF-8?Q?Jaanuar_Veebruar,_M=C3=A4rts?=\" <=?UTF-8?Q?m=C3=A4rts?=@xn--mrts-loa.eu>");
+
+ mc.setMessageOption({
+ sender: 'aavik <aavik@node.ee>'
+ });
+
+ test.equal(mc._message.from, '"aavik" <aavik@node.ee>');
+
+ mc.setMessageOption({
+ sender: '<aavik@node.ee>'
+ });
+
+ test.equal(mc._message.from, 'aavik@node.ee');
+
+ mc.setMessageOption({
+ sender: '<aavik@märts.eu>'
+ });
+
+ test.equal(mc._message.from, 'aavik@xn--mrts-loa.eu');
+
+ // multiple
+
+ mc.setMessageOption({
+ sender: '<aavik@märts.eu>, juulius@node.ee, "Node, Master" <node@node.ee>'
+ });
+
+ test.equal(mc._message.from, 'aavik@xn--mrts-loa.eu, juulius@node.ee, "Node, Master" <node@node.ee>');
+
+ test.done();
+ },
+
+ "Invalid subject": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ subject: "tere\ntere!"
+ });
+
+ test.equal(mc._message.subject, "tere tere!");
+ test.done();
+ },
+
+ "Long header line": function(test){
+ var mc = new MailComposer();
+
+ mc._headers = {
+ From: "a very log line, \"=?UTF-8?Q?Jaanuar_Veebruar,_M=C3=A4rts?=\" <=?UTF-8?Q?m=C3=A4rts?=@xn--mrts-loa.eu>"
+ };
+
+ mc.on("data", function(chunk){
+ test.ok(chunk.toString().trim().match(/From\:\s[^\r\n]+\r\n\s+[^\r\n]+/));
+ test.done();
+ });
+ mc._composeHeader();
+
+ }
+
+};
+
+exports["Mail related"] = {
+ "Envelope": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ sender: '"Jaanuar Veebruar, Märts" <märts@märts.eu>',
+ to: '<aavik@märts.eu>, juulius@node.ee',
+ cc: '"Node, Master" <node@node.ee>'
+ });
+
+ test.deepEqual(mc._envelope, {from:[ 'märts@xn--mrts-loa.eu' ],to:[ 'aavik@xn--mrts-loa.eu', 'juulius@node.ee'], cc:['node@node.ee' ]});
+ test.done();
+ },
+
+ "User defined envelope": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ sender: '"Jaanuar Veebruar, Märts" <märts@märts.eu>',
+ envelope: {
+ from: "Andris <andris@tr.ee>",
+ to: ["Andris <andris@tr.ee>, Node <andris@node.ee>", "aavik@märts.eu", "juulius@gmail.com"],
+ cc: "trips@node.ee"
+ },
+ to: '<aavik@märts.eu>, juulius@node.ee',
+ cc: '"Node, Master" <node@node.ee>'
+ });
+
+ test.deepEqual(mc._envelope, {userDefined: true, from:[ 'andris@tr.ee' ],to:[ 'andris@tr.ee', 'andris@node.ee', 'aavik@xn--mrts-loa.eu', 'juulius@gmail.com'], "cc":['trips@node.ee']});
+ test.done();
+ },
+
+ "Add attachment": function(test){
+ var mc = new MailComposer();
+ mc.addAttachment();
+ test.equal(mc._attachments.length, 0);
+
+ mc.addAttachment({filePath:"/tmp/var.txt"});
+ test.equal(mc._attachments[0].contentType, "text/plain");
+ test.equal(mc._attachments[0].fileName, "var.txt");
+
+ mc.addAttachment({contents:"/tmp/var.txt"});
+ test.equal(mc._attachments[1].contentType, "application/octet-stream");
+ test.equal(mc._attachments[1].fileName, undefined);
+
+ mc.addAttachment({filePath:"/tmp/var.txt", fileName:"test.txt"});
+ test.equal(mc._attachments[2].fileName, "test.txt");
+
+ test.done();
+ },
+
+ "Default attachment disposition": function(test){
+ var mc = new MailComposer();
+ mc.addAttachment();
+ test.equal(mc._attachments.length, 0);
+
+ mc.addAttachment({filePath:"/tmp/var.txt"});
+ test.equal(mc._attachments[0].contentDisposition, undefined);
+
+ test.done();
+ },
+
+ "Set attachment disposition": function(test){
+ var mc = new MailComposer();
+ mc.addAttachment();
+ test.equal(mc._attachments.length, 0);
+
+ mc.addAttachment({filePath:"/tmp/var.txt", contentDisposition: "inline"});
+ test.equal(mc._attachments[0].contentDisposition, "inline");
+
+ test.done();
+ },
+
+ "Generate envelope": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ sender: '"Jaanuar Veebruar, Märts" <märts@märts.eu>, karu@ahven.ee',
+ to: '<aavik@märts.eu>, juulius@node.ee',
+ cc: '"Node, Master" <node@node.ee>'
+ });
+
+ test.deepEqual(mc.getEnvelope(), {from: 'märts@xn--mrts-loa.eu',to:[ 'aavik@xn--mrts-loa.eu', 'juulius@node.ee', 'node@node.ee' ], stamp: 'Postage paid, Par Avion'});
+ test.done();
+ },
+
+ "Generate user defined envelope": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ sender: '"Jaanuar Veebruar, Märts" <märts@märts.eu>, karu@ahven.ee',
+ to: '<aavik@märts.eu>, juulius@node.ee',
+ envelope: {
+ from: "Andris <andris@tr.ee>",
+ to: ["Andris <andris@tr.ee>, Node <andris@node.ee>", "aavik@märts.eu", "juulius@gmail.com"],
+ cc: "trips@node.ee"
+ },
+ cc: '"Node, Master" <node@node.ee>'
+ });
+
+ test.deepEqual(mc.getEnvelope(), {from: 'andris@tr.ee', to:[ 'andris@tr.ee', 'andris@node.ee', 'aavik@xn--mrts-loa.eu', 'juulius@gmail.com', 'trips@node.ee'], stamp: 'Postage paid, Par Avion'});
+ test.done();
+ },
+
+ "Generate Headers": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ sender: '"Jaanuar Veebruar, Märts" <märts@märts.eu>, karu@ahven.ee',
+ to: '<aavik@märts.eu>, juulius@node.ee',
+ cc: '"Node, Master" <node@node.ee>',
+ replyTo: 'julla@pulla.ee',
+ subject: "Tere õkva!"
+ });
+
+ mc.on("data", function(chunk){
+ chunk = (chunk || "").toString("utf-8");
+ test.ok(chunk.match(/^(?:(?:[\s]+|[a-zA-Z0-0\-]+\:)[^\r\n]+\r\n)+\r\n$/));
+ test.done();
+ });
+
+ mc._composeHeader();
+ }
+};
+
+exports["Mime tree"] = {
+ "No contents": function(test){
+ test.expect(4);
+
+ var mc = new MailComposer();
+ mc._composeMessage();
+
+ test.ok(!mc._message.tree.boundary);
+ test.equal(mc._getHeader("Content-Type").split(";").shift().trim(), "text/plain");
+ test.equal(mc._message.tree.childNodes.length, 0);
+
+ for(var i=0, len = mc._message.flatTree.length; i<len; i++){
+ if(typeof mc._message.flatTree[i] == "object"){
+ test.equal(mc._message.flatTree[i].contents, "\r\n");
+ }
+ }
+
+ test.done();
+ },
+ "Text contents": function(test){
+ test.expect(4);
+
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ body: "test"
+ });
+ mc._composeMessage();
+
+ test.ok(!mc._message.tree.boundary);
+ test.equal(mc._getHeader("Content-Type").split(";").shift().trim(), "text/plain");
+ test.equal(mc._message.tree.childNodes.length, 0);
+
+ for(var i=0, len = mc._message.flatTree.length; i<len; i++){
+ if(typeof mc._message.flatTree[i] == "object"){
+ test.equal(mc._message.flatTree[i].contents, "test");
+ }
+ }
+
+ test.done();
+ },
+ "HTML contents": function(test){
+ test.expect(4);
+
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ html: "<b>test</b>"
+ });
+ mc._composeMessage();
+
+ test.ok(!mc._message.tree.boundary);
+ test.equal(mc._getHeader("Content-Type").split(";").shift().trim(), "text/html");
+ test.equal(mc._message.tree.childNodes.length, 0);
+
+ for(var i=0, len = mc._message.flatTree.length; i<len; i++){
+ if(typeof mc._message.flatTree[i] == "object"){
+ test.equal(mc._message.flatTree[i].contents, "<b>test</b>");
+ }
+ }
+
+ test.done();
+ },
+ "HTML and text contents": function(test){
+ test.expect(5);
+
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ body: "test",
+ html: "test"
+ });
+ mc._composeMessage();
+
+ test.equal(mc._message.tree.childNodes.length, 2);
+ test.equal(mc._getHeader("Content-Type").split(";").shift().trim(), "multipart/alternative");
+ test.ok(mc._message.tree.boundary);
+
+ for(var i=0, len = mc._message.flatTree.length; i<len; i++){
+ if(typeof mc._message.flatTree[i] == "object"){
+ test.equal(mc._message.flatTree[i].contents, "test");
+ }
+ }
+
+ test.done();
+ },
+ "Attachment": function(test){
+ test.expect(5);
+
+ var mc = new MailComposer();
+ mc.setMessageOption();
+ mc.addAttachment({contents:"\r\n"});
+ mc._composeMessage();
+
+ test.equal(mc._message.tree.childNodes.length, 2);
+ test.equal(mc._getHeader("Content-Type").split(";").shift().trim(), "multipart/mixed");
+ test.ok(mc._message.tree.boundary);
+
+ for(var i=0, len = mc._message.flatTree.length; i<len; i++){
+ if(typeof mc._message.flatTree[i] == "object"){
+ test.equal(mc._message.flatTree[i].contents, "\r\n");
+ }
+ }
+
+ test.done();
+ },
+ "Several attachments": function(test){
+ test.expect(6);
+
+ var mc = new MailComposer();
+ mc.setMessageOption();
+ mc.addAttachment({contents:"\r\n"});
+ mc.addAttachment({contents:"\r\n"});
+
+ mc._composeMessage();
+
+ test.equal(mc._message.tree.childNodes.length, 3);
+ test.equal(mc._getHeader("Content-Type").split(";").shift().trim(), "multipart/mixed");
+ test.ok(mc._message.tree.boundary);
+
+ for(var i=0, len = mc._message.flatTree.length; i<len; i++){
+ if(typeof mc._message.flatTree[i] == "object"){
+ test.equal(mc._message.flatTree[i].contents, "\r\n");
+ }
+ }
+
+ test.done();
+ },
+ "Attachment and text": function(test){
+ test.expect(7);
+
+ var mc = new MailComposer();
+ mc.setMessageOption();
+ mc.addAttachment({contents:"test"});
+ mc.setMessageOption({
+ body: "test"
+ });
+ mc._composeMessage();
+
+ test.equal(mc._message.tree.childNodes.length, 2);
+ test.equal(mc._getHeader("Content-Type").split(";").shift().trim(), "multipart/mixed");
+ test.ok(mc._message.tree.boundary);
+
+ mc._message.tree.childNodes[0].headers.forEach(function(header){
+ if(header[0]=="Content-Type"){
+ test.equal(header[1].split(";").shift().trim(), "text/plain");
+ }
+ });
+
+ mc._message.tree.childNodes[1].headers.forEach(function(header){
+ if(header[0]=="Content-Type"){
+ test.equal(header[1].split(";").shift().trim(), "application/octet-stream");
+ }
+ });
+
+ for(var i=0, len = mc._message.flatTree.length; i<len; i++){
+ if(typeof mc._message.flatTree[i] == "object"){
+ test.equal(mc._message.flatTree[i].contents, "test");
+ }
+ }
+
+ test.done();
+ },
+ "Attachment and html": function(test){
+ test.expect(7);
+
+ var mc = new MailComposer();
+ mc.setMessageOption();
+ mc.addAttachment({contents:"test"});
+ mc.setMessageOption({
+ html: "test"
+ });
+ mc._composeMessage();
+
+ test.equal(mc._message.tree.childNodes.length, 2);
+ test.equal(mc._getHeader("Content-Type").split(";").shift().trim(), "multipart/mixed");
+ test.ok(mc._message.tree.boundary);
+
+ mc._message.tree.childNodes[0].headers.forEach(function(header){
+ if(header[0]=="Content-Type"){
+ test.equal(header[1].split(";").shift().trim(), "text/html");
+ }
+ });
+
+ mc._message.tree.childNodes[1].headers.forEach(function(header){
+ if(header[0]=="Content-Type"){
+ test.equal(header[1].split(";").shift().trim(), "application/octet-stream");
+ }
+ });
+
+ for(var i=0, len = mc._message.flatTree.length; i<len; i++){
+ if(typeof mc._message.flatTree[i] == "object"){
+ test.equal(mc._message.flatTree[i].contents, "test");
+ }
+ }
+
+ test.done();
+ },
+ "Attachment, html and text": function(test){
+ test.expect(11);
+
+ var mc = new MailComposer();
+ mc.addAttachment({contents:"test"});
+ mc.setMessageOption({
+ body: "test",
+ html: "test"
+ });
+ mc._composeMessage();
+
+ test.equal(mc._message.tree.childNodes.length, 2);
+ test.equal(mc._getHeader("Content-Type").split(";").shift().trim(), "multipart/mixed");
+ test.ok(mc._message.tree.boundary);
+
+ mc._message.tree.childNodes[0].headers.forEach(function(header){
+ if(header[0]=="Content-Type"){
+ test.equal(header[1].split(";").shift().trim(), "multipart/alternative");
+ }
+ });
+
+ test.ok(mc._message.tree.childNodes[0].boundary);
+
+ mc._message.tree.childNodes[0].childNodes[0].headers.forEach(function(header){
+ if(header[0]=="Content-Type"){
+ test.equal(header[1].split(";").shift().trim(), "text/plain");
+ }
+ });
+
+ mc._message.tree.childNodes[0].childNodes[1].headers.forEach(function(header){
+ if(header[0]=="Content-Type"){
+ test.equal(header[1].split(";").shift().trim(), "text/html");
+ }
+ });
+
+ mc._message.tree.childNodes[1].headers.forEach(function(header){
+ if(header[0]=="Content-Type"){
+ test.equal(header[1].split(";").shift().trim(), "application/octet-stream");
+ }
+ });
+
+ for(var i=0, len = mc._message.flatTree.length; i<len; i++){
+ if(typeof mc._message.flatTree[i] == "object"){
+ test.equal(mc._message.flatTree[i].contents, "test");
+ }
+ }
+
+ test.done();
+ }
+
+};
+
+exports["Stream parser"] = {
+ "Text": function(test){
+ var mc = new MailComposer(),
+ file = fs.readFileSync(__dirname+"/textfile.txt").toString("utf-8");
+ mc.setMessageOption({
+ from: "andris@node.ee",
+ to:"andris@tr.ee, andris@kreata.ee",
+ subject: "õäöü",
+ body: file
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.from[0].address, "andris@node.ee");
+ test.equal(mail.to[0].address, "andris@tr.ee");
+ test.equal(mail.to[1].address, "andris@kreata.ee");
+ test.equal(mail.subject, "õäöü");
+ test.equal(mail.text.trim(), file.trim());
+ test.done();
+ });
+ },
+ "HTML": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ html: "<b>test</b>"
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.html.trim(), "<b>test</b>");
+ test.done();
+ });
+ },
+ "HTML and text": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ html: "<b>test</b>",
+ body: "test"
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.text.trim(), "test");
+ test.equal(mail.html.trim(), "<b>test</b>");
+ test.done();
+ });
+ },
+ "Flowed text": function(test){
+ var mc = new MailComposer({encoding:"8bit"}),
+ file = fs.readFileSync(__dirname+"/textfile.txt").toString("utf-8");
+
+ mc.setMessageOption({
+ body: file
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.text.trim(), file.trim());
+ test.done();
+ });
+ },
+ "Attachment as string": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption();
+ mc.addAttachment({
+ fileName: "file.txt",
+ contents: fs.readFileSync(__dirname+"/textfile.txt").toString("utf-8")
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.attachments[0].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ test.done();
+ });
+ },
+ "Attachment as buffer": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption();
+ mc.addAttachment({
+ fileName: "file.txt",
+ contents: fs.readFileSync(__dirname+"/textfile.txt")
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.attachments[0].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ test.done();
+ });
+ },
+ "Attachment file stream": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption();
+ mc.addAttachment({
+ fileName: "file.txt",
+ filePath: __dirname+"/textfile.txt"
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.attachments[0].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ test.done();
+ });
+ },
+ "Attachment source stream": function(test){
+ var mc = new MailComposer();
+
+ var fileStream = fs.createReadStream(__dirname+"/textfile.txt");
+
+ mc.setMessageOption();
+ mc.addAttachment({
+ fileName: "file.txt",
+ streamSource: fileStream
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.attachments[0].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ test.done();
+ });
+ },
+ "Attachment source url": function(test){
+
+ var server = http.createServer(function (req, res) {
+ if(req.url=="/textfile.txt"){
+ fs.createReadStream(__dirname+"/textfile.txt")
+ fs.createReadStream(__dirname+"/textfile.txt").pipe(res);
+ }else{
+ res.writeHead(404, {'Content-Type': 'text/plain'});
+ res.end('Not found!\n');
+ }
+ });
+ server.listen(HTTP_PORT, '127.0.0.1');
+
+ var mc = new MailComposer();
+
+ mc.setMessageOption();
+ mc.addAttachment({
+ fileName: "file.txt",
+ filePath: "http://localhost:"+HTTP_PORT+"/textfile.txt"
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.attachments[0].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ server.close();
+ test.done();
+ });
+ },
+ "Attachment source invalid url": function(test){
+
+ var server = http.createServer(function (req, res) {
+ res.writeHead(404, {'Content-Type': 'text/plain'});
+ res.end('Not found!\n');
+ })
+ server.listen(HTTP_PORT, '127.0.0.1');
+
+ var mc = new MailComposer();
+
+ mc.setMessageOption();
+ mc.addAttachment({
+ fileName: "file.txt",
+ filePath: "http://localhost:"+HTTP_PORT+"/textfile.txt"
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.attachments[0].checksum, "3995d423c7453e472ce0d54e475bae3e");
+ server.close();
+ test.done();
+ });
+ },
+ "Custom User-Agent": function(test){
+
+ var server = http.createServer(function (req, res) {
+ test.equal(req.headers['user-agent'], "test");
+
+ res.writeHead(200, {'Content-Type': 'text/plain'});
+ res.end('OK!\n');
+ })
+ server.listen(HTTP_PORT, '127.0.0.1');
+
+ var mc = new MailComposer();
+
+ mc.setMessageOption();
+ mc.addAttachment({
+ fileName: "file.txt",
+ filePath: "http://localhost:"+HTTP_PORT+"/textfile.txt",
+ userAgent: "test"
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ server.close();
+ test.done();
+ });
+ },
+ "escape SMTP": function(test){
+ var mc = new MailComposer({escapeSMTP: true});
+ mc.setMessageOption({
+ body: ".\r\n."
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.text.trim(), "..\n..");
+ test.done();
+ });
+ },
+ "don't escape SMTP": function(test){
+ var mc = new MailComposer({escapeSMTP: false});
+ mc.setMessageOption({
+ body: ".\r\n."
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.text.trim(), ".\n.");
+ test.done();
+ });
+ },
+ "HTML and text and attachment": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ html: "<b>test</b>",
+ body: "test"
+ });
+ mc.addAttachment({
+ fileName: "file.txt",
+ contents: fs.readFileSync(__dirname+"/textfile.txt").toString("utf-8")
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.text.trim(), "test");
+ test.equal(mail.html.trim(), "<b>test</b>");
+ test.equal(mail.attachments[0].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ test.done();
+ });
+ },
+ "HTML and related attachment": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ html: "<b><img src=\"cid:test@node\"/></b>"
+ });
+ mc.addAttachment({
+ fileName: "file.txt",
+ cid: "test@node",
+ contents: fs.readFileSync(__dirname+"/textfile.txt").toString("utf-8")
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+ /*
+ var d = "";
+ mc.on("data", function(data){
+ d += data.toString();
+ })
+
+ mc.on("end", function(){
+ console.log(d);
+ });
+ */
+
+ mp.on("end", function(mail){
+ test.equal(mc._attachments.length, 0);
+ test.equal(mc._relatedAttachments.length, 1);
+ test.equal(mail.html.trim(), "<b><img src=\"cid:test@node\"/></b>");
+ test.equal(mail.attachments[0].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ test.done();
+ });
+ },
+ "HTML and related plus regular attachment": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ html: "<b><img src=\"cid:test@node\"/></b>"
+ });
+ mc.addAttachment({
+ fileName: "file.txt",
+ cid: "test@node",
+ contents: fs.readFileSync(__dirname+"/textfile.txt").toString("utf-8")
+ });
+ mc.addAttachment({
+ fileName: "file.txt",
+ contents: fs.readFileSync(__dirname+"/textfile.txt").toString("utf-8")
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mc._attachments.length, 1);
+ test.equal(mc._relatedAttachments.length, 1);
+ test.equal(mail.html.trim(), "<b><img src=\"cid:test@node\"/></b>");
+ test.equal(mail.attachments[0].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ test.equal(mail.attachments[1].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ test.done();
+ });
+ },
+ "HTML and text related attachment": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ html: "<b><img src=\"cid:test@node\"/></b>",
+ text:"test"
+ });
+ mc.addAttachment({
+ fileName: "file.txt",
+ cid: "test@node",
+ contents: fs.readFileSync(__dirname+"/textfile.txt").toString("utf-8")
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mc._attachments.length, 0);
+ test.equal(mc._relatedAttachments.length, 1);
+ test.equal(mail.text.trim(), "test");
+ test.equal(mail.html.trim(), "<b><img src=\"cid:test@node\"/></b>");
+ test.equal(mail.attachments[0].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ test.done();
+ });
+ },
+ "HTML, text, related+regular attachment": function(test){
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ html: "<b><img src=\"cid:test@node\"/></b>",
+ text:"test"
+ });
+ mc.addAttachment({
+ fileName: "file.txt",
+ cid: "test@node",
+ contents: fs.readFileSync(__dirname+"/textfile.txt").toString("utf-8")
+ });
+ mc.addAttachment({
+ fileName: "file.txt",
+ contents: fs.readFileSync(__dirname+"/textfile.txt").toString("utf-8")
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mc._attachments.length, 1);
+ test.equal(mc._relatedAttachments.length, 1);
+ test.equal(mail.text.trim(), "test");
+ test.equal(mail.html.trim(), "<b><img src=\"cid:test@node\"/></b>");
+ test.equal(mail.attachments[0].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ test.equal(mail.attachments[1].checksum, "59fbcbcaf18cb9232f7da6663f374eb9");
+ test.done();
+ });
+ },
+ "References Header": function(test){
+
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ references: ["myrdo", "vyrdo"]
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.deepEqual(mail.references, ["myrdo", "vyrdo"]);
+ test.done();
+ });
+ },
+ "InReplyTo Header": function(test){
+
+ var mc = new MailComposer();
+ mc.setMessageOption({
+ inReplyTo: "test"
+ });
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.inReplyTo, "test");
+ test.done();
+ });
+ }
+};
+
+exports["Output buffering"] = {
+ "Use DKIM": function(test){
+ var mc = new MailComposer();
+
+ mc.setMessageOption({
+ from: "Andris Reinman <andris@node.ee>",
+ to: "Andris <andris.reinman@gmail.com>",
+ html: "<b>Hello world!</b>",
+ subject: "Hello world!"
+ });
+
+ mc.useDKIM({
+ domainName: "do-not-trust.node.ee",
+ keySelector: "dkim",
+ privateKey: fs.readFileSync(__dirname+"/test_private.pem")
+ });
+
+ mc.streamMessage();
+
+ var mp = new MailParser();
+
+ mc.pipe(mp);
+
+ mp.on("end", function(mail){
+ test.equal(mail.headers['dkim-signature'].replace(/\s/g, ""), 'v=1;a=rsa-sha256;c=relaxed/relaxed;d=do-not-trust.node.ee;q=dns/txt;s=dkim;bh=88i0PUP3tj3X/n0QT6Baw8ZPSeHZPqT7J0EmE26pjng=;h=from:subject:to:mime-version:content-type:content-transfer-encoding;b=dtxxQLotrcarEA5nbgBJLBJQxSAHcfrNxxpItcXSj68ntRvxmjXt9aPZTbVrzfRYe+xRzP2FTGpS7js8iYpAZZ2N3DBRLVp4gyyKHB1oWMkg/EV92uPtnjQ3MlHMbxC0');
+ test.done();
+ });
+ }
+}
+
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/test/test_private.pem b/tools/node_modules/nodemailer/node_modules/mailcomposer/test/test_private.pem
new file mode 100644
index 0000000..9d03266
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/test/test_private.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBywIBAAJhANCx7ncKUfQ8wBUYmMqq6ky8rBB0NL8knBf3+uA7q/CSxpX6sQ8N
+dFNtEeEd7gu7BWEM7+PkO1P0M78eZOvVmput8BP9R44ARpgHY4V0qSCdUt4rD32n
+wfjlGbh8p5ua5wIDAQABAmAm+uUQpQPTu7kg95wqVqw2sxLsa9giT6M8MtxQH7Uo
+1TF0eAO0TQ4KOxgY1S9OT5sGPVKnag258m3qX7o5imawcuyStb68DQgAUg6xv7Af
+AqAEDfYN5HW6xK+X81jfOUECMQDr7XAS4PERATvgb1B3vRu5UEbuXcenHDYgdoyT
+3qJFViTbep4qeaflF0uF9eFveMcCMQDic10rJ8fopGD7/a45O4VJb0+lRXVdqZxJ
+QzAp+zVKWqDqPfX7L93SQLzOGhdd7OECMQDeQyD7WBkjSQNMy/GF7I1qxrscIxNN
+VqGTcbu8Lti285Hjhx/sqhHHHGwU9vB7oM8CMQDKTS3Kw/s/xrot5O+kiZwFgr+w
+cmDrj/7jJHb+ykFNb7GaEkiSYqzUjKkfpweBDYECMFJUyzuuFJAjq3BXmGJlyykQ
+TweUw+zMVdSXjO+FCPcYNi6CP1t1KoESzGKBVoqA/g==
+-----END RSA PRIVATE KEY-----
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/test/test_public.pem b/tools/node_modules/nodemailer/node_modules/mailcomposer/test/test_public.pem
new file mode 100644
index 0000000..2214c80
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/test/test_public.pem
@@ -0,0 +1,5 @@
+-----BEGIN PUBLIC KEY-----
+MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhANCx7ncKUfQ8wBUYmMqq6ky8rBB0NL8k
+nBf3+uA7q/CSxpX6sQ8NdFNtEeEd7gu7BWEM7+PkO1P0M78eZOvVmput8BP9R44A
+RpgHY4V0qSCdUt4rD32nwfjlGbh8p5ua5wIDAQAB
+-----END PUBLIC KEY-----
diff --git a/tools/node_modules/nodemailer/node_modules/mailcomposer/test/textfile.txt b/tools/node_modules/nodemailer/node_modules/mailcomposer/test/textfile.txt
new file mode 100644
index 0000000..3628c58
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/mailcomposer/test/textfile.txt
@@ -0,0 +1,601 @@
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+Some unicode symbols ÕÄÖÜ ↑, →, ↓, ↔, ↕, ↖, ↗, ↘, ↙, ↚, ↛, ↜, ↝, ↞, ↟, ↠, ↡, ↢, ↣, ↤, ↥, ↦
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
+
+"Because I am scorched all over, Captain Ahab," answered Perth, resting for a moment on his hammer; "I am past scorching; not easily can'st thou scorch a scar."
+
+"Well, well; no more. Thy shrunk voice sounds too calmly, sanely woeful to me. In no Paradise myself, I am impatient of all misery in others that is not mad. Thou should'st go mad, blacksmith; say, why dost thou not go mad? How can'st thou endure without being mad? Do the heavens yet hate thee, that thou can'st not go mad?—What wert thou making there?"
+
+"Welding an old pike-head, sir; there were seams and dents in it."
+
+"And can'st thou make it all smooth again, blacksmith, after such hard usage as it had?"
+
+"I think so, sir."
+
+"And I suppose thou can'st smoothe almost any seams and dents; never mind how hard the metal, blacksmith?"
+
+"Aye, sir, I think I can; all seams and dents but one."
+
+"Look ye here, then," cried Ahab, passionately advancing, and leaning with both hands on Perth's shoulders; "look ye here—HERE—can ye smoothe out a seam like this, blacksmith," sweeping one hand across his ribbed brow; "if thou could'st, blacksmith, glad enough would I lay my head upon thy anvil, and feel thy heaviest hammer between my eyes. Answer! Can'st thou smoothe this seam?"
+
+"Oh! that is the one, sir! Said I not all seams and dents but one?"
+
+"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for though thou only see'st it here in my flesh, it has worked down into the bone of my skull—THAT is all wrinkles! But, away with child's play; no more gaffs and pikes to-day. Look ye here!" jingling the leathern bag, as if it were full of gold coins. "I, too, want a harpoon made; one that a thousand yoke of fiends could not part, Perth; something that will stick in a whale like his own fin-bone. There's the stuff," flinging the pouch upon the anvil. "Look ye, blacksmith, these are the gathered nail-stubbs of the steel shoes of racing horses."
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/.npmignore b/tools/node_modules/nodemailer/node_modules/simplesmtp/.npmignore
new file mode 100644
index 0000000..b512c09
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/.npmignore
@@ -0,0 +1 @@
+node_modules \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/.travis.yml b/tools/node_modules/nodemailer/node_modules/simplesmtp/.travis.yml
new file mode 100644
index 0000000..c8f68ef
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/.travis.yml
@@ -0,0 +1,12 @@
+language: node_js
+node_js:
+ - 0.6
+ - 0.8
+ - 0.9
+
+notifications:
+ email:
+ recipients:
+ - andris@node.ee
+ on_success: change
+ on_failure: change
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/LICENSE b/tools/node_modules/nodemailer/node_modules/simplesmtp/LICENSE
new file mode 100644
index 0000000..a47b0ea
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/LICENSE
@@ -0,0 +1,16 @@
+Copyright (c) 2012 Andris Reinman
+
+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 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. \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/README.md b/tools/node_modules/nodemailer/node_modules/simplesmtp/README.md
new file mode 100644
index 0000000..0c4d0c4
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/README.md
@@ -0,0 +1,275 @@
+# simplesmtp
+
+This is a module to easily create custom SMTP servers and clients - use SMTP as a first class protocol in Node.JS!
+
+[![Build Status](https://secure.travis-ci.org/andris9/simplesmtp.png)](http://travis-ci.org/andris9/simplesmtp)
+
+## Support simplesmtp development
+
+[![Donate to author](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DB26KWR2BQX5W)
+
+## SMTP Server
+
+### Usage
+
+Create a new SMTP server instance with
+
+ var smtp = simplesmtp.createServer([options]);
+
+And start listening on selected port
+
+ smtp.listen(25, [function(err){}]);
+
+SMTP options can include the following:
+
+ * **name** - the hostname of the server, will be used for informational messages
+ * **debug** - if set to true, print out messages about the connection
+ * **timeout** - client timeout in milliseconds, defaults to 60 000 (60 sec.)
+ * **secureConnection** - start a server on secure connection
+ * **SMTPBanner** - greeting banner that is sent to the client on connection
+ * **requireAuthentication** - if set to true, require that the client must authenticate itself
+ * **enableAuthentication** - if set to true, client may authenticate itself but don't have to (as opposed to `requireAuthentication` that explicitly requires clients to authenticate themselves)
+ * **validateSender** - if set to true, emit `'validateSender'` with `envelope`, `email` and `callback` when the client enters `MAIL FROM:<address>`
+ * **validateRecipients** - if set to true, emit `'validateRecipient'` with `envelope`, `email` and `callback` when the client enters `RCPT TO:<address>`
+ * **maxSize** - maximum size of an e-mail in bytes (currently informational only)
+ * **credentials** - TLS credentials (`{key:'', cert:'', ca:['']}`) for the server
+ * **authMethods** - allowed authentication methods, defaults to `["PLAIN", "LOGIN"]`
+ * **disableEHLO** - if set to true, support HELO command only
+ * **ignoreTLS** - if set to true, allow client do not use STARTTLS
+
+### Example
+
+ var simplesmtp = require("simplesmtp"),
+ fs = require("fs");
+
+ var smtp = simplesmtp.createServer();
+ smtp.listen(25);
+
+ smtp.on("startData", function(envelope){
+ console.log("Message from:", envelope.from);
+ console.log("Message to:", envelope.to);
+ envelope.saveStream = fs.createWriteStream("/tmp/message.txt");
+ });
+
+ smtp.on("data", function(envelope, chunk){
+ envelope.saveStream.write(chunk);
+ });
+
+ smtp.on("dataReady", function(envelope, callback){
+ envelope.saveStream.end();
+ console.log("Incoming message saved to /tmp/message.txt");
+ callback(null, "ABC1"); // ABC1 is the queue id to be advertised to the client
+ // callback(new Error("That was clearly a spam!"));
+ });
+
+
+### Events
+
+ * **startData** *(envelope)* - DATA stream is opened by the client (`envelope` is an object with `from`, `to`, `host` and `remoteAddress` properties)
+ * **data** *(envelope, chunk)* - e-mail data chunk is passed from the client
+ * **dataReady** *(envelope, callback)* - client is finished passing e-mail data, `callback` returns the queue id to the client
+ * **authorizeUser** *(envelope, username, password, callback)* - will be emitted if `requireAuthentication` option is set to true. `callback` has two parameters *(err, success)* where `success` is Boolean and should be true, if user is authenticated successfully
+ * **validateSender** *(envelope, email, callback)* - will be emitted if `validateSender` option is set to true
+ * **validateRecipient** *(envelope, email, callback)* - will be emitted it `validataRecipients` option is set to true
+ * **close** *(envelope)* - emitted when the connection to client is closed
+
+## SMTP Client
+
+### Usage
+
+SMTP client can be created with `simplesmptp.connect(port[,host][, options])`
+where
+
+ * **port** is the port to connect to
+ * **host** is the hostname to connect to (defaults to "localhost")
+ * **options** is an optional options object (see below)
+
+### Connection options
+
+The following connection options can be used with `simplesmtp.connect`:
+
+ * **secureConnection** - use SSL
+ * **name** - the name of the client server
+ * **auth** - authentication object `{user:"...", pass:"..."}` or `{XOAuthToken:"base64data"}`
+ * **ignoreTLS** - ignore server support for STARTTLS
+ * **debug** - output client and server messages to console
+ * **instanceId** - unique instance id for debugging (will be output console with the messages)
+
+### Connection events
+
+Once a connection is set up the following events can be listened to:
+
+ * **'idle'** - the connection to the SMTP server has been successfully set up and the client is waiting for an envelope
+ * **'message'** - the envelope is passed successfully to the server and a message stream can be started
+ * **'ready'** `(success)` - the message was sent
+ * **'rcptFailed'** `(addresses)` - not all recipients were accepted (invalid addresses are included as an array)
+ * **'error'** `(err)` - An error occurred. The connection is closed and an 'end' event is emitted shortly
+ * **'end'** - connection to the client is closed
+
+### Sending an envelope
+
+When an `'idle'` event is emitted, an envelope object can be sent to the server.
+This includes a string `from` and an array of strings `to` property.
+
+Envelope can be sent with `client.useEnvelope(envelope)`
+
+ // run only once as 'idle' is emitted again after message delivery
+ client.once("idle", function(){
+ client.useEnvelope({
+ from: "me@example.com",
+ to: ["receiver1@example.com", "receiver2@example.com"]
+ });
+ });
+
+The `to` part of the envelope includes **all** recipients from `To:`, `Cc:` and `Bcc:` fields.
+
+If setting the envelope up fails, an error is emitted. If only some (not all)
+recipients are not accepted, the mail can still be sent but an `rcptFailed`
+event is emitted.
+
+ client.on("rcptFailed", function(addresses){
+ console.log("The following addresses were rejected: ", addresses);
+ });
+
+If the envelope is set up correctly a `'message'` event is emitted.
+
+### Sending a message
+
+When `'message'` event is emitted, it is possible to send mail. To do this
+you can pipe directly a message source (for example an .eml file) to the client
+or alternatively you can send the message with `client.write` calls (you also
+need to call `client.end()` once the message is completed.
+
+If you are piping a stream to the client, do not leave the `'end'` event out,
+this is needed to complete the message sequence by the client.
+
+ client.on("message", function(){
+ fs.createReadStream("test.eml").pipe(client);
+ });
+
+Once the message is delivered a `'ready'` event is emitted. The event has an
+parameter which indicates if the message was transmitted( (true) or not (false)
+and another which includes the last received data from the server.
+
+ client.on("ready", function(success, response){
+ if(success){
+ console.log("The message was transmitted successfully with "+response);
+ }
+ });
+
+### XOAUTH
+
+**simplesmtp** supports [XOAUTH](https://developers.google.com/google-apps/gmail/oauth_protocol) authentication.
+
+To use this feature you can set `XOAuthToken` param as an `auth` option
+
+ var mailOptions = {
+ ...,
+ auth:{
+ XOAuthToken: "R0VUIGh0dHBzOi8vbWFpbC5nb29...."
+ }
+ }
+
+Alternatively it is also possible to use XOAuthToken generators (supported by Nodemailer) - this
+needs to be an object with a mandatory method `generate` that takes a callback function for
+generating a XOAUTH token string. This is better for generating tokens only when needed -
+there is no need to calculate unique token for every e-mail request, since a lot of these
+might share the same connection and thus the cleint needs not to re-authenticate itself
+with another token.
+
+ var XOGen = {
+ token: "abc",
+ generate: function(callback){
+ if(1 != 1){
+ return callback(new Error("Tokens can't be generated in strange environments"));
+ }
+ callback(null, new Buffer(this.token, "utf-8").toString("base64"));
+ }
+ }
+
+ var mailOptions = {
+ ...,
+ auth:{
+ XOAuthToken: XOGen
+ }
+ }
+
+### Error types
+
+Emitted errors include the reason for failing in the `name` property
+
+ * **UnknowAuthError** - the client tried to authenticate but the method was not supported
+ * **AuthError** - the username/password used were rejected
+ * **TLSError** - STARTTLS failed
+ * **SenderError** - the sender e-mail address was rejected
+ * **RecipientError** - all recipients were rejected (if only some of the recipients are rejected, a `'rcptFailed'` event is raised instead
+
+There's also an additional property in the error object called `data` that includes
+the last response received from the server (if available for the current error type).
+
+### About reusing the connection
+
+You can reuse the same connection several times but you can't send a mail
+through the same connection concurrently. So if you catch and `'idle'` event
+lock the connection to a message process and unlock after `'ready'`.
+
+On `'error'` events you should reschedule the message and on `'end'` events
+you should recreate the connection.
+
+### Closing the client
+
+By default the client tries to keep the connection up. If you want to close it,
+run `client.quit()` - this sends a `QUIT` command to the server and closes the
+connection
+
+ client.quit();
+
+## SMTP Client Connection pool
+
+**simplesmtp** has the option for connection pooling if you want to reuse a bulk
+of connections.
+
+### Usage
+
+Create a connection pool of SMTP clients with
+
+ simplesmtp.createClientPool(port[,host][, options])
+
+where
+
+ * **port** is the port to connect to
+ * **host** is the hostname to connect to (defaults to "localhost")
+ * **options** is an optional options object (see below)
+
+### Connection options
+
+The following connection options can be used with `simplesmtp.connect`:
+
+ * **secureConnection** - use SSL
+ * **name** - the name of the client server
+ * **auth** - authentication object `{user:"...", pass:"..."}` or `{XOAuthToken:"base64data"}`
+ * **ignoreTLS** - ignore server support for STARTTLS
+ * **debug** - output client and server messages to console
+ * **maxConnections** - how many connections to keep in the pool (defaults to 5)
+
+### Send an e-mail
+
+E-mails can be sent through the pool with
+
+ pool.sendMail(mail[, callback])
+
+where
+
+ * **mail** is a [MailComposer](/andris9/mailcomposer) compatible object
+ * **callback** `(error, responseObj)` - is the callback function to run after the message is delivered or an error occured. `responseObj` may include `failedRecipients` which is an array with e-mail addresses that were rejected and `message` which is the last response from the server.
+
+### Errors
+
+In addition to SMTP client errors another error name is used
+
+ * **DeliveryError** - used if the message was not accepted by the SMTP server
+
+## License
+
+**MIT**
+
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/index.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/index.js
new file mode 100644
index 0000000..3202ee3
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/index.js
@@ -0,0 +1,5 @@
+
+// expose the API to the world
+module.exports.createServer = require("./lib/server.js");
+module.exports.connect = require("./lib/client.js");
+module.exports.createClientPool = require("./lib/pool.js"); \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/client.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/client.js
new file mode 100644
index 0000000..cfe8cea
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/client.js
@@ -0,0 +1,709 @@
+// TODO:
+// * Lisada timeout serveri ühenduse jaoks
+
+var Stream = require("stream").Stream,
+ utillib = require("util"),
+ net = require("net"),
+ tls = require("tls"),
+ oslib = require("os"),
+ starttls = require("./starttls").starttls;
+
+// monkey patch net and tls to support nodejs 0.4
+if(!net.connect && net.createConnection){
+ net.connect = net.createConnection;
+}
+
+if(!tls.connect && tls.createConnection){
+ tls.connect = tls.createConnection;
+}
+
+// expose to the world
+module.exports = function(port, host, options){
+ var connection = new SMTPClient(port, host, options);
+ process.nextTick(connection.connect.bind(connection));
+ return connection;
+};
+
+/**
+ * <p>Generates a SMTP connection object</p>
+ *
+ * <p>Optional options object takes the following possible properties:</p>
+ * <ul>
+ * <li><b>secureConnection</b> - use SSL</li>
+ * <li><b>name</b> - the name of the client server</li>
+ * <li><b>auth</b> - authentication object <code>{user:"...", pass:"..."}</code>
+ * <li><b>ignoreTLS</b> - ignore server support for STARTTLS</li>
+ * <li><b>debug</b> - output client and server messages to console</li>
+ * <li><b>instanceId</b> - unique instance id for debugging</li>
+ * </ul>
+ *
+ * @constructor
+ * @namespace SMTP Client module
+ * @param {Number} [port=25] Port number to connect to
+ * @param {String} [host="localhost"] Hostname to connect to
+ * @param {Object} [options] Option properties
+ */
+function SMTPClient(port, host, options){
+ Stream.call(this);
+ this.writable = true;
+ this.readable = true;
+
+ this.options = options || {};
+
+ this.port = port || (this.options.secureConnection ? 465 : 25);
+ this.host = host || "localhost";
+
+ this.options.secureConnection = !!this.options.secureConnection;
+ this.options.auth = this.options.auth || false;
+ this.options.maxConnections = this.options.maxConnections || 5;
+
+ if(!this.options.name){
+ // defaul hostname is machine hostname or [IP]
+ var defaultHostname = (oslib.hostname && oslib.hostname()) ||
+ (oslib.getHostname && oslib.getHostname()) ||
+ "";
+ if(defaultHostname.indexOf('.')<0){
+ defaultHostname = "[127.0.0.1]";
+ }
+ if(defaultHostname.match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)){
+ defaultHostname = "["+defaultHostname+"]";
+ }
+
+ this.options.name = defaultHostname;
+ }
+
+ this._init();
+}
+utillib.inherits(SMTPClient, Stream);
+
+/**
+ * <p>Initializes instance variables</p>
+ */
+SMTPClient.prototype._init = function(){
+ /**
+ * Defines if the current connection is secure or not. If not,
+ * STARTTLS can be used if available
+ * @private
+ */
+ this._secureMode = false;
+
+ /**
+ * Ignore incoming data on TLS negotiation
+ * @private
+ */
+ this._ignoreData = false;
+
+ /**
+ * Store incomplete messages coming from the server
+ * @private
+ */
+ this._remainder = "";
+
+ /**
+ * If set to true, then this object is no longer active
+ * @private
+ */
+ this.destroyed = false;
+
+ /**
+ * The socket connecting to the server
+ * @publick
+ */
+ this.socket = false;
+
+ /**
+ * Lists supported auth mechanisms
+ * @private
+ */
+ this._supportedAuth = [];
+
+ /**
+ * Currently in data transfer state
+ * @private
+ */
+ this._dataMode = false;
+
+ /**
+ * Keep track if the client sends a leading \r\n in data mode
+ * @private
+ */
+ this._lastDataBytes = new Buffer(2);
+
+ /**
+ * Function to run if a data chunk comes from the server
+ * @private
+ */
+ this._currentAction = false;
+
+ if(this.options.ignoreTLS || this.options.secureConnection){
+ this._secureMode = true;
+ }
+};
+
+/**
+ * <p>Creates a connection to a SMTP server and sets up connection
+ * listener</p>
+ */
+SMTPClient.prototype.connect = function(){
+
+ if(this.options.secureConnection){
+ this.socket = tls.connect(this.port, this.host, {}, this._onConnect.bind(this));
+ }else{
+ this.socket = net.connect(this.port, this.host);
+ this.socket.on("connect", this._onConnect.bind(this));
+ }
+
+ this.socket.on("error", this._onError.bind(this));
+};
+
+/**
+ * <p>Upgrades the connection to TLS</p>
+ *
+ * @param {Function} callback Callbac function to run when the connection
+ * has been secured
+ */
+SMTPClient.prototype._upgradeConnection = function(callback){
+ this._ignoreData = true;
+ starttls(this.socket, (function(socket){
+ this.socket = socket;
+ this._ignoreData = false;
+ this._secureMode = true;
+ this.socket.on("data", this._onData.bind(this));
+
+ return callback(null, true);
+ }).bind(this));
+};
+
+/**
+ * <p>Connection listener that is run when the connection to
+ * the server is opened</p>
+ *
+ * @event
+ */
+SMTPClient.prototype._onConnect = function(){
+ if("setKeepAlive" in this.socket){
+ this.socket.setKeepAlive(true);
+ }else if(this.socket.encrypted && "setKeepAlive" in this.socket.encrypted){
+ this.socket.encrypted.setKeepAlive(true); // secure connection
+ }
+
+ this.socket.on("data", this._onData.bind(this));
+ this.socket.on("close", this._onClose.bind(this));
+ this.socket.on("end", this._onEnd.bind(this));
+
+ this._currentAction = this._actionGreeting;
+};
+
+/**
+ * <p>Destroys the client - removes listeners etc.</p>
+ */
+SMTPClient.prototype._destroy = function(){
+ if(this._destroyed)return;
+ this._destroyed = true;
+ this.emit("end");
+ this.removeAllListeners();
+};
+
+/**
+ * <p>'data' listener for data coming from the server</p>
+ *
+ * @event
+ * @param {Buffer} chunk Data chunk coming from the server
+ */
+SMTPClient.prototype._onData = function(chunk){
+ var str;
+
+ if(this._ignoreData || !chunk || !chunk.length){
+ return;
+ }
+
+ // Wait until end of line
+ if(chunk[chunk.length-1] != 0x0A){
+ this._remainder += chunk.toString();
+ return;
+ }else{
+ str = (this._remainder + chunk.toString()).trim();
+ this._remainder = "";
+ }
+
+ if(this.options.debug){
+ console.log("SERVER"+(this.options.instanceId?" "+
+ this.options.instanceId:"")+":\n└──"+str.replace(/\r?\n/g,"\n "));
+ }
+
+ if(typeof this._currentAction == "function"){
+ this._currentAction.call(this, str);
+ }
+};
+
+/**
+ * <p>'error' listener for the socket</p>
+ *
+ * @event
+ * @param {Error} err Error object
+ * @param {String} type Error name
+ */
+SMTPClient.prototype._onError = function(err, type, data){
+ if(type && type != "Error"){
+ err.name = type;
+ }
+ if(data){
+ err.data = data;
+ }
+ this.emit("error", err);
+ this.close();
+};
+
+/**
+ * <p>'close' listener for the socket</p>
+ *
+ * @event
+ */
+SMTPClient.prototype._onClose = function(){
+ this._destroy();
+};
+
+/**
+ * <p>'end' listener for the socket</p>
+ *
+ * @event
+ */
+SMTPClient.prototype._onEnd = function(){
+ this._destroy();
+};
+
+/**
+ * <p>Passes data stream to socket if in data mode</p>
+ *
+ * @param {Buffer} chunk Chunk of data to be sent to the server
+ */
+SMTPClient.prototype.write = function(chunk){
+ // works only in data mode
+ if(!this._dataMode){
+ // this line should never be reached but if it does, then
+ // say act like everything's normal.
+ return true;
+ }
+
+ if(typeof chunk == "string"){
+ chunk = new Buffer(chunk, "utf-8");
+ }
+
+ if(chunk.length > 2){
+ this._lastDataBytes[0] = chunk[chunk.length-2];
+ this._lastDataBytes[1] = chunk[chunk.length-1];
+ }else if(chunk.length == 1){
+ this._lastDataBytes[0] = this._lastDataBytes[1];
+ this._lastDataBytes[1] = chunk[0];
+ }
+
+ if(this.options.debug){
+ console.log("CLIENT (DATA)"+(this.options.instanceId?" "+
+ this.options.instanceId:"")+":\n└──"+chunk.toString().trim().replace(/\n/g,"\n "));
+ }
+
+ // pass the chunk to the socket
+ return this.socket.write(chunk);
+};
+
+/**
+ * <p>Indicates that a data stream for the socket is ended. Works only
+ * in data mode.</p>
+ *
+ * @param {Buffer} [chunk] Chunk of data to be sent to the server
+ */
+SMTPClient.prototype.end = function(chunk){
+ // works only in data mode
+ if(!this._dataMode){
+ // this line should never be reached but if it does, then
+ // say act like everything's normal.
+ return true;
+ }
+
+ if(chunk && chunk.length){
+ this.write(chunk);
+ }
+
+ // redirect output from the server to _actionStream
+ this._currentAction = this._actionStream;
+
+ // indicate that the stream has ended by sending a single dot on its own line
+ // if the client already closed the data with \r\n no need to do it again
+ if(this._lastDataBytes[0] == 0x0D && this._lastDataBytes[1] == 0x0A){
+ this.socket.write(new Buffer(".\r\n", "utf-8"));
+ }else if(this._lastDataBytes[1] == 0x0D){
+ this.socket.write(new Buffer("\n.\r\n"));
+ }else{
+ this.socket.write(new Buffer("\r\n.\r\n"));
+ }
+
+ // end data mode
+ this._dataMode = false;
+};
+
+/**
+ * <p>Send a command to the server, append \r\n</p>
+ *
+ * @param {String} str String to be sent to the server
+ */
+SMTPClient.prototype.sendCommand = function(str){
+ if(this.options.debug){
+ console.log("CLIENT"+(this.options.instanceId?" "+
+ this.options.instanceId:"")+":\n└──"+(str || "").toString().trim().replace(/\n/g,"\n "));
+ }
+ this.socket.write(new Buffer(str+"\r\n", "utf-8"));
+};
+
+/**
+ * <p>Sends QUIT</p>
+ */
+SMTPClient.prototype.quit = function(){
+ this.sendCommand("QUIT");
+ this._currentAction = this.close;
+};
+
+/**
+ * <p>Closes the connection to the server</p>
+ */
+SMTPClient.prototype.close = function(){
+ if(this.options.debug){
+ console.log("Closing connection to the server");
+ }
+ if(this.socket && !this.socket.destroyed){
+ this.socket.end();
+ }
+ this._destroy();
+};
+
+/**
+ * <p>Initiates a new message by submitting envelope data, starting with
+ * <code>MAIL FROM:</code> command</p>
+ *
+ * @param {Object} envelope Envelope object in the form of
+ * <code>{from:"...", to:["..."]}</code>
+ */
+SMTPClient.prototype.useEnvelope = function(envelope){
+ this._envelope = envelope || {};
+ this._envelope.from = this._envelope.from || ("anonymous@"+this.options.name);
+
+ // clone the recipients array for latter manipulation
+ this._envelope.rcptQueue = JSON.parse(JSON.stringify(this._envelope.to || []));
+ this._envelope.rcptFailed = [];
+
+ this._currentAction = this._actionMAIL;
+ this.sendCommand("MAIL FROM:<"+(this._envelope.from)+">");
+};
+
+/**
+ * <p>If needed starts the authentication, if not emits 'idle' to
+ * indicate that this client is ready to take in an outgoing mail</p>
+ */
+SMTPClient.prototype._authenticateUser = function(){
+
+ if(!this.options.auth){
+ // no need to authenticate, at least no data given
+ this._currentAction = this._actionIdle;
+ this.emit("idle"); // ready to take orders
+ return;
+ }
+
+ var auth;
+
+ if(this.options.auth.XOAuthToken && this._supportedAuth.indexOf("XOAUTH")>=0){
+ auth = "XOAUTH";
+ }else if(this.options.authMethod) {
+ auth = this.options.authMethod.toUpperCase().trim();
+ }else{
+ // use first supported
+ auth = (this._supportedAuth[0] || "PLAIN").toUpperCase().trim();
+ }
+
+ switch(auth){
+ case "XOAUTH":
+ this._currentAction = this._actionAUTHComplete;
+
+ if(typeof this.options.auth.XOAuthToken == "object" &&
+ typeof this.options.auth.XOAuthToken.generate == "function"){
+ this.options.auth.XOAuthToken.generate((function(err, XOAuthToken){
+ if(err){
+ return this._onError(err, "XOAuthTokenError");
+ }
+ this.sendCommand("AUTH XOAUTH " + XOAuthToken);
+ }).bind(this));
+ }else{
+ this.sendCommand("AUTH XOAUTH " + this.options.auth.XOAuthToken.toString());
+ }
+ return;
+ case "LOGIN":
+ this._currentAction = this._actionAUTH_LOGIN_USER;
+ this.sendCommand("AUTH LOGIN");
+ return;
+ case "PLAIN":
+ this._currentAction = this._actionAUTHComplete;
+ this.sendCommand("AUTH PLAIN "+new Buffer(
+ this.options.auth.user+"\u0000"+
+ this.options.auth.user+"\u0000"+
+ this.options.auth.pass,"utf-8").toString("base64"));
+ return;
+ }
+
+ this._onError(new Error("Unknown authentication method - "+auth), "UnknowAuthError");
+};
+
+/** ACTIONS **/
+
+/**
+ * <p>Will be run after the connection is created and the server sends
+ * a greeting. If the incoming message starts with 220 initiate
+ * SMTP session by sending EHLO command</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionGreeting = function(str){
+ if(str.substr(0,3) != "220"){
+ this._onError(new Error("Invalid greeting from server - "+str), false, str);
+ return;
+ }
+
+ this._currentAction = this._actionEHLO;
+ this.sendCommand("EHLO "+this.options.name);
+};
+
+/**
+ * <p>Handles server response for EHLO command. If it yielded in
+ * error, try HELO instead, otherwise initiate TLS negotiation
+ * if STARTTLS is supported by the server or move into the
+ * authentication phase.</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionEHLO = function(str){
+ if(str.charAt(0) != "2"){
+ // Try HELO instead
+ this._currentAction = this._actionHELO;
+ this.sendCommand("HELO "+this.options.name);
+ return;
+ }
+
+ // Detect if the server supports STARTTLS
+ if(!this._secureMode && str.match(/[ \-]STARTTLS\r?$/mi)){
+ this.sendCommand("STARTTLS");
+ this._currentAction = this._actionSTARTTLS;
+ return;
+ }
+
+ // Detect if the server supports PLAIN auth
+ if(str.match(/AUTH(?:\s+[^\n]*\s+|\s+)PLAIN/i)){
+ this._supportedAuth.push("PLAIN");
+ }
+
+ // Detect if the server supports LOGIN auth
+ if(str.match(/AUTH(?:\s+[^\n]*\s+|\s+)LOGIN/i)){
+ this._supportedAuth.push("LOGIN");
+ }
+
+ // Detect if the server supports LOGIN auth
+ if(str.match(/AUTH(?:\s+[^\n]*\s+|\s+)XOAUTH/i)){
+ this._supportedAuth.push("XOAUTH");
+ }
+
+ this._authenticateUser.call(this);
+};
+
+/**
+ * <p>Handles server response for HELO command. If it yielded in
+ * error, emit 'error', otherwise move into the authentication phase.</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionHELO = function(str){
+ if(str.charAt(0) != "2"){
+ this._onError(new Error("Invalid response for EHLO/HELO - "+str), false, str);
+ return;
+ }
+ this._authenticateUser.call(this);
+};
+
+/**
+ * <p>Handles server response for STARTTLS command. If there's an error
+ * try HELO instead, otherwise initiate TLS upgrade. If the upgrade
+ * succeedes restart the EHLO</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionSTARTTLS = function(str){
+ if(str.charAt(0) != "2"){
+ // Try HELO instead
+ this._currentAction = this._actionHELO;
+ this.sendCommand("HELO "+this.options.name);
+ return;
+ }
+
+ this._upgradeConnection((function(err, secured){
+ if(err){
+ this._onError(new Error("Error initiating TLS - "+(err.message || err)), "TLSError");
+ return;
+ }
+ if(this.options.debug){
+ console.log("Connection secured");
+ }
+
+ if(secured){
+ // restart session
+ this._currentAction = this._actionEHLO;
+ this.sendCommand("EHLO "+this.options.name);
+ }else{
+ this._authenticateUser.call(this);
+ }
+ }).bind(this));
+};
+
+/**
+ * <p>Handle the response for AUTH LOGIN command. We are expecting
+ * '334 VXNlcm5hbWU6' (base64 for 'Username:'). Data to be sent as
+ * response needs to be base64 encoded username.</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionAUTH_LOGIN_USER = function(str){
+ if(str != "334 VXNlcm5hbWU6"){
+ this._onError(new Error("Invalid login sequence while waiting for '334 VXNlcm5hbWU6' - "+str), false, str);
+ return;
+ }
+ this._currentAction = this._actionAUTH_LOGIN_PASS;
+ this.sendCommand(new Buffer(
+ this.options.auth.user, "utf-8").toString("base64"));
+};
+
+/**
+ * <p>Handle the response for AUTH LOGIN command. We are expecting
+ * '334 UGFzc3dvcmQ6' (base64 for 'Password:'). Data to be sent as
+ * response needs to be base64 encoded password.</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionAUTH_LOGIN_PASS = function(str){
+ if(str != "334 UGFzc3dvcmQ6"){
+ this._onError(new Error("Invalid login sequence while waiting for '334 UGFzc3dvcmQ6' - "+str), false, str);
+ return;
+ }
+ this._currentAction = this._actionAUTHComplete;
+ this.sendCommand(new Buffer(this.options.auth.pass, "utf-8").toString("base64"));
+};
+
+/**
+ * <p>Handles the response for authentication, if there's no error,
+ * the user can be considered logged in. Emit 'idle' and start
+ * waiting for a message to send</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionAUTHComplete = function(str){
+ if(str.charAt(0) != "2"){
+ this._onError(new Error("Invalid login - "+str), "AuthError", str);
+ return;
+ }
+
+ this._currentAction = this._actionIdle;
+ this.emit("idle"); // ready to take orders
+};
+
+/**
+ * <p>This function is not expected to run. If it does then there's probably
+ * an error (timeout etc.)</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionIdle = function(str){
+ if(Number(str.charAt(0)) > 3){
+ this._onError(new Error(str), false, str);
+ return;
+ }
+
+ // this line should never get called
+};
+
+/**
+ * <p>Handle response for a <code>MAIL FROM:</code> command</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionMAIL = function(str){
+ if(Number(str.charAt(0)) != "2"){
+ this._onError(new Error("Mail from command failed - " + str), "SenderError", str);
+ return;
+ }
+
+ if(!this._envelope.rcptQueue.length){
+ this._onError(new Error("Can't send mail - no recipients defined"), "RecipientError");
+ }else{
+ this._envelope.curRecipient = this._envelope.rcptQueue.shift();
+ this._currentAction = this._actionRCPT;
+ this.sendCommand("RCPT TO:<"+this._envelope.curRecipient+">");
+ }
+};
+
+/**
+ * <p>Handle response for a <code>RCPT TO:</code> command</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionRCPT = function(str){
+ if(Number(str.charAt(0)) != "2"){
+ // this is a soft error
+ this._envelope.rcptFailed.push(this._envelope.curRecipient);
+ }
+
+ if(!this._envelope.rcptQueue.length){
+ if(this._envelope.rcptFailed.length < this._envelope.to.length){
+ this.emit("rcptFailed", this._envelope.rcptFailed);
+ this._currentAction = this._actionDATA;
+ this.sendCommand("DATA");
+ }else{
+ this._onError(new Error("Can't send mail - all recipients were rejected"), "RecipientError");
+ return;
+ }
+ }else{
+ this._envelope.curRecipient = this._envelope.rcptQueue.shift();
+ this._currentAction = this._actionRCPT;
+ this.sendCommand("RCPT TO:<"+this._envelope.curRecipient+">");
+ }
+};
+
+/**
+ * <p>Handle response for a <code>DATA</code> command</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionDATA = function(str){
+ // response should be 354 but according to this issue https://github.com/eleith/emailjs/issues/24
+ // some servers might use 250 instead, so lets check for 2 or 3 as the first digit
+ if([2,3].indexOf(Number(str.charAt(0)))<0){
+ this._onError(new Error("Data command failed - " + str), false, str);
+ return;
+ }
+
+ // Emit that connection is set up for streaming
+ this._dataMode = true;
+ this._currentAction = this._actionIdle;
+ this.emit("message");
+};
+
+/**
+ * <p>Handle response for a <code>DATA</code> stream</p>
+ *
+ * @param {String} str Message from the server
+ */
+SMTPClient.prototype._actionStream = function(str){
+ if(Number(str.charAt(0)) != "2"){
+ // Message failed
+ this.emit("ready", false, str);
+ }else{
+ // Message sent succesfully
+ this.emit("ready", true, str);
+ }
+
+ // Waiting for new connections
+ this._currentAction = this._actionIdle;
+ process.nextTick(this.emit.bind(this, "idle"));
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/pool.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/pool.js
new file mode 100644
index 0000000..7a96d68
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/pool.js
@@ -0,0 +1,316 @@
+var simplesmtp = require("../index"),
+ EventEmitter = require('events').EventEmitter,
+ utillib = require("util");
+
+// expose to the world
+module.exports = function(port, host, options){
+ var pool = new SMTPConnectionPool(port, host, options);
+ return pool;
+};
+
+/**
+ * <p>Creates a SMTP connection pool</p>
+ *
+ * <p>Optional options object takes the following possible properties:</p>
+ * <ul>
+ * <li><b>secureConnection</b> - use SSL</li>
+ * <li><b>name</b> - the name of the client server</li>
+ * <li><b>auth</b> - authentication object <code>{user:"...", pass:"..."}</code>
+ * <li><b>ignoreTLS</b> - ignore server support for STARTTLS</li>
+ * <li><b>debug</b> - output client and server messages to console</li>
+ * <li><b>maxConnections</b> - how many connections to keep in the pool</li>
+ * </ul>
+ *
+ * @constructor
+ * @namespace SMTP Client Pool module
+ * @param {Number} [port=25] The port number to connecto to
+ * @param {String} [host="localhost"] THe hostname to connect to
+ * @param {Object} [options] optional options object
+ */
+function SMTPConnectionPool(port, host, options){
+ EventEmitter.call(this);
+
+ /**
+ * Port number to connect to
+ * @public
+ */
+ this.port = port || 25;
+
+ /**
+ * Hostname to connect to
+ * @public
+ */
+ this.host = host || "localhost";
+
+ /**
+ * Options object
+ * @public
+ */
+ this.options = options || {};
+ this.options.maxConnections = this.options.maxConnections || 5;
+
+ /**
+ * An array of connections that are currently idle
+ * @private
+ */
+ this._connectionsAvailable = [];
+
+ /**
+ * An array of connections that are currently in use
+ * @private
+ */
+ this._connectionsInUse = [];
+
+ /**
+ * Message queue (FIFO)
+ * @private
+ */
+ this._messageQueue = [];
+
+ /**
+ * Counter for generating ID values for debugging
+ * @private
+ */
+ this._idgen = 0;
+}
+utillib.inherits(SMTPConnectionPool, EventEmitter);
+
+/**
+ * <p>Sends a message. If there's any idling connections available
+ * use one to send the message immediatelly, otherwise add to queue.</p>
+ *
+ * @param {Object} message MailComposer object
+ * @param {Function} callback Callback function to run on finish, gets an
+ * <code>error</code> object as a parameter if the sending failed
+ * and on success an object with <code>failedRecipients</code> array as
+ * a list of addresses that were rejected (if any) and
+ * <code>message</code> which indicates the last message received from
+ * the server
+ */
+SMTPConnectionPool.prototype.sendMail = function(message, callback){
+ var connection;
+
+ message.returnCallback = callback;
+
+ if(this._connectionsAvailable.length){
+ // if available connections pick one
+ connection = this._connectionsAvailable.pop();
+ this._connectionsInUse.push(connection);
+ this._processMessage(message, connection);
+ }else{
+ this._messageQueue.push(message);
+
+ if(this._connectionsAvailable.length + this._connectionsInUse.length < this.options.maxConnections){
+ this._createConnection();
+ }
+ }
+
+};
+
+/**
+ * <p>Closes all connections</p>
+ */
+SMTPConnectionPool.prototype.close = function(callback){
+ var connection;
+
+ // for some reason destroying the connections seem to be the only way :S
+ while(this._connectionsAvailable.length){
+ connection = this._connectionsAvailable.pop();
+ if(connection.socket){
+ connection.socket.destroy();
+ }
+ }
+
+ while(this._connectionsInUse.length){
+ connection = this._connectionsInUse.pop();
+ if(connection.socket){
+ connection.socket.destroy();
+ }
+ }
+
+ if(callback){
+ process.nextTick(callback);
+ }
+};
+
+/**
+ * <p>Initiates a connection to the SMTP server and adds it to the pool</p>
+ */
+SMTPConnectionPool.prototype._createConnection = function(){
+ var connectionOptions = {
+ instanceId: ++this._idgen,
+ debug: !!this.options.debug,
+ ignoreTLS: !!this.options.ignoreTLS,
+ auth: this.options.auth || false,
+ authMethod: this.options.authMethod,
+ name: this.options.name || false,
+ secureConnection: !!this.options.secureConnection
+ },
+ connection = simplesmtp.connect(this.port, this.host, connectionOptions);
+
+ connection.on("idle", this._onConnectionIdle.bind(this, connection));
+ connection.on("message", this._onConnectionMessage.bind(this, connection));
+ connection.on("ready", this._onConnectionReady.bind(this, connection));
+ connection.on("error", this._onConnectionError.bind(this, connection));
+ connection.on("end", this._onConnectionEnd.bind(this, connection));
+ connection.on("rcptFailed", this._onConnectionRCPTFailed.bind(this, connection));
+
+ this.emit('connectionCreated', connection);
+
+ // as the connection is not ready yet, add to "in use" queue
+ this._connectionsInUse.push(connection);
+};
+
+/**
+ * <p>Processes a message by assigning it to a connection object and initiating
+ * the sending process by setting the envelope</p>
+ *
+ * @param {Object} message MailComposer message object
+ * @param {Object} connection <code>simplesmtp.connect</code> connection
+ */
+SMTPConnectionPool.prototype._processMessage = function(message, connection){
+ connection.currentMessage = message;
+ message.currentConnection = connection;
+
+ // send envelope
+ connection.useEnvelope(message.getEnvelope());
+};
+
+/**
+ * <p>Will be fired on <code>'idle'</code> events by the connection, if
+ * there's a message currently in queue</p>
+ *
+ * @event
+ * @param {Object} connection Connection object that fired the event
+ */
+SMTPConnectionPool.prototype._onConnectionIdle = function(connection){
+
+ var message = this._messageQueue.shift();
+
+ if(message){
+ this._processMessage(message, connection);
+ }else{
+ for(var i=0, len = this._connectionsInUse.length; i<len; i++){
+ if(this._connectionsInUse[i] == connection){
+ this._connectionsInUse.splice(i,1); // remove from list
+ break;
+ }
+ }
+ this._connectionsAvailable.push(connection);
+ }
+};
+
+/**
+ * <p>Will be called when not all recipients were accepted</p>
+ *
+ * @event
+ * @param {Object} connection Connection object that fired the event
+ * @param {Array} addresses Failed addresses as an array of strings
+ */
+SMTPConnectionPool.prototype._onConnectionRCPTFailed = function(connection, addresses){
+ if(connection.currentMessage){
+ connection.currentMessage.failedRecipients = addresses;
+ }
+};
+
+/**
+ * <p>Will be called when the client is waiting for a message to deliver</p>
+ *
+ * @event
+ * @param {Object} connection Connection object that fired the event
+ */
+SMTPConnectionPool.prototype._onConnectionMessage = function(connection){
+ if(connection.currentMessage){
+ connection.currentMessage.streamMessage();
+ connection.currentMessage.pipe(connection);
+ }
+};
+
+/**
+ * <p>Will be called when a message has been delivered</p>
+ *
+ * @event
+ * @param {Object} connection Connection object that fired the event
+ * @param {Boolean} success True if the message was queued by the SMTP server
+ * @param {String} message Last message received from the server
+ */
+SMTPConnectionPool.prototype._onConnectionReady = function(connection, success, message){
+ var error, responseObj = {};
+ if(connection.currentMessage && connection.currentMessage.returnCallback){
+ if(success){
+
+ if(connection.currentMessage.failedRecipients){
+ responseObj.failedRecipients = connection.currentMessage.failedRecipients;
+ }
+ if(message){
+ responseObj.message = message;
+ }
+
+ connection.currentMessage.returnCallback(null, responseObj);
+
+ }else{
+ error = new Error("Message delivery failed");
+ error.name = "DeliveryError";
+ connection.currentMessage.returnCallback(error);
+ }
+ }
+ connection.currentMessage = false;
+};
+
+/**
+ * <p>Will be called when an error occurs</p>
+ *
+ * @event
+ * @param {Object} connection Connection object that fired the event
+ * @param {Object} error Error object
+ */
+SMTPConnectionPool.prototype._onConnectionError = function(connection, error){
+ var message = connection.currentMessage;
+ connection.currentMessage = false;
+
+ // clear a first message from the list, otherwise an infinite loop will emerge
+ if(!message){
+ message = this._messageQueue.shift();
+ }
+
+ if(message && message.returnCallback){
+ message.returnCallback(error);
+ }
+};
+
+/**
+ * <p>Will be called when a connection to the client is closed</p>
+ *
+ * @event
+ * @param {Object} connection Connection object that fired the event
+ */
+SMTPConnectionPool.prototype._onConnectionEnd = function(connection){
+ var removed = false, i, len;
+
+ // if in "available" list, remove
+ for(i=0, len = this._connectionsAvailable.length; i<len; i++){
+ if(this._connectionsAvailable[i] == connection){
+ this._connectionsAvailable.splice(i,1); // remove from list
+ removed = true;
+ break;
+ }
+ }
+
+ if(!removed){
+ // if in "in use" list, remove
+ for(i=0, len = this._connectionsInUse.length; i<len; i++){
+ if(this._connectionsInUse[i] == connection){
+ this._connectionsInUse.splice(i,1); // remove from list
+ removed = true;
+ break;
+ }
+ }
+ }
+
+ // if there's still unprocessed mail and available connection slots, create
+ // a new connection
+ if(this._messageQueue.length &&
+ this._connectionsInUse.length + this._connectionsAvailable.length < this.options.maxConnections){
+ this._createConnection();
+ }
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/server.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/server.js
new file mode 100644
index 0000000..62aa650
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/server.js
@@ -0,0 +1,664 @@
+/**
+ * @fileOverview This is the main file for the simplesmtp library to create custom SMTP servers
+ * @author <a href="mailto:andris@node.ee">Andris Reinman</a>
+ */
+
+var RAIServer = require("rai").RAIServer,
+ EventEmitter = require('events').EventEmitter,
+ oslib = require('os'),
+ utillib = require("util"),
+ dnslib = require("dns");
+
+// expose to the world
+module.exports = function(options){
+ return new SMTPServer(options);
+};
+
+/**
+ * <p>Constructs a SMTP server</p>
+ *
+ * <p>Possible options are:</p>
+ *
+ * <ul>
+ * <li><b>name</b> - the hostname of the server, will be used for
+ * informational messages</li>
+ * <li><b>debug</b> - if set to true, print out messages about the connection</li>
+ * <li><b>timeout</b> - client timeout in milliseconds, defaults to 60 000</li>
+ * <li><b>secureConnection</b> - start a server on secure connection</li>
+ * <li><b>SMTPBanner</b> - greeting banner that is sent to the client on connection</li>
+ * <li><b>requireAuthentication</b> - if set to true, require that the client
+ * must authenticate itself</li>
+ * <li><b>enableAuthentication</b> - if set to true, client may authenticate itself but don't have to</li>
+ * <li><b>validateSender</b> - if set to true, emit <code>'validateSender'</code>
+ * with <code>envelope</code>, <code>email</code> and <code>callback</code> when the client
+ * enters <code>MAIL FROM:&lt;address&gt;</code></li>
+ * <li><b>validateRecipients</b> - if set to true, emit <code>'validateRecipient'</code>
+ * with <code>envelope</code>, <code>email</code> and <code>callback</code> when the client
+ * enters <code>RCPT TO:&lt;address&gt;</code></li>
+ * <li><b>maxSize</b> - maximum size of an e-mail in bytes</li>
+ * <li><b>credentials</b> - TLS credentials</li>
+ * <li><b>authMethods</b> - allowed authentication methods, defaults to <code>["PLAIN", "LOGIN"]</code></li>
+ * <li><b>disableEHLO</b> - if set, support HELO only</li>
+ * <li><b>ignoreTLS</b> - if set, allow client do not use STARTTLS</li>
+ * </ul>
+ *
+ * @constructor
+ * @namespace SMTP Server module
+ * @param {Object} [options] Options object
+ */
+function SMTPServer(options){
+ EventEmitter.call(this);
+
+ this.options = options || {};
+ this.options.name = this.options.name || (oslib.hostname && oslib.hostname()) ||
+ (oslib.getHostname && oslib.getHostname()) ||
+ "127.0.0.1";
+
+ this.options.authMethods = (this.options.authMethods || ["PLAIN", "LOGIN"]).map(
+ function(auth){
+ return auth.toUpperCase().trim();
+ });
+
+ this.options.disableEHLO = !!this.options.disableEHLO;
+ this.options.ignoreTLS = !!this.options.ignoreTLS;
+
+ this.SMTPServer = new RAIServer({
+ secureConnection: !!this.options.secureConnection,
+ timeout: this.options.timeout || 60*1000,
+ disconnectOnTimeout: false,
+ debug: !!this.options.debug
+ });
+
+ this.SMTPServer.on("connect", this._createSMTPServerConnection.bind(this));
+}
+utillib.inherits(SMTPServer, EventEmitter);
+
+/**
+ * Server starts listening on defined port and hostname
+ *
+ * @param {Number} port The port number to listen
+ * @param {String} [host] The hostname to listen
+ * @param {Function} callback The callback function to run when the server is listening
+ */
+SMTPServer.prototype.listen = function(port, host, callback){
+ this.SMTPServer.listen(port, host, callback);
+};
+
+/**
+ * <p>Closes the server</p>
+ *
+ * @param {Function} callback The callback function to run when the server is closed
+ */
+SMTPServer.prototype.end = function(callback){
+ this.SMTPServer.end(callback);
+};
+
+/**
+ * <p>Creates a new {@link SMTPServerConnection} object and links the main server with
+ * the client socket</p>
+ *
+ * @param {Object} client RAISocket object to a client
+ */
+SMTPServer.prototype._createSMTPServerConnection = function(client){
+ new SMTPServerConnection(this, client);
+};
+
+/**
+ * <p>Sets up a handler for the connected client</p>
+ *
+ * <p>Restarts the state and sets up event listeners for client actions</p>
+ *
+ * @constructor
+ * @param {Object} server {@link SMTPServer} instance
+ * @param {Object} client RAISocket instance for the client
+ */
+function SMTPServerConnection(server, client){
+ this.server = server;
+ this.client = client;
+
+ this.init();
+
+ if(this.server.options.debug){
+ console.log("Connection from", this.client.remoteAddress);
+ }
+
+ this.client.on("timeout", this._onTimeout.bind(this));
+ this.client.on("error", this._onError.bind(this));
+ this.client.on("command", this._onCommand.bind(this));
+ this.client.on("end", this._onEnd.bind(this));
+
+ this.client.on("data", this._onData.bind(this));
+ this.client.on("ready", this._onDataReady.bind(this));
+
+ // Send the greeting banner
+ this.client.send("220 "+this.server.options.name+" "+(this.server.options.SMTPBanner || "ESMTP node.js simplesmtp"));
+}
+
+/**
+ * <p>Reset the envelope state</p>
+ *
+ * <p>If <code>keepAuthData</code> is set to true, then doesn't remove
+ * authentication data</p>
+ *
+ * @param {Boolean} [keepAuthData=false] If set to true keep authentication data
+ */
+SMTPServerConnection.prototype.init = function(keepAuthData){
+ this.envelope = {from: "", to:[], date: new Date()};
+
+ if(this.hostNameAppearsAs){
+ this.envelope.host = this.hostNameAppearsAs;
+ }
+
+ if(this.client.remoteAddress){
+ this.envelope.remoteAddress = this.client.remoteAddress;
+ }
+
+ if(!keepAuthData){
+ this.authentication = {
+ username: false,
+ authenticated: false,
+ state: "NORMAL"
+ };
+ }
+
+ this.envelope.authentication = this.authentication;
+};
+
+/**
+ * <p>Sends a message to the client and closes the connection</p>
+ *
+ * @param {String} [message] if set, send it to the client before disconnecting
+ */
+SMTPServerConnection.prototype.end = function(message){
+ if(message){
+ this.client.send(message);
+ }
+ this.client.end();
+};
+
+/**
+ * <p>Will be called when the connection to the client is closed</p>
+ *
+ * @event
+ */
+SMTPServerConnection.prototype._onEnd = function(){
+ if(this.server.options.debug){
+ console.log("Connection closed to", this.client.remoteAddress);
+ }
+ this.server.emit("close", this.envelope);
+};
+
+/**
+ * <p>Will be called when timeout occurs</p>
+ *
+ * @event
+ */
+SMTPServerConnection.prototype._onTimeout = function(){
+ this.end("421 4.4.2 "+this.server.options.name+" Error: timeout exceeded");
+};
+
+/**
+ * <p>Will be called when an error occurs</p>
+ *
+ * @event
+ */
+SMTPServerConnection.prototype._onError = function(){
+ this.end("421 4.4.2 "+this.server.options.name+" Error: client error");
+};
+
+/**
+ * <p>Will be called when a command is received from the client</p>
+ *
+ * <p>If there's curently an authentication process going on, route
+ * the data to <code>_handleAuthLogin</code>, otherwise act as
+ * defined</p>
+ *
+ * @event
+ * @param {String} command Command
+ * @param {Buffer} command Payload related to the command
+ */
+SMTPServerConnection.prototype._onCommand = function(command, payload){
+
+ if(this.authentication.state == "AUTHPLAINUSERDATA"){
+ this._handleAuthPlain(command.toString("utf-8").trim().split(" "));
+ return;
+ }
+
+ if(this.authentication.state == "AUTHENTICATING"){
+ this._handleAuthLogin(command);
+ return;
+ }
+
+ switch((command || "").toString().trim().toUpperCase()){
+
+ // Should not occur too often
+ case "HELO":
+ this._onCommandHELO(payload.toString("utf-8").trim());
+ break;
+
+ // Lists server capabilities
+ case "EHLO":
+ if(!this.server.options.disableEHLO){
+ this._onCommandEHLO(payload.toString("utf-8").trim());
+ }else{
+ this.client.send("502 5.5.2 Error: command not recognized");
+ }
+ break;
+
+ // Closes the connection
+ case "QUIT":
+ this.end("221 2.0.0 Goodbye!");
+ break;
+
+ // Resets the current state
+ case "RSET":
+ this._onCommandRSET();
+ break;
+
+ // Doesn't work for spam related purposes
+ case "VRFY":
+ this.client.send("252 2.1.5 Send some mail, I'll try my best");
+ break;
+
+ // Initiate an e-mail by defining a sender
+ case "MAIL":
+ this._onCommandMAIL(payload.toString("utf-8").trim());
+ break;
+
+ // Add recipients to the e-mail envelope
+ case "RCPT":
+ this._onCommandRCPT(payload.toString("utf-8").trim());
+ break;
+
+ // Authenticate if needed
+ case "AUTH":
+ this._onCommandAUTH(payload);
+ break;
+
+ // Start accepting binary data stream
+ case "DATA":
+ this._onCommandDATA();
+ break;
+
+ // Upgrade connection to secure TLS
+ case "STARTTLS":
+ this._onCommandSTARTTLS();
+ break;
+
+ // Display an error on anything else
+ default:
+ this.client.send("502 5.5.2 Error: command not recognized");
+ }
+};
+
+/**
+ * <p>Initiate an e-mail by defining a sender.</p>
+ *
+ * <p>This doesn't work if authorization is required but the client is
+ * not logged in yet.</p>
+ *
+ * <p>If <code>validateSender</code> option is set to true, then emits
+ * <code>'validateSender'</code> and wait for the callback before moving
+ * on</p>
+ *
+ * @param {String} mail Address payload in the form of "FROM:&lt;address&gt;"
+ */
+SMTPServerConnection.prototype._onCommandMAIL = function(mail){
+ var match, email, domain;
+
+ if(!this.hostNameAppearsAs){
+ return this.client.send("503 5.5.1 Error: send HELO/EHLO first");
+ }
+
+ if(this.server.options.requireAuthentication && !this.authentication.authenticated){
+ return this.client.send("530 5.5.1 Authentication Required");
+ }
+
+ if(this.envelope.from){
+ return this.client.send("503 5.5.1 Error: nested MAIL command");
+ }
+
+ if(!(match = mail.match(/^from\:\s*<([^@>]+\@([^@>]+))>$/i))){
+ return this.client.send("501 5.1.7 Bad sender address syntax");
+ }
+
+ email = match[1] || "";
+ domain = (match[2] || "").toLowerCase();
+
+ dnslib.resolveMx(domain, (function(err, addresses){
+ if(err || !addresses || !addresses.length){
+ return this.client.send("450 4.1.8 <"+email+">: Sender address rejected: Domain not found");
+ }
+
+ if(this.server.options.validateSender){
+ this.server.emit("validateSender", this.envelope, email, (function(err){
+ if(err){
+ return this.client.send("550 5.1.1 <"+email+">: Sender address rejected: User unknown in local sender table");
+ }
+
+ // force domain part to be lowercase
+ email = email.substr(0, email.length - domain.length) + domain;
+ this.envelope.from = email;
+ this.client.send("250 2.1.0 Ok");
+
+ }).bind(this));
+ }else{
+ // force domain part to be lowercase
+ email = email.substr(0, email.length - domain.length) + domain;
+ this.envelope.from = email;
+ this.client.send("250 2.1.0 Ok");
+ }
+ }).bind(this));
+};
+
+/**
+ * <p>Add recipients to the e-mail envelope</p>
+ *
+ * <p>This doesn't work if <code>MAIL</code> command is not yet executed</p>
+ *
+ * <p>If <code>validateRecipients</code> option is set to true, then emits
+ * <code>'validateRecipient'</code> and wait for the callback before moving
+ * on</p>
+ *
+ * @param {String} mail Address payload in the form of "TO:&lt;address&gt;"
+ */
+SMTPServerConnection.prototype._onCommandRCPT = function(mail){
+ var match, email, domain;
+
+ if(!this.envelope.from){
+ return this.client.send("503 5.5.1 Error: need MAIL command");
+ }
+
+ if(!(match = mail.match(/^to\:\s*<([^@>]+\@([^@>]+))>$/i))){
+ return this.client.send("501 5.1.7 Bad recipient address syntax");
+ }
+
+ email = match[1] || "";
+ domain = (match[2] || "").toLowerCase();
+
+ dnslib.resolveMx(domain, (function(err, addresses){
+ if(err || !addresses || !addresses.length){
+ return this.client.send("450 4.1.8 <"+email+">: Recipient address rejected: Domain not found");
+ }
+
+ if(this.server.options.validateRecipients){
+ this.server.emit("validateRecipient", this.envelope, email, (function(err){
+ if(err){
+ return this.client.send("550 5.1.1 <"+email+">: Recipient address rejected: User unknown in local recipient table");
+ }
+
+ // force domain part to be lowercase
+ email = email.substr(0, email.length - domain.length) + domain;
+
+ // add to recipients list
+ if(this.envelope.to.indexOf(email)<0){
+ this.envelope.to.push(email);
+ }
+ this.client.send("250 2.1.0 Ok");
+ }).bind(this));
+ }else{
+ // force domain part to be lowercase
+ email = email.substr(0, email.length - domain.length) + domain;
+
+ // add to recipients list
+ if(this.envelope.to.indexOf(email)<0){
+ this.envelope.to.push(email);
+ }
+ this.client.send("250 2.1.0 Ok");
+ }
+ }).bind(this));
+};
+
+/**
+ * <p>Switch to data mode and starts waiting for a binary data stream. Emits
+ * <code>'startData'</code>.</p>
+ *
+ * <p>If <code>RCPT</code> is not yet run, stop</p>
+ */
+SMTPServerConnection.prototype._onCommandDATA = function(){
+
+ if(!this.envelope.to.length){
+ return this.client.send("503 5.5.1 Error: need RCPT command");
+ }
+
+ this.client.startDataMode();
+ this.client.send("354 End data with <CR><LF>.<CR><LF>");
+ this.server.emit("startData", this.envelope);
+};
+
+/**
+ * <p>Resets the current state - e-mail data and authentication info</p>
+ */
+SMTPServerConnection.prototype._onCommandRSET = function(){
+ this.init();
+ this.client.send("250 2.0.0 Ok");
+};
+
+/**
+ * <p>If the server is in secure connection mode, start the authentication
+ * process. Param <code>payload</code> defines the authentication mechanism.</p>
+ *
+ * <p>Currently supported - PLAIN and LOGIN. There is no need for more
+ * complicated mechanisms (different CRAM versions etc.) since authentication
+ * is only done in secure connection mode</p>
+ *
+ * @param {Buffer} payload Defines the authentication mechanism
+ */
+SMTPServerConnection.prototype._onCommandAUTH = function(payload){
+ var method;
+
+ if(!this.server.options.requireAuthentication && !this.server.options.enableAuthentication){
+ return this.client.send("503 5.5.1 Error: authentication not enabled");
+ }
+
+ if(!this.server.options.ignoreTLS && !this.client.secureConnection){
+ return this.client.send("530 5.7.0 Must issue a STARTTLS command first");
+ }
+
+ if(this.authentication.authenticated){
+ return this.client.send("503 5.7.0 No identity changes permitted");
+ }
+
+ payload = payload.toString("utf-8").trim().split(" ");
+ method = payload.shift().trim().toUpperCase();
+
+ if(this.server.options.authMethods.indexOf(method)<0){
+ return this.client.send("535 5.7.8 Error: authentication failed: no mechanism available");
+ }
+
+ switch(method){
+ case "PLAIN":
+ this._handleAuthPlain(payload);
+ break;
+ case "LOGIN":
+ this._handleAuthLogin();
+ break;
+ }
+};
+
+/**
+ * <p>Upgrade the connection to a secure TLS connection</p>
+ */
+SMTPServerConnection.prototype._onCommandSTARTTLS = function(){
+ if(this.client.secureConnection){
+ return this.client.send("554 5.5.1 Error: TLS already active");
+ }
+
+ this.client.send("220 2.0.0 Ready to start TLS");
+
+ this.client.startTLS(this.server.options.credentials, (function(){
+ // Connection secured
+ // nothing to do here, since it is the client that should
+ // make the next move
+ }).bind(this));
+};
+
+/**
+ * <p>Retrieve hostname from the client. Not very important, since client
+ * IP is already known and the client can send fake data</p>
+ *
+ * @param {String} host Hostname of the client
+ */
+SMTPServerConnection.prototype._onCommandHELO = function(host){
+ if(!host){
+ return this.client.send("501 Syntax: EHLO hostname");
+ }else{
+ this.hostNameAppearsAs = host;
+ this.envelope.host = host;
+ }
+ this.client.send("250 "+this.server.options.name+" at your service, ["+
+ this.client.remoteAddress+"]");
+};
+
+/**
+ * <p>Retrieve hostname from the client. Not very important, since client
+ * IP is already known and the client can send fake data</p>
+ *
+ * <p>Additionally displays server capability list to the client</p>
+ *
+ * @param {String} host Hostname of the client
+ */
+SMTPServerConnection.prototype._onCommandEHLO = function(host){
+ var response = [this.server.options.name+" at your service, ["+
+ this.client.remoteAddress+"]", "8BITMIME", "ENHANCEDSTATUSCODES"];
+
+ if(this.server.options.maxSize){
+ response.push("SIZE "+this.server.options.maxSize);
+ }
+
+ if((this.client.secureConnection || this.server.options.ignoreTLS) && (this.server.options.requireAuthentication || this.server.options.enableAuthentication)){
+ response.push("AUTH "+this.server.options.authMethods.join(" "));
+ response.push("AUTH="+this.server.options.authMethods.join(" "));
+ }
+
+ if(!this.client.secureConnection){
+ response.push("STARTTLS");
+ }
+
+ if(!host){
+ return this.client.send("501 Syntax: EHLO hostname");
+ }else{
+ this.hostNameAppearsAs = host;
+ this.envelope.host = host;
+ }
+
+ this.client.send(response.map(function(feature, i, arr){
+ return "250"+(i<arr.length-1?"-":" ")+feature;
+ }).join("\r\n"));
+};
+
+/**
+ * <p>Detect login information from the payload and initiate authentication
+ * by emitting <code>'authorizeUser'</code> and waiting for its callback</p>
+ *
+ * @param {Buffer} payload AUTH PLAIN login information
+ */
+SMTPServerConnection.prototype._handleAuthPlain = function(payload){
+ if (payload.length) {
+ var userdata = new Buffer(payload.join(" "), "base64"), password;
+ userdata = userdata.toString("utf-8").split("\u0000");
+
+ if (userdata.length != 3) {
+ return this.client.send("500 5.5.2 Error: invalid userdata to decode");
+ }
+
+ this.authentication.username = userdata[1] || userdata[0] || "";
+ password = userdata[2] || "";
+
+ this.server.emit("authorizeUser",
+ this.envelope,
+ this.authentication.username,
+ password,
+ (function(err, success){
+ if(err || !success){
+ this.authentication.authenticated = false;
+ this.authentication.username = false;
+ this.authentication.state = "NORMAL";
+ return this.client.send("535 5.7.8 Error: authentication failed: generic failure");
+ }
+ this.client.send("235 2.7.0 Authentication successful");
+ this.authentication.authenticated = true;
+ this.authentication.state = "AUTHENTICATED";
+ }).bind(this));
+ } else {
+ if(this.authentication.state == "NORMAL"){
+ this.authentication.state = "AUTHPLAINUSERDATA";
+ this.client.send("334");
+ }
+ }
+
+};
+
+/**
+ * <p>Sets authorization state to "AUTHENTICATING" and reuqests for the
+ * username and password from the client</p>
+ *
+ * <p>If username and password are set initiate authentication
+ * by emitting <code>'authorizeUser'</code> and waiting for its callback</p>
+ *
+ * @param {Buffer} payload AUTH LOGIN login information
+ */
+SMTPServerConnection.prototype._handleAuthLogin = function(payload){
+ if(this.authentication.state == "NORMAL"){
+ this.authentication.state = "AUTHENTICATING";
+ this.client.send("334 VXNlcm5hbWU6");
+ }else if(this.authentication.state == "AUTHENTICATING"){
+ if(this.authentication.username === false){
+ this.authentication.username = new Buffer(payload, "base64").toString("utf-8");
+ this.client.send("334 UGFzc3dvcmQ6");
+ }else{
+ this.authentication.state = "VERIFYING";
+ this.server.emit("authorizeUser",
+ this.envelope,
+ this.authentication.username,
+ new Buffer(payload, "base64").toString("utf-8"),
+ (function(err, success){
+ if(err || !success){
+ this.authentication.authenticated = false;
+ this.authentication.username = false;
+ this.authentication.state = "NORMAL";
+ return this.client.send("535 5.7.8 Error: authentication failed: generic failure");
+ }
+ this.client.send("235 2.7.0 Authentication successful");
+ this.authentication.authenticated = true;
+ this.authentication.state = "AUTHENTICATED";
+ }).bind(this));
+ }
+
+ }
+};
+
+/**
+ * <p>Emits the data received from the client with <code>'data'</code>
+ *
+ * @event
+ * @param {Buffer} chunk Binary data sent by the client on data mode
+ */
+SMTPServerConnection.prototype._onData = function(chunk){
+ this.server.emit("data", this.envelope, chunk);
+};
+
+/**
+ * <p>If the data stream ends, emit <code>'dataReady'</code>and wait for
+ * the callback, only if server listened for it.</p>
+ *
+ * @event
+ */
+SMTPServerConnection.prototype._onDataReady = function(){
+ if (this.server.listeners('dataReady').length) {
+ this.server.emit("dataReady", this.envelope, (function(err, code){
+ this.init(true); //reset state, keep auth data
+
+ if(err){
+ this.client.send("550 FAILED");
+ }else{
+ this.client.send("250 2.0.0 Ok: queued as "+(code || "FOOBARBAZ"));
+ }
+
+ }).bind(this));
+ } else {
+ this.init(true); //reset state, keep auth data
+ this.client.send("250 2.0.0 Ok: queued as FOOBARBAZ");
+ }
+};
+
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/starttls.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/starttls.js
new file mode 100644
index 0000000..836f0f6
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/lib/starttls.js
@@ -0,0 +1,112 @@
+// SOURCE: https://gist.github.com/848444
+
+// Target API:
+//
+// var s = require('net').createStream(25, 'smtp.example.com');
+// s.on('connect', function() {
+// require('starttls')(s, options, function() {
+// if (!s.authorized) {
+// s.destroy();
+// return;
+// }
+//
+// s.end("hello world\n");
+// });
+// });
+//
+//
+
+/**
+ * @namespace Client STARTTLS module
+ * @name starttls
+ */
+module.exports.starttls = starttls;
+
+/**
+ * <p>Upgrades a socket to a secure TLS connection</p>
+ *
+ * @memberOf starttls
+ * @param {Object} socket Plaintext socket to be upgraded
+ * @param {Function} callback Callback function to be run after upgrade
+ */
+function starttls(socket, callback) {
+ var sslcontext, pair, cleartext;
+
+ socket.removeAllListeners("data");
+ sslcontext = require('crypto').createCredentials();
+ pair = require('tls').createSecurePair(sslcontext, false);
+ cleartext = pipe(pair, socket);
+
+ pair.on('secure', function() {
+ var verifyError = (pair._ssl || pair.ssl).verifyError();
+
+ if (verifyError) {
+ cleartext.authorized = false;
+ cleartext.authorizationError = verifyError;
+ } else {
+ cleartext.authorized = true;
+ }
+
+ callback(cleartext);
+ });
+
+ cleartext._controlReleased = true;
+ return pair;
+}
+
+function forwardEvents(events, emitterSource, emitterDestination) {
+ var map = [], name, handler;
+
+ for(var i = 0, len = events.length; i < len; i++) {
+ name = events[i];
+
+ handler = forwardEvent.bind(emitterDestination, name);
+
+ map.push(name);
+ emitterSource.on(name, handler);
+ }
+
+ return map;
+}
+
+function forwardEvent() {
+ this.emit.apply(this, arguments);
+}
+
+function removeEvents(map, emitterSource) {
+ for(var i = 0, len = map.length; i < len; i++){
+ emitterSource.removeAllListeners(map[i]);
+ }
+}
+
+function pipe(pair, socket) {
+ pair.encrypted.pipe(socket);
+ socket.pipe(pair.encrypted);
+
+ pair.fd = socket.fd;
+
+ var cleartext = pair.cleartext;
+
+ cleartext.socket = socket;
+ cleartext.encrypted = pair.encrypted;
+ cleartext.authorized = false;
+
+ function onerror(e) {
+ if (cleartext._controlReleased) {
+ cleartext.emit('error', e);
+ }
+ }
+
+ var map = forwardEvents(["timeout", "end", "close", "drain", "error"], socket, cleartext);
+
+ function onclose() {
+ socket.removeListener('error', onerror);
+ socket.removeListener('close', onclose);
+ removeEvents(map,socket);
+ }
+
+ socket.on('error', onerror);
+ socket.on('close', onclose);
+
+ return cleartext;
+} \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/.npmignore b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/.npmignore
new file mode 100644
index 0000000..b512c09
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/.npmignore
@@ -0,0 +1 @@
+node_modules \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/.travis.yml b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/.travis.yml
new file mode 100644
index 0000000..cf1b970
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/.travis.yml
@@ -0,0 +1,12 @@
+language: node_js
+node_js:
+ - 0.4
+ - 0.6
+ - 0.7
+
+notifications:
+ email:
+ recipients:
+ - andris@node.ee
+ on_success: change
+ on_failure: change
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/LICENSE b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/LICENSE
new file mode 100644
index 0000000..a47b0ea
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/LICENSE
@@ -0,0 +1,16 @@
+Copyright (c) 2012 Andris Reinman
+
+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 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. \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/README.md b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/README.md
new file mode 100644
index 0000000..542409e
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/README.md
@@ -0,0 +1,163 @@
+# RAI - Request-Answer-Interface
+
+**rai** is a node.js module to easily generate text based command line servers.
+When a client sends something to the server, the first word of the line is
+treated as a command and the rest of the line as binary payload.
+
+[![Build Status](https://secure.travis-ci.org/andris9/rai.png)](http://travis-ci.org/andris9/rai)
+
+In addition to line based commands, there's also a data mode, to transmit
+everygting received. And there's also an option to switch to TLS mode for
+secure connections.
+
+This way it is trivial to create SMTP, POP3 or similar servers.
+
+## Documentation
+
+Autogenerated docs can be seen [here](http://node.ee/raidoc/).
+
+## Installation
+
+ npm install rai
+
+## Usage
+
+### Simple server
+
+ var RAIServer = require("rai").RAIServer;
+
+ // create a RAIServer on port 1234
+ var server = new RAIServer();
+ server.listen(1234);
+
+ // Start listening for client connections
+ server.on("connect", function(client){
+
+ // Greet the client
+ client.send("Hello!");
+
+ // Wait for a command
+ client.on("command", function(command, payload){
+
+ if(command == "STATUS"){
+ client.send("Status is OK!");
+ }else if(command == "QUIT"){
+ client.send("Goodbye");
+ client.end();
+ }else{
+ client.send("Unknown command");
+ }
+
+ });
+
+ });
+
+Server only emits `'connect'` and `'error'` events, while the client
+objects emit `'timeout'`, `'error'` and `'end'` in addition to data
+related events.
+
+### Starting a server
+
+Server can be started with `new RAIServer([options])` where options is an optional
+parameters object with the following properties:
+
+ * **debug** - if set to true print traffic to console
+ * **disconnectOnTimeout** - if set to true close the connection on disconnect
+ * **secureConnection** - if set to true close the connection on disconnect
+ * **credentials** - credentials for secureConnection and STARTTLS
+ * **timeout** - timeout in milliseconds for disconnecting the client, defaults to 0 (no timeout)
+
+Once the server has been set up, it can start listening for client connections
+with `server.listen(port[, hostname][, callback])`. Callback function gets an error
+object as a parameter if the listening failed.
+
+ var server = new RAIServer();
+ server.listen(25); // start listening for port 25 on "localhost"
+
+### Closing server
+
+Server can be closed with `server.end([callback])` where callback is run when
+the server is finally closed.
+
+### Sending data
+
+Data can be sent with `client.send(data)` where `data` is either a String or
+a Buffer. `"\r\n"` is automatically appended to the data.
+
+ client.send("Greetings!");
+
+### Forcing connection close
+
+Connections can be ended with `client.end()`
+
+ if(command == "QUIT"){
+ client.send("Good bye!");
+ client.end();
+ }
+
+### TLS mode
+
+TLS can be switched on with `client.startTLS([credentials][, callback])` and the status can
+be listened with `'tls'` (emitted when secure connection is established)
+
+`credentials` is an object with strings of pem encoded `key`, `cert` and optionally an
+array `ca`. If `credentials` is not supplied, an autogenerated value is used.
+
+ if(command == "STARTTLS"){
+ client.startTLS();
+ }
+
+ client.on("tls", function(){
+ console.log("Switched to secure connection");
+ });
+
+If `callback` is not set `'tls'` will be emitted on connection upgrade.
+
+### Data mode
+
+Data mode can be turned on with `client.startDataMode([endSequence])` and incoming
+chunks can be received with `'data'`. The end of data mode can be detected by
+`'ready'`.
+
+`endSequence` is a String for matching the end (entire line) of the data stream.
+By default it's `"."` which is suitable for SMTP and POP3.
+
+ if(command == "DATA"){
+ client.send("End data with <CR><LF>.<CR><LF>");
+ client.startDataMode();
+ }
+
+ client.on("data", function(chunk){
+ console.log("Data from client:", chunk);
+ });
+
+ client.on("ready", function(){
+ client.send("Data received");
+ });
+
+## Testing
+
+There is a possibility to set up a mockup client which sends a batch of commands
+one by one to the server and returns the last response.
+
+ var runClientMockup = require("rai").runClientMockup;
+
+ var cmds = ["EHLO FOOBAR", "STARTTLS", "QUIT"];
+ runClientMockup(25, "mail.hot.ee", cmds, function(resp){
+ console.log("Final:", resp.toString("utf-8").trim());
+ });
+
+`runClientMockup` has he following parameters in the following order:
+
+ * **port** - Port number
+ * **host** - Hostname to connect to
+ * **commands** - Command list (an array) to be sent to server
+ * **callback** - Callback function to run on completion
+ * **debug** - if set to true log all input/output
+
+Response from the callback function is a Buffer and contains the
+last data received from the server
+
+## License
+
+**MIT** \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/cert/cert.pem b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/cert/cert.pem
new file mode 100644
index 0000000..c72af8a
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/cert/cert.pem
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICWzCCAcQCCQDBn+mBQGOp/jANBgkqhkiG9w0BAQUFADByMQswCQYDVQQGEwJF
+RTEOMAwGA1UECBMFSGFyanUxEDAOBgNVBAcTB1RhbGxpbm4xDzANBgNVBAoTBkty
+ZWF0YTEPMA0GA1UEAxMGYW5kcmlzMR8wHQYJKoZIhvcNAQkBFhBhbmRyaXNAa3Jl
+YXRhLmVlMB4XDTEyMDExNzE0NDYxNloXDTEyMDIxNjE0NDYxNlowcjELMAkGA1UE
+BhMCRUUxDjAMBgNVBAgTBUhhcmp1MRAwDgYDVQQHEwdUYWxsaW5uMQ8wDQYDVQQK
+EwZLcmVhdGExDzANBgNVBAMTBmFuZHJpczEfMB0GCSqGSIb3DQEJARYQYW5kcmlz
+QGtyZWF0YS5lZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAv+G/z03hCpY1
+xN31H0uco4ehyoj1cGGzRVPBPcjVVgbjhuK5Azsp284yVdCTqiB2fWBMjhMOv11S
+9rtIS7sR7AZIXH+aoyaOJYhysnl2zlGAvIfSL+F3pt78oWnVo42pD2UJae3VkAcK
+KP4zu5TWPim4+rUznbgl1Gas6f5zYoECAwEAATANBgkqhkiG9w0BAQUFAAOBgQAq
+jTrU4GPFwBbOJluYDy46qm+2G35A1jL8Ko7ZRgefc68OXkmuFnavjU4YkWV9i52c
+JjQ/MeY0llZaLIQsCsoVCWLVekoqU24V2KA4GkK4WJiax7vgUjy/z/4bfmXa1Xzd
+fc0blopaiBATshEyt+xN5u/acFVfftc4HCb4TarG8g==
+-----END CERTIFICATE-----
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/cert/key.pem b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/cert/key.pem
new file mode 100644
index 0000000..288cf85
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/cert/key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQC/4b/PTeEKljXE3fUfS5yjh6HKiPVwYbNFU8E9yNVWBuOG4rkD
+OynbzjJV0JOqIHZ9YEyOEw6/XVL2u0hLuxHsBkhcf5qjJo4liHKyeXbOUYC8h9Iv
+4Xem3vyhadWjjakPZQlp7dWQBwoo/jO7lNY+Kbj6tTOduCXUZqzp/nNigQIDAQAB
+AoGBAKAwHqk6Iv1rmUfY5KJTxVjgCjnDTOOdLMRbv5+M4k0HQzuAW2RPKArQgUUS
+87O7li/lDQQu9MjdaD2C7EAM1E/7G0bQ02sHtmwT1+2IyvlbRS+Ki6HgJ3fPfbdC
+8+bJHF+Rlksp+fu0eOGLRAcUMH7fwTeqrfGg3b1eIEgt7ZKBAkEA8bgPILaiN7Nt
+JtXhJBC8C5DUj28x/tyR81SkFfYXHwTf8VGiGcufGEVS9YNcYS6ef0WrDrtL4akg
+KlyRdQPmZQJBAMs36lfEngWk1lqho9mR7pu9LA+eChIGvMWshlO1bdOU6ObLhcva
+v/DhjlTgDLy772VGZR5DyCrJrFtRoGDBy+0CQQDiKHpO+1IPl5s6yMZbviSTFbEr
+erhmYu1TpA/aVGQRq7fzy5NFW1TBmqsh9wQKEVpOblq779XxjxH/UJjvyPRZAkAK
+yBOpxmev2vf4ZP0BbQmgv5+X0IWuQSdAwY9633RNNmhI3mFh2GA4km7vt9dVKA9i
+ayKwQV5cTsjTK3h7yaxdAkA2FiEAbkx0ODWOsYv7Ey/G6wBK04CYVuG3Abe8Siul
+H0sKoLmOZRWG4UyjUCfVRH4LiV+4IaV5XPwOqw5zHuns
+-----END RSA PRIVATE KEY-----
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/examples/smtp.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/examples/smtp.js
new file mode 100644
index 0000000..4ee2763
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/examples/smtp.js
@@ -0,0 +1,73 @@
+var RAIServer = require("../lib/rai").RAIServer;
+
+var server = new RAIServer({debug: true, timeout:25*1000});
+
+server.listen(1234, function(err){
+ console.log(err || "listening on port 1234...")
+});
+
+server.on("connection", function(socket){
+
+ socket.send("220 foo.bar"); // send banner greeting
+
+ socket.on("command", function(command, payload){
+
+ command = (command || "").toString().toUpperCase().trim();
+
+ switch(command){
+ case "EHLO":
+ socket.send("250-foo.bar at your service\r\n"+
+ "250-PIPELINING\r\n" +
+ "250-8BITMIME\r\n"+
+ "250 STARTTLS");
+ break;
+ case "STARTTLS":
+ socket.send("220 Ready to start TLS");
+ socket.startTLS();
+ break;
+ case "MAIL":
+ socket.send("250 Ok");
+ break;
+ case "RCPT":
+ socket.send("250 Ok");
+ break;
+ case "DATA":
+ socket.send("354 End with <CR><LF>.<CR><LF>");
+ socket.startDataMode();
+ break;
+ case "QUIT":
+ socket.send("221 Good bye");
+ socket.end();
+ break;
+ default:
+ socket.send("500 Unknown command");
+ }
+
+ });
+
+ socket.on("tls", function(data){
+ console.log("TLS STARTED");
+ });
+
+ socket.on("data", function(data){
+ console.log("MAIL DATA", data);
+ });
+
+ socket.on("ready", function(data){
+ console.log("DATA READY");
+ socket.send("250 Ok: queued as FOOBAR");
+ });
+
+ socket.on("timeout", function(data){
+ console.log("TIMEOUT");
+ });
+
+ socket.on("error", function(err){
+ console.log("ERROR:", err.message || err);
+ });
+
+ socket.on("end", function(){
+ console.log("Connection closed");
+ });
+
+}); \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/all.css b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/all.css
new file mode 100644
index 0000000..c253cb0
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/all.css
@@ -0,0 +1,358 @@
+/* TABLE OF CONTENTS:
+ * - Browser reset
+ * - HTML elements
+ * - JsDoc styling
+ */
+
+
+
+
+
+
+/*
+ * BEGIN BROWSER RESET
+ */
+
+body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,p,pre,form,fieldset,input,textarea,p,blockquote,th,td {
+ margin:0;
+ padding:0
+}
+html {
+ height:100%;
+ overflow:-moz-scrollbars-vertical;
+ overflow-x:auto
+}
+table {
+ border:0;
+ border-collapse:collapse;
+ border-spacing:0
+}
+fieldset,img {
+ border:0
+}
+address,caption,cite,code,dfn,em,strong,th,var {
+ font-style:normal;
+ font-weight:normal
+}
+em,cite {
+ font-style:italic
+}
+strong {
+ font-weight:bold
+}
+ol,ul {
+ list-style:none
+}
+caption,th {
+ text-align:left
+}
+h1,h2,h3,h4,h5,h6 {
+ font-size:100%;
+ font-weight:normal;
+ margin:0;
+ padding:0
+}
+q:before,q:after {
+ content:''
+}
+abbr,acronym {
+ border:0
+}
+section,article,header,footer,nav,aside,hgroup {
+ display:block
+}
+
+/*
+ * END BROWSER RESET
+ */
+
+
+
+
+
+
+/*
+ * HTML ELEMENTS
+ */
+
+@font-face {
+ font-family: 'M1m';
+ src: url('fonts/mplus-1m-regular-webfont.eot');
+ src: local('☺'), url('fonts/mplus-1m-regular-webfont.woff') format('woff'), url('fonts/mplus-1m-regular-webfont.ttf') format('truetype'), url('fonts/mplus-1m-regular-webfont.svg#webfontVd14f4NN') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'M1m';
+ src: url('fonts/mplus-1m-bold-webfont.eot');
+ src: local('☺'), url('fonts/mplus-1m-bold-webfont.woff') format('woff'), url('fonts/mplus-1m-bold-webfont.ttf') format('truetype'), url('fonts/mplus-1m-bold-webfont.svg#webfontIjI5mZqE') format('svg');
+ font-weight: bold;
+ font-style: normal;
+}
+
+
+
+* {
+ line-height: 1.4em;
+}
+
+html {
+ font-size: 100%;
+}
+
+body {
+ font-size: 0.75em;
+ padding: 15px 0;
+ background: #eee;
+ background-image: -moz-linear-gradient(left, #dddddd, #f9f9f9) fixed;
+ background-image: -webkit-gradient(linear,left bottom,right bottom,color-stop(0, #dddddd),color-stop(1, #f9f9f9)) fixed;
+ }
+
+body,
+input,
+select,
+textarea {
+ color: #000;
+ font-family: Arial, Geneva, sans-serif;
+}
+
+a:link,
+a:hover,
+a:active,
+a:visited {
+ color: #19199e;
+}
+a:hover,
+a:focus {
+ color: #00f;
+ text-decoration: none;
+}
+
+p {
+ margin: 0 0 1.5em 0;
+}
+
+/*
+ * END HTML ELEMENTS
+ */
+
+
+
+/*
+ * BEGIN HACK
+ */
+
+div.containerMain:after,
+div.safeBox:after {
+ content:"";
+ display:block;
+ height:0;
+ clear:both;
+}
+
+/*
+ * END HACK
+ */
+
+
+
+/*
+ * BEGIN JSDOC
+ */
+
+/* Start menu */
+div.index *.heading1 {
+ margin-bottom: 0.5em;
+ border-bottom: 1px solid #999999;
+ font-family: M1m, Arial, sans-serif;
+ font-size: 1.6em;
+ letter-spacing: 1px;
+ line-height: 1.3em;
+}
+
+div.index div.menu {
+ background-color: #FFFFFF;
+}
+*+html div.index div.menu {
+ background-color: #FFFFFF;
+}
+* html div.index div.menu {
+ background-color: #FFFFFF;
+}
+
+div.index div.menu div {
+ text-align: left;
+}
+
+div.index div.menu a {
+ text-decoration: none;
+}
+div.index div.menu a:hover {
+ text-decoration: underline;
+}
+
+div.index ul.classList {
+ padding-left: 0;
+}
+
+div.index ul.classList a {
+ display: block;
+ margin: 1px 0;
+ padding: 4px 0 2px 10px;
+ text-indent: -10px;
+}
+
+div.index div.fineprint {
+ color: #777;
+ font-size: 0.9em;
+}
+div.index div.fineprint a {
+ color: #777;
+}
+/* End menu */
+
+
+
+/* Start content */
+div.content ul {
+ padding-left: 0;
+}
+
+div.content *.classTitle {
+ font-size: 1.2em;
+ font-weight: bold;
+ line-height: 1em;
+}
+
+div.content *.classTitle span {
+ display: block;
+ font-size: 2em;
+ letter-spacing: 2px;
+ line-height: 1em;
+ padding-top: 5px;
+ text-shadow: 1px 1px 1px #999999;
+ word-wrap: break-word;
+}
+
+div.content p.summary {
+ font-size: 1.25em;
+}
+
+div.content ul *.classname a,
+div.content ul *.filename a {
+ font-family: Consolas, "Courier New", Courier, monospace;
+ text-decoration: none;
+ font-weight: bold;
+}
+div.content ul *.classname a:hover,
+div.content ul *.filename a:hover {
+ text-decoration: underline;
+}
+
+div.content div.props {
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+ background: #fff;
+ background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.2)); /* FF3.6 */
+ background: -webkit-gradient(linear,left top,left bottom,color-stop(0, rgba(255, 255, 255, 0.7)),color-stop(1, rgba(255, 255, 255, 0.2)));
+ -moz-box-shadow: 0px 0px 10px #ccc;
+ -webkit-box-shadow: 0px 0px 5px #bbb;
+ box-shadow: 0px 0px 5px #bbb;
+}
+
+
+
+*.sectionTitle {
+ font-family: M1m, sans-serif;
+ font-size: 1.6em;
+ letter-spacing: 1px;
+}
+
+table.summaryTable td,
+table.summaryTable th {
+ vertical-align: top;
+}
+table.summaryTable tr:last-child td {
+ padding-bottom: 0;
+}
+
+table.summaryTable th {
+ font-weight: bold;
+}
+
+table.summaryTable td.attributes {
+ font-family: Consolas, "Courier New", Courier, monospace;
+ color: #666;
+}
+
+table.summaryTable td.nameDescription div.fixedFont {
+ font-weight: bold;
+}
+
+table.summaryTable div.description {
+ color: #333;
+}
+
+
+
+dl.detailList dt {
+ font-weight: bold;
+}
+
+dl.inheritsList dd + dt {
+ margin-top: 10px;
+}
+
+dl.inheritsList dd {
+ display: inline;
+}
+
+
+
+.fixedFont {
+ font-family: Consolas, "Courier New", Courier, monospace;
+}
+
+.fixedFont.heading {
+ font-size: 1.25em;
+ line-height: 1.1em
+}
+
+.fixedFont.heading + .description {
+ font-size: 1.2em;
+}
+
+.fixedFont.heading .light,
+.fixedFont.heading .lighter {
+ font-weight: bold;
+}
+
+pre.code {
+ overflow: auto;
+ font-family: Consolas, "Courier New", Courier, monospace;
+ background: #eee;
+}
+/* Start content */
+
+
+
+/* Start general styles */
+.light {
+ color: #666;
+}
+
+.lighter {
+ color: #999;
+}
+
+span.break {
+ font-size: 1px;
+ line-height: 1px;
+}
+/* End general styles */
+
+/*
+ * END JSDOC
+ */
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.eot b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.eot
new file mode 100644
index 0000000..6c64f8d
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.eot
Binary files differ
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.svg b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.svg
new file mode 100644
index 0000000..5129512
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.svg
@@ -0,0 +1,134 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG webfont generated by Font Squirrel.
+Foundry URL : http://mplus-fonts.sourceforge.jp
+</metadata>
+<defs>
+<font id="webfontIjI5mZqE" horiz-adv-x="500" >
+<font-face units-per-em="1000" ascent="860" descent="-140" />
+<missing-glyph horiz-adv-x="500" />
+<glyph unicode=" " />
+<glyph unicode="!" d="M165 730h170l-20 -495h-130zM170 0v150h160v-150h-160z" />
+<glyph unicode="&#x22;" d="M270 780h160l-30 -320h-100zM70 780h160l-30 -320h-100z" />
+<glyph unicode="#" d="M20 165v120h62l24 185h-51v120h67l18 140h135l-18 -140h45l18 140h135l-18 -140h43v-120h-59l-24 -185h48v-120h-64l-21 -165h-135l21 165h-45l-21 -165h-135l21 165h-46zM217 285h45l24 185h-45z" />
+<glyph unicode="$" d="M357 397q55 -32 76.5 -74t21.5 -108q0 -190 -192 -199v-101h-110v112q-51 16 -88 43v140q38 -35 88 -55v191q-53 33 -75.5 75.5t-22.5 103.5q0 89 50 138.5t142 51.5v100h110v-112q42 -12 78 -33v-135q-32 25 -78 42v-180zM247 445v149q-54 -9 -54 -69q0 -55 54 -80z M263 295v-157q52 13 52 77q0 55 -52 80z" />
+<glyph unicode="%" d="M40 310l420 220v-110l-420 -220v110zM160 740q70 0 110 -41t40 -119t-40 -119t-110 -41t-110 41t-40 119t40 119t110 41zM340 310q70 0 110 -41t40 -119t-40 -119t-110 -41t-110 41t-40 119t40 119t110 41zM160 518q38 0 38 62t-38 62t-38 -62t38 -62zM340 88q38 0 38 62 t-38 62t-38 -62t38 -62z" />
+<glyph unicode="&#x26;" d="M235 615q-23 0 -36.5 -14.5t-13.5 -40.5q0 -18 7.5 -37.5t33.5 -65.5q35 30 47 52.5t12 50.5q0 26 -13.5 40.5t-36.5 14.5zM118 368q-47 77 -62.5 116t-15.5 76q0 80 51.5 130t138.5 50t141 -50.5t54 -129.5q0 -114 -130 -220l55 -94v2v132h125v-225q-16 -25 -41 -52 l61 -103h-150l-15 24q-66 -34 -130 -34q-88 0 -136.5 45.5t-48.5 134.5q0 99 103 198zM269 124l-77 125q-27 -37 -27 -74q0 -60 65 -60q20 0 39 9z" />
+<glyph unicode="'" d="M160 780h180l-35 -320h-110z" />
+<glyph unicode="(" d="M100 300q0 136 50 256.5t144 213.5h126q-196 -194 -196 -470t196 -470h-126q-94 93 -144 213.5t-50 256.5z" />
+<glyph unicode=")" d="M400 300q0 -136 -50 -256.5t-144 -213.5h-126q196 194 196 470t-196 470h126q94 -93 144 -213.5t50 -256.5z" />
+<glyph unicode="*" d="M193 750h114l-4 -144l136 48l35 -109l-138 -40l88 -115l-93 -67l-81 119l-81 -119l-93 67l88 115l-138 40l35 109l136 -48z" />
+<glyph unicode="+" d="M315 545v-195h135v-110h-135v-195h-130v195h-135v110h135v195h130z" />
+<glyph unicode="," d="M180 190h190l-130 -320h-120z" />
+<glyph unicode="-" d="M90 240v110h320v-110h-320z" />
+<glyph unicode="." d="M155 0v190h190v-190h-190z" />
+<glyph unicode="/" d="M465 730l-310 -770h-120l310 770h120z" />
+<glyph unicode="0" d="M250 740q73 0 117.5 -32.5t68.5 -116t24 -226.5t-24 -226.5t-68.5 -116t-117.5 -32.5t-117.5 32.5t-68.5 116t-24 226.5t24 226.5t68.5 116t117.5 32.5zM171 317l142 248q-9 34 -24.5 47t-38.5 13q-28 0 -44.5 -19.5t-26 -77.5t-9.5 -163q0 -33 1 -48zM183 179 q9 -41 25.5 -57.5t41.5 -16.5q28 0 44.5 19.5t26 77.5t9.5 163q0 47 -1 67z" />
+<glyph unicode="1" d="M240 592l-2 1l-173 -91v128l175 100h140v-730h-140v592z" />
+<glyph unicode="2" d="M220 122v-2h220v-120h-380v120q127 141 181 237t54 173q0 43 -21 66.5t-59 23.5q-31 0 -74 -22t-81 -58v130q78 70 185 70q90 0 140 -51t50 -149q0 -180 -215 -418z" />
+<glyph unicode="3" d="M290 608v2h-230v120h385v-120l-170 -178v-2h10q79 0 122 -51.5t43 -153.5q0 -121 -54 -178t-166 -57q-51 0 -81.5 6.5t-78.5 28.5v130q80 -45 150 -45q46 0 68 27t22 88q0 58 -26 76.5t-114 18.5h-40v120z" />
+<glyph unicode="4" d="M400 150v-150h-135v150h-245v120l230 460h150v-460h80v-120h-80zM265 270v255h-2l-127 -253v-2h129z" />
+<glyph unicode="5" d="M202 455q36 19 82 19q161 0 161 -239q0 -245 -230 -245q-76 0 -150 35v130q80 -45 140 -45q51 0 75.5 29t24.5 96t-14.5 93t-46.5 26q-34 0 -64 -34h-110l10 410h345v-120h-220l-5 -155h2z" />
+<glyph unicode="6" d="M295 625q-54 0 -76.5 -34.5t-28.5 -135.5h2q45 35 98 35q92 0 133.5 -54.5t41.5 -185.5q0 -141 -51 -200.5t-159 -59.5q-75 0 -119 28.5t-67.5 101t-23.5 200.5q0 162 25 254t75 129t135 37q66 0 135 -20v-125q-57 30 -120 30zM255 107q39 0 55.5 29.5t16.5 113.5 q0 79 -14 104.5t-53 25.5q-38 0 -56.5 -29.5t-18.5 -100.5q0 -81 17 -112t53 -31z" />
+<glyph unicode="7" d="M55 730h390v-120q-113 -273 -200 -610h-146q92 325 216 608v2h-260v120z" />
+<glyph unicode="8" d="M258 625q-41 0 -59.5 -20.5t-18.5 -64.5q0 -74 75 -105q33 16 51.5 43.5t18.5 61.5q0 40 -18 62.5t-49 22.5zM250 -10q-105 0 -162.5 52t-57.5 148q0 116 105 179v2q-42 31 -66 80t-24 104q0 87 53.5 136t151.5 49t151.5 -48.5t53.5 -136.5q0 -98 -100 -164v-2 q115 -62 115 -199q0 -96 -58 -148t-162 -52zM242 105q93 0 93 100q0 75 -103 115q-33 -17 -52.5 -48.5t-19.5 -66.5q0 -48 22.5 -74t59.5 -26z" />
+<glyph unicode="9" d="M205 110q55 0 77 32.5t28 132.5h-2q-45 -35 -98 -35q-89 0 -132 57.5t-43 192.5q0 131 51 190.5t159 59.5q79 0 123 -27.5t65.5 -99.5t21.5 -203q0 -162 -25 -254t-75 -129t-135 -37q-66 0 -135 20v130q57 -30 120 -30zM245 623q-39 0 -55.5 -28t-16.5 -105 q0 -83 15.5 -111.5t51.5 -28.5q75 0 75 140q0 73 -17 103t-53 30z" />
+<glyph unicode=":" d="M160 390v190h180v-190h-180zM160 0v190h180v-190h-180z" />
+<glyph unicode=";" d="M170 190h190l-130 -320h-120zM170 390v190h180v-190h-180z" />
+<glyph unicode="&#x3c;" d="M445 470l-320 -174v-2l320 -174v-120l-400 225v140l400 225v-120z" />
+<glyph unicode="=" d="M50 125v110h400v-110h-400zM50 362v103h400v-103h-400z" />
+<glyph unicode="&#x3e;" d="M55 470v120l400 -225v-140l-400 -225v120l320 174v2z" />
+<glyph unicode="?" d="M460 575q0 -36 -12.5 -69t-25 -51t-38.5 -49q-25 -30 -38 -48.5t-27.5 -52.5t-18.5 -70h-130q0 49 17 94.5t32 66.5t44 57q21 25 30.5 38t19 33.5t9.5 40.5q0 58 -82 58t-180 -53v130q95 40 200 40q95 0 147.5 -44t52.5 -121zM155 0v150h160v-150h-160z" />
+<glyph unicode="@" d="M285 635q-72 0 -108.5 -62.5t-36.5 -207.5q0 -265 160 -265q58 0 125 30v-115q-70 -25 -150 -25q-260 0 -260 375q0 194 64 284.5t191 90.5q99 0 152 -51.5t53 -148.5v-325q-28 -28 -76 -46.5t-94 -18.5q-69 0 -102 49t-33 166q0 114 31.5 164.5t93.5 50.5q36 0 68 -25h2 v15q0 26 -23.5 45.5t-56.5 19.5zM290 365q0 -72 8 -93.5t29 -21.5q20 0 28 18v147q0 41 -6 53t-25 12t-26.5 -22t-7.5 -93z" />
+<glyph unicode="A" d="M249 620h-2l-55 -335h112zM323 170h-150l-28 -170h-140l165 730h160l165 -730h-144z" />
+<glyph unicode="B" d="M190 445h15q59 0 85 20.5t26 64.5q0 49 -23 71t-73 22q-17 0 -30 -5v-173zM190 330v-218q20 -5 45 -5q51 0 75 27.5t24 90.5q0 57 -25.5 81t-88.5 24h-30zM470 210q0 -220 -240 -220q-93 0 -180 15v720q92 15 190 15q210 0 210 -185q0 -62 -32 -105t-83 -54v-2 q57 -10 96 -61.5t39 -122.5z" />
+<glyph unicode="C" d="M30 365q0 195 64.5 285t190.5 90q80 0 150 -25v-115q-70 25 -125 25q-74 0 -109.5 -58.5t-35.5 -201.5q0 -260 150 -260q57 0 125 30v-120q-70 -25 -150 -25q-260 0 -260 375z" />
+<glyph unicode="D" d="M344 365q0 142 -30 198.5t-94 56.5q-23 0 -40 -5v-500q17 -5 40 -5q63 0 93.5 55.5t30.5 199.5zM480 365q0 -144 -28.5 -226.5t-83.5 -115.5t-148 -33q-92 0 -180 15v720q88 15 180 15q141 0 200.5 -82t59.5 -293z" />
+<glyph unicode="E" d="M210 610v-165h220v-115h-220v-210h230v-120h-370v730h370v-120h-230z" />
+<glyph unicode="F" d="M220 330v-330h-140v730h360v-120h-220v-165h210v-115h-210z" />
+<glyph unicode="G" d="M310 625q-82 0 -116 -55t-34 -205q0 -143 32 -201.5t93 -58.5q27 0 48 10v215h-98v115h230v-415q-83 -40 -180 -40q-260 0 -260 375q0 196 69.5 285.5t215.5 89.5q70 0 130 -25v-115q-72 25 -130 25z" />
+<glyph unicode="H" d="M318 330h-140v-330h-138v730h138v-280h140v280h142v-730h-142v330z" />
+<glyph unicode="I" d="M430 0h-360v115h108v500h-108v115h360v-115h-108v-500h108v-115z" />
+<glyph unicode="J" d="M410 730v-515q0 -126 -48.5 -175.5t-166.5 -49.5q-86 0 -155 30v130q29 -18 68 -30t67 -12q50 0 71 26.5t21 95.5v385h-147v115h290z" />
+<glyph unicode="K" d="M192 330h-2v-330h-140v730h140v-300h2l135 300h148l-160 -345l165 -385h-150z" />
+<glyph unicode="L" d="M230 730v-610h210v-120h-350v730h140z" />
+<glyph unicode="M" d="M338 500h-2l-38 -300h-100l-38 300h-2v-500h-133v730h167l59 -400h2l59 400h163v-730h-137v500z" />
+<glyph unicode="N" d="M187 460h-2v-460h-140v730h147l125 -460h2v460h136v-730h-143z" />
+<glyph unicode="O" d="M250 740q121 0 175.5 -84t54.5 -291t-54.5 -291t-175.5 -84t-175.5 84t-54.5 291t54.5 291t175.5 84zM250 108q52 0 75 53.5t23 203.5t-23 203.5t-75 53.5t-75 -53.5t-23 -203.5t23 -203.5t75 -53.5z" />
+<glyph unicode="P" d="M334 503q0 120 -104 120q-23 0 -40 -5v-235q18 -5 40 -5q53 0 78.5 28t25.5 97zM470 503q0 -127 -57 -184.5t-173 -57.5q-26 0 -50 5v-266h-140v725q90 15 185 15q122 0 178.5 -56t56.5 -181z" />
+<glyph unicode="Q" d="M250 740q121 0 175.5 -84t54.5 -291q0 -257 -92 -333v-2q39 -22 68.5 -74t33.5 -106h-145q-15 81 -36.5 110.5t-58.5 29.5q-121 0 -175.5 84t-54.5 291t54.5 291t175.5 84zM250 108q52 0 75 53.5t23 203.5t-23 203.5t-75 53.5t-75 -53.5t-23 -203.5t23 -203.5t75 -53.5z " />
+<glyph unicode="R" d="M465 513q0 -151 -98 -199l-1 -2q27 -19 58 -118l61 -194h-145l-57 204q-12 43 -25.5 57.5t-42.5 14.5h-30v-276h-140v725q90 15 185 15q124 0 179.5 -53.5t55.5 -173.5zM185 393h30q64 0 89 24.5t25 95.5q0 58 -25.5 84t-78.5 26q-23 0 -40 -5v-225z" />
+<glyph unicode="S" d="M440 575q-84 48 -165 48q-41 0 -65 -21t-24 -57q0 -71 69 -100q116 -48 160.5 -103t44.5 -142q0 -210 -225 -210q-100 0 -180 50v135q83 -68 173 -68q94 0 94 88q0 76 -77 110q-108 46 -151.5 99.5t-43.5 135.5q0 90 57 145t153 55q102 0 180 -35v-130z" />
+<glyph unicode="T" d="M320 615v-615h-140v615h-145v115h430v-115h-145z" />
+<glyph unicode="U" d="M250 -10q-112 0 -161 54t-49 186v500h142v-460q0 -101 14.5 -131.5t55.5 -30.5t55.5 30.5t14.5 131.5v460h138v-500q0 -132 -49 -186t-161 -54z" />
+<glyph unicode="V" d="M253 110l92 620h140l-155 -730h-160l-155 730h144l92 -620h2z" />
+<glyph unicode="W" d="M164 190h2l38 440h100l38 -440h2l15 540h126l-45 -730h-157l-34 420h-2l-34 -420h-153l-45 730h134z" />
+<glyph unicode="X" d="M251 470h2l74 260h145l-132 -360l135 -370h-152l-74 270h-2l-74 -270h-148l135 370l-132 360h149z" />
+<glyph unicode="Y" d="M251 415h2l84 315h148l-165 -455v-275h-140v275l-165 455h152z" />
+<glyph unicode="Z" d="M290 613v2h-235v115h390v-115l-235 -498v-2h235v-115h-390v115z" />
+<glyph unicode="[" d="M410 675h-170v-750h170v-95h-290v940h290v-95z" />
+<glyph unicode="\" d="M35 730h120l310 -770h-120z" />
+<glyph unicode="]" d="M90 675v95h290v-940h-290v95h170v750h-170z" />
+<glyph unicode="^" d="M251 655h-2l-111 -375h-123l145 450h180l145 -450h-123z" />
+<glyph unicode="_" d="M40 -170v88h420v-88h-420z" />
+<glyph unicode="`" d="M90 810h190l100 -320h-120z" />
+<glyph unicode="a" d="M65 495q39 14 95 24.5t90 10.5q111 0 155.5 -45t44.5 -160v-325h-127l-2 65h-2q-49 -75 -134 -75q-68 0 -106.5 42t-38.5 118q0 88 63.5 136.5t186.5 48.5h25v10q0 40 -16 56.5t-54 16.5q-32 0 -86.5 -11.5t-93.5 -26.5v115zM315 245h-25q-59 0 -89.5 -23t-30.5 -62 q0 -31 15 -48t40 -17q90 0 90 130v20z" />
+<glyph unicode="b" d="M45 730h137v-275h2q49 75 116 75q83 0 129 -66.5t46 -203.5q0 -133 -47.5 -201.5t-127.5 -68.5q-35 0 -62.5 17.5t-56.5 62.5h-2l-2 -70h-132v730zM338 260q0 150 -78 150q-80 0 -80 -145v-10q0 -145 80 -145q35 0 56.5 36.5t21.5 113.5z" />
+<glyph unicode="c" d="M305 420q-115 0 -115 -160q0 -163 120 -163q60 0 120 28v-110q-68 -25 -140 -25q-116 0 -178 67.5t-62 202.5t60 202.5t175 67.5q67 0 135 -25v-110q-61 25 -115 25z" />
+<glyph unicode="d" d="M455 0h-132l-2 70h-2q-29 -45 -56.5 -62.5t-62.5 -17.5q-80 0 -127.5 68.5t-47.5 201.5q0 137 46 203.5t129 66.5q67 0 116 -75h2v275h137v-730zM162 260q0 -77 21.5 -113.5t56.5 -36.5q80 0 80 145v10q0 145 -80 145q-78 0 -78 -150z" />
+<glyph unicode="e" d="M182 206q7 -62 33 -85.5t80 -23.5q52 0 135 28v-110q-84 -25 -155 -25q-112 0 -173.5 68t-61.5 202q0 270 220 270q200 0 200 -270q0 -31 -2 -54h-276zM181 310h142q-1 63 -15.5 88t-47.5 25q-41 0 -58 -23t-21 -90z" />
+<glyph unicode="f" d="M60 391v109h100v45q0 104 40.5 149.5t129.5 45.5q56 0 110 -15v-110q-36 16 -80 16q-37 0 -50 -20.5t-13 -85.5v-25h143v-109h-143v-391h-137v391h-100z" />
+<glyph unicode="g" d="M323 75h-2q-45 -75 -116 -75q-78 0 -126.5 66.5t-48.5 193.5q0 137 46 203.5t129 66.5q35 0 62.5 -17.5t56.5 -62.5h2l2 70h132v-505q0 -245 -240 -245q-81 0 -150 25v115q76 -33 145 -33q55 0 81.5 34t26.5 114v50zM167 260q0 -70 22 -105t56 -35q80 0 80 135v10 q0 145 -80 145q-78 0 -78 -150z" />
+<glyph unicode="h" d="M50 730h137v-275h2q47 75 126 75t112 -47.5t33 -172.5v-310h-135v290q0 74 -12.5 98t-47.5 24t-56.5 -43.5t-21.5 -131.5v-237h-137v730z" />
+<glyph unicode="i" d="M110 520h240v-413h100v-107h-370v107h130v306h-100v107zM190 630v130h160v-130h-160z" />
+<glyph unicode="j" d="M225 -20v433h-110v107h250v-540q0 -68 -10.5 -106t-44 -63t-87.5 -33t-148 -8v109q39 0 60.5 0.5t41 5t27 9.5t13.5 18t7 27.5t1 40.5zM205 630v130h160v-130h-160z" />
+<glyph unicode="k" d="M480 520l-185 -250l185 -270h-162l-131 224v-224h-137v730h137v-418l133 208h160z" />
+<glyph unicode="l" d="M310 190q0 -68 9 -80.5t56 -12.5q31 0 75 6v-108q-44 -5 -100 -5q-111 0 -145.5 32.5t-34.5 137.5v463h-120v107h260v-540z" />
+<glyph unicode="m" d="M360 0v340q0 40 -21 40q-8 0 -12.5 -5t-7 -22.5t-2.5 -52.5v-300h-130v340q0 40 -21 40q-8 0 -12.5 -5t-7 -22.5t-2.5 -52.5v-300h-134v520h120l2 -65h2q15 34 39.5 54.5t48.5 20.5q28 0 45 -16t32 -59h2q42 75 99 75q48 0 69 -36t21 -134v-360h-130z" />
+<glyph unicode="n" d="M50 520h132l2 -70h2q49 80 129 80q79 0 112 -47.5t33 -172.5v-310h-135v290q0 74 -12.5 98t-47.5 24t-56.5 -43.5t-21.5 -131.5v-237h-137v520z" />
+<glyph unicode="o" d="M250 530q220 0 220 -270t-220 -270t-220 270t220 270zM250 97q44 0 62 33.5t18 129.5t-18 129.5t-62 33.5t-62 -33.5t-18 -129.5t18 -129.5t62 -33.5z" />
+<glyph unicode="p" d="M179 70h-2v-290h-137v740h132l2 -70h2q29 45 56.5 62.5t62.5 17.5q83 0 129 -66.5t46 -203.5q0 -133 -47.5 -201.5t-127.5 -68.5q-71 0 -116 80zM333 260q0 150 -78 150q-80 0 -80 -145v-10q0 -145 80 -145q35 0 56.5 36.5t21.5 113.5z" />
+<glyph unicode="q" d="M321 70q-45 -80 -116 -80q-80 0 -127.5 68.5t-47.5 201.5q0 137 46 203.5t129 66.5q35 0 62.5 -17.5t56.5 -62.5h2l2 70h132v-740h-137v290h-2zM167 260q0 -77 21.5 -113.5t56.5 -36.5q80 0 80 145v10q0 145 -80 145q-78 0 -78 -150z" />
+<glyph unicode="r" d="M375 416q-69 0 -111 -52t-42 -144v-220h-137v520h135v-85h2q36 53 70.5 74t82.5 21q36 0 70 -10v-115q-36 11 -70 11z" />
+<glyph unicode="s" d="M265 418q-73 0 -73 -43q0 -22 14.5 -35t48.5 -20q109 -21 149.5 -60t40.5 -115q0 -74 -50.5 -114.5t-144.5 -40.5q-107 0 -190 35v120q87 -43 165 -43q45 0 64 11.5t19 36.5q0 22 -14 34t-54 21q-99 21 -142 62.5t-43 112.5t49 110.5t146 39.5q99 0 180 -30v-115 q-87 33 -165 33z" />
+<glyph unicode="t" d="M445 500v-109h-158v-201q0 -61 10.5 -74.5t57.5 -13.5q43 0 80 17v-114q-50 -15 -110 -15q-98 0 -136.5 36.5t-38.5 133.5v231h-105v109h105v190h137v-190h158z" />
+<glyph unicode="u" d="M445 0h-132l-2 70h-2q-50 -80 -124 -80q-77 0 -108.5 44.5t-31.5 165.5v320h135v-300q0 -70 11 -91t44 -21q73 0 73 175v237h137v-520z" />
+<glyph unicode="v" d="M251 90h2l79 430h138l-130 -520h-180l-130 520h142z" />
+<glyph unicode="w" d="M343 120h2l29 400h116l-70 -520h-137l-37 358h-2l-31 -358h-133l-70 520h124l29 -400h2l39 400h100z" />
+<glyph unicode="x" d="M251 335h2l69 185h143l-125 -260l125 -260h-152l-64 180h-2l-64 -180h-148l125 260l-125 260h147z" />
+<glyph unicode="y" d="M254 170h2l87 350h142l-237 -740h-138l85 230l-170 510h142z" />
+<glyph unicode="z" d="M275 411h-210v109h370v-109l-210 -300v-2h210v-109h-370v109l210 300v2z" />
+<glyph unicode="{" d="M187 301v-2q58 -24 85.5 -62t27.5 -100v-112q0 -73 12 -86.5t75 -13.5h53v-95h-107q-80 0 -116.5 37t-36.5 123v147q0 61 -22 88t-68 27h-40v96h40q46 0 68 27t22 88v147q0 86 36.5 123t116.5 37h107v-95h-53q-63 0 -75 -13.5t-12 -86.5v-112q0 -62 -27.5 -100t-85.5 -62 z" />
+<glyph unicode="|" d="M188 -220v1030h124v-1030h-124z" />
+<glyph unicode="}" d="M313 301q-58 24 -85.5 62t-27.5 100v112q0 73 -12 86.5t-75 13.5h-53v95h107q80 0 116.5 -37t36.5 -123v-147q0 -61 22 -88t68 -27h40v-96h-40q-46 0 -68 -27t-22 -88v-147q0 -86 -36.5 -123t-116.5 -37h-107v95h53q63 0 75 13.5t12 86.5v112q0 62 27.5 100t85.5 62v2z " />
+<glyph unicode="~" d="M40 568v107q45 35 100 35q63 0 131 -50q49 -37 84 -37q49 0 105 51v-107q-45 -35 -100 -35q-63 0 -131 50q-49 37 -84 37q-49 0 -105 -51z" />
+<glyph unicode="&#xa0;" />
+<glyph unicode="&#xa5;" d="M251 415h2l84 315h148l-132 -365h97v-95h-130v-65h130v-95h-130v-110h-140v110h-130v95h130v65h-130v95h97l-132 365h152z" />
+<glyph unicode="&#xad;" d="M90 240v110h320v-110h-320z" />
+<glyph unicode="&#x2000;" horiz-adv-x="407" />
+<glyph unicode="&#x2001;" horiz-adv-x="815" />
+<glyph unicode="&#x2002;" horiz-adv-x="407" />
+<glyph unicode="&#x2003;" horiz-adv-x="815" />
+<glyph unicode="&#x2004;" horiz-adv-x="271" />
+<glyph unicode="&#x2005;" horiz-adv-x="203" />
+<glyph unicode="&#x2006;" horiz-adv-x="135" />
+<glyph unicode="&#x2007;" horiz-adv-x="135" />
+<glyph unicode="&#x2008;" horiz-adv-x="101" />
+<glyph unicode="&#x2009;" horiz-adv-x="163" />
+<glyph unicode="&#x200a;" horiz-adv-x="45" />
+<glyph unicode="&#x2010;" d="M90 240v110h320v-110h-320z" />
+<glyph unicode="&#x2011;" d="M90 240v110h320v-110h-320z" />
+<glyph unicode="&#x2013;" d="M50 240v110h400v-110h-400z" />
+<glyph unicode="&#x2014;" d="M10 240v110h480v-110h-480z" />
+<glyph unicode="&#x2018;" d="M305 460h-190l130 320h120z" />
+<glyph unicode="&#x2019;" d="M190 780h190l-130 -320h-120z" />
+<glyph unicode="&#x201c;" d="M405 460h-170l130 320h100zM195 460h-170l130 320h100z" />
+<glyph unicode="&#x201d;" d="M300 780h170l-130 -320h-100zM90 780h170l-130 -320h-100z" />
+<glyph unicode="&#x2026;" horiz-adv-x="1000" d="M72 270v190h190v-190h-190zM405 270v190h190v-190h-190zM738 270v190h190v-190h-190z" />
+<glyph unicode="&#x202f;" horiz-adv-x="163" />
+<glyph unicode="&#x205f;" horiz-adv-x="203" />
+<glyph unicode="&#x2122;" horiz-adv-x="1000" d="M838 500h-2l-38 -300h-100l-38 300h-2v-500h-133v730h167l59 -400h2l59 400h163v-730h-137v500zM320 615v-615h-140v615h-145v115h430v-115h-145z" />
+</font>
+</defs></svg> \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.ttf b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.ttf
new file mode 100644
index 0000000..0cf54cb
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.ttf
Binary files differ
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.woff b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.woff
new file mode 100644
index 0000000..f90475d
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-bold-webfont.woff
Binary files differ
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.eot b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.eot
new file mode 100644
index 0000000..a53f8b5
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.eot
Binary files differ
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.svg b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.svg
new file mode 100644
index 0000000..3c835a3
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.svg
@@ -0,0 +1,134 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG webfont generated by Font Squirrel.
+Foundry URL : http://mplus-fonts.sourceforge.jp
+</metadata>
+<defs>
+<font id="webfontVd14f4NN" horiz-adv-x="500" >
+<font-face units-per-em="1000" ascent="860" descent="-140" />
+<missing-glyph horiz-adv-x="500" />
+<glyph unicode=" " />
+<glyph unicode="!" d="M200 730h100l-10 -515h-80zM195 0v130h110v-130h-110z" />
+<glyph unicode="&#x22;" d="M275 780h100l-20 -280h-60zM125 780h100l-20 -280h-60z" />
+<glyph unicode="#" d="M40 188v72h77l29 228h-71v72h80l21 170h82l-21 -170h76l21 170h82l-21 -170h65v-72h-74l-29 -228h68v-72h-77l-23 -188h-82l23 188h-76l-23 -188h-82l23 188h-68zM199 260h76l29 228h-76z" />
+<glyph unicode="$" d="M293 311v-214q58 21 58 108q0 71 -58 106zM293 19v-104h-76v101q-70 6 -137 49v95q65 -57 137 -69v251q-77 31 -109.5 75.5t-32.5 117.5q0 76 37 122.5t105 55.5v102h76v-102q69 -8 127 -38v-90q-52 38 -127 52v-237q77 -31 109.5 -76.5t32.5 -118.5q0 -163 -142 -186z M217 429v207q-58 -18 -58 -101q0 -73 58 -106z" />
+<glyph unicode="%" d="M60 260l380 290v-80l-380 -290v80zM160 740q61 0 95.5 -41t34.5 -119t-34.5 -119t-95.5 -41t-95.5 41t-34.5 119t34.5 119t95.5 41zM340 310q61 0 95.5 -41t34.5 -119t-34.5 -119t-95.5 -41t-95.5 41t-34.5 119t34.5 119t95.5 41zM160 488q52 0 52 92t-52 92t-52 -92 t52 -92zM340 58q52 0 52 92t-52 92t-52 -92t52 -92z" />
+<glyph unicode="&#x26;" d="M228 665q-38 0 -60.5 -20t-22.5 -55q0 -29 12.5 -59t53.5 -95q59 51 79 83.5t20 70.5q0 33 -22 54t-60 21zM151 385l-9 14q-47 71 -63.5 111.5t-16.5 79.5q0 66 45 108t118 42t119 -42t46 -108q0 -57 -30.5 -106.5t-106.5 -112.5l119 -183v217h80v-253q-13 -28 -26 -46 l69 -106h-87l-33 49q-69 -59 -175 -59q-82 0 -128.5 46t-46.5 129q0 107 126 220zM331 115l-137 206q-84 -79 -84 -153q0 -51 27 -77t78 -26q70 0 116 50z" />
+<glyph unicode="'" d="M195 780h110l-25 -280h-60z" />
+<glyph unicode="(" d="M125 315q0 275 194 455h76q-196 -184 -196 -455t196 -455h-76q-194 180 -194 455z" />
+<glyph unicode=")" d="M375 315q0 -275 -194 -455h-76q196 184 196 455t-196 455h76q194 -180 194 -455z" />
+<glyph unicode="*" d="M214 750h72l-3 -169l160 55l22 -68l-161 -50l101 -135l-58 -42l-97 138l-97 -138l-58 42l101 135l-161 50l22 68l160 -55z" />
+<glyph unicode="+" d="M291 555v-214h149v-72h-149v-214h-82v214h-149v72h149v214h82z" />
+<glyph unicode="," d="M210 150h120l-110 -280h-70z" />
+<glyph unicode="-" d="M100 269v72h300v-72h-300z" />
+<glyph unicode="." d="M185 0v150h130v-150h-130z" />
+<glyph unicode="/" d="M452 730l-332 -770h-72l332 770h72z" />
+<glyph unicode="0" d="M250 740q48 0 82 -18t59 -60t37 -115.5t12 -181.5t-12 -181.5t-37 -115.5t-59 -60t-82 -18t-82 18t-59 60t-37 115.5t-12 181.5t12 181.5t37 115.5t59 60t82 18zM142 249l196 339q-26 82 -88 82q-36 0 -60 -26t-38 -95t-14 -184q0 -50 4 -116zM158 155q26 -95 92 -95 q36 0 60 26t38 95t14 184q0 78 -6 133z" />
+<glyph unicode="1" d="M258 0v645l-2 1l-173 -101v80l175 105h82v-730h-82z" />
+<glyph unicode="2" d="M175 74v-2h245v-72h-340v72q251 288 251 478q0 116 -93 116q-30 0 -76 -22.5t-82 -55.5v87q75 65 170 65q85 0 125 -47t40 -143q0 -99 -54 -208t-186 -268z" />
+<glyph unicode="3" d="M330 656v2h-250v72h345v-72l-180 -229v-2h10q91 0 133 -51t42 -166q0 -220 -195 -220q-73 0 -145 30v87q77 -43 130 -43q64 0 95 34.5t31 111.5q0 89 -25 117t-101 28h-70v72z" />
+<glyph unicode="4" d="M293 590h-2l-175 -341v-2h177v343zM293 175h-253v82l243 473h92v-483h85v-72h-85v-175h-82v175z" />
+<glyph unicode="5" d="M180 430h2q33 30 88 30q160 0 160 -230q0 -125 -49.5 -182.5t-145.5 -57.5q-74 0 -145 30v87q75 -43 140 -43q116 0 116 166q0 156 -96 156q-46 0 -80 -41h-75l10 385h305v-72h-223z" />
+<glyph unicode="6" d="M285 740q61 0 115 -20v-77q-50 25 -105 25q-70 0 -101 -48.5t-39 -184.5h2q50 50 113 50q87 0 128.5 -56t41.5 -184q0 -134 -46.5 -194.5t-138.5 -60.5q-65 0 -104 28.5t-60 101.5t-21 200q0 158 25.5 252t71 131t118.5 37zM255 62q54 0 78.5 39t24.5 144q0 94 -23.5 132 t-74.5 38q-106 0 -106 -160q0 -107 25 -150t76 -43z" />
+<glyph unicode="7" d="M345 656v2h-270v72h350v-72q-128 -296 -210 -658h-88q84 353 218 656z" />
+<glyph unicode="8" d="M255 670q-53 0 -81.5 -27.5t-28.5 -77.5q0 -54 29 -94t76 -51q52 14 80.5 51.5t28.5 93.5q0 47 -28.5 76t-75.5 29zM250 -10q-96 0 -148 51t-52 149q0 68 33 119t92 75v2q-48 23 -79 73.5t-31 105.5q0 82 49 128.5t136 46.5t136 -47t49 -128q0 -56 -30.5 -103.5 t-79.5 -70.5v-2q59 -23 92 -75t33 -124q0 -98 -52 -149t-148 -51zM255 60q53 0 84 33.5t31 96.5q0 130 -125 160q-61 -16 -90 -54.5t-29 -105.5q0 -62 35 -96t94 -34z" />
+<glyph unicode="9" d="M215 -10q-61 0 -115 20v80q52 -26 105 -26q70 0 101 47.5t39 183.5h-2q-50 -50 -113 -50q-84 0 -127 59t-43 191q0 126 46 185.5t139 59.5q68 0 107 -28t58.5 -100.5t19.5 -201.5q0 -158 -25.5 -252t-71 -131t-118.5 -37zM245 668q-55 0 -79 -38t-24 -135t25 -138.5 t73 -41.5q49 0 77.5 41.5t28.5 128.5q0 100 -25 141.5t-76 41.5z" />
+<glyph unicode=":" d="M190 390v150h120v-150h-120zM190 0v150h120v-150h-120z" />
+<glyph unicode=";" d="M200 150h120l-110 -280h-70zM200 390v150h120v-150h-120z" />
+<glyph unicode="&#x3c;" d="M435 510l-330 -204v-2l330 -204v-80l-380 245v80l380 245v-80z" />
+<glyph unicode="=" d="M60 165v72h380v-72h-380zM60 373v72h380v-72h-380z" />
+<glyph unicode="&#x3e;" d="M65 510v80l380 -245v-80l-380 -245v80l330 204v2z" />
+<glyph unicode="?" d="M445 580q0 -41 -14 -77t-28.5 -55t-42.5 -49q-29 -33 -43 -52t-28 -55t-14 -77h-80q0 55 16.5 101.5t32.5 68t47 56.5q24 27 36 42.5t23 41.5t11 55q0 41 -29.5 63.5t-86.5 22.5q-85 0 -180 -61v90q93 45 190 45q91 0 140.5 -42t49.5 -118zM180 0v130h110v-130h-110z" />
+<glyph unicode="@" d="M375 258v167q0 41 -16 63t-44 22q-40 0 -56 -29.5t-16 -115.5q0 -82 17 -113.5t55 -31.5q44 0 60 38zM165 365q0 215 140 215q38 0 73 -25h2v5q0 50 -27.5 79t-72.5 29q-83 0 -124 -70.5t-41 -232.5q0 -166 40 -234.5t125 -68.5q62 0 125 38v-80q-59 -30 -130 -30 q-122 0 -181 86t-59 289q0 197 60.5 286t179.5 89q87 0 133.5 -50t46.5 -150v-325q-65 -65 -140 -65q-76 0 -113 49t-37 166z" />
+<glyph unicode="A" d="M249 660h-2l-83 -380h168zM348 210h-200l-46 -210h-82l180 730h100l180 -730h-86z" />
+<glyph unicode="B" d="M157 430h45q80 0 116.5 29.5t36.5 90.5q0 57 -36 88.5t-102 31.5q-36 0 -60 -8v-232zM157 360v-292q37 -8 90 -8q126 0 126 160q0 140 -161 140h-55zM455 210q0 -220 -225 -220q-80 0 -155 15v720q75 15 155 15q205 0 205 -180q0 -61 -30.5 -103t-84.5 -56v-2 q58 -11 96.5 -64t38.5 -125z" />
+<glyph unicode="C" d="M55 365q0 197 60.5 286t179.5 89q66 0 125 -30v-75q-60 33 -120 33q-165 0 -165 -303q0 -164 42 -233.5t123 -69.5q62 0 125 38v-80q-59 -30 -130 -30q-122 0 -181 86t-59 289z" />
+<glyph unicode="D" d="M383 365q0 168 -43.5 235.5t-137.5 67.5q-33 0 -55 -8v-590q22 -8 55 -8q65 0 102.5 24.5t58 91.5t20.5 187zM465 365q0 -207 -63.5 -291t-199.5 -84q-70 0 -137 15v720q67 15 137 15q137 0 200 -85.5t63 -289.5z" />
+<glyph unicode="E" d="M162 658v-228h248v-70h-248v-288h258v-72h-340v730h340v-72h-258z" />
+<glyph unicode="F" d="M172 360v-360h-82v730h330v-72h-248v-228h238v-70h-238z" />
+<glyph unicode="G" d="M370 85v275h-155v70h235v-400q-80 -40 -170 -40q-118 0 -179 89t-61 286q0 196 63.5 285.5t191.5 89.5q59 0 130 -25v-77q-66 30 -130 30q-87 0 -132 -72t-45 -231q0 -303 167 -303q45 0 85 23z" />
+<glyph unicode="H" d="M140 730v-298h216v298h84v-730h-84v360h-216v-360h-80v730h80z" />
+<glyph unicode="I" d="M410 0h-320v70h118v590h-118v70h320v-70h-118v-590h118v-70z" />
+<glyph unicode="J" d="M400 730v-540q0 -110 -43.5 -155t-146.5 -45q-82 0 -150 30v87q29 -17 75.5 -31t74.5 -14q53 0 79 30.5t26 99.5v468h-165v70h250z" />
+<glyph unicode="K" d="M157 400h2l206 330h95l-225 -350l230 -380h-95l-211 360h-2v-360h-82v730h82v-330z" />
+<glyph unicode="L" d="M182 730v-658h238v-72h-320v730h82z" />
+<glyph unicode="M" d="M378 540h-2l-88 -340h-80l-88 340h-2v-540h-78v730h92l119 -450h2l119 450h88v-730h-82v540z" />
+<glyph unicode="N" d="M151 550h-2v-550h-84v730h84l204 -550h2v550h80v-730h-80z" />
+<glyph unicode="O" d="M250 740q107 0 158.5 -84.5t51.5 -290.5t-51.5 -290.5t-158.5 -84.5t-158.5 84.5t-51.5 290.5t51.5 290.5t158.5 84.5zM250 62q44 0 71 25.5t43 93.5t16 184t-16 184t-43 93.5t-71 25.5t-71 -25.5t-43 -93.5t-16 -184t16 -184t43 -93.5t71 -25.5z" />
+<glyph unicode="P" d="M375 520q0 79 -36 114.5t-112 35.5q-41 0 -70 -8v-292q30 -5 70 -5q77 0 112.5 35.5t35.5 119.5zM455 520q0 -120 -52.5 -172.5t-165.5 -52.5q-35 0 -80 5v-300h-82v725q78 15 160 15q114 0 167 -52.5t53 -167.5z" />
+<glyph unicode="Q" d="M250 740q107 0 158.5 -84.5t51.5 -290.5q0 -273 -100 -344v-2q41 -21 73 -66t47 -103h-88q-21 78 -54 109t-88 31q-107 0 -158.5 84.5t-51.5 290.5t51.5 290.5t158.5 84.5zM250 62q44 0 71 25.5t43 93.5t16 184t-16 184t-43 93.5t-71 25.5t-71 -25.5t-43 -93.5t-16 -184 t16 -184t43 -93.5t71 -25.5z" />
+<glyph unicode="R" d="M370 540q0 130 -148 130q-41 0 -70 -8v-272h60q87 0 122.5 33.5t35.5 116.5zM152 320v-320h-82v725q78 15 160 15q112 0 166 -49.5t54 -150.5q0 -143 -109 -193v-2q31 -15 66 -131l63 -214h-86l-59 216q-17 64 -41 84t-82 20h-50z" />
+<glyph unicode="S" d="M260 668q-47 0 -77.5 -30.5t-30.5 -77.5q0 -50 21.5 -82.5t71.5 -55.5q111 -49 153 -102.5t42 -139.5q0 -94 -51.5 -142t-148.5 -48q-91 0 -165 55v95q80 -78 170 -78q113 0 113 118q0 55 -26 91t-87 64q-94 42 -134.5 95.5t-40.5 129.5q0 80 51 130t134 50q53 0 87 -8 t78 -32v-90q-77 58 -160 58z" />
+<glyph unicode="T" d="M209 0v660h-154v70h390v-70h-154v-660h-82z" />
+<glyph unicode="U" d="M250 -10q-95 0 -142.5 48.5t-47.5 151.5v540h84v-520q0 -81 26.5 -114.5t81.5 -33.5t81.5 33.5t26.5 114.5v520h80v-540q0 -103 -47.5 -151.5t-142.5 -48.5z" />
+<glyph unicode="V" d="M253 70l135 660h82l-170 -730h-100l-170 730h86l135 -660h2z" />
+<glyph unicode="W" d="M153 120h2l54 510h90l54 -510h2l45 610h75l-60 -730h-109l-55 520h-2l-55 -520h-109l-60 730h83z" />
+<glyph unicode="X" d="M251 440h2l112 290h83l-148 -355l150 -375h-90l-111 305h-2l-112 -305h-85l150 375l-148 355h88z" />
+<glyph unicode="Y" d="M251 375h2l132 355h85l-179 -440v-290h-82v290l-179 440h90z" />
+<glyph unicode="Z" d="M335 658v2h-260v70h350v-70l-260 -588v-2h260v-70h-350v70z" />
+<glyph unicode="[" d="M390 710h-178v-790h178v-60h-250v910h250v-60z" />
+<glyph unicode="\" d="M48 730h72l332 -770h-72z" />
+<glyph unicode="]" d="M110 710v60h250v-910h-250v60h178v790h-178z" />
+<glyph unicode="^" d="M251 680h-2l-147 -400h-72l170 450h100l170 -450h-72z" />
+<glyph unicode="_" d="M50 -140v56h400v-56h-400z" />
+<glyph unicode="`" d="M130 810h120l100 -280h-70z" />
+<glyph unicode="a" d="M255 530q100 0 137.5 -40t37.5 -150v-340h-72l-2 75h-2q-47 -85 -149 -85q-65 0 -105 41.5t-40 113.5q0 91 61.5 140.5t183.5 49.5h48v25q0 57 -22 80t-76 23q-33 0 -84 -12t-86 -28v72q35 15 85 25t85 10zM353 275h-48q-170 0 -170 -125q0 -45 23 -69t62 -24q59 0 96 48 t37 135v35z" />
+<glyph unicode="b" d="M144 445h2q43 85 134 85q175 0 175 -270q0 -135 -48 -202.5t-127 -67.5q-84 0 -137 85h-2l-2 -75h-74v730h79v-285zM376 260q0 195 -116 195q-51 0 -83.5 -49.5t-32.5 -140.5v-10q0 -91 32.5 -140.5t83.5 -49.5q53 0 84.5 48.5t31.5 146.5z" />
+<glyph unicode="c" d="M70 260q0 134 55 202t155 68q61 0 125 -25v-80q-60 33 -120 33q-63 0 -98 -50t-35 -148q0 -101 37 -151t101 -50q59 0 120 36v-80q-64 -25 -125 -25q-102 0 -158.5 67.5t-56.5 202.5z" />
+<glyph unicode="d" d="M356 730h79v-730h-74l-2 75h-2q-53 -85 -137 -85q-79 0 -127 67.5t-48 202.5q0 270 175 270q91 0 134 -85h2v285zM124 260q0 -98 31.5 -146.5t84.5 -48.5q51 0 83.5 49.5t32.5 140.5v10q0 91 -32.5 140.5t-83.5 49.5q-116 0 -116 -195z" />
+<glyph unicode="e" d="M138 234q4 -93 38 -134t99 -41q61 0 135 36v-80q-74 -25 -140 -25q-215 0 -215 270q0 141 50 205.5t150 64.5q91 0 135.5 -62t44.5 -203q0 -11 -2 -31h-295zM138 300h218q-1 161 -101 161q-57 0 -85 -36t-32 -125z" />
+<glyph unicode="f" d="M75 431v69h120v60q0 98 33 139t107 41q45 0 90 -15v-72q-38 18 -75 18q-47 0 -61.5 -23.5t-14.5 -107.5v-40h151v-69h-151v-431h-79v431h-120z" />
+<glyph unicode="g" d="M50 260q0 270 175 270q83 0 137 -85h2l2 75h74v-515q0 -125 -50.5 -180t-154.5 -55q-71 0 -140 25v80q71 -36 140 -36q126 0 126 166v80h-2q-43 -85 -134 -85q-80 0 -127.5 66t-47.5 194zM129 260q0 -92 31.5 -138.5t84.5 -46.5q52 0 84 45.5t32 134.5v10 q0 91 -32.5 140.5t-83.5 49.5q-58 0 -87 -46.5t-29 -148.5z" />
+<glyph unicode="h" d="M440 330v-330h-77v312q0 88 -20 117.5t-73 29.5q-50 0 -85.5 -56t-35.5 -151v-252h-79v730h79v-285h2q19 39 56.5 62t82.5 23q79 0 114.5 -45.5t35.5 -154.5z" />
+<glyph unicode="i" d="M316 520v-452h109v-68h-330v68h139v384h-109v68h191zM214 640v120h102v-120h-102z" />
+<glyph unicode="j" d="M249 -33v485h-119v68h201v-553q0 -65 -8.5 -101t-36.5 -59t-72 -30t-123 -7v68q40 0 63 1t42.5 6.5t28.5 12.5t15.5 23.5t7.5 34.5t1 51zM229 640v120h102v-120h-102z" />
+<glyph unicode="k" d="M460 520l-230 -250l230 -270h-95l-206 253v-253h-79v730h79v-444l207 234h94z" />
+<glyph unicode="l" d="M281 150q0 -66 10.5 -79t63.5 -13q33 0 75 6v-69q-47 -5 -85 -5q-90 0 -118 28.5t-28 121.5v522h-129v68h211v-580z" />
+<glyph unicode="m" d="M290 0h-78v360q-1 58 -10.5 77.5t-32.5 19.5q-20 0 -35 -24t-25 -83.5t-10 -149.5v-200h-79v520h70l2 -70h2q17 38 42.5 59t53.5 21q31 0 50.5 -18.5t33.5 -61.5h2q39 80 104 80q53 0 76.5 -32.5t23.5 -117.5v-380h-77v360q-1 59 -11.5 78t-37.5 19q-64 0 -64 -197v-260z " />
+<glyph unicode="n" d="M440 330v-330h-77v312q0 88 -20 117.5t-73 29.5q-50 0 -85.5 -56t-35.5 -151v-252h-79v520h74l2 -75h2q19 38 58 61.5t84 23.5q79 0 114.5 -45.5t35.5 -154.5z" />
+<glyph unicode="o" d="M250 530q200 0 200 -270t-200 -270t-200 270t200 270zM250 59q61 0 89.5 45.5t28.5 155.5t-28.5 155.5t-89.5 45.5t-89.5 -45.5t-28.5 -155.5t28.5 -155.5t89.5 -45.5z" />
+<glyph unicode="p" d="M141 75h-2v-295h-79v740h74l2 -75h2q54 85 137 85q175 0 175 -270q0 -135 -48 -202.5t-127 -67.5q-91 0 -134 85zM371 260q0 195 -116 195q-51 0 -83.5 -49.5t-32.5 -140.5v-10q0 -91 32.5 -140.5t83.5 -49.5q53 0 84.5 48.5t31.5 146.5z" />
+<glyph unicode="q" d="M359 75q-43 -85 -134 -85q-79 0 -127 67.5t-48 202.5q0 270 175 270q83 0 137 -85h2l2 75h74v-740h-79v295h-2zM129 260q0 -98 31.5 -146.5t84.5 -48.5q51 0 83.5 49.5t32.5 140.5v10q0 91 -32.5 140.5t-83.5 49.5q-116 0 -116 -195z" />
+<glyph unicode="r" d="M186 520v-100h2q62 110 172 110q37 0 70 -10v-70q-35 11 -70 11q-73 0 -122 -61t-49 -160v-240h-79v520h76z" />
+<glyph unicode="s" d="M255 463q-96 0 -96 -73q0 -34 21 -54.5t75 -35.5q106 -30 140.5 -63t34.5 -102t-47 -107t-133 -38t-165 40v80q78 -53 155 -53q111 0 111 78q0 37 -21.5 57t-84.5 38q-92 26 -128.5 62t-36.5 98q0 66 43.5 103t126.5 37q84 0 160 -35v-75q-79 43 -155 43z" />
+<glyph unicode="t" d="M244 500h181v-69h-181v-281q0 -56 16.5 -74.5t64.5 -18.5q50 0 90 18v-70q-48 -15 -100 -15q-84 0 -117 32.5t-33 117.5v291h-100v69h100v190h79v-190z" />
+<glyph unicode="u" d="M65 180v340h77v-322q0 -83 18.5 -110t69.5 -27q49 0 82.5 55t33.5 152v252h79v-520h-74l-2 75h-2q-19 -40 -56 -62.5t-81 -22.5q-77 0 -111 43t-34 147z" />
+<glyph unicode="v" d="M251 60h2l115 460h82l-145 -520h-110l-145 520h86z" />
+<glyph unicode="w" d="M351 80h2l49 440h78l-80 -520h-99l-54 440h-2l-49 -440h-96l-80 520h82l49 -440h2l49 440h100z" />
+<glyph unicode="x" d="M251 305h2l104 215h88l-145 -260l145 -260h-94l-102 215h-2l-102 -215h-90l145 260l-145 260h92z" />
+<glyph unicode="y" d="M259 120h2l117 400h87l-240 -740h-83l78 230l-175 510h88z" />
+<glyph unicode="z" d="M80 520h340v-69l-248 -380v-2h248v-69h-340v69l248 380v2h-248v69z" />
+<glyph unicode="{" d="M195 316l4 -2q81 -38 81 -149v-135q0 -72 16.5 -91t78.5 -19h40v-60h-65q-73 0 -107.5 35.5t-34.5 114.5v150q0 66 -21.5 95.5t-66.5 29.5h-45v60h45q45 0 66.5 29.5t21.5 95.5v150q0 79 34.5 114.5t107.5 35.5h65v-60h-40q-62 0 -78.5 -19t-16.5 -91v-135q0 -61 -20 -95 t-65 -54z" />
+<glyph unicode="|" d="M212 -220v1030h76v-1030h-76z" />
+<glyph unicode="}" d="M305 316q-45 20 -65 54t-20 95v135q0 72 -16.5 91t-78.5 19h-40v60h65q73 0 107.5 -35.5t34.5 -114.5v-150q0 -66 21.5 -95.5t66.5 -29.5h45v-60h-45q-45 0 -66.5 -29.5t-21.5 -95.5v-150q0 -79 -34.5 -114.5t-107.5 -35.5h-65v60h40q62 0 78.5 19t16.5 91v135 q0 111 81 149z" />
+<glyph unicode="~" d="M50 602v75q42 33 95 33q61 0 125 -48q48 -35 80 -35q25 0 47 10t53 39v-75q-42 -33 -95 -33q-61 0 -125 48q-47 35 -80 35q-25 0 -47 -10t-53 -39z" />
+<glyph unicode="&#xa0;" />
+<glyph unicode="&#xa5;" d="M251 375h2l132 355h85l-153 -375h123v-65h-149v-85h149v-65h-149v-140h-82v140h-149v65h149v85h-149v65h123l-153 375h90z" />
+<glyph unicode="&#xad;" d="M100 269v72h300v-72h-300z" />
+<glyph unicode="&#x2000;" horiz-adv-x="407" />
+<glyph unicode="&#x2001;" horiz-adv-x="815" />
+<glyph unicode="&#x2002;" horiz-adv-x="407" />
+<glyph unicode="&#x2003;" horiz-adv-x="815" />
+<glyph unicode="&#x2004;" horiz-adv-x="271" />
+<glyph unicode="&#x2005;" horiz-adv-x="203" />
+<glyph unicode="&#x2006;" horiz-adv-x="135" />
+<glyph unicode="&#x2007;" horiz-adv-x="135" />
+<glyph unicode="&#x2008;" horiz-adv-x="101" />
+<glyph unicode="&#x2009;" horiz-adv-x="163" />
+<glyph unicode="&#x200a;" horiz-adv-x="45" />
+<glyph unicode="&#x2010;" d="M100 269v72h300v-72h-300z" />
+<glyph unicode="&#x2011;" d="M100 269v72h300v-72h-300z" />
+<glyph unicode="&#x2013;" d="M60 269v72h380v-72h-380z" />
+<glyph unicode="&#x2014;" d="M20 269v72h460v-72h-460z" />
+<glyph unicode="&#x2018;" d="M275 500h-120l110 280h70z" />
+<glyph unicode="&#x2019;" d="M220 780h120l-110 -280h-70z" />
+<glyph unicode="&#x201c;" d="M340 500h-110l110 280h60zM190 500h-110l110 280h60z" />
+<glyph unicode="&#x201d;" d="M300 780h110l-110 -280h-60zM150 780h110l-110 -280h-60z" />
+<glyph unicode="&#x2026;" horiz-adv-x="1000" d="M102 288v150h130v-150h-130zM435 288v150h130v-150h-130zM768 288v150h130v-150h-130z" />
+<glyph unicode="&#x202f;" horiz-adv-x="163" />
+<glyph unicode="&#x205f;" horiz-adv-x="203" />
+<glyph unicode="&#x2122;" horiz-adv-x="1000" d="M878 540h-2l-88 -340h-80l-88 340h-2v-540h-78v730h92l119 -450h2l119 450h88v-730h-82v540zM209 0v660h-154v70h390v-70h-154v-660h-82z" />
+</font>
+</defs></svg> \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.ttf b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.ttf
new file mode 100644
index 0000000..684abfd
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.ttf
Binary files differ
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.woff b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.woff
new file mode 100644
index 0000000..49585d8
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/fonts/mplus-1m-regular-webfont.woff
Binary files differ
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/handheld.css b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/handheld.css
new file mode 100644
index 0000000..073c0d1
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/handheld.css
@@ -0,0 +1,217 @@
+/*
+ * TABLE OF CONTENTS:
+ * - Browser reset
+ * - HTML elements
+ * - JsDoc styling
+ * - Media query check
+ */
+
+
+
+
+
+
+/*
+ * HTML ELEMENTS
+ */
+
+body {
+ padding: 1% 4% 1% 4%;
+}
+
+/*
+ * HTML ELEMENTS
+ */
+
+
+
+
+
+/*
+ * BEGIN JSDOC
+ */
+
+/* Start menu */
+div.index div.menu {
+ position: fixed;
+ top: 0;
+ right: 0;
+ -moz-border-radius-bottomleft: 15px;
+ -webkit-border-bottom-left-radius: 15px;
+ -border-bottom-left-radius: 15px;
+ padding: 4px 5px 8px 10px;
+ -moz-box-shadow: 0px 0px 10px #c4c4c4;
+ -webkit-box-shadow: 0px 0px 10px #c4c4c4;
+ box-shadow: 0px 0px 10px #c4c4c4;
+ background-color: rgba(255, 255, 255, 0.9);
+}
+
+div.index input.classFilter {
+ display: none;
+}
+
+div.index div.indexLinks a {
+ float: right;
+ clear: both;
+ font-size: 1.1em;
+}
+
+div.index *.heading1 {
+ display:none;
+}
+
+div.index ul.classList {
+ display:none;
+}
+
+div.index div.fineprint {
+ display:none;
+}
+
+div.indexStatic {
+ display: none;
+}
+/* End menu */
+
+
+
+/* Start content */
+div.content *.classTitle {
+ margin-right: 60px;
+ margin-bottom: 15px;
+}
+
+div.content div.intro {
+ margin: 15px 0 35px;
+}
+
+div.content p.description.summary {
+ margin-bottom: 0.2em;
+}
+
+div.content div.props {
+ margin: 1.5em -2% 0 -2%;
+ padding: 2%;
+}
+
+table.summaryTable {
+ position: relative;
+ left: -10px;
+ width: 100%;
+ border-collapse: collapse;
+ box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box;
+ -ms-box-sizing: content-box;
+ -o-box-sizing: content-box;
+ -icab-box-sizing: content-box;
+ -khtml-box-sizing: content-box;
+}
+
+*.sectionTitle {
+ padding: 0 10px 10px 0;
+}
+caption.sectionTitle {
+ padding-left: 10px;
+}
+
+table.summaryTable td,
+table.summaryTable th {
+ padding: 0px 10px 10px 10px;
+}
+table.summaryTable tr:last-child td {
+ padding-bottom: 0;
+}
+
+table.summaryTable td.attributes {
+ width: 35%;
+}
+
+table.summaryTable td.nameDescription {
+ width: 65%
+}
+
+
+
+dl.detailList {
+ margin-top: 0.5em;
+}
+
+dl.detailList.nomargin + dl.detailList.nomargin {
+ margin-top: 0;
+}
+
+dl.detailList dt {
+ display: inline;
+ margin-right: 5px;
+}
+
+dl.detailList dt:before {
+ display: block;
+ content: "";
+}
+
+dl.detailList dd {
+ display: inline;
+}
+
+dl.detailList.params dt {
+ display: block;
+}
+dl.detailList.params dd {
+ display: block;
+ padding-left: 2em;
+ padding-bottom: 0.4em;
+}
+
+
+
+
+ul.fileList li {
+ margin-bottom: 1.5em;
+}
+
+
+
+.fixedFont.heading {
+ margin-bottom: 0.5em;
+}
+
+pre.code {
+ margin: 10px 0 10px 0;
+ padding: 10px;
+ border: 1px solid #ccc;
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+}
+/* End content */
+
+/*
+ * END JSDOC
+ */
+
+
+
+
+
+
+
+/*
+ * START MEDIA QUERY CHECK
+ */
+
+.cssLoadCheck {
+ position: absolute;
+ top: -99999px;
+ left: -99999px;
+ border: 0;
+ width: 100px;
+ padding: 0;
+ overflow: hidden;
+}
+
+/*
+ * END MEDIA QUERY CHECK
+ */
+
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/screen.css b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/screen.css
new file mode 100644
index 0000000..8cb4bba
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/css/screen.css
@@ -0,0 +1,297 @@
+/*
+ * TABLE OF CONTENTS:
+ * - JsDoc styling
+ * - Media query check
+ */
+
+
+
+
+
+
+/*
+ * BEGIN JSDOC
+ */
+
+/* Start menu */
+div.index {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ float: left;
+ width: 30%;
+ min-width: 100px;
+ max-width: 300px;
+ padding: 0 0 10px 0;
+ overflow: auto;
+}
+
+div.index *.heading1 {
+ padding: 8px 0 0 0;
+}
+
+div.index div.menu {
+ margin: 0 15px 0 -15px;
+ -moz-border-radius-bottomright: 15px;
+ -webkit-border-bottom-right-radius: 15px;
+ -border-bottom-right-radius: 15px;
+ padding: 15px 15px 15px 30px;
+ -moz-box-shadow: 0px 0px 10px #c4c4c4;
+ -webkit-box-shadow: 0px 0px 10px #c4c4c4;
+ box-shadow: 0px 0px 10px #c4c4c4;
+ background-color: rgba(255, 255, 255, 0.5);
+}
+
+div.index div.indexLinks {
+ margin-top: 13px;
+ position: absolute;
+ right: 30px;
+}
+
+div.index div.indexLinks a {
+ color: #999999;
+ text-transform: lowercase;
+}
+
+div.index div.indexLinks a:first-child {
+ margin-right: 3px;
+ border-right: 1px solid #999999;
+ padding-right: 5px;
+}
+
+div.index input.classFilter {
+ margin-bottom: 4px;
+ width: 100%;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #CCCCCC #999999 #999999 #CCCCCC;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ -border-radius: 3px;
+}
+
+div.index ul.classList a {
+ line-height: 1.3em;
+}
+
+div.index ul.classList a + a {
+ margin-left: 0.5em;
+}
+
+div.index div.fineprint {
+ margin: 1em 0 0 15px;
+ color: #777;
+ font-size: 0.9em;
+}
+
+div.index div.fineprint a {
+ color: #777;
+}
+
+div.indexStatic {
+ position: static;
+ min-height: 1em;
+}
+/* End menu */
+
+
+/* Start content */
+div.content {
+ float: left;
+ width: 70%;
+ min-width: 300px;
+ max-width: 600px;
+}
+div.innerContent {
+ padding: 0 0 0 2.5em;
+}
+
+div.content ul,
+div.content ol {
+ margin-bottom: 3em;
+}
+
+div.content ul.methodDetail {
+ margin-bottom: 0;
+}
+
+div.content *.classTitle {
+ position: relative;
+ left: -10px;
+ margin: -30px 0 15px 0;
+ -moz-border-radius: 15px;
+ -webkit-border-radius: 15px;
+ border-radius: 15px;
+ padding: 25px 15px 15px 15px;
+ background-color: #FFFFFF;
+ background-color: rgba(255, 255, 255, 0.5);
+ -moz-box-shadow: 0px 0px 10px #c4c4c4;
+ -webkit-box-shadow: 0px 0px 10px #c4c4c4;
+ box-shadow: 0px 0px 10px #c4c4c4;
+}
+
+div.content div.intro {
+ margin: 15px 0 45px
+}
+
+div.content p.summary {
+ margin-bottom: 0.5em;
+}
+
+div.content ul.summary {
+ margin-bottom: 1.5em;
+}
+
+div.content ul *.classname a,
+div.content ul *.filename a {
+ font-family: Consolas, "Courier New", Courier, monospace;
+ text-decoration: none;
+ font-weight: bold;
+}
+div.content ul *.classname a:hover,
+div.content ul *.filename a:hover {
+ text-decoration: underline;
+}
+
+div.content div.props {
+ position: relative;
+ left: -10px;
+ margin-bottom: 2.5em;
+ padding: 10px 15px 15px 15px;
+ overflow: hidden;
+}
+
+div.content div.hr {
+ margin: 0 10px 0 0;
+ height: 4em;
+}
+
+
+
+table.summaryTable {
+ position: relative;
+ left: -10px;
+ width: 100%;
+ border-collapse: collapse;
+ box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box;
+ -ms-box-sizing: content-box;
+ -o-box-sizing: content-box;
+ -icab-box-sizing: content-box;
+ -khtml-box-sizing: content-box;
+}
+
+*.sectionTitle {
+ padding: 0 10px 10px 0;
+}
+caption.sectionTitle {
+ padding-left: 10px;
+}
+
+table.summaryTable td,
+table.summaryTable th {
+ padding: 0px 10px 10px 10px;
+}
+table.summaryTable tr:last-child td {
+ padding-bottom: 0;
+}
+
+table.summaryTable td.attributes {
+ width: 35%;
+}
+
+table.summaryTable td.nameDescription {
+ width: 65%
+}
+
+
+
+dl.detailList {
+ margin-top: 0.5em;
+}
+
+dl.detailList.nomargin + dl.detailList.nomargin {
+ margin-top: 0;
+}
+
+dl.detailList dt {
+ display: inline;
+ margin-right: 5px;
+}
+
+dl.detailList dt:before {
+ display: block;
+ content: "";
+}
+
+dl.detailList dd {
+ display: inline;
+}
+
+dl.detailList.params dt {
+ display: block;
+}
+dl.detailList.params dd {
+ display: block;
+ padding-left: 2em;
+ padding-bottom: 0.4em;
+}
+
+
+
+
+ul.fileList li {
+ margin-bottom: 1.5em;
+}
+
+
+
+.fixedFont.heading {
+ margin-bottom: 0.5em;
+}
+
+pre.code {
+ margin: 10px 0 10px 0;
+ padding: 10px;
+ border: 1px solid #ccc;
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+}
+/* End content */
+
+.clear {
+ clear: both;
+ width: 100%;
+ min-height: 0;
+}
+
+/*
+ * END JSDOC
+ */
+
+
+
+
+
+
+
+/*
+ * START MEDIA QUERY CHECK
+ */
+
+.cssLoadCheck {
+ position: absolute;
+ top: -99999px;
+ left: -99999px;
+ border: 0;
+ width: 100px;
+ padding: 0;
+ overflow: hidden;
+}
+
+/*
+ * END MEDIA QUERY CHECK
+ */
+
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/files.html b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/files.html
new file mode 100644
index 0000000..a4f372a
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/files.html
@@ -0,0 +1,133 @@
+
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="generator" content="JsDoc Toolkit" />
+ <title>File Index | JsDoc Reference</title>
+
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
+ <meta name="mobileoptimized" content="0" />
+
+ <link rel="stylesheet" href="css/all.css" media="all" />
+ <link rel="stylesheet" href="css/handheld.css" media="only screen and (max-width: 660px)" />
+ <link rel="stylesheet" href="css/handheld.css" media="handheld" />
+ <link rel="stylesheet" href="css/screen.css" media="screen and (min-width: 661px)" />
+
+ <script src="javascript/all.js"></script>
+ <!--[if lt IE 9]>
+ <script src="javascript/html5.js"></script>
+ <![endif]-->
+ </head>
+
+ <body>
+
+<div class="index">
+ <div class="menu">
+ <div class="indexLinks">
+ <a href="index.html">Classes</a>
+ <a href="files.html">Files</a>
+ </div>
+
+ <h2 class="heading1">Classes</h2>
+
+ <input type="text" name="classFilter" class="classFilter" id="ClassFilter" placeholder="Filter"></input>
+
+ <nav>
+ <ul class="classList" id="ClassList">
+
+ <li><a href="symbols/_global_.html">_global_</a></li>
+
+ <li><a href="symbols/mockup.html">mockup</a></li>
+
+ <li><a href="symbols/RAIServer.html">RAIServer</a></li>
+
+ <li><a href="symbols/RAISocket.html">RAISocket</a></li>
+
+ <li><a href="symbols/starttls.html">starttls</a></li>
+
+ </ul>
+ </nav>
+ </div>
+ <div class="fineprint" style="clear:both">
+ <footer>
+
+ Documentation generator: <a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank">JsDoc Toolkit</a> 2.4.0<br />
+ Template: <a href="http://www.thebrightlines.com/2010/05/06/new-template-for-jsdoctoolkit-codeview/" target="_blank">Codeview</a> 1.2<br />
+ Generated on:
+ <time datetime='2012-0-22' pubdate>2012-0-22 12:15</time>
+ </footer>
+ </div>
+</div>
+
+<div class="index indexStatic"></div>
+
+<div class="content">
+ <div class="innerContent">
+ <article>
+ <h1 class="classTitle"><span>File Index</span></h1>
+
+ <ul class="fileList" id="FileList">
+
+ <li>
+ <h2 class="filename"><a href="symbols/src/RAI_lib_rai.js.html">rai.js</a></h2>
+
+
+This is the main file for the RAI library to create text based servers
+
+ <dl class="detailList">
+
+ <dt class="heading">Author:</dt>
+ <dd><a href="mailto:andris@node.ee">Andris Reinman</a></dd>
+
+
+
+ <dt class="heading">Version:</dt>
+ <dd>0.1.3</dd>
+
+
+
+
+ </dl>
+ </li>
+
+ <li>
+ <h2 class="filename"><a href="symbols/src/RAI_lib_mockup.js.html">RAI/lib/mockup.js</a></h2>
+
+
+
+ <dl class="detailList">
+
+
+
+
+
+
+ </dl>
+ </li>
+
+ <li>
+ <h2 class="filename"><a href="symbols/src/RAI_lib_starttls.js.html">RAI/lib/starttls.js</a></h2>
+
+
+
+ <dl class="detailList">
+
+
+
+
+
+
+ </dl>
+ </li>
+
+ </ul>
+ </article>
+ </div>
+</div>
+ <script type="text/javascript">
+ wbos.CssTools.MediaQueryFallBack.LoadCss('css/screen.css', 'css/handheld.css', 660)
+ codeview.classFilter.Init()
+ </script>
+ </body>
+</html>
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/index.html b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/index.html
new file mode 100644
index 0000000..544613f
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/index.html
@@ -0,0 +1,107 @@
+
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="generator" content="JsDoc Toolkit" />
+ <title>Class Index | JsDoc Reference</title>
+
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
+ <meta name="mobileoptimized" content="0" />
+
+ <link rel="stylesheet" href="css/all.css" media="all" />
+ <link rel="stylesheet" href="css/handheld.css" media="only screen and (max-width: 660px)" />
+ <link rel="stylesheet" href="css/handheld.css" media="handheld" />
+ <link rel="stylesheet" href="css/screen.css" media="screen and (min-width: 661px)" />
+
+ <script src="javascript/all.js"></script>
+ <!--[if lt IE 9]>
+ <script src="javascript/html5.js"></script>
+ <![endif]-->
+ </head>
+
+ <body>
+
+<div class="index">
+ <div class="menu">
+ <div class="indexLinks">
+ <a href="index.html">Classes</a>
+ <a href="files.html">Files</a>
+ </div>
+
+ <h2 class="heading1">Classes</h2>
+
+ <input type="text" name="classFilter" class="classFilter" id="ClassFilter" placeholder="Filter"></input>
+
+ <nav>
+ <ul class="classList" id="ClassList">
+
+ <li><a href="symbols/_global_.html">_global_</a></li>
+
+ <li><a href="symbols/mockup.html">mockup</a></li>
+
+ <li><a href="symbols/RAIServer.html">RAIServer</a></li>
+
+ <li><a href="symbols/RAISocket.html">RAISocket</a></li>
+
+ <li><a href="symbols/starttls.html">starttls</a></li>
+
+ </ul>
+ </nav>
+ </div>
+ <div class="fineprint" style="clear:both">
+ <footer>
+
+ Documentation generator: <a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank">JsDoc Toolkit</a> 2.4.0<br />
+ Template: <a href="http://www.thebrightlines.com/2010/05/06/new-template-for-jsdoctoolkit-codeview/" target="_blank">Codeview</a> 1.2<br />
+ Generated on:
+ <time datetime='2012-0-22' pubdate>2012-0-22 12:15</time>
+ </footer>
+ </div>
+</div>
+
+<div class="index indexStatic"></div>
+
+<div class="content">
+ <div class="innerContent">
+ <article>
+ <h1 class="classTitle"><span>Class Index</span></h1>
+
+ <ul id="ClassList2">
+
+ <li>
+ <h2 class="classname"><a href="symbols/_global_.html">_global_</a></h2>
+ <p></p>
+ </li>
+
+ <li>
+ <h2 class="classname"><a href="symbols/mockup.html">mockup</a></h2>
+ <p>Mockup module</p>
+ </li>
+
+ <li>
+ <h2 class="classname"><a href="symbols/RAIServer.html">RAIServer</a></h2>
+ <p></p>
+ </li>
+
+ <li>
+ <h2 class="classname"><a href="symbols/RAISocket.html">RAISocket</a></h2>
+ <p></p>
+ </li>
+
+ <li>
+ <h2 class="classname"><a href="symbols/starttls.html">starttls</a></h2>
+ <p>STARTTLS module</p>
+ </li>
+
+ </ul>
+ </article>
+ </div>
+</div>
+ <script type="text/javascript">
+ wbos.CssTools.MediaQueryFallBack.LoadCss('css/screen.css', 'css/handheld.css', 660)
+ codeview.classFilter.Init()
+ </script>
+ </body>
+</html>
+
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/javascript/all.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/javascript/all.js
new file mode 100644
index 0000000..5b6876a
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/javascript/all.js
@@ -0,0 +1,326 @@
+/**
+ * @fileOverview Contains standard code in the namespace 'wbos' and code specifically written for Codeview in the namespace 'codeview'
+ * @author Wouter Bos (www.thebrightlines.com)
+ * @since 1.0 - 2010-09-10
+ * @version 1.0 - 2010-09-10
+ */
+
+
+
+
+
+
+if (typeof(wbos) == "undefined") {
+ /**
+ * @namespace Standard code of Wouter Bos (wbos)
+ */
+ wbos = {}
+}
+if (typeof(wbos.CssTools) == "undefined") {
+ /**
+ * @namespace Namespace for CSS-related functionality
+ */
+ wbos.CssTools = {}
+}
+
+
+
+
+/**
+ * @namespace Fallback for CSS advanced media query
+ * @class
+ * @since 1.0 - 2010-09-10
+ * @version 1.0 - 2010-09-10
+ */
+wbos.CssTools.MediaQueryFallBack = ( function() {
+ var config = {
+ cssScreen: "/css/screen.css",
+ cssHandheld: "/css/handheld.css",
+ mobileMaxWidth: 660,
+ testDivClass: "cssLoadCheck",
+ dynamicCssLinkId: "DynCssLink",
+ resizeDelay: 30
+ }
+ var noMediaQuery = false;
+ var delay;
+ var currentCssMediaType;
+
+ // Adding events to elements in the DOM without overwriting it
+ function addEvent(element, newFunction, eventType) {
+ var oldEvent = eval("element." + eventType);
+ var eventContentType = eval("typeof element." + eventType)
+
+ if ( eventContentType != 'function' ) {
+ eval("element." + eventType + " = newFunction")
+ } else {
+ eval("element." + eventType + " = function(e) { oldEvent(e); newFunction(e); }")
+ }
+ }
+
+ // Get the the inner width of the browser window
+ function getWindowWidth() {
+ if (window.innerWidth) {
+ return window.innerWidth;
+ } else if (document.documentElement.clientWidth) {
+ return document.documentElement.clientWidth;
+ } else if (document.body.clientWidth) {
+ return document.body.clientWidth;
+ } else{
+ return 0;
+ }
+ }
+
+ function addCssLink(cssHref) {
+ var cssNode = document.createElement('link');
+ var windowWidth;
+ cssNode.type = 'text/css';
+ cssNode.rel = 'stylesheet';
+ cssNode.media = 'screen, handheld, fallback';
+ cssNode.href = cssHref;
+ document.getElementsByTagName("head")[0].appendChild(cssNode);
+ }
+
+
+
+ /* Start public */
+ return {
+ /**
+ * Adds link to CSS in the head if no CSS is loaded
+ *
+ * @since 1.0 - 2010-08-21
+ * @version 1.0 - 2010-08-21
+ * @param {String|Object} cssScreen URL to CSS file for larger screens
+ * @param {String|Object} cssHandheld URL to CSS file for smaller screens
+ * @param {Number} mobileMaxWidth Maximum width for handheld devices
+ * @example
+ * wbos.CssTools.MediaQueryFallBack.LoadCss(['screen.css', 'screen2.css'], 'mobile.css', 480)
+ */
+ LoadCss: function(cssScreen, cssHandheld, mobileMaxWidth) {
+ // Set config values
+ if (typeof(cssScreen) != "undefined") {
+ config.cssScreen = cssScreen;
+ }
+ if (typeof(cssHandheld) != "undefined") {
+ config.cssHandheld = cssHandheld;
+ }
+ if (typeof(mobileMaxWidth) != "undefined") {
+ config.mobileMaxWidth = mobileMaxWidth;
+ }
+
+ // Check if CSS is loaded
+ var cssloadCheckNode = document.createElement('div');
+ cssloadCheckNode.className = config.testDivClass;
+ document.getElementsByTagName("body")[0].appendChild(cssloadCheckNode);
+ if (cssloadCheckNode.offsetWidth != 100 && noMediaQuery == false) {
+ noMediaQuery = true;
+ }
+ cssloadCheckNode.parentNode.removeChild(cssloadCheckNode)
+
+ if (noMediaQuery == true) {
+ // Browser does not support Media Queries, so JavaScript will supply a fallback
+ var cssHref = "";
+
+ // Determines what CSS file to load
+ if (getWindowWidth() <= config.mobileMaxWidth) {
+ cssHref = config.cssHandheld;
+ newCssMediaType = "handheld";
+ } else {
+ cssHref = config.cssScreen;
+ newCssMediaType = "screen";
+ }
+
+ // Add CSS link to <head> of page
+ if (cssHref != "" && currentCssMediaType != newCssMediaType) {
+ var currentCssLinks = document.styleSheets
+ for (var i = 0; i < currentCssLinks.length; i++) {
+ for (var ii = 0; ii < currentCssLinks[i].media.length; ii++) {
+ if (typeof(currentCssLinks[i].media) == "object") {
+ if (currentCssLinks[i].media.item(ii) == "fallback") {
+ currentCssLinks[i].ownerNode.parentNode.removeChild(currentCssLinks[i].ownerNode)
+ i--
+ break;
+ }
+ } else {
+ if (currentCssLinks[i].media.indexOf("fallback") >= 0) {
+ currentCssLinks[i].owningElement.parentNode.removeChild(currentCssLinks[i].owningElement)
+ i--
+ break;
+ }
+ }
+ }
+ }
+ if (typeof(cssHref) == "object") {
+ for (var i = 0; i < cssHref.length; i++) {
+ addCssLink(cssHref[i])
+ }
+ } else {
+ addCssLink(cssHref)
+ }
+
+ currentCssMediaType = newCssMediaType;
+ }
+
+
+ // Check screen size again if user resizes window
+ addEvent(window, wbos.CssTools.MediaQueryFallBack.LoadCssDelayed, 'onresize')
+ }
+ },
+
+ /**
+ * Runs LoadCSS after a short delay
+ *
+ * @since 1.0 - 2010-08-21
+ * @version 1.0 - 2010-08-21
+ * @example
+ * wbos.CssTools.MediaQueryFallBack.LoadCssDelayed()
+ */
+ LoadCssDelayed: function() {
+ clearTimeout(delay);
+ delay = setTimeout( "wbos.CssTools.MediaQueryFallBack.LoadCss()", config.resizeDelay)
+ }
+
+ }
+ /* End public */
+})();
+
+
+
+
+
+
+/**
+ * @namespace Adds a function to an event of a single element. Use this if
+ * you don't want to use jQuery
+ * @class
+ * @since 1.0 - 2010-02-23
+ * @version 1.0 - 2010-02-23
+ */
+wbos.Events = ( function() {
+ /* Start public */
+ return {
+ /**
+ * Adds a function to an event of a single element
+ *
+ * @since 1.0 - 2010-02-23
+ * @version 1.0 - 2010-02-23
+ * @param {Object} element The element on which the event is placed
+ * @param {Function} newFunction The function that has to be linked to the event
+ * @param {String} eventType Name of the event
+ * @example
+ * wbos.Events.AddEvent( document.getElementById('elementId'), functionName, "onclick" )
+ */
+ AddEvent: function( element, newFunction, eventType ) {
+ var oldEvent = eval("element." + eventType);
+ var eventContentType = eval("typeof element." + eventType)
+
+ if ( eventContentType != 'function' ) {
+ eval("element." + eventType + " = newFunction")
+ } else {
+ eval("element." + eventType + " = function(e) { oldEvent(e); newFunction(e); }")
+ }
+ }
+ }
+ /* End public */
+})();
+
+
+
+
+
+
+if (typeof(codeview) == "undefined") {
+ /**
+ * @namespace Code written for the Codeview template
+ */
+ codeview = {}
+}
+
+
+
+
+
+
+
+/**
+ * @namespace Enables filtering in class lists
+ * @class
+ * @since 1.0 - 2010-11-08
+ * @version 1.0 - 2010-11-08
+ */
+codeview.classFilter = ( function() {
+ function onkeyup_ClassFilter() {
+ var listItems
+ var search = document.getElementById('ClassFilter').value
+ search = search.toLowerCase()
+ if (document.getElementById('ClassList')) {
+ listItems = document.getElementById('ClassList').getElementsByTagName('li')
+ filterList(listItems, search)
+ }
+ if (document.getElementById('ClassList2')) {
+ listItems = document.getElementById('ClassList2').getElementsByTagName('li')
+ filterList(listItems, search)
+ }
+ if (document.getElementById('FileList')) {
+ listItems = document.getElementById('FileList').getElementsByTagName('li')
+ filterList(listItems, search)
+ }
+ if (document.getElementById('MethodsListInherited')) {
+ var links = document.getElementById('MethodsListInherited').getElementsByTagName('a')
+ var linksSelected = new Array()
+ for (var i=0; i < links.length; i++) {
+ if (links[i].parentNode.parentNode.tagName == "DD") {
+ linksSelected.push(links[i])
+ }
+ }
+ filterList(linksSelected, search)
+ }
+ if (document.getElementById('MethodsList')) {
+ listItems = document.getElementById('MethodsList').getElementsByTagName('tbody')[0].getElementsByTagName('tr')
+ filterList(listItems, search, document.getElementById('MethodDetail').getElementsByTagName('li'))
+ }
+ }
+
+ function filterList(listItems, search, relatedElements) {
+ var itemContent = ""
+ for (var i=0; i < listItems.length; i++) {
+ itemContent = listItems[i].textContent||listItems[i].innerText
+ if (itemContent != undefined) {
+ itemContent = itemContent.toLowerCase()
+ itemContent = itemContent.replace(/\s/g, "")
+ if (itemContent.indexOf(search) >= 0 || itemContent == "") {
+ listItems[i].style.display = ""
+ } else {
+ listItems[i].style.display = "none"
+ }
+ if (relatedElements != null) {
+ filterRelatedList(listItems[i], search, relatedElements)
+ }
+ }
+ }
+ }
+
+ function filterRelatedList(listItem, search, relatedElements) {
+ var itemIndex = parseInt(listItem.className.replace('item', ''))
+ if (itemIndex <= relatedElements.length) {
+ if (relatedElements[itemIndex].className == "item"+ itemIndex) {
+ relatedElements[itemIndex].style.display = listItem.style.display
+ }
+ }
+ }
+
+
+
+
+
+ /* Start public */
+ return {
+ Init: function() {
+ wbos.Events.AddEvent(
+ document.getElementById('ClassFilter'),
+ onkeyup_ClassFilter,
+ "onkeyup"
+ )
+ }
+ }
+ /* End public */
+})();
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/javascript/html5.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/javascript/html5.js
new file mode 100644
index 0000000..3587bf7
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/javascript/html5.js
@@ -0,0 +1,6 @@
+// html5shiv MIT @rem remysharp.com/html5-enabling-script
+// iepp v1.6.2 MIT @jon_neal iecss.com/print-protector
+/*@cc_on(function(m,c){var z="abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video";function n(d){for(var a=-1;++a<o;)d.createElement(i[a])}function p(d,a){for(var e=-1,b=d.length,j,q=[];++e<b;){j=d[e];if((a=j.media||a)!="screen")q.push(p(j.imports,a),j.cssText)}return q.join("")}var g=c.createElement("div");g.innerHTML="<z>i</z>";if(g.childNodes.length!==1){var i=z.split("|"),o=i.length,s=RegExp("(^|\\s)("+z+")",
+"gi"),t=RegExp("<(/*)("+z+")","gi"),u=RegExp("(^|[^\\n]*?\\s)("+z+")([^\\n]*)({[\\n\\w\\W]*?})","gi"),r=c.createDocumentFragment(),k=c.documentElement;g=k.firstChild;var h=c.createElement("body"),l=c.createElement("style"),f;n(c);n(r);g.insertBefore(l,
+g.firstChild);l.media="print";m.attachEvent("onbeforeprint",function(){var d=-1,a=p(c.styleSheets,"all"),e=[],b;for(f=f||c.body;(b=u.exec(a))!=null;)e.push((b[1]+b[2]+b[3]).replace(s,"$1.iepp_$2")+b[4]);for(l.styleSheet.cssText=e.join("\n");++d<o;){a=c.getElementsByTagName(i[d]);e=a.length;for(b=-1;++b<e;)if(a[b].className.indexOf("iepp_")<0)a[b].className+=" iepp_"+i[d]}r.appendChild(f);k.appendChild(h);h.className=f.className;h.innerHTML=f.innerHTML.replace(t,"<$1font")});m.attachEvent("onafterprint",
+function(){h.innerHTML="";k.removeChild(h);k.appendChild(f);l.styleSheet.cssText=""})}})(this,document);@*/ \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/RAIServer.html b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/RAIServer.html
new file mode 100644
index 0000000..3e91613
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/RAIServer.html
@@ -0,0 +1,565 @@
+
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="generator" content="JsDoc Toolkit" />
+ <title>RAIServer | JsDoc Reference</title>
+
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
+ <meta name="mobileoptimized" content="0" />
+
+ <link rel="stylesheet" href="../css/all.css" media="all" />
+ <link rel="stylesheet" href="../css/handheld.css" media="only screen and (max-width: 660px)" />
+ <link rel="stylesheet" href="../css/handheld.css" media="handheld" />
+ <link rel="stylesheet" href="../css/screen.css" media="screen and (min-width: 661px)" />
+
+ <script src="../javascript/all.js"></script>
+ <!--[if lt IE 9]>
+ <script src="../javascript/html5.js"></script>
+ <![endif]-->
+ </head>
+
+ <body>
+
+<div class="index">
+ <div class="menu">
+ <div class="indexLinks">
+ <a href="../index.html">Classes</a>
+ <a href="../files.html">Files</a>
+ </div>
+
+ <h2 class="heading1">Classes</h2>
+
+ <input type="text" name="classFilter" class="classFilter" id="ClassFilter" placeholder="Filter"></input>
+
+ <nav>
+ <ul class="classList" id="ClassList">
+
+ <li><a href="../symbols/_global_.html">_global_</a></li>
+
+ <li><a href="../symbols/mockup.html">mockup</a></li>
+
+ <li><a href="../symbols/RAIServer.html">RAIServer</a></li>
+
+ <li><a href="../symbols/RAISocket.html">RAISocket</a></li>
+
+ <li><a href="../symbols/starttls.html">starttls</a></li>
+
+ </ul>
+ </nav>
+ </div>
+ <div class="fineprint" style="clear:both">
+ <footer>
+
+ Documentation generator: <a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank">JsDoc Toolkit</a> 2.4.0<br />
+ Template: <a href="http://www.thebrightlines.com/2010/05/06/new-template-for-jsdoctoolkit-codeview/" target="_blank">Codeview</a> 1.2<br />
+ Generated on:
+ <time datetime='2012-0-22' pubdate>2012-0-22 12:15</time>
+ </footer>
+ </div>
+</div>
+
+<div class="index indexStatic"></div>
+
+<div class="content">
+ <div class="innerContent">
+ <article>
+ <header>
+ <h1 class="classTitle">
+
+ Class <span>RAIServer</span>
+ </h1>
+
+ <div class="intro">
+ <p class="description summary">
+
+ </p>
+
+
+ <ul class="summary">
+
+
+
+ <li>Defined in: <a href="../symbols/src/RAI_lib_rai.js.html">rai.js</a></li>
+
+
+ </ul>
+
+ </div>
+ </header>
+
+
+ <section>
+ <div class="props">
+ <table class="summaryTable" cellspacing="0" summary="A summary of the constructor documented in the class RAIServer.">
+ <caption class="sectionTitle">Class Summary</caption>
+ <thead>
+ <tr>
+ <th scope="col">Constructor Attributes</th>
+ <th scope="col">Constructor Name and Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="attributes">&nbsp;</td>
+ <td class="nameDescription" >
+ <div class="fixedFont">
+ <b><a href="../symbols/RAIServer.html#constructor">RAIServer</a></b>(options)
+ </div>
+ <div class="description"><p>Creates instance of RAIServer</p>
+
+<p>Options object has the following properties:</p>
+
+<ul>
+ <li><b>debug</b> - if set to true print traffic to console</li>
+ <li><b>disconnectOnTimeout</b> - if set to true close the connection on disconnect</li>
+ <li><b>timeout</b> - timeout in milliseconds for disconnecting the client,
+ defaults to 0 (no timeout)</li>
+</ul>
+
+<p><b>Events</b></p>
+
+<ul>
+ <li><b>'connect'</b> - emitted if a client connects to the server, param
+ is a client (<a href="../symbols/RAISocket.html">RAISocket</a>) object</li>
+ <li><b>'error'</b> - emitted on error, has an error object as a param</li>
+</ul></div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </section>
+
+
+
+ <!--
+ #### METHODS SUMMARY
+ -->
+
+ <section>
+
+
+ <div class="props">
+ <h2 class="sectionTitle">Method Summary</h2>
+
+
+ <nav>
+ <table class="summaryTable" id="MethodsList" cellspacing="0" summary="A summary of the methods documented in the class RAIServer.">
+ <thead>
+ <tr>
+ <th scope="col">Method Attributes</th>
+ <th scope="col">Method Name and Description</th>
+ </tr>
+ </thead>
+
+ <tbody>
+
+
+ <tr
+ class='item0'
+ >
+ <td class="attributes">&lt;private&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAIServer.html#_createServer">_createServer</a></b>()
+ </div>
+ <div class="description"><p>Creates a server with listener callback</p></div>
+ </td>
+ </tr>
+
+ <tr
+ class='item1'
+ >
+ <td class="attributes">&lt;private&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAIServer.html#_serverListener">_serverListener</a></b>(socket)
+ </div>
+ <div class="description"><p>Server listener that is run on client connection</p>
+
+<p><a href="../symbols/RAISocket.html">RAISocket</a> object instance is created based on the client socket
+ and a <code>'connection'</code> event is emitted</p></div>
+ </td>
+ </tr>
+
+ <tr
+ class='item2'
+ >
+ <td class="attributes">&nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAIServer.html#end">end</a></b>(callback)
+ </div>
+ <div class="description"><p>Stops the server</p></div>
+ </td>
+ </tr>
+
+ <tr
+ class='item3'
+ >
+ <td class="attributes">&nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAIServer.html#listen">listen</a></b>(port, host, callback)
+ </div>
+ <div class="description"><p>Starts listening on selected port</p></div>
+ </td>
+ </tr>
+
+ </tbody>
+ </table>
+ </nav>
+
+
+
+ </div>
+ </section>
+
+
+ <!--
+ #### EVENTS SUMMARY
+ -->
+
+
+ <section>
+
+ <nav>
+ <div class="props">
+ <table class="summaryTable" cellspacing="0" summary="A summary of the events documented in the class RAIServer.">
+ <caption class="sectionTitle">Event Summary</caption>
+
+ <thead>
+ <tr>
+ <th scope="col">Event Attributes</th>
+ <th scope="col">Event Name and Description</th>
+ </tr>
+ </thead>
+
+ <tbody>
+
+ <tr>
+ <td class="attributes">&lt;private&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAIServer.html#event:_onError">_onError</a></b>(err)
+ </div>
+ <div class="description"><p>Listens for errors</p></div>
+ </td>
+ </tr>
+
+ </tbody>
+ </table>
+ </div>
+ </nav>
+
+
+
+ </section>
+
+ <!--
+ #### CONSTRUCTOR DETAILS
+ -->
+
+ <section>
+ <div class="details props">
+ <div class="innerProps">
+ <h2 class="sectionTitle" id="constructor">
+ Class Detail
+ </h2>
+
+ <div class="fixedFont">
+ <b>RAIServer</b>(options)
+ </div>
+
+ <div class="description">
+ <p>Creates instance of RAIServer</p>
+
+<p>Options object has the following properties:</p>
+
+<ul>
+ <li><b>debug</b> - if set to true print traffic to console</li>
+ <li><b>disconnectOnTimeout</b> - if set to true close the connection on disconnect</li>
+ <li><b>timeout</b> - timeout in milliseconds for disconnecting the client,
+ defaults to 0 (no timeout)</li>
+</ul>
+
+<p><b>Events</b></p>
+
+<ul>
+ <li><b>'connect'</b> - emitted if a client connects to the server, param
+ is a client (<a href="../symbols/RAISocket.html">RAISocket</a>) object</li>
+ <li><b>'error'</b> - emitted on error, has an error object as a param</li>
+</ul>
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Object}</span> <b>options</b>
+ <i>Optional</i>
+ </dt>
+ <dd>Optional options object</dd>
+
+ </dl>
+
+
+
+ </div>
+ </div>
+ </section>
+
+ <!--
+ #### FIELD DETAILS
+ -->
+
+ <!--
+ #### METHOD DETAILS
+ -->
+
+ <section>
+ <div class="details props">
+ <div class="innerProps">
+ <h2 class="sectionTitle">
+ Method Detail
+ </h2>
+
+ <ul class="methodDetail" id="MethodDetail">
+
+
+ <li
+ class='item0'
+ >
+ <div class="fixedFont heading" id="_createServer">
+ <span class='lighter'>
+ &lt;private&gt;
+ </span>
+
+
+
+ <b>_createServer</b>()
+ </div>
+
+ <div class="description">
+ <p>Creates a server with listener callback</p>
+
+
+
+
+ </div>
+
+
+
+
+
+
+ <div class="hr"></div>
+ </li>
+
+ <li
+ class='item1'
+ >
+ <div class="fixedFont heading" id="_serverListener">
+ <span class='lighter'>
+ &lt;private&gt;
+ </span>
+
+
+
+ <b>_serverListener</b>(socket)
+ </div>
+
+ <div class="description">
+ <p>Server listener that is run on client connection</p>
+
+<p><a href="../symbols/RAISocket.html">RAISocket</a> object instance is created based on the client socket
+ and a <code>'connection'</code> event is emitted</p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Object}</span> <b>socket</b>
+
+ </dt>
+ <dd>The socket to the client</dd>
+
+ </dl>
+
+
+
+ <div class="hr"></div>
+ </li>
+
+ <li
+ class='item2'
+ >
+ <div class="fixedFont heading" id="end">
+ <span class='lighter'>
+
+ </span>
+
+
+
+ <b>end</b>(callback)
+ </div>
+
+ <div class="description">
+ <p>Stops the server</p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Function}</span> <b>callback</b>
+
+ </dt>
+ <dd>Is run when the server is closed</dd>
+
+ </dl>
+
+
+
+ <div class="hr"></div>
+ </li>
+
+ <li
+ class='item3'
+ >
+ <div class="fixedFont heading" id="listen">
+ <span class='lighter'>
+
+ </span>
+
+
+
+ <b>listen</b>(port, host, callback)
+ </div>
+
+ <div class="description">
+ <p>Starts listening on selected port</p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Number}</span> <b>port</b>
+
+ </dt>
+ <dd>The port to listen</dd>
+
+ <dt>
+ <span class="light fixedFont">{String}</span> <b>host</b>
+ <i>Optional</i>
+ </dt>
+ <dd>The IP address to listen</dd>
+
+ <dt>
+ <span class="light fixedFont">{Function}</span> <b>callback</b>
+
+ </dt>
+ <dd>The callback function to be run after the server
+is listening, the only param is an error message if the operation failed</dd>
+
+ </dl>
+
+
+
+
+ </li>
+
+ </ul>
+ </div>
+ </div>
+ </section>
+
+
+ <!--
+ #### EVENT DETAILS
+ -->
+
+ <section>
+ <div class="details props">
+ <div class="innerProps">
+ <h2 class="sectionTitle">
+ Event Detail
+ </h2>
+
+
+ <div class="fixedFont heading" id="event:_onError">
+ <span class='lighter'>
+ &lt;private&gt;
+ </span>
+
+
+
+ <b>_onError</b>(err)
+ </div>
+
+ <div class="description">
+ <p>Listens for errors</p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Object}</span> <b>err</b>
+
+ </dt>
+ <dd>Error object</dd>
+
+ </dl>
+
+
+
+
+
+
+ </div>
+ </div>
+ </section>
+
+ </article>
+ </div>
+</div>
+
+ <script type="text/javascript">
+ wbos.CssTools.MediaQueryFallBack.LoadCss('../css/screen.css', '../css/handheld.css', 660)
+ codeview.classFilter.Init()
+ </script>
+ </body>
+</html>
+
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/RAISocket.html b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/RAISocket.html
new file mode 100644
index 0000000..15cad38
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/RAISocket.html
@@ -0,0 +1,826 @@
+
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="generator" content="JsDoc Toolkit" />
+ <title>RAISocket | JsDoc Reference</title>
+
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
+ <meta name="mobileoptimized" content="0" />
+
+ <link rel="stylesheet" href="../css/all.css" media="all" />
+ <link rel="stylesheet" href="../css/handheld.css" media="only screen and (max-width: 660px)" />
+ <link rel="stylesheet" href="../css/handheld.css" media="handheld" />
+ <link rel="stylesheet" href="../css/screen.css" media="screen and (min-width: 661px)" />
+
+ <script src="../javascript/all.js"></script>
+ <!--[if lt IE 9]>
+ <script src="../javascript/html5.js"></script>
+ <![endif]-->
+ </head>
+
+ <body>
+
+<div class="index">
+ <div class="menu">
+ <div class="indexLinks">
+ <a href="../index.html">Classes</a>
+ <a href="../files.html">Files</a>
+ </div>
+
+ <h2 class="heading1">Classes</h2>
+
+ <input type="text" name="classFilter" class="classFilter" id="ClassFilter" placeholder="Filter"></input>
+
+ <nav>
+ <ul class="classList" id="ClassList">
+
+ <li><a href="../symbols/_global_.html">_global_</a></li>
+
+ <li><a href="../symbols/mockup.html">mockup</a></li>
+
+ <li><a href="../symbols/RAIServer.html">RAIServer</a></li>
+
+ <li><a href="../symbols/RAISocket.html">RAISocket</a></li>
+
+ <li><a href="../symbols/starttls.html">starttls</a></li>
+
+ </ul>
+ </nav>
+ </div>
+ <div class="fineprint" style="clear:both">
+ <footer>
+
+ Documentation generator: <a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank">JsDoc Toolkit</a> 2.4.0<br />
+ Template: <a href="http://www.thebrightlines.com/2010/05/06/new-template-for-jsdoctoolkit-codeview/" target="_blank">Codeview</a> 1.2<br />
+ Generated on:
+ <time datetime='2012-0-22' pubdate>2012-0-22 12:15</time>
+ </footer>
+ </div>
+</div>
+
+<div class="index indexStatic"></div>
+
+<div class="content">
+ <div class="innerContent">
+ <article>
+ <header>
+ <h1 class="classTitle">
+
+ Class <span>RAISocket</span>
+ </h1>
+
+ <div class="intro">
+ <p class="description summary">
+
+ </p>
+
+
+ <ul class="summary">
+
+
+
+ <li>Defined in: <a href="../symbols/src/RAI_lib_rai.js.html">rai.js</a></li>
+
+
+ </ul>
+
+ </div>
+ </header>
+
+
+ <section>
+ <div class="props">
+ <table class="summaryTable" cellspacing="0" summary="A summary of the constructor documented in the class RAISocket.">
+ <caption class="sectionTitle">Class Summary</caption>
+ <thead>
+ <tr>
+ <th scope="col">Constructor Attributes</th>
+ <th scope="col">Constructor Name and Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="attributes">&nbsp;</td>
+ <td class="nameDescription" >
+ <div class="fixedFont">
+ <b><a href="../symbols/RAISocket.html#constructor">RAISocket</a></b>(socket, options)
+ </div>
+ <div class="description"><p>Creates a instance for interacting with a client (socket)</p>
+
+<p>Optional options object is the same that is passed to the parent
+<a href="../symbols/RAIServer.html">RAIServer</a> object</p>
+
+<p><b>Events</b></p>
+
+<ul>
+ <li><b>'command'</b> - emitted if a client sends a command.</div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </section>
+
+
+
+ <!--
+ #### METHODS SUMMARY
+ -->
+
+ <section>
+
+
+ <div class="props">
+ <h2 class="sectionTitle">Method Summary</h2>
+
+
+ <nav>
+ <table class="summaryTable" id="MethodsList" cellspacing="0" summary="A summary of the methods documented in the class RAISocket.">
+ <thead>
+ <tr>
+ <th scope="col">Method Attributes</th>
+ <th scope="col">Method Name and Description</th>
+ </tr>
+ </thead>
+
+ <tbody>
+
+
+ <tr
+ class='item0'
+ >
+ <td class="attributes">&lt;private&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAISocket.html#_destroy">_destroy</a></b>()
+ </div>
+ <div class="description"><p>Called when the connection is or is going to be ended</p></div>
+ </td>
+ </tr>
+
+ <tr
+ class='item1'
+ >
+ <td class="attributes">&lt;private&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAISocket.html#_processData">_processData</a></b>(str)
+ </div>
+ <div class="description"><p>Processed incoming command lines and emits found data as
+<code>'command'</code> with the command name as the first param and the rest
+of the data as second (Buffer)</p></div>
+ </td>
+ </tr>
+
+ <tr
+ class='item2'
+ >
+ <td class="attributes">&nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAISocket.html#end">end</a></b>()
+ </div>
+ <div class="description"><p>Closes the connection to the client</p></div>
+ </td>
+ </tr>
+
+ <tr
+ class='item3'
+ >
+ <td class="attributes">&nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAISocket.html#send">send</a></b>(data)
+ </div>
+ <div class="description"><p>Sends some data to the client.</div>
+ </td>
+ </tr>
+
+ <tr
+ class='item4'
+ >
+ <td class="attributes">&nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAISocket.html#startDataMode">startDataMode</a></b>(sequence)
+ </div>
+ <div class="description"><p>Instructs the server to be listening for mixed data instead of line based
+ commands</p></div>
+ </td>
+ </tr>
+
+ <tr
+ class='item5'
+ >
+ <td class="attributes">&nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAISocket.html#startTLS">startTLS</a></b>(credentials, callback)
+ </div>
+ <div class="description"><p>Instructs the server to upgrade the connection to secure TLS connection</p>
+
+<p>Fires <code>callback</code> on successful connection upgrade if set,
+otherwise emits <code>'tls'</code></p></div>
+ </td>
+ </tr>
+
+ </tbody>
+ </table>
+ </nav>
+
+
+
+ </div>
+ </section>
+
+
+ <!--
+ #### EVENTS SUMMARY
+ -->
+
+
+ <section>
+
+ <nav>
+ <div class="props">
+ <table class="summaryTable" cellspacing="0" summary="A summary of the events documented in the class RAISocket.">
+ <caption class="sectionTitle">Event Summary</caption>
+
+ <thead>
+ <tr>
+ <th scope="col">Event Attributes</th>
+ <th scope="col">Event Name and Description</th>
+ </tr>
+ </thead>
+
+ <tbody>
+
+ <tr>
+ <td class="attributes">&lt;private&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAISocket.html#event:_onClose">_onClose</a></b>(hadError)
+ </div>
+ <div class="description"><p>Called when the connection is closed</p></div>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="attributes">&lt;private&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAISocket.html#event:_onEnd">_onEnd</a></b>()
+ </div>
+ <div class="description"><p>Called when the connection is ended.</div>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="attributes">&lt;private&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAISocket.html#event:_onError">_onError</a></b>(err)
+ </div>
+ <div class="description"><p>Called when an error has appeared.</div>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="attributes">&lt;private&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAISocket.html#event:_onReceiveData">_onReceiveData</a></b>(chunk)
+ </div>
+ <div class="description"><p>Called when a chunk of data arrives from the client.</div>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="attributes">&lt;private&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont"><b><a href="../symbols/RAISocket.html#event:_onTimeout">_onTimeout</a></b>()
+ </div>
+ <div class="description"><p>Called when a timeout has occured.</div>
+ </td>
+ </tr>
+
+ </tbody>
+ </table>
+ </div>
+ </nav>
+
+
+
+ </section>
+
+ <!--
+ #### CONSTRUCTOR DETAILS
+ -->
+
+ <section>
+ <div class="details props">
+ <div class="innerProps">
+ <h2 class="sectionTitle" id="constructor">
+ Class Detail
+ </h2>
+
+ <div class="fixedFont">
+ <b>RAISocket</b>(socket, options)
+ </div>
+
+ <div class="description">
+ <p>Creates a instance for interacting with a client (socket)</p>
+
+<p>Optional options object is the same that is passed to the parent
+<a href="../symbols/RAIServer.html">RAIServer</a> object</p>
+
+<p><b>Events</b></p>
+
+<ul>
+ <li><b>'command'</b> - emitted if a client sends a command. Gets two
+ params - command (String) and payload (Buffer)</li>
+ <li><b>'data'</b> - emitted when a chunk is received in data mode, the
+ param being the payload (Buffer)</li>
+ <li><b>'ready'</b> - emitted when data stream ends and normal command
+ flow is recovered</li>
+ <li><b>'tls'</b> - emitted when the connection is secured by TLS</li>
+ <li><b>'error'</b> - emitted when an error occurs. Connection to the
+ client is disconnected automatically. Param is an error object.</l>
+ <li><b>'timeout'</b> - emitted when a timeout occurs. Connection to the
+ client is disconnected automatically if disconnectOnTimeout option
+ is set to true.</l>
+ <li><b>'end'</b> - emitted when the client disconnects</l>
+</ul>
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Object}</span> <b>socket</b>
+
+ </dt>
+ <dd>Socket for the client</dd>
+
+ <dt>
+ <span class="light fixedFont">{Object}</span> <b>options</b>
+ <i>Optional</i>
+ </dt>
+ <dd>Optional options object</dd>
+
+ </dl>
+
+
+
+ </div>
+ </div>
+ </section>
+
+ <!--
+ #### FIELD DETAILS
+ -->
+
+ <!--
+ #### METHOD DETAILS
+ -->
+
+ <section>
+ <div class="details props">
+ <div class="innerProps">
+ <h2 class="sectionTitle">
+ Method Detail
+ </h2>
+
+ <ul class="methodDetail" id="MethodDetail">
+
+
+ <li
+ class='item0'
+ >
+ <div class="fixedFont heading" id="_destroy">
+ <span class='lighter'>
+ &lt;private&gt;
+ </span>
+
+
+
+ <b>_destroy</b>()
+ </div>
+
+ <div class="description">
+ <p>Called when the connection is or is going to be ended</p>
+
+
+
+
+ </div>
+
+
+
+
+
+
+ <div class="hr"></div>
+ </li>
+
+ <li
+ class='item1'
+ >
+ <div class="fixedFont heading" id="_processData">
+ <span class='lighter'>
+ &lt;private&gt;
+ </span>
+
+
+
+ <b>_processData</b>(str)
+ </div>
+
+ <div class="description">
+ <p>Processed incoming command lines and emits found data as
+<code>'command'</code> with the command name as the first param and the rest
+of the data as second (Buffer)</p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{String}</span> <b>str</b>
+
+ </dt>
+ <dd>Binary string to be processed</dd>
+
+ </dl>
+
+
+
+ <div class="hr"></div>
+ </li>
+
+ <li
+ class='item2'
+ >
+ <div class="fixedFont heading" id="end">
+ <span class='lighter'>
+
+ </span>
+
+
+
+ <b>end</b>()
+ </div>
+
+ <div class="description">
+ <p>Closes the connection to the client</p>
+
+
+
+
+ </div>
+
+
+
+
+
+
+ <div class="hr"></div>
+ </li>
+
+ <li
+ class='item3'
+ >
+ <div class="fixedFont heading" id="send">
+ <span class='lighter'>
+
+ </span>
+
+
+
+ <b>send</b>(data)
+ </div>
+
+ <div class="description">
+ <p>Sends some data to the client. <code>&lt;CR&gt;&lt;LF&gt;</code> is automatically appended to
+ the data</p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{String|Buffer}</span> <b>data</b>
+
+ </dt>
+ <dd>Data to be sent to the client</dd>
+
+ </dl>
+
+
+
+ <div class="hr"></div>
+ </li>
+
+ <li
+ class='item4'
+ >
+ <div class="fixedFont heading" id="startDataMode">
+ <span class='lighter'>
+
+ </span>
+
+
+
+ <b>startDataMode</b>(sequence)
+ </div>
+
+ <div class="description">
+ <p>Instructs the server to be listening for mixed data instead of line based
+ commands</p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{String}</span> <b>sequence</b>
+ <i>Optional, Default: "."</i>
+ </dt>
+ <dd>- optional sequence on separate line for
+ matching the data end</dd>
+
+ </dl>
+
+
+
+ <div class="hr"></div>
+ </li>
+
+ <li
+ class='item5'
+ >
+ <div class="fixedFont heading" id="startTLS">
+ <span class='lighter'>
+
+ </span>
+
+
+
+ <b>startTLS</b>(credentials, callback)
+ </div>
+
+ <div class="description">
+ <p>Instructs the server to upgrade the connection to secure TLS connection</p>
+
+<p>Fires <code>callback</code> on successful connection upgrade if set,
+otherwise emits <code>'tls'</code></p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Object}</span> <b>credentials</b>
+ <i>Optional</i>
+ </dt>
+ <dd>An object with PEM encoded key and
+ certificate <code>{key:"---BEGIN...", cert:"---BEGIN..."}</code>,
+ if not set autogenerated values will be used.</dd>
+
+ <dt>
+ <span class="light fixedFont">{Function}</span> <b>callback</b>
+ <i>Optional</i>
+ </dt>
+ <dd>If calback is set fire it after successful connection
+ upgrade, otherwise <code>'tls'</code> is emitted</dd>
+
+ </dl>
+
+
+
+
+ </li>
+
+ </ul>
+ </div>
+ </div>
+ </section>
+
+
+ <!--
+ #### EVENT DETAILS
+ -->
+
+ <section>
+ <div class="details props">
+ <div class="innerProps">
+ <h2 class="sectionTitle">
+ Event Detail
+ </h2>
+
+
+ <div class="fixedFont heading" id="event:_onClose">
+ <span class='lighter'>
+ &lt;private&gt;
+ </span>
+
+
+
+ <b>_onClose</b>(hadError)
+ </div>
+
+ <div class="description">
+ <p>Called when the connection is closed</p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Boolean}</span> <b>hadError</b>
+
+ </dt>
+ <dd>did the connection end because of an error?</dd>
+
+ </dl>
+
+
+
+
+ <div class="hr"></div>
+
+ <div class="fixedFont heading" id="event:_onEnd">
+ <span class='lighter'>
+ &lt;private&gt;
+ </span>
+
+
+
+ <b>_onEnd</b>()
+ </div>
+
+ <div class="description">
+ <p>Called when the connection is ended. Emits <code>'end'</code></p>
+
+
+
+
+ </div>
+
+
+
+
+
+
+
+ <div class="hr"></div>
+
+ <div class="fixedFont heading" id="event:_onError">
+ <span class='lighter'>
+ &lt;private&gt;
+ </span>
+
+
+
+ <b>_onError</b>(err)
+ </div>
+
+ <div class="description">
+ <p>Called when an error has appeared. Emits <code>'error'</code> with
+the error object as a parameter.</p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Object}</span> <b>err</b>
+
+ </dt>
+ <dd>Error object</dd>
+
+ </dl>
+
+
+
+
+ <div class="hr"></div>
+
+ <div class="fixedFont heading" id="event:_onReceiveData">
+ <span class='lighter'>
+ &lt;private&gt;
+ </span>
+
+
+
+ <b>_onReceiveData</b>(chunk)
+ </div>
+
+ <div class="description">
+ <p>Called when a chunk of data arrives from the client. If currently in data
+mode, transmit the data otherwise send it to <code>_processData</code></p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Buffer|String}</span> <b>chunk</b>
+
+ </dt>
+ <dd>Data sent by the client</dd>
+
+ </dl>
+
+
+
+
+ <div class="hr"></div>
+
+ <div class="fixedFont heading" id="event:_onTimeout">
+ <span class='lighter'>
+ &lt;private&gt;
+ </span>
+
+
+
+ <b>_onTimeout</b>()
+ </div>
+
+ <div class="description">
+ <p>Called when a timeout has occured. Connection will be closed and
+<code>'timeout'</code> is emitted.</p>
+
+
+
+
+ </div>
+
+
+
+
+
+
+
+
+
+ </div>
+ </div>
+ </section>
+
+ </article>
+ </div>
+</div>
+
+ <script type="text/javascript">
+ wbos.CssTools.MediaQueryFallBack.LoadCss('../css/screen.css', '../css/handheld.css', 660)
+ codeview.classFilter.Init()
+ </script>
+ </body>
+</html>
+
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/_global_.html b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/_global_.html
new file mode 100644
index 0000000..b215cf7
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/_global_.html
@@ -0,0 +1,122 @@
+
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="generator" content="JsDoc Toolkit" />
+ <title>_global_ | JsDoc Reference</title>
+
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
+ <meta name="mobileoptimized" content="0" />
+
+ <link rel="stylesheet" href="../css/all.css" media="all" />
+ <link rel="stylesheet" href="../css/handheld.css" media="only screen and (max-width: 660px)" />
+ <link rel="stylesheet" href="../css/handheld.css" media="handheld" />
+ <link rel="stylesheet" href="../css/screen.css" media="screen and (min-width: 661px)" />
+
+ <script src="../javascript/all.js"></script>
+ <!--[if lt IE 9]>
+ <script src="../javascript/html5.js"></script>
+ <![endif]-->
+ </head>
+
+ <body>
+
+<div class="index">
+ <div class="menu">
+ <div class="indexLinks">
+ <a href="../index.html">Classes</a>
+ <a href="../files.html">Files</a>
+ </div>
+
+ <h2 class="heading1">Classes</h2>
+
+ <input type="text" name="classFilter" class="classFilter" id="ClassFilter" placeholder="Filter"></input>
+
+ <nav>
+ <ul class="classList" id="ClassList">
+
+ <li><a href="../symbols/_global_.html">_global_</a></li>
+
+ <li><a href="../symbols/mockup.html">mockup</a></li>
+
+ <li><a href="../symbols/RAIServer.html">RAIServer</a></li>
+
+ <li><a href="../symbols/RAISocket.html">RAISocket</a></li>
+
+ <li><a href="../symbols/starttls.html">starttls</a></li>
+
+ </ul>
+ </nav>
+ </div>
+ <div class="fineprint" style="clear:both">
+ <footer>
+
+ Documentation generator: <a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank">JsDoc Toolkit</a> 2.4.0<br />
+ Template: <a href="http://www.thebrightlines.com/2010/05/06/new-template-for-jsdoctoolkit-codeview/" target="_blank">Codeview</a> 1.2<br />
+ Generated on:
+ <time datetime='2012-0-22' pubdate>2012-0-22 12:15</time>
+ </footer>
+ </div>
+</div>
+
+<div class="index indexStatic"></div>
+
+<div class="content">
+ <div class="innerContent">
+ <article>
+ <header>
+ <h1 class="classTitle">
+
+ Built-In Namespace <span>_global_</span>
+ </h1>
+
+ <div class="intro">
+ <p class="description summary">
+
+ </p>
+
+
+ </div>
+ </header>
+
+
+
+
+ <!--
+ #### METHODS SUMMARY
+ -->
+
+
+ <!--
+ #### EVENTS SUMMARY
+ -->
+
+ <!--
+ #### CONSTRUCTOR DETAILS
+ -->
+
+ <!--
+ #### FIELD DETAILS
+ -->
+
+ <!--
+ #### METHOD DETAILS
+ -->
+
+
+ <!--
+ #### EVENT DETAILS
+ -->
+
+ </article>
+ </div>
+</div>
+
+ <script type="text/javascript">
+ wbos.CssTools.MediaQueryFallBack.LoadCss('../css/screen.css', '../css/handheld.css', 660)
+ codeview.classFilter.Init()
+ </script>
+ </body>
+</html>
+
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/mockup.html b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/mockup.html
new file mode 100644
index 0000000..987f5be
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/mockup.html
@@ -0,0 +1,264 @@
+
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="generator" content="JsDoc Toolkit" />
+ <title>mockup | JsDoc Reference</title>
+
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
+ <meta name="mobileoptimized" content="0" />
+
+ <link rel="stylesheet" href="../css/all.css" media="all" />
+ <link rel="stylesheet" href="../css/handheld.css" media="only screen and (max-width: 660px)" />
+ <link rel="stylesheet" href="../css/handheld.css" media="handheld" />
+ <link rel="stylesheet" href="../css/screen.css" media="screen and (min-width: 661px)" />
+
+ <script src="../javascript/all.js"></script>
+ <!--[if lt IE 9]>
+ <script src="../javascript/html5.js"></script>
+ <![endif]-->
+ </head>
+
+ <body>
+
+<div class="index">
+ <div class="menu">
+ <div class="indexLinks">
+ <a href="../index.html">Classes</a>
+ <a href="../files.html">Files</a>
+ </div>
+
+ <h2 class="heading1">Classes</h2>
+
+ <input type="text" name="classFilter" class="classFilter" id="ClassFilter" placeholder="Filter"></input>
+
+ <nav>
+ <ul class="classList" id="ClassList">
+
+ <li><a href="../symbols/_global_.html">_global_</a></li>
+
+ <li><a href="../symbols/mockup.html">mockup</a></li>
+
+ <li><a href="../symbols/RAIServer.html">RAIServer</a></li>
+
+ <li><a href="../symbols/RAISocket.html">RAISocket</a></li>
+
+ <li><a href="../symbols/starttls.html">starttls</a></li>
+
+ </ul>
+ </nav>
+ </div>
+ <div class="fineprint" style="clear:both">
+ <footer>
+
+ Documentation generator: <a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank">JsDoc Toolkit</a> 2.4.0<br />
+ Template: <a href="http://www.thebrightlines.com/2010/05/06/new-template-for-jsdoctoolkit-codeview/" target="_blank">Codeview</a> 1.2<br />
+ Generated on:
+ <time datetime='2012-0-22' pubdate>2012-0-22 12:15</time>
+ </footer>
+ </div>
+</div>
+
+<div class="index indexStatic"></div>
+
+<div class="content">
+ <div class="innerContent">
+ <article>
+ <header>
+ <h1 class="classTitle">
+
+ Namespace <span>mockup</span>
+ </h1>
+
+ <div class="intro">
+ <p class="description summary">
+ Mockup module
+ </p>
+
+
+ <ul class="summary">
+
+
+
+ <li>Defined in: <a href="../symbols/src/RAI_lib_mockup.js.html">mockup.js</a></li>
+
+
+ </ul>
+
+ </div>
+ </header>
+
+
+
+
+ <!--
+ #### METHODS SUMMARY
+ -->
+
+ <section>
+
+
+ <div class="props">
+ <h2 class="sectionTitle">Method Summary</h2>
+
+
+ <nav>
+ <table class="summaryTable" id="MethodsList" cellspacing="0" summary="A summary of the methods documented in the class mockup.">
+ <thead>
+ <tr>
+ <th scope="col">Method Attributes</th>
+ <th scope="col">Method Name and Description</th>
+ </tr>
+ </thead>
+
+ <tbody>
+
+
+ <tr
+ class='item0'
+ >
+ <td class="attributes">&lt;static&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont">mockup.<b><a href="../symbols/mockup.html#.runClientMockup">runClientMockup</a></b>(port, host, commands, callback, debug)
+ </div>
+ <div class="description"><p>Runs a batch of commands against a server</p>
+
+<pre>
+var cmds = ["EHLO FOOBAR", "STARTTLS", "QUIT"];
+runClientMockup(25, "mail.hot.ee", cmds, function(resp){
+ console.log("Final:", resp.toString("utf-8").trim());
+});
+</pre></div>
+ </td>
+ </tr>
+
+ </tbody>
+ </table>
+ </nav>
+
+
+
+ </div>
+ </section>
+
+
+ <!--
+ #### EVENTS SUMMARY
+ -->
+
+ <!--
+ #### CONSTRUCTOR DETAILS
+ -->
+
+ <!--
+ #### FIELD DETAILS
+ -->
+
+ <!--
+ #### METHOD DETAILS
+ -->
+
+ <section>
+ <div class="details props">
+ <div class="innerProps">
+ <h2 class="sectionTitle">
+ Method Detail
+ </h2>
+
+ <ul class="methodDetail" id="MethodDetail">
+
+
+ <li
+ class='item0'
+ >
+ <div class="fixedFont heading" id=".runClientMockup">
+ <span class='lighter'>
+ &lt;static&gt;
+ </span>
+
+
+
+ <span class="light">mockup.</span><b>runClientMockup</b>(port, host, commands, callback, debug)
+ </div>
+
+ <div class="description">
+ <p>Runs a batch of commands against a server</p>
+
+<pre>
+var cmds = ["EHLO FOOBAR", "STARTTLS", "QUIT"];
+runClientMockup(25, "mail.hot.ee", cmds, function(resp){
+ console.log("Final:", resp.toString("utf-8").trim());
+});
+</pre>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Number}</span> <b>port</b>
+
+ </dt>
+ <dd>Port number</dd>
+
+ <dt>
+ <span class="light fixedFont">{String}</span> <b>host</b>
+
+ </dt>
+ <dd>Hostname to connect to</dd>
+
+ <dt>
+ <span class="light fixedFont">{Array}</span> <b>commands</b>
+
+ </dt>
+ <dd>Command list to be sent to server</dd>
+
+ <dt>
+ <span class="light fixedFont">{Function}</span> <b>callback</b>
+
+ </dt>
+ <dd>Callback function to run on completion,
+ has the last response from the server as a param</dd>
+
+ <dt>
+ <span class="light fixedFont">{Boolean}</span> <b>debug</b>
+ <i>Optional</i>
+ </dt>
+ <dd>if set to true log all input/output</dd>
+
+ </dl>
+
+
+
+
+ </li>
+
+ </ul>
+ </div>
+ </div>
+ </section>
+
+
+ <!--
+ #### EVENT DETAILS
+ -->
+
+ </article>
+ </div>
+</div>
+
+ <script type="text/javascript">
+ wbos.CssTools.MediaQueryFallBack.LoadCss('../css/screen.css', '../css/handheld.css', 660)
+ codeview.classFilter.Init()
+ </script>
+ </body>
+</html>
+
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_index.js.html b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_index.js.html
new file mode 100644
index 0000000..3cee0e3
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_index.js.html
@@ -0,0 +1,394 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"> <style>
+ .KEYW {color: #933;}
+ .COMM {color: #bbb; font-style: italic;}
+ .NUMB {color: #393;}
+ .STRN {color: #393;}
+ .REGX {color: #339;}
+ .line {border-right: 1px dotted #666; color: #666; font-style: normal;}
+ </style></head><body><pre><span class='line'> 1</span> <span class="COMM">/**
+<span class='line'> 2</span> * @fileOverview This is the main file for the RAI library to create text based servers
+<span class='line'> 3</span> * @author &lt;a href="mailto:andris@node.ee">Andris Reinman&lt;/a>
+<span class='line'> 4</span> * @version 0.1.0
+<span class='line'> 5</span> */</span><span class="WHIT">
+<span class='line'> 6</span>
+<span class='line'> 7</span> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">netlib</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"net"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 8</span> </span><span class="WHIT"> </span><span class="NAME">utillib</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"util"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 9</span> </span><span class="WHIT"> </span><span class="NAME">EventEmitter</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">'events'</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">EventEmitter</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 10</span> </span><span class="WHIT"> </span><span class="NAME">starttls</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"./starttls"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 11</span> </span><span class="WHIT"> </span><span class="NAME">tlslib</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"tls"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 12</span> </span><span class="WHIT"> </span><span class="NAME">crypto</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"crypto"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 13</span> </span><span class="WHIT"> </span><span class="NAME">fs</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"fs"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 14</span>
+<span class='line'> 15</span> </span><span class="COMM">// Default credentials for starting TLS server</span><span class="WHIT">
+<span class='line'> 16</span> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">defaultCredentials</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 17</span> </span><span class="WHIT"> </span><span class="NAME">key</span><span class="PUNC">:</span><span class="WHIT"> </span><span class="NAME">fs.readFileSync</span><span class="PUNC">(</span><span class="NAME">__dirname</span><span class="PUNC">+</span><span class="STRN">"/cert/key.pem"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 18</span> </span><span class="WHIT"> </span><span class="NAME">cert</span><span class="PUNC">:</span><span class="WHIT"> </span><span class="NAME">fs.readFileSync</span><span class="PUNC">(</span><span class="NAME">__dirname</span><span class="PUNC">+</span><span class="STRN">"/cert/cert.pem"</span><span class="PUNC">)</span><span class="WHIT">
+<span class='line'> 19</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 20</span>
+<span class='line'> 21</span> </span><span class="COMM">// Expose to the world</span><span class="WHIT">
+<span class='line'> 22</span> </span><span class="NAME">module.exports.RAIServer</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">RAIServer</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 23</span>
+<span class='line'> 24</span> </span><span class="COMM">/**
+<span class='line'> 25</span> * &lt;p>Creates instance of RAIServer&lt;/p>
+<span class='line'> 26</span> *
+<span class='line'> 27</span> * &lt;p>Options object has the following properties:&lt;/p>
+<span class='line'> 28</span> *
+<span class='line'> 29</span> * &lt;ul>
+<span class='line'> 30</span> * &lt;li>&lt;b>debug&lt;/b> - if set to true print traffic to console&lt;/li>
+<span class='line'> 31</span> * &lt;li>&lt;b>timeout&lt;/b> - timeout in milliseconds for disconnecting the client,
+<span class='line'> 32</span> * defaults to 0 (no timeout)&lt;/li>
+<span class='line'> 33</span> * &lt;/ul>
+<span class='line'> 34</span> *
+<span class='line'> 35</span> * &lt;p>&lt;b>Events&lt;/b>&lt;/p>
+<span class='line'> 36</span> *
+<span class='line'> 37</span> * &lt;ul>
+<span class='line'> 38</span> * &lt;li>&lt;b>'connect'&lt;/b> - emitted if a client connects to the server, param
+<span class='line'> 39</span> * is a client ({@link RAISocket}) object&lt;/li>
+<span class='line'> 40</span> * &lt;/ul>
+<span class='line'> 41</span> *
+<span class='line'> 42</span> * @constructor
+<span class='line'> 43</span> * @param {Object} [options] Optional options object
+<span class='line'> 44</span> */</span><span class="WHIT">
+<span class='line'> 45</span> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">RAIServer</span><span class="PUNC">(</span><span class="NAME">options</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 46</span> </span><span class="WHIT"> </span><span class="NAME">EventEmitter.call</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 47</span> </span><span class="WHIT">
+<span class='line'> 48</span> </span><span class="NAME">this.options</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">options</span><span class="TOKN"> </span><span class="PUNC">||</span><span class="TOKN"> </span><span class="PUNC">{</span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 49</span> </span><span class="WHIT">
+<span class='line'> 50</span> </span><span class="NAME">this._createServer</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 51</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 52</span> </span><span class="NAME">utillib.inherits</span><span class="PUNC">(</span><span class="NAME">RAIServer</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">EventEmitter</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 53</span>
+<span class='line'> 54</span> </span><span class="COMM">/**
+<span class='line'> 55</span> * &lt;p>Starts listening on selected port&lt;/p>
+<span class='line'> 56</span> *
+<span class='line'> 57</span> * @param {Number} port The port to listen
+<span class='line'> 58</span> * @param {String} [host] The IP address to listen
+<span class='line'> 59</span> * @param {Function} callback The callback function to be run after the server
+<span class='line'> 60</span> * is listening, the only param is an error message if the operation failed
+<span class='line'> 61</span> */</span><span class="WHIT">
+<span class='line'> 62</span> </span><span class="NAME">RAIServer.prototype.listen</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">port</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">host</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 63</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">!</span><span class="NAME">callback</span><span class="WHIT"> </span><span class="PUNC">&&</span><span class="WHIT"> </span><span class="KEYW">typeof</span><span class="WHIT"> </span><span class="NAME">host</span><span class="PUNC">==</span><span class="STRN">"function"</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 64</span> </span><span class="WHIT"> </span><span class="NAME">callback</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">host</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 65</span> </span><span class="WHIT"> </span><span class="NAME">host</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">undefined</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 66</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 67</span> </span><span class="WHIT"> </span><span class="NAME">this._port</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">port</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 68</span> </span><span class="WHIT"> </span><span class="NAME">this._host</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">host</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 69</span> </span><span class="WHIT">
+<span class='line'> 70</span> </span><span class="NAME">this._server.listen</span><span class="PUNC">(</span><span class="NAME">port</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">host</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 71</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">err</span><span class="WHIT"> </span><span class="PUNC">&&</span><span class="WHIT"> </span><span class="PUNC">!</span><span class="NAME">callback</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 72</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"error"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 73</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">callback</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 74</span> </span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">(</span><span class="NAME">err</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="WHIT"> </span><span class="KEYW">null</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 75</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 76</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 77</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 78</span>
+<span class='line'> 79</span> </span><span class="COMM">/**
+<span class='line'> 80</span> * &lt;p>Creates a server with listener callback&lt;/p>
+<span class='line'> 81</span> */</span><span class="WHIT">
+<span class='line'> 82</span> </span><span class="NAME">RAIServer.prototype._createServer</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 83</span> </span><span class="WHIT"> </span><span class="NAME">this._server</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">netlib.createServer</span><span class="PUNC">(</span><span class="NAME">this._serverListener.bind</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 84</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 85</span>
+<span class='line'> 86</span> </span><span class="COMM">/**
+<span class='line'> 87</span> * &lt;p>Server listener that is run on client connection&lt;/p>
+<span class='line'> 88</span> *
+<span class='line'> 89</span> * &lt;p>{@link RAISocket} object instance is created based on the client socket
+<span class='line'> 90</span> * and a &lt;code>'connection'&lt;/code> event is emitted&lt;/p>
+<span class='line'> 91</span> *
+<span class='line'> 92</span> * @param {Object} socket The socket to the client
+<span class='line'> 93</span> */</span><span class="WHIT">
+<span class='line'> 94</span> </span><span class="NAME">RAIServer.prototype._serverListener</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">socket</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 95</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 96</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"CONNECTION FROM "</span><span class="PUNC">+</span><span class="NAME">socket.remoteAddress</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 97</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 98</span> </span><span class="WHIT">
+<span class='line'> 99</span> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">handler</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">RAISocket</span><span class="PUNC">(</span><span class="NAME">socket</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">this.options</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>100</span> </span><span class="WHIT">
+<span class='line'>101</span> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">"data"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler._onReceiveData.bind</span><span class="PUNC">(</span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>102</span> </span><span class="WHIT"> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">"end"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler._onEnd.bind</span><span class="PUNC">(</span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>103</span> </span><span class="WHIT"> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">"error"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler._onError.bind</span><span class="PUNC">(</span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>104</span> </span><span class="WHIT"> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">"timeout"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler._onTimeout.bind</span><span class="PUNC">(</span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>105</span> </span><span class="WHIT"> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">"close"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler._onClose.bind</span><span class="PUNC">(</span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>106</span>
+<span class='line'>107</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"connection"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>108</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>109</span>
+<span class='line'>110</span> </span><span class="COMM">/**
+<span class='line'>111</span> * &lt;p>Creates a instance for interacting with a client (socket)&lt;/p>
+<span class='line'>112</span> *
+<span class='line'>113</span> * &lt;p>Optional options object is the same that is passed to the parent
+<span class='line'>114</span> * {@link RAIServer} object&lt;/p>
+<span class='line'>115</span> *
+<span class='line'>116</span> * &lt;p>&lt;b>Events&lt;/b>&lt;/p>
+<span class='line'>117</span> *
+<span class='line'>118</span> * &lt;ul>
+<span class='line'>119</span> * &lt;li>&lt;b>'command'&lt;/b> - emitted if a client sends a command. Gets two
+<span class='line'>120</span> * params - command (String) and payload (Buffer)&lt;/li>
+<span class='line'>121</span> * &lt;li>&lt;b>'data'&lt;/b> - emitted when a chunk is received in data mode, the
+<span class='line'>122</span> * param being the payload (Buffer)&lt;/li>
+<span class='line'>123</span> * &lt;li>&lt;b>'ready'&lt;/b> - emitted when data stream ends and normal command
+<span class='line'>124</span> * flow is recovered&lt;/li>
+<span class='line'>125</span> * &lt;li>&lt;b>'tls'&lt;/b> - emitted when the connection is secured by TLS&lt;/li>
+<span class='line'>126</span> * &lt;li>&lt;b>'error'&lt;/b> - emitted when an error occurs. Connection to the
+<span class='line'>127</span> * client is disconnected automatically. Param is an error object.&lt;/l>
+<span class='line'>128</span> * &lt;li>&lt;b>'timeout'&lt;/b> - emitted when a timeout occurs. Connection to the
+<span class='line'>129</span> * client is disconnected automatically.&lt;/l>
+<span class='line'>130</span> * &lt;li>&lt;b>'end'&lt;/b> - emitted when the client disconnects&lt;/l>
+<span class='line'>131</span> * &lt;/ul>
+<span class='line'>132</span> *
+<span class='line'>133</span> * @constructor
+<span class='line'>134</span> * @param {Object} socket Socket for the client
+<span class='line'>135</span> * @param {Object} [options] Optional options object
+<span class='line'>136</span> */</span><span class="WHIT">
+<span class='line'>137</span> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">RAISocket</span><span class="PUNC">(</span><span class="NAME">socket</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">options</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>138</span> </span><span class="WHIT"> </span><span class="NAME">EventEmitter.call</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>139</span> </span><span class="WHIT">
+<span class='line'>140</span> </span><span class="NAME">this.socket</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">socket</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>141</span> </span><span class="WHIT"> </span><span class="NAME">this.options</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">options</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="TOKN"> </span><span class="PUNC">{</span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>142</span> </span><span class="WHIT">
+<span class='line'>143</span> </span><span class="NAME">this.remoteAddress</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">socket.remoteAddress</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>144</span> </span><span class="WHIT">
+<span class='line'>145</span> </span><span class="NAME">this._dataMode</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>146</span> </span><span class="WHIT"> </span><span class="NAME">this._endDataModeSequence</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="REGX">/\r\n\.\r\n|^\.\r\n/</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>147</span> </span><span class="WHIT">
+<span class='line'>148</span> </span><span class="NAME">this._secureConnection</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>149</span> </span><span class="WHIT"> </span><span class="NAME">this._destroyed</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>150</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>151</span> </span><span class="WHIT">
+<span class='line'>152</span> </span><span class="NAME">this._ignore_data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>153</span> </span><span class="WHIT">
+<span class='line'>154</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.timeout</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>155</span> </span><span class="WHIT"> </span><span class="NAME">socket.setTimeout</span><span class="PUNC">(</span><span class="NAME">this.options.timeout</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>156</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>157</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>158</span> </span><span class="NAME">utillib.inherits</span><span class="PUNC">(</span><span class="NAME">RAISocket</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">EventEmitter</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>159</span>
+<span class='line'>160</span> </span><span class="COMM">/**
+<span class='line'>161</span> * &lt;p>Sends some data to the client. &lt;CR>&lt;LF> is automatically appended to
+<span class='line'>162</span> * the data&lt;/p>
+<span class='line'>163</span> *
+<span class='line'>164</span> * @param {String|Buffer} data Data to be sent to the client
+<span class='line'>165</span> */</span><span class="WHIT">
+<span class='line'>166</span> </span><span class="NAME">RAISocket.prototype.send</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">data</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>167</span> </span><span class="WHIT"> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">buffer</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>168</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">data</span><span class="WHIT"> </span><span class="KEYW">instanceof</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="TOKN"> </span><span class="PUNC">(</span><span class="KEYW">typeof</span><span class="WHIT"> </span><span class="NAME">SlowBuffer</span><span class="WHIT"> </span><span class="PUNC">!=</span><span class="WHIT"> </span><span class="STRN">"undefined"</span><span class="WHIT"> </span><span class="PUNC">&&</span><span class="WHIT"> </span><span class="NAME">data</span><span class="WHIT"> </span><span class="KEYW">instanceof</span><span class="WHIT"> </span><span class="NAME">SlowBuffer</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>169</span> </span><span class="WHIT"> </span><span class="NAME">buffer</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="PUNC">(</span><span class="NAME">data.length</span><span class="PUNC">+</span><span class="NUMB">2</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>170</span> </span><span class="WHIT"> </span><span class="NAME">buffer</span><span class="PUNC">[</span><span class="NAME">buffer.length</span><span class="PUNC">-</span><span class="NUMB">2</span><span class="PUNC">]</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NUMB">0xD</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>171</span> </span><span class="WHIT"> </span><span class="NAME">buffer</span><span class="PUNC">[</span><span class="NAME">buffer.length</span><span class="PUNC">-</span><span class="NUMB">1</span><span class="PUNC">]</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NUMB">0xA</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>172</span> </span><span class="WHIT"> </span><span class="NAME">data.copy</span><span class="PUNC">(</span><span class="NAME">buffer</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>173</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>174</span> </span><span class="WHIT"> </span><span class="NAME">buffer</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="PUNC">(</span><span class="PUNC">(</span><span class="NAME">data</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="TOKN"> </span><span class="STRN">""</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">toString</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">+</span><span class="STRN">"\r\n"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"binary"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>175</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>176</span> </span><span class="WHIT">
+<span class='line'>177</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>178</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"OUT: \""</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="NAME">buffer.toString</span><span class="PUNC">(</span><span class="STRN">"utf-8"</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">trim</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">+</span><span class="STRN">"\""</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>179</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>180</span> </span><span class="WHIT">
+<span class='line'>181</span> </span><span class="NAME">this.socket.write</span><span class="PUNC">(</span><span class="NAME">buffer</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>182</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>183</span>
+<span class='line'>184</span> </span><span class="COMM">/**
+<span class='line'>185</span> * &lt;p>Instructs the server to be listening for mixed data instead of line based
+<span class='line'>186</span> * commands&lt;/p>
+<span class='line'>187</span> *
+<span class='line'>188</span> * @param {String|RegExp} [sequence="\r\n.\r\n"] - optional sequence for
+<span class='line'>189</span> * matching the data end
+<span class='line'>190</span> */</span><span class="WHIT">
+<span class='line'>191</span> </span><span class="NAME">RAISocket.prototype.startDataMode</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">sequence</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>192</span> </span><span class="WHIT"> </span><span class="NAME">this._dataMode</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>193</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">sequence</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>194</span> </span><span class="WHIT"> </span><span class="NAME">this._endDataModeSequence</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">typeof</span><span class="WHIT"> </span><span class="NAME">sequence</span><span class="WHIT"> </span><span class="PUNC">==</span><span class="WHIT"> </span><span class="STRN">"string"</span><span class="WHIT"> </span><span class="PUNC">?</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">RegExp</span><span class="PUNC">(</span><span class="NAME">sequence</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">:</span><span class="WHIT"> </span><span class="NAME">sequence</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>195</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>196</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>197</span>
+<span class='line'>198</span> </span><span class="COMM">/**
+<span class='line'>199</span> * &lt;p>Instructs the server to upgrade the connection to secure TLS connection&lt;/p>
+<span class='line'>200</span> *
+<span class='line'>201</span> * &lt;p>Emits &lt;code>'tls'&lt;/code> on successful upgrade&lt;/p>
+<span class='line'>202</span> *
+<span class='line'>203</span> * @param {Object} [credentials] - An object with PEM encoded key and
+<span class='line'>204</span> * certificate &lt;code>{key:"---BEGIN...", cert:"---BEGIN..."}&lt;/code>,
+<span class='line'>205</span> * if not set autogenerated values will be used.
+<span class='line'>206</span> */</span><span class="WHIT">
+<span class='line'>207</span> </span><span class="NAME">RAISocket.prototype.startTLS</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">credentials</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>208</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this._secureConnection</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>209</span> </span><span class="WHIT"> </span><span class="NAME">this._onError</span><span class="PUNC">(</span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Error</span><span class="PUNC">(</span><span class="STRN">"Secure connection already established"</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>210</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>211</span> </span><span class="WHIT">
+<span class='line'>212</span> </span><span class="NAME">credentials</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">credentials</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="WHIT"> </span><span class="NAME">defaultCredentials</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>213</span> </span><span class="WHIT">
+<span class='line'>214</span> </span><span class="NAME">this._ignore_data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>215</span> </span><span class="WHIT">
+<span class='line'>216</span> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">secure_connector</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">starttls</span><span class="PUNC">(</span><span class="NAME">this.socket</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">credentials</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">ssl_socket</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>217</span>
+<span class='line'>218</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="WHIT"> </span><span class="PUNC">&&</span><span class="WHIT"> </span><span class="PUNC">!</span><span class="NAME">ssl_socket.authorized</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>219</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"WARNING: TLS ERROR ("</span><span class="PUNC">+</span><span class="NAME">ssl_socket.authorizationError</span><span class="PUNC">+</span><span class="STRN">")"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>220</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>221</span> </span><span class="WHIT">
+<span class='line'>222</span> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>223</span> </span><span class="WHIT"> </span><span class="NAME">this._ignore_data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>224</span> </span><span class="WHIT">
+<span class='line'>225</span> </span><span class="NAME">this._secureConnection</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>226</span> </span><span class="WHIT">
+<span class='line'>227</span> </span><span class="NAME">this.socket</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">ssl_socket</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>228</span> </span><span class="WHIT"> </span><span class="NAME">this.socket.on</span><span class="PUNC">(</span><span class="STRN">"data"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">this._onReceiveData.bind</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>229</span> </span><span class="WHIT">
+<span class='line'>230</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>231</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"TLS CONNECTION STARTED"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>232</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>233</span> </span><span class="WHIT">
+<span class='line'>234</span> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"tls"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>235</span> </span><span class="WHIT">
+<span class='line'>236</span> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">bind</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>237</span> </span><span class="WHIT">
+<span class='line'>238</span> </span><span class="NAME">secure_connector.on</span><span class="PUNC">(</span><span class="STRN">"error"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>239</span> </span><span class="WHIT"> </span><span class="NAME">this._onError</span><span class="PUNC">(</span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>240</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">bind</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>241</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>242</span>
+<span class='line'>243</span> </span><span class="COMM">/**
+<span class='line'>244</span> * &lt;p>Closes the connection to the client&lt;/p>
+<span class='line'>245</span> */</span><span class="WHIT">
+<span class='line'>246</span> </span><span class="NAME">RAISocket.prototype.end</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>247</span> </span><span class="WHIT"> </span><span class="NAME">this.socket.end</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>248</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>249</span>
+<span class='line'>250</span> </span><span class="COMM">/**
+<span class='line'>251</span> * &lt;p>Called when a chunk of data arrives from the client. If currently in data
+<span class='line'>252</span> * mode, transmit the data otherwise send it to &lt;code>_processData&lt;/code>&lt;/p>
+<span class='line'>253</span> *
+<span class='line'>254</span> * @param {Buffer|String} chunk Data sent by the client
+<span class='line'>255</span> */</span><span class="WHIT">
+<span class='line'>256</span> </span><span class="NAME">RAISocket.prototype._onReceiveData</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">chunk</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>257</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this._ignore_data</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT"> </span><span class="COMM">// if currently setting up TLS connection</span><span class="WHIT">
+<span class='line'>258</span> </span><span class="WHIT"> </span><span class="KEYW">return</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>259</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>260</span> </span><span class="WHIT">
+<span class='line'>261</span> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">str</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">typeof</span><span class="WHIT"> </span><span class="NAME">chunk</span><span class="PUNC">==</span><span class="STRN">"string"</span><span class="PUNC">?</span><span class="NAME">chunk</span><span class="PUNC">:</span><span class="NAME">chunk.toString</span><span class="PUNC">(</span><span class="STRN">"binary"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'>262</span> </span><span class="WHIT"> </span><span class="NAME">dataEndMatch</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">dataRemainderMatch</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">data</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>263</span> </span><span class="WHIT">
+<span class='line'>264</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this._dataMode</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>265</span> </span><span class="WHIT">
+<span class='line'>266</span> </span><span class="NAME">str</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="WHIT"> </span><span class="NAME">str</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>267</span> </span><span class="WHIT">
+<span class='line'>268</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">dataEndMatch</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">str.match</span><span class="PUNC">(</span><span class="REGX">/\r\n.*?$/</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>269</span> </span><span class="WHIT"> </span><span class="COMM">// if theres a line that is not ended, keep it for later</span><span class="WHIT">
+<span class='line'>270</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">str.substr</span><span class="PUNC">(</span><span class="NAME">dataEndMatch.index</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>271</span> </span><span class="WHIT"> </span><span class="NAME">str</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">str.substr</span><span class="PUNC">(</span><span class="NUMB">0</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">dataEndMatch.index</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>272</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>273</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>274</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>275</span> </span><span class="WHIT">
+<span class='line'>276</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">(</span><span class="NAME">dataRemainderMatch</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="NAME">str</span><span class="PUNC">+</span><span class="NAME">this._remainder</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">match</span><span class="PUNC">(</span><span class="NAME">this._endDataModeSequence</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>277</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">dataRemainderMatch.index</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>278</span> </span><span class="WHIT"> </span><span class="NAME">data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="PUNC">(</span><span class="PUNC">(</span><span class="NAME">str</span><span class="PUNC">+</span><span class="NAME">this._remainder</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">substr</span><span class="PUNC">(</span><span class="NUMB">0</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">dataRemainderMatch.index</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"binary"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>279</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>280</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"DATA:"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">data.toString</span><span class="PUNC">(</span><span class="STRN">"utf-8"</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>281</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>282</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"data"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">data</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>283</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>284</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>285</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"ready"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>286</span> </span><span class="WHIT"> </span><span class="NAME">this._dataMode</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>287</span> </span><span class="WHIT">
+<span class='line'>288</span> </span><span class="COMM">// send the remaining data for processing</span><span class="WHIT">
+<span class='line'>289</span> </span><span class="WHIT"> </span><span class="NAME">this._processData</span><span class="PUNC">(</span><span class="NAME">str.substr</span><span class="PUNC">(</span><span class="NAME">dataRemainderMatch.index</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="WHIT"> </span><span class="NAME">dataRemainderMatch</span><span class="PUNC">[</span><span class="NUMB">0</span><span class="PUNC">]</span><span class="PUNC">.</span><span class="NAME">length</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>290</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>291</span> </span><span class="WHIT"> </span><span class="NAME">data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="PUNC">(</span><span class="NAME">str</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"binary"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>292</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>293</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"DATA:"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">data.toString</span><span class="PUNC">(</span><span class="STRN">"utf-8"</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>294</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>295</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"data"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">data</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>296</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>297</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>298</span> </span><span class="WHIT"> </span><span class="NAME">this._processData</span><span class="PUNC">(</span><span class="NAME">str</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>299</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>300</span> </span><span class="WHIT">
+<span class='line'>301</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>302</span>
+<span class='line'>303</span> </span><span class="COMM">/**
+<span class='line'>304</span> * &lt;p>Processed incoming command lines and emits found data as
+<span class='line'>305</span> * &lt;code>'command'&lt;/code> with the command name as the first param and the rest
+<span class='line'>306</span> * of the data as second (Buffer)&lt;/p>
+<span class='line'>307</span> *
+<span class='line'>308</span> * @param {String} str Binary string to be processed
+<span class='line'>309</span> */</span><span class="WHIT">
+<span class='line'>310</span> </span><span class="NAME">RAISocket.prototype._processData</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">str</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>311</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">!</span><span class="NAME">str.length</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>312</span> </span><span class="WHIT"> </span><span class="KEYW">return</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>313</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>314</span> </span><span class="WHIT"> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">lines</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="NAME">this._remainder</span><span class="PUNC">+</span><span class="NAME">str</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">split</span><span class="PUNC">(</span><span class="STRN">"\r\n"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'>315</span> </span><span class="WHIT"> </span><span class="NAME">match</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">command</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>316</span> </span><span class="WHIT">
+<span class='line'>317</span> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">lines.pop</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>318</span> </span><span class="WHIT">
+<span class='line'>319</span> </span><span class="KEYW">for</span><span class="PUNC">(</span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">i</span><span class="PUNC">=</span><span class="NUMB">0</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">len</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">lines.length</span><span class="PUNC">;</span><span class="WHIT"> </span><span class="NAME">i</span><span class="PUNC">&lt;</span><span class="NAME">len</span><span class="PUNC">;</span><span class="WHIT"> </span><span class="NAME">i</span><span class="PUNC">++</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>320</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">!</span><span class="NAME">this._dataMode</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>321</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">match</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">lines</span><span class="PUNC">[</span><span class="NAME">i</span><span class="PUNC">]</span><span class="PUNC">.</span><span class="NAME">match</span><span class="PUNC">(</span><span class="REGX">/\s*[\S]+\s?/</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>322</span> </span><span class="WHIT"> </span><span class="NAME">command</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="NAME">match</span><span class="PUNC">[</span><span class="NUMB">0</span><span class="PUNC">]</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">trim</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>323</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>324</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"COMMAND:"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">lines</span><span class="PUNC">[</span><span class="NAME">i</span><span class="PUNC">]</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>325</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>326</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"command"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">command</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="PUNC">(</span><span class="NAME">lines</span><span class="PUNC">[</span><span class="NAME">i</span><span class="PUNC">]</span><span class="PUNC">.</span><span class="NAME">substr</span><span class="PUNC">(</span><span class="NAME">match.index</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="WHIT"> </span><span class="NAME">match</span><span class="PUNC">[</span><span class="NUMB">0</span><span class="PUNC">]</span><span class="PUNC">.</span><span class="NAME">length</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"binary"</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>327</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>328</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>329</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this._remainder</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>330</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">"\r\n"</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>331</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>332</span> </span><span class="WHIT"> </span><span class="NAME">this._onReceiveData</span><span class="PUNC">(</span><span class="NAME">lines.slice</span><span class="PUNC">(</span><span class="NAME">i</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">join</span><span class="PUNC">(</span><span class="STRN">"\r\n"</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>333</span> </span><span class="WHIT"> </span><span class="KEYW">break</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>334</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>335</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>336</span> </span><span class="WHIT">
+<span class='line'>337</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>338</span>
+<span class='line'>339</span> </span><span class="COMM">/**
+<span class='line'>340</span> * &lt;p>Called when the connection is or is going to be ended&lt;/p>
+<span class='line'>341</span> */</span><span class="WHIT">
+<span class='line'>342</span> </span><span class="NAME">RAISocket.prototype._destroy</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>343</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this._destroyed</span><span class="PUNC">)</span><span class="KEYW">return</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>344</span> </span><span class="WHIT"> </span><span class="NAME">this._destroyed</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>345</span> </span><span class="WHIT">
+<span class='line'>346</span> </span><span class="NAME">this.removeAllListeners</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>347</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>348</span>
+<span class='line'>349</span> </span><span class="COMM">/**
+<span class='line'>350</span> * &lt;p>Called when the connection is ended. Emits &lt;code>'end'&lt;/code>&lt;/p>
+<span class='line'>351</span> */</span><span class="WHIT">
+<span class='line'>352</span> </span><span class="NAME">RAISocket.prototype._onEnd</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>353</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"end"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>354</span> </span><span class="WHIT"> </span><span class="NAME">this._destroy</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>355</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>356</span>
+<span class='line'>357</span> </span><span class="COMM">/**
+<span class='line'>358</span> * &lt;p>Called when an error has appeared. Emits &lt;code>'error'&lt;/code> with
+<span class='line'>359</span> * the error object as a parameter.&lt;/p>
+<span class='line'>360</span> *
+<span class='line'>361</span> * @param {Object} err Error object
+<span class='line'>362</span> */</span><span class="WHIT">
+<span class='line'>363</span> </span><span class="NAME">RAISocket.prototype._onError</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>364</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"error"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>365</span> </span><span class="WHIT"> </span><span class="NAME">this._destroy</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>366</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>367</span>
+<span class='line'>368</span> </span><span class="COMM">/**
+<span class='line'>369</span> * &lt;p>Called when a timeout has occured. Connection will be closed and
+<span class='line'>370</span> * &lt;code>'timeout'&lt;/code> is emitted.&lt;/p>
+<span class='line'>371</span> */</span><span class="WHIT">
+<span class='line'>372</span> </span><span class="NAME">RAISocket.prototype._onTimeout</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>373</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.socket</span><span class="WHIT"> </span><span class="PUNC">&&</span><span class="WHIT"> </span><span class="PUNC">!</span><span class="NAME">this.socket.destroyed</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>374</span> </span><span class="WHIT"> </span><span class="NAME">this.socket.end</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>375</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>376</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"timeout"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>377</span> </span><span class="WHIT"> </span><span class="NAME">this._destroy</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>378</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>379</span>
+<span class='line'>380</span> </span><span class="COMM">/**
+<span class='line'>381</span> * &lt;p>Called when the connection is closed&lt;/p>
+<span class='line'>382</span> *
+<span class='line'>383</span> * @param {Boolean} hadError did the connection end because of an error?
+<span class='line'>384</span> */</span><span class="WHIT">
+<span class='line'>385</span> </span><span class="NAME">RAISocket.prototype._onClose</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">hadError</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>386</span> </span><span class="WHIT"> </span><span class="NAME">this._destroy</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>387</span> </span><span class="PUNC">}</span></pre></body></html> \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_mockup.js.html b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_mockup.js.html
new file mode 100644
index 0000000..2690ce4
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_mockup.js.html
@@ -0,0 +1,110 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"> <style>
+ .KEYW {color: #933;}
+ .COMM {color: #bbb; font-style: italic;}
+ .NUMB {color: #393;}
+ .STRN {color: #393;}
+ .REGX {color: #339;}
+ .line {border-right: 1px dotted #666; color: #666; font-style: normal;}
+ </style></head><body><pre><span class='line'> 1</span> <span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">net</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"net"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 2</span> </span><span class="WHIT"> </span><span class="NAME">crypto</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"crypto"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 3</span> </span><span class="WHIT"> </span><span class="NAME">tlslib</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"tls"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 4</span>
+<span class='line'> 5</span> </span><span class="COMM">/**
+<span class='line'> 6</span> * @namespace Mockup module
+<span class='line'> 7</span> * @name mockup
+<span class='line'> 8</span> */</span><span class="WHIT">
+<span class='line'> 9</span> </span><span class="NAME">module.exports</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">runClientMockup</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 10</span>
+<span class='line'> 11</span> </span><span class="COMM">/**
+<span class='line'> 12</span> * &lt;p>Runs a batch of commands against a server&lt;/p>
+<span class='line'> 13</span> *
+<span class='line'> 14</span> * &lt;pre>
+<span class='line'> 15</span> * var cmds = ["EHLO FOOBAR", "STARTTLS", "QUIT"];
+<span class='line'> 16</span> * runClientMockup(25, "mail.hot.ee", cmds, function(resp){
+<span class='line'> 17</span> * console.log("Final:", resp.toString("utf-8").trim());
+<span class='line'> 18</span> * });
+<span class='line'> 19</span> * &lt;/pre>
+<span class='line'> 20</span> *
+<span class='line'> 21</span> * @memberOf mockup
+<span class='line'> 22</span> * @param {Number} port Port number
+<span class='line'> 23</span> * @param {String} host Hostname to connect to
+<span class='line'> 24</span> * @param {Array} commands Command list to be sent to server
+<span class='line'> 25</span> * @param {Function} callback Callback function to run on completion,
+<span class='line'> 26</span> * has the last response from the server as a param
+<span class='line'> 27</span> * @param {Boolean} [debug] if set to true log all input/output
+<span class='line'> 28</span> */</span><span class="WHIT">
+<span class='line'> 29</span> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">runClientMockup</span><span class="PUNC">(</span><span class="NAME">port</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">host</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">commands</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 30</span> </span><span class="WHIT"> </span><span class="NAME">host</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">host</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="TOKN"> </span><span class="STRN">"localhost"</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 31</span> </span><span class="WHIT"> </span><span class="NAME">port</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">port</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="TOKN"> </span><span class="NUMB">25</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 32</span> </span><span class="WHIT"> </span><span class="NAME">commands</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">Array.isArray</span><span class="PUNC">(</span><span class="NAME">commands</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">?</span><span class="WHIT"> </span><span class="NAME">commands</span><span class="WHIT"> </span><span class="PUNC">:</span><span class="WHIT"> </span><span class="PUNC">[</span><span class="PUNC">]</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 33</span>
+<span class='line'> 34</span> </span><span class="WHIT"> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">command</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">ignore_data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">sslcontext</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">pair</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 35</span>
+<span class='line'> 36</span> </span><span class="WHIT"> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">socket</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">net.connect</span><span class="PUNC">(</span><span class="NAME">port</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">host</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 37</span> </span><span class="WHIT"> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">"data"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">chunk</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 38</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">ignore_data</span><span class="PUNC">)</span><span class="KEYW">return</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 39</span> </span><span class="WHIT">
+<span class='line'> 40</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 41</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"S: "</span><span class="PUNC">+</span><span class="NAME">chunk.toString</span><span class="PUNC">(</span><span class="STRN">"utf-8"</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">trim</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 42</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 43</span> </span><span class="WHIT">
+<span class='line'> 44</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">!</span><span class="NAME">commands.length</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 45</span> </span><span class="WHIT"> </span><span class="NAME">socket.end</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 46</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="KEYW">typeof</span><span class="WHIT"> </span><span class="NAME">callback</span><span class="WHIT"> </span><span class="PUNC">==</span><span class="WHIT"> </span><span class="STRN">"function"</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 47</span> </span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">(</span><span class="NAME">chunk</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 48</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 49</span> </span><span class="WHIT"> </span><span class="KEYW">return</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 50</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 51</span> </span><span class="WHIT">
+<span class='line'> 52</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">[</span><span class="STRN">"STARTTLS"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"STLS"</span><span class="PUNC">]</span><span class="PUNC">.</span><span class="NAME">indexOf</span><span class="PUNC">(</span><span class="PUNC">(</span><span class="NAME">command</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">trim</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">toUpperCase</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">>=</span><span class="NUMB">0</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 53</span> </span><span class="WHIT"> </span><span class="NAME">ignore_data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 54</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 55</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"Initiated TLS connection"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 56</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 57</span> </span><span class="WHIT"> </span><span class="NAME">sslcontext</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">crypto.createCredentials</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 58</span> </span><span class="WHIT"> </span><span class="NAME">pair</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">tlslib.createSecurePair</span><span class="PUNC">(</span><span class="NAME">sslcontext</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 59</span> </span><span class="WHIT">
+<span class='line'> 60</span> </span><span class="NAME">pair.encrypted.pipe</span><span class="PUNC">(</span><span class="NAME">socket</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 61</span> </span><span class="WHIT"> </span><span class="NAME">socket.pipe</span><span class="PUNC">(</span><span class="NAME">pair.encrypted</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 62</span> </span><span class="WHIT"> </span><span class="NAME">pair.fd</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">socket.fd</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 63</span> </span><span class="WHIT">
+<span class='line'> 64</span> </span><span class="NAME">pair.on</span><span class="PUNC">(</span><span class="STRN">"secure"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 65</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 66</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"TLS connection secured"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 67</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 68</span> </span><span class="WHIT"> </span><span class="NAME">command</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">commands.shift</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 69</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 70</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"C: "</span><span class="PUNC">+</span><span class="NAME">command</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 71</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 72</span> </span><span class="WHIT"> </span><span class="NAME">pair.cleartext.write</span><span class="PUNC">(</span><span class="NAME">command</span><span class="PUNC">+</span><span class="STRN">"\r\n"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 73</span>
+<span class='line'> 74</span> </span><span class="WHIT"> </span><span class="NAME">pair.cleartext.on</span><span class="PUNC">(</span><span class="STRN">"data"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">chunk</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 75</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 76</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"S: "</span><span class="PUNC">+</span><span class="NAME">chunk.toString</span><span class="PUNC">(</span><span class="STRN">"utf-8"</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">trim</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 77</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 78</span> </span><span class="WHIT">
+<span class='line'> 79</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">!</span><span class="NAME">commands.length</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 80</span> </span><span class="WHIT"> </span><span class="NAME">pair.cleartext.end</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 81</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="KEYW">typeof</span><span class="WHIT"> </span><span class="NAME">callback</span><span class="WHIT"> </span><span class="PUNC">==</span><span class="WHIT"> </span><span class="STRN">"function"</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 82</span> </span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">(</span><span class="NAME">chunk</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 83</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 84</span> </span><span class="WHIT"> </span><span class="KEYW">return</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 85</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 86</span> </span><span class="WHIT"> </span><span class="NAME">command</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">commands.shift</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 87</span> </span><span class="WHIT"> </span><span class="NAME">pair.cleartext.write</span><span class="PUNC">(</span><span class="NAME">command</span><span class="PUNC">+</span><span class="STRN">"\r\n"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 88</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 89</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"C: "</span><span class="PUNC">+</span><span class="NAME">command</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 90</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 91</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 92</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 93</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 94</span> </span><span class="WHIT"> </span><span class="NAME">command</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">commands.shift</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 95</span> </span><span class="WHIT"> </span><span class="NAME">socket.write</span><span class="PUNC">(</span><span class="NAME">command</span><span class="PUNC">+</span><span class="STRN">"\r\n"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 96</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 97</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"C: "</span><span class="PUNC">+</span><span class="NAME">command</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 98</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 99</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>100</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>101</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>102</span> </span><span class="WHIT">
+<span class='line'>103</span> </span><span class="PUNC">}</span></pre></body></html> \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_rai.js.html b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_rai.js.html
new file mode 100644
index 0000000..4e12b24
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_rai.js.html
@@ -0,0 +1,484 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"> <style>
+ .KEYW {color: #933;}
+ .COMM {color: #bbb; font-style: italic;}
+ .NUMB {color: #393;}
+ .STRN {color: #393;}
+ .REGX {color: #339;}
+ .line {border-right: 1px dotted #666; color: #666; font-style: normal;}
+ </style></head><body><pre><span class='line'> 1</span> <span class="COMM">/**
+<span class='line'> 2</span> * @fileOverview This is the main file for the RAI library to create text based servers
+<span class='line'> 3</span> * @author &lt;a href="mailto:andris@node.ee">Andris Reinman&lt;/a>
+<span class='line'> 4</span> * @version 0.1.3
+<span class='line'> 5</span> */</span><span class="WHIT">
+<span class='line'> 6</span>
+<span class='line'> 7</span> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">netlib</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"net"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 8</span> </span><span class="WHIT"> </span><span class="NAME">utillib</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"util"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 9</span> </span><span class="WHIT"> </span><span class="NAME">EventEmitter</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">'events'</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">EventEmitter</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 10</span> </span><span class="WHIT"> </span><span class="NAME">starttls</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"./starttls"</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">starttls</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 11</span> </span><span class="WHIT"> </span><span class="NAME">tlslib</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"tls"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 12</span> </span><span class="WHIT"> </span><span class="NAME">crypto</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"crypto"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 13</span> </span><span class="WHIT"> </span><span class="NAME">fs</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"fs"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 14</span>
+<span class='line'> 15</span> </span><span class="COMM">// Default credentials for starting TLS server</span><span class="WHIT">
+<span class='line'> 16</span> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">defaultCredentials</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 17</span> </span><span class="WHIT"> </span><span class="NAME">key</span><span class="PUNC">:</span><span class="WHIT"> </span><span class="NAME">fs.readFileSync</span><span class="PUNC">(</span><span class="NAME">__dirname</span><span class="PUNC">+</span><span class="STRN">"/../cert/key.pem"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'> 18</span> </span><span class="WHIT"> </span><span class="NAME">cert</span><span class="PUNC">:</span><span class="WHIT"> </span><span class="NAME">fs.readFileSync</span><span class="PUNC">(</span><span class="NAME">__dirname</span><span class="PUNC">+</span><span class="STRN">"/../cert/cert.pem"</span><span class="PUNC">)</span><span class="WHIT">
+<span class='line'> 19</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 20</span>
+<span class='line'> 21</span> </span><span class="COMM">// Expose to the world</span><span class="WHIT">
+<span class='line'> 22</span> </span><span class="NAME">module.exports.RAIServer</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">RAIServer</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 23</span> </span><span class="NAME">module.exports.runClientMockup</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">"./mockup"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 24</span>
+<span class='line'> 25</span> </span><span class="COMM">/**
+<span class='line'> 26</span> * &lt;p>Creates instance of RAIServer&lt;/p>
+<span class='line'> 27</span> *
+<span class='line'> 28</span> * &lt;p>Options object has the following properties:&lt;/p>
+<span class='line'> 29</span> *
+<span class='line'> 30</span> * &lt;ul>
+<span class='line'> 31</span> * &lt;li>&lt;b>debug&lt;/b> - if set to true print traffic to console&lt;/li>
+<span class='line'> 32</span> * &lt;li>&lt;b>disconnectOnTimeout&lt;/b> - if set to true close the connection on disconnect&lt;/li>
+<span class='line'> 33</span> * &lt;li>&lt;b>timeout&lt;/b> - timeout in milliseconds for disconnecting the client,
+<span class='line'> 34</span> * defaults to 0 (no timeout)&lt;/li>
+<span class='line'> 35</span> * &lt;/ul>
+<span class='line'> 36</span> *
+<span class='line'> 37</span> * &lt;p>&lt;b>Events&lt;/b>&lt;/p>
+<span class='line'> 38</span> *
+<span class='line'> 39</span> * &lt;ul>
+<span class='line'> 40</span> * &lt;li>&lt;b>'connect'&lt;/b> - emitted if a client connects to the server, param
+<span class='line'> 41</span> * is a client ({@link RAISocket}) object&lt;/li>
+<span class='line'> 42</span> * &lt;li>&lt;b>'error'&lt;/b> - emitted on error, has an error object as a param&lt;/li>
+<span class='line'> 43</span> * &lt;/ul>
+<span class='line'> 44</span> *
+<span class='line'> 45</span> * @constructor
+<span class='line'> 46</span> * @param {Object} [options] Optional options object
+<span class='line'> 47</span> */</span><span class="WHIT">
+<span class='line'> 48</span> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">RAIServer</span><span class="PUNC">(</span><span class="NAME">options</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 49</span> </span><span class="WHIT"> </span><span class="NAME">EventEmitter.call</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 50</span> </span><span class="WHIT">
+<span class='line'> 51</span> </span><span class="NAME">this.options</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">options</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 52</span> </span><span class="WHIT">
+<span class='line'> 53</span> </span><span class="NAME">this._createServer</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 54</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 55</span> </span><span class="NAME">utillib.inherits</span><span class="PUNC">(</span><span class="NAME">RAIServer</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">EventEmitter</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 56</span>
+<span class='line'> 57</span> </span><span class="COMM">/**
+<span class='line'> 58</span> * &lt;p>Starts listening on selected port&lt;/p>
+<span class='line'> 59</span> *
+<span class='line'> 60</span> * @param {Number} port The port to listen
+<span class='line'> 61</span> * @param {String} [host] The IP address to listen
+<span class='line'> 62</span> * @param {Function} callback The callback function to be run after the server
+<span class='line'> 63</span> * is listening, the only param is an error message if the operation failed
+<span class='line'> 64</span> */</span><span class="WHIT">
+<span class='line'> 65</span> </span><span class="NAME">RAIServer.prototype.listen</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">port</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">host</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 66</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">!</span><span class="NAME">callback</span><span class="WHIT"> </span><span class="PUNC">&&</span><span class="WHIT"> </span><span class="KEYW">typeof</span><span class="WHIT"> </span><span class="NAME">host</span><span class="PUNC">==</span><span class="STRN">"function"</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 67</span> </span><span class="WHIT"> </span><span class="NAME">callback</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">host</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 68</span> </span><span class="WHIT"> </span><span class="NAME">host</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">undefined</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 69</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 70</span> </span><span class="WHIT"> </span><span class="NAME">this._port</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">port</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 71</span> </span><span class="WHIT"> </span><span class="NAME">this._host</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">host</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 72</span> </span><span class="WHIT">
+<span class='line'> 73</span> </span><span class="NAME">this._connected</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 74</span> </span><span class="WHIT">
+<span class='line'> 75</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">callback</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 76</span> </span><span class="WHIT">
+<span class='line'> 77</span> </span><span class="NAME">this._server.on</span><span class="PUNC">(</span><span class="STRN">"listening"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 78</span> </span><span class="WHIT"> </span><span class="NAME">this._connected</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 79</span> </span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">(</span><span class="KEYW">null</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 80</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">bind</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 81</span> </span><span class="WHIT">
+<span class='line'> 82</span> </span><span class="NAME">this._server.on</span><span class="PUNC">(</span><span class="STRN">"error"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 83</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">!</span><span class="NAME">this._connected</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 84</span> </span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">(</span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 85</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 86</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">bind</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 87</span> </span><span class="WHIT">
+<span class='line'> 88</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 89</span> </span><span class="WHIT">
+<span class='line'> 90</span> </span><span class="NAME">this._server.listen</span><span class="PUNC">(</span><span class="NAME">this._port</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">this._host</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 91</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 92</span>
+<span class='line'> 93</span> </span><span class="COMM">/**
+<span class='line'> 94</span> * &lt;p>Stops the server&lt;/p>
+<span class='line'> 95</span> *
+<span class='line'> 96</span> * @param {Function} callback Is run when the server is closed
+<span class='line'> 97</span> */</span><span class="WHIT">
+<span class='line'> 98</span> </span><span class="NAME">RAIServer.prototype.end</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">callback</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 99</span> </span><span class="WHIT"> </span><span class="NAME">this._server.on</span><span class="PUNC">(</span><span class="STRN">"close"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>100</span> </span><span class="WHIT"> </span><span class="NAME">this._server.close</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>101</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>102</span>
+<span class='line'>103</span> </span><span class="COMM">/**
+<span class='line'>104</span> * &lt;p>Creates a server with listener callback&lt;/p>
+<span class='line'>105</span> */</span><span class="WHIT">
+<span class='line'>106</span> </span><span class="NAME">RAIServer.prototype._createServer</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>107</span> </span><span class="WHIT"> </span><span class="NAME">this._server</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">netlib.createServer</span><span class="PUNC">(</span><span class="NAME">this._serverListener.bind</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>108</span> </span><span class="WHIT"> </span><span class="NAME">this._server.on</span><span class="PUNC">(</span><span class="STRN">"error"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">this._onError.bind</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>109</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>110</span>
+<span class='line'>111</span> </span><span class="COMM">/**
+<span class='line'>112</span> * &lt;p>Listens for errors&lt;/p>
+<span class='line'>113</span> *
+<span class='line'>114</span> * @event
+<span class='line'>115</span> * @param {Object} err Error object
+<span class='line'>116</span> */</span><span class="WHIT">
+<span class='line'>117</span> </span><span class="NAME">RAIServer.prototype._onError</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>118</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this._connected</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>119</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"error"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>120</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>121</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>122</span>
+<span class='line'>123</span> </span><span class="COMM">/**
+<span class='line'>124</span> * &lt;p>Server listener that is run on client connection&lt;/p>
+<span class='line'>125</span> *
+<span class='line'>126</span> * &lt;p>{@link RAISocket} object instance is created based on the client socket
+<span class='line'>127</span> * and a &lt;code>'connection'&lt;/code> event is emitted&lt;/p>
+<span class='line'>128</span> *
+<span class='line'>129</span> * @param {Object} socket The socket to the client
+<span class='line'>130</span> */</span><span class="WHIT">
+<span class='line'>131</span> </span><span class="NAME">RAIServer.prototype._serverListener</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">socket</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>132</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>133</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"CONNECTION FROM "</span><span class="PUNC">+</span><span class="NAME">socket.remoteAddress</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>134</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>135</span> </span><span class="WHIT">
+<span class='line'>136</span> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">handler</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">RAISocket</span><span class="PUNC">(</span><span class="NAME">socket</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">this.options</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>137</span> </span><span class="WHIT">
+<span class='line'>138</span> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">"data"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler._onReceiveData.bind</span><span class="PUNC">(</span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>139</span> </span><span class="WHIT"> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">"end"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler._onEnd.bind</span><span class="PUNC">(</span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>140</span> </span><span class="WHIT"> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">"error"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler._onError.bind</span><span class="PUNC">(</span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>141</span> </span><span class="WHIT"> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">"timeout"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler._onTimeout.bind</span><span class="PUNC">(</span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>142</span> </span><span class="WHIT"> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">"close"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler._onClose.bind</span><span class="PUNC">(</span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>143</span>
+<span class='line'>144</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"connection"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>145</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>146</span>
+<span class='line'>147</span> </span><span class="COMM">/**
+<span class='line'>148</span> * &lt;p>Creates a instance for interacting with a client (socket)&lt;/p>
+<span class='line'>149</span> *
+<span class='line'>150</span> * &lt;p>Optional options object is the same that is passed to the parent
+<span class='line'>151</span> * {@link RAIServer} object&lt;/p>
+<span class='line'>152</span> *
+<span class='line'>153</span> * &lt;p>&lt;b>Events&lt;/b>&lt;/p>
+<span class='line'>154</span> *
+<span class='line'>155</span> * &lt;ul>
+<span class='line'>156</span> * &lt;li>&lt;b>'command'&lt;/b> - emitted if a client sends a command. Gets two
+<span class='line'>157</span> * params - command (String) and payload (Buffer)&lt;/li>
+<span class='line'>158</span> * &lt;li>&lt;b>'data'&lt;/b> - emitted when a chunk is received in data mode, the
+<span class='line'>159</span> * param being the payload (Buffer)&lt;/li>
+<span class='line'>160</span> * &lt;li>&lt;b>'ready'&lt;/b> - emitted when data stream ends and normal command
+<span class='line'>161</span> * flow is recovered&lt;/li>
+<span class='line'>162</span> * &lt;li>&lt;b>'tls'&lt;/b> - emitted when the connection is secured by TLS&lt;/li>
+<span class='line'>163</span> * &lt;li>&lt;b>'error'&lt;/b> - emitted when an error occurs. Connection to the
+<span class='line'>164</span> * client is disconnected automatically. Param is an error object.&lt;/l>
+<span class='line'>165</span> * &lt;li>&lt;b>'timeout'&lt;/b> - emitted when a timeout occurs. Connection to the
+<span class='line'>166</span> * client is disconnected automatically if disconnectOnTimeout option
+<span class='line'>167</span> * is set to true.&lt;/l>
+<span class='line'>168</span> * &lt;li>&lt;b>'end'&lt;/b> - emitted when the client disconnects&lt;/l>
+<span class='line'>169</span> * &lt;/ul>
+<span class='line'>170</span> *
+<span class='line'>171</span> * @constructor
+<span class='line'>172</span> * @param {Object} socket Socket for the client
+<span class='line'>173</span> * @param {Object} [options] Optional options object
+<span class='line'>174</span> */</span><span class="WHIT">
+<span class='line'>175</span> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">RAISocket</span><span class="PUNC">(</span><span class="NAME">socket</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">options</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>176</span> </span><span class="WHIT"> </span><span class="NAME">EventEmitter.call</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>177</span> </span><span class="WHIT">
+<span class='line'>178</span> </span><span class="NAME">this.socket</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">socket</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>179</span> </span><span class="WHIT"> </span><span class="NAME">this.options</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">options</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>180</span> </span><span class="WHIT">
+<span class='line'>181</span> </span><span class="NAME">this.remoteAddress</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">socket.remoteAddress</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>182</span> </span><span class="WHIT">
+<span class='line'>183</span> </span><span class="NAME">this._dataMode</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>184</span> </span><span class="WHIT"> </span><span class="NAME">this._endDataModeSequence</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">"\r\n.\r\n"</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>185</span> </span><span class="WHIT"> </span><span class="NAME">this._endDataModeSequenceRegEx</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="REGX">/\r\n\.\r\n|^\.\r\n/</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>186</span> </span><span class="WHIT">
+<span class='line'>187</span> </span><span class="NAME">this.secureConnection</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>188</span> </span><span class="WHIT"> </span><span class="NAME">this._destroyed</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>189</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>190</span> </span><span class="WHIT">
+<span class='line'>191</span> </span><span class="NAME">this._ignore_data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>192</span> </span><span class="WHIT">
+<span class='line'>193</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.timeout</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>194</span> </span><span class="WHIT"> </span><span class="NAME">socket.setTimeout</span><span class="PUNC">(</span><span class="NAME">this.options.timeout</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>195</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>196</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>197</span> </span><span class="NAME">utillib.inherits</span><span class="PUNC">(</span><span class="NAME">RAISocket</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">EventEmitter</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>198</span>
+<span class='line'>199</span> </span><span class="COMM">/**
+<span class='line'>200</span> * &lt;p>Sends some data to the client. &lt;code>&lt;CR&gt;&lt;LF&gt;&lt;/code> is automatically appended to
+<span class='line'>201</span> * the data&lt;/p>
+<span class='line'>202</span> *
+<span class='line'>203</span> * @param {String|Buffer} data Data to be sent to the client
+<span class='line'>204</span> */</span><span class="WHIT">
+<span class='line'>205</span> </span><span class="NAME">RAISocket.prototype.send</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">data</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>206</span> </span><span class="WHIT"> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">buffer</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>207</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">data</span><span class="WHIT"> </span><span class="KEYW">instanceof</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="KEYW">typeof</span><span class="WHIT"> </span><span class="NAME">SlowBuffer</span><span class="WHIT"> </span><span class="PUNC">!=</span><span class="WHIT"> </span><span class="STRN">"undefined"</span><span class="WHIT"> </span><span class="PUNC">&&</span><span class="WHIT"> </span><span class="NAME">data</span><span class="WHIT"> </span><span class="KEYW">instanceof</span><span class="WHIT"> </span><span class="NAME">SlowBuffer</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>208</span> </span><span class="WHIT"> </span><span class="NAME">buffer</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="PUNC">(</span><span class="NAME">data.length</span><span class="PUNC">+</span><span class="NUMB">2</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>209</span> </span><span class="WHIT"> </span><span class="NAME">buffer</span><span class="PUNC">[</span><span class="NAME">buffer.length</span><span class="PUNC">-</span><span class="NUMB">2</span><span class="PUNC">]</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NUMB">0xD</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>210</span> </span><span class="WHIT"> </span><span class="NAME">buffer</span><span class="PUNC">[</span><span class="NAME">buffer.length</span><span class="PUNC">-</span><span class="NUMB">1</span><span class="PUNC">]</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NUMB">0xA</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>211</span> </span><span class="WHIT"> </span><span class="NAME">data.copy</span><span class="PUNC">(</span><span class="NAME">buffer</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>212</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>213</span> </span><span class="WHIT"> </span><span class="NAME">buffer</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="PUNC">(</span><span class="PUNC">(</span><span class="NAME">data</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">toString</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">+</span><span class="STRN">"\r\n"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"binary"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>214</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>215</span> </span><span class="WHIT">
+<span class='line'>216</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>217</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"OUT: \""</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="NAME">buffer.toString</span><span class="PUNC">(</span><span class="STRN">"utf-8"</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">trim</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">+</span><span class="STRN">"\""</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>218</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>219</span> </span><span class="WHIT">
+<span class='line'>220</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.socket</span><span class="WHIT"> </span><span class="PUNC">&&</span><span class="WHIT"> </span><span class="NAME">this.socket.writable</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>221</span> </span><span class="WHIT"> </span><span class="NAME">this.socket.write</span><span class="PUNC">(</span><span class="NAME">buffer</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>222</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>223</span> </span><span class="WHIT"> </span><span class="NAME">this.socket.end</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>224</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>225</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>226</span>
+<span class='line'>227</span> </span><span class="COMM">/**
+<span class='line'>228</span> * &lt;p>Instructs the server to be listening for mixed data instead of line based
+<span class='line'>229</span> * commands&lt;/p>
+<span class='line'>230</span> *
+<span class='line'>231</span> * @param {String} [sequence="."] - optional sequence on separate line for
+<span class='line'>232</span> * matching the data end
+<span class='line'>233</span> */</span><span class="WHIT">
+<span class='line'>234</span> </span><span class="NAME">RAISocket.prototype.startDataMode</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">sequence</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>235</span> </span><span class="WHIT"> </span><span class="NAME">this._dataMode</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>236</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">sequence</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>237</span> </span><span class="WHIT"> </span><span class="NAME">sequence</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">sequence.replace</span><span class="PUNC">(</span><span class="REGX">/\.\=\(\)\-\?\*\\\[\]\^\+\:\|\,/g</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"\\$1"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>238</span> </span><span class="WHIT"> </span><span class="NAME">this._endDataModeSequence</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">"\r\n"</span><span class="PUNC">+</span><span class="NAME">sequence</span><span class="PUNC">+</span><span class="STRN">"\r\n"</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>239</span> </span><span class="WHIT"> </span><span class="NAME">this._endDataModeSequenceRegEx</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">RegExp</span><span class="PUNC">(</span><span class="STRN">"/\r\n"</span><span class="PUNC">+</span><span class="NAME">sequence</span><span class="PUNC">+</span><span class="STRN">"\r\n|^"</span><span class="PUNC">+</span><span class="NAME">sequence</span><span class="PUNC">+</span><span class="STRN">"\r\n/"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>240</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>241</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>242</span>
+<span class='line'>243</span> </span><span class="COMM">/**
+<span class='line'>244</span> * &lt;p>Instructs the server to upgrade the connection to secure TLS connection&lt;/p>
+<span class='line'>245</span> *
+<span class='line'>246</span> * &lt;p>Fires &lt;code>callback&lt;/code> on successful connection upgrade if set,
+<span class='line'>247</span> * otherwise emits &lt;code>'tls'&lt;/code>&lt;/p>
+<span class='line'>248</span> *
+<span class='line'>249</span> * @param {Object} [credentials] An object with PEM encoded key and
+<span class='line'>250</span> * certificate &lt;code>{key:"---BEGIN...", cert:"---BEGIN..."}&lt;/code>,
+<span class='line'>251</span> * if not set autogenerated values will be used.
+<span class='line'>252</span> * @param {Function} [callback] If calback is set fire it after successful connection
+<span class='line'>253</span> * upgrade, otherwise &lt;code>'tls'&lt;/code> is emitted
+<span class='line'>254</span> */</span><span class="WHIT">
+<span class='line'>255</span> </span><span class="NAME">RAISocket.prototype.startTLS</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">credentials</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>256</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.secureConnection</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>257</span> </span><span class="WHIT"> </span><span class="NAME">this._onError</span><span class="PUNC">(</span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Error</span><span class="PUNC">(</span><span class="STRN">"Secure connection already established"</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>258</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>259</span> </span><span class="WHIT">
+<span class='line'>260</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">!</span><span class="NAME">callback</span><span class="WHIT"> </span><span class="PUNC">&&</span><span class="WHIT"> </span><span class="KEYW">typeof</span><span class="WHIT"> </span><span class="NAME">credentials</span><span class="WHIT"> </span><span class="PUNC">==</span><span class="WHIT"> </span><span class="STRN">"function"</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>261</span> </span><span class="WHIT"> </span><span class="NAME">callback</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">credentials</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>262</span> </span><span class="WHIT"> </span><span class="NAME">credentials</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">undefined</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>263</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>264</span> </span><span class="WHIT">
+<span class='line'>265</span> </span><span class="NAME">credentials</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">credentials</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="WHIT"> </span><span class="NAME">defaultCredentials</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>266</span> </span><span class="WHIT">
+<span class='line'>267</span> </span><span class="NAME">this._ignore_data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>268</span> </span><span class="WHIT">
+<span class='line'>269</span> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">secure_connector</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">starttls</span><span class="PUNC">(</span><span class="NAME">this.socket</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">credentials</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">ssl_socket</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>270</span>
+<span class='line'>271</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="WHIT"> </span><span class="PUNC">&&</span><span class="WHIT"> </span><span class="PUNC">!</span><span class="NAME">ssl_socket.authorized</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>272</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"WARNING: TLS ERROR ("</span><span class="PUNC">+</span><span class="NAME">ssl_socket.authorizationError</span><span class="PUNC">+</span><span class="STRN">")"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>273</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>274</span> </span><span class="WHIT">
+<span class='line'>275</span> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>276</span> </span><span class="WHIT"> </span><span class="NAME">this._ignore_data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>277</span> </span><span class="WHIT">
+<span class='line'>278</span> </span><span class="NAME">this.secureConnection</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>279</span> </span><span class="WHIT">
+<span class='line'>280</span> </span><span class="NAME">this.socket</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">ssl_socket</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>281</span> </span><span class="WHIT"> </span><span class="NAME">this.socket.on</span><span class="PUNC">(</span><span class="STRN">"data"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">this._onReceiveData.bind</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>282</span> </span><span class="WHIT">
+<span class='line'>283</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>284</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"TLS CONNECTION STARTED"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>285</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>286</span> </span><span class="WHIT">
+<span class='line'>287</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">callback</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>288</span> </span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>289</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>290</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"tls"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>291</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>292</span> </span><span class="WHIT">
+<span class='line'>293</span> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">bind</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>294</span> </span><span class="WHIT">
+<span class='line'>295</span> </span><span class="NAME">secure_connector.on</span><span class="PUNC">(</span><span class="STRN">"error"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>296</span> </span><span class="WHIT"> </span><span class="NAME">this._onError</span><span class="PUNC">(</span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>297</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">bind</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>298</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>299</span>
+<span class='line'>300</span> </span><span class="COMM">/**
+<span class='line'>301</span> * &lt;p>Closes the connection to the client&lt;/p>
+<span class='line'>302</span> */</span><span class="WHIT">
+<span class='line'>303</span> </span><span class="NAME">RAISocket.prototype.end</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>304</span> </span><span class="WHIT"> </span><span class="NAME">this.socket.end</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>305</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>306</span>
+<span class='line'>307</span> </span><span class="COMM">/**
+<span class='line'>308</span> * &lt;p>Called when a chunk of data arrives from the client. If currently in data
+<span class='line'>309</span> * mode, transmit the data otherwise send it to &lt;code>_processData&lt;/code>&lt;/p>
+<span class='line'>310</span> *
+<span class='line'>311</span> * @event
+<span class='line'>312</span> * @param {Buffer|String} chunk Data sent by the client
+<span class='line'>313</span> */</span><span class="WHIT">
+<span class='line'>314</span> </span><span class="NAME">RAISocket.prototype._onReceiveData</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">chunk</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>315</span>
+<span class='line'>316</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this._ignore_data</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT"> </span><span class="COMM">// if currently setting up TLS connection</span><span class="WHIT">
+<span class='line'>317</span> </span><span class="WHIT"> </span><span class="KEYW">return</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>318</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>319</span> </span><span class="WHIT">
+<span class='line'>320</span> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">str</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">typeof</span><span class="WHIT"> </span><span class="NAME">chunk</span><span class="PUNC">==</span><span class="STRN">"string"</span><span class="PUNC">?</span><span class="NAME">chunk</span><span class="PUNC">:</span><span class="NAME">chunk.toString</span><span class="PUNC">(</span><span class="STRN">"binary"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'>321</span> </span><span class="WHIT"> </span><span class="NAME">dataEndMatch</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">dataRemainderMatch</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">data</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">match</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>322</span> </span><span class="WHIT">
+<span class='line'>323</span> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this._dataMode</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>324</span> </span><span class="WHIT">
+<span class='line'>325</span> </span><span class="NAME">str</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="WHIT"> </span><span class="NAME">str</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>326</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">(</span><span class="NAME">dataEndMatch</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">str.match</span><span class="PUNC">(</span><span class="REGX">/\r\n.*?$/</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>327</span> </span><span class="WHIT"> </span><span class="COMM">// if theres a line that is not ended, keep it for later</span><span class="WHIT">
+<span class='line'>328</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">str.substr</span><span class="PUNC">(</span><span class="NAME">dataEndMatch.index</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>329</span> </span><span class="WHIT"> </span><span class="NAME">str</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">str.substr</span><span class="PUNC">(</span><span class="NUMB">0</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">dataEndMatch.index</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>330</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>331</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>332</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>333</span>
+<span class='line'>334</span> </span><span class="WHIT"> </span><span class="COMM">// check if a data end sequence is found from the data</span><span class="WHIT">
+<span class='line'>335</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">(</span><span class="NAME">dataRemainderMatch</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="NAME">str</span><span class="PUNC">+</span><span class="NAME">this._remainder</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">match</span><span class="PUNC">(</span><span class="NAME">this._endDataModeSequenceRegEx</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>336</span> </span><span class="WHIT"> </span><span class="NAME">str</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">str</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>337</span> </span><span class="WHIT"> </span><span class="COMM">// if the sequence is not on byte 0 emit remaining data</span><span class="WHIT">
+<span class='line'>338</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">dataRemainderMatch.index</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>339</span> </span><span class="WHIT"> </span><span class="NAME">data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="PUNC">(</span><span class="NAME">str.substr</span><span class="PUNC">(</span><span class="NUMB">0</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">dataRemainderMatch.index</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"binary"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>340</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>341</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"DATA:"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">data.toString</span><span class="PUNC">(</span><span class="STRN">"utf-8"</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>342</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>343</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"data"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">data</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>344</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>345</span> </span><span class="WHIT"> </span><span class="COMM">// emit data ready</span><span class="WHIT">
+<span class='line'>346</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>347</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"ready"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>348</span> </span><span class="WHIT"> </span><span class="NAME">this._dataMode</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>349</span> </span><span class="WHIT"> </span><span class="COMM">// send the remaining data for processing</span><span class="WHIT">
+<span class='line'>350</span> </span><span class="WHIT"> </span><span class="NAME">this._processData</span><span class="PUNC">(</span><span class="NAME">str.substr</span><span class="PUNC">(</span><span class="NAME">dataRemainderMatch.index</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="WHIT"> </span><span class="NAME">dataRemainderMatch</span><span class="PUNC">[</span><span class="NUMB">0</span><span class="PUNC">]</span><span class="PUNC">.</span><span class="NAME">length</span><span class="PUNC">)</span><span class="PUNC">+</span><span class="STRN">"\r\n"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>351</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>352</span> </span><span class="WHIT"> </span><span class="COMM">// check if there's not something in the end of the data that resembles</span><span class="WHIT">
+<span class='line'>353</span> </span><span class="WHIT"> </span><span class="COMM">// end sequence - if so, cut it off and save it to the remainder</span><span class="WHIT">
+<span class='line'>354</span> </span><span class="WHIT"> </span><span class="NAME">str</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">str</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>355</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>356</span> </span><span class="WHIT"> </span><span class="KEYW">for</span><span class="PUNC">(</span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">i</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">Math.min</span><span class="PUNC">(</span><span class="NAME">this._endDataModeSequence.length</span><span class="PUNC">-</span><span class="NUMB">1</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">str.length</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT"> </span><span class="NAME">i</span><span class="PUNC">></span><span class="NUMB">0</span><span class="PUNC">;</span><span class="WHIT"> </span><span class="NAME">i</span><span class="PUNC">--</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>357</span> </span><span class="WHIT"> </span><span class="NAME">match</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">this._endDataModeSequence.substr</span><span class="PUNC">(</span><span class="NUMB">0</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">i</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>358</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">str.substr</span><span class="PUNC">(</span><span class="PUNC">-</span><span class="NAME">match.length</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">==</span><span class="WHIT"> </span><span class="NAME">match</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>359</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">str.substr</span><span class="PUNC">(</span><span class="PUNC">-</span><span class="NAME">match.length</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>360</span> </span><span class="WHIT"> </span><span class="NAME">str</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">str.substr</span><span class="PUNC">(</span><span class="NUMB">0</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">str.length</span><span class="WHIT"> </span><span class="PUNC">-</span><span class="WHIT"> </span><span class="NAME">match.length</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>361</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>362</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>363</span>
+<span class='line'>364</span> </span><span class="WHIT"> </span><span class="COMM">// if there's some data leht, emit it</span><span class="WHIT">
+<span class='line'>365</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">str.length</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>366</span> </span><span class="WHIT"> </span><span class="NAME">data</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="PUNC">(</span><span class="NAME">str</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"binary"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>367</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>368</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"DATA:"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">data.toString</span><span class="PUNC">(</span><span class="STRN">"utf-8"</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>369</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>370</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"data"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">data</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>371</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>372</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>373</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>374</span> </span><span class="WHIT"> </span><span class="COMM">// Not in data mode, process as command</span><span class="WHIT">
+<span class='line'>375</span> </span><span class="WHIT"> </span><span class="NAME">this._processData</span><span class="PUNC">(</span><span class="NAME">str</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>376</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>377</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>378</span>
+<span class='line'>379</span> </span><span class="COMM">/**
+<span class='line'>380</span> * &lt;p>Processed incoming command lines and emits found data as
+<span class='line'>381</span> * &lt;code>'command'&lt;/code> with the command name as the first param and the rest
+<span class='line'>382</span> * of the data as second (Buffer)&lt;/p>
+<span class='line'>383</span> *
+<span class='line'>384</span> * @param {String} str Binary string to be processed
+<span class='line'>385</span> */</span><span class="WHIT">
+<span class='line'>386</span> </span><span class="NAME">RAISocket.prototype._processData</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">str</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>387</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">!</span><span class="NAME">str.length</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>388</span> </span><span class="WHIT"> </span><span class="KEYW">return</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>389</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>390</span> </span><span class="WHIT"> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">lines</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="NAME">this._remainder</span><span class="PUNC">+</span><span class="NAME">str</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">split</span><span class="PUNC">(</span><span class="STRN">"\r\n"</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT">
+<span class='line'>391</span> </span><span class="WHIT"> </span><span class="NAME">match</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">command</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>392</span> </span><span class="WHIT">
+<span class='line'>393</span> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">lines.pop</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>394</span> </span><span class="WHIT">
+<span class='line'>395</span> </span><span class="KEYW">for</span><span class="PUNC">(</span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">i</span><span class="PUNC">=</span><span class="NUMB">0</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">len</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">lines.length</span><span class="PUNC">;</span><span class="WHIT"> </span><span class="NAME">i</span><span class="PUNC">&lt;</span><span class="NAME">len</span><span class="PUNC">;</span><span class="WHIT"> </span><span class="NAME">i</span><span class="PUNC">++</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>396</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this._ignore_data</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>397</span> </span><span class="WHIT"> </span><span class="COMM">// If TLS upgrade is initiated do not process current buffer</span><span class="WHIT">
+<span class='line'>398</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>399</span> </span><span class="WHIT"> </span><span class="KEYW">break</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>400</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>401</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">!</span><span class="NAME">this._dataMode</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>402</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="PUNC">(</span><span class="NAME">match</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">lines</span><span class="PUNC">[</span><span class="NAME">i</span><span class="PUNC">]</span><span class="PUNC">.</span><span class="NAME">match</span><span class="PUNC">(</span><span class="REGX">/\s*[\S]+\s?/</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>403</span> </span><span class="WHIT"> </span><span class="NAME">command</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="NAME">match</span><span class="PUNC">[</span><span class="NUMB">0</span><span class="PUNC">]</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="WHIT"> </span><span class="STRN">""</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">trim</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>404</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.debug</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>405</span> </span><span class="WHIT"> </span><span class="NAME">console.log</span><span class="PUNC">(</span><span class="STRN">"COMMAND:"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">lines</span><span class="PUNC">[</span><span class="NAME">i</span><span class="PUNC">]</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>406</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>407</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"command"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">command</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="KEYW">new</span><span class="WHIT"> </span><span class="NAME">Buffer</span><span class="PUNC">(</span><span class="NAME">lines</span><span class="PUNC">[</span><span class="NAME">i</span><span class="PUNC">]</span><span class="PUNC">.</span><span class="NAME">substr</span><span class="PUNC">(</span><span class="NAME">match.index</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="WHIT"> </span><span class="NAME">match</span><span class="PUNC">[</span><span class="NUMB">0</span><span class="PUNC">]</span><span class="PUNC">.</span><span class="NAME">length</span><span class="PUNC">)</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"binary"</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>408</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>409</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>410</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this._remainder</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>411</span> </span><span class="WHIT"> </span><span class="NAME">this._remainder</span><span class="WHIT"> </span><span class="PUNC">+</span><span class="PUNC">=</span><span class="WHIT"> </span><span class="STRN">"\r\n"</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>412</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>413</span> </span><span class="WHIT"> </span><span class="NAME">this._onReceiveData</span><span class="PUNC">(</span><span class="NAME">lines.slice</span><span class="PUNC">(</span><span class="NAME">i</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">join</span><span class="PUNC">(</span><span class="STRN">"\r\n"</span><span class="PUNC">)</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>414</span> </span><span class="WHIT"> </span><span class="KEYW">break</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>415</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>416</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>417</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>418</span>
+<span class='line'>419</span> </span><span class="COMM">/**
+<span class='line'>420</span> * &lt;p>Called when the connection is or is going to be ended&lt;/p>
+<span class='line'>421</span> */</span><span class="WHIT">
+<span class='line'>422</span> </span><span class="NAME">RAISocket.prototype._destroy</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>423</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this._destroyed</span><span class="PUNC">)</span><span class="KEYW">return</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>424</span> </span><span class="WHIT"> </span><span class="NAME">this._destroyed</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>425</span> </span><span class="WHIT">
+<span class='line'>426</span> </span><span class="NAME">this.removeAllListeners</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>427</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>428</span>
+<span class='line'>429</span> </span><span class="COMM">/**
+<span class='line'>430</span> * &lt;p>Called when the connection is ended. Emits &lt;code>'end'&lt;/code>&lt;/p>
+<span class='line'>431</span> *
+<span class='line'>432</span> * @event
+<span class='line'>433</span> */</span><span class="WHIT">
+<span class='line'>434</span> </span><span class="NAME">RAISocket.prototype._onEnd</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>435</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"end"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>436</span> </span><span class="WHIT"> </span><span class="NAME">this._destroy</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>437</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>438</span>
+<span class='line'>439</span> </span><span class="COMM">/**
+<span class='line'>440</span> * &lt;p>Called when an error has appeared. Emits &lt;code>'error'&lt;/code> with
+<span class='line'>441</span> * the error object as a parameter.&lt;/p>
+<span class='line'>442</span> *
+<span class='line'>443</span> * @event
+<span class='line'>444</span> * @param {Object} err Error object
+<span class='line'>445</span> */</span><span class="WHIT">
+<span class='line'>446</span> </span><span class="NAME">RAISocket.prototype._onError</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>447</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"error"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">err</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>448</span> </span><span class="WHIT"> </span><span class="NAME">this._destroy</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>449</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>450</span>
+<span class='line'>451</span> </span><span class="COMM">/**
+<span class='line'>452</span> * &lt;p>Called when a timeout has occured. Connection will be closed and
+<span class='line'>453</span> * &lt;code>'timeout'&lt;/code> is emitted.&lt;/p>
+<span class='line'>454</span> *
+<span class='line'>455</span> * @event
+<span class='line'>456</span> */</span><span class="WHIT">
+<span class='line'>457</span> </span><span class="NAME">RAISocket.prototype._onTimeout</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>458</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.options.disconnectOnTimeout</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>459</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="PUNC">(</span><span class="NAME">this.socket</span><span class="WHIT"> </span><span class="PUNC">&&</span><span class="WHIT"> </span><span class="PUNC">!</span><span class="NAME">this.socket.destroyed</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>460</span> </span><span class="WHIT"> </span><span class="NAME">this.socket.end</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>461</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>462</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"timeout"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>463</span> </span><span class="WHIT"> </span><span class="NAME">this._destroy</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>464</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="KEYW">else</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>465</span> </span><span class="WHIT"> </span><span class="NAME">this.emit</span><span class="PUNC">(</span><span class="STRN">"timeout"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>466</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>467</span> </span><span class="PUNC">}</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>468</span>
+<span class='line'>469</span> </span><span class="COMM">/**
+<span class='line'>470</span> * &lt;p>Called when the connection is closed&lt;/p>
+<span class='line'>471</span> *
+<span class='line'>472</span> * @event
+<span class='line'>473</span> * @param {Boolean} hadError did the connection end because of an error?
+<span class='line'>474</span> */</span><span class="WHIT">
+<span class='line'>475</span> </span><span class="NAME">RAISocket.prototype._onClose</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="NAME">hadError</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>476</span> </span><span class="WHIT"> </span><span class="NAME">this._destroy</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>477</span> </span><span class="PUNC">}</span><span class="PUNC">;</span></pre></body></html> \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_starttls.js.html b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_starttls.js.html
new file mode 100644
index 0000000..dd1b2ea
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/src/RAI_lib_starttls.js.html
@@ -0,0 +1,120 @@
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8"> <style>
+ .KEYW {color: #933;}
+ .COMM {color: #bbb; font-style: italic;}
+ .NUMB {color: #393;}
+ .STRN {color: #393;}
+ .REGX {color: #339;}
+ .line {border-right: 1px dotted #666; color: #666; font-style: normal;}
+ </style></head><body><pre><span class='line'> 1</span> <span class="COMM">// SOURCE: https://gist.github.com/848444</span><span class="WHIT">
+<span class='line'> 2</span>
+<span class='line'> 3</span> </span><span class="COMM">// Target API:</span><span class="WHIT">
+<span class='line'> 4</span> </span><span class="COMM">//</span><span class="WHIT">
+<span class='line'> 5</span> </span><span class="COMM">// var s = require('net').createStream(25, 'smtp.example.com');</span><span class="WHIT">
+<span class='line'> 6</span> </span><span class="COMM">// s.on('connect', function() {</span><span class="WHIT">
+<span class='line'> 7</span> </span><span class="COMM">// require('starttls')(s, options, function() {</span><span class="WHIT">
+<span class='line'> 8</span> </span><span class="COMM">// if (!s.authorized) {</span><span class="WHIT">
+<span class='line'> 9</span> </span><span class="COMM">// s.destroy();</span><span class="WHIT">
+<span class='line'> 10</span> </span><span class="COMM">// return;</span><span class="WHIT">
+<span class='line'> 11</span> </span><span class="COMM">// }</span><span class="WHIT">
+<span class='line'> 12</span> </span><span class="COMM">//</span><span class="WHIT">
+<span class='line'> 13</span> </span><span class="COMM">// s.end("hello world\n");</span><span class="WHIT">
+<span class='line'> 14</span> </span><span class="COMM">// });</span><span class="WHIT">
+<span class='line'> 15</span> </span><span class="COMM">// });</span><span class="WHIT">
+<span class='line'> 16</span> </span><span class="COMM">//</span><span class="WHIT">
+<span class='line'> 17</span> </span><span class="COMM">//</span><span class="WHIT">
+<span class='line'> 18</span>
+<span class='line'> 19</span> </span><span class="COMM">/**
+<span class='line'> 20</span> * @namespace STARTTLS module
+<span class='line'> 21</span> * @name starttls
+<span class='line'> 22</span> */</span><span class="WHIT">
+<span class='line'> 23</span> </span><span class="NAME">module.exports.starttls</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">starttls</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 24</span>
+<span class='line'> 25</span> </span><span class="COMM">/**
+<span class='line'> 26</span> * &lt;p>Upgrades a socket to a secure TLS connection&lt;/p>
+<span class='line'> 27</span> *
+<span class='line'> 28</span> * @memberOf starttls
+<span class='line'> 29</span> * @param {Object} socket Plaintext socket to be upgraded
+<span class='line'> 30</span> * @param {Object} options Certificate data for the server
+<span class='line'> 31</span> * @param {Function} callback Callback function to be run after upgrade
+<span class='line'> 32</span> */</span><span class="WHIT">
+<span class='line'> 33</span> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">starttls</span><span class="PUNC">(</span><span class="NAME">socket</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">options</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 34</span> </span><span class="WHIT"> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">sslcontext</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">pair</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">cleartext</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 35</span> </span><span class="WHIT">
+<span class='line'> 36</span> </span><span class="NAME">socket.removeAllListeners</span><span class="PUNC">(</span><span class="STRN">"data"</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 37</span> </span><span class="WHIT"> </span><span class="NAME">sslcontext</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">'crypto'</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">createCredentials</span><span class="PUNC">(</span><span class="NAME">options</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 38</span> </span><span class="WHIT"> </span><span class="NAME">pair</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">require</span><span class="PUNC">(</span><span class="STRN">'tls'</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">createSecurePair</span><span class="PUNC">(</span><span class="NAME">sslcontext</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 39</span> </span><span class="WHIT"> </span><span class="NAME">cleartext</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">pipe</span><span class="PUNC">(</span><span class="NAME">pair</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">socket</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 40</span>
+<span class='line'> 41</span> </span><span class="WHIT"> </span><span class="NAME">pair.on</span><span class="PUNC">(</span><span class="STRN">'secure'</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="KEYW">function</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 42</span> </span><span class="WHIT"> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">verifyError</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="NAME">pair._ssl</span><span class="WHIT"> </span><span class="PUNC">||</span><span class="WHIT"> </span><span class="NAME">pair.ssl</span><span class="PUNC">)</span><span class="PUNC">.</span><span class="NAME">verifyError</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 43</span>
+<span class='line'> 44</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="NAME">verifyError</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 45</span> </span><span class="WHIT"> </span><span class="NAME">cleartext.authorized</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 46</span> </span><span class="WHIT"> </span><span class="NAME">cleartext.authorizationError</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">verifyError</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 47</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT"> </span><span class="KEYW">else</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 48</span> </span><span class="WHIT"> </span><span class="NAME">cleartext.authorized</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 49</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 50</span>
+<span class='line'> 51</span> </span><span class="WHIT"> </span><span class="NAME">callback</span><span class="PUNC">(</span><span class="NAME">cleartext</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 52</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 53</span>
+<span class='line'> 54</span> </span><span class="WHIT"> </span><span class="NAME">cleartext._controlReleased</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">true</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 55</span> </span><span class="WHIT"> </span><span class="KEYW">return</span><span class="WHIT"> </span><span class="NAME">pair</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 56</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 57</span>
+<span class='line'> 58</span> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">forwardEvents</span><span class="PUNC">(</span><span class="NAME">events</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">emitterSource</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">emitterDestination</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 59</span> </span><span class="WHIT"> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">map</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="PUNC">[</span><span class="PUNC">]</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">name</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 60</span> </span><span class="WHIT">
+<span class='line'> 61</span> </span><span class="KEYW">for</span><span class="PUNC">(</span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">i</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NUMB">0</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">len</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">events.length</span><span class="PUNC">;</span><span class="WHIT"> </span><span class="NAME">i</span><span class="WHIT"> </span><span class="PUNC">&lt;</span><span class="WHIT"> </span><span class="NAME">len</span><span class="PUNC">;</span><span class="WHIT"> </span><span class="NAME">i</span><span class="PUNC">++</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 62</span> </span><span class="WHIT"> </span><span class="NAME">name</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">events</span><span class="PUNC">[</span><span class="NAME">i</span><span class="PUNC">]</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 63</span>
+<span class='line'> 64</span> </span><span class="WHIT"> </span><span class="NAME">handler</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">forwardEvent.bind</span><span class="PUNC">(</span><span class="NAME">emitterDestination</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">name</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 65</span> </span><span class="WHIT">
+<span class='line'> 66</span> </span><span class="NAME">map.push</span><span class="PUNC">(</span><span class="NAME">name</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 67</span> </span><span class="WHIT"> </span><span class="NAME">emitterSource.on</span><span class="PUNC">(</span><span class="NAME">name</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">handler</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 68</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 69</span> </span><span class="WHIT">
+<span class='line'> 70</span> </span><span class="KEYW">return</span><span class="WHIT"> </span><span class="NAME">map</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 71</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 72</span>
+<span class='line'> 73</span> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">forwardEvent</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 74</span> </span><span class="WHIT"> </span><span class="NAME">this.emit.apply</span><span class="PUNC">(</span><span class="KEYW">this</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">arguments</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 75</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 76</span>
+<span class='line'> 77</span> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">removeEvents</span><span class="PUNC">(</span><span class="NAME">map</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">emitterSource</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 78</span> </span><span class="WHIT"> </span><span class="KEYW">for</span><span class="PUNC">(</span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">i</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NUMB">0</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">len</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">map.length</span><span class="PUNC">;</span><span class="WHIT"> </span><span class="NAME">i</span><span class="WHIT"> </span><span class="PUNC">&lt;</span><span class="WHIT"> </span><span class="NAME">len</span><span class="PUNC">;</span><span class="WHIT"> </span><span class="NAME">i</span><span class="PUNC">++</span><span class="PUNC">)</span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 79</span> </span><span class="WHIT"> </span><span class="NAME">emitterSource.removeAllListeners</span><span class="PUNC">(</span><span class="NAME">map</span><span class="PUNC">[</span><span class="NAME">i</span><span class="PUNC">]</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 80</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 81</span> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 82</span>
+<span class='line'> 83</span> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">pipe</span><span class="PUNC">(</span><span class="NAME">pair</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">socket</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 84</span> </span><span class="WHIT"> </span><span class="NAME">pair.encrypted.pipe</span><span class="PUNC">(</span><span class="NAME">socket</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 85</span> </span><span class="WHIT"> </span><span class="NAME">socket.pipe</span><span class="PUNC">(</span><span class="NAME">pair.encrypted</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 86</span>
+<span class='line'> 87</span> </span><span class="WHIT"> </span><span class="NAME">pair.fd</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">socket.fd</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 88</span> </span><span class="WHIT">
+<span class='line'> 89</span> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">cleartext</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">pair.cleartext</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 90</span> </span><span class="WHIT">
+<span class='line'> 91</span> </span><span class="NAME">cleartext.socket</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">socket</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 92</span> </span><span class="WHIT"> </span><span class="NAME">cleartext.encrypted</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">pair.encrypted</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 93</span> </span><span class="WHIT"> </span><span class="NAME">cleartext.authorized</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="KEYW">false</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 94</span>
+<span class='line'> 95</span> </span><span class="WHIT"> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">onerror</span><span class="PUNC">(</span><span class="NAME">e</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 96</span> </span><span class="WHIT"> </span><span class="KEYW">if</span><span class="WHIT"> </span><span class="PUNC">(</span><span class="NAME">cleartext._controlReleased</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'> 97</span> </span><span class="WHIT"> </span><span class="NAME">cleartext.emit</span><span class="PUNC">(</span><span class="STRN">'error'</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">e</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'> 98</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'> 99</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>100</span>
+<span class='line'>101</span> </span><span class="WHIT"> </span><span class="KEYW">var</span><span class="WHIT"> </span><span class="NAME">map</span><span class="WHIT"> </span><span class="PUNC">=</span><span class="WHIT"> </span><span class="NAME">forwardEvents</span><span class="PUNC">(</span><span class="PUNC">[</span><span class="STRN">"timeout"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"end"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"close"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"drain"</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="STRN">"error"</span><span class="PUNC">]</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">socket</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">cleartext</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>102</span> </span><span class="WHIT">
+<span class='line'>103</span> </span><span class="KEYW">function</span><span class="WHIT"> </span><span class="NAME">onclose</span><span class="PUNC">(</span><span class="PUNC">)</span><span class="WHIT"> </span><span class="PUNC">{</span><span class="WHIT">
+<span class='line'>104</span> </span><span class="WHIT"> </span><span class="NAME">socket.removeListener</span><span class="PUNC">(</span><span class="STRN">'error'</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">onerror</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>105</span> </span><span class="WHIT"> </span><span class="NAME">socket.removeListener</span><span class="PUNC">(</span><span class="STRN">'close'</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">onclose</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>106</span> </span><span class="WHIT"> </span><span class="NAME">removeEvents</span><span class="PUNC">(</span><span class="NAME">map</span><span class="PUNC">,</span><span class="NAME">socket</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>107</span> </span><span class="WHIT"> </span><span class="PUNC">}</span><span class="WHIT">
+<span class='line'>108</span>
+<span class='line'>109</span> </span><span class="WHIT"> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">'error'</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">onerror</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>110</span> </span><span class="WHIT"> </span><span class="NAME">socket.on</span><span class="PUNC">(</span><span class="STRN">'close'</span><span class="PUNC">,</span><span class="WHIT"> </span><span class="NAME">onclose</span><span class="PUNC">)</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>111</span>
+<span class='line'>112</span> </span><span class="WHIT"> </span><span class="KEYW">return</span><span class="WHIT"> </span><span class="NAME">cleartext</span><span class="PUNC">;</span><span class="WHIT">
+<span class='line'>113</span> </span><span class="PUNC">}</span></pre></body></html> \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/starttls.html b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/starttls.html
new file mode 100644
index 0000000..e16b915
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/jsdoc/symbols/starttls.html
@@ -0,0 +1,237 @@
+
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="generator" content="JsDoc Toolkit" />
+ <title>starttls | JsDoc Reference</title>
+
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
+ <meta name="mobileoptimized" content="0" />
+
+ <link rel="stylesheet" href="../css/all.css" media="all" />
+ <link rel="stylesheet" href="../css/handheld.css" media="only screen and (max-width: 660px)" />
+ <link rel="stylesheet" href="../css/handheld.css" media="handheld" />
+ <link rel="stylesheet" href="../css/screen.css" media="screen and (min-width: 661px)" />
+
+ <script src="../javascript/all.js"></script>
+ <!--[if lt IE 9]>
+ <script src="../javascript/html5.js"></script>
+ <![endif]-->
+ </head>
+
+ <body>
+
+<div class="index">
+ <div class="menu">
+ <div class="indexLinks">
+ <a href="../index.html">Classes</a>
+ <a href="../files.html">Files</a>
+ </div>
+
+ <h2 class="heading1">Classes</h2>
+
+ <input type="text" name="classFilter" class="classFilter" id="ClassFilter" placeholder="Filter"></input>
+
+ <nav>
+ <ul class="classList" id="ClassList">
+
+ <li><a href="../symbols/_global_.html">_global_</a></li>
+
+ <li><a href="../symbols/mockup.html">mockup</a></li>
+
+ <li><a href="../symbols/RAIServer.html">RAIServer</a></li>
+
+ <li><a href="../symbols/RAISocket.html">RAISocket</a></li>
+
+ <li><a href="../symbols/starttls.html">starttls</a></li>
+
+ </ul>
+ </nav>
+ </div>
+ <div class="fineprint" style="clear:both">
+ <footer>
+
+ Documentation generator: <a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank">JsDoc Toolkit</a> 2.4.0<br />
+ Template: <a href="http://www.thebrightlines.com/2010/05/06/new-template-for-jsdoctoolkit-codeview/" target="_blank">Codeview</a> 1.2<br />
+ Generated on:
+ <time datetime='2012-0-22' pubdate>2012-0-22 12:15</time>
+ </footer>
+ </div>
+</div>
+
+<div class="index indexStatic"></div>
+
+<div class="content">
+ <div class="innerContent">
+ <article>
+ <header>
+ <h1 class="classTitle">
+
+ Namespace <span>starttls</span>
+ </h1>
+
+ <div class="intro">
+ <p class="description summary">
+ STARTTLS module
+ </p>
+
+
+ <ul class="summary">
+
+
+
+ <li>Defined in: <a href="../symbols/src/RAI_lib_starttls.js.html">starttls.js</a></li>
+
+
+ </ul>
+
+ </div>
+ </header>
+
+
+
+
+ <!--
+ #### METHODS SUMMARY
+ -->
+
+ <section>
+
+
+ <div class="props">
+ <h2 class="sectionTitle">Method Summary</h2>
+
+
+ <nav>
+ <table class="summaryTable" id="MethodsList" cellspacing="0" summary="A summary of the methods documented in the class starttls.">
+ <thead>
+ <tr>
+ <th scope="col">Method Attributes</th>
+ <th scope="col">Method Name and Description</th>
+ </tr>
+ </thead>
+
+ <tbody>
+
+
+ <tr
+ class='item0'
+ >
+ <td class="attributes">&lt;static&gt; &nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont">starttls.<b><a href="../symbols/starttls.html#.starttls">starttls</a></b>(socket, options, callback)
+ </div>
+ <div class="description"><p>Upgrades a socket to a secure TLS connection</p></div>
+ </td>
+ </tr>
+
+ </tbody>
+ </table>
+ </nav>
+
+
+
+ </div>
+ </section>
+
+
+ <!--
+ #### EVENTS SUMMARY
+ -->
+
+ <!--
+ #### CONSTRUCTOR DETAILS
+ -->
+
+ <!--
+ #### FIELD DETAILS
+ -->
+
+ <!--
+ #### METHOD DETAILS
+ -->
+
+ <section>
+ <div class="details props">
+ <div class="innerProps">
+ <h2 class="sectionTitle">
+ Method Detail
+ </h2>
+
+ <ul class="methodDetail" id="MethodDetail">
+
+
+ <li
+ class='item0'
+ >
+ <div class="fixedFont heading" id=".starttls">
+ <span class='lighter'>
+ &lt;static&gt;
+ </span>
+
+
+
+ <span class="light">starttls.</span><b>starttls</b>(socket, options, callback)
+ </div>
+
+ <div class="description">
+ <p>Upgrades a socket to a secure TLS connection</p>
+
+
+
+
+ </div>
+
+
+
+
+ <dl class="detailList params">
+ <dt class="heading">Parameters:</dt>
+
+ <dt>
+ <span class="light fixedFont">{Object}</span> <b>socket</b>
+
+ </dt>
+ <dd>Plaintext socket to be upgraded</dd>
+
+ <dt>
+ <span class="light fixedFont">{Object}</span> <b>options</b>
+
+ </dt>
+ <dd>Certificate data for the server</dd>
+
+ <dt>
+ <span class="light fixedFont">{Function}</span> <b>callback</b>
+
+ </dt>
+ <dd>Callback function to be run after upgrade</dd>
+
+ </dl>
+
+
+
+
+ </li>
+
+ </ul>
+ </div>
+ </div>
+ </section>
+
+
+ <!--
+ #### EVENT DETAILS
+ -->
+
+ </article>
+ </div>
+</div>
+
+ <script type="text/javascript">
+ wbos.CssTools.MediaQueryFallBack.LoadCss('../css/screen.css', '../css/handheld.css', 660)
+ codeview.classFilter.Init()
+ </script>
+ </body>
+</html>
+
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/mockup.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/mockup.js
new file mode 100644
index 0000000..47bbc4a
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/mockup.js
@@ -0,0 +1,113 @@
+var net = require("net"),
+ crypto = require("crypto"),
+ tlslib = require("tls");
+
+// monkey patch net and tls to support nodejs 0.4
+if(!net.connect && net.createConnection){
+ net.connect = net.createConnection;
+}
+
+if(!tlslib.connect && tlslib.createConnection){
+ tlslib.connect = tlslib.createConnection;
+}
+
+/**
+ * @namespace Mockup module
+ * @name mockup
+ */
+module.exports = runClientMockup;
+
+/**
+ * <p>Runs a batch of commands against a server</p>
+ *
+ * <pre>
+ * var cmds = ["EHLO FOOBAR", "STARTTLS", "QUIT"];
+ * runClientMockup(25, "mail.hot.ee", cmds, function(resp){
+ * console.log("Final:", resp.toString("utf-8").trim());
+ * });
+ * </pre>
+ *
+ * @memberOf mockup
+ * @param {Number} port Port number
+ * @param {String} host Hostname to connect to
+ * @param {Array} commands Command list to be sent to server
+ * @param {Function} callback Callback function to run on completion,
+ * has the last response from the server as a param
+ * @param {Boolean} [debug] if set to true log all input/output
+ */
+function runClientMockup(port, host, commands, callback, debug){
+ host = host || "localhost";
+ port = port || 25;
+ commands = Array.isArray(commands) ? commands : [];
+
+ var command, ignore_data = false, sslcontext, pair;
+
+ var socket = net.connect(port, host);
+ socket.on("connect", function(){
+ socket.on("data", function(chunk){
+ if(ignore_data)return;
+
+ if(debug){
+ console.log("S: "+chunk.toString("utf-8").trim());
+ }
+
+ if(!commands.length){
+ socket.end();
+ if(typeof callback == "function"){
+ callback(chunk);
+ }
+ return;
+ }
+
+ if(["STARTTLS", "STLS"].indexOf((command || "").trim().toUpperCase())>=0){
+ ignore_data = true;
+ if(debug){
+ console.log("Initiated TLS connection");
+ }
+ sslcontext = crypto.createCredentials();
+ pair = tlslib.createSecurePair(sslcontext, false);
+
+ pair.encrypted.pipe(socket);
+ socket.pipe(pair.encrypted);
+ pair.fd = socket.fd;
+
+ pair.on("secure", function(){
+ if(debug){
+ console.log("TLS connection secured");
+ }
+ command = commands.shift();
+ if(debug){
+ console.log("C: "+command);
+ }
+ pair.cleartext.write(command+"\r\n");
+
+ pair.cleartext.on("data", function(chunk){
+ if(debug){
+ console.log("S: "+chunk.toString("utf-8").trim());
+ }
+
+ if(!commands.length){
+ pair.cleartext.end();
+ if(typeof callback == "function"){
+ callback(chunk);
+ }
+ return;
+ }
+ command = commands.shift();
+ pair.cleartext.write(command+"\r\n");
+ if(debug){
+ console.log("C: "+command);
+ }
+ });
+ });
+ }else{
+ command = commands.shift();
+ socket.write(command+"\r\n");
+ if(debug){
+ console.log("C: "+command);
+ }
+ }
+ });
+ });
+
+} \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/rai.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/rai.js
new file mode 100644
index 0000000..d472063
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/rai.js
@@ -0,0 +1,489 @@
+/**
+ * @fileOverview This is the main file for the RAI library to create text based servers
+ * @author <a href="mailto:andris@node.ee">Andris Reinman</a>
+ * @version 0.1.3
+ */
+
+var netlib = require("net"),
+ utillib = require("util"),
+ EventEmitter = require('events').EventEmitter,
+ starttls = require("./starttls").starttls,
+ tlslib = require("tls"),
+ crypto = require("crypto"),
+ fs = require("fs");
+
+// Default credentials for starting TLS server
+var defaultCredentials = {
+ key: fs.readFileSync(__dirname+"/../cert/key.pem"),
+ cert: fs.readFileSync(__dirname+"/../cert/cert.pem")
+};
+
+// Expose to the world
+module.exports.RAIServer = RAIServer;
+module.exports.runClientMockup = require("./mockup");
+
+/**
+ * <p>Creates instance of RAIServer</p>
+ *
+ * <p>Options object has the following properties:</p>
+ *
+ * <ul>
+ * <li><b>debug</b> - if set to true print traffic to console</li>
+ * <li><b>disconnectOnTimeout</b> - if set to true close the connection on disconnect</li>
+ * <li><b>secureConnection</b> - if set to true close the connection on disconnect</li>
+ * <li><b>credentials</b> - credentials for secureConnection and STARTTLS</li>
+ * <li><b>timeout</b> - timeout in milliseconds for disconnecting the client,
+ * defaults to 0 (no timeout)</li>
+ * </ul>
+ *
+ * <p><b>Events</b></p>
+ *
+ * <ul>
+ * <li><b>'connect'</b> - emitted if a client connects to the server, param
+ * is a client ({@link RAISocket}) object</li>
+ * <li><b>'error'</b> - emitted on error, has an error object as a param</li>
+ * </ul>
+ *
+ * @constructor
+ * @param {Object} [options] Optional options object
+ */
+function RAIServer(options){
+ EventEmitter.call(this);
+
+ this.options = options || {};
+
+ this._createServer();
+}
+utillib.inherits(RAIServer, EventEmitter);
+
+/**
+ * <p>Starts listening on selected port</p>
+ *
+ * @param {Number} port The port to listen
+ * @param {String} [host] The IP address to listen
+ * @param {Function} callback The callback function to be run after the server
+ * is listening, the only param is an error message if the operation failed
+ */
+RAIServer.prototype.listen = function(port, host, callback){
+ if(!callback && typeof host=="function"){
+ callback = host;
+ host = undefined;
+ }
+ this._port = port;
+ this._host = host;
+
+ this._connected = false;
+ if(callback){
+ this._server.on("listening", (function(){
+ this._connected = true;
+ callback(null);
+ }).bind(this));
+
+ this._server.on("error", (function(err){
+ if(!this._connected){
+ callback(err);
+ }
+ }).bind(this));
+ }
+
+ this._server.listen(this._port, this._host);
+};
+
+/**
+ * <p>Stops the server</p>
+ *
+ * @param {Function} callback Is run when the server is closed
+ */
+RAIServer.prototype.end = function(callback){
+ this._server.on("close", callback);
+ this._server.close();
+};
+
+/**
+ * <p>Creates a server with listener callback</p>
+ */
+RAIServer.prototype._createServer = function(){
+ if(this.options.secureConnection){
+ this._server = tlslib.createServer(
+ this.options.credentials || defaultCredentials,
+ this._serverListener.bind(this));
+ }else{
+ this._server = netlib.createServer(this._serverListener.bind(this));
+ }
+ this._server.on("error", this._onError.bind(this));
+};
+
+/**
+ * <p>Listens for errors</p>
+ *
+ * @event
+ * @param {Object} err Error object
+ */
+RAIServer.prototype._onError = function(err){
+ if(this._connected){
+ this.emit("error", err);
+ }
+};
+
+/**
+ * <p>Server listener that is run on client connection</p>
+ *
+ * <p>{@link RAISocket} object instance is created based on the client socket
+ * and a <code>'connection'</code> event is emitted</p>
+ *
+ * @param {Object} socket The socket to the client
+ */
+RAIServer.prototype._serverListener = function(socket){
+ if(this.options.debug){
+ console.log("CONNECTION FROM "+socket.remoteAddress);
+ }
+
+ var handler = new RAISocket(socket, this.options);
+
+ socket.on("data", handler._onReceiveData.bind(handler));
+ socket.on("end", handler._onEnd.bind(handler));
+ socket.on("error", handler._onError.bind(handler));
+ socket.on("timeout", handler._onTimeout.bind(handler));
+ socket.on("close", handler._onClose.bind(handler));
+
+ if("setKeepAlive" in socket){
+ socket.setKeepAlive(true); // plaintext server
+ }else if(socket.encrypted && "setKeepAlive" in socket.encrypted){
+ socket.encrypted.setKeepAlive(true); // secure server
+ }
+
+ this.emit("connect", handler);
+};
+
+/**
+ * <p>Creates a instance for interacting with a client (socket)</p>
+ *
+ * <p>Optional options object is the same that is passed to the parent
+ * {@link RAIServer} object</p>
+ *
+ * <p><b>Events</b></p>
+ *
+ * <ul>
+ * <li><b>'command'</b> - emitted if a client sends a command. Gets two
+ * params - command (String) and payload (Buffer)</li>
+ * <li><b>'data'</b> - emitted when a chunk is received in data mode, the
+ * param being the payload (Buffer)</li>
+ * <li><b>'ready'</b> - emitted when data stream ends and normal command
+ * flow is recovered</li>
+ * <li><b>'tls'</b> - emitted when the connection is secured by TLS</li>
+ * <li><b>'error'</b> - emitted when an error occurs. Connection to the
+ * client is disconnected automatically. Param is an error object.</l>
+ * <li><b>'timeout'</b> - emitted when a timeout occurs. Connection to the
+ * client is disconnected automatically if disconnectOnTimeout option
+ * is set to true.</l>
+ * <li><b>'end'</b> - emitted when the client disconnects</l>
+ * </ul>
+ *
+ * @constructor
+ * @param {Object} socket Socket for the client
+ * @param {Object} [options] Optional options object
+ */
+function RAISocket(socket, options){
+ EventEmitter.call(this);
+
+ this.socket = socket;
+ this.options = options || {};
+
+ this.remoteAddress = socket.remoteAddress;
+
+ this._dataMode = false;
+ this._endDataModeSequence = "\r\n.\r\n";
+ this._endDataModeSequenceRegEx = /\r\n\.\r\n|^\.\r\n/;
+
+ this.secureConnection = !!this.options.secureConnection;
+ this._destroyed = false;
+ this._remainder = "";
+
+ this._ignore_data = false;
+
+ if(this.options.timeout){
+ socket.setTimeout(this.options.timeout);
+ }
+}
+utillib.inherits(RAISocket, EventEmitter);
+
+/**
+ * <p>Sends some data to the client. <code>&lt;CR&gt;&lt;LF&gt;</code> is automatically appended to
+ * the data</p>
+ *
+ * @param {String|Buffer} data Data to be sent to the client
+ */
+RAISocket.prototype.send = function(data){
+ var buffer;
+ if(data instanceof Buffer || (typeof SlowBuffer != "undefined" && data instanceof SlowBuffer)){
+ buffer = new Buffer(data.length+2);
+ buffer[buffer.length-2] = 0xD;
+ buffer[buffer.length-1] = 0xA;
+ data.copy(buffer);
+ }else{
+ buffer = new Buffer((data || "").toString()+"\r\n", "binary");
+ }
+
+ if(this.options.debug){
+ console.log("OUT: \"" +buffer.toString("utf-8").trim()+"\"");
+ }
+
+ if(this.socket && this.socket.writable){
+ this.socket.write(buffer);
+ }else{
+ this.socket.end();
+ }
+};
+
+/**
+ * <p>Instructs the server to be listening for mixed data instead of line based
+ * commands</p>
+ *
+ * @param {String} [sequence="."] - optional sequence on separate line for
+ * matching the data end
+ */
+RAISocket.prototype.startDataMode = function(sequence){
+ this._dataMode = true;
+ if(sequence){
+ sequence = sequence.replace(/\.\=\(\)\-\?\*\\\[\]\^\+\:\|\,/g, "\\$1");
+ this._endDataModeSequence = "\r\n"+sequence+"\r\n";
+ this._endDataModeSequenceRegEx = new RegExp("/\r\n"+sequence+"\r\n|^"+sequence+"\r\n/");
+ }
+};
+
+/**
+ * <p>Instructs the server to upgrade the connection to secure TLS connection</p>
+ *
+ * <p>Fires <code>callback</code> on successful connection upgrade if set,
+ * otherwise emits <code>'tls'</code></p>
+ *
+ * @param {Object} [credentials] An object with PEM encoded key and
+ * certificate <code>{key:"---BEGIN...", cert:"---BEGIN..."}</code>,
+ * if not set autogenerated values will be used.
+ * @param {Function} [callback] If calback is set fire it after successful connection
+ * upgrade, otherwise <code>'tls'</code> is emitted
+ */
+RAISocket.prototype.startTLS = function(credentials, callback){
+
+ if(this.secureConnection){
+ return this._onError(new Error("Secure connection already established"));
+ }
+
+ if(!callback && typeof credentials == "function"){
+ callback = credentials;
+ credentials = undefined;
+ }
+
+ credentials = credentials || this.options.credentials || defaultCredentials;
+
+ this._ignore_data = true;
+
+ var secure_connector = starttls(this.socket, credentials, (function(ssl_socket){
+
+ if(this.options.debug && !ssl_socket.authorized){
+ console.log("WARNING: TLS ERROR ("+ssl_socket.authorizationError+")");
+ }
+
+ this._remainder = "";
+ this._ignore_data = false;
+
+ this.secureConnection = true;
+
+ this.socket = ssl_socket;
+ this.socket.on("data", this._onReceiveData.bind(this));
+
+ if(this.options.debug){
+ console.log("TLS CONNECTION STARTED");
+ }
+
+ if(callback){
+ callback();
+ }else{
+ this.emit("tls");
+ }
+
+ }).bind(this));
+
+ secure_connector.on("error", (function(err){
+ this._onError(err);
+ }).bind(this));
+};
+
+/**
+ * <p>Closes the connection to the client</p>
+ */
+RAISocket.prototype.end = function(){
+ this.socket.end();
+};
+
+/**
+ * <p>Called when a chunk of data arrives from the client. If currently in data
+ * mode, transmit the data otherwise send it to <code>_processData</code></p>
+ *
+ * @event
+ * @param {Buffer|String} chunk Data sent by the client
+ */
+RAISocket.prototype._onReceiveData = function(chunk){
+
+ if(this._ignore_data){ // if currently setting up TLS connection
+ return;
+ }
+
+ var str = typeof chunk=="string"?chunk:chunk.toString("binary"),
+ dataEndMatch, dataRemainderMatch, data, match;
+
+ if(this._dataMode){
+
+ str = this._remainder + str;
+ if((dataEndMatch = str.match(/\r\n.*?$/))){
+ // if ther's a line that is not ended, keep it for later
+ this._remainder = str.substr(dataEndMatch.index);
+ str = str.substr(0, dataEndMatch.index);
+ }else{
+ this._remainder = "";
+ }
+
+ // check if a data end sequence is found from the data
+ if((dataRemainderMatch = (str+this._remainder).match(this._endDataModeSequenceRegEx))){
+ str = str + this._remainder;
+ // if the sequence is not on byte 0 emit remaining data
+ if(dataRemainderMatch.index){
+ data = new Buffer(str.substr(0, dataRemainderMatch.index), "binary");
+ if(this.options.debug){
+ console.log("DATA:", data.toString("utf-8"));
+ }
+ this.emit("data", data);
+ }
+ // emit data ready
+ this._remainder = "";
+ this.emit("ready");
+ this._dataMode = false;
+ // send the remaining data for processing
+ this._processData(str.substr(dataRemainderMatch.index + dataRemainderMatch[0].length)+"\r\n");
+ }else{
+ // check if there's not something in the end of the data that resembles
+ // end sequence - if so, cut it off and save it to the remainder
+ str = str + this._remainder;
+ this._remainder= "";
+ for(var i = Math.min(this._endDataModeSequence.length-1, str.length); i>0; i--){
+ match = this._endDataModeSequence.substr(0, i);
+ if(str.substr(-match.length) == match){
+ this._remainder = str.substr(-match.length);
+ str = str.substr(0, str.length - match.length);
+ }
+ }
+
+ // if there's some data leht, emit it
+ if(str.length){
+ data = new Buffer(str, "binary");
+ if(this.options.debug){
+ console.log("DATA:", data.toString("utf-8"));
+ }
+ this.emit("data", data);
+ }
+ }
+ }else{
+ // Not in data mode, process as command
+ this._processData(str);
+ }
+};
+
+/**
+ * <p>Processed incoming command lines and emits found data as
+ * <code>'command'</code> with the command name as the first param and the rest
+ * of the data as second (Buffer)</p>
+ *
+ * @param {String} str Binary string to be processed
+ */
+RAISocket.prototype._processData = function(str){
+ if(!str.length){
+ return;
+ }
+ var lines = (this._remainder+str).split("\r\n"),
+ match, command;
+
+ this._remainder = lines.pop();
+
+ for(var i=0, len = lines.length; i<len; i++){
+ if(this._ignore_data){
+ // If TLS upgrade is initiated do not process current buffer
+ this._remainder = "";
+ break;
+ }
+ if(!this._dataMode){
+ if((match = lines[i].match(/\s*[\S]+\s?/))){
+ command = (match[0] || "").trim();
+ if(this.options.debug){
+ console.log("COMMAND:", lines[i]);
+ }
+ this.emit("command", command, new Buffer(lines[i].substr(match.index + match[0].length), "binary"));
+ }
+ }else{
+ if(this._remainder){
+ this._remainder += "\r\n";
+ }
+ this._onReceiveData(lines.slice(i).join("\r\n"));
+ break;
+ }
+ }
+};
+
+/**
+ * <p>Called when the connection is or is going to be ended</p>
+ */
+RAISocket.prototype._destroy = function(){
+ if(this._destroyed)return;
+ this._destroyed = true;
+
+ this.removeAllListeners();
+};
+
+/**
+ * <p>Called when the connection is ended. Emits <code>'end'</code></p>
+ *
+ * @event
+ */
+RAISocket.prototype._onEnd = function(){
+ this.emit("end");
+ this._destroy();
+};
+
+/**
+ * <p>Called when an error has appeared. Emits <code>'error'</code> with
+ * the error object as a parameter.</p>
+ *
+ * @event
+ * @param {Object} err Error object
+ */
+RAISocket.prototype._onError = function(err){
+ this.emit("error", err);
+ this._destroy();
+};
+
+/**
+ * <p>Called when a timeout has occured. Connection will be closed and
+ * <code>'timeout'</code> is emitted.</p>
+ *
+ * @event
+ */
+RAISocket.prototype._onTimeout = function(){
+ if(this.options.disconnectOnTimeout){
+ if(this.socket && !this.socket.destroyed){
+ this.socket.end();
+ }
+ this.emit("timeout");
+ this._destroy();
+ }else{
+ this.emit("timeout");
+ }
+};
+
+/**
+ * <p>Called when the connection is closed</p>
+ *
+ * @event
+ * @param {Boolean} hadError did the connection end because of an error?
+ */
+RAISocket.prototype._onClose = function(hadError){
+ this._destroy();
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/starttls.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/starttls.js
new file mode 100644
index 0000000..b17dc65
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/lib/starttls.js
@@ -0,0 +1,113 @@
+// SOURCE: https://gist.github.com/848444
+
+// Target API:
+//
+// var s = require('net').createStream(25, 'smtp.example.com');
+// s.on('connect', function() {
+// require('starttls')(s, options, function() {
+// if (!s.authorized) {
+// s.destroy();
+// return;
+// }
+//
+// s.end("hello world\n");
+// });
+// });
+//
+//
+
+/**
+ * @namespace STARTTLS module
+ * @name starttls
+ */
+module.exports.starttls = starttls;
+
+/**
+ * <p>Upgrades a socket to a secure TLS connection</p>
+ *
+ * @memberOf starttls
+ * @param {Object} socket Plaintext socket to be upgraded
+ * @param {Object} options Certificate data for the server
+ * @param {Function} callback Callback function to be run after upgrade
+ */
+function starttls(socket, options, callback) {
+ var sslcontext, pair, cleartext;
+
+ socket.removeAllListeners("data");
+ sslcontext = require('crypto').createCredentials(options);
+ pair = require('tls').createSecurePair(sslcontext, true);
+ cleartext = pipe(pair, socket);
+
+ pair.on('secure', function() {
+ var verifyError = (pair._ssl || pair.ssl).verifyError();
+
+ if (verifyError) {
+ cleartext.authorized = false;
+ cleartext.authorizationError = verifyError;
+ } else {
+ cleartext.authorized = true;
+ }
+
+ callback(cleartext);
+ });
+
+ cleartext._controlReleased = true;
+ return pair;
+}
+
+function forwardEvents(events, emitterSource, emitterDestination) {
+ var map = [], name, handler;
+
+ for(var i = 0, len = events.length; i < len; i++) {
+ name = events[i];
+
+ handler = forwardEvent.bind(emitterDestination, name);
+
+ map.push(name);
+ emitterSource.on(name, handler);
+ }
+
+ return map;
+}
+
+function forwardEvent() {
+ this.emit.apply(this, arguments);
+}
+
+function removeEvents(map, emitterSource) {
+ for(var i = 0, len = map.length; i < len; i++){
+ emitterSource.removeAllListeners(map[i]);
+ }
+}
+
+function pipe(pair, socket) {
+ pair.encrypted.pipe(socket);
+ socket.pipe(pair.encrypted);
+
+ pair.fd = socket.fd;
+
+ var cleartext = pair.cleartext;
+
+ cleartext.socket = socket;
+ cleartext.encrypted = pair.encrypted;
+ cleartext.authorized = false;
+
+ function onerror(e) {
+ if (cleartext._controlReleased) {
+ cleartext.emit('error', e);
+ }
+ }
+
+ var map = forwardEvents(["timeout", "end", "close", "drain", "error"], socket, cleartext);
+
+ function onclose() {
+ socket.removeListener('error', onerror);
+ socket.removeListener('close', onclose);
+ removeEvents(map,socket);
+ }
+
+ socket.on('error', onerror);
+ socket.on('close', onclose);
+
+ return cleartext;
+} \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/package.json b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/package.json
new file mode 100644
index 0000000..7ff1a25
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "rai",
+ "description": "Request-Answer-Interface for generating text based command servers (SMTP, POP etc)",
+ "version": "0.1.6",
+ "author": {
+ "name": "Andris Reinman"
+ },
+ "maintainers": [
+ {
+ "name": "andris",
+ "email": "andris@node.ee"
+ }
+ ],
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/andris9/rai.git"
+ },
+ "scripts": {
+ "test": "node ./run_tests.js"
+ },
+ "main": "./lib/rai",
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://github.com/andris9/rai/blob/master/LICENSE"
+ }
+ ],
+ "devDependencies": {
+ "nodeunit": "*"
+ },
+ "engines": [
+ "node >=0.4.0"
+ ],
+ "keywords": [
+ "servers",
+ "text-based"
+ ],
+ "readme": "# RAI - Request-Answer-Interface\n\n**rai** is a node.js module to easily generate text based command line servers.\nWhen a client sends something to the server, the first word of the line is\ntreated as a command and the rest of the line as binary payload.\n\n[![Build Status](https://secure.travis-ci.org/andris9/rai.png)](http://travis-ci.org/andris9/rai)\n\nIn addition to line based commands, there's also a data mode, to transmit\neverygting received. And there's also an option to switch to TLS mode for\nsecure connections.\n\nThis way it is trivial to create SMTP, POP3 or similar servers.\n\n## Documentation\n\nAutogenerated docs can be seen [here](http://node.ee/raidoc/).\n\n## Installation\n\n npm install rai\n \n## Usage\n\n### Simple server\n\n var RAIServer = require(\"rai\").RAIServer;\n \n // create a RAIServer on port 1234\n var server = new RAIServer();\n server.listen(1234);\n \n // Start listening for client connections\n server.on(\"connect\", function(client){\n \n // Greet the client\n client.send(\"Hello!\");\n \n // Wait for a command\n client.on(\"command\", function(command, payload){\n \n if(command == \"STATUS\"){\n client.send(\"Status is OK!\");\n }else if(command == \"QUIT\"){\n client.send(\"Goodbye\");\n client.end();\n }else{\n client.send(\"Unknown command\");\n }\n \n });\n \n });\n\nServer only emits `'connect'` and `'error'` events, while the client \nobjects emit `'timeout'`, `'error'` and `'end'` in addition to data \nrelated events.\n\n### Starting a server\n\nServer can be started with `new RAIServer([options])` where options is an optional\nparameters object with the following properties:\n\n * **debug** - if set to true print traffic to console\n * **disconnectOnTimeout** - if set to true close the connection on disconnect\n * **secureConnection** - if set to true close the connection on disconnect\n * **credentials** - credentials for secureConnection and STARTTLS\n * **timeout** - timeout in milliseconds for disconnecting the client, defaults to 0 (no timeout)\n \nOnce the server has been set up, it can start listening for client connections\nwith `server.listen(port[, hostname][, callback])`. Callback function gets an error\nobject as a parameter if the listening failed.\n\n var server = new RAIServer();\n server.listen(25); // start listening for port 25 on \"localhost\"\n\n### Closing server\n\nServer can be closed with `server.end([callback])` where callback is run when\nthe server is finally closed.\n\n### Sending data\n\nData can be sent with `client.send(data)` where `data` is either a String or\na Buffer. `\"\\r\\n\"` is automatically appended to the data.\n\n client.send(\"Greetings!\");\n\n### Forcing connection close\n\nConnections can be ended with `client.end()`\n\n if(command == \"QUIT\"){\n client.send(\"Good bye!\");\n client.end();\n }\n\n### TLS mode\n\nTLS can be switched on with `client.startTLS([credentials][, callback])` and the status can\nbe listened with `'tls'` (emitted when secure connection is established)\n\n`credentials` is an object with strings of pem encoded `key`, `cert` and optionally an\narray `ca`. If `credentials` is not supplied, an autogenerated value is used.\n\n if(command == \"STARTTLS\"){\n client.startTLS();\n }\n \n client.on(\"tls\", function(){\n console.log(\"Switched to secure connection\");\n });\n\nIf `callback` is not set `'tls'` will be emitted on connection upgrade.\n\n### Data mode\n\nData mode can be turned on with `client.startDataMode([endSequence])` and incoming\nchunks can be received with `'data'`. The end of data mode can be detected by\n`'ready'`.\n\n`endSequence` is a String for matching the end (entire line) of the data stream.\nBy default it's `\".\"` which is suitable for SMTP and POP3.\n\n if(command == \"DATA\"){\n client.send(\"End data with <CR><LF>.<CR><LF>\");\n client.startDataMode();\n }\n\n client.on(\"data\", function(chunk){\n console.log(\"Data from client:\", chunk);\n });\n \n client.on(\"ready\", function(){\n client.send(\"Data received\");\n });\n\n## Testing\n\nThere is a possibility to set up a mockup client which sends a batch of commands\none by one to the server and returns the last response.\n\n var runClientMockup = require(\"rai\").runClientMockup;\n \n var cmds = [\"EHLO FOOBAR\", \"STARTTLS\", \"QUIT\"];\n runClientMockup(25, \"mail.hot.ee\", cmds, function(resp){\n console.log(\"Final:\", resp.toString(\"utf-8\").trim());\n });\n\n`runClientMockup` has he following parameters in the following order:\n\n * **port** - Port number\n * **host** - Hostname to connect to\n * **commands** - Command list (an array) to be sent to server\n * **callback** - Callback function to run on completion\n * **debug** - if set to true log all input/output\n\nResponse from the callback function is a Buffer and contains the\nlast data received from the server\n\n## License\n\n**MIT**",
+ "_id": "rai@0.1.6",
+ "_from": "rai@*"
+}
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/run_tests.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/run_tests.js
new file mode 100644
index 0000000..9446683
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/run_tests.js
@@ -0,0 +1,2 @@
+var reporter = require('nodeunit').reporters["default"];
+reporter.run(['test']); \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/test/rai.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/test/rai.js
new file mode 100644
index 0000000..a1af00b
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/node_modules/rai/test/rai.js
@@ -0,0 +1,589 @@
+var RAIServer = require("../lib/rai").RAIServer,
+ testCase = require('nodeunit').testCase,
+ utillib = require("util"),
+ netlib = require("net"),
+ crypto = require("crypto"),
+ tlslib = require("tls");
+
+var PORT_NUMBER = 8397;
+
+// monkey patch net and tls to support nodejs 0.4
+if(!netlib.connect && netlib.createConnection){
+ netlib.connect = netlib.createConnection;
+}
+
+if(!tlslib.connect && tlslib.createConnection){
+ tlslib.connect = tlslib.createConnection;
+}
+
+exports["General tests"] = {
+ "Create and close a server": function(test){
+ var server = new RAIServer();
+ server.listen(PORT_NUMBER, function(err){
+ test.ifError(err);
+ server.end(function(){
+ test.ok(1, "Server closed");
+ test.done();
+ });
+ });
+ },
+ "Create a secure server": function(test){
+ var server = new RAIServer({secureConnection: true});
+ server.listen(PORT_NUMBER, function(err){
+ test.ifError(err);
+ server.end(function(){
+ test.ok(1, "Server closed");
+ test.done();
+ });
+ });
+ },
+ "Duplicate server fails": function(test){
+ var server = new RAIServer();
+ server.listen(PORT_NUMBER, function(err){
+ test.ifError(err);
+
+ var duplicate = new RAIServer();
+ duplicate.listen(PORT_NUMBER, function(err){
+ test.ok(err, "Responds with error");
+ server.end(function(){
+ test.ok(1, "Server closed");
+ test.done();
+ });
+ });
+
+ });
+ },
+ "Connection event": function(test){
+ var server = new RAIServer();
+ test.expect(3);
+ server.listen(PORT_NUMBER, function(err){
+
+ server.on("connect", function(socket){
+ test.ok(socket, "Client connected");
+
+ socket.on("end", function(){
+ test.ok(1, "Connection closed");
+
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ test.ok(1, "Connected to server");
+ client.end();
+ });
+
+ });
+ },
+ "Close client socket": function(test){
+ var server = new RAIServer();
+ test.expect(4);
+ server.listen(PORT_NUMBER, function(err){
+
+ server.on("connect", function(socket){
+ test.ok(socket, "Client connected");
+
+ socket.on("end", function(){
+ test.ok(1, "Connection closed");
+
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+
+ socket.end();
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ test.ok(1, "Connected to server");
+ });
+ client.on("end", function(){
+ test.ok(1, "Connection closed by host");
+ });
+
+ });
+ },
+ "Send data to client": function(test){
+ var server = new RAIServer();
+ server.listen(PORT_NUMBER, function(err){
+
+ server.on("connect", function(socket){
+
+ socket.send("HELLO");
+
+ socket.on("end", function(){
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ client.on("data", function(chunk){
+ test.equal(chunk.toString(), "HELLO\r\n");
+ client.end();
+ });
+ });
+
+ });
+ }
+};
+
+exports["Secure connection"] = {
+ "STARTTLS with event": function(test){
+ var server = new RAIServer();
+ server.listen(PORT_NUMBER, function(err){
+
+ test.expect(2);
+
+ server.on("connect", function(socket){
+
+ socket.startTLS();
+ socket.on("tls", function(){
+ test.ok(1, "Secure connection opened");
+ socket.send("TEST");
+ });
+
+ socket.on("end", function(){
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ var sslcontext = crypto.createCredentials();
+ var pair = tlslib.createSecurePair(sslcontext, false);
+
+ pair.encrypted.pipe(client);
+ client.pipe(pair.encrypted);
+ pair.fd = client.fd;
+
+ pair.on("secure", function(){
+ pair.cleartext.on("data", function(chunk){
+ test.equal(chunk.toString(), "TEST\r\n");
+ pair.cleartext.end();
+ });
+ });
+ });
+
+ });
+ },
+ "STARTTLS Callback": function(test){
+ var server = new RAIServer();
+ server.listen(PORT_NUMBER, function(err){
+
+ test.expect(2);
+
+ server.on("connect", function(socket){
+
+ socket.startTLS(function(){
+ test.ok(1, "Secure connection opened");
+ socket.send("TEST");
+ });
+
+ socket.on("tls", function(){
+ test.ok(0, "Should not occur");
+ });
+
+ socket.on("end", function(){
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ var sslcontext = crypto.createCredentials();
+ var pair = tlslib.createSecurePair(sslcontext, false);
+
+ pair.encrypted.pipe(client);
+ client.pipe(pair.encrypted);
+ pair.fd = client.fd;
+
+ pair.on("secure", function(){
+ pair.cleartext.on("data", function(chunk){
+ test.equal(chunk.toString(), "TEST\r\n");
+ pair.cleartext.end();
+ });
+ });
+ });
+
+ });
+ },
+ "STARTTLS clears command buffer": function(test){
+ var server = new RAIServer();
+ server.listen(PORT_NUMBER, function(err){
+
+ test.expect(2);
+
+ server.on("connect", function(socket){
+
+ socket.on("command", function(command){
+ if(command == "STARTTLS"){
+ socket.startTLS();
+ socket.send("OK");
+ }else if(command == "KILL"){
+ test.ok(0, "Should not occur");
+ }else if(command == "OK"){
+ test.ok(1, "OK");
+ }
+
+ });
+
+ socket.on("tls", function(){
+ test.ok(1, "Secure connection opened");
+ socket.send("TEST");
+ });
+
+ socket.on("end", function(){
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+
+ client.write("STARTTLS\r\nKILL\r\n");
+
+ client.on("data", function(chunk){
+ if(chunk.toString("utf-8").trim() == "OK"){
+ var sslcontext = crypto.createCredentials();
+ var pair = tlslib.createSecurePair(sslcontext, false);
+
+ pair.encrypted.pipe(client);
+ client.pipe(pair.encrypted);
+ pair.fd = client.fd;
+
+ pair.on("secure", function(){
+ pair.cleartext.write("OK\r\n");
+ pair.cleartext.end();
+ });
+ }
+ });
+
+ });
+
+ });
+ },
+ "STARTTLS on secure server fails": function(test){
+ var server = new RAIServer({secureConnection: true});
+ server.listen(PORT_NUMBER, function(err){
+
+ test.expect(2);
+ server.on("connect", function(socket){
+
+ socket.on("error", function(err){
+ test.ok(err);
+ socket.end();
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("command", (function(command){
+ process.nextTick(socket.startTLS.bind(socket, function(){
+ test.ok(false, "Secure connection opened"); // should not occur
+ server.end(function(){
+ test.done();
+ });
+ }));
+
+ }).bind(this));
+
+ socket.on("tls", function(){
+ test.ok(0, "Should not occur");
+ });
+
+ });
+
+ var client = tlslib.connect(PORT_NUMBER, function(){
+ test.ok(true);
+ client.write("HELLO!\r\n");
+ });
+
+ });
+ }
+};
+
+exports["Client commands"] = {
+ "Receive Simple Command": function(test){
+ var server = new RAIServer();
+ server.listen(PORT_NUMBER, function(err){
+
+ server.on("connect", function(socket){
+
+ socket.on("command", function(command, payload){
+ test.equal(command, "STATUS");
+ test.equal(payload.toString(), "");
+ socket.end();
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ client.write("STATUS\r\n");
+ });
+
+ });
+ },
+ "Receive Command with payload": function(test){
+ var server = new RAIServer();
+ server.listen(PORT_NUMBER, function(err){
+
+ server.on("connect", function(socket){
+
+ socket.on("command", function(command, payload){
+ test.equal(command, "MAIL");
+ test.equal(payload.toString(), "TO:");
+ socket.end();
+
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ client.write("MAIL TO:\r\n");
+ });
+
+ });
+ }
+};
+
+exports["Data mode"] = {
+ "DATA mode": function(test){
+ var server = new RAIServer(),
+ datapayload = "tere\r\nvana kere";
+ server.listen(PORT_NUMBER, function(err){
+
+ server.on("connect", function(socket){
+
+ socket.startDataMode();
+
+ test.expect(2);
+
+ socket.on("data", function(chunk){
+ test.equal(datapayload, chunk.toString());
+ });
+
+ socket.on("ready", function(){
+ test.ok(1,"Data ready");
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ client.write(datapayload+"\r\n.\r\n");
+ client.end();
+ });
+
+ });
+ },
+ "Small chunks DATA mode": function(test){
+ var server = new RAIServer(),
+ datapayload = "tere\r\nvana kere õäöü\r\n.\r",
+ databytes = [],
+ fullpayload = datapayload+"\r\n.\r\n";
+ server.listen(PORT_NUMBER, function(err){
+
+ server.on("connect", function(socket){
+
+ socket.startDataMode();
+
+ test.expect(1);
+
+ socket.on("data", function(chunk){
+ databytes = databytes.concat(Array.prototype.slice.call(chunk));
+ });
+
+ socket.on("ready", function(){
+ test.equal(new Buffer(databytes).toString("utf-8"), datapayload);
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+
+ for(var i=0, len = fullpayload.length; i<len; i++){
+ socket._onReceiveData(new Buffer(fullpayload.charAt(i), "utf-8").toString("binary"));
+ }
+
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ client.end();
+ });
+
+ });
+ }
+};
+
+exports["Pipelining support"] = {
+ "Pipelining": function(test){
+ var server = new RAIServer();
+ server.listen(PORT_NUMBER, function(err){
+
+ test.expect(8);
+
+ server.on("connect", function(socket){
+
+ socket.on("command", function(command, payload){
+ if(command == "STATUS"){
+ test.ok(1, "Status received");
+ }else if(command=="DATA"){
+ test.ok(1, "data command received");
+ socket.startDataMode();
+ }else if(command=="END"){
+ test.ok(1, "all received");
+ }else{
+ test.ok(0, "Unexpected command: "+command);
+ }
+ });
+
+ socket.on("data", function(chunk){
+ test.equal(chunk.toString(), "TE\r\nST");
+ });
+
+ socket.on("ready", function(){
+ test.ok(1, "Data mode ended");
+ });
+
+ socket.on("end", function(){
+ test.ok(1, "All ready");
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ client.write("STATUS\r\nSTATUS\r\nSTATUS\r\nDATA\r\nTE\r\nST\r\n.\r\nEND\r\n");
+ client.end();
+ });
+
+ });
+ }
+};
+
+exports["Timeout tests"] = {
+ "Timeout": function(test){
+ var server = new RAIServer({timeout: 300, disconnectOnTimeout: true});
+ test.expect(3);
+ server.listen(PORT_NUMBER, function(err){
+
+ server.on("connect", function(socket){
+ test.ok(socket, "Client connected");
+
+ socket.on("timeout", function(){
+ test.ok(1, "Connection closed");
+
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ test.ok(1, "Connected to server");
+ });
+
+ });
+ },
+ "Timeout with TLS": function(test){
+ var server = new RAIServer({timeout: 300, disconnectOnTimeout: true});
+ server.listen(PORT_NUMBER, function(err){
+
+ test.expect(3);
+
+ server.on("connect", function(socket){
+
+ socket.startTLS();
+ socket.on("tls", function(){
+ test.ok(1, "Secure connection opened");
+ socket.send("TEST");
+ });
+
+ socket.on("timeout", function(){
+ test.ok(1, "Timeout occurred");
+ server.end(function(){
+ test.done();
+ });
+ });
+
+ socket.on("error", function(err){
+ test.isError(err);
+ });
+ });
+
+ var client = netlib.connect(PORT_NUMBER, function(){
+ var sslcontext = crypto.createCredentials();
+ var pair = tlslib.createSecurePair(sslcontext, false);
+
+ pair.encrypted.pipe(client);
+ client.pipe(pair.encrypted);
+ pair.fd = client.fd;
+
+ pair.on("secure", function(){
+ test.ok(1, "secure connection");
+ });
+ });
+
+ });
+ }
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/package.json b/tools/node_modules/nodemailer/node_modules/simplesmtp/package.json
new file mode 100644
index 0000000..4aa7925
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "simplesmtp",
+ "description": "Simple SMTP server module to create custom SMTP servers",
+ "version": "0.1.20",
+ "author": {
+ "name": "Andris Reinman"
+ },
+ "maintainers": [
+ {
+ "name": "andris",
+ "email": "andris@node.ee"
+ }
+ ],
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/andris9/simplesmtp.git"
+ },
+ "scripts": {
+ "test": "nodeunit test/"
+ },
+ "main": "./lib/smtp",
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://github.com/andris9/simplesmtp/blob/master/LICENSE"
+ }
+ ],
+ "dependencies": {
+ "rai": "*"
+ },
+ "devDependencies": {
+ "nodeunit": "*",
+ "mailcomposer": "*"
+ },
+ "engines": [
+ "node >=0.4.0"
+ ],
+ "keywords": [
+ "servers",
+ "text-based",
+ "smtp",
+ "email",
+ "mail",
+ "e-mail"
+ ],
+ "readme": "# simplesmtp\n\nThis is a module to easily create custom SMTP servers and clients - use SMTP as a first class protocol in Node.JS!\n\n[![Build Status](https://secure.travis-ci.org/andris9/simplesmtp.png)](http://travis-ci.org/andris9/simplesmtp)\n\n## Support simplesmtp development\n\n[![Donate to author](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DB26KWR2BQX5W)\n\n## SMTP Server\n\n### Usage\n\nCreate a new SMTP server instance with\n\n var smtp = simplesmtp.createServer([options]);\n \nAnd start listening on selected port\n\n smtp.listen(25, [function(err){}]);\n \nSMTP options can include the following:\n\n * **name** - the hostname of the server, will be used for informational messages\n * **debug** - if set to true, print out messages about the connection\n * **timeout** - client timeout in milliseconds, defaults to 60 000 (60 sec.)\n * **secureConnection** - start a server on secure connection\n * **SMTPBanner** - greeting banner that is sent to the client on connection\n * **requireAuthentication** - if set to true, require that the client must authenticate itself\n * **enableAuthentication** - if set to true, client may authenticate itself but don't have to (as opposed to `requireAuthentication` that explicitly requires clients to authenticate themselves)\n * **validateSender** - if set to true, emit `'validateSender'` with `envelope`, `email` and `callback` when the client enters `MAIL FROM:<address>`\n * **validateRecipients** - if set to true, emit `'validateRecipient'` with `envelope`, `email` and `callback` when the client enters `RCPT TO:<address>`\n * **maxSize** - maximum size of an e-mail in bytes (currently informational only)\n * **credentials** - TLS credentials (`{key:'', cert:'', ca:['']}`) for the server\n * **authMethods** - allowed authentication methods, defaults to `[\"PLAIN\", \"LOGIN\"]`\n * **disableEHLO** - if set to true, support HELO command only\n * **ignoreTLS** - if set to true, allow client do not use STARTTLS\n \n### Example\n\n var simplesmtp = require(\"simplesmtp\"),\n fs = require(\"fs\");\n\n var smtp = simplesmtp.createServer();\n smtp.listen(25);\n\n smtp.on(\"startData\", function(envelope){\n console.log(\"Message from:\", envelope.from);\n console.log(\"Message to:\", envelope.to);\n envelope.saveStream = fs.createWriteStream(\"/tmp/message.txt\");\n });\n \n smtp.on(\"data\", function(envelope, chunk){\n envelope.saveStream.write(chunk);\n });\n \n smtp.on(\"dataReady\", function(envelope, callback){\n envelope.saveStream.end();\n console.log(\"Incoming message saved to /tmp/message.txt\");\n callback(null, \"ABC1\"); // ABC1 is the queue id to be advertised to the client\n // callback(new Error(\"That was clearly a spam!\"));\n });\n\n\n### Events\n\n * **startData** *(envelope)* - DATA stream is opened by the client (`envelope` is an object with `from`, `to`, `host` and `remoteAddress` properties)\n * **data** *(envelope, chunk)* - e-mail data chunk is passed from the client \n * **dataReady** *(envelope, callback)* - client is finished passing e-mail data, `callback` returns the queue id to the client\n * **authorizeUser** *(envelope, username, password, callback)* - will be emitted if `requireAuthentication` option is set to true. `callback` has two parameters *(err, success)* where `success` is Boolean and should be true, if user is authenticated successfully\n * **validateSender** *(envelope, email, callback)* - will be emitted if `validateSender` option is set to true\n * **validateRecipient** *(envelope, email, callback)* - will be emitted it `validataRecipients` option is set to true\n * **close** *(envelope)* - emitted when the connection to client is closed\n \n## SMTP Client\n\n### Usage\n\nSMTP client can be created with `simplesmptp.connect(port[,host][, options])`\nwhere\n\n * **port** is the port to connect to\n * **host** is the hostname to connect to (defaults to \"localhost\")\n * **options** is an optional options object (see below)\n \n### Connection options\n\nThe following connection options can be used with `simplesmtp.connect`:\n\n * **secureConnection** - use SSL\n * **name** - the name of the client server\n * **auth** - authentication object `{user:\"...\", pass:\"...\"}` or `{XOAuthToken:\"base64data\"}`\n * **ignoreTLS** - ignore server support for STARTTLS\n * **debug** - output client and server messages to console\n * **instanceId** - unique instance id for debugging (will be output console with the messages)\n\n### Connection events\n\nOnce a connection is set up the following events can be listened to:\n\n * **'idle'** - the connection to the SMTP server has been successfully set up and the client is waiting for an envelope\n * **'message'** - the envelope is passed successfully to the server and a message stream can be started\n * **'ready'** `(success)` - the message was sent\n * **'rcptFailed'** `(addresses)` - not all recipients were accepted (invalid addresses are included as an array)\n * **'error'** `(err)` - An error occurred. The connection is closed and an 'end' event is emitted shortly\n * **'end'** - connection to the client is closed\n\n### Sending an envelope\n\nWhen an `'idle'` event is emitted, an envelope object can be sent to the server.\nThis includes a string `from` and an array of strings `to` property.\n\nEnvelope can be sent with `client.useEnvelope(envelope)`\n\n // run only once as 'idle' is emitted again after message delivery\n client.once(\"idle\", function(){\n client.useEnvelope({\n from: \"me@example.com\",\n to: [\"receiver1@example.com\", \"receiver2@example.com\"]\n });\n });\n\nThe `to` part of the envelope includes **all** recipients from `To:`, `Cc:` and `Bcc:` fields.\n\nIf setting the envelope up fails, an error is emitted. If only some (not all)\nrecipients are not accepted, the mail can still be sent but an `rcptFailed`\nevent is emitted.\n\n client.on(\"rcptFailed\", function(addresses){\n console.log(\"The following addresses were rejected: \", addresses);\n });\n\nIf the envelope is set up correctly a `'message'` event is emitted.\n\n### Sending a message\n\nWhen `'message'` event is emitted, it is possible to send mail. To do this\nyou can pipe directly a message source (for example an .eml file) to the client\nor alternatively you can send the message with `client.write` calls (you also\nneed to call `client.end()` once the message is completed.\n\nIf you are piping a stream to the client, do not leave the `'end'` event out,\nthis is needed to complete the message sequence by the client. \n\n client.on(\"message\", function(){\n fs.createReadStream(\"test.eml\").pipe(client);\n });\n\nOnce the message is delivered a `'ready'` event is emitted. The event has an\nparameter which indicates if the message was transmitted( (true) or not (false)\nand another which includes the last received data from the server.\n\n client.on(\"ready\", function(success, response){\n if(success){\n console.log(\"The message was transmitted successfully with \"+response);\n }\n });\n\n### XOAUTH\n\n**simplesmtp** supports [XOAUTH](https://developers.google.com/google-apps/gmail/oauth_protocol) authentication.\n\nTo use this feature you can set `XOAuthToken` param as an `auth` option\n\n var mailOptions = {\n ...,\n auth:{\n XOAuthToken: \"R0VUIGh0dHBzOi8vbWFpbC5nb29....\"\n }\n }\n\nAlternatively it is also possible to use XOAuthToken generators (supported by Nodemailer) - this\nneeds to be an object with a mandatory method `generate` that takes a callback function for\ngenerating a XOAUTH token string. This is better for generating tokens only when needed - \nthere is no need to calculate unique token for every e-mail request, since a lot of these\nmight share the same connection and thus the cleint needs not to re-authenticate itself\nwith another token.\n\n var XOGen = {\n token: \"abc\",\n generate: function(callback){\n if(1 != 1){\n return callback(new Error(\"Tokens can't be generated in strange environments\"));\n }\n callback(null, new Buffer(this.token, \"utf-8\").toString(\"base64\"));\n }\n }\n \n var mailOptions = {\n ...,\n auth:{\n XOAuthToken: XOGen\n }\n }\n\n### Error types\n\nEmitted errors include the reason for failing in the `name` property\n\n * **UnknowAuthError** - the client tried to authenticate but the method was not supported\n * **AuthError** - the username/password used were rejected\n * **TLSError** - STARTTLS failed\n * **SenderError** - the sender e-mail address was rejected\n * **RecipientError** - all recipients were rejected (if only some of the recipients are rejected, a `'rcptFailed'` event is raised instead\n\nThere's also an additional property in the error object called `data` that includes\nthe last response received from the server (if available for the current error type). \n\n### About reusing the connection\n\nYou can reuse the same connection several times but you can't send a mail\nthrough the same connection concurrently. So if you catch and `'idle'` event\nlock the connection to a message process and unlock after `'ready'`.\n\nOn `'error'` events you should reschedule the message and on `'end'` events\nyou should recreate the connection.\n\n### Closing the client\n\nBy default the client tries to keep the connection up. If you want to close it,\nrun `client.quit()` - this sends a `QUIT` command to the server and closes the\nconnection\n\n client.quit();\n\n## SMTP Client Connection pool\n\n**simplesmtp** has the option for connection pooling if you want to reuse a bulk\nof connections.\n\n### Usage\n\nCreate a connection pool of SMTP clients with\n\n simplesmtp.createClientPool(port[,host][, options])\n\nwhere\n\n * **port** is the port to connect to\n * **host** is the hostname to connect to (defaults to \"localhost\")\n * **options** is an optional options object (see below)\n\n### Connection options\n\nThe following connection options can be used with `simplesmtp.connect`:\n\n * **secureConnection** - use SSL\n * **name** - the name of the client server\n * **auth** - authentication object `{user:\"...\", pass:\"...\"}` or `{XOAuthToken:\"base64data\"}`\n * **ignoreTLS** - ignore server support for STARTTLS\n * **debug** - output client and server messages to console\n * **maxConnections** - how many connections to keep in the pool (defaults to 5)\n\n### Send an e-mail\n\nE-mails can be sent through the pool with\n\n pool.sendMail(mail[, callback])\n\nwhere\n\n * **mail** is a [MailComposer](/andris9/mailcomposer) compatible object\n * **callback** `(error, responseObj)` - is the callback function to run after the message is delivered or an error occured. `responseObj` may include `failedRecipients` which is an array with e-mail addresses that were rejected and `message` which is the last response from the server.\n\n### Errors\n\nIn addition to SMTP client errors another error name is used\n\n * **DeliveryError** - used if the message was not accepted by the SMTP server\n\n## License\n\n**MIT**\n\n",
+ "_id": "simplesmtp@0.1.20",
+ "dist": {
+ "shasum": "563c1a4203e1ed7f50b27108bb5881e5aa48a984"
+ },
+ "_from": "simplesmtp@>= 0.1.19"
+}
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/test/client.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/test/client.js
new file mode 100644
index 0000000..a6fe624
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/test/client.js
@@ -0,0 +1,444 @@
+var testCase = require('nodeunit').testCase,
+ runClientMockup = require("rai").runClientMockup,
+ simplesmtp = require("../index"),
+ fs = require("fs");
+
+var PORT_NUMBER = 8397;
+
+
+
+exports["General tests"] = {
+ setUp: function (callback) {
+ this.server = new simplesmtp.createServer();
+ this.server.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ },
+
+ tearDown: function (callback) {
+ this.server.end(callback);
+ },
+
+ "Connect and setup": function(test){
+ var client = simplesmtp.connect(PORT_NUMBER);
+
+ client.once("idle", function(){
+ // Client is ready to take messages
+ test.ok(true);
+ client.close();
+ });
+
+ client.on("error", function(err){
+ test.ok(false);
+ });
+
+ client.on("end", function(){
+ test.done();
+ });
+ }
+};
+
+exports["Secure server"] = {
+ setUp: function (callback) {
+ this.server = new simplesmtp.createServer({
+ secureConnection: true
+ });
+ this.server.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ },
+
+ tearDown: function (callback) {
+ this.server.end(callback);
+ },
+
+ "Connect and setup": function(test){
+ var client = simplesmtp.connect(PORT_NUMBER, false, {
+ secureConnection: true
+ });
+
+ client.once("idle", function(){
+ // Client is ready to take messages
+ test.ok(true);
+ client.close();
+ });
+
+ client.on("error", function(err){
+ test.ok(false);
+ });
+
+ client.on("end", function(){
+ test.done();
+ });
+ }
+};
+
+exports["Disabled EHLO"] = {
+ setUp: function (callback) {
+ this.server = new simplesmtp.createServer({disableEHLO: true});
+ this.server.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ },
+
+ tearDown: function (callback) {
+ this.server.end(callback);
+ },
+
+ "Connect and setup": function(test){
+ var client = simplesmtp.connect(PORT_NUMBER, false, {});
+
+ client.once("idle", function(){
+ // Client is ready to take messages
+ test.ok(true);
+ client.close();
+ });
+
+ client.on("error", function(err){
+ test.ok(false);
+ });
+
+ client.on("end", function(){
+ test.done();
+ });
+ }
+};
+
+exports["Authentication needed"] = {
+ setUp: function (callback) {
+ this.server = new simplesmtp.createServer({
+ requireAuthentication: true
+ });
+
+ this.server.on("authorizeUser", function(envelope, user, pass, callback){
+ callback(null, user=="test1" && pass == "test2");
+ });
+
+ this.server.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ },
+
+ tearDown: function (callback) {
+ this.server.end(callback);
+ },
+
+ "Auth success": function(test){
+ var client = simplesmtp.connect(PORT_NUMBER, false, {
+ auth: {
+ user: "test1",
+ pass: "test2"
+ }
+ });
+
+ client.once("idle", function(){
+ // Client is ready to take messages
+ test.ok(true);
+ client.close();
+ });
+
+ client.on("error", function(err){
+ test.ok(false);
+ });
+
+ client.on("end", function(){
+ test.done();
+ });
+ },
+
+ "Auth fails": function(test){
+ var client = simplesmtp.connect(PORT_NUMBER, false, {
+ auth: {
+ user: "test3",
+ pass: "test4"
+ }
+ });
+
+ client.once("idle", function(){
+ // Client is ready to take messages
+ test.ok(false); // should not occur
+ client.close();
+ });
+
+ client.on("error", function(err){
+ test.ok(true); // login failed
+ });
+
+ client.on("end", function(){
+ test.done();
+ });
+ }
+};
+
+exports["Message tests"] = {
+ setUp: function (callback) {
+ this.server = new simplesmtp.createServer({
+ validateSender: true,
+ validateRecipients: true
+ });
+
+ this.server.on("validateSender", function(envelope, email, callback){
+ callback(email != "test@node.ee"?new Error("Failed sender") : null);
+ });
+
+ this.server.on("validateRecipient", function(envelope, email, callback){
+ callback(email.split("@").pop() != "node.ee"?new Error("Failed recipient") : null);
+ });
+
+ this.server.on("dataReady", function(envelope, callback){
+ callback(null, "ABC1"); // ABC1 is the queue id to be advertised to the client
+ // callback(new Error("That was clearly a spam!"));
+ });
+
+ this.server.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ },
+
+ tearDown: function (callback) {
+ this.server.end(callback);
+ },
+
+ "Set envelope success": function(test){
+ test.expect(2);
+
+ var client = simplesmtp.connect(PORT_NUMBER, false, {});
+
+ client.once("idle", function(){
+ // Client is ready to take messages
+ test.ok(true); // waiting for envelope
+
+ client.useEnvelope({
+ from: "test@node.ee",
+ to: [
+ "test1@node.ee",
+ "test2@node.ee"
+ ]
+ });
+ });
+
+ client.on("message", function(){
+ // Client is ready to take messages
+ test.ok(true); // waiting for message
+ client.close();
+ });
+
+ client.on("error", function(err){
+ test.ok(false);
+ });
+
+ client.on("end", function(){
+ test.done();
+ });
+ },
+
+ "Set envelope fails for sender": function(test){
+ test.expect(2);
+
+ var client = simplesmtp.connect(PORT_NUMBER, false, {});
+
+ client.once("idle", function(){
+ // Client is ready to take messages
+ test.ok(true); // waiting for envelope
+
+ client.useEnvelope({
+ from: "test3@node.ee",
+ to: [
+ "test1@node.ee",
+ "test2@node.ee"
+ ]
+ });
+ });
+
+ client.on("message", function(){
+ // Client is ready to take messages
+ test.ok(false); // waiting for message
+ client.close();
+ });
+
+ client.on("error", function(err){
+ test.ok(true);
+ });
+
+ client.on("end", function(){
+ test.done();
+ });
+ },
+
+ "Set envelope fails for receiver": function(test){
+ test.expect(2);
+
+ var client = simplesmtp.connect(PORT_NUMBER, false, {});
+
+ client.once("idle", function(){
+ // Client is ready to take messages
+ test.ok(true); // waiting for envelope
+
+ client.useEnvelope({
+ from: "test@node.ee",
+ to: [
+ "test1@kreata.ee",
+ "test2@kreata.ee"
+ ]
+ });
+ });
+
+ client.on("message", function(){
+ // Client is ready to take messages
+ test.ok(false); // waiting for message
+ client.close();
+ });
+
+ client.on("error", function(err){
+ test.ok(true);
+ });
+
+ client.on("end", function(){
+ test.done();
+ });
+ },
+
+ "Set envelope partly fails": function(test){
+ test.expect(3);
+
+ var client = simplesmtp.connect(PORT_NUMBER, false, {});
+
+ client.once("idle", function(){
+ // Client is ready to take messages
+ test.ok(true); // waiting for envelope
+
+ client.useEnvelope({
+ from: "test@node.ee",
+ to: [
+ "test1@node.ee",
+ "test2@kreata.ee"
+ ]
+ });
+ });
+
+ client.on("rcptFailed", function(){
+ // Client is ready to take messages
+ test.ok(true); // waiting for message
+ });
+
+ client.on("message", function(){
+ // Client is ready to take messages
+ test.ok(true); // waiting for message
+ client.close();
+ });
+
+ client.on("error", function(err){
+ test.ok(false);
+ });
+
+ client.on("end", function(){
+ test.done();
+ });
+ },
+
+ "Send message success": function(test){
+ test.expect(3);
+
+ var client = simplesmtp.connect(PORT_NUMBER, false, {});
+
+ client.once("idle", function(){
+ // Client is ready to take messages
+ test.ok(true); // waiting for envelope
+
+ client.useEnvelope({
+ from: "test@node.ee",
+ to: [
+ "test1@node.ee",
+ "test2@node.ee"
+ ]
+ });
+ });
+
+ client.on("message", function(){
+ // Client is ready to take messages
+ test.ok(true); // waiting for message
+
+ client.write("From: abc@example.com\r\nTo:cde@example.com\r\nSubject: test\r\n\r\nHello World!");
+ client.end();
+ });
+
+ client.on("ready", function(success){
+ test.ok(success);
+ client.close();
+ });
+
+ client.on("error", function(err){
+ test.ok(false);
+ });
+
+ client.on("end", function(){
+ test.done();
+ });
+ },
+
+ "Stream message": function(test){
+ test.expect(3);
+
+ var client = simplesmtp.connect(PORT_NUMBER, false, {});
+
+ client.once("idle", function(){
+ // Client is ready to take messages
+ test.ok(true); // waiting for envelope
+
+ client.useEnvelope({
+ from: "test@node.ee",
+ to: [
+ "test1@node.ee",
+ "test2@node.ee"
+ ]
+ });
+ });
+
+ client.on("message", function(){
+ // Client is ready to take messages
+ test.ok(true); // waiting for message
+
+ // pipe file to client
+ fs.createReadStream(__dirname+"/testmessage.eml").pipe(client);
+ });
+
+ client.on("ready", function(success){
+ test.ok(success);
+ client.close();
+ });
+
+ client.on("error", function(err){
+ test.ok(false);
+ });
+
+ client.on("end", function(){
+ test.done();
+ });
+ }
+
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/test/pool.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/test/pool.js
new file mode 100644
index 0000000..84a5c05
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/test/pool.js
@@ -0,0 +1,275 @@
+var testCase = require('nodeunit').testCase,
+ runClientMockup = require("rai").runClientMockup,
+ simplesmtp = require("../index"),
+ MailComposer = require("mailcomposer").MailComposer,
+ fs = require("fs");
+
+var PORT_NUMBER = 8397;
+
+exports["General tests"] = {
+ setUp: function (callback) {
+ this.server = new simplesmtp.createServer({});
+ this.server.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ },
+
+ tearDown: function (callback) {
+ this.server.end(callback);
+ },
+
+ "Send single message": function(test){
+
+ var pool = simplesmtp.createClientPool(PORT_NUMBER),
+ mc = new MailComposer({escapeSMTP: true});
+
+ mc.setMessageOption({
+ from: "andmekala@hot.ee",
+ to: "andris@node.ee",
+ subject:"Hello!",
+ body: "Hello world!",
+ html: "<b>Hello world!</b>"
+ });
+
+ this.server.on("dataReady", function(envelope, callback){
+ test.ok(true);
+ callback();
+ });
+
+ pool.sendMail(mc, function(error){
+ test.ifError(error);
+ pool.close(function(){
+ test.ok(true);
+ test.done();
+ });
+ });
+ },
+
+ "Send several messages": function(test){
+ var total = 10;
+
+ test.expect(total*2);
+
+ var pool = simplesmtp.createClientPool(PORT_NUMBER),
+ mc;
+
+ this.server.on("dataReady", function(envelope, callback){
+ process.nextTick(callback);
+ });
+
+ var completed = 0;
+ for(var i=0; i<total; i++){
+ mc = new MailComposer({escapeSMTP: true});
+ mc.setMessageOption({
+ from: "andmekala@hot.ee",
+ to: "andris@node.ee",
+ subject:"Hello!",
+ body: "Hello world!",
+ html: "<b>Hello world!</b>"
+ });
+ pool.sendMail(mc, function(error){
+ test.ifError(error);
+ test.ok(true);
+ completed++;
+ if(completed >= total){
+ pool.close(function(){
+ test.done();
+ });
+ }
+ });
+ }
+ },
+
+ "Delivery error once": function(test){
+
+ var pool = simplesmtp.createClientPool(PORT_NUMBER),
+ mc = new MailComposer({escapeSMTP: true});
+
+ mc.setMessageOption({
+ from: "andmekala@hot.ee",
+ to: "andris@node.ee",
+ subject:"Hello!",
+ body: "Hello world!",
+ html: "<b>Hello world!</b>"
+ });
+
+ this.server.on("dataReady", function(envelope, callback){
+ test.ok(true);
+ callback(new Error("Spam!"));
+ });
+
+ pool.sendMail(mc, function(error){
+ test.equal(error && error.name, "DeliveryError");
+ pool.close(function(){
+ test.ok(true);
+ test.done();
+ });
+ });
+ },
+
+ "Delivery error several times": function(test){
+ var total = 10;
+
+ test.expect(total);
+
+ var pool = simplesmtp.createClientPool(PORT_NUMBER),
+ mc;
+
+ this.server.on("dataReady", function(envelope, callback){
+ process.nextTick(function(){callback(new Error("Spam!"));});
+ });
+
+ var completed = 0;
+ for(var i=0; i<total; i++){
+ mc = new MailComposer({escapeSMTP: true});
+ mc.setMessageOption({
+ from: "andmekala@hot.ee",
+ to: "andris@node.ee",
+ subject:"Hello!",
+ body: "Hello world!",
+ html: "<b>Hello world!</b>"
+ });
+
+ pool.sendMail(mc, function(error){
+ test.equal(error && error.name, "DeliveryError");
+ completed++;
+ if(completed >= total){
+ pool.close(function(){
+ test.done();
+ });
+ }
+ });
+ }
+ }
+};
+
+exports["Auth fail tests"] = {
+ setUp: function (callback) {
+ this.server = new simplesmtp.createServer({
+ requireAuthentication: true
+ });
+
+ this.server.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ this.server.on("authorizeUser", function(envelope, username, password, callback){
+ callback(null, username == password);
+ });
+ },
+
+ tearDown: function (callback) {
+ this.server.end(callback);
+ },
+
+ "Authentication passes once": function(test){
+ var pool = simplesmtp.createClientPool(PORT_NUMBER, false, {
+ auth: {
+ "user": "test",
+ "pass": "test"
+ }
+ }),
+ mc = new MailComposer({escapeSMTP: true});
+
+ mc.setMessageOption({
+ from: "andmekala2@hot.ee",
+ to: "andris2@node.ee",
+ subject:"Hello2!",
+ body: "Hello2 world!",
+ html: "<b>Hello2 world!</b>"
+ });
+
+ this.server.on("dataReady", function(envelope, callback){
+ test.ok(true);
+ callback();
+ });
+
+ pool.sendMail(mc, function(error){
+ test.ifError(error);
+ pool.close(function(){
+ test.ok(true);
+ test.done();
+ });
+ });
+
+ },
+
+ "Authentication error once": function(test){
+ var pool = simplesmtp.createClientPool(PORT_NUMBER, false, {
+ auth: {
+ "user": "test1",
+ "pass": "test2"
+ }
+ }),
+ mc = new MailComposer({escapeSMTP: true});
+
+ mc.setMessageOption({
+ from: "andmekala2@hot.ee",
+ to: "andris2@node.ee",
+ subject:"Hello2!",
+ body: "Hello2 world!",
+ html: "<b>Hello2 world!</b>"
+ });
+
+ this.server.on("dataReady", function(envelope, callback){
+ test.ok(true);
+ callback();
+ });
+
+ pool.sendMail(mc, function(error){
+ test.equal(error && error.name, "AuthError");
+ pool.close(function(){
+ test.ok(true);
+ test.done();
+ });
+ });
+
+ },
+
+ "Authentication error several times": function(test){
+ var total = 10;
+ test.expect(total);
+
+ var pool = simplesmtp.createClientPool(PORT_NUMBER, false, {
+ auth: {
+ "user": "test1",
+ "pass": "test2"
+ }
+ }),
+ mc;
+ this.server.on("dataReady", function(envelope, callback){
+ process.nextTick(function(){callback(new Error("Spam!"));});
+ });
+
+ var completed = 0;
+ for(var i=0; i<total; i++){
+ mc = new MailComposer({escapeSMTP: true});
+ mc.setMessageOption({
+ from: "andmekala@hot.ee",
+ to: "andris@node.ee",
+ subject:"Hello!",
+ body: "Hello world!",
+ html: "<b>Hello world!</b>"
+ });
+
+ pool.sendMail(mc, function(error){
+ test.equal(error && error.name, "AuthError");
+ completed++;
+ if(completed >= total){
+ pool.close(function(){
+ test.done();
+ });
+ }
+ });
+ }
+ }
+}; \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/test/server.js b/tools/node_modules/nodemailer/node_modules/simplesmtp/test/server.js
new file mode 100644
index 0000000..32b1ec8
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/test/server.js
@@ -0,0 +1,590 @@
+var testCase = require('nodeunit').testCase,
+ runClientMockup = require("rai").runClientMockup,
+ simplesmtp = require("../index"),
+ netlib = require("net");
+
+var PORT_NUMBER = 8397;
+
+// monkey patch net and tls to support nodejs 0.4
+if(!netlib.connect && netlib.createConnection){
+ netlib.connect = netlib.createConnection;
+}
+
+exports["General tests"] = {
+ setUp: function (callback) {
+
+ this.smtp = new simplesmtp.createServer({
+ SMTPBanner: "SCORPIO",
+ name: "MYRDO",
+ maxSize: 1234
+ });
+ this.smtp.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ },
+ tearDown: function (callback) {
+ this.smtp.end(callback);
+ },
+ "QUIT": function(test){
+ var cmds = ["QUIT"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("221",resp.toString("utf-8").trim().substr(0,3));
+ test.done();
+ });
+
+ },
+ "HELO": function(test){
+ var cmds = ["HELO FOO"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("250",resp.toString("utf-8").trim().substr(0,3));
+ test.done();
+ });
+
+ },
+ "HELO fails": function(test){
+ var cmds = ["HELO"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "EHLO": function(test){
+ var cmds = ["EHLO FOO"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ resp = resp.toString("utf-8").trim();
+ var lines = resp.split("\r\n");
+ for(var i=0; i<lines.length-1; i++){
+ test.equal("250-", lines[i].substr(0,4));
+ }
+ test.equal("250 ", lines[i].substr(0,4));
+ test.done();
+ });
+ },
+ "EHLO fails": function(test){
+ var cmds = ["EHLO"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "HELO after STARTTLS": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "HELO FOO"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("250",resp.toString("utf-8").trim().substr(0,3));
+ test.done();
+ });
+ },
+ "HELO fails after STARTTLS": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "HELO"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "EHLO after STARTTLS": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "HELO FOO"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ resp = resp.toString("utf-8").trim();
+ var lines = resp.split("\r\n");
+ for(var i=0; i<lines.length-1; i++){
+ test.equal("250-", lines[i].substr(0,4));
+ }
+ test.equal("250 ", lines[i].substr(0,4));
+ test.done();
+ });
+ },
+ "EHLO fails after STARTTLS": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH fails if not required": function(test){
+ var cmds = ["EHLO FOO", "AUTH LOGIN"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH fails if not required TLS": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "AUTH LOGIN"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "Custom Greeting banner": function(test){
+ var client = netlib.connect(PORT_NUMBER, function(){
+ client.on("data", function(chunk){
+ test.equal("SCORPIO", (chunk || "").toString().trim().split(" ").pop());
+ client.end();
+ });
+ client.on('end', function() {
+ test.done();
+ });
+ });
+ },
+ "HELO name": function(test){
+ var cmds = ["HELO FOO"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("MYRDO",resp.toString("utf-8").trim().substr(4).split(" ").shift());
+ test.done();
+ });
+ },
+ "EHLO name": function(test){
+ var cmds = ["EHLO FOO"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("MYRDO",resp.toString("utf-8").trim().substr(4).split(" ").shift());
+ test.done();
+ });
+ },
+ "MAXSIZE": function(test){
+ var cmds = ["EHLO FOO"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.ok(resp.toString("utf-8").trim().match(/^250[\- ]SIZE 1234$/mi));
+ test.done();
+ });
+ }
+};
+
+exports["EHLO setting"] = {
+ setUp: function (callback) {
+
+ this.smtp = new simplesmtp.createServer({
+ disableEHLO: true
+ });
+ this.smtp.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ },
+ tearDown: function (callback) {
+ this.smtp.end(callback);
+ },
+ "Disable EHLO": function(test){
+ runClientMockup(PORT_NUMBER, "localhost", ["EHLO foo"], function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ runClientMockup(PORT_NUMBER, "localhost", ["HELO foo"], function(resp){
+ test.equal("2",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ });
+
+ }
+};
+
+exports["Client disconnect"] = {
+
+ "Client disconnect": function(test){
+
+ var smtp = new simplesmtp.createServer(),
+ clientEnvelope;
+ smtp.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }
+
+ runClientMockup(PORT_NUMBER, "localhost", ["EHLO foo", "MAIL FROM:<andris@node.ee>", "RCPT TO:<andris@node.ee>", "DATA"], function(resp){
+ test.equal("3",resp.toString("utf-8").trim().substr(0,1));
+ });
+
+ });
+ smtp.on("startData", function(envelope){
+ clientEnvelope = envelope;
+ });
+ smtp.on("close", function(envelope){
+ test.equal(envelope, clientEnvelope);
+ smtp.end(function(){});
+ test.done();
+ });
+
+ }
+};
+
+exports["Require AUTH"] = {
+ setUp: function (callback) {
+
+ this.smtp = new simplesmtp.createServer({requireAuthentication: true});
+ this.smtp.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ this.smtp.on("authorizeUser", function(envelope, username, password, callback){
+ callback(null, username=="andris" && password=="test");
+ });
+
+ },
+ tearDown: function (callback) {
+ this.smtp.end(callback);
+ },
+ "Fail without AUTH": function(test){
+ var cmds = ["EHLO FOO", "MAIL FROM:<andris@node.ee>"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "Unknown AUTH": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH CRAM"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH fails before STARTTLS": function(test){
+ var cmds = ["EHLO FOO", "AUTH LOGIN"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH LOGIN": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH LOGIN"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("3",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH LOGIN Invalid login": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH LOGIN",
+ new Buffer("inv").toString("base64"),
+ new Buffer("alid").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH LOGIN Invalid username": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH LOGIN",
+ new Buffer("inv").toString("base64"),
+ new Buffer("test").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH LOGIN Invalid password": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH LOGIN",
+ new Buffer("andris").toString("base64"),
+ new Buffer("alid").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH LOGIN Login success": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH LOGIN",
+ new Buffer("andris").toString("base64"),
+ new Buffer("test").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("2",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("3",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN Invalid login": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN "+
+ new Buffer("inv\u0000inv\u0000alid").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN Invalid user": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN "+
+ new Buffer("inv\u0000inv\u0000test").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN Invalid password": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN "+
+ new Buffer("andris\u0000andris\u0000alid").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN Login success": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN "+
+ new Buffer("andris\u0000andris\u0000test").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("2",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN Yet another login success": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN",
+ new Buffer("andris\u0000andris\u0000test").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("2",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ }
+};
+
+exports["Enable AUTH"] = {
+ setUp: function (callback) {
+
+ this.smtp = new simplesmtp.createServer({enableAuthentication: true});
+ this.smtp.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ this.smtp.on("authorizeUser", function(envelope, username, password, callback){
+ callback(null, username=="andris" && password=="test");
+ });
+
+ },
+ tearDown: function (callback) {
+ this.smtp.end(callback);
+ },
+ "Pass without AUTH": function(test){
+ var cmds = ["EHLO FOO", "MAIL FROM:<andris@node.ee>"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("2",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "Unknown AUTH": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH CRAM"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH fails before STARTTLS": function(test){
+ var cmds = ["EHLO FOO", "AUTH LOGIN"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH LOGIN": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH LOGIN"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("3",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH LOGIN Invalid login": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH LOGIN",
+ new Buffer("inv").toString("base64"),
+ new Buffer("alid").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH LOGIN Invalid username": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH LOGIN",
+ new Buffer("inv").toString("base64"),
+ new Buffer("test").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH LOGIN Invalid password": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH LOGIN",
+ new Buffer("andris").toString("base64"),
+ new Buffer("alid").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH LOGIN Login success": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH LOGIN",
+ new Buffer("andris").toString("base64"),
+ new Buffer("test").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("2",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("3",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN Invalid login": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN "+
+ new Buffer("inv\u0000inv\u0000alid").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN Invalid user": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN "+
+ new Buffer("inv\u0000inv\u0000test").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN Invalid password": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN "+
+ new Buffer("andris\u0000andris\u0000alid").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN Login success": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN "+
+ new Buffer("andris\u0000andris\u0000test").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("2",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "AUTH PLAIN Yet another login success": function(test){
+ var cmds = ["EHLO FOO", "STARTTLS", "EHLO FOO", "AUTH PLAIN",
+ new Buffer("andris\u0000andris\u0000test").toString("base64")];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("2",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ }
+};
+
+exports["ignoreTLS"] = {
+ setUp: function (callback) {
+
+ this.smtp = new simplesmtp.createServer({requireAuthentication: true, ignoreTLS: true});
+ this.smtp.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ this.smtp.on("authorizeUser", function(envelope, username, password, callback){
+ callback(null, username=="d3ph" && password=="test");
+ });
+ },
+ tearDown: function (callback) {
+ this.smtp.end(callback);
+ },
+ "Fail without AUTH": function(test){
+ var cmds = ["EHLO FOO", "MAIL FROM:<d3ph.ru@gmail.com>"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "Fail MAIL FROM without HELO": function(test){
+ var cmds = ["MAIL FROM:<d3ph.ru@gmail.com>"];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("5",resp.toString("utf-8").trim().substr(0,1));
+ test.done();
+ });
+ },
+ "Success AUTH & SEND MAIL with <CR><LF>.<CR><LF>": function(test){
+ var cmds = ["EHLO FOO",
+ "AUTH PLAIN",
+ new Buffer("\u0000d3ph\u0000test").toString("base64"),
+ "MAIL FROM:<d3ph@github.com>",
+ "RCPT TO:<andris@node.ee>",
+ "DATA",
+ "Test mail\015\012.\015\012",
+ ];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ var resp = resp.toString("utf-8").trim();
+ test.equal("2",resp.substr(0,1));
+ test.ok(resp.match('FOOBARBAZ'));
+ test.done();
+ });
+ }
+};
+
+exports["Sending mail listen for dataReady"] = {
+ setUp: function (callback) {
+ var data = "";
+
+ this.smtp = new simplesmtp.createServer({ignoreTLS: true});
+ this.smtp.listen(PORT_NUMBER, function(err){
+ if(err){
+ throw err;
+ }else{
+ callback();
+ }
+ });
+
+ this.smtp.on("authorizeUser", function(envelope, username, password, callback){
+ callback(null, username=="d3ph" && password=="test");
+ });
+
+ this.smtp.on("data", function(envelope, chunk){
+ data += chunk;
+ });
+
+ this.smtp.on("dataReady", function(envelope, callback){
+ if (data.match('spam')) {
+ callback(true);
+ } else {
+ callback(null, '#ID');
+ }
+ });
+ },
+ tearDown: function (callback) {
+ this.smtp.end(callback);
+ },
+ "Fail send mail if body contains 'spam'": function(test){
+ var cmds = ["EHLO FOO",
+ "MAIL FROM:<d3ph@github.com>",
+ "RCPT TO:<andris@node.ee>",
+ "DATA",
+ "Test mail with spam!\015\012.\015\012",
+ ];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ test.equal("550 FAILED",resp.toString("utf-8").trim());
+ test.done();
+ });
+ },
+ "Create #ID for mail": function(test){
+ var cmds = ["EHLO FOO",
+ "MAIL FROM:<d3ph@github.com>",
+ "RCPT TO:<andris@node.ee>",
+ "DATA",
+ "Clear mail body\015\012.\015\012",
+ ];
+ runClientMockup(PORT_NUMBER, "localhost", cmds, function(resp){
+ var resp = resp.toString("utf-8").trim();
+ test.equal("2",resp.substr(0,1));
+ test.ok(resp.match('#ID'));
+ test.done();
+ });
+ }
+}
+
diff --git a/tools/node_modules/nodemailer/node_modules/simplesmtp/test/testmessage.eml b/tools/node_modules/nodemailer/node_modules/simplesmtp/test/testmessage.eml
new file mode 100644
index 0000000..5e0523e
--- /dev/null
+++ b/tools/node_modules/nodemailer/node_modules/simplesmtp/test/testmessage.eml
@@ -0,0 +1,5 @@
+From: test@node.ee
+To: test@node.ee
+Subject: Test
+
+Hello world! \ No newline at end of file
diff --git a/tools/node_modules/nodemailer/package.json b/tools/node_modules/nodemailer/package.json
new file mode 100644
index 0000000..40f6a43
--- /dev/null
+++ b/tools/node_modules/nodemailer/package.json
@@ -0,0 +1,53 @@
+{
+ "name": "nodemailer",
+ "description": "Easy to use module to send e-mails, supports unicode and SSL/TLS",
+ "version": "0.3.22",
+ "author": {
+ "name": "Andris Reinman"
+ },
+ "maintainers": [
+ {
+ "name": "andris",
+ "email": "andris@node.ee"
+ }
+ ],
+ "homepage": "http://github.com/andris9/nodemailer",
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/andris9/nodemailer.git"
+ },
+ "scripts": {
+ "test": "nodeunit test/"
+ },
+ "main": "./lib/nodemailer",
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://github.com/andris9/nodemailer/blob/master/LICENSE"
+ }
+ ],
+ "dependencies": {
+ "mailcomposer": ">= 0.1.15",
+ "simplesmtp": ">= 0.1.19"
+ },
+ "devDependencies": {
+ "nodeunit": "*"
+ },
+ "engine": {
+ "node": ">=0.4"
+ },
+ "keywords": [
+ "e-mail",
+ "mime",
+ "email",
+ "mail",
+ "sendmail",
+ "ses"
+ ],
+ "readme": "Nodemailer\n==========\n\n**Nodemailer** is an easy to use module to send e-mails with Node.JS (using\nSMTP or sendmail or Amazon SES) and is unicode friendly - You can use any characters you like ✔\n\nNodemailer is Windows friendly, you can install it with *npm* on Windows just like any other module, there are no compiled dependencies. Use it from Azure or from your Windows box hassle free.\n\nVersion v0.3 of Nodemailer is built from scratch and might break some existing scripts, so beware while upgrading. Nodemailer should be backwards compatible - if your script worked before, then it should work now, even if Nodemailer documentation differs from your code (method names, properties etc.).\n\nUse [DocumentUp](http://documentup.com/andris9/nodemailer/) to read this README\nin a more structured way (with TOC).\n\n[![Build Status](https://secure.travis-ci.org/andris9/Nodemailer.png)](http://travis-ci.org/andris9/Nodemailer)\n\n## Nodemailer supports\n\n * **Unicode** to use any characters\n * **HTML content** as well as **plain text** alternative\n * **Attachments** (including attachment **streaming** for sending larger files)\n * **Embedded images** in HTML\n * **SSL/STARTTLS** for secure e-mail delivery\n * Different transport methods - **SMTP**, **sendmail** and **Amazon SES**\n * SMTP **Connection pool** and connection reuse for rapid delivery\n * **Preconfigured** services for using SMTP with Gmail, Hotmail etc.\n * Use objects as header values for **SendGrid** SMTP API\n * **XOAUTH** authentication support and token generation (3-legged OAuth) - useful with Gmail\n * **DKIM** signing\n\n## Support Nodemailer development\n\n[![Donate to author](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DB26KWR2BQX5W)\n\n## Check out my other mail related modules\n\nIf you want to parse generated or received e-mail instead of sending it, check\nout [MailParser](https://github.com/andris9/mailparser).\n\nIf you only want to generate the raw e-mail stream, check out\n[MailComposer](https://github.com/andris9/mailcomposer).\n\nIf you only want to communicate with the SMTP (both as client and the server),\ncheck out [simplesmtp](https://github.com/andris9/simplesmtp).\n\n## Templates\n\nTo use Nodemailer with templates, please see documentation for [node-email-templates](https://github.com/niftylettuce/node-email-templates).\n\n## Example\n\nThis is a complete example to send an e-mail with plaintext and HTML body\n\n```javascript\nvar nodemailer = require(\"nodemailer\");\n\n// create reusable transport method (opens pool of SMTP connections)\nvar smtpTransport = nodemailer.createTransport(\"SMTP\",{\n service: \"Gmail\",\n auth: {\n user: \"gmail.user@gmail.com\",\n pass: \"userpass\"\n }\n});\n\n// setup e-mail data with unicode symbols\nvar mailOptions = {\n from: \"Sender Name ✔ <sender@example.com>\", // sender address\n to: \"receiver1@example.com, receiver2@example.com\", // list of receivers\n subject: \"Hello ✔\", // Subject line\n text: \"Hello world ✔\", // plaintext body\n html: \"<b>Hello world ✔</b>\" // html body\n}\n\n// send mail with defined transport object\nsmtpTransport.sendMail(mailOptions, function(error, response){\n if(error){\n console.log(error);\n }else{\n console.log(\"Message sent: \" + response.message);\n }\n\n // if you don't want to use this transport object anymore, uncomment following line\n //smtpTransport.close(); // shut down the connection pool, no more messages\n});\n```\n\nSee also the [examples folder](https://github.com/andris9/Nodemailer/tree/master/examples)\nfor full featured examples\n\n## Installation\n\nInstall through NPM\n\n```\nnpm install nodemailer\n```\n\n## Usage\n\nInclude the module\n\n```javascript\nvar nodemailer = require(\"nodemailer\");\n```\n\nAn e-mail can be sent with `sendMail(mailOptions[, callback])` command\n\n```javascript\ntransport.sendMail(mailOptions, callback);\n```\n\nWhere\n\n * `transport` is a transport method defined with `nodemailer.createTransport`\n * **mailOptions** defines the e-mail (set its subject, body text, receivers etc.), see **E-mail Message Fields** for details\n * **callback** is the callback function that will be run after the e-mail is sent or the sending failed (see **Return callback** for details)\n\n## Setting up a transport method\n\nBefore you can send any e-mails you need to set up a transport method. This can\nbe done with `nodemailer.createTransport(type, options)` where `type` indicates\nthe transport protocol and `options` defines how it is used.\n\n```javascript\nvar transport = nodemailer.createTransport(\"SMTP\", {smtp_options});\n```\n\nThe same transport object can and should be reused several times.\n\nWhen the transport method is defined, it can be used to send e-mail with `sendMail`\n\n```javascript\nvar transport = nodemailer.createTransport(\"SMTP\", {smtp_options});\n\ntransport.sendMail({\n from: \"sender@tr.ee\",\n to: \"receiver@tr.ee\"\n ...\n});\n```\n\n### Possible transport methods\n\nRequired `type` parameter can be one of the following:\n\n * **SMTP** for using SMTP\n * **SES** for using Amazon SES\n * **Sendmail** for utilizing systems *sendmail* command\n\n### Setting up SMTP\n\nSMTP is different from the other transport mechanisms, as in its case a connection\npool is created. All the connections try to stay alive as long as possible and\nare reusable to minimize the protocol overhead delay - for example setting up\nTLS for authenticating is relatively lengthy process (in CPU terms, not by human\nterms), you do not want to do it several times.\n\nPossible SMTP options are the following:\n\n * **service** - an optional well known service identifier (\"Gmail\", \"Hotmail\" etc., see **Well known Services** for a list of supported services) to auto-configure host, port and secure connection settings\n * **host** - hostname of the SMTP server (defaults to \"localhost\", not needed with `service`)\n * **port** - port of the SMTP server (defaults to 25, not needed with `service`)\n * **secureConnection** - use SSL (default is `false`, not needed with `service`). If you're using port 587 then keep `secureConnection` false, since the connection is started in insecure plain text mode and only later upgraded with STARTTLS\n * **name** - the name of the client server (defaults to machine name)\n * **auth** - authentication object as `{user:\"...\", pass:\"...\"}` or `{XOAuthToken: \"base64data\"}`\n * **ignoreTLS** - ignore server support for STARTTLS (defaults to `false`)\n * **debug** - output client and server messages to console\n * **maxConnections** - how many connections to keep in the pool (defaults to 5)\n\nExample:\n\n```javascript\nvar transport = nodemailer.createTransport(\"SMTP\", {\n service: \"Gmail\",\n auth: {\n user: \"gmail.user@gmail.com\",\n pass: \"userpass\"\n }\n});\n```\n\nor the same without `service` parameter\n\n```javascript\nvar transport = nodemailer.createTransport(\"SMTP\", {\n host: \"smtp.gmail.com\", // hostname\n secureConnection: true, // use SSL\n port: 465, // port for secure SMTP\n auth: {\n user: \"gmail.user@gmail.com\",\n pass: \"userpass\"\n }\n});\n```\n\n**NB!** if you want to close the pool (cancel all open connections) you can use `transport.close()`\n\n```javascript\n\nvar transport = nodemailer.createTransport(\"SMTP\",{});\n...\ntransport.close(); // close the pool\n```\n\n\n#### SMTP XOAUTH and token generation\n\n**nodemailer** supports XOAUTH authentication for SMTP. To use this, include `XOAuthToken` option in `auth` instead of the regular `user` and `pass`.\n\n```javascript\nvar transportOptions = {\n ...,\n auth: {\n XOAuthToken: \"R0VUIGh0dHBzOi8vbWFpbC5nb29....\"\n }\n}\n```\n\n**nodemailer** includes also built in XOAUTH token generator which can be used\nwith `nodemailer.createXOAuthGenerator()`. The function is preconfigured for\nGmail, so in this case only mandatory options are `user`, `token` and `tokenSecret`.\n\n```javascript\nvar XOAuthTokenGenerator = nodemailer.createXOAuthGenerator({\n user: \"test.nodemailer@gmail.com\",\n // requestUrl: \"https://oauth.access.point\",\n // consumerKey: \"anonymous\",\n // consumerSecret: \"anonymous\",\n token: \"1/O_HgoO4h2uOUfpus0V--7mygICXrQQ0ZajB3ZH52KqM\",\n tokenSecret: \"_mUBkIwNPnfQBUIWrJrpXJ0c\"\n });\n```\n\nOne of `user` or `requestUrl` is mandatory. `consumerKey` and `consumerSecret` both\ndefault to `\"anonymous\"`.\n\n```javascript\nvar transportOptions = {\n service: \"Gmail\",\n auth: {\n XOAuthToken: nodemailer.createXOAuthGenerator({\n user: \"test.nodemailer@gmail.com\",\n token: \"1/O_HgoO4h2uOUfpus0V--7mygICXrQQ0ZajB3ZH52KqM\",\n tokenSecret: \"_mUBkIwNPnfQBUIWrJrpXJ0c\"\n })\n }\n}\n```\n\n### Setting up SES\n\nSES is actually a HTTP based protocol, the compiled e-mail and related info\n(signatures and such) are sent as a HTTP request to SES servers.\n\nPossible SES options are the following:\n\n * **AWSAccessKeyID** - AWS access key (required)\n * **AWSSecretKey** - AWS secret (required)\n * **ServiceUrl** - optional API end point URL (defaults to *\"https://email.us-east-1.amazonaws.com\"*)\n\nExample:\n\n```javascript\nvar transport = nodemailer.createTransport(\"SES\", {\n AWSAccessKeyID: \"AWSACCESSKEY\",\n AWSSecretKey: \"AWS/Secret/key\"\n});\n```\n\n### Setting up Sendmail\n\nSendmail transport method streams the compiled message to the *stdin* of *sendmail*\ncommand.\n\nOptions object is optional, possible sendmail options are the following:\n\n * **path** - path to the `sendmail` command (defaults to *\"sendmail\"*)\n * **args** - an array of extra command line options to pass to the `sendmail` command (ie. `[\"-f sender@example.com\"]`)\n\nExample:\n\n```javascript\nvar transport = nodemailer.createTransport(\"sendmail\");\n```\n\nor\n\n```javascript\nvar transport = nodemailer.createTransport(\"sendmail\", {\n path: \"/usr/local/bin/sendmail\",\n args: [\"-f sender@example.com\"]\n});\n```\n\n### DKIM Signing\n\n**Nodemailer** supports DKIM signing with very simple setup. Use this with caution\nthough since the generated message needs to be buffered entirely before it can be\nsigned. Not a big deal with small messages but might consume a lot of RAM when\nusing larger attachments.\n\nSet up the DKIM signing with `useDKIM` method for a transport object:\n\n```javascript\ntransport.useDKIM(dkimOptions)\n```\n\nWhere `dkimOptions` includes necessary options for signing\n\n * **domainName** - the domainname that is being used for signing\n * **keySelector** - key selector. If you have set up a TXT record with DKIM public key at *zzz._domainkey.example.com* then `zzz` is the selector\n * **privateKey** - DKIM private key that is used for signing as a string\n * **headerFieldNames** - optional colon separated list of header fields to sign, by default all fields suggested by RFC4871 #5.5 are used\n\nAll messages transmitted through this transport objects are from now on DKIM signed.\n\nCurrently if several header fields with the same name exists, only the last one (the one in the bottom) is signed.\n\nExample:\n\n```javascript\nvar transport = nodemailer.createTransport(\"Sendmail\");\n\ntransport.useDKIM({\n domainName: \"node.ee\",\n keySelector: \"dkim\",\n privateKey: fs.readFileSync(\"private_key.pem\")\n});\n\ntransport.sendMail(mailOptions);\n```\n\nSee examples/example_dkim.js for a complete example.\n\n**NB!** Be careful when using services like Gmail, SES etc. through SMTP\n(SES API is handled by Nodemailer automatically) - these tend to modify some\nheaders like Message-Id or Date which invalidates the signature. In this case use\n`headerFieldNames` property to define only fields that won't be changed and leave\nout `Date` or any other unsupported field.\n\n### Well known services for SMTP\n\nIf you want to use a well known service as the SMTP host, you do not need\nto enter the hostname or port number, just use the `service` parameter (**NB!** case sensitive).\n\nCurrently cupported services are:\n\n * **\"Gmail\"** for Google Mail\n * **\"hot.ee\"** for www.hot.ee\n * **\"Hotmail\"** for Microsoft Live Hotmail\n * **\"iCloud\"** for Apple iCloud\n * **\"mail.ee\"** for www.mail.ee\n * **\"Postmark\"** for Postmark App\n * **\"SendGrid\"** for SendGrid\n * **\"SES\"** for Amazon SES\n * **\"Yahoo\"** for Yahoo Mail\n * **\"Zoho\"** for Zoho Mail\n\nPredefined service data covers `host`, `port` and secure connection settings,\nany other parameters (ie. `auth`) need to be set separately.\n\n## E-mail message fields\n\nThe following are the possible fields of an e-mail message:\n\n - **from** - The e-mail address of the sender. All e-mail addresses can be plain `sender@server.com` or formatted `Sender Name <sender@server.com>`\n - **to** - Comma separated list of recipients e-mail addresses that will appear on the `To:` field\n - **cc** - Comma separated list of recipients e-mail addresses that will appear on the `Cc:` field\n - **bcc** - Comma separated list of recipients e-mail addresses that will appear on the `Bcc:` field\n - **replyTo** - An e-mail address that will appear on the `Reply-To:` field\n - **inReplyTo** - The message-id this message is replying\n - **references** - Message-id list\n - **subject** - The subject of the e-mail\n - **text** - The plaintext version of the message\n - **html** - The HTML version of the message\n - **generateTextFromHTML** - if set to true uses HTML to generate plain text body part from the HTML if the text is not defined\n - **headers** - An object of additional header fields `{\"X-Key-Name\": \"key value\"}` (NB! values are passed as is, you should do your own encoding to 7bit if needed)\n - **attachments** - An array of attachment objects.\n - **envelope** - optional SMTP envelope, if auto generated envelope is not suitable\n - **messageId** - optional Message-Id value, random value will be generated if not set. Set to false to omit the Message-Id header\n - **encoding** - optional transfer encoding for the textual parts (defaults to \"quoted-printable\")\n\nAll text fields (e-mail addresses, plaintext body, html body) use UTF-8 as the encoding.\nAttachments are streamed as binary.\n\nExample:\n\n```javascript\nvar transport = nodemailer.createTransport(\"Sendmail\");\n\nvar mailOptions = {\n from: \"me@tr.ee\",\n to: \"me@tr.ee\",\n subject: \"Hello world!\",\n text: \"Plaintext body\"\n}\n\ntransport.sendMail(mailOptions);\n```\n\n### SendGrid support\n\nNodemailer supports SendGrid [SMTP API](http://docs.sendgrid.com/documentation/api/smtp-api/) out of the box - you can\nuse objects as header values and these are automatically JSONized (and mime encoded if needed).\n\n```javascript\nvar mailOptions = {\n ...,\n headers: {\n 'X-SMTPAPI': {\n category : \"newuser\",\n sub:{\n \"%name%\": [\"Žiguli Õllepruul\"]\n }\n }\n },\n subject: \"Hello, %name%\"\n}\n```\n\nThis also applies to any other service that expects a JSON string as a header value for specified key.\n\n### Generate Text from HTML\n\nIf `generateTextFromHTML` option is set to true, then HTML contents of the mail is automatically converted\nto plaintext format when plaintext content is empty or missing.\n\nFor example\n\n```javascript\nmailOptions = {\n ...,\n generateTextFromHTML: true,\n html: '<h1>Hello world</h1><p><b>How</b> are you?',\n // text: '' // no text part\n}\n```\n\nis automatically converted in the backround by Nodemailer to:\n\n```javascript\nmailOptions = {\n ...,\n // source html:\n html: '<h1>Hello world</h1><p><b>How</b> are you?',\n // automatically generated plaintext message:\n text: \"Hello world\\n\"+\n \"===========\\n\"+\n \"\\n\"+\n \"**How** are you?\"\n}\n```\n\nAs you can see the output syntax for `generateTextFromHTML` looks similar to markdown, and that\nis exactly the case here - Nodemailer includes a simple HTML to markdown converter. But don't\nexpect too much from it, it's not full featured or perfect, just some regexes here and there.\n\n### Attachment fields\n\nAttahcment object consists of the following properties:\n\n * **fileName** - filename to be reported as the name of the attached file, use of unicode is allowed (except when using Amazon SES which doesn't like it)\n * **cid** - optional content id for using inline images in HTML message source\n * **contents** - String or a Buffer contents for the attachment\n * **filePath** - path to a file or an URL if you want to stream the file instead of including it (better for larger attachments)\n * **streamSource** - Stream object for arbitrary binary streams if you want to stream the contents (needs to support *pause*/*resume*)\n * **contentType** - optional content type for the attachment, if not set will be derived from the `fileName` property\n * **contentDisposition** - optional content disposition type for the attachment, defaults to \"attachment\"\n\nOne of `contents`, `filePath` or `streamSource` must be specified, if none is\npresent, the attachment will be discarded. Other fields are optional.\n\nAttachments can be added as many as you want.\n\n```javascript\nvar mailOptions = {\n ...\n attachments: [\n { // utf-8 string as an attachment\n fileName: \"text1.txt\",\n contents: \"hello world!\n },\n { // binary buffer as an attachment\n fileName: \"text2.txt\",\n contents: new Buffer(\"hello world!,\"utf-8\")\n },\n { // file on disk as an attachment\n fileName: \"text3.txt\",\n filePath: \"/path/to/file.txt\" // stream this file\n },\n { // fileName and content type is derived from filePath\n filePath: \"/path/to/file.txt\"\n },\n { // stream as an attachment\n fileName: \"text4.txt\",\n streamSource: fs.createReadStream(\"file.txt\")\n },\n { // define custom content type for the attachment\n fileName: \"text.bin\",\n contents: \"hello world!,\n contentType: \"text/plain\"\n },\n { // use URL as an attachment\n fileName: \"license.txt\",\n filePath: \"https://raw.github.com/andris9/Nodemailer/master/LICENSE\"\n }\n ]\n}\n```\n\n### Address Formatting\n\nAll the e-mail addresses can be plain e-mail address\n\n```\nusername@example.com\n```\n\nor with formatted name (includes unicode support)\n\n```\n\"Ноде Майлер\" <username@example.com>\n```\n\nTo, Cc and Bcc fields accept comma separated list of e-mails. Formatting can be mixed.\n\n```\nusername@example.com, \"Ноде Майлер\" <username@example.com>, \"Name, User\" <username@example.com>\n```\n\nYou can even use unicode domain and user names, these are automatically converted\nto the supported form\n\n```\n\"Uncode Domain\" <info@müriaad-polüteism.info>\n```\n\n### SMTP envelope\n\nSMTP envelope is usually auto generated from `from`, `to`, `cc` and `bcc` fields but\nif for some reason you want to specify it yourself, you can do it with `envelope` property.\n\n`envelope` is an object with the following params: `from`, `to`, `cc` and `bcc` just like\nwith regular mail options. You can also use the regular address format.\n\n```javascript\nmailOptions = {\n ...,\n from: \"mailer@node.ee\",\n to: \"daemon@node.ee\",\n envelope: {\n from: \"Daemon <deamon@node.ee>\",\n to: \"mailer@node.ee, Mailer <mailer2@node.ee>\"\n }\n}\n```\n\n### Using Embedded Images\n\nAttachments can be used as embedded images in the HTML body. To use this\nfeature, you need to set additional property of the attachment - `cid` (unique\nidentifier of the file) which is a reference to the attachment file. The same\n`cid` value must be used as the image URL in HTML (using `cid:` as the URL\nprotocol, see example below).\n\n**NB!** the cid value should be as unique as possible!\n\n```javascript\nvar mailOptions = {\n ...\n html: \"Embedded image: <img src='cid:unique@node.ee' />\",\n attachments: [{\n filename: \"image.png\",\n filePath: \"/path/to/file\",\n cid: \"unique@node.ee\" //same cid value as in the html img src\n }]\n}\n```\n\n## Return callback\n\nReturn callback gets two parameters\n\n * **error** - an error object if the message failed\n * **responseStatus** - an object with some information about the status on success\n\nExample:\n\n```javascript\nnodemailer.sendMail(mailOptions, function(error, responseStatus){\n if(!error){\n console.log(responseStatus.message); // response from the server\n }\n});\n```\n\n## Tests\n\nRun the tests with npm in Nodemailer's directory\n\n```\nnpm test\n```\n\nThere aren't currently many tests for Nodemailer but there are a lot of tests\nin the modules that are used to generate the raw e-mail body and to use the\nSMTP client connection.\n\n## Tweaking\n\nNodemailer in itself is actually more like a wrapper for my other modules\n[mailcomposer](https://github.com/andris9/mailcomposer) for composing the raw message stream\nand [simplesmtp](https://github.com/andris9/simplesmtp) for delivering it, by providing an\nunified API. If there's some problems with particular parts of the\nmessage composing/sending process you should look at the appropriate module.\n\n## License\n\n**Nodemailer** is licensed under [MIT license](https://github.com/andris9/Nodemailer/blob/master/LICENSE). Basically you can do whatever you want to with it.\n",
+ "_id": "nodemailer@0.3.22",
+ "dist": {
+ "shasum": "be91fa155ba9c110ff35663073d5d7159d25d4b9"
+ },
+ "_from": "nodemailer@0.3.22"
+}
diff --git a/tools/node_modules/nodemailer/test/nodemailer.js b/tools/node_modules/nodemailer/test/nodemailer.js
new file mode 100644
index 0000000..777473c
--- /dev/null
+++ b/tools/node_modules/nodemailer/test/nodemailer.js
@@ -0,0 +1,201 @@
+var testCase = require('nodeunit').testCase,
+ nodemailer = require("../lib/nodemailer"),
+ stripHTML = require("../lib/helpers").stripHTML;
+
+exports["General tests"] = {
+
+ "Create a new Nodemailer object": function(test){
+ // this is more like a stub here
+ var mail = new nodemailer.Nodemailer();
+ test.done();
+ },
+
+ "stripHTML": function(test){
+
+ var html = "<h1>Tere &raquo;</h1><ul><li>Test</li></ul>",
+ output = "Tere »\n======\n\n * Test";
+
+ test.equal(stripHTML(html).trim(), output);
+ test.done();
+ },
+
+ "generate XOAuthToken": function(test){
+ nodemailer.createXOAuthGenerator({
+ user: "test.nodemailer@gmail.com",
+ consumerKey: "anonymous", // optional
+ consumerSecret: "anonymous", // optional
+ token: "1/O_HgoO4h2uOUfpus0V--7mygICXrQQ0ZajB3ZH52KqM",
+ tokenSecret: "_mUBkIwNPnfQBUIWrJrpXJ0c",
+ timestamp: "1332499914",
+ nonce: "3595015741981970681"
+ }).generate(function(err, token){
+ test.equal(token, "R0VUIGh0dHBzOi8vbWFpbC5nb29nbGUuY29tL21haWwvYi90ZXN0Lm5vZGVtYWlsZXJAZ21haWwuY29tL3NtdHAvIG9hdXRoX2NvbnN1bWVyX2tleT0iYW5vbnltb3VzIixvYXV0aF9ub25jZT0iMzU5NTAxNTc0MTk4MTk3MDY4MSIsb2F1dGhfc2lnbmF0dXJlPSJZZkt4QlJHZnRkMUx0bk5LMXM5d25QUjM5UnclM0QiLG9hdXRoX3NpZ25hdHVyZV9tZXRob2Q9IkhNQUMtU0hBMSIsb2F1dGhfdGltZXN0YW1wPSIxMzMyNDk5OTE0IixvYXV0aF90b2tlbj0iMSUyRk9fSGdvTzRoMnVPVWZwdXMwVi0tN215Z0lDWHJRUTBaYWpCM1pINTJLcU0iLG9hdXRoX3ZlcnNpb249IjEuMCI=");
+ test.done();
+ });
+
+ },
+
+ "generate XOAuthToken with defaults": function(test){
+ nodemailer.createXOAuthGenerator({
+ user: "test.nodemailer@gmail.com",
+ token: "1/O_HgoO4h2uOUfpus0V--7mygICXrQQ0ZajB3ZH52KqM",
+ tokenSecret: "_mUBkIwNPnfQBUIWrJrpXJ0c",
+ timestamp: "1332499914",
+ nonce: "3595015741981970681"
+ }).generate(function(err, token){
+ test.equal(token, "R0VUIGh0dHBzOi8vbWFpbC5nb29nbGUuY29tL21haWwvYi90ZXN0Lm5vZGVtYWlsZXJAZ21haWwuY29tL3NtdHAvIG9hdXRoX2NvbnN1bWVyX2tleT0iYW5vbnltb3VzIixvYXV0aF9ub25jZT0iMzU5NTAxNTc0MTk4MTk3MDY4MSIsb2F1dGhfc2lnbmF0dXJlPSJZZkt4QlJHZnRkMUx0bk5LMXM5d25QUjM5UnclM0QiLG9hdXRoX3NpZ25hdHVyZV9tZXRob2Q9IkhNQUMtU0hBMSIsb2F1dGhfdGltZXN0YW1wPSIxMzMyNDk5OTE0IixvYXV0aF90b2tlbj0iMSUyRk9fSGdvTzRoMnVPVWZwdXMwVi0tN215Z0lDWHJRUTBaYWpCM1pINTJLcU0iLG9hdXRoX3ZlcnNpb249IjEuMCI=");
+ test.done();
+ });
+
+ },
+
+ "Use default Message-Id value": function(test){
+ var transport = nodemailer.createTransport("Stub"),
+ mailOptions = {};
+
+ transport.sendMail(mailOptions, function(error, response){
+ test.ifError(error);
+ var regex = "^Message\\-Id:\\s*<[0-9\.a-fA-F]+@"+nodemailer.X_MAILER_NAME.replace(/([\(\)\\\.\[\]\-\?\:\!\{\}])/g, "\\$1")+">$";
+ test.ok(response.message.match(new RegExp(regex, "m")));
+ test.done();
+ })
+ },
+
+ "Use custom Message-Id value": function(test){
+ var transport = nodemailer.createTransport("Stub"),
+ mailOptions = {
+ messageId: "ABCDEF"
+ };
+
+ transport.sendMail(mailOptions, function(error, response){
+ test.ifError(error);
+ test.ok(response.message.match(/Message\-Id:\s*<ABCDEF>/));
+ // default not present
+ var regex = "^Message\\-Id:\\s*<[0-9\.a-fA-F]+@"+nodemailer.X_MAILER_NAME.replace(/([\(\)\\\.\[\]\-\?\:\!\{\}])/g, "\\$1")+">$";
+ test.ok(!response.message.match(new RegExp(regex, "m")));
+ test.done();
+ })
+ },
+
+ "Use In-Reply-To": function(test){
+ var transport = nodemailer.createTransport("Stub"),
+ mailOptions = {
+ inReplyTo: "abc"
+ };
+
+ transport.sendMail(mailOptions, function(error, response){
+ test.ifError(error);
+ test.ok(response.message.match(/^In\-Reply\-To:\s*<abc>$/m));
+ test.done();
+ })
+ },
+
+ "Use References": function(test){
+ var transport = nodemailer.createTransport("Stub"),
+ mailOptions = {
+ references: ["abc def <ghi>", "jkl"]
+ };
+
+ transport.sendMail(mailOptions, function(error, response){
+ test.ifError(error);
+ test.ok(response.message.match(/^References:\s*<abc> <def> <ghi> <jkl>$/m));
+ test.done();
+ })
+ },
+
+ "Skip Message-Id value": function(test){
+ var transport = nodemailer.createTransport("Stub"),
+ mailOptions = {
+ messageId: false
+ };
+
+ transport.sendMail(mailOptions, function(error, response){
+ test.ifError(error);
+ test.ok(!response.message.match(/Message\-Id:/i));
+ test.done();
+ });
+ },
+
+ "Use custom envelope": function(test){
+ var transport = nodemailer.createTransport("Stub"),
+ mailOptions = {
+ from: "sender1@tr.ee",
+ to: "receiver1@tr.ee",
+ envelope: {
+ from: "sender2@tr.ee",
+ to: "receiver2@tr.ee",
+ }
+ };
+
+ transport.sendMail(mailOptions, function(error, response){
+ test.ifError(error);
+ test.deepEqual(response.envelope, {from:'sender2@tr.ee',to: [ 'receiver2@tr.ee' ],stamp: 'Postage paid, Par Avion'})
+ test.done();
+ })
+ },
+
+ "Use default envelope": function(test){
+ var transport = nodemailer.createTransport("Stub"),
+ mailOptions = {
+ from: "sender1@tr.ee",
+ to: "receiver1@tr.ee"
+ };
+
+ transport.sendMail(mailOptions, function(error, response){
+ test.ifError(error);
+ test.deepEqual(response.envelope, {from:'sender1@tr.ee',to: [ 'receiver1@tr.ee' ],stamp: 'Postage paid, Par Avion'})
+ test.done();
+ })
+ }
+};
+
+exports["Transport close"] = {
+ "SMTP - Callback in transport.close": function(test){
+ var transport = nodemailer.createTransport("SMTP", {});
+ transport.close(function(){
+ test.ok(true);
+ test.done();
+ });
+ },
+
+ "SMTP - No callback in transport.close": function(test){
+ var transport = nodemailer.createTransport("SMTP", {});
+ transport.close();
+ process.nextTick(function(){
+ test.ok(true);
+ test.done();
+ });
+ },
+ "Sendmail - Callback in transport.close": function(test){
+ var transport = nodemailer.createTransport("Sendmail", {});
+ transport.close(function(){
+ test.ok(true);
+ test.done();
+ });
+ },
+
+ "Sendmail - No callback in transport.close": function(test){
+ var transport = nodemailer.createTransport("Sendmail", {});
+ transport.close();
+ process.nextTick(function(){
+ test.ok(true);
+ test.done();
+ });
+ },
+ "SES - Callback in transport.close": function(test){
+ var transport = nodemailer.createTransport("SES", {});
+ transport.close(function(){
+ test.ok(true);
+ test.done();
+ });
+ },
+
+ "SES - No callback in transport.close": function(test){
+ var transport = nodemailer.createTransport("SES", {});
+ transport.close();
+ process.nextTick(function(){
+ test.ok(true);
+ test.done();
+ });
+ }
+};