From e8f8a1ad1ff78f295fdaefaa310e036e52172660 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Fri, 25 Aug 2017 15:15:34 -0700 Subject: [PATCH] Kill PhantomShim. (#533) This patch kills PhantomShim, a lightweight layer that helped to bootstrap Puppeteer API. At this point, PhantomShim: - passes 139 phantomJS tests - fails 13 tests - lacks capabilities to run 26 The failings and unsupported tests don't have any value for Puppeteer API, so it doesn't make sense to maintain PhantomShim any longer. --- .npmignore | 4 - .travis.yml | 1 - package.json | 1 - phantom_shim/FileSystem.js | 375 - phantom_shim/Phantom.js | 142 - phantom_shim/README.md | 21 - phantom_shim/System.js | 118 - phantom_shim/WebPage.js | 748 -- phantom_shim/WebServer.js | 83 - phantom_shim/runner.js | 115 - phantom_shim/utilities.js | 32 - third_party/phantomjs/CHANGES.md | 19 - third_party/phantomjs/LICENSE.BSD | 22 - third_party/phantomjs/bootstrap.js | 235 - third_party/phantomjs/examples/arguments.js | 10 - .../examples/child_process-examples.js | 28 - third_party/phantomjs/examples/colorwheel.js | 52 - third_party/phantomjs/examples/countdown.js | 10 - third_party/phantomjs/examples/detectsniff.js | 60 - third_party/phantomjs/examples/echoToFile.js | 24 - third_party/phantomjs/examples/features.js | 30 - third_party/phantomjs/examples/fibo.js | 10 - third_party/phantomjs/examples/hello.js | 3 - third_party/phantomjs/examples/injectme.js | 26 - third_party/phantomjs/examples/loadspeed.js | 24 - .../phantomjs/examples/loadurlwithoutcss.js | 26 - third_party/phantomjs/examples/modernizr.js | 1406 --- third_party/phantomjs/examples/module.js | 5 - third_party/phantomjs/examples/netlog.js | 26 - third_party/phantomjs/examples/netsniff.js | 144 - .../phantomjs/examples/openurlwithproxy.js | 25 - .../phantomjs/examples/outputEncoding.js | 17 - third_party/phantomjs/examples/page_events.js | 147 - .../phantomjs/examples/pagecallback.js | 18 - .../phantomjs/examples/phantomwebintro.js | 21 - third_party/phantomjs/examples/post.js | 15 - third_party/phantomjs/examples/postjson.js | 19 - third_party/phantomjs/examples/postserver.js | 35 - third_party/phantomjs/examples/printenv.js | 10 - .../phantomjs/examples/printheaderfooter.js | 90 - .../phantomjs/examples/printmargins.js | 36 - third_party/phantomjs/examples/rasterize.js | 49 - .../phantomjs/examples/render_multi_url.js | 74 - .../examples/responsive-screenshot.js | 181 - third_party/phantomjs/examples/run-jasmine.js | 92 - .../phantomjs/examples/run-jasmine2.js | 94 - third_party/phantomjs/examples/run-qunit.js | 77 - third_party/phantomjs/examples/scandir.js | 24 - third_party/phantomjs/examples/server.js | 44 - .../phantomjs/examples/serverkeepalive.js | 35 - .../phantomjs/examples/simpleserver.js | 43 - third_party/phantomjs/examples/sleepsort.js | 27 - .../phantomjs/examples/stdin-stdout-stderr.js | 19 - third_party/phantomjs/examples/universe.js | 10 - third_party/phantomjs/examples/unrandomize.js | 25 - third_party/phantomjs/examples/useragent.js | 15 - third_party/phantomjs/examples/version.js | 6 - third_party/phantomjs/examples/waitfor.js | 58 - .../phantomjs/examples/walk_through_frames.js | 73 - third_party/phantomjs/test/basics/exit0.js | 8 - third_party/phantomjs/test/basics/exit23.js | 8 - third_party/phantomjs/test/basics/module.js | 27 - .../phantomjs/test/basics/phantom-object.js | 39 - third_party/phantomjs/test/basics/require.js | 10 - .../phantomjs/test/basics/require/a.js | 2 - .../phantomjs/test/basics/require/b.js | 2 - .../test/basics/require/dir/dummy.js | 1 - .../test/basics/require/dir/subdir/dummy.js | 1 - .../test/basics/require/dir/subdir/loader.js | 1 - .../test/basics/require/dir/subdir2/loader.js | 1 - .../phantomjs/test/basics/require/dummy.js | 1 - .../phantomjs/test/basics/require/empty.js | 0 .../test/basics/require/json_dummy.json | 3 - .../basics/require/node_modules/dummy_file.js | 1 - .../dummy_module/libdir/dummy_module.js | 1 - .../node_modules/dummy_module/package.json | 4 - .../node_modules/dummy_module2/index.js | 1 - .../test/basics/require/not_found.js | 3 - .../test/basics/require/require_spec.js | 131 - .../phantomjs/test/basics/require/stubber.js | 5 - .../test/basics/require/stubber_child.js | 1 - .../phantomjs/test/basics/require/thrower.js | 3 - .../phantomjs/test/basics/stacktrace.js | 12 - .../phantomjs/test/basics/test-server.js | 33 - third_party/phantomjs/test/basics/timeout.js | 7 - .../phantomjs/test/basics/url-utils.js | 16 - third_party/phantomjs/test/basics/version.js | 7 - .../phantomjs/test/certs/https-snakeoil.crt | 18 - .../phantomjs/test/certs/https-snakeoil.key | 28 - third_party/phantomjs/test/fixtures/dummy.js | 1 - .../phantomjs/test/fixtures/error-helper.js | 9 - .../test/fixtures/parse-error-helper.js | 2 - .../test/manual/standards/ecma-test262.js | 36 - .../test/module/cookiejar/cookiejar.js | 93 - .../phantomjs/test/module/cookiejar/to-map.js | 52 - .../phantomjs/test/module/fs/basics.js | 220 - .../phantomjs/test/module/fs/fileattrs.js | 91 - third_party/phantomjs/test/module/fs/paths.js | 72 - .../phantomjs/test/module/system/stdin.js | 22 - .../test/module/system/stdout-err.js | 14 - .../phantomjs/test/module/system/system.js | 77 - .../module/webpage/abort-network-request.js | 36 - .../test/module/webpage/add-header.js | 24 - .../phantomjs/test/module/webpage/callback.js | 16 - .../test/module/webpage/capture-content.js | 50 - .../webpage/change-request-encoded-url.js | 26 - .../test/module/webpage/change-request-url.js | 40 - .../test/module/webpage/cjk-text-codecs.js | 33 - .../test/module/webpage/clip-rect.js | 19 - .../webpage/construction-with-options.js | 59 - .../test/module/webpage/contextclick-event.js | 32 - .../phantomjs/test/module/webpage/cookies.js | 112 - .../test/module/webpage/custom-headers.js | 30 - .../module/webpage/evaluate-broken-json.js | 14 - .../test/module/webpage/file-upload.js | 54 - .../webpage/frame-switching-deprecated.js | 68 - .../test/module/webpage/frame-switching.js | 97 - .../test/module/webpage/https-bad-cert.js | 15 - .../test/module/webpage/https-good-cert.js | 14 - .../test/module/webpage/includejs.js | 42 - .../test/module/webpage/keydown-event.js | 20 - .../test/module/webpage/keypress-event.js | 67 - .../test/module/webpage/keyup-event.js | 20 - .../phantomjs/test/module/webpage/loading.js | 21 - .../webpage/local-urls-disabled-iframe.js | 23 - .../module/webpage/local-urls-disabled.js | 22 - .../webpage/local-urls-enabled-iframe.js | 23 - .../test/module/webpage/local-urls-enabled.js | 23 - .../module/webpage/long-running-javascript.js | 18 - .../test/module/webpage/modify-header.js | 27 - .../test/module/webpage/mouseclick-event.js | 38 - .../module/webpage/mousedoubleclick-event.js | 30 - .../test/module/webpage/mousedown-event.js | 26 - .../test/module/webpage/mousemove-event.js | 18 - .../test/module/webpage/mouseup-event.js | 26 - .../test/module/webpage/navigation.js | 31 - .../test/module/webpage/no-plugin.js | 19 - .../phantomjs/test/module/webpage/object.js | 77 - .../test/module/webpage/on-confirm.js | 33 - .../phantomjs/test/module/webpage/on-error.js | 110 - .../test/module/webpage/on-initialized.js | 21 - .../phantomjs/test/module/webpage/open.js | 53 - .../phantomjs/test/module/webpage/postdata.js | 47 - .../phantomjs/test/module/webpage/prompt.js | 16 - .../test/module/webpage/remove-header.js | 26 - .../phantomjs/test/module/webpage/render.js | 68 - .../test/module/webpage/renders/index.js | 7 - .../test/module/webpage/renders/test.jpg | Bin 6818 -> 0 bytes .../test/module/webpage/renders/test.pdf | Bin 27123 -> 0 bytes .../test/module/webpage/renders/test.png | Bin 67174 -> 0 bytes .../test/module/webpage/renders/test50.jpg | Bin 4930 -> 0 bytes .../test/module/webpage/repaint-requested.js | 20 - .../module/webpage/resource-received-error.js | 33 - .../module/webpage/resource-request-error.js | 27 - .../test/module/webpage/scroll-position.js | 18 - .../test/module/webpage/set-content.js | 20 - .../test/module/webpage/subwindows.js | 130 - .../test/module/webpage/url-encoding.js | 134 - .../test/module/webpage/user-agent.js | 22 - .../test/module/webpage/viewport-size.js | 17 - .../phantomjs/test/module/webpage/window.js | 4 - .../test/module/webpage/zoom-factor.js | 18 - .../phantomjs/test/module/webserver/basics.js | 25 - .../test/module/webserver/requests.js | 179 - .../test/node_modules/dummy_exposed.js | 1 - .../phantomjs/test/node_modules/dummy_file.js | 1 - .../test/node_modules/dummy_file2.js | 1 - third_party/phantomjs/test/regression/README | 3 - .../phantomjs/test/regression/pjs-10690.js | 14 - .../phantomjs/test/regression/pjs-12482.js | 48 - .../phantomjs/test/regression/pjs-13551.js | 52 - .../phantomjs/test/regression/webkit-60448.js | 12 - third_party/phantomjs/test/run-tests.py | 1051 -- .../test/standards/console/console_log.js | 9 - .../test/standards/javascript/date.js | 12 - .../test/standards/javascript/function.js | 46 - third_party/phantomjs/test/testharness.js | 1489 --- third_party/phantomjs/test/writing-tests.md | 596 -- third_party/phantomjs/test/www/__init__.py | 2 - third_party/phantomjs/test/www/delay.py | 15 - third_party/phantomjs/test/www/echo.py | 29 - .../phantomjs/test/www/frameset/frame1-1.html | 8 - .../phantomjs/test/www/frameset/frame1-2.html | 8 - .../phantomjs/test/www/frameset/frame1.html | 9 - .../phantomjs/test/www/frameset/frame2-1.html | 8 - .../phantomjs/test/www/frameset/frame2-2.html | 8 - .../phantomjs/test/www/frameset/frame2-3.html | 8 - .../phantomjs/test/www/frameset/frame2.html | 10 - .../phantomjs/test/www/frameset/index.html | 9 - third_party/phantomjs/test/www/hello.html | 8 - third_party/phantomjs/test/www/iframe.html | 17 - third_party/phantomjs/test/www/includejs.js | 3 - .../phantomjs/test/www/includejs1.html | 2 - .../phantomjs/test/www/includejs2.html | 2 - .../phantomjs/test/www/js-infinite-loop.html | 12 - third_party/phantomjs/test/www/logo.html | 8 - third_party/phantomjs/test/www/logo.png | Bin 22055 -> 0 bytes .../phantomjs/test/www/missing-img.html | 8 - .../phantomjs/test/www/navigation/dest.html | 2 - .../phantomjs/test/www/navigation/index.html | 2 - third_party/phantomjs/test/www/phantomjs.png | Bin 26905 -> 0 bytes .../www/regression/pjs-10690/Windsong.ttf | Bin 84852 -> 0 bytes .../test/www/regression/pjs-10690/font.css | 7 - .../test/www/regression/pjs-10690/index.html | 9 - .../test/www/regression/pjs-10690/jquery.js | 9441 ----------------- .../test/www/regression/pjs-13551/child1.html | 2 - .../www/regression/pjs-13551/child1a.html | 12 - .../test/www/regression/pjs-13551/child2.html | 9 - .../regression/pjs-13551/closing-parent.html | 23 - .../pjs-13551/reloading-parent.html | 22 - .../test/www/regression/webkit-60448.html | 15 - .../phantomjs/test/www/render/image.jpg | Bin 19583 -> 0 bytes .../phantomjs/test/www/render/index.html | 15 - third_party/phantomjs/test/www/status.py | 50 - .../phantomjs/test/www/url-encoding.py | 85 - .../phantomjs/test/www/user-agent.html | 9 - 216 files changed, 21793 deletions(-) delete mode 100644 phantom_shim/FileSystem.js delete mode 100644 phantom_shim/Phantom.js delete mode 100644 phantom_shim/README.md delete mode 100644 phantom_shim/System.js delete mode 100644 phantom_shim/WebPage.js delete mode 100644 phantom_shim/WebServer.js delete mode 100755 phantom_shim/runner.js delete mode 100644 phantom_shim/utilities.js delete mode 100644 third_party/phantomjs/CHANGES.md delete mode 100644 third_party/phantomjs/LICENSE.BSD delete mode 100644 third_party/phantomjs/bootstrap.js delete mode 100644 third_party/phantomjs/examples/arguments.js delete mode 100644 third_party/phantomjs/examples/child_process-examples.js delete mode 100644 third_party/phantomjs/examples/colorwheel.js delete mode 100644 third_party/phantomjs/examples/countdown.js delete mode 100644 third_party/phantomjs/examples/detectsniff.js delete mode 100644 third_party/phantomjs/examples/echoToFile.js delete mode 100644 third_party/phantomjs/examples/features.js delete mode 100644 third_party/phantomjs/examples/fibo.js delete mode 100644 third_party/phantomjs/examples/hello.js delete mode 100644 third_party/phantomjs/examples/injectme.js delete mode 100644 third_party/phantomjs/examples/loadspeed.js delete mode 100644 third_party/phantomjs/examples/loadurlwithoutcss.js delete mode 100644 third_party/phantomjs/examples/modernizr.js delete mode 100644 third_party/phantomjs/examples/module.js delete mode 100644 third_party/phantomjs/examples/netlog.js delete mode 100644 third_party/phantomjs/examples/netsniff.js delete mode 100644 third_party/phantomjs/examples/openurlwithproxy.js delete mode 100644 third_party/phantomjs/examples/outputEncoding.js delete mode 100644 third_party/phantomjs/examples/page_events.js delete mode 100644 third_party/phantomjs/examples/pagecallback.js delete mode 100644 third_party/phantomjs/examples/phantomwebintro.js delete mode 100644 third_party/phantomjs/examples/post.js delete mode 100644 third_party/phantomjs/examples/postjson.js delete mode 100644 third_party/phantomjs/examples/postserver.js delete mode 100644 third_party/phantomjs/examples/printenv.js delete mode 100644 third_party/phantomjs/examples/printheaderfooter.js delete mode 100644 third_party/phantomjs/examples/printmargins.js delete mode 100644 third_party/phantomjs/examples/rasterize.js delete mode 100644 third_party/phantomjs/examples/render_multi_url.js delete mode 100644 third_party/phantomjs/examples/responsive-screenshot.js delete mode 100644 third_party/phantomjs/examples/run-jasmine.js delete mode 100644 third_party/phantomjs/examples/run-jasmine2.js delete mode 100644 third_party/phantomjs/examples/run-qunit.js delete mode 100644 third_party/phantomjs/examples/scandir.js delete mode 100644 third_party/phantomjs/examples/server.js delete mode 100644 third_party/phantomjs/examples/serverkeepalive.js delete mode 100644 third_party/phantomjs/examples/simpleserver.js delete mode 100644 third_party/phantomjs/examples/sleepsort.js delete mode 100644 third_party/phantomjs/examples/stdin-stdout-stderr.js delete mode 100644 third_party/phantomjs/examples/universe.js delete mode 100644 third_party/phantomjs/examples/unrandomize.js delete mode 100644 third_party/phantomjs/examples/useragent.js delete mode 100644 third_party/phantomjs/examples/version.js delete mode 100644 third_party/phantomjs/examples/waitfor.js delete mode 100644 third_party/phantomjs/examples/walk_through_frames.js delete mode 100644 third_party/phantomjs/test/basics/exit0.js delete mode 100644 third_party/phantomjs/test/basics/exit23.js delete mode 100644 third_party/phantomjs/test/basics/module.js delete mode 100644 third_party/phantomjs/test/basics/phantom-object.js delete mode 100644 third_party/phantomjs/test/basics/require.js delete mode 100644 third_party/phantomjs/test/basics/require/a.js delete mode 100644 third_party/phantomjs/test/basics/require/b.js delete mode 100644 third_party/phantomjs/test/basics/require/dir/dummy.js delete mode 100644 third_party/phantomjs/test/basics/require/dir/subdir/dummy.js delete mode 100644 third_party/phantomjs/test/basics/require/dir/subdir/loader.js delete mode 100644 third_party/phantomjs/test/basics/require/dir/subdir2/loader.js delete mode 100644 third_party/phantomjs/test/basics/require/dummy.js delete mode 100644 third_party/phantomjs/test/basics/require/empty.js delete mode 100644 third_party/phantomjs/test/basics/require/json_dummy.json delete mode 100644 third_party/phantomjs/test/basics/require/node_modules/dummy_file.js delete mode 100644 third_party/phantomjs/test/basics/require/node_modules/dummy_module/libdir/dummy_module.js delete mode 100644 third_party/phantomjs/test/basics/require/node_modules/dummy_module/package.json delete mode 100644 third_party/phantomjs/test/basics/require/node_modules/dummy_module2/index.js delete mode 100644 third_party/phantomjs/test/basics/require/not_found.js delete mode 100644 third_party/phantomjs/test/basics/require/require_spec.js delete mode 100644 third_party/phantomjs/test/basics/require/stubber.js delete mode 100644 third_party/phantomjs/test/basics/require/stubber_child.js delete mode 100644 third_party/phantomjs/test/basics/require/thrower.js delete mode 100644 third_party/phantomjs/test/basics/stacktrace.js delete mode 100644 third_party/phantomjs/test/basics/test-server.js delete mode 100644 third_party/phantomjs/test/basics/timeout.js delete mode 100644 third_party/phantomjs/test/basics/url-utils.js delete mode 100644 third_party/phantomjs/test/basics/version.js delete mode 100644 third_party/phantomjs/test/certs/https-snakeoil.crt delete mode 100644 third_party/phantomjs/test/certs/https-snakeoil.key delete mode 100644 third_party/phantomjs/test/fixtures/dummy.js delete mode 100644 third_party/phantomjs/test/fixtures/error-helper.js delete mode 100644 third_party/phantomjs/test/fixtures/parse-error-helper.js delete mode 100644 third_party/phantomjs/test/manual/standards/ecma-test262.js delete mode 100644 third_party/phantomjs/test/module/cookiejar/cookiejar.js delete mode 100644 third_party/phantomjs/test/module/cookiejar/to-map.js delete mode 100644 third_party/phantomjs/test/module/fs/basics.js delete mode 100644 third_party/phantomjs/test/module/fs/fileattrs.js delete mode 100644 third_party/phantomjs/test/module/fs/paths.js delete mode 100644 third_party/phantomjs/test/module/system/stdin.js delete mode 100644 third_party/phantomjs/test/module/system/stdout-err.js delete mode 100644 third_party/phantomjs/test/module/system/system.js delete mode 100644 third_party/phantomjs/test/module/webpage/abort-network-request.js delete mode 100644 third_party/phantomjs/test/module/webpage/add-header.js delete mode 100644 third_party/phantomjs/test/module/webpage/callback.js delete mode 100644 third_party/phantomjs/test/module/webpage/capture-content.js delete mode 100644 third_party/phantomjs/test/module/webpage/change-request-encoded-url.js delete mode 100644 third_party/phantomjs/test/module/webpage/change-request-url.js delete mode 100644 third_party/phantomjs/test/module/webpage/cjk-text-codecs.js delete mode 100644 third_party/phantomjs/test/module/webpage/clip-rect.js delete mode 100644 third_party/phantomjs/test/module/webpage/construction-with-options.js delete mode 100644 third_party/phantomjs/test/module/webpage/contextclick-event.js delete mode 100644 third_party/phantomjs/test/module/webpage/cookies.js delete mode 100644 third_party/phantomjs/test/module/webpage/custom-headers.js delete mode 100644 third_party/phantomjs/test/module/webpage/evaluate-broken-json.js delete mode 100644 third_party/phantomjs/test/module/webpage/file-upload.js delete mode 100644 third_party/phantomjs/test/module/webpage/frame-switching-deprecated.js delete mode 100644 third_party/phantomjs/test/module/webpage/frame-switching.js delete mode 100644 third_party/phantomjs/test/module/webpage/https-bad-cert.js delete mode 100644 third_party/phantomjs/test/module/webpage/https-good-cert.js delete mode 100644 third_party/phantomjs/test/module/webpage/includejs.js delete mode 100644 third_party/phantomjs/test/module/webpage/keydown-event.js delete mode 100644 third_party/phantomjs/test/module/webpage/keypress-event.js delete mode 100644 third_party/phantomjs/test/module/webpage/keyup-event.js delete mode 100644 third_party/phantomjs/test/module/webpage/loading.js delete mode 100644 third_party/phantomjs/test/module/webpage/local-urls-disabled-iframe.js delete mode 100644 third_party/phantomjs/test/module/webpage/local-urls-disabled.js delete mode 100644 third_party/phantomjs/test/module/webpage/local-urls-enabled-iframe.js delete mode 100644 third_party/phantomjs/test/module/webpage/local-urls-enabled.js delete mode 100644 third_party/phantomjs/test/module/webpage/long-running-javascript.js delete mode 100644 third_party/phantomjs/test/module/webpage/modify-header.js delete mode 100644 third_party/phantomjs/test/module/webpage/mouseclick-event.js delete mode 100644 third_party/phantomjs/test/module/webpage/mousedoubleclick-event.js delete mode 100644 third_party/phantomjs/test/module/webpage/mousedown-event.js delete mode 100644 third_party/phantomjs/test/module/webpage/mousemove-event.js delete mode 100644 third_party/phantomjs/test/module/webpage/mouseup-event.js delete mode 100644 third_party/phantomjs/test/module/webpage/navigation.js delete mode 100644 third_party/phantomjs/test/module/webpage/no-plugin.js delete mode 100644 third_party/phantomjs/test/module/webpage/object.js delete mode 100644 third_party/phantomjs/test/module/webpage/on-confirm.js delete mode 100644 third_party/phantomjs/test/module/webpage/on-error.js delete mode 100644 third_party/phantomjs/test/module/webpage/on-initialized.js delete mode 100644 third_party/phantomjs/test/module/webpage/open.js delete mode 100644 third_party/phantomjs/test/module/webpage/postdata.js delete mode 100644 third_party/phantomjs/test/module/webpage/prompt.js delete mode 100644 third_party/phantomjs/test/module/webpage/remove-header.js delete mode 100644 third_party/phantomjs/test/module/webpage/render.js delete mode 100644 third_party/phantomjs/test/module/webpage/renders/index.js delete mode 100644 third_party/phantomjs/test/module/webpage/renders/test.jpg delete mode 100644 third_party/phantomjs/test/module/webpage/renders/test.pdf delete mode 100644 third_party/phantomjs/test/module/webpage/renders/test.png delete mode 100644 third_party/phantomjs/test/module/webpage/renders/test50.jpg delete mode 100644 third_party/phantomjs/test/module/webpage/repaint-requested.js delete mode 100644 third_party/phantomjs/test/module/webpage/resource-received-error.js delete mode 100644 third_party/phantomjs/test/module/webpage/resource-request-error.js delete mode 100644 third_party/phantomjs/test/module/webpage/scroll-position.js delete mode 100644 third_party/phantomjs/test/module/webpage/set-content.js delete mode 100644 third_party/phantomjs/test/module/webpage/subwindows.js delete mode 100644 third_party/phantomjs/test/module/webpage/url-encoding.js delete mode 100644 third_party/phantomjs/test/module/webpage/user-agent.js delete mode 100644 third_party/phantomjs/test/module/webpage/viewport-size.js delete mode 100644 third_party/phantomjs/test/module/webpage/window.js delete mode 100644 third_party/phantomjs/test/module/webpage/zoom-factor.js delete mode 100644 third_party/phantomjs/test/module/webserver/basics.js delete mode 100644 third_party/phantomjs/test/module/webserver/requests.js delete mode 100644 third_party/phantomjs/test/node_modules/dummy_exposed.js delete mode 100644 third_party/phantomjs/test/node_modules/dummy_file.js delete mode 100644 third_party/phantomjs/test/node_modules/dummy_file2.js delete mode 100644 third_party/phantomjs/test/regression/README delete mode 100644 third_party/phantomjs/test/regression/pjs-10690.js delete mode 100644 third_party/phantomjs/test/regression/pjs-12482.js delete mode 100644 third_party/phantomjs/test/regression/pjs-13551.js delete mode 100644 third_party/phantomjs/test/regression/webkit-60448.js delete mode 100755 third_party/phantomjs/test/run-tests.py delete mode 100644 third_party/phantomjs/test/standards/console/console_log.js delete mode 100644 third_party/phantomjs/test/standards/javascript/date.js delete mode 100644 third_party/phantomjs/test/standards/javascript/function.js delete mode 100644 third_party/phantomjs/test/testharness.js delete mode 100644 third_party/phantomjs/test/writing-tests.md delete mode 100644 third_party/phantomjs/test/www/__init__.py delete mode 100644 third_party/phantomjs/test/www/delay.py delete mode 100644 third_party/phantomjs/test/www/echo.py delete mode 100644 third_party/phantomjs/test/www/frameset/frame1-1.html delete mode 100644 third_party/phantomjs/test/www/frameset/frame1-2.html delete mode 100644 third_party/phantomjs/test/www/frameset/frame1.html delete mode 100644 third_party/phantomjs/test/www/frameset/frame2-1.html delete mode 100644 third_party/phantomjs/test/www/frameset/frame2-2.html delete mode 100644 third_party/phantomjs/test/www/frameset/frame2-3.html delete mode 100644 third_party/phantomjs/test/www/frameset/frame2.html delete mode 100644 third_party/phantomjs/test/www/frameset/index.html delete mode 100644 third_party/phantomjs/test/www/hello.html delete mode 100644 third_party/phantomjs/test/www/iframe.html delete mode 100644 third_party/phantomjs/test/www/includejs.js delete mode 100644 third_party/phantomjs/test/www/includejs1.html delete mode 100644 third_party/phantomjs/test/www/includejs2.html delete mode 100644 third_party/phantomjs/test/www/js-infinite-loop.html delete mode 100644 third_party/phantomjs/test/www/logo.html delete mode 100644 third_party/phantomjs/test/www/logo.png delete mode 100644 third_party/phantomjs/test/www/missing-img.html delete mode 100644 third_party/phantomjs/test/www/navigation/dest.html delete mode 100644 third_party/phantomjs/test/www/navigation/index.html delete mode 100644 third_party/phantomjs/test/www/phantomjs.png delete mode 100644 third_party/phantomjs/test/www/regression/pjs-10690/Windsong.ttf delete mode 100644 third_party/phantomjs/test/www/regression/pjs-10690/font.css delete mode 100644 third_party/phantomjs/test/www/regression/pjs-10690/index.html delete mode 100644 third_party/phantomjs/test/www/regression/pjs-10690/jquery.js delete mode 100644 third_party/phantomjs/test/www/regression/pjs-13551/child1.html delete mode 100644 third_party/phantomjs/test/www/regression/pjs-13551/child1a.html delete mode 100644 third_party/phantomjs/test/www/regression/pjs-13551/child2.html delete mode 100644 third_party/phantomjs/test/www/regression/pjs-13551/closing-parent.html delete mode 100644 third_party/phantomjs/test/www/regression/pjs-13551/reloading-parent.html delete mode 100644 third_party/phantomjs/test/www/regression/webkit-60448.html delete mode 100644 third_party/phantomjs/test/www/render/image.jpg delete mode 100644 third_party/phantomjs/test/www/render/index.html delete mode 100644 third_party/phantomjs/test/www/status.py delete mode 100644 third_party/phantomjs/test/www/url-encoding.py delete mode 100644 third_party/phantomjs/test/www/user-agent.html diff --git a/.npmignore b/.npmignore index c2dd518c763..ea37a1d02c9 100644 --- a/.npmignore +++ b/.npmignore @@ -1,7 +1,3 @@ -# exclude phantomjs tests -third_party/phantomjs/ -# exclude phantom_shim project -phantom_shim # exclude all tests test utils/node6-transform diff --git a/.travis.yml b/.travis.yml index e3927edbf07..bbf8e4c500a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,6 @@ install: script: - 'if [ "$NODE7" = "true" ]; then yarn run lint; fi' - 'if [ "$NODE7" = "true" ]; then yarn run coverage; fi' - - 'if [ "$NODE7" = "true" ]; then yarn run test-phantom; fi' - 'if [ "$NODE6" = "true" ]; then yarn run node6; fi' - 'if [ "$NODE6" = "true" ]; then yarn run test-node6; fi' - 'if [ "$NODE6" = "true" ]; then yarn run node6-sanity; fi' diff --git a/package.json b/package.json index 6c4dffe0a48..f1e15d75ae1 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "scripts": { "unit": "jasmine test/test.js", "debug-unit": "DEBUG_TEST=true node --inspect-brk ./node_modules/.bin/jasmine test/test.js", - "test-phantom": "python third_party/phantomjs/test/run-tests.py", "test-doclint": "jasmine utils/doclint/check_public_api/test/test.js && jasmine utils/doclint/preprocessor/test.js", "test": "npm run lint --silent && npm run coverage && npm run test-phantom && npm run test-doclint && npm run test-node6", "install": "node install.js", diff --git a/phantom_shim/FileSystem.js b/phantom_shim/FileSystem.js deleted file mode 100644 index 5ff79af19fa..00000000000 --- a/phantom_shim/FileSystem.js +++ /dev/null @@ -1,375 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const path = require('path'); -const fs = require('fs'); -const deasync = require('deasync'); -const removeRecursive = require('rimraf').sync; -const copyRecursive = deasync(require('ncp').ncp); - -class FileSystem { - constructor() { - this.separator = path.sep; - } - - /** - * @return {string} - */ - get workingDirectory() { - return process.cwd(); - } - - /** - * @param {string} directoryPath - */ - changeWorkingDirectory(directoryPath) { - try { - process.chdir(directoryPath); - return true; - } catch (e){ - return false; - } - } - - /** - * @param {string} relativePath - * @return {string} - */ - absolute(relativePath) { - relativePath = path.normalize(relativePath); - if (path.isAbsolute(relativePath)) - return relativePath; - return path.resolve(path.join(process.cwd(), relativePath)); - } - - /** - * @param {string} filePath - * @return {boolean} - */ - exists(filePath) { - return fs.existsSync(filePath); - } - - /** - * @param {string} fromPath - * @param {string} toPath - */ - copy(fromPath, toPath) { - const content = fs.readFileSync(fromPath); - fs.writeFileSync(toPath, content); - } - - /** - * @param {string} fromPath - * @param {string} toPath - */ - move(fromPath, toPath) { - const content = fs.readFileSync(fromPath); - fs.writeFileSync(toPath, content); - fs.unlinkSync(fromPath); - } - - /** - * @param {string} filePath - * @return {number} - */ - size(filePath) { - return fs.statSync(filePath).size; - } - - /** - * @param {string} filePath - */ - touch(filePath) { - fs.closeSync(fs.openSync(filePath, 'a')); - } - - /** - * @param {string} filePath - */ - remove(filePath) { - fs.unlinkSync(filePath); - } - - /** - * @param {string} filePath - * @return {boolean} - */ - lastModified(filePath) { - return fs.statSync(filePath).mtime; - } - - /** - * @param {string} dirPath - * @return {boolean} - */ - makeDirectory(dirPath) { - try { - fs.mkdirSync(dirPath); - return true; - } catch (e) { - return false; - } - } - - /** - * @param {string} dirPath - * @return {boolean} - */ - makeTree(dirPath) { - return this.makeDirectory(dirPath); - } - - /** - * @param {string} dirPath - */ - removeTree(dirPath) { - removeRecursive(dirPath); - } - - /** - * @param {string} fromPath - * @param {string} toPath - */ - copyTree(fromPath, toPath) { - copyRecursive(fromPath, toPath); - } - - /** - * @param {string} dirPath - * @return {!Array} - */ - list(dirPath) { - return fs.readdirSync(dirPath); - } - - /** - * @param {string} linkPath - * @return {string} - */ - readLink(linkPath) { - return fs.readlinkSync(linkPath); - } - - /** - * @param {string} filePath - * @param {Object} data - * @param {string} mode - */ - write(filePath, data, mode) { - const fd = new FileDescriptor(filePath, mode, 'utf8'); - fd.write(data); - fd.close(); - } - - /** - * @param {string} somePath - * @return {boolean} - */ - isAbsolute(somePath) { - return path.isAbsolute(somePath); - } - - /** - * @return {string} - */ - read(filePath) { - return fs.readFileSync(filePath, 'utf8'); - } - - /** - * @param {string} filePath - * @return {boolean} - */ - isFile(filePath) { - return fs.existsSync(filePath) && fs.lstatSync(filePath).isFile(); - } - - /** - * @param {string} dirPath - * @return {boolean} - */ - isDirectory(dirPath) { - return fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory(); - } - - /** - * @param {string} filePath - * @return {boolean} - */ - isLink(filePath) { - return fs.existsSync(filePath) && fs.lstatSync(filePath).isSymbolicLink(); - } - - /** - * @param {string} filePath - * @return {boolean} - */ - isReadable(filePath) { - try { - fs.accessSync(filePath, fs.constants.R_OK); - return true; - } catch (e) { - return false; - } - } - - /** - * @param {string} filePath - * @return {boolean} - */ - isWritable(filePath) { - try { - fs.accessSync(filePath, fs.constants.W_OK); - return true; - } catch (e) { - return false; - } - } - - /** - * @param {string} filePath - * @return {boolean} - */ - isExecutable(filePath) { - try { - fs.accessSync(filePath, fs.constants.X_OK); - return true; - } catch (e) { - return false; - } - } - - /** - * @param {string} somePath - * @return {!Array} - */ - split(somePath) { - somePath = path.normalize(somePath); - if (somePath.endsWith(path.sep)) - somePath = somePath.substring(0, somePath.length - path.sep.length); - return somePath.split(path.sep); - } - - /** - * @param {string} path1 - * @param {string} path2 - * @return {string} - */ - join(...args) { - if (args[0] === '' && args.length > 1) - args[0] = path.sep; - args = args.filter(part => typeof part === 'string'); - return path.join.apply(path, args); - } - - /** - * @param {string} filePath - * @param {(string|!Object)} option - * @return {!FileDescriptor} - */ - open(filePath, option) { - if (typeof option === 'string') - return new FileDescriptor(filePath, option); - return new FileDescriptor(filePath, option.mode); - } -} - -const fdwrite = deasync(fs.write); -const fdread = deasync(fs.read); - -class FileDescriptor { - /** - * @param {string} filePath - * @param {string} mode - */ - constructor(filePath, mode) { - this._position = 0; - this._encoding = 'utf8'; - if (mode === 'rb') { - this._mode = 'r'; - this._encoding = 'latin1'; - } else if (mode === 'wb' || mode === 'b') { - this._mode = 'w'; - this._encoding = 'latin1'; - } else if (mode === 'rw+') { - this._mode = 'a+'; - this._position = fs.existsSync(filePath) ? fs.statSync(filePath).size : 0; - } else { - this._mode = mode; - } - this._fd = fs.openSync(filePath, this._mode); - } - - /** - * @param {string} data - */ - write(data) { - const buffer = Buffer.from(data, this._encoding); - const written = fdwrite(this._fd, buffer, 0, buffer.length, this._position); - this._position += written; - } - - getEncoding() { - return 'UTF-8'; - } - - /** - * @param {string} data - */ - writeLine(data) { - this.write(data + '\n'); - } - - /** - * @param {number=} size - * @return {string} - */ - read(size) { - let position = this._position; - if (!size) { - size = fs.fstatSync(this._fd).size; - position = 0; - } - const buffer = new Buffer(size); - const bytesRead = fdread(this._fd, buffer, 0, size, position); - this._position += bytesRead; - return buffer.toString(this._encoding); - } - - flush() { - // noop. - } - - /** - * @param {number} position - */ - seek(position) { - this._position = position; - } - - close() { - fs.closeSync(this._fd); - } - - /** - * @return {boolean} - */ - atEnd() { - } -} - -module.exports = FileSystem; diff --git a/phantom_shim/Phantom.js b/phantom_shim/Phantom.js deleted file mode 100644 index dbbd93ad7fb..00000000000 --- a/phantom_shim/Phantom.js +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const fs = require('fs'); -const path = require('path'); -const vm = require('vm'); -const url = require('url'); - -const VERSION = [0, 0, 1]; - -module.exports.version = VERSION; - -/** - * @param {!Object} context - * @param {string} scriptPath - */ -module.exports.create = function(context, scriptPath) { - const phantom = { - page: { - onConsoleMessage: null, - }, - - /** - * @param {string} relative - * @param {string} base - * @return {string} - */ - resolveRelativeUrl: function(relative, base) { - return url.resolve(base, relative); - }, - - /** - * @param {string} url - * @return {string} - */ - fullyDecodeUrl: function(url) { - return decodeURI(url); - }, - - libraryPath: path.dirname(scriptPath), - - onError: null, - - /** - * @return {string} - */ - get outputEncoding() { - return 'UTF-8'; - }, - - /** - * @param {string} value - */ - set outputEncoding(value) { - throw new Error('Phantom.outputEncoding setter is not implemented'); - }, - - /** - * @return {boolean} - */ - get cookiesEnabled() { - return true; - }, - - /** - * @param {boolean} value - */ - set cookiesEnabled(value) { - throw new Error('Phantom.cookiesEnabled setter is not implemented'); - }, - - /** - * @return {!{major: number, minor: number, patch: number}} - */ - get version() { - return { - major: VERSION[0], - minor: VERSION[1], - patch: VERSION[2], - }; - }, - - /** - * @param {number=} code - */ - exit: function(code) { - process.exit(code); - }, - - /** - * @param {string} filePath - * @return {boolean} - */ - injectJs: function(filePath) { - filePath = path.resolve(phantom.libraryPath, filePath); - if (!fs.existsSync(filePath)) - return false; - let code = fs.readFileSync(filePath, 'utf8'); - if (code.startsWith('#!')) - code = code.substring(code.indexOf('\n')); - vm.runInContext(code, context, { - filename: filePath, - displayErrors: true - }); - return true; - }, - - /** - * @param {string} moduleSource - * @param {string} filename - */ - loadModule: function(moduleSource, filename) { - const code = [ - '(function(require, exports, module) {\n', - moduleSource, - '\n}.call({},', - 'require.cache[\'' + filename + '\']._getRequire(),', - 'require.cache[\'' + filename + '\'].exports,', - 'require.cache[\'' + filename + '\']', - '));' - ].join(''); - vm.runInContext(code, context, { - filename: filename, - displayErrors: true - }); - }, - }; - return phantom; -}; diff --git a/phantom_shim/README.md b/phantom_shim/README.md deleted file mode 100644 index cdbe8e786ec..00000000000 --- a/phantom_shim/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# PhantomShim - -PhantomShim is a phantomJS script runner built atop of Puppeteer API. - -### Q: Can I use PhantomShim to run my scripts? -No. - -PhantomShim aims to pass PhantomJS tests rather then to be a valid PhantomJS script runner: -- PhantomShim shortcuts a lot of corners (e.g. [handling only a few keys](https://github.com/GoogleChrome/puppeteer/blob/4269f6a1bb0c2d1cc27a9ed1132017669c33a259/phantom_shim/WebPage.js#L75) that are necessary to pass tests). -- PhantomShim spawns [nested event loops](https://github.com/abbr/deasync) to emulate PhantomJS execution model. This might result in unpredictable side-effects, e.g. in [unexpected reenterability](https://github.com/GoogleChrome/puppeteer/blob/4269f6a1bb0c2d1cc27a9ed1132017669c33a259/phantom_shim/WebPage.js#L694). - -### Q: What's the purpose of PhantomShim? -The goal is to prove comprehensiveness of Puppeteer API. - -PhantomShim is built atop of Puppeteer API and is used to run PhantomJS tests. -Whenever PhantomShim can't implement certain capability to pass phantomJS test, Puppeteer API is improved to make it possible. - -### Q: Are there plans to evolve PhantomShim into a real PhantomJS script runner? -No. - -On the contrary, PhantomShim is likely to be removed from the Puppeteer repository as it passes all interesting PhantomJS tests. \ No newline at end of file diff --git a/phantom_shim/System.js b/phantom_shim/System.js deleted file mode 100644 index f8cc2dadf8c..00000000000 --- a/phantom_shim/System.js +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const readline = require('readline'); -const await = require('./utilities').await; -const os = require('os'); - -class System { - /** - * @param {!Array} args - */ - constructor(args) { - this.args = args; - this.env = {}; - Object.assign(this.env, process.env); - this.stdin = new StandardInput(process.stdin); - this.stdout = new StandardOutput(process.stdout); - this.stderr = new StandardOutput(process.stderr); - this.platform = 'phantomjs'; - this.pid = process.pid; - this.isSSLSupported = false; - this.os = { - architecture: os.arch(), - name: os.type(), - version: os.release() - }; - } -} - -class StandardInput { - /** - * @param {!Readable} readableStream - */ - constructor(readableStream) { - this._readline = readline.createInterface({ - input: readableStream - }); - this._lines = []; - this._closed = false; - this._readline.on('line', line => this._lines.push(line)); - this._readline.on('close', () => this._closed = true); - } - - /** - * @return {string} - */ - readLine() { - if (this._closed && !this._lines.length) - return ''; - if (!this._lines.length) { - const linePromise = new Promise(fulfill => this._readline.once('line', fulfill)); - await(linePromise); - } - return this._lines.shift(); - } - - /** - * @return {string} - */ - read() { - if (!this._closed) { - const closePromise = new Promise(fulfill => this._readline.once('close', fulfill)); - await(closePromise); - } - const text = this._lines.join('\n'); - this._lines = []; - return text; - } - - close() { - this._readline.close(); - } -} - -class StandardOutput { - /** - * @param {!Writable} writableStream - */ - constructor(writableStream) { - this._stream = writableStream; - } - - /** - * @param {string} data - */ - write(data) { - this._stream.write(data); - } - - /** - * @param {string} data - */ - writeLine(data) { - this._stream.write(data + '\n'); - } - - flush() { - } - - close() { - this._stream.end(); - } -} - -module.exports = System; diff --git a/phantom_shim/WebPage.js b/phantom_shim/WebPage.js deleted file mode 100644 index 6b74937c050..00000000000 --- a/phantom_shim/WebPage.js +++ /dev/null @@ -1,748 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const await = require('./utilities').await; -const EventEmitter = require('events'); -const fs = require('fs'); -const path = require('path'); -const PageEvents = require('../lib/Page').Events; - -const noop = function() { }; - -class WebPage { - /** - * @param {!Browser} browser - * @param {string} scriptPath - * @param {!Object=} options - */ - constructor(browser, scriptPath, options = {}) { - this._page = await(browser.newPage()); - this.settings = new WebPageSettings(this._page); - - options.settings = options.settings || {}; - if (options.settings.userAgent) - this.settings.userAgent = options.settings.userAgent; - if (options.viewportSize) - await(this._page.setViewport(options.viewportSize)); - else - await(this._page.setViewport({width: 400, height: 300})); - - this.loading = false; - this.loadingProgress = 0; - this.clipRect = options.clipRect || {left: 0, top: 0, width: 0, height: 0}; - this.onConsoleMessage = null; - this.onLoadFinished = null; - this.onResourceError = null; - this.onResourceReceived = null; - this._onInitialized = undefined; - this._deferEvaluate = false; - this._customHeaders = {}; - - this._currentFrame = this._page.mainFrame(); - - this.libraryPath = path.dirname(scriptPath); - - this._onResourceRequestedCallback = undefined; - this._onConfirmCallback = undefined; - this._onPromptCallback = undefined; - this._onAlertCallback = undefined; - this._onError = noop; - - this._pageEvents = new AsyncEmitter(this._page); - this._pageEvents.on(PageEvents.Request, request => this._onRequest(request)); - this._pageEvents.on(PageEvents.Response, response => this._onResponseReceived(response)); - this._pageEvents.on(PageEvents.RequestFinished, request => this._onRequestFinished(request)); - this._pageEvents.on(PageEvents.RequestFailed, event => (this.onResourceError || noop).call(null, event)); - this._pageEvents.on(PageEvents.Console, (...args) => this._onConsole(...args)); - this._pageEvents.on(PageEvents.Confirm, message => this._onConfirm(message)); - this._pageEvents.on(PageEvents.Alert, message => this._onAlert(message)); - this._pageEvents.on(PageEvents.Dialog, dialog => this._onDialog(dialog)); - this._pageEvents.on(PageEvents.PageError, error => (this._onError || noop).call(null, error.message, error.stack)); - this.event = { - key: { - A: 65, - B: 66, - C: 67, - Home: ['Home'], - Delete: ['Delete'], - Backspace: ['Backspace'], - Cut: ['Cut'], - Paste: ['Paste'] - }, - modifier: { - shift: 'Shift' - } - }; - } - - /** - * @param {!Array} args - */ - _onConsole(...args) { - if (!this.onConsoleMessage) - return; - const text = args.join(' '); - this.onConsoleMessage(text); - } - - /** - * @return {string} - */ - currentFrameName() { - return this.frameName; - } - - /** - * @return {number} - */ - childFramesCount() { - return this.framesCount; - } - - /** - * @return {!Array} - */ - childFramesName() { - return this.framesName; - } - - /** - * @param {(string|number)} frameName - * @return {boolean} - */ - switchToChildFrame(frame) { - return this.switchToFrame(frame); - } - - /** - * @return {string} - */ - get frameName() { - return this._currentFrame.name(); - } - - /** - * @return {number} - */ - get framesCount() { - return this._currentFrame.childFrames().length; - } - - /** - * @return {!Array} - */ - get framesName() { - return this._currentFrame.childFrames().map(frame => frame.name()); - } - - /** - * @return {string} - */ - get focusedFrameName() { - const focusedFrame = this._focusedFrame(); - return focusedFrame ? focusedFrame.name() : ''; - } - - /** - * @return {?Frame} - */ - _focusedFrame() { - const frames = this._currentFrame.childFrames().slice(); - frames.push(this._currentFrame); - const promises = frames.map(frame => frame.evaluate(() => document.hasFocus())); - const result = await(Promise.all(promises)); - for (let i = 0; i < result.length; ++i) { - if (result[i]) - return frames[i]; - } - return null; - } - - switchToFocusedFrame() { - const frame = this._focusedFrame(); - this._currentFrame = frame; - } - - /** - * @param {(string|number)} frameName - * @return {boolean} - */ - switchToFrame(frameName) { - let frame = null; - if (typeof frameName === 'string') - frame = this._currentFrame.childFrames().find(frame => frame.name() === frameName); - else if (typeof frameName === 'number') - frame = this._currentFrame.childFrames()[frameName]; - if (!frame) - return false; - this._currentFrame = frame; - return true; - } - - /** - * @return {boolean} - */ - switchToParentFrame() { - const frame = this._currentFrame.parentFrame(); - if (!frame) - return false; - this._currentFrame = frame; - return true; - } - - switchToMainFrame() { - this._currentFrame = this._page.mainFrame(); - } - - get cookies() { - return await(this._page.cookies()); - } - - set cookies(cookies) { - const cookies2 = await(this._page.cookies()); - await(this._page.deleteCookie(...cookies2)); - await(this._page.setCookie(...cookies)); - - } - - addCookie(cookie) { - await(this._page.setCookie(cookie)); - } - - deleteCookie(cookieName) { - await(this._page.deleteCookie({name: cookieName})); - } - - get onInitialized() { - return this._onInitialized; - } - - set onInitialized(value) { - if (typeof value !== 'function') - this._onInitialized = undefined; - else - this._onInitialized = value; - } - - /** - * @return {?function(!Object, !Request)} - */ - get onResourceRequested() { - return this._onResourceRequestedCallback; - } - - /** - * @return {?function(!Object, !Request)} callback - */ - set onResourceRequested(callback) { - await(this._page.setRequestInterceptionEnabled(!!callback)); - this._onResourceRequestedCallback = callback; - } - - _onRequest(request) { - if (!this._onResourceRequestedCallback) - return; - const requestData = new RequestData(request); - const phantomRequest = new PhantomRequest(); - this._onResourceRequestedCallback.call(null, requestData, phantomRequest); - if (phantomRequest._aborted) { - request.abort(); - } else { - request.continue({ - url: phantomRequest._url, - headers: phantomRequest._headers, - }); - } - } - - _onResponseReceived(response) { - if (!this.onResourceReceived) - return; - const phantomResponse = new PhantomResponse(response, false /* isResponseFinished */); - this.onResourceReceived.call(null, phantomResponse); - } - - _onRequestFinished(request) { - if (!this.onResourceReceived) - return; - const phantomResponse = new PhantomResponse(request.response(), true /* isResponseFinished */); - this.onResourceReceived.call(null, phantomResponse); - } - - /** - * @param {string} url - * @param {function()} callback - */ - includeJs(url, callback) { - this._page.addScriptTag(url).then(callback); - } - - /** - * @return {!{width: number, height: number}} - */ - get viewportSize() { - return this._page.viewport(); - } - - /** - * @return {!Object} - */ - get customHeaders() { - return this._customHeaders; - } - - /** - * @param {!Object} value - */ - set customHeaders(value) { - this._customHeaders = value; - await(this._page.setExtraHTTPHeaders(new Map(Object.entries(value)))); - } - - /** - * @param {string} filePath - */ - injectJs(filePath) { - if (!fs.existsSync(filePath)) - filePath = path.resolve(this.libraryPath, filePath); - if (!fs.existsSync(filePath)) - return false; - await(this._page.injectFile(filePath)); - return true; - } - - /** - * @return {string} - */ - get plainText() { - return await(this._page.plainText()); - } - - /** - * @return {string} - */ - get title() { - return await(this._page.title()); - } - - /** - * @return {(function()|undefined)} - */ - get onError() { - return this._onError; - } - - /** - * @param {(function()|undefined)} handler - */ - set onError(handler) { - if (typeof handler !== 'function') - handler = undefined; - this._onError = handler; - } - - /** - * @return {(function()|undefined)} - */ - get onConfirm() { - return this._onConfirmCallback; - } - - /** - * @param {function()} handler - */ - set onConfirm(handler) { - if (typeof handler !== 'function') - handler = undefined; - this._onConfirmCallback = handler; - } - - /** - * @return {(function()|undefined)} - */ - get onPrompt() { - return this._onPromptCallback; - } - - /** - * @param {function()} handler - */ - set onPrompt(handler) { - if (typeof handler !== 'function') - handler = undefined; - this._onPromptCallback = handler; - } - - /** - * @return {(function()|undefined)} - */ - get onAlert() { - return this._onAlertCallback; - } - - /** - * @param {function()} handler - */ - set onAlert(handler) { - if (typeof handler !== 'function') - handler = undefined; - this._onAlertCallback = handler; - } - - /** - * @param {!Dialog} dialog - */ - _onDialog(dialog) { - if (dialog.type === 'alert' && this._onAlertCallback) { - this._onAlertCallback.call(null, dialog.message()); - await(dialog.accept()); - } else if (dialog.type === 'confirm' && this._onConfirmCallback) { - const result = this._onConfirmCallback.call(null, dialog.message()); - await(result ? dialog.accept() : dialog.dismiss()); - } else if (dialog.type === 'prompt' && this._onPromptCallback) { - const result = this._onPromptCallback.call(null, dialog.message(), dialog.defaultValue()); - await(result ? dialog.accept(result) : dialog.dismiss()); - } - } - - /** - * @return {string} - */ - get url() { - return await(this._page.url()); - } - - /** - * @param {string} html - */ - set content(html) { - await(this._page.setContent(html)); - } - - /** - * @param {string} selector - * @param {(string|!Array)} files - */ - uploadFile(selector, files) { - if (typeof files === 'string') - await(await(this._page.$(selector)).uploadFile(files)); - else - await(await(this._page.$(selector)).uploadFile(...files)); - } - - /** - * @param {string} eventType - * @param {!Array<*>} args - */ - sendEvent(eventType, ...args) { - if (eventType.startsWith('key')) - this._sendKeyboardEvent.apply(this, arguments); - else - this._sendMouseEvent.apply(this, arguments); - } - - /** - * @param {string} eventType - * @param {string} keyOrKeys - * @param {null} nop1 - * @param {null} nop2 - * @param {number} modifier - */ - _sendKeyboardEvent(eventType, keyOrKeys, nop1, nop2, modifier) { - switch (eventType) { - case 'keyup': - if (typeof keyOrKeys === 'number') { - await(this._page.keyboard.up(String.fromCharCode(keyOrKeys))); - break; - } - for (const key of keyOrKeys) - await(this._page.keyboard.up(key)); - break; - case 'keypress': - if (modifier & 0x04000000) - this._page.keyboard.down('Control'); - if (modifier & 0x02000000) - this._page.keyboard.down('Shift'); - if (keyOrKeys instanceof Array) { - this._page.keyboard.down(keyOrKeys[0]); - await(this._page.keyboard.up(keyOrKeys[0])); - } else if (typeof keyOrKeys === 'number') { - await(this._page.type(String.fromCharCode(keyOrKeys))); - } else { - await(this._page.type(keyOrKeys)); - } - if (modifier & 0x02000000) - this._page.keyboard.up('Shift'); - if (modifier & 0x04000000) - this._page.keyboard.up('Control'); - break; - case 'keydown': - if (typeof keyOrKeys === 'number') { - await(this._page.keyboard.down(String.fromCharCode(keyOrKeys))); - break; - } - for (const key of keyOrKeys) - await(this._page.keyboard.down(key)); - break; - } - } - - /** - * @param {string} eventType - * @param {number} x - * @param {number} y - * @param {string|undefined} button - * @param {number|undefined} modifier - */ - _sendMouseEvent(eventType, x, y, button, modifier) { - if (modifier) - await(this._page.keyboard.down(modifier)); - switch (eventType) { - case 'mousemove': - await(this._page.mouse.move(x, y)); - break; - case 'mousedown': - await(this._page.mouse.move(x, y)); - await(this._page.mouse.down({button})); - break; - case 'mouseup': - await(this._page.mouse.move(x, y)); - await(this._page.mouse.up({button})); - break; - case 'doubleclick': - await(this._page.mouse.click(x, y, {button})); - await(this._page.mouse.click(x, y, {button, clickCount: 2})); - break; - case 'click': - await(this._page.mouse.click(x, y, {button})); - break; - case 'contextmenu': - await(this._page.mouse.click(x, y, {button: 'right'})); - break; - } - if (modifier) - await(this._page.keyboard.up(modifier)); - } - /** - * @param {string} html - * @param {function()=} callback - */ - open(url, callback) { - console.assert(arguments.length <= 2, 'WebPage.open does not support METHOD and DATA arguments'); - this._deferEvaluate = true; - if (typeof this._onInitialized === 'function') - this._onInitialized(); - this._deferEvaluate = false; - this.loading = true; - this.loadingProgress = 50; - - const handleNavigation = (error, response) => { - this.loadingProgress = 100; - this.loading = false; - if (error) { - this.onResourceError.call(null, { - url, - errorString: 'SSL handshake failed' - }); - } - const status = error ? 'fail' : 'success'; - if (this.onLoadFinished) - this.onLoadFinished.call(null, status); - if (callback) - callback.call(null, status); - this.loadingProgress = 0; - }; - this._page.goto(url).then(response => handleNavigation(null, response)) - .catch(e => handleNavigation(e, null)); - } - - /** - * @param {!{width: number, height: number}} options - */ - set viewportSize(options) { - await(this._page.setViewport(options)); - } - - /** - * @param {function()|string} fun - * @param {!Array} args - */ - evaluate(fun, ...args) { - if (typeof fun === 'string') - fun = `(${fun})()`; - if (this._deferEvaluate) - return await(this._page.evaluateOnNewDocument(fun, ...args)); - return await(this._currentFrame.evaluate(fun, ...args)); - } - - /** - * {string} fileName - */ - render(fileName) { - if (fileName.endsWith('pdf')) { - const options = {}; - const paperSize = this.paperSize || {}; - options.margin = paperSize.margin; - options.format = paperSize.format; - options.landscape = paperSize.orientation === 'landscape'; - options.width = paperSize.width; - options.height = paperSize.height; - options.path = fileName; - await(this._page.pdf(options)); - } else { - const options = {}; - if (this.clipRect && (this.clipRect.left || this.clipRect.top || this.clipRect.width || this.clipRect.height)) { - options.clip = { - x: this.clipRect.left, - y: this.clipRect.top, - width: this.clipRect.width, - height: this.clipRect.height - }; - } - options.path = fileName; - await(this._page.screenshot(options)); - } - } - - release() { - this._page.close(); - } - - close() { - this._page.close(); - } -} - -class WebPageSettings { - /** - * @param {!Page} page - */ - constructor(page) { - this._page = page; - } - - /** - * @param {string} value - */ - set userAgent(value) { - await(this._page.setUserAgent(value)); - } - - /** - * @return {string} - */ - get userAgent() { - return await(this._page.evaluate(() => window.navigator.userAgent)); - } -} - -class PhantomRequest { - constructor() { - this._url = undefined; - this._headers = undefined; - } - - /** - * @param {string} key - * @param {string} value - */ - setHeader(key, value) { - if (!this._headers) - this._headers = new Map(); - this._headers.set(key, value); - } - - abort() { - this._aborted = true; - } - - /** - * @param {string} url - */ - changeUrl(newUrl) { - this._url = newUrl; - } -} - -class PhantomResponse { - /** - * @param {!Response} response - * @param {boolean} isResponseFinished - */ - constructor(response, isResponseFinished) { - this.url = response.url; - this.status = response.status; - this.statusText = response.statusText; - this.stage = isResponseFinished ? 'end' : 'start'; - this.headers = []; - for (const entry of response.headers.entries()) { - this.headers.push({ - name: entry[0], - value: entry[1] - }); - } - } -} - -class RequestData { - /** - * @param {!InterceptedRequest} request - */ - constructor(request) { - this.url = request.url, - this.headers = {}; - for (const entry of request.headers.entries()) - this.headers[entry[0]] = entry[1]; - } -} - -// To prevent reenterability, eventemitters should emit events -// only being in a consistent state. -// This is not the case for 'ws' npm module: https://goo.gl/sy3dJY -// -// Since out phantomjs environment uses nested event loops, we -// exploit this condition in 'ws', which probably never happens -// in case of regular I/O. -// -// This class is a wrapper around EventEmitter which re-emits events asynchronously, -// helping to overcome the issue. -class AsyncEmitter extends EventEmitter { - /** - * @param {!Page} page - */ - constructor(page) { - super(); - this._page = page; - this._symbol = Symbol('AsyncEmitter'); - this.on('newListener', this._onListenerAdded); - this.on('removeListener', this._onListenerRemoved); - } - - _onListenerAdded(event, listener) { - // Async listener calls original listener on next tick. - const asyncListener = (...args) => { - process.nextTick(() => listener.apply(null, args)); - }; - listener[this._symbol] = asyncListener; - this._page.on(event, asyncListener); - } - - _onListenerRemoved(event, listener) { - this._page.removeListener(event, listener[this._symbol]); - } -} - -module.exports = WebPage; diff --git a/phantom_shim/WebServer.js b/phantom_shim/WebServer.js deleted file mode 100644 index 96fe5ff7893..00000000000 --- a/phantom_shim/WebServer.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const http = require('http'); -const await = require('./utilities').await; - -class WebServer { - constructor() { - this._server = http.createServer(); - this.objectName = 'WebServer'; - this.listenOnPort = this.listen; - this.newRequest = function(req, res) { }; - Object.defineProperty(this, 'port', { - get: () => { - if (!this._server.listening) - return ''; - return this._server.address().port + ''; - }, - enumerable: true, - configurable: false - }); - } - - close() { - this._server.close(); - } - - /** - * @param {nubmer} port - * @return {boolean} - */ - listen(port, callback) { - if (this._server.listening) - return false; - this.newRequest = callback; - this._server.listen(port); - const errorPromise = new Promise(x => this._server.once('error', x)); - const successPromise = new Promise(x => this._server.once('listening', x)); - await(Promise.race([errorPromise, successPromise])); - if (!this._server.listening) - return false; - - this._server.on('request', (req, res) => { - res.close = res.end.bind(res); - const headers = res.getHeaders(); - res.headers = []; - for (const key in headers) { - res.headers.push({ - name: key, - value: headers[key] - }); - } - res.header = res.getHeader; - res.setHeaders = headers => { - for (const key in headers) - res.setHeader(key, headers[key]); - }; - Object.defineProperty(res, 'statusCode', { - enumerable: true, - configurable: true, - writable: true, - value: res.statusCode - }); - this.newRequest.call(null, req, res); - }); - return true; - } -} - -module.exports = WebServer; diff --git a/phantom_shim/runner.js b/phantom_shim/runner.js deleted file mode 100755 index 469fb42cb49..00000000000 --- a/phantom_shim/runner.js +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env node -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const await = require('./utilities').await; -const vm = require('vm'); -const path = require('path'); -const fs = require('fs'); -const Phantom = require('./Phantom'); -const FileSystem = require('./FileSystem'); -const System = require('./System'); -const WebPage = require('./WebPage'); -const WebServer = require('./WebServer'); -const child_process = require('child_process'); -const puppeteer = require('..'); -const argv = require('minimist')(process.argv.slice(2), { - alias: { v: 'version' }, - boolean: ['headless'], - default: {'headless': true }, -}); - -if (argv.version) { - console.log('PhantomShim v' + Phantom.version.join('.')); - return; -} - -if (argv['ssl-certificates-path']) { - console.error('Flag --ssl-certificates-path is not supported.'); - process.exit(1); - return; -} - -const scriptArguments = argv._; -if (!scriptArguments.length) { - console.log(__filename.split('/').pop() + ' [scriptfile]'); - return; -} - -const scriptPath = path.resolve(process.cwd(), scriptArguments[0]); -if (!fs.existsSync(scriptPath)) { - console.error(`script not found: ${scriptPath}`); - process.exit(1); - return; -} - -const context = createPhantomContext(argv.headless, scriptPath, argv); -const scriptContent = fs.readFileSync(scriptPath, 'utf8'); -vm.runInContext(scriptContent, context); - -/** - * @param {boolean} headless - * @param {string} scriptPath - * @param {!Array} argv - * @return {!Object} - */ -function createPhantomContext(headless, scriptPath, argv) { - const context = {}; - let browser = null; - context.setInterval = setInterval; - context.setTimeout = setTimeout; - context.clearInterval = clearInterval; - context.clearTimeout = clearTimeout; - - context.phantom = Phantom.create(context, scriptPath); - context.console = console; - context.window = context; - context.WebPage = options => new WebPage(ensureBrowser(), scriptPath, options); - - vm.createContext(context); - - const nativeExports = { - fs: new FileSystem(), - system: new System(argv._), - webpage: { - create: context.WebPage, - }, - webserver: { - create: () => new WebServer(), - }, - cookiejar: { - create: () => {}, - }, - child_process: child_process - }; - const bootstrapPath = path.join(__dirname, '..', 'third_party', 'phantomjs', 'bootstrap.js'); - const bootstrapCode = fs.readFileSync(bootstrapPath, 'utf8'); - vm.runInContext(bootstrapCode, context, { - filename: 'bootstrap.js' - })(nativeExports); - return context; - - function ensureBrowser() { - if (!browser) { - browser = await(puppeteer.launch({ - headless: argv.headless, - args: ['--no-sandbox'] - })); - } - return browser; - } -} - diff --git a/phantom_shim/utilities.js b/phantom_shim/utilities.js deleted file mode 100644 index 1f36ac94be7..00000000000 --- a/phantom_shim/utilities.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const loopWhile = require('deasync').loopWhile; - -module.exports = { - await: function(promise) { - let error; - let result; - let done = false; - promise.then(r => result = r) - .catch(err => error = err) - .then(() => done = true); - loopWhile(() => !done); - if (error) - throw error; - return result; - } -}; diff --git a/third_party/phantomjs/CHANGES.md b/third_party/phantomjs/CHANGES.md deleted file mode 100644 index d5256cfec4c..00000000000 --- a/third_party/phantomjs/CHANGES.md +++ /dev/null @@ -1,19 +0,0 @@ -Short Name: phantomjs -URL: https://github.com/ariya/phantomjs/tree/2.1.1 -Version: 2.1.1 -License: BSD -License File: LICENSE.BSD -Security Critical: no - -Description: -This package is used to aid puppeteer in running phantom.js scripts: -- test/ - testsuite is used to validate puppeteer running phantom.js scripts -- boostrap.js - used to bootstrap puppeteer environment - -Local Modifications: - -- test/run_test.py was changed to run puppeteer instead of phantomjs -- Certain tests under test/ were changed where tests were unreasonably strict in their expectations - (e.g. validating the exact format of error messages) -- bootstrap.js was changed to accept native modules as function arguments. -- test/run_test.py was enhanced to support "unsupported" directive diff --git a/third_party/phantomjs/LICENSE.BSD b/third_party/phantomjs/LICENSE.BSD deleted file mode 100644 index d5dfdd1f661..00000000000 --- a/third_party/phantomjs/LICENSE.BSD +++ /dev/null @@ -1,22 +0,0 @@ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL 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. diff --git a/third_party/phantomjs/bootstrap.js b/third_party/phantomjs/bootstrap.js deleted file mode 100644 index f3a69c55009..00000000000 --- a/third_party/phantomjs/bootstrap.js +++ /dev/null @@ -1,235 +0,0 @@ -/*jslint sloppy: true, nomen: true */ -/*global window:true,phantom:true */ - -/* - This file is part of the PhantomJS project from Ofi Labs. - - Copyright (C) 2011 Ariya Hidayat - Copyright (C) 2011 Ivan De Marino - Copyright (C) 2011 James Roe - Copyright (C) 2011 execjosh, http://execjosh.blogspot.com - Copyright (C) 2012 James M. Greene - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL 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. -*/ - -(function(nativeExports) { - // CommonJS module implementation follows - - window.global = window; - // fs is loaded at the end, when everything is ready - var fs; - var cache = {}; - var paths = []; - var extensions = { - '.js': function(module, filename) { - var code = fs.read(filename); - module._compile(code); - }, - - '.json': function(module, filename) { - module.exports = JSON.parse(fs.read(filename)); - } - }; - - function dirname(path) { - var replaced = path.replace(/\/[^\/]*\/?$/, ''); - if (replaced == path) { - replaced = ''; - } - return replaced; - } - - function basename(path) { - return path.replace(/.*\//, ''); - } - - function joinPath() { - // It should be okay to hard-code a slash here. - // The FileSystem module returns a platform-specific - // separator, but the JavaScript engine only expects - // the slash. - var args = Array.prototype.slice.call(arguments); - return args.join('/'); - } - - function tryFile(path) { - if (fs.isFile(path)) return path; - return null; - } - - function tryExtensions(path) { - var filename, exts = Object.keys(extensions); - for (var i=0; i 0 ) { - console.log(t--); - } else { - console.log("BLAST OFF!"); - phantom.exit(); - } - }, 1000); diff --git a/third_party/phantomjs/examples/detectsniff.js b/third_party/phantomjs/examples/detectsniff.js deleted file mode 100644 index f30867b35aa..00000000000 --- a/third_party/phantomjs/examples/detectsniff.js +++ /dev/null @@ -1,60 +0,0 @@ -// Detect if a web page sniffs the user agent or not. - -"use strict"; -var page = require('webpage').create(), - system = require('system'), - sniffed, - address; - -page.onInitialized = function () { - page.evaluate(function () { - - (function () { - var userAgent = window.navigator.userAgent, - platform = window.navigator.platform; - - window.navigator = { - appCodeName: 'Mozilla', - appName: 'Netscape', - cookieEnabled: false, - sniffed: false - }; - - window.navigator.__defineGetter__('userAgent', function () { - window.navigator.sniffed = true; - return userAgent; - }); - - window.navigator.__defineGetter__('platform', function () { - window.navigator.sniffed = true; - return platform; - }); - })(); - }); -}; - -if (system.args.length === 1) { - console.log('Usage: detectsniff.js '); - phantom.exit(1); -} else { - address = system.args[1]; - console.log('Checking ' + address + '...'); - page.open(address, function (status) { - if (status !== 'success') { - console.log('FAIL to load the address'); - phantom.exit(); - } else { - window.setTimeout(function () { - sniffed = page.evaluate(function () { - return navigator.sniffed; - }); - if (sniffed) { - console.log('The page tried to sniff the user agent.'); - } else { - console.log('The page did not try to sniff the user agent.'); - } - phantom.exit(); - }, 1500); - } - }); -} diff --git a/third_party/phantomjs/examples/echoToFile.js b/third_party/phantomjs/examples/echoToFile.js deleted file mode 100644 index cfb8858cb96..00000000000 --- a/third_party/phantomjs/examples/echoToFile.js +++ /dev/null @@ -1,24 +0,0 @@ -// echoToFile.js - Write in a given file all the parameters passed on the CLI -"use strict"; -var fs = require('fs'), - system = require('system'); - -if (system.args.length < 3) { - console.log("Usage: echoToFile.js DESTINATION_FILE "); - phantom.exit(1); -} else { - var content = '', - f = null, - i; - for ( i= 2; i < system.args.length; ++i ) { - content += system.args[i] + (i === system.args.length-1 ? '' : ' '); - } - - try { - fs.write(system.args[1], content, 'w'); - } catch(e) { - console.log(e); - } - - phantom.exit(); -} diff --git a/third_party/phantomjs/examples/features.js b/third_party/phantomjs/examples/features.js deleted file mode 100644 index 4c2a14acc13..00000000000 --- a/third_party/phantomjs/examples/features.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; -var feature, supported = [], unsupported = []; - -phantom.injectJs('modernizr.js'); -console.log('Detected features (using Modernizr ' + Modernizr._version + '):'); -for (feature in Modernizr) { - if (Modernizr.hasOwnProperty(feature)) { - if (feature[0] !== '_' && typeof Modernizr[feature] !== 'function' && - feature !== 'input' && feature !== 'inputtypes') { - if (Modernizr[feature]) { - supported.push(feature); - } else { - unsupported.push(feature); - } - } - } -} - -console.log(''); -console.log('Supported:'); -supported.forEach(function (e) { - console.log(' ' + e); -}); - -console.log(''); -console.log('Not supported:'); -unsupported.forEach(function (e) { - console.log(' ' + e); -}); -phantom.exit(); diff --git a/third_party/phantomjs/examples/fibo.js b/third_party/phantomjs/examples/fibo.js deleted file mode 100644 index 7ee472a9925..00000000000 --- a/third_party/phantomjs/examples/fibo.js +++ /dev/null @@ -1,10 +0,0 @@ -"use strict"; -var fibs = [0, 1]; -var ticker = window.setInterval(function () { - console.log(fibs[fibs.length - 1]); - fibs.push(fibs[fibs.length - 1] + fibs[fibs.length - 2]); - if (fibs.length > 10) { - window.clearInterval(ticker); - phantom.exit(); - } -}, 300); diff --git a/third_party/phantomjs/examples/hello.js b/third_party/phantomjs/examples/hello.js deleted file mode 100644 index 82d2dbbcc4e..00000000000 --- a/third_party/phantomjs/examples/hello.js +++ /dev/null @@ -1,3 +0,0 @@ -"use strict"; -console.log('Hello, world!'); -phantom.exit(); diff --git a/third_party/phantomjs/examples/injectme.js b/third_party/phantomjs/examples/injectme.js deleted file mode 100644 index 18d9fda52aa..00000000000 --- a/third_party/phantomjs/examples/injectme.js +++ /dev/null @@ -1,26 +0,0 @@ -// Use 'page.injectJs()' to load the script itself in the Page context - -"use strict"; -if ( typeof(phantom) !== "undefined" ) { - var page = require('webpage').create(); - - // Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this") - page.onConsoleMessage = function(msg) { - console.log(msg); - }; - - page.onAlert = function(msg) { - console.log(msg); - }; - - console.log("* Script running in the Phantom context."); - console.log("* Script will 'inject' itself in a page..."); - page.open("about:blank", function(status) { - if ( status === "success" ) { - console.log(page.injectJs("injectme.js") ? "... done injecting itself!" : "... fail! Check the $PWD?!"); - } - phantom.exit(); - }); -} else { - alert("* Script running in the Page context."); -} diff --git a/third_party/phantomjs/examples/loadspeed.js b/third_party/phantomjs/examples/loadspeed.js deleted file mode 100644 index 626a51cf333..00000000000 --- a/third_party/phantomjs/examples/loadspeed.js +++ /dev/null @@ -1,24 +0,0 @@ -"use strict"; -var page = require('webpage').create(), - system = require('system'), - t, address; - -if (system.args.length === 1) { - console.log('Usage: loadspeed.js '); - phantom.exit(1); -} else { - t = Date.now(); - address = system.args[1]; - page.open(address, function (status) { - if (status !== 'success') { - console.log('FAIL to load the address'); - } else { - t = Date.now() - t; - console.log('Page title is ' + page.evaluate(function () { - return document.title; - })); - console.log('Loading time ' + t + ' msec'); - } - phantom.exit(); - }); -} diff --git a/third_party/phantomjs/examples/loadurlwithoutcss.js b/third_party/phantomjs/examples/loadurlwithoutcss.js deleted file mode 100644 index b6f13c6153a..00000000000 --- a/third_party/phantomjs/examples/loadurlwithoutcss.js +++ /dev/null @@ -1,26 +0,0 @@ -"use strict"; -var page = require('webpage').create(), - system = require('system'); - -if (system.args.length < 2) { - console.log('Usage: loadurlwithoutcss.js URL'); - phantom.exit(); -} - -var address = system.args[1]; - -page.onResourceRequested = function(requestData, request) { - if ((/http:\/\/.+?\.css/gi).test(requestData['url']) || requestData.headers['Content-Type'] == 'text/css') { - console.log('The url of the request is matching. Aborting: ' + requestData['url']); - request.abort(); - } -}; - -page.open(address, function(status) { - if (status === 'success') { - phantom.exit(); - } else { - console.log('Unable to load the address!'); - phantom.exit(); - } -}); diff --git a/third_party/phantomjs/examples/modernizr.js b/third_party/phantomjs/examples/modernizr.js deleted file mode 100644 index 24de6cc7513..00000000000 --- a/third_party/phantomjs/examples/modernizr.js +++ /dev/null @@ -1,1406 +0,0 @@ -/*! - * Modernizr v2.8.2 - * www.modernizr.com - * - * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton - * Available under the BSD and MIT licenses: www.modernizr.com/license/ - */ - -/* - * Modernizr tests which native CSS3 and HTML5 features are available in - * the current UA and makes the results available to you in two ways: - * as properties on a global Modernizr object, and as classes on the - * element. This information allows you to progressively enhance - * your pages with a granular level of control over the experience. - * - * Modernizr has an optional (not included) conditional resource loader - * called Modernizr.load(), based on Yepnope.js (yepnopejs.com). - * To get a build that includes Modernizr.load(), as well as choosing - * which tests to include, go to www.modernizr.com/download/ - * - * Authors Faruk Ates, Paul Irish, Alex Sexton - * Contributors Ryan Seddon, Ben Alman - */ - -window.Modernizr = (function( window, document, undefined ) { - - var version = '2.8.2', - - Modernizr = {}, - - /*>>cssclasses*/ - // option for enabling the HTML classes to be added - enableClasses = true, - /*>>cssclasses*/ - - docElement = document.documentElement, - - /** - * Create our "modernizr" element that we do most feature tests on. - */ - mod = 'modernizr', - modElem = document.createElement(mod), - mStyle = modElem.style, - - /** - * Create the input element for various Web Forms feature tests. - */ - inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ , - - /*>>smile*/ - smile = ':)', - /*>>smile*/ - - toString = {}.toString, - - // TODO :: make the prefixes more granular - /*>>prefixes*/ - // List of property values to set for css tests. See ticket #21 - prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), - /*>>prefixes*/ - - /*>>domprefixes*/ - // Following spec is to expose vendor-specific style properties as: - // elem.style.WebkitBorderRadius - // and the following would be incorrect: - // elem.style.webkitBorderRadius - - // Webkit ghosts their properties in lowercase but Opera & Moz do not. - // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ - // erik.eae.net/archives/2008/03/10/21.48.10/ - - // More here: github.com/Modernizr/Modernizr/issues/issue/21 - omPrefixes = 'Webkit Moz O ms', - - cssomPrefixes = omPrefixes.split(' '), - - domPrefixes = omPrefixes.toLowerCase().split(' '), - /*>>domprefixes*/ - - /*>>ns*/ - ns = {'svg': 'http://www.w3.org/2000/svg'}, - /*>>ns*/ - - tests = {}, - inputs = {}, - attrs = {}, - - classes = [], - - slice = classes.slice, - - featureName, // used in testing loop - - - /*>>teststyles*/ - // Inject element with style element and some CSS rules - injectElementWithStyles = function( rule, callback, nodes, testnames ) { - - var style, ret, node, docOverflow, - div = document.createElement('div'), - // After page load injecting a fake body doesn't work so check if body exists - body = document.body, - // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it. - fakeBody = body || document.createElement('body'); - - if ( parseInt(nodes, 10) ) { - // In order not to give false positives we create a node for each test - // This also allows the method to scale for unspecified uses - while ( nodes-- ) { - node = document.createElement('div'); - node.id = testnames ? testnames[nodes] : mod + (nodes + 1); - div.appendChild(node); - } - } - - // '].join(''); - div.id = mod; - // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody. - // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 - (body ? div : fakeBody).innerHTML += style; - fakeBody.appendChild(div); - if ( !body ) { - //avoid crashing IE8, if background image is used - fakeBody.style.background = ''; - //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible - fakeBody.style.overflow = 'hidden'; - docOverflow = docElement.style.overflow; - docElement.style.overflow = 'hidden'; - docElement.appendChild(fakeBody); - } - - ret = callback(div, rule); - // If this is done after page load we don't want to remove the body so check if body exists - if ( !body ) { - fakeBody.parentNode.removeChild(fakeBody); - docElement.style.overflow = docOverflow; - } else { - div.parentNode.removeChild(div); - } - - return !!ret; - - }, - /*>>teststyles*/ - - /*>>mq*/ - // adapted from matchMedia polyfill - // by Scott Jehl and Paul Irish - // gist.github.com/786768 - testMediaQuery = function( mq ) { - - var matchMedia = window.matchMedia || window.msMatchMedia; - if ( matchMedia ) { - return matchMedia(mq) && matchMedia(mq).matches || false; - } - - var bool; - - injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) { - bool = (window.getComputedStyle ? - getComputedStyle(node, null) : - node.currentStyle)['position'] == 'absolute'; - }); - - return bool; - - }, - /*>>mq*/ - - - /*>>hasevent*/ - // - // isEventSupported determines if a given element supports the given event - // kangax.github.com/iseventsupported/ - // - // The following results are known incorrects: - // Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative - // Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333 - // ... - isEventSupported = (function() { - - var TAGNAMES = { - 'select': 'input', 'change': 'input', - 'submit': 'form', 'reset': 'form', - 'error': 'img', 'load': 'img', 'abort': 'img' - }; - - function isEventSupported( eventName, element ) { - - element = element || document.createElement(TAGNAMES[eventName] || 'div'); - eventName = 'on' + eventName; - - // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those - var isSupported = eventName in element; - - if ( !isSupported ) { - // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element - if ( !element.setAttribute ) { - element = document.createElement('div'); - } - if ( element.setAttribute && element.removeAttribute ) { - element.setAttribute(eventName, ''); - isSupported = is(element[eventName], 'function'); - - // If property was created, "remove it" (by setting value to `undefined`) - if ( !is(element[eventName], 'undefined') ) { - element[eventName] = undefined; - } - element.removeAttribute(eventName); - } - } - - element = null; - return isSupported; - } - return isEventSupported; - })(), - /*>>hasevent*/ - - // TODO :: Add flag for hasownprop ? didn't last time - - // hasOwnProperty shim by kangax needed for Safari 2.0 support - _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; - - if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { - hasOwnProp = function (object, property) { - return _hasOwnProperty.call(object, property); - }; - } - else { - hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ - return ((property in object) && is(object.constructor.prototype[property], 'undefined')); - }; - } - - // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js - // es5.github.com/#x15.3.4.5 - - if (!Function.prototype.bind) { - Function.prototype.bind = function bind(that) { - - var target = this; - - if (typeof target != "function") { - throw new TypeError(); - } - - var args = slice.call(arguments, 1), - bound = function () { - - if (this instanceof bound) { - - var F = function(){}; - F.prototype = target.prototype; - var self = new F(); - - var result = target.apply( - self, - args.concat(slice.call(arguments)) - ); - if (Object(result) === result) { - return result; - } - return self; - - } else { - - return target.apply( - that, - args.concat(slice.call(arguments)) - ); - - } - - }; - - return bound; - }; - } - - /** - * setCss applies given styles to the Modernizr DOM node. - */ - function setCss( str ) { - mStyle.cssText = str; - } - - /** - * setCssAll extrapolates all vendor-specific css strings. - */ - function setCssAll( str1, str2 ) { - return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); - } - - /** - * is returns a boolean for if typeof obj is exactly type. - */ - function is( obj, type ) { - return typeof obj === type; - } - - /** - * contains returns a boolean for if substr is found within str. - */ - function contains( str, substr ) { - return !!~('' + str).indexOf(substr); - } - - /*>>testprop*/ - - // testProps is a generic CSS / DOM property test. - - // In testing support for a given CSS property, it's legit to test: - // `elem.style[styleName] !== undefined` - // If the property is supported it will return an empty string, - // if unsupported it will return undefined. - - // We'll take advantage of this quick test and skip setting a style - // on our modernizr element, but instead just testing undefined vs - // empty string. - - // Because the testing of the CSS property names (with "-", as - // opposed to the camelCase DOM properties) is non-portable and - // non-standard but works in WebKit and IE (but not Gecko or Opera), - // we explicitly reject properties with dashes so that authors - // developing in WebKit or IE first don't end up with - // browser-specific content by accident. - - function testProps( props, prefixed ) { - for ( var i in props ) { - var prop = props[i]; - if ( !contains(prop, "-") && mStyle[prop] !== undefined ) { - return prefixed == 'pfx' ? prop : true; - } - } - return false; - } - /*>>testprop*/ - - // TODO :: add testDOMProps - /** - * testDOMProps is a generic DOM property test; if a browser supports - * a certain property, it won't return undefined for it. - */ - function testDOMProps( props, obj, elem ) { - for ( var i in props ) { - var item = obj[props[i]]; - if ( item !== undefined) { - - // return the property name as a string - if (elem === false) return props[i]; - - // let's bind a function - if (is(item, 'function')){ - // default to autobind unless override - return item.bind(elem || obj); - } - - // return the unbound function or obj or value - return item; - } - } - return false; - } - - /*>>testallprops*/ - /** - * testPropsAll tests a list of DOM properties we want to check against. - * We specify literally ALL possible (known and/or likely) properties on - * the element including the non-vendor prefixed one, for forward- - * compatibility. - */ - function testPropsAll( prop, prefixed, elem ) { - - var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), - props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); - - // did they call .prefixed('boxSizing') or are we just testing a prop? - if(is(prefixed, "string") || is(prefixed, "undefined")) { - return testProps(props, prefixed); - - // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) - } else { - props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); - return testDOMProps(props, prefixed, elem); - } - } - /*>>testallprops*/ - - - /** - * Tests - * ----- - */ - - // The *new* flexbox - // dev.w3.org/csswg/css3-flexbox - - tests['flexbox'] = function() { - return testPropsAll('flexWrap'); - }; - - // The *old* flexbox - // www.w3.org/TR/2009/WD-css3-flexbox-20090723/ - - tests['flexboxlegacy'] = function() { - return testPropsAll('boxDirection'); - }; - - // On the S60 and BB Storm, getContext exists, but always returns undefined - // so we actually have to call getContext() to verify - // github.com/Modernizr/Modernizr/issues/issue/97/ - - tests['canvas'] = function() { - var elem = document.createElement('canvas'); - return !!(elem.getContext && elem.getContext('2d')); - }; - - tests['canvastext'] = function() { - return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); - }; - - // webk.it/70117 is tracking a legit WebGL feature detect proposal - - // We do a soft detect which may false positive in order to avoid - // an expensive context creation: bugzil.la/732441 - - tests['webgl'] = function() { - return !!window.WebGLRenderingContext; - }; - - /* - * The Modernizr.touch test only indicates if the browser supports - * touch events, which does not necessarily reflect a touchscreen - * device, as evidenced by tablets running Windows 7 or, alas, - * the Palm Pre / WebOS (touch) phones. - * - * Additionally, Chrome (desktop) used to lie about its support on this, - * but that has since been rectified: crbug.com/36415 - * - * We also test for Firefox 4 Multitouch Support. - * - * For more info, see: modernizr.github.com/Modernizr/touch.html - */ - - tests['touch'] = function() { - var bool; - - if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { - bool = true; - } else { - injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) { - bool = node.offsetTop === 9; - }); - } - - return bool; - }; - - - // geolocation is often considered a trivial feature detect... - // Turns out, it's quite tricky to get right: - // - // Using !!navigator.geolocation does two things we don't want. It: - // 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513 - // 2. Disables page caching in WebKit: webk.it/43956 - // - // Meanwhile, in Firefox < 8, an about:config setting could expose - // a false positive that would throw an exception: bugzil.la/688158 - - tests['geolocation'] = function() { - return 'geolocation' in navigator; - }; - - - tests['postmessage'] = function() { - return !!window.postMessage; - }; - - - // Chrome incognito mode used to throw an exception when using openDatabase - // It doesn't anymore. - tests['websqldatabase'] = function() { - return !!window.openDatabase; - }; - - // Vendors had inconsistent prefixing with the experimental Indexed DB: - // - Webkit's implementation is accessible through webkitIndexedDB - // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB - // For speed, we don't test the legacy (and beta-only) indexedDB - tests['indexedDB'] = function() { - return !!testPropsAll("indexedDB", window); - }; - - // documentMode logic from YUI to filter out IE8 Compat Mode - // which false positives. - tests['hashchange'] = function() { - return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); - }; - - // Per 1.6: - // This used to be Modernizr.historymanagement but the longer - // name has been deprecated in favor of a shorter and property-matching one. - // The old API is still available in 1.6, but as of 2.0 will throw a warning, - // and in the first release thereafter disappear entirely. - tests['history'] = function() { - return !!(window.history && history.pushState); - }; - - tests['draganddrop'] = function() { - var div = document.createElement('div'); - return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); - }; - - // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10 - // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17. - // FF10 still uses prefixes, so check for it until then. - // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/ - tests['websockets'] = function() { - return 'WebSocket' in window || 'MozWebSocket' in window; - }; - - - // css-tricks.com/rgba-browser-support/ - tests['rgba'] = function() { - // Set an rgba() color and check the returned value - - setCss('background-color:rgba(150,255,150,.5)'); - - return contains(mStyle.backgroundColor, 'rgba'); - }; - - tests['hsla'] = function() { - // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, - // except IE9 who retains it as hsla - - setCss('background-color:hsla(120,40%,100%,.5)'); - - return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); - }; - - tests['multiplebgs'] = function() { - // Setting multiple images AND a color on the background shorthand property - // and then querying the style.background property value for the number of - // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! - - setCss('background:url(https://),url(https://),red url(https://)'); - - // If the UA supports multiple backgrounds, there should be three occurrences - // of the string "url(" in the return value for elemStyle.background - - return (/(url\s*\(.*?){3}/).test(mStyle.background); - }; - - - - // this will false positive in Opera Mini - // github.com/Modernizr/Modernizr/issues/396 - - tests['backgroundsize'] = function() { - return testPropsAll('backgroundSize'); - }; - - tests['borderimage'] = function() { - return testPropsAll('borderImage'); - }; - - - // Super comprehensive table about all the unique implementations of - // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance - - tests['borderradius'] = function() { - return testPropsAll('borderRadius'); - }; - - // WebOS unfortunately false positives on this test. - tests['boxshadow'] = function() { - return testPropsAll('boxShadow'); - }; - - // FF3.0 will false positive on this test - tests['textshadow'] = function() { - return document.createElement('div').style.textShadow === ''; - }; - - - tests['opacity'] = function() { - // Browsers that actually have CSS Opacity implemented have done so - // according to spec, which means their return values are within the - // range of [0.0,1.0] - including the leading zero. - - setCssAll('opacity:.55'); - - // The non-literal . in this regex is intentional: - // German Chrome returns this value as 0,55 - // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 - return (/^0.55$/).test(mStyle.opacity); - }; - - - // Note, Android < 4 will pass this test, but can only animate - // a single property at a time - // goo.gl/v3V4Gp - tests['cssanimations'] = function() { - return testPropsAll('animationName'); - }; - - - tests['csscolumns'] = function() { - return testPropsAll('columnCount'); - }; - - - tests['cssgradients'] = function() { - /** - * For CSS Gradients syntax, please see: - * webkit.org/blog/175/introducing-css-gradients/ - * developer.mozilla.org/en/CSS/-moz-linear-gradient - * developer.mozilla.org/en/CSS/-moz-radial-gradient - * dev.w3.org/csswg/css3-images/#gradients- - */ - - var str1 = 'background-image:', - str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', - str3 = 'linear-gradient(left top,#9f9, white);'; - - setCss( - // legacy webkit syntax (FIXME: remove when syntax not in use anymore) - (str1 + '-webkit- '.split(' ').join(str2 + str1) + - // standard syntax // trailing 'background-image:' - prefixes.join(str3 + str1)).slice(0, -str1.length) - ); - - return contains(mStyle.backgroundImage, 'gradient'); - }; - - - tests['cssreflections'] = function() { - return testPropsAll('boxReflect'); - }; - - - tests['csstransforms'] = function() { - return !!testPropsAll('transform'); - }; - - - tests['csstransforms3d'] = function() { - - var ret = !!testPropsAll('perspective'); - - // Webkit's 3D transforms are passed off to the browser's own graphics renderer. - // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in - // some conditions. As a result, Webkit typically recognizes the syntax but - // will sometimes throw a false positive, thus we must do a more thorough check: - if ( ret && 'webkitPerspective' in docElement.style ) { - - // Webkit allows this media query to succeed only if the feature is enabled. - // `@media (transform-3d),(-webkit-transform-3d){ ... }` - injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) { - ret = node.offsetLeft === 9 && node.offsetHeight === 3; - }); - } - return ret; - }; - - - tests['csstransitions'] = function() { - return testPropsAll('transition'); - }; - - - /*>>fontface*/ - // @font-face detection routine by Diego Perini - // javascript.nwbox.com/CSSSupport/ - - // false positives: - // WebOS github.com/Modernizr/Modernizr/issues/342 - // WP7 github.com/Modernizr/Modernizr/issues/538 - tests['fontface'] = function() { - var bool; - - injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) { - var style = document.getElementById('smodernizr'), - sheet = style.sheet || style.styleSheet, - cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : ''; - - bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0; - }); - - return bool; - }; - /*>>fontface*/ - - // CSS generated content detection - tests['generatedcontent'] = function() { - var bool; - - injectElementWithStyles(['#',mod,'{font:0/0 a}#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) { - bool = node.offsetHeight >= 3; - }); - - return bool; - }; - - - - // These tests evaluate support of the video/audio elements, as well as - // testing what types of content they support. - // - // We're using the Boolean constructor here, so that we can extend the value - // e.g. Modernizr.video // true - // Modernizr.video.ogg // 'probably' - // - // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 - // thx to NielsLeenheer and zcorpan - - // Note: in some older browsers, "no" was a return value instead of empty string. - // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2 - // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5 - - tests['video'] = function() { - var elem = document.createElement('video'), - bool = false; - - // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 - try { - if ( bool = !!elem.canPlayType ) { - bool = new Boolean(bool); - bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,''); - - // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546 - bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); - - bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,''); - } - - } catch(e) { } - - return bool; - }; - - tests['audio'] = function() { - var elem = document.createElement('audio'), - bool = false; - - try { - if ( bool = !!elem.canPlayType ) { - bool = new Boolean(bool); - bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); - bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,''); - - // Mimetypes accepted: - // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements - // bit.ly/iphoneoscodecs - bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); - bool.m4a = ( elem.canPlayType('audio/x-m4a;') || - elem.canPlayType('audio/aac;')) .replace(/^no$/,''); - } - } catch(e) { } - - return bool; - }; - - - // In FF4, if disabled, window.localStorage should === null. - - // Normally, we could not test that directly and need to do a - // `('localStorage' in window) && ` test first because otherwise Firefox will - // throw bugzil.la/365772 if cookies are disabled - - // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem - // will throw the exception: - // QUOTA_EXCEEDED_ERRROR DOM Exception 22. - // Peculiarly, getItem and removeItem calls do not throw. - - // Because we are forced to try/catch this, we'll go aggressive. - - // Just FWIW: IE8 Compat mode supports these features completely: - // www.quirksmode.org/dom/html5.html - // But IE8 doesn't support either with local files - - tests['localstorage'] = function() { - try { - localStorage.setItem(mod, mod); - localStorage.removeItem(mod); - return true; - } catch(e) { - return false; - } - }; - - tests['sessionstorage'] = function() { - try { - sessionStorage.setItem(mod, mod); - sessionStorage.removeItem(mod); - return true; - } catch(e) { - return false; - } - }; - - - tests['webworkers'] = function() { - return !!window.Worker; - }; - - - tests['applicationcache'] = function() { - return !!window.applicationCache; - }; - - - // Thanks to Erik Dahlstrom - tests['svg'] = function() { - return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; - }; - - // specifically for SVG inline in HTML, not within XHTML - // test page: paulirish.com/demo/inline-svg - tests['inlinesvg'] = function() { - var div = document.createElement('div'); - div.innerHTML = ''; - return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; - }; - - // SVG SMIL animation - tests['smil'] = function() { - return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); - }; - - // This test is only for clip paths in SVG proper, not clip paths on HTML content - // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg - - // However read the comments to dig into applying SVG clippaths to HTML content here: - // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491 - tests['svgclippaths'] = function() { - return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); - }; - - /*>>webforms*/ - // input features and input types go directly onto the ret object, bypassing the tests loop. - // Hold this guy to execute in a moment. - function webforms() { - /*>>input*/ - // Run through HTML5's new input attributes to see if the UA understands any. - // We're using f which is the element created early on - // Mike Taylr has created a comprehensive resource for testing these attributes - // when applied to all input types: - // miketaylr.com/code/input-type-attr.html - // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary - - // Only input placeholder is tested while textarea's placeholder is not. - // Currently Safari 4 and Opera 11 have support only for the input placeholder - // Both tests are available in feature-detects/forms-placeholder.js - Modernizr['input'] = (function( props ) { - for ( var i = 0, len = props.length; i < len; i++ ) { - attrs[ props[i] ] = !!(props[i] in inputElem); - } - if (attrs.list){ - // safari false positive's on datalist: webk.it/74252 - // see also github.com/Modernizr/Modernizr/issues/146 - attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); - } - return attrs; - })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); - /*>>input*/ - - /*>>inputtypes*/ - // Run through HTML5's new input types to see if the UA understands any. - // This is put behind the tests runloop because it doesn't return a - // true/false like all the other tests; instead, it returns an object - // containing each input type with its corresponding true/false value - - // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/ - Modernizr['inputtypes'] = (function(props) { - - for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) { - - inputElem.setAttribute('type', inputElemType = props[i]); - bool = inputElem.type !== 'text'; - - // We first check to see if the type we give it sticks.. - // If the type does, we feed it a textual value, which shouldn't be valid. - // If the value doesn't stick, we know there's input sanitization which infers a custom UI - if ( bool ) { - - inputElem.value = smile; - inputElem.style.cssText = 'position:absolute;visibility:hidden;'; - - if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { - - docElement.appendChild(inputElem); - defaultView = document.defaultView; - - // Safari 2-4 allows the smiley as a value, despite making a slider - bool = defaultView.getComputedStyle && - defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && - // Mobile android web browser has false positive, so must - // check the height to see if the widget is actually there. - (inputElem.offsetHeight !== 0); - - docElement.removeChild(inputElem); - - } else if ( /^(search|tel)$/.test(inputElemType) ){ - // Spec doesn't define any special parsing or detectable UI - // behaviors so we pass these through as true - - // Interestingly, opera fails the earlier test, so it doesn't - // even make it here. - - } else if ( /^(url|email)$/.test(inputElemType) ) { - // Real url and email support comes with prebaked validation. - bool = inputElem.checkValidity && inputElem.checkValidity() === false; - - } else { - // If the upgraded input compontent rejects the :) text, we got a winner - bool = inputElem.value != smile; - } - } - - inputs[ props[i] ] = !!bool; - } - return inputs; - })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); - /*>>inputtypes*/ - } - /*>>webforms*/ - - - // End of test definitions - // ----------------------- - - - - // Run through all tests and detect their support in the current UA. - // todo: hypothetically we could be doing an array of tests and use a basic loop here. - for ( var feature in tests ) { - if ( hasOwnProp(tests, feature) ) { - // run the test, throw the return value into the Modernizr, - // then based on that boolean, define an appropriate className - // and push it into an array of classes we'll join later. - featureName = feature.toLowerCase(); - Modernizr[featureName] = tests[feature](); - - classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); - } - } - - /*>>webforms*/ - // input tests need to run. - Modernizr.input || webforms(); - /*>>webforms*/ - - - /** - * addTest allows the user to define their own feature tests - * the result will be added onto the Modernizr object, - * as well as an appropriate className set on the html element - * - * @param feature - String naming the feature - * @param test - Function returning true if feature is supported, false if not - */ - Modernizr.addTest = function ( feature, test ) { - if ( typeof feature == 'object' ) { - for ( var key in feature ) { - if ( hasOwnProp( feature, key ) ) { - Modernizr.addTest( key, feature[ key ] ); - } - } - } else { - - feature = feature.toLowerCase(); - - if ( Modernizr[feature] !== undefined ) { - // we're going to quit if you're trying to overwrite an existing test - // if we were to allow it, we'd do this: - // var re = new RegExp("\\b(no-)?" + feature + "\\b"); - // docElement.className = docElement.className.replace( re, '' ); - // but, no rly, stuff 'em. - return Modernizr; - } - - test = typeof test == 'function' ? test() : test; - - if (typeof enableClasses !== "undefined" && enableClasses) { - docElement.className += ' ' + (test ? '' : 'no-') + feature; - } - Modernizr[feature] = test; - - } - - return Modernizr; // allow chaining. - }; - - - // Reset modElem.cssText to nothing to reduce memory footprint. - setCss(''); - modElem = inputElem = null; - - /*>>shiv*/ - /** - * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed - */ - ;(function(window, document) { - /*jshint evil:true */ - /** version */ - var version = '3.7.0'; - - /** Preset options */ - var options = window.html5 || {}; - - /** Used to skip problem elements */ - var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; - - /** Not all elements can be cloned in IE **/ - var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; - - /** Detect whether the browser supports default html5 styles */ - var supportsHtml5Styles; - - /** Name of the expando, to work with multiple documents or to re-shiv one document */ - var expando = '_html5shiv'; - - /** The id for the the documents expando */ - var expanID = 0; - - /** Cached data for each document */ - var expandoData = {}; - - /** Detect whether the browser supports unknown elements */ - var supportsUnknownElements; - - (function() { - try { - var a = document.createElement('a'); - a.innerHTML = ''; - //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles - supportsHtml5Styles = ('hidden' in a); - - supportsUnknownElements = a.childNodes.length == 1 || (function() { - // assign a false positive if unable to shiv - (document.createElement)('a'); - var frag = document.createDocumentFragment(); - return ( - typeof frag.cloneNode == 'undefined' || - typeof frag.createDocumentFragment == 'undefined' || - typeof frag.createElement == 'undefined' - ); - }()); - } catch(e) { - // assign a false positive if detection fails => unable to shiv - supportsHtml5Styles = true; - supportsUnknownElements = true; - } - - }()); - - /*--------------------------------------------------------------------------*/ - - /** - * Creates a style sheet with the given CSS text and adds it to the document. - * @private - * @param {Document} ownerDocument The document. - * @param {String} cssText The CSS text. - * @returns {StyleSheet} The style element. - */ - function addStyleSheet(ownerDocument, cssText) { - var p = ownerDocument.createElement('p'), - parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; - - p.innerHTML = 'x'; - return parent.insertBefore(p.lastChild, parent.firstChild); - } - - /** - * Returns the value of `html5.elements` as an array. - * @private - * @returns {Array} An array of shived element node names. - */ - function getElements() { - var elements = html5.elements; - return typeof elements == 'string' ? elements.split(' ') : elements; - } - - /** - * Returns the data associated to the given document - * @private - * @param {Document} ownerDocument The document. - * @returns {Object} An object of data. - */ - function getExpandoData(ownerDocument) { - var data = expandoData[ownerDocument[expando]]; - if (!data) { - data = {}; - expanID++; - ownerDocument[expando] = expanID; - expandoData[expanID] = data; - } - return data; - } - - /** - * returns a shived element for the given nodeName and document - * @memberOf html5 - * @param {String} nodeName name of the element - * @param {Document} ownerDocument The context document. - * @returns {Object} The shived element. - */ - function createElement(nodeName, ownerDocument, data){ - if (!ownerDocument) { - ownerDocument = document; - } - if(supportsUnknownElements){ - return ownerDocument.createElement(nodeName); - } - if (!data) { - data = getExpandoData(ownerDocument); - } - var node; - - if (data.cache[nodeName]) { - node = data.cache[nodeName].cloneNode(); - } else if (saveClones.test(nodeName)) { - node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); - } else { - node = data.createElem(nodeName); - } - - // Avoid adding some elements to fragments in IE < 9 because - // * Attributes like `name` or `type` cannot be set/changed once an element - // is inserted into a document/fragment - // * Link elements with `src` attributes that are inaccessible, as with - // a 403 response, will cause the tab/window to crash - // * Script elements appended to fragments will execute when their `src` - // or `text` property is set - return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; - } - - /** - * returns a shived DocumentFragment for the given document - * @memberOf html5 - * @param {Document} ownerDocument The context document. - * @returns {Object} The shived DocumentFragment. - */ - function createDocumentFragment(ownerDocument, data){ - if (!ownerDocument) { - ownerDocument = document; - } - if(supportsUnknownElements){ - return ownerDocument.createDocumentFragment(); - } - data = data || getExpandoData(ownerDocument); - var clone = data.frag.cloneNode(), - i = 0, - elems = getElements(), - l = elems.length; - for(;i>shiv*/ - - // Assign private properties to the return object with prefix - Modernizr._version = version; - - // expose these for the plugin API. Look in the source for how to join() them against your input - /*>>prefixes*/ - Modernizr._prefixes = prefixes; - /*>>prefixes*/ - /*>>domprefixes*/ - Modernizr._domPrefixes = domPrefixes; - Modernizr._cssomPrefixes = cssomPrefixes; - /*>>domprefixes*/ - - /*>>mq*/ - // Modernizr.mq tests a given media query, live against the current state of the window - // A few important notes: - // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false - // * A max-width or orientation query will be evaluated against the current state, which may change later. - // * You must specify values. Eg. If you are testing support for the min-width media query use: - // Modernizr.mq('(min-width:0)') - // usage: - // Modernizr.mq('only screen and (max-width:768)') - Modernizr.mq = testMediaQuery; - /*>>mq*/ - - /*>>hasevent*/ - // Modernizr.hasEvent() detects support for a given event, with an optional element to test on - // Modernizr.hasEvent('gesturestart', elem) - Modernizr.hasEvent = isEventSupported; - /*>>hasevent*/ - - /*>>testprop*/ - // Modernizr.testProp() investigates whether a given style property is recognized - // Note that the property names must be provided in the camelCase variant. - // Modernizr.testProp('pointerEvents') - Modernizr.testProp = function(prop){ - return testProps([prop]); - }; - /*>>testprop*/ - - /*>>testallprops*/ - // Modernizr.testAllProps() investigates whether a given style property, - // or any of its vendor-prefixed variants, is recognized - // Note that the property names must be provided in the camelCase variant. - // Modernizr.testAllProps('boxSizing') - Modernizr.testAllProps = testPropsAll; - /*>>testallprops*/ - - - /*>>teststyles*/ - // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards - // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... }) - Modernizr.testStyles = injectElementWithStyles; - /*>>teststyles*/ - - - /*>>prefixed*/ - // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input - // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' - - // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. - // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: - // - // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); - - // If you're trying to ascertain which transition end event to bind to, you might do something like... - // - // var transEndEventNames = { - // 'WebkitTransition' : 'webkitTransitionEnd', - // 'MozTransition' : 'transitionend', - // 'OTransition' : 'oTransitionEnd', - // 'msTransition' : 'MSTransitionEnd', - // 'transition' : 'transitionend' - // }, - // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; - - Modernizr.prefixed = function(prop, obj, elem){ - if(!obj) { - return testPropsAll(prop, 'pfx'); - } else { - // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' - return testPropsAll(prop, obj, elem); - } - }; - /*>>prefixed*/ - - - /*>>cssclasses*/ - // Remove "no-js" class from element, if it exists: - docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + - - // Add the new classes to the element. - (enableClasses ? ' js ' + classes.join(' ') : ''); - /*>>cssclasses*/ - - return Modernizr; - -})(this, this.document); diff --git a/third_party/phantomjs/examples/module.js b/third_party/phantomjs/examples/module.js deleted file mode 100644 index c3826e9509a..00000000000 --- a/third_party/phantomjs/examples/module.js +++ /dev/null @@ -1,5 +0,0 @@ -"use strict"; -var universe = require('./universe'); -universe.start(); -console.log('The answer is ' + universe.answer); -phantom.exit(); diff --git a/third_party/phantomjs/examples/netlog.js b/third_party/phantomjs/examples/netlog.js deleted file mode 100644 index 0418c23f7ca..00000000000 --- a/third_party/phantomjs/examples/netlog.js +++ /dev/null @@ -1,26 +0,0 @@ -"use strict"; -var page = require('webpage').create(), - system = require('system'), - address; - -if (system.args.length === 1) { - console.log('Usage: netlog.js '); - phantom.exit(1); -} else { - address = system.args[1]; - - page.onResourceRequested = function (req) { - console.log('requested: ' + JSON.stringify(req, undefined, 4)); - }; - - page.onResourceReceived = function (res) { - console.log('received: ' + JSON.stringify(res, undefined, 4)); - }; - - page.open(address, function (status) { - if (status !== 'success') { - console.log('FAIL to load the address'); - } - phantom.exit(); - }); -} diff --git a/third_party/phantomjs/examples/netsniff.js b/third_party/phantomjs/examples/netsniff.js deleted file mode 100644 index 4655a364312..00000000000 --- a/third_party/phantomjs/examples/netsniff.js +++ /dev/null @@ -1,144 +0,0 @@ -"use strict"; -if (!Date.prototype.toISOString) { - Date.prototype.toISOString = function () { - function pad(n) { return n < 10 ? '0' + n : n; } - function ms(n) { return n < 10 ? '00'+ n : n < 100 ? '0' + n : n } - return this.getFullYear() + '-' + - pad(this.getMonth() + 1) + '-' + - pad(this.getDate()) + 'T' + - pad(this.getHours()) + ':' + - pad(this.getMinutes()) + ':' + - pad(this.getSeconds()) + '.' + - ms(this.getMilliseconds()) + 'Z'; - } -} - -function createHAR(address, title, startTime, resources) -{ - var entries = []; - - resources.forEach(function (resource) { - var request = resource.request, - startReply = resource.startReply, - endReply = resource.endReply; - - if (!request || !startReply || !endReply) { - return; - } - - // Exclude Data URI from HAR file because - // they aren't included in specification - if (request.url.match(/(^data:image\/.*)/i)) { - return; - } - - entries.push({ - startedDateTime: request.time.toISOString(), - time: endReply.time - request.time, - request: { - method: request.method, - url: request.url, - httpVersion: "HTTP/1.1", - cookies: [], - headers: request.headers, - queryString: [], - headersSize: -1, - bodySize: -1 - }, - response: { - status: endReply.status, - statusText: endReply.statusText, - httpVersion: "HTTP/1.1", - cookies: [], - headers: endReply.headers, - redirectURL: "", - headersSize: -1, - bodySize: startReply.bodySize, - content: { - size: startReply.bodySize, - mimeType: endReply.contentType - } - }, - cache: {}, - timings: { - blocked: 0, - dns: -1, - connect: -1, - send: 0, - wait: startReply.time - request.time, - receive: endReply.time - startReply.time, - ssl: -1 - }, - pageref: address - }); - }); - - return { - log: { - version: '1.2', - creator: { - name: "PhantomJS", - version: phantom.version.major + '.' + phantom.version.minor + - '.' + phantom.version.patch - }, - pages: [{ - startedDateTime: startTime.toISOString(), - id: address, - title: title, - pageTimings: { - onLoad: page.endTime - page.startTime - } - }], - entries: entries - } - }; -} - -var page = require('webpage').create(), - system = require('system'); - -if (system.args.length === 1) { - console.log('Usage: netsniff.js '); - phantom.exit(1); -} else { - - page.address = system.args[1]; - page.resources = []; - - page.onLoadStarted = function () { - page.startTime = new Date(); - }; - - page.onResourceRequested = function (req) { - page.resources[req.id] = { - request: req, - startReply: null, - endReply: null - }; - }; - - page.onResourceReceived = function (res) { - if (res.stage === 'start') { - page.resources[res.id].startReply = res; - } - if (res.stage === 'end') { - page.resources[res.id].endReply = res; - } - }; - - page.open(page.address, function (status) { - var har; - if (status !== 'success') { - console.log('FAIL to load the address'); - phantom.exit(1); - } else { - page.endTime = new Date(); - page.title = page.evaluate(function () { - return document.title; - }); - har = createHAR(page.address, page.title, page.startTime, page.resources); - console.log(JSON.stringify(har, undefined, 4)); - phantom.exit(); - } - }); -} diff --git a/third_party/phantomjs/examples/openurlwithproxy.js b/third_party/phantomjs/examples/openurlwithproxy.js deleted file mode 100644 index 30b6ffd42a7..00000000000 --- a/third_party/phantomjs/examples/openurlwithproxy.js +++ /dev/null @@ -1,25 +0,0 @@ -"use strict"; -var page = require('webpage').create(), - system = require('system'), - host, port, address; - -if (system.args.length < 4) { - console.log('Usage: openurlwithproxy.js '); - phantom.exit(1); -} else { - host = system.args[1]; - port = system.args[2]; - address = system.args[3]; - phantom.setProxy(host, port, 'manual', '', ''); - page.open(address, function (status) { - if (status !== 'success') { - console.log('FAIL to load the address "' + - address + '" using proxy "' + host + ':' + port + '"'); - } else { - console.log('Page title is ' + page.evaluate(function () { - return document.title; - })); - } - phantom.exit(); - }); -} diff --git a/third_party/phantomjs/examples/outputEncoding.js b/third_party/phantomjs/examples/outputEncoding.js deleted file mode 100644 index 82af2444c3f..00000000000 --- a/third_party/phantomjs/examples/outputEncoding.js +++ /dev/null @@ -1,17 +0,0 @@ -"use strict"; -function helloWorld() { - console.log(phantom.outputEncoding + ": こんにちは、世界!"); -} - -console.log("Using default encoding..."); -helloWorld(); - -console.log("\nUsing other encodings..."); - -var encodings = ["euc-jp", "sjis", "utf8", "System"]; -for (var i = 0; i < encodings.length; i++) { - phantom.outputEncoding = encodings[i]; - helloWorld(); -} - -phantom.exit() diff --git a/third_party/phantomjs/examples/page_events.js b/third_party/phantomjs/examples/page_events.js deleted file mode 100644 index ef6563ec0c6..00000000000 --- a/third_party/phantomjs/examples/page_events.js +++ /dev/null @@ -1,147 +0,0 @@ -// The purpose of this is to show how and when events fire, considering 5 steps -// happening as follows: -// -// 1. Load URL -// 2. Load same URL, but adding an internal FRAGMENT to it -// 3. Click on an internal Link, that points to another internal FRAGMENT -// 4. Click on an external Link, that will send the page somewhere else -// 5. Close page -// -// Take particular care when going through the output, to understand when -// things happen (and in which order). Particularly, notice what DOESN'T -// happen during step 3. -// -// If invoked with "-v" it will print out the Page Resources as they are -// Requested and Received. -// -// NOTE.1: The "onConsoleMessage/onAlert/onPrompt/onConfirm" events are -// registered but not used here. This is left for you to have fun with. -// NOTE.2: This script is not here to teach you ANY JavaScript. It's aweful! -// NOTE.3: Main audience for this are people new to PhantomJS. - -"use strict"; -var sys = require("system"), - page = require("webpage").create(), - logResources = false, - step1url = "http://en.wikipedia.org/wiki/DOM_events", - step2url = "http://en.wikipedia.org/wiki/DOM_events#Event_flow"; - -if (sys.args.length > 1 && sys.args[1] === "-v") { - logResources = true; -} - -function printArgs() { - var i, ilen; - for (i = 0, ilen = arguments.length; i < ilen; ++i) { - console.log(" arguments[" + i + "] = " + JSON.stringify(arguments[i])); - } - console.log(""); -} - -//////////////////////////////////////////////////////////////////////////////// - -page.onInitialized = function() { - console.log("page.onInitialized"); - printArgs.apply(this, arguments); -}; -page.onLoadStarted = function() { - console.log("page.onLoadStarted"); - printArgs.apply(this, arguments); -}; -page.onLoadFinished = function() { - console.log("page.onLoadFinished"); - printArgs.apply(this, arguments); -}; -page.onUrlChanged = function() { - console.log("page.onUrlChanged"); - printArgs.apply(this, arguments); -}; -page.onNavigationRequested = function() { - console.log("page.onNavigationRequested"); - printArgs.apply(this, arguments); -}; -page.onRepaintRequested = function() { - console.log("page.onRepaintRequested"); - printArgs.apply(this, arguments); -}; - -if (logResources === true) { - page.onResourceRequested = function() { - console.log("page.onResourceRequested"); - printArgs.apply(this, arguments); - }; - page.onResourceReceived = function() { - console.log("page.onResourceReceived"); - printArgs.apply(this, arguments); - }; -} - -page.onClosing = function() { - console.log("page.onClosing"); - printArgs.apply(this, arguments); -}; - -// window.console.log(msg); -page.onConsoleMessage = function() { - console.log("page.onConsoleMessage"); - printArgs.apply(this, arguments); -}; - -// window.alert(msg); -page.onAlert = function() { - console.log("page.onAlert"); - printArgs.apply(this, arguments); -}; -// var confirmed = window.confirm(msg); -page.onConfirm = function() { - console.log("page.onConfirm"); - printArgs.apply(this, arguments); -}; -// var user_value = window.prompt(msg, default_value); -page.onPrompt = function() { - console.log("page.onPrompt"); - printArgs.apply(this, arguments); -}; - -//////////////////////////////////////////////////////////////////////////////// - -setTimeout(function() { - console.log(""); - console.log("### STEP 1: Load '" + step1url + "'"); - page.open(step1url); -}, 0); - -setTimeout(function() { - console.log(""); - console.log("### STEP 2: Load '" + step2url + "' (load same URL plus FRAGMENT)"); - page.open(step2url); -}, 5000); - -setTimeout(function() { - console.log(""); - console.log("### STEP 3: Click on page internal link (aka FRAGMENT)"); - page.evaluate(function() { - var ev = document.createEvent("MouseEvents"); - ev.initEvent("click", true, true); - document.querySelector("a[href='#Event_object']").dispatchEvent(ev); - }); -}, 10000); - -setTimeout(function() { - console.log(""); - console.log("### STEP 4: Click on page external link"); - page.evaluate(function() { - var ev = document.createEvent("MouseEvents"); - ev.initEvent("click", true, true); - document.querySelector("a[title='JavaScript']").dispatchEvent(ev); - }); -}, 15000); - -setTimeout(function() { - console.log(""); - console.log("### STEP 5: Close page and shutdown (with a delay)"); - page.close(); - setTimeout(function(){ - phantom.exit(); - }, 100); -}, 20000); diff --git a/third_party/phantomjs/examples/pagecallback.js b/third_party/phantomjs/examples/pagecallback.js deleted file mode 100644 index a14b57e8ce3..00000000000 --- a/third_party/phantomjs/examples/pagecallback.js +++ /dev/null @@ -1,18 +0,0 @@ -"use strict"; -var p = require("webpage").create(); - -p.onConsoleMessage = function(msg) { console.log(msg); }; - -// Calls to "callPhantom" within the page 'p' arrive here -p.onCallback = function(msg) { - console.log("Received by the 'phantom' main context: "+msg); - return "Hello there, I'm coming to you from the 'phantom' context instead"; -}; - -p.evaluate(function() { - // Return-value of the "onCallback" handler arrive here - var callbackResponse = window.callPhantom("Hello, I'm coming to you from the 'page' context"); - console.log("Received by the 'page' context: "+callbackResponse); -}); - -phantom.exit(); diff --git a/third_party/phantomjs/examples/phantomwebintro.js b/third_party/phantomjs/examples/phantomwebintro.js deleted file mode 100644 index 6cb4e46d87c..00000000000 --- a/third_party/phantomjs/examples/phantomwebintro.js +++ /dev/null @@ -1,21 +0,0 @@ -// Read the Phantom webpage '#intro' element text using jQuery and "includeJs" - -"use strict"; -var page = require('webpage').create(); - -page.onConsoleMessage = function(msg) { - console.log(msg); -}; - -page.open("http://phantomjs.org/", function(status) { - if (status === "success") { - page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() { - page.evaluate(function() { - console.log("$(\".explanation\").text() -> " + $(".explanation").text()); - }); - phantom.exit(0); - }); - } else { - phantom.exit(1); - } -}); diff --git a/third_party/phantomjs/examples/post.js b/third_party/phantomjs/examples/post.js deleted file mode 100644 index 4b998b82a91..00000000000 --- a/third_party/phantomjs/examples/post.js +++ /dev/null @@ -1,15 +0,0 @@ -// Example using HTTP POST operation - -"use strict"; -var page = require('webpage').create(), - server = 'http://posttestserver.com/post.php?dump', - data = 'universe=expanding&answer=42'; - -page.open(server, 'post', data, function (status) { - if (status !== 'success') { - console.log('Unable to post!'); - } else { - console.log(page.content); - } - phantom.exit(); -}); diff --git a/third_party/phantomjs/examples/postjson.js b/third_party/phantomjs/examples/postjson.js deleted file mode 100644 index b02f4303783..00000000000 --- a/third_party/phantomjs/examples/postjson.js +++ /dev/null @@ -1,19 +0,0 @@ -// Example using HTTP POST operation - -"use strict"; -var page = require('webpage').create(), - server = 'http://posttestserver.com/post.php?dump', - data = '{"universe": "expanding", "answer": 42}'; - -var headers = { - "Content-Type": "application/json" -} - -page.open(server, 'post', data, headers, function (status) { - if (status !== 'success') { - console.log('Unable to post!'); - } else { - console.log(page.content); - } - phantom.exit(); -}); diff --git a/third_party/phantomjs/examples/postserver.js b/third_party/phantomjs/examples/postserver.js deleted file mode 100644 index e854701b28e..00000000000 --- a/third_party/phantomjs/examples/postserver.js +++ /dev/null @@ -1,35 +0,0 @@ -// Example using HTTP POST operation - -"use strict"; -var page = require('webpage').create(), - server = require('webserver').create(), - system = require('system'), - data = 'universe=expanding&answer=42'; - -if (system.args.length !== 2) { - console.log('Usage: postserver.js '); - phantom.exit(1); -} - -var port = system.args[1]; - -service = server.listen(port, function (request, response) { - console.log('Request received at ' + new Date()); - - response.statusCode = 200; - response.headers = { - 'Cache': 'no-cache', - 'Content-Type': 'text/plain;charset=utf-8' - }; - response.write(JSON.stringify(request, null, 4)); - response.close(); -}); - -page.open('http://localhost:' + port + '/', 'post', data, function (status) { - if (status !== 'success') { - console.log('Unable to post!'); - } else { - console.log(page.plainText); - } - phantom.exit(); -}); diff --git a/third_party/phantomjs/examples/printenv.js b/third_party/phantomjs/examples/printenv.js deleted file mode 100644 index 6baea038391..00000000000 --- a/third_party/phantomjs/examples/printenv.js +++ /dev/null @@ -1,10 +0,0 @@ -var system = require('system'), - env = system.env, - key; - -for (key in env) { - if (env.hasOwnProperty(key)) { - console.log(key + '=' + env[key]); - } -} -phantom.exit(); diff --git a/third_party/phantomjs/examples/printheaderfooter.js b/third_party/phantomjs/examples/printheaderfooter.js deleted file mode 100644 index 286af2b0abf..00000000000 --- a/third_party/phantomjs/examples/printheaderfooter.js +++ /dev/null @@ -1,90 +0,0 @@ -"use strict"; -var page = require('webpage').create(), - system = require('system'); - -function someCallback(pageNum, numPages) { - return "

someCallback: " + pageNum + " / " + numPages + "

"; -} - -if (system.args.length < 3) { - console.log('Usage: printheaderfooter.js URL filename'); - phantom.exit(1); -} else { - var address = system.args[1]; - var output = system.args[2]; - page.viewportSize = { width: 600, height: 600 }; - page.paperSize = { - format: 'A4', - margin: "1cm", - /* default header/footer for pages that don't have custom overwrites (see below) */ - header: { - height: "1cm", - contents: phantom.callback(function(pageNum, numPages) { - if (pageNum == 1) { - return ""; - } - return "

Header " + pageNum + " / " + numPages + "

"; - }) - }, - footer: { - height: "1cm", - contents: phantom.callback(function(pageNum, numPages) { - if (pageNum == numPages) { - return ""; - } - return "

Footer " + pageNum + " / " + numPages + "

"; - }) - } - }; - page.open(address, function (status) { - if (status !== 'success') { - console.log('Unable to load the address!'); - } else { - /* check whether the loaded page overwrites the header/footer setting, - i.e. whether a PhantomJSPriting object exists. Use that then instead - of our defaults above. - - example: - - - - -

asdfadsf

asdfadsfycvx

- - */ - if (page.evaluate(function(){return typeof PhantomJSPrinting == "object";})) { - paperSize = page.paperSize; - paperSize.header.height = page.evaluate(function() { - return PhantomJSPrinting.header.height; - }); - paperSize.header.contents = phantom.callback(function(pageNum, numPages) { - return page.evaluate(function(pageNum, numPages){return PhantomJSPrinting.header.contents(pageNum, numPages);}, pageNum, numPages); - }); - paperSize.footer.height = page.evaluate(function() { - return PhantomJSPrinting.footer.height; - }); - paperSize.footer.contents = phantom.callback(function(pageNum, numPages) { - return page.evaluate(function(pageNum, numPages){return PhantomJSPrinting.footer.contents(pageNum, numPages);}, pageNum, numPages); - }); - page.paperSize = paperSize; - console.log(page.paperSize.header.height); - console.log(page.paperSize.footer.height); - } - window.setTimeout(function () { - page.render(output); - phantom.exit(); - }, 200); - } - }); -} diff --git a/third_party/phantomjs/examples/printmargins.js b/third_party/phantomjs/examples/printmargins.js deleted file mode 100644 index 57c1acc19c5..00000000000 --- a/third_party/phantomjs/examples/printmargins.js +++ /dev/null @@ -1,36 +0,0 @@ -"use strict"; -var page = require('webpage').create(), - system = require('system'); - -if (system.args.length < 7) { - console.log('Usage: printmargins.js URL filename LEFT TOP RIGHT BOTTOM'); - console.log(' margin examples: "1cm", "10px", "7mm", "5in"'); - phantom.exit(1); -} else { - var address = system.args[1]; - var output = system.args[2]; - var marginLeft = system.args[3]; - var marginTop = system.args[4]; - var marginRight = system.args[5]; - var marginBottom = system.args[6]; - page.viewportSize = { width: 600, height: 600 }; - page.paperSize = { - format: 'A4', - margin: { - left: marginLeft, - top: marginTop, - right: marginRight, - bottom: marginBottom - } - }; - page.open(address, function (status) { - if (status !== 'success') { - console.log('Unable to load the address!'); - } else { - window.setTimeout(function () { - page.render(output); - phantom.exit(); - }, 200); - } - }); -} diff --git a/third_party/phantomjs/examples/rasterize.js b/third_party/phantomjs/examples/rasterize.js deleted file mode 100644 index c0950deb4e8..00000000000 --- a/third_party/phantomjs/examples/rasterize.js +++ /dev/null @@ -1,49 +0,0 @@ -"use strict"; -var page = require('webpage').create(), - system = require('system'), - address, output, size; - -if (system.args.length < 3 || system.args.length > 5) { - console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]'); - console.log(' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"'); - console.log(' image (png/jpg output) examples: "1920px" entire page, window width 1920px'); - console.log(' "800px*600px" window, clipped to 800x600'); - phantom.exit(1); -} else { - address = system.args[1]; - output = system.args[2]; - page.viewportSize = { width: 600, height: 600 }; - if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") { - size = system.args[3].split('*'); - page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' } - : { format: system.args[3], orientation: 'portrait', margin: '1cm' }; - } else if (system.args.length > 3 && system.args[3].substr(-2) === "px") { - size = system.args[3].split('*'); - if (size.length === 2) { - pageWidth = parseInt(size[0], 10); - pageHeight = parseInt(size[1], 10); - page.viewportSize = { width: pageWidth, height: pageHeight }; - page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight }; - } else { - console.log("size:", system.args[3]); - pageWidth = parseInt(system.args[3], 10); - pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any - console.log ("pageHeight:",pageHeight); - page.viewportSize = { width: pageWidth, height: pageHeight }; - } - } - if (system.args.length > 4) { - page.zoomFactor = system.args[4]; - } - page.open(address, function (status) { - if (status !== 'success') { - console.log('Unable to load the address!'); - phantom.exit(1); - } else { - window.setTimeout(function () { - page.render(output); - phantom.exit(); - }, 200); - } - }); -} diff --git a/third_party/phantomjs/examples/render_multi_url.js b/third_party/phantomjs/examples/render_multi_url.js deleted file mode 100644 index 9f7348debc6..00000000000 --- a/third_party/phantomjs/examples/render_multi_url.js +++ /dev/null @@ -1,74 +0,0 @@ -// Render Multiple URLs to file - -"use strict"; -var RenderUrlsToFile, arrayOfUrls, system; - -system = require("system"); - -/* -Render given urls -@param array of URLs to render -@param callbackPerUrl Function called after finishing each URL, including the last URL -@param callbackFinal Function called after finishing everything -*/ -RenderUrlsToFile = function(urls, callbackPerUrl, callbackFinal) { - var getFilename, next, page, retrieve, urlIndex, webpage; - urlIndex = 0; - webpage = require("webpage"); - page = null; - getFilename = function() { - return "rendermulti-" + urlIndex + ".png"; - }; - next = function(status, url, file) { - page.close(); - callbackPerUrl(status, url, file); - return retrieve(); - }; - retrieve = function() { - var url; - if (urls.length > 0) { - url = urls.shift(); - urlIndex++; - page = webpage.create(); - page.viewportSize = { - width: 800, - height: 600 - }; - page.settings.userAgent = "Phantom.js bot"; - return page.open("http://" + url, function(status) { - var file; - file = getFilename(); - if (status === "success") { - return window.setTimeout((function() { - page.render(file); - return next(status, url, file); - }), 200); - } else { - return next(status, url, file); - } - }); - } else { - return callbackFinal(); - } - }; - return retrieve(); -}; - -arrayOfUrls = null; - -if (system.args.length > 1) { - arrayOfUrls = Array.prototype.slice.call(system.args, 1); -} else { - console.log("Usage: phantomjs render_multi_url.js [domain.name1, domain.name2, ...]"); - arrayOfUrls = ["www.google.com", "www.bbc.co.uk", "phantomjs.org"]; -} - -RenderUrlsToFile(arrayOfUrls, (function(status, url, file) { - if (status !== "success") { - return console.log("Unable to render '" + url + "'"); - } else { - return console.log("Rendered '" + url + "' at '" + file + "'"); - } -}), function() { - return phantom.exit(); -}); diff --git a/third_party/phantomjs/examples/responsive-screenshot.js b/third_party/phantomjs/examples/responsive-screenshot.js deleted file mode 100644 index 35aac605f53..00000000000 --- a/third_party/phantomjs/examples/responsive-screenshot.js +++ /dev/null @@ -1,181 +0,0 @@ -/** - * Captures the full height document even if it's not showing on the screen or captures with the provided range of screen sizes. - * - * A basic example for taking a screen shot using phantomjs which is sampled for https://nodejs-dersleri.github.io/ - * - * usage : phantomjs responsive-screenshot.js {url} [output format] [doClipping] - * - * examples > - * phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/ - * phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/ pdf - * phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/ true - * phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/ png true - * - * @author Salih sagdilek - */ - -/** - * http://phantomjs.org/api/system/property/args.html - * - * Queries and returns a list of the command-line arguments. - * The first one is always the script name, which is then followed by the subsequent arguments. - */ -var args = require('system').args; -/** - * http://phantomjs.org/api/fs/ - * - * file system api - */ -var fs = require('fs'); - -/** - * http://phantomjs.org/api/webpage/ - * - * Web page api - */ -var page = new WebPage(); - -/** - * if url address does not exist, exit phantom - */ -if ( 1 === args.length ) { - console.log('Url address is required'); - phantom.exit(); -} - -/** - * setup url address (second argument); - */ -var urlAddress = args[1].toLowerCase(); - - -/** - * set output extension format - * @type {*} - */ -var ext = getFileExtension(); - -/** - * set if clipping ? - * @type {boolean} - */ -var clipping = getClipping(); - -/** - * setup viewports - */ -var viewports = [ - { - width : 1200, - height : 800 - }, - { - width : 1024, - height : 768 - }, - { - width : 768, - height : 1024 - }, - { - width : 480, - height : 640 - }, - { - width : 320, - height : 480 - } -]; - -page.open(urlAddress, function (status) { - if ( 'success' !== status ) { - console.log('Unable to load the url address!'); - } else { - var folder = urlToDir(urlAddress); - var output, key; - - function render(n) { - if ( !!n ) { - key = n - 1; - page.viewportSize = viewports[key]; - if ( clipping ) { - page.clipRect = viewports[key]; - } - output = folder + "/" + getFileName(viewports[key]); - console.log('Saving ' + output); - page.render(output); - render(key); - } - } - - render(viewports.length); - } - phantom.exit(); -}); - -/** - * filename generator helper - * @param viewport - * @returns {string} - */ -function getFileName(viewport) { - var d = new Date(); - var date = [ - d.getUTCFullYear(), - d.getUTCMonth() + 1, - d.getUTCDate() - ]; - var time = [ - d.getHours() <= 9 ? '0' + d.getHours() : d.getHours(), - d.getMinutes() <= 9 ? '0' + d.getMinutes() : d.getMinutes(), - d.getSeconds() <= 9 ? '0' + d.getSeconds() : d.getSeconds(), - d.getMilliseconds() - ]; - var resolution = viewport.width + (clipping ? "x" + viewport.height : ''); - - return date.join('-') + '_' + time.join('-') + "_" + resolution + ext; -} - -/** - * output extension format helper - * - * @returns {*} - */ -function getFileExtension() { - if ( 'true' != args[2] && !!args[2] ) { - return '.' + args[2]; - } - return '.png'; -} - -/** - * check if clipping - * - * @returns {boolean} - */ -function getClipping() { - if ( 'true' == args[3] ) { - return !!args[3]; - } else if ( 'true' == args[2] ) { - return !!args[2]; - } - return false; -} - -/** - * url to directory helper - * - * @param url - * @returns {string} - */ -function urlToDir(url) { - var dir = url - .replace(/^(http|https):\/\//, '') - .replace(/\/$/, ''); - - if ( !fs.makeTree(dir) ) { - console.log('"' + dir + '" is NOT created.'); - phantom.exit(); - } - return dir; -} diff --git a/third_party/phantomjs/examples/run-jasmine.js b/third_party/phantomjs/examples/run-jasmine.js deleted file mode 100644 index 652bb61ec84..00000000000 --- a/third_party/phantomjs/examples/run-jasmine.js +++ /dev/null @@ -1,92 +0,0 @@ -"use strict"; -var system = require('system'); - -/** - * Wait until the test condition is true or a timeout occurs. Useful for waiting - * on a server response or for a ui change (fadeIn, etc.) to occur. - * - * @param testFx javascript condition that evaluates to a boolean, - * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or - * as a callback function. - * @param onReady what to do when testFx condition is fulfilled, - * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or - * as a callback function. - * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used. - */ -function waitFor(testFx, onReady, timeOutMillis) { - var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timeout is 3s - start = new Date().getTime(), - condition = false, - interval = setInterval(function() { - if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) { - // If not time-out yet and condition not yet fulfilled - condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code - } else { - if(!condition) { - // If condition still not fulfilled (timeout but condition is 'false') - console.log("'waitFor()' timeout"); - phantom.exit(1); - } else { - // Condition fulfilled (timeout and/or condition is 'true') - console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms."); - typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled - clearInterval(interval); //< Stop this interval - } - } - }, 100); //< repeat check every 100ms -}; - - -if (system.args.length !== 2) { - console.log('Usage: run-jasmine.js URL'); - phantom.exit(1); -} - -var page = require('webpage').create(); - -// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this") -page.onConsoleMessage = function(msg) { - console.log(msg); -}; - -page.open(system.args[1], function(status){ - if (status !== "success") { - console.log("Unable to open " + system.args[1]); - phantom.exit(1); - } else { - waitFor(function(){ - return page.evaluate(function(){ - return document.body.querySelector('.symbolSummary .pending') === null - }); - }, function(){ - var exitCode = page.evaluate(function(){ - try { - console.log(''); - console.log(document.body.querySelector('.description').innerText); - var list = document.body.querySelectorAll('.results > #details > .specDetail.failed'); - if (list && list.length > 0) { - console.log(''); - console.log(list.length + ' test(s) FAILED:'); - for (i = 0; i < list.length; ++i) { - var el = list[i], - desc = el.querySelector('.description'), - msg = el.querySelector('.resultMessage.fail'); - console.log(''); - console.log(desc.innerText); - console.log(msg.innerText); - console.log(''); - } - return 1; - } else { - console.log(document.body.querySelector('.alert > .passingAlert.bar').innerText); - return 0; - } - } catch (ex) { - console.log(ex); - return 1; - } - }); - phantom.exit(exitCode); - }); - } -}); diff --git a/third_party/phantomjs/examples/run-jasmine2.js b/third_party/phantomjs/examples/run-jasmine2.js deleted file mode 100644 index 343117ab0d6..00000000000 --- a/third_party/phantomjs/examples/run-jasmine2.js +++ /dev/null @@ -1,94 +0,0 @@ -"use strict"; -var system = require('system'); - -/** - * Wait until the test condition is true or a timeout occurs. Useful for waiting - * on a server response or for a ui change (fadeIn, etc.) to occur. - * - * @param testFx javascript condition that evaluates to a boolean, - * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or - * as a callback function. - * @param onReady what to do when testFx condition is fulfilled, - * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or - * as a callback function. - * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used. - */ -function waitFor(testFx, onReady, timeOutMillis) { - var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timeout is 3s - start = new Date().getTime(), - condition = false, - interval = setInterval(function() { - if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) { - // If not time-out yet and condition not yet fulfilled - condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code - } else { - if(!condition) { - // If condition still not fulfilled (timeout but condition is 'false') - console.log("'waitFor()' timeout"); - phantom.exit(1); - } else { - // Condition fulfilled (timeout and/or condition is 'true') - console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms."); - typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled - clearInterval(interval); //< Stop this interval - } - } - }, 100); //< repeat check every 100ms -}; - - -if (system.args.length !== 2) { - console.log('Usage: run-jasmine2.js URL'); - phantom.exit(1); -} - -var page = require('webpage').create(); - -// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this") -page.onConsoleMessage = function(msg) { - console.log(msg); -}; - -page.open(system.args[1], function(status){ - if (status !== "success") { - console.log("Unable to access network"); - phantom.exit(); - } else { - waitFor(function(){ - return page.evaluate(function(){ - return (document.body.querySelector('.symbolSummary .pending') === null && - document.body.querySelector('.duration') !== null); - }); - }, function(){ - var exitCode = page.evaluate(function(){ - console.log(''); - - var title = 'Jasmine'; - var version = document.body.querySelector('.version').innerText; - var duration = document.body.querySelector('.duration').innerText; - var banner = title + ' ' + version + ' ' + duration; - console.log(banner); - - var list = document.body.querySelectorAll('.results > .failures > .spec-detail.failed'); - if (list && list.length > 0) { - console.log(''); - console.log(list.length + ' test(s) FAILED:'); - for (i = 0; i < list.length; ++i) { - var el = list[i], - desc = el.querySelector('.description'), - msg = el.querySelector('.messages > .result-message'); - console.log(''); - console.log(desc.innerText); - console.log(msg.innerText); - console.log(''); - } - return 1; - } else { - console.log(document.body.querySelector('.alert > .bar.passed,.alert > .bar.skipped').innerText); - return 0; - } - }); - phantom.exit(exitCode); - }); - } -}); diff --git a/third_party/phantomjs/examples/run-qunit.js b/third_party/phantomjs/examples/run-qunit.js deleted file mode 100644 index d3cbf5b9c9a..00000000000 --- a/third_party/phantomjs/examples/run-qunit.js +++ /dev/null @@ -1,77 +0,0 @@ -"use strict"; -var system = require('system'); - -/** - * Wait until the test condition is true or a timeout occurs. Useful for waiting - * on a server response or for a ui change (fadeIn, etc.) to occur. - * - * @param testFx javascript condition that evaluates to a boolean, - * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or - * as a callback function. - * @param onReady what to do when testFx condition is fulfilled, - * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or - * as a callback function. - * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used. - */ -function waitFor(testFx, onReady, timeOutMillis) { - var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timout is 3s - start = new Date().getTime(), - condition = false, - interval = setInterval(function() { - if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) { - // If not time-out yet and condition not yet fulfilled - condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code - } else { - if(!condition) { - // If condition still not fulfilled (timeout but condition is 'false') - console.log("'waitFor()' timeout"); - phantom.exit(1); - } else { - // Condition fulfilled (timeout and/or condition is 'true') - console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms."); - typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled - clearInterval(interval); //< Stop this interval - } - } - }, 100); //< repeat check every 250ms -}; - - -if (system.args.length !== 2) { - console.log('Usage: run-qunit.js URL'); - phantom.exit(1); -} - -var page = require('webpage').create(); - -// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this") -page.onConsoleMessage = function(msg) { - console.log(msg); -}; - -page.open(system.args[1], function(status){ - if (status !== "success") { - console.log("Unable to access network"); - phantom.exit(1); - } else { - waitFor(function(){ - return page.evaluate(function(){ - var el = document.getElementById('qunit-testresult'); - if (el && el.innerText.match('completed')) { - return true; - } - return false; - }); - }, function(){ - var failedNum = page.evaluate(function(){ - var el = document.getElementById('qunit-testresult'); - console.log(el.innerText); - try { - return el.getElementsByClassName('failed')[0].innerHTML; - } catch (e) { } - return 10000; - }); - phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0); - }); - } -}); diff --git a/third_party/phantomjs/examples/scandir.js b/third_party/phantomjs/examples/scandir.js deleted file mode 100644 index 73943679a10..00000000000 --- a/third_party/phantomjs/examples/scandir.js +++ /dev/null @@ -1,24 +0,0 @@ -// List all the files in a Tree of Directories - -"use strict"; -var system = require('system'); - -if (system.args.length !== 2) { - console.log("Usage: phantomjs scandir.js DIRECTORY_TO_SCAN"); - phantom.exit(1); -} - -var scanDirectory = function (path) { - var fs = require('fs'); - if (fs.exists(path) && fs.isFile(path)) { - console.log(path); - } else if (fs.isDirectory(path)) { - fs.list(path).forEach(function (e) { - if ( e !== "." && e !== ".." ) { //< Avoid loops - scanDirectory(path + '/' + e); - } - }); - } -}; -scanDirectory(system.args[1]); -phantom.exit(); diff --git a/third_party/phantomjs/examples/server.js b/third_party/phantomjs/examples/server.js deleted file mode 100644 index ff5ef3d2f81..00000000000 --- a/third_party/phantomjs/examples/server.js +++ /dev/null @@ -1,44 +0,0 @@ -"use strict"; -var page = require('webpage').create(); -var server = require('webserver').create(); -var system = require('system'); -var host, port; - -if (system.args.length !== 2) { - console.log('Usage: server.js '); - phantom.exit(1); -} else { - port = system.args[1]; - var listening = server.listen(port, function (request, response) { - console.log("GOT HTTP REQUEST"); - console.log(JSON.stringify(request, null, 4)); - - // we set the headers here - response.statusCode = 200; - response.headers = {"Cache": "no-cache", "Content-Type": "text/html"}; - // this is also possible: - response.setHeader("foo", "bar"); - // now we write the body - // note: the headers above will now be sent implictly - response.write("YES!"); - // note: writeBody can be called multiple times - response.write("

pretty cool :)"); - response.close(); - }); - if (!listening) { - console.log("could not create web server listening on port " + port); - phantom.exit(); - } - var url = "http://localhost:" + port + "/foo/bar.php?asdf=true"; - console.log("SENDING REQUEST TO:"); - console.log(url); - page.open(url, function (status) { - if (status !== 'success') { - console.log('FAIL to load the address'); - } else { - console.log("GOT REPLY FROM SERVER:"); - console.log(page.content); - } - phantom.exit(); - }); -} diff --git a/third_party/phantomjs/examples/serverkeepalive.js b/third_party/phantomjs/examples/serverkeepalive.js deleted file mode 100644 index 00b462aaa83..00000000000 --- a/third_party/phantomjs/examples/serverkeepalive.js +++ /dev/null @@ -1,35 +0,0 @@ -"use strict"; -var port, server, service, - system = require('system'); - -if (system.args.length !== 2) { - console.log('Usage: serverkeepalive.js '); - phantom.exit(1); -} else { - port = system.args[1]; - server = require('webserver').create(); - - service = server.listen(port, { keepAlive: true }, function (request, response) { - console.log('Request at ' + new Date()); - console.log(JSON.stringify(request, null, 4)); - - var body = JSON.stringify(request, null, 4); - response.statusCode = 200; - response.headers = { - 'Cache': 'no-cache', - 'Content-Type': 'text/plain', - 'Connection': 'Keep-Alive', - 'Keep-Alive': 'timeout=5, max=100', - 'Content-Length': body.length - }; - response.write(body); - response.close(); - }); - - if (service) { - console.log('Web server running on port ' + port); - } else { - console.log('Error: Could not create web server listening on port ' + port); - phantom.exit(); - } -} diff --git a/third_party/phantomjs/examples/simpleserver.js b/third_party/phantomjs/examples/simpleserver.js deleted file mode 100644 index ba4779a95e8..00000000000 --- a/third_party/phantomjs/examples/simpleserver.js +++ /dev/null @@ -1,43 +0,0 @@ -"use strict"; -var port, server, service, - system = require('system'); - -if (system.args.length !== 2) { - console.log('Usage: simpleserver.js '); - phantom.exit(1); -} else { - port = system.args[1]; - server = require('webserver').create(); - - service = server.listen(port, function (request, response) { - - console.log('Request at ' + new Date()); - console.log(JSON.stringify(request, null, 4)); - - response.statusCode = 200; - response.headers = { - 'Cache': 'no-cache', - 'Content-Type': 'text/html' - }; - response.write(''); - response.write(''); - response.write('Hello, world!'); - response.write(''); - response.write(''); - response.write('

This is from PhantomJS web server.

'); - response.write('

Request data:

'); - response.write('
');
-        response.write(JSON.stringify(request, null, 4));
-        response.write('
'); - response.write(''); - response.write(''); - response.close(); - }); - - if (service) { - console.log('Web server running on port ' + port); - } else { - console.log('Error: Could not create web server listening on port ' + port); - phantom.exit(); - } -} diff --git a/third_party/phantomjs/examples/sleepsort.js b/third_party/phantomjs/examples/sleepsort.js deleted file mode 100644 index 7959799567b..00000000000 --- a/third_party/phantomjs/examples/sleepsort.js +++ /dev/null @@ -1,27 +0,0 @@ -// sleepsort.js - Sort integers from the commandline in a very ridiculous way: leveraging timeouts :P - -"use strict"; -var system = require('system'); - -function sleepSort(array, callback) { - var sortedCount = 0, - i, len; - for ( i = 0, len = array.length; i < len; ++i ) { - setTimeout((function(j){ - return function() { - console.log(array[j]); - ++sortedCount; - (len === sortedCount) && callback(); - }; - }(i)), array[i]); - } -} - -if ( system.args.length < 2 ) { - console.log("Usage: phantomjs sleepsort.js PUT YOUR INTEGERS HERE SEPARATED BY SPACES"); - phantom.exit(1); -} else { - sleepSort(system.args.slice(1), function() { - phantom.exit(); - }); -} diff --git a/third_party/phantomjs/examples/stdin-stdout-stderr.js b/third_party/phantomjs/examples/stdin-stdout-stderr.js deleted file mode 100644 index 4161ba3b233..00000000000 --- a/third_party/phantomjs/examples/stdin-stdout-stderr.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; -var system = require('system'); - -system.stdout.write('Hello, system.stdout.write!'); -system.stdout.writeLine('\nHello, system.stdout.writeLine!'); - -system.stderr.write('Hello, system.stderr.write!'); -system.stderr.writeLine('\nHello, system.stderr.writeLine!'); - -system.stdout.writeLine('system.stdin.readLine(): '); -var line = system.stdin.readLine(); -system.stdout.writeLine(JSON.stringify(line)); - -// This is essentially a `readAll` -system.stdout.writeLine('system.stdin.read(5): (ctrl+D to end)'); -var input = system.stdin.read(5); -system.stdout.writeLine(JSON.stringify(input)); - -phantom.exit(0); diff --git a/third_party/phantomjs/examples/universe.js b/third_party/phantomjs/examples/universe.js deleted file mode 100644 index 2655aaf4a83..00000000000 --- a/third_party/phantomjs/examples/universe.js +++ /dev/null @@ -1,10 +0,0 @@ -// This is to be used by "module.js" (and "module.coffee") example(s). -// There should NOT be a "universe.coffee" as only 1 of the 2 would -// ever be loaded unless the file extension was specified. - -"use strict"; -exports.answer = 42; - -exports.start = function () { - console.log('Starting the universe....'); -} diff --git a/third_party/phantomjs/examples/unrandomize.js b/third_party/phantomjs/examples/unrandomize.js deleted file mode 100644 index 7f0e1bbf5e0..00000000000 --- a/third_party/phantomjs/examples/unrandomize.js +++ /dev/null @@ -1,25 +0,0 @@ -// Modify global object at the page initialization. -// In this example, effectively Math.random() always returns 0.42. - -"use strict"; -var page = require('webpage').create(); - -page.onInitialized = function () { - page.evaluate(function () { - Math.random = function() { - return 42 / 100; - }; - }); -}; - -page.open('http://ariya.github.com/js/random/', function (status) { - var result; - if (status !== 'success') { - console.log('Network error.'); - } else { - console.log(page.evaluate(function () { - return document.getElementById('numbers').textContent; - })); - } - phantom.exit(); -}); diff --git a/third_party/phantomjs/examples/useragent.js b/third_party/phantomjs/examples/useragent.js deleted file mode 100644 index 5a48091a38c..00000000000 --- a/third_party/phantomjs/examples/useragent.js +++ /dev/null @@ -1,15 +0,0 @@ -"use strict"; -var page = require('webpage').create(); -console.log('The default user agent is ' + page.settings.userAgent); -page.settings.userAgent = 'SpecialAgent'; -page.open('http://www.httpuseragent.org', function (status) { - if (status !== 'success') { - console.log('Unable to access network'); - } else { - var ua = page.evaluate(function () { - return document.getElementById('myagent').innerText; - }); - console.log(ua); - } - phantom.exit(); -}); diff --git a/third_party/phantomjs/examples/version.js b/third_party/phantomjs/examples/version.js deleted file mode 100644 index dfda4f8edcb..00000000000 --- a/third_party/phantomjs/examples/version.js +++ /dev/null @@ -1,6 +0,0 @@ -"use strict"; -console.log('using PhantomJS version ' + - phantom.version.major + '.' + - phantom.version.minor + '.' + - phantom.version.patch); -phantom.exit(); diff --git a/third_party/phantomjs/examples/waitfor.js b/third_party/phantomjs/examples/waitfor.js deleted file mode 100644 index c470a92b653..00000000000 --- a/third_party/phantomjs/examples/waitfor.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Wait until the test condition is true or a timeout occurs. Useful for waiting - * on a server response or for a ui change (fadeIn, etc.) to occur. - * - * @param testFx javascript condition that evaluates to a boolean, - * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or - * as a callback function. - * @param onReady what to do when testFx condition is fulfilled, - * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or - * as a callback function. - * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used. - */ - -"use strict"; -function waitFor(testFx, onReady, timeOutMillis) { - var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s - start = new Date().getTime(), - condition = false, - interval = setInterval(function() { - if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) { - // If not time-out yet and condition not yet fulfilled - condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code - } else { - if(!condition) { - // If condition still not fulfilled (timeout but condition is 'false') - console.log("'waitFor()' timeout"); - phantom.exit(1); - } else { - // Condition fulfilled (timeout and/or condition is 'true') - console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms."); - typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled - clearInterval(interval); //< Stop this interval - } - } - }, 250); //< repeat check every 250ms -}; - - -var page = require('webpage').create(); - -// Open Twitter on 'sencha' profile and, onPageLoad, do... -page.open("http://twitter.com/#!/sencha", function (status) { - // Check for page load success - if (status !== "success") { - console.log("Unable to access network"); - } else { - // Wait for 'signin-dropdown' to be visible - waitFor(function() { - // Check in the page if a specific element is now visible - return page.evaluate(function() { - return $("#signin-dropdown").is(":visible"); - }); - }, function() { - console.log("The sign-in dialog should be visible now."); - phantom.exit(); - }); - } -}); diff --git a/third_party/phantomjs/examples/walk_through_frames.js b/third_party/phantomjs/examples/walk_through_frames.js deleted file mode 100644 index d0fabfcde90..00000000000 --- a/third_party/phantomjs/examples/walk_through_frames.js +++ /dev/null @@ -1,73 +0,0 @@ -"use strict"; -var p = require("webpage").create(); - -function pageTitle(page) { - return page.evaluate(function(){ - return window.document.title; - }); -} - -function setPageTitle(page, newTitle) { - page.evaluate(function(newTitle){ - window.document.title = newTitle; - }, newTitle); -} - -p.open("../test/webpage-spec-frames/index.html", function(status) { - console.log("pageTitle(): " + pageTitle(p)); - console.log("currentFrameName(): "+p.currentFrameName()); - console.log("childFramesCount(): "+p.childFramesCount()); - console.log("childFramesName(): "+p.childFramesName()); - console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited"); - console.log(""); - - console.log("p.switchToChildFrame(\"frame1\"): "+p.switchToChildFrame("frame1")); - console.log("pageTitle(): " + pageTitle(p)); - console.log("currentFrameName(): "+p.currentFrameName()); - console.log("childFramesCount(): "+p.childFramesCount()); - console.log("childFramesName(): "+p.childFramesName()); - console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited"); - console.log(""); - - console.log("p.switchToChildFrame(\"frame1-2\"): "+p.switchToChildFrame("frame1-2")); - console.log("pageTitle(): " + pageTitle(p)); - console.log("currentFrameName(): "+p.currentFrameName()); - console.log("childFramesCount(): "+p.childFramesCount()); - console.log("childFramesName(): "+p.childFramesName()); - console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited"); - console.log(""); - - console.log("p.switchToParentFrame(): "+p.switchToParentFrame()); - console.log("pageTitle(): " + pageTitle(p)); - console.log("currentFrameName(): "+p.currentFrameName()); - console.log("childFramesCount(): "+p.childFramesCount()); - console.log("childFramesName(): "+p.childFramesName()); - console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited"); - console.log(""); - - console.log("p.switchToChildFrame(0): "+p.switchToChildFrame(0)); - console.log("pageTitle(): " + pageTitle(p)); - console.log("currentFrameName(): "+p.currentFrameName()); - console.log("childFramesCount(): "+p.childFramesCount()); - console.log("childFramesName(): "+p.childFramesName()); - console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited"); - console.log(""); - - console.log("p.switchToMainFrame()"); p.switchToMainFrame(); - console.log("pageTitle(): " + pageTitle(p)); - console.log("currentFrameName(): "+p.currentFrameName()); - console.log("childFramesCount(): "+p.childFramesCount()); - console.log("childFramesName(): "+p.childFramesName()); - console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited"); - console.log(""); - - console.log("p.switchToChildFrame(\"frame2\"): "+p.switchToChildFrame("frame2")); - console.log("pageTitle(): " + pageTitle(p)); - console.log("currentFrameName(): "+p.currentFrameName()); - console.log("childFramesCount(): "+p.childFramesCount()); - console.log("childFramesName(): "+p.childFramesName()); - console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited"); - console.log(""); - - phantom.exit(); -}); diff --git a/third_party/phantomjs/test/basics/exit0.js b/third_party/phantomjs/test/basics/exit0.js deleted file mode 100644 index 13243eadbed..00000000000 --- a/third_party/phantomjs/test/basics/exit0.js +++ /dev/null @@ -1,8 +0,0 @@ -//! no-harness -//! expect-exit: 0 -//! expect-stdout: "we are alive" - -var sys = require('system'); -sys.stdout.write("we are alive\n"); -phantom.exit(); -sys.stdout.write("ERROR control passed beyond phantom.exit"); diff --git a/third_party/phantomjs/test/basics/exit23.js b/third_party/phantomjs/test/basics/exit23.js deleted file mode 100644 index eb3e05aa3c2..00000000000 --- a/third_party/phantomjs/test/basics/exit23.js +++ /dev/null @@ -1,8 +0,0 @@ -//! no-harness -//! expect-exit: 23 -//! expect-stdout: "we are alive" - -var sys = require('system'); -sys.stdout.write("we are alive\n"); -phantom.exit(23); -sys.stdout.write("ERROR control passed beyond phantom.exit"); diff --git a/third_party/phantomjs/test/basics/module.js b/third_party/phantomjs/test/basics/module.js deleted file mode 100644 index 58e8b33cd3b..00000000000 --- a/third_party/phantomjs/test/basics/module.js +++ /dev/null @@ -1,27 +0,0 @@ -// Test the properties of the 'module' object. -// Assumes the 'dummy_exposed' module is to be found in a directory -// named 'node_modules'. - -// Module load might fail, so do it in a setup function. -var module; -setup(function () { - module = require("dummy_exposed"); -}); - -test(function() { - assert_regexp_match(module.filename, /\/node_modules\/dummy_exposed\.js$/); -}, "module.filename is the absolute pathname of the module .js file"); - -test(function() { - assert_regexp_match(module.dirname, /\/node_modules$/); -}, "module.dirname is the absolute pathname of the directory containing "+ - "the module"); - -test(function() { - assert_equals(module.id, module.filename); -}, "module.id equals module.filename"); - -test(function() { - var dummy_file = module.require('./dummy_file'); - assert_equals(dummy_file, 'spec/node_modules/dummy_file'); -}, "module.require is callable and resolves relative to the module"); diff --git a/third_party/phantomjs/test/basics/phantom-object.js b/third_party/phantomjs/test/basics/phantom-object.js deleted file mode 100644 index c046351a58f..00000000000 --- a/third_party/phantomjs/test/basics/phantom-object.js +++ /dev/null @@ -1,39 +0,0 @@ -test(function () { - assert_type_of(phantom, 'object'); -}, "phantom object"); - -test(function () { - assert_own_property(phantom, 'libraryPath'); - assert_type_of(phantom.libraryPath, 'string'); - assert_greater_than(phantom.libraryPath.length, 0); -}, "phantom.libraryPath"); - -test(function () { - assert_own_property(phantom, 'outputEncoding'); - assert_type_of(phantom.outputEncoding, 'string'); - assert_equals(phantom.outputEncoding.toLowerCase(), 'utf-8'); // default -}, "phantom.outputEncoding"); - -test(function () { - assert_own_property(phantom, 'injectJs'); - assert_type_of(phantom.injectJs, 'function'); -}, "phantom.injectJs"); - -test(function () { - assert_own_property(phantom, 'exit'); - assert_type_of(phantom.exit, 'function'); -}, "phantom.exit"); - -test(function () { - assert_own_property(phantom, 'cookiesEnabled'); - assert_type_of(phantom.cookiesEnabled, 'boolean'); - assert_is_true(phantom.cookiesEnabled); -}, "phantom.cookiesEnabled"); - -test(function () { - assert_own_property(phantom, 'version'); - assert_type_of(phantom.version, 'object'); - assert_type_of(phantom.version.major, 'number'); - assert_type_of(phantom.version.minor, 'number'); - assert_type_of(phantom.version.patch, 'number'); -}, "phantom.version"); diff --git a/third_party/phantomjs/test/basics/require.js b/third_party/phantomjs/test/basics/require.js deleted file mode 100644 index 02a2d638048..00000000000 --- a/third_party/phantomjs/test/basics/require.js +++ /dev/null @@ -1,10 +0,0 @@ -/* The require tests need to run inside a module to work correctly; that - module is require/require_spec.js. (That directory also contains a - bunch of other files used by this test.) The module exports an array - of test functions in the form expected by generate_tests(). */ - -var rtests = require("require/require_spec.js").tests; - -for (var i = 0; i < rtests.length; i++) { - test.apply(null, rtests[i]); -} diff --git a/third_party/phantomjs/test/basics/require/a.js b/third_party/phantomjs/test/basics/require/a.js deleted file mode 100644 index 02cf3f554e7..00000000000 --- a/third_party/phantomjs/test/basics/require/a.js +++ /dev/null @@ -1,2 +0,0 @@ -var b = require('./b'); -exports.b = b; diff --git a/third_party/phantomjs/test/basics/require/b.js b/third_party/phantomjs/test/basics/require/b.js deleted file mode 100644 index 69660fca3a3..00000000000 --- a/third_party/phantomjs/test/basics/require/b.js +++ /dev/null @@ -1,2 +0,0 @@ -var a = require('./a'); -exports.a = a; diff --git a/third_party/phantomjs/test/basics/require/dir/dummy.js b/third_party/phantomjs/test/basics/require/dir/dummy.js deleted file mode 100644 index 0705990b1dd..00000000000 --- a/third_party/phantomjs/test/basics/require/dir/dummy.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'dir/dummy'; diff --git a/third_party/phantomjs/test/basics/require/dir/subdir/dummy.js b/third_party/phantomjs/test/basics/require/dir/subdir/dummy.js deleted file mode 100644 index a8cfec5a4fc..00000000000 --- a/third_party/phantomjs/test/basics/require/dir/subdir/dummy.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'subdir/dummy'; diff --git a/third_party/phantomjs/test/basics/require/dir/subdir/loader.js b/third_party/phantomjs/test/basics/require/dir/subdir/loader.js deleted file mode 100644 index 5033ccb6699..00000000000 --- a/third_party/phantomjs/test/basics/require/dir/subdir/loader.js +++ /dev/null @@ -1 +0,0 @@ -exports.dummyFile2 = require('dummy_file2'); diff --git a/third_party/phantomjs/test/basics/require/dir/subdir2/loader.js b/third_party/phantomjs/test/basics/require/dir/subdir2/loader.js deleted file mode 100644 index 620991106a4..00000000000 --- a/third_party/phantomjs/test/basics/require/dir/subdir2/loader.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'require/subdir2/loader' diff --git a/third_party/phantomjs/test/basics/require/dummy.js b/third_party/phantomjs/test/basics/require/dummy.js deleted file mode 100644 index 96425ed22dc..00000000000 --- a/third_party/phantomjs/test/basics/require/dummy.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'require/dummy'; diff --git a/third_party/phantomjs/test/basics/require/empty.js b/third_party/phantomjs/test/basics/require/empty.js deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/third_party/phantomjs/test/basics/require/json_dummy.json b/third_party/phantomjs/test/basics/require/json_dummy.json deleted file mode 100644 index 78ad073b667..00000000000 --- a/third_party/phantomjs/test/basics/require/json_dummy.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "hello" -} diff --git a/third_party/phantomjs/test/basics/require/node_modules/dummy_file.js b/third_party/phantomjs/test/basics/require/node_modules/dummy_file.js deleted file mode 100644 index a1427b93b70..00000000000 --- a/third_party/phantomjs/test/basics/require/node_modules/dummy_file.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'require/node_modules/dummy_file'; diff --git a/third_party/phantomjs/test/basics/require/node_modules/dummy_module/libdir/dummy_module.js b/third_party/phantomjs/test/basics/require/node_modules/dummy_module/libdir/dummy_module.js deleted file mode 100644 index 55016f51dd9..00000000000 --- a/third_party/phantomjs/test/basics/require/node_modules/dummy_module/libdir/dummy_module.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'require/node_modules/dummy_module'; diff --git a/third_party/phantomjs/test/basics/require/node_modules/dummy_module/package.json b/third_party/phantomjs/test/basics/require/node_modules/dummy_module/package.json deleted file mode 100644 index 8345e9bbddb..00000000000 --- a/third_party/phantomjs/test/basics/require/node_modules/dummy_module/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "dummy", - "main": "./libdir/dummy_module.js" -} diff --git a/third_party/phantomjs/test/basics/require/node_modules/dummy_module2/index.js b/third_party/phantomjs/test/basics/require/node_modules/dummy_module2/index.js deleted file mode 100644 index f360c638607..00000000000 --- a/third_party/phantomjs/test/basics/require/node_modules/dummy_module2/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'require/node_modules/dummy_module2'; diff --git a/third_party/phantomjs/test/basics/require/not_found.js b/third_party/phantomjs/test/basics/require/not_found.js deleted file mode 100644 index fbc35327f1c..00000000000 --- a/third_party/phantomjs/test/basics/require/not_found.js +++ /dev/null @@ -1,3 +0,0 @@ -exports.requireNonExistent = function() { - require('./non_existent'); -}; diff --git a/third_party/phantomjs/test/basics/require/require_spec.js b/third_party/phantomjs/test/basics/require/require_spec.js deleted file mode 100644 index 655654f8607..00000000000 --- a/third_party/phantomjs/test/basics/require/require_spec.js +++ /dev/null @@ -1,131 +0,0 @@ -var fs = require('fs'); -var tests = []; -exports.tests = tests; - -tests.push([function () { - assert_no_property(window, 'CoffeeScript'); - assert_own_property(window, 'require'); - - assert_own_property(require('webpage'), 'create'); - assert_own_property(require('webserver'), 'create'); - assert_own_property(require('cookiejar'), 'create'); - - assert_own_property(require('fs'), 'separator'); - assert_equals(require('system').platform, 'phantomjs'); - -}, "native modules"]); - -tests.push([function () { - assert_equals(require('./json_dummy').message, 'hello'); - assert_equals(require('./dummy.js'), 'require/dummy'); -}, "JS and JSON modules"]); - -tests.push([function () { - require('./empty').hello = 'hola'; - assert_equals(require('./empty').hello, 'hola'); - - // assert_own_property rejects Functions - assert_equals(require.hasOwnProperty('cache'), true); - - var exposed = require('dummy_exposed'); - assert_equals(require.cache[exposed.filename], exposed); - -}, "module caching"]); - -tests.push([function () { - var a = require('./a'); - var b = require('./b'); - assert_equals(a.b, b); - assert_equals(b.a, a); -}, "circular dependencies"]); - -tests.push([function () { - assert_throws("Cannot find module 'dummy_missing'", - function () { require('dummy_missing'); }); - - try { - require('./not_found').requireNonExistent(); - } catch (e) { - assert_regexp_match(e.stack, /at require /); - } -}, "error handling 1"]); - -tests.push([function error_handling_2 () { - try { - require('./thrower').fn(); - } catch (e) { - assert_regexp_match(e.toString() + "\n" + e.stack, - /^Error: fn\nError: fn\n at Object.thrower/); - } -}, "error handling 2"]); - -tests.push([function () { - assert_equals(require('./stubber').stubbed, 'stubbed module'); - assert_equals(require('./stubber').child.stubbed, 'stubbed module'); - assert_throws("Cannot find module 'stubbed'", - function () { require('stubbed'); }); - - var count = 0; - require.stub('lazily_stubbed', function() { - ++count; - return 'lazily stubbed module'; - }); - - assert_equals(require('lazily_stubbed'), 'lazily stubbed module'); - require('lazily_stubbed'); - assert_equals(count, 1); - -}, "stub modules"]); - -tests.push([function () { - assert_equals(require('./dummy'), 'require/dummy'); - assert_equals(require('../fixtures/dummy'), 'spec/dummy'); - assert_equals(require('./dir/dummy'), 'dir/dummy'); - assert_equals(require('./dir/subdir/dummy'), 'subdir/dummy'); - assert_equals(require('./dir/../dummy'), 'require/dummy'); - assert_equals(require('./dir/./dummy'), 'dir/dummy'); - assert_equals(require( - fs.absolute(module.dirname + '/dummy.js')), 'require/dummy'); - -}, "relative and absolute paths"]); - -tests.push([function () { - assert_equals(require('dummy_file'), 'require/node_modules/dummy_file'); - assert_equals(require('dummy_file2'), 'spec/node_modules/dummy_file2'); - assert_equals(require('./dir/subdir/loader').dummyFile2, - 'spec/node_modules/dummy_file2'); - assert_equals(require('dummy_module'), - 'require/node_modules/dummy_module'); - assert_equals(require('dummy_module2'), - 'require/node_modules/dummy_module2'); -}, "loading from node_modules"]); - -function require_paths_tests_1 () { - assert_equals(require('loader').dummyFile2, - 'spec/node_modules/dummy_file2'); - assert_equals(require('../subdir2/loader'), - 'require/subdir2/loader'); - assert_equals(require('../fixtures/dummy'), 'spec/dummy'); -} -function require_paths_tests_2 () { - assert_throws("Cannot find module 'loader'", - function () { require('loader'); }); -} - -tests.push([function () { - require.paths.push('dir/subdir'); - this.add_cleanup(function () { require.paths.pop(); }); - require_paths_tests_1(); -}, "relative paths in require.paths"]); - -tests.push([ - require_paths_tests_2, "relative paths in require paths (after removal)"]); - -tests.push([function () { - require.paths.push(fs.absolute(module.dirname + '/dir/subdir')); - this.add_cleanup(function () { require.paths.pop(); }); - require_paths_tests_1(); -}, "absolute paths in require.paths"]); - -tests.push([ - require_paths_tests_2, "relative paths in require paths (after removal)"]); diff --git a/third_party/phantomjs/test/basics/require/stubber.js b/third_party/phantomjs/test/basics/require/stubber.js deleted file mode 100644 index 727d10484ca..00000000000 --- a/third_party/phantomjs/test/basics/require/stubber.js +++ /dev/null @@ -1,5 +0,0 @@ -require.stub('stubbed', 'stubbed module'); -exports.stubbed = require('stubbed'); -try { - exports.child = require('./stubber_child'); -} catch (e) {} diff --git a/third_party/phantomjs/test/basics/require/stubber_child.js b/third_party/phantomjs/test/basics/require/stubber_child.js deleted file mode 100644 index 527c14fd812..00000000000 --- a/third_party/phantomjs/test/basics/require/stubber_child.js +++ /dev/null @@ -1 +0,0 @@ -exports.stubbed = require('stubbed'); diff --git a/third_party/phantomjs/test/basics/require/thrower.js b/third_party/phantomjs/test/basics/require/thrower.js deleted file mode 100644 index 6a98c3fd0a1..00000000000 --- a/third_party/phantomjs/test/basics/require/thrower.js +++ /dev/null @@ -1,3 +0,0 @@ -exports.fn = function thrower() { - throw new Error('fn'); -}; diff --git a/third_party/phantomjs/test/basics/stacktrace.js b/third_party/phantomjs/test/basics/stacktrace.js deleted file mode 100644 index d195144e0e7..00000000000 --- a/third_party/phantomjs/test/basics/stacktrace.js +++ /dev/null @@ -1,12 +0,0 @@ -// A SyntaxError leaks to phantom.onError, despite the try-catch. -setup({ allow_uncaught_exception: true }); - -test(function () { - var helperFile = "../fixtures/parse-error-helper.js"; - try { - phantom.injectJs(helperFile); - assert_is_true(false); - } catch (e) { - assert_is_true(e.stack.indexOf('fixtures/parse-error-helper.js:2') !== -1); - } -}, "stack trace from syntax error in injected file"); diff --git a/third_party/phantomjs/test/basics/test-server.js b/third_party/phantomjs/test/basics/test-server.js deleted file mode 100644 index 0b8d2149bec..00000000000 --- a/third_party/phantomjs/test/basics/test-server.js +++ /dev/null @@ -1,33 +0,0 @@ -//! unsupported -/* Test the test server itself. */ - -var webpage = require('webpage'); - -function test_one_page(url) { - var page = webpage.create(); - page.onResourceReceived = this.step_func(function (response) { - assert_equals(response.status, 200); - }); - page.onResourceError = this.unreached_func(); - page.onResourceTimeout = this.unreached_func(); - page.onLoadFinished = this.step_func_done(function (status) { - assert_equals(status, 'success'); - }); - page.open(url); -} - -function do_test(path) { - var http_url = TEST_HTTP_BASE + path; - var https_url = TEST_HTTPS_BASE + path; - var http_test = async_test(http_url); - var https_test = async_test(https_url); - http_test.step(test_one_page, null, http_url); - https_test.step(test_one_page, null, https_url); -} - -[ - 'hello.html', - 'status?200', - 'echo' -] - .forEach(do_test); diff --git a/third_party/phantomjs/test/basics/timeout.js b/third_party/phantomjs/test/basics/timeout.js deleted file mode 100644 index 7a753543215..00000000000 --- a/third_party/phantomjs/test/basics/timeout.js +++ /dev/null @@ -1,7 +0,0 @@ -//! unsupported -//! no-harness -//! expect-exit: -15 -//! expect-stderr: TIMEOUT: Process terminated after 0.25 seconds. -//! timeout: 0.25 - -// no code, so phantom will just sleep forever diff --git a/third_party/phantomjs/test/basics/url-utils.js b/third_party/phantomjs/test/basics/url-utils.js deleted file mode 100644 index 80a5265c73b..00000000000 --- a/third_party/phantomjs/test/basics/url-utils.js +++ /dev/null @@ -1,16 +0,0 @@ -// These are cursory tests; we assume the underlying Qt -// features are properly tested elsewhere. - -test(function () { - assert_equals( - phantom.resolveRelativeUrl( - "../scripts/foo.js", - "http://example.com/topic/page.html"), - "http://example.com/scripts/foo.js"); - - assert_equals( - phantom.fullyDecodeUrl( - "https://ja.wikipedia.org/wiki/%E8%87%A8%E6%B5%B7%E5%AD%A6%E6%A0%A1"), - "https://ja.wikipedia.org/wiki/臨海学校"); - -}, "resolveRelativeUrl and fullyDecodeUrl"); diff --git a/third_party/phantomjs/test/basics/version.js b/third_party/phantomjs/test/basics/version.js deleted file mode 100644 index 39e28dbe349..00000000000 --- a/third_party/phantomjs/test/basics/version.js +++ /dev/null @@ -1,7 +0,0 @@ -// This is separate from basics/phantom-object.js because it has to be -// updated with every release. -test(function () { - assert_equals(phantom.version.major, 0); - assert_equals(phantom.version.minor, 0); - assert_equals(phantom.version.patch, 1); -}, "PhantomJS version number is accurate"); diff --git a/third_party/phantomjs/test/certs/https-snakeoil.crt b/third_party/phantomjs/test/certs/https-snakeoil.crt deleted file mode 100644 index 74e5158f3fc..00000000000 --- a/third_party/phantomjs/test/certs/https-snakeoil.crt +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIC+zCCAeOgAwIBAgIJAJ7HwZBrgnLwMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV -BAMMCWxvY2FsaG9zdDAeFw0xNTA4MTEyMjU4MTZaFw0yNTA4MTAyMjU4MTZaMBQx -EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBANFha8c5JKjYrHc7BTqmuFSAxYsSKbUUa0k+0PFpjhj7Io/NOeHhxfdLJX/B -LVQXEDhvOlSTDBgC3RQkxCZJmMzKZjMDlj0cxY0esZtcqt0sRpwRvT+EBE9SlFu4 -TWM2BQ6k5E4OIX/9aUk9HQ99pSjqmhu/7n76n/5DfqxGwkfVZengI1KwfezaB5+Q -wAvoS7tadROqTyynV1kd+OF9BJZwO1eR9lAiGc139J/BHegVcqdrI043oR+1vyTw -BFpodw4HYdJHNgo7DKAtmXoDAws5myqx2GcnVng1wyzu6LdM65nMV4/p5Y/Y6Ziy -RqeV1gVbtpxTcrLmWFnI8BRwFBUCAwEAAaNQME4wHQYDVR0OBBYEFPP1YOkZpJmE -x/W48Kwv2N1QC1oDMB8GA1UdIwQYMBaAFPP1YOkZpJmEx/W48Kwv2N1QC1oDMAwG -A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAA1NxsrmKxGecAS6TEHNBqFZ -9NhV23kXY5sdv8zl7HUmzR+vIBumd9lkSZdOwAy5/hmj6ACReSJ9f2xpyi0fOtx5 -WZ8Vcrg9Qjuy17qmGi66yL860yr0h6hltzCWCi7e26Eybawm3/9PmbNV3Hcwgxug -D+gv4LZLlyj4JI4lg/8RVXaNXqGBZ39YhRH0LFVjbYiFWUGqzfAT9YBoC67Ov8Yv -Bl1PoV3sJcagx67X6y8ru+gecc/OOXKJHxSidhjRqhKB6WOWIPfugsMOl1g2FMPv -tuPFsIQNSaln7V+ECeDOipJOSp9KAyM5fNcVjldd/e4V+qwcyoOijFywNfSK10M= ------END CERTIFICATE----- diff --git a/third_party/phantomjs/test/certs/https-snakeoil.key b/third_party/phantomjs/test/certs/https-snakeoil.key deleted file mode 100644 index ab989325df6..00000000000 --- a/third_party/phantomjs/test/certs/https-snakeoil.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDRYWvHOSSo2Kx3 -OwU6prhUgMWLEim1FGtJPtDxaY4Y+yKPzTnh4cX3SyV/wS1UFxA4bzpUkwwYAt0U -JMQmSZjMymYzA5Y9HMWNHrGbXKrdLEacEb0/hARPUpRbuE1jNgUOpORODiF//WlJ -PR0PfaUo6pobv+5++p/+Q36sRsJH1WXp4CNSsH3s2gefkMAL6Eu7WnUTqk8sp1dZ -HfjhfQSWcDtXkfZQIhnNd/SfwR3oFXKnayNON6Eftb8k8ARaaHcOB2HSRzYKOwyg -LZl6AwMLOZsqsdhnJ1Z4NcMs7ui3TOuZzFeP6eWP2OmYskanldYFW7acU3Ky5lhZ -yPAUcBQVAgMBAAECggEAOwI/w8fhAwz9niSuFpeB/57DDayywGveyKfBbygWegfc -97YZCAX/KvCswtKImdheI+mFAOzoTaQQ9mpeNYQsYhrwrpPmNZb0Pg9WcritFuQx -ii6drVbheBGH6kmI1dsVlcj25uCopE+g6pkkpYb9kwh7IjL3XiX4DUqsWpUej+ub -2iL/luW7nYHHIRqzOFgP3v/f29sFHNvYcgihphBMHtgb4VpeYQ/f7AC7k1bFYfA/ -TmvfUcXdiPwJf0XICZOaLrT/6pigk0bRiLNn8npISu7Wlf4jF60bNAe4+krBVU4O -p8UjW99LiGKLDh8GpoudnzlnnngZ3SA5+bO7kwTjCQKBgQDvJwUShOWm2+5wJsr4 -hWieTVDaZEDb+1WTe7DwtqRWNBWXchh8is9buWeXIe6+1WldBYYiQjgdggQCw8xG -IFFg1j1E6kPqk/kzrHYSsJ+/u8uaxypvvrVBhUqt5FduOxFojW2REX9W5n8HTdT4 -32BGR4mGpuXzR+BsVK00QRgM+wKBgQDgIXtu6rbfx+mdXTFi6apWJoyu5bRWcrL2 -mGoR+IjCk6NefcvBE33q54H/dk3+0Sxp6+uFo7lyKv4EL3lozQO2oga6sp2LOIEK -DUo+KQVOmntCNrjuN/PbjSu2s1j5QDnLNR9VvXGiYBWdpZ7k3YzoKJ1I4ZyB3kGs -H/lCXv52LwKBgER1HvaWJEcHXdGsyR0q0y+9Yg+h8w8FexGkrpm5LoGely+q8Wd1 -NLZE9GpGxFjMLkT6d9MGsZmAxjUkZy0Lwz+9E/zOMnLLuOIZ1BK1jIUN9NJxgKxM -IwaGaUItwvlC31DWay7Dm3f8sxAcL4KuLpjvkWaCEAD76joYYxw6JfBRAoGADMe7 -+xolLWN/3bpHq6U5UkpGcV6lxtwpekg8nCO44Kd8hFHWAX90CaYD0qZTUjlpN+z8 -9BTe6TSsYV63pJM0KADbM2Al/Z9ONF2Hoz3BkLbcWm02ZFcKb7WADZ3yb9wKr5yq -2b/AsAqckO21vsUnWMGgHlzHCNy8j+0O0IsMJX8CgYAORhyGaU7x5t4kEvqBNIan -mOzuB0b5nYV9mHxmyFhOsa8LeM25SA4n1rFpTb8h6vmZF1y9+4Zy4uNfCR2wXg0v -I51qtZ8npbIksYvNqvHaTPg8ZBcFK5mHr3TDxXJCcc0ylzM98ze08D+qKr0joX4w -KlqN6KjGmYfb+RHehLk9sw== ------END PRIVATE KEY----- diff --git a/third_party/phantomjs/test/fixtures/dummy.js b/third_party/phantomjs/test/fixtures/dummy.js deleted file mode 100644 index 4def305e706..00000000000 --- a/third_party/phantomjs/test/fixtures/dummy.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'spec/dummy'; diff --git a/third_party/phantomjs/test/fixtures/error-helper.js b/third_party/phantomjs/test/fixtures/error-helper.js deleted file mode 100644 index 3619b16da31..00000000000 --- a/third_party/phantomjs/test/fixtures/error-helper.js +++ /dev/null @@ -1,9 +0,0 @@ -ErrorHelper = { - foo: function() { - this.bar() - }, - - bar: function bar() { - referenceError - } -}; diff --git a/third_party/phantomjs/test/fixtures/parse-error-helper.js b/third_party/phantomjs/test/fixtures/parse-error-helper.js deleted file mode 100644 index 5538cb451ca..00000000000 --- a/third_party/phantomjs/test/fixtures/parse-error-helper.js +++ /dev/null @@ -1,2 +0,0 @@ -var ok; -bar("run away" \ No newline at end of file diff --git a/third_party/phantomjs/test/manual/standards/ecma-test262.js b/third_party/phantomjs/test/manual/standards/ecma-test262.js deleted file mode 100644 index edb19941932..00000000000 --- a/third_party/phantomjs/test/manual/standards/ecma-test262.js +++ /dev/null @@ -1,36 +0,0 @@ -// Launch the official test suite for ECMA-262 - -var webpage = require('webpage'); - -page = webpage.create(); -page.onError = function() {}; - -page.open('http://test262.ecmascript.org/', function() { - page.evaluate(function() { $('a#run').click(); }); - page.evaluate(function() { $('img#btnRunAll').click(); }); - - function monitor() { - - var data = page.evaluate(function() { - return { - ran: $('#totalCounter').text(), - total: $('#testsToRun').text(), - pass: $('#Pass').text(), - fail: $('#Fail').text(), - progress: $('div#progressbar').text() - }; - }); - - console.log('Tests: ', data.ran, 'of', data.total, - ' Pass:', data.pass, ' Fail:', data.fail); - - if (data.progress.indexOf('complete') > 0) { - page.render('report.png'); - phantom.exit(); - } else { - setTimeout(monitor, 1000); - } - } - - setTimeout(monitor, 0); -}); diff --git a/third_party/phantomjs/test/module/cookiejar/cookiejar.js b/third_party/phantomjs/test/module/cookiejar/cookiejar.js deleted file mode 100644 index 4c9e4cc4c76..00000000000 --- a/third_party/phantomjs/test/module/cookiejar/cookiejar.js +++ /dev/null @@ -1,93 +0,0 @@ -//! unsupported -var cookie0 = { - 'name': 'Valid-Cookie-Name', - 'value': 'Valid-Cookie-Value', - 'domain': 'localhost', - 'path': '/foo', - 'httponly': true, - 'secure': false -}; -var cookie1 = { - 'name': 'Valid-Cookie-Name-1', - 'value': 'Valid-Cookie-Value', - 'domain': 'localhost', - 'path': '/foo', - 'httponly': true, - 'secure': false -}; -var cookie2 = { - 'name': 'Valid-Cookie-Name-2', - 'value': 'Valid-Cookie-Value', - 'domain': 'localhost', - 'path': '/foo', - 'httponly': true, - 'secure': false -}; -var cookies = [{ - 'name': 'Valid-Cookie-Name', - 'value': 'Valid-Cookie-Value', - 'domain': 'localhost', - 'path': '/foo', - 'httponly': true, - 'secure': false -},{ - 'name': 'Valid-Cookie-Name-Sec', - 'value': 'Valid-Cookie-Value-Sec', - 'domain': 'localhost', - 'path': '/foo', - 'httponly': true, - 'secure': false, - 'expires': new Date().getTime() + 3600 //< expires in 1h -}]; - -var cookiejar, jar1, jar2; -setup(function () { - cookiejar = require('cookiejar'); - jar1 = cookiejar.create(); - jar2 = cookiejar.create(); -}); - -test(function () { - assert_type_of(jar1, 'object'); - assert_not_equals(jar1, null); - assert_type_of(jar1.cookies, 'object'); - - assert_type_of(jar1.addCookie, 'function'); - assert_type_of(jar1.deleteCookie, 'function'); - assert_type_of(jar1.clearCookies, 'function'); -}, "cookie jar properties"); - -test(function () { - assert_equals(jar1.cookies.length, 0); - - jar1.addCookie(cookie0); - assert_equals(jar1.cookies.length, 1); - - jar1.deleteCookie('Valid-Cookie-Name'); - assert_equals(jar1.cookies.length, 0); -}, "adding and removing cookies"); - -test(function () { - assert_equals(jar1.cookies.length, 0); - - jar1.cookies = cookies; - assert_equals(jar1.cookies.length, 2); - - jar1.clearCookies(); - assert_equals(jar1.cookies.length, 0); -}, "setting and clearing a cookie jar"); - -test(function () { - jar1.addCookie(cookie1); - assert_equals(jar1.cookies.length, 1); - assert_equals(jar2.cookies.length, 0); - - jar2.addCookie(cookie2); - jar1.deleteCookie('Valid-Cookie-Name-1'); - assert_equals(jar1.cookies.length, 0); - assert_equals(jar2.cookies.length, 1); - - jar1.close(); - jar2.close(); - -}, "cookie jar isolation"); diff --git a/third_party/phantomjs/test/module/cookiejar/to-map.js b/third_party/phantomjs/test/module/cookiejar/to-map.js deleted file mode 100644 index 7528e3fc578..00000000000 --- a/third_party/phantomjs/test/module/cookiejar/to-map.js +++ /dev/null @@ -1,52 +0,0 @@ -//! unsupported -var cookies = { - 'beforeExpires': { - 'name': 'beforeExpires', - 'value': 'expireValue', - 'domain': '.abc.com', - 'path': '/', - 'httponly': false, - 'secure': false, - 'expires': 'Tue, 10 Jun 2025 12:28:29 GMT' - }, - 'noExpiresDate': { - 'name': 'noExpiresDate', - 'value': 'value', - 'domain': '.abc.com', - 'path': '/', - 'httponly': false, - 'secure': false, - 'expires': null - }, - 'afterExpires': { - 'name': 'afterExpires', - 'value': 'value', - 'domain': '.abc.com', - 'path': '/', - 'httponly': false, - 'secure': false, - 'expires': 'Mon, 10 Jun 2024 12:28:29 GMT' - } -}; - -test(function () { - var i, c, d, prop; - for (i in cookies) { - if (!cookies.hasOwnProperty(i)) continue; - phantom.addCookie(cookies[i]); - } - for (i in phantom.cookies) { - d = phantom.cookies[i]; - c = cookies[d.name]; - for (prop in c) { - if (!c.hasOwnProperty(prop)) continue; - if (c[prop] === null) { - assert_no_property(d, prop); - } else { - assert_own_property(d, prop); - assert_equals(c[prop], d[prop]); - } - } - } - -}, "optional cookie properties should not leak"); diff --git a/third_party/phantomjs/test/module/fs/basics.js b/third_party/phantomjs/test/module/fs/basics.js deleted file mode 100644 index c522ab7f299..00000000000 --- a/third_party/phantomjs/test/module/fs/basics.js +++ /dev/null @@ -1,220 +0,0 @@ -// Basic Files API (read, write, remove, ...) - -var FILENAME = "temp-01.test", - FILENAME_COPY = FILENAME + ".copy", - FILENAME_MOVED = FILENAME + ".moved", - FILENAME_EMPTY = FILENAME + ".empty", - FILENAME_ENC = FILENAME + ".enc", - FILENAME_BIN = FILENAME + ".bin", - ABSENT = "absent-01.test"; - -var fs; - -setup(function () { - fs = require('fs'); - var f = fs.open(FILENAME, "w"); - - f.write("hello"); - f.writeLine(""); - f.writeLine("world"); - f.close(); -}); - -test(function () { - assert_is_true(fs.exists(FILENAME)); - // we might've gotten DOS line endings - assert_greater_than_equal(fs.size(FILENAME), "hello\nworld\n".length); - -}, "create a file with contents"); - -test(function () { - assert_is_false(fs.exists(FILENAME_EMPTY)); - fs.touch(FILENAME_EMPTY); - assert_is_true(fs.exists(FILENAME_EMPTY)); - assert_equals(fs.size(FILENAME_EMPTY), 0); - -}, "create (touch) an empty file"); - -test(function () { - var content = ""; - var f = fs.open(FILENAME, "r"); - this.add_cleanup(function () { f.close(); }); - - content = f.read(); - assert_equals(content, "hello\nworld\n"); - -}, "read content from a file"); - -test(function () { - var content = ""; - var f = fs.open(FILENAME, "r"); - this.add_cleanup(function () { f.close(); }); - - f.seek(3); - content = f.read(5); - assert_equals(content, "lo\nwo"); - -}, "read specific number of bytes from a specific position in a file"); - -test(function () { - var content = ""; - var f = fs.open(FILENAME, "rw+"); - this.add_cleanup(function () { f.close(); }); - - f.writeLine("asdf"); - content = f.read(); - assert_equals(content, "hello\nworld\nasdf\n"); - -}, "append content to a file"); - -test(function () { - var f = fs.open(FILENAME, "r"); - this.add_cleanup(function () { f.close(); }); - assert_equals(f.getEncoding(), "UTF-8"); - -}, "get the file encoding (default: UTF-8)"); - -test(function () { - var f = fs.open(FILENAME, { charset: "UTF-8", mode: "r" }); - this.add_cleanup(function () { f.close(); }); - assert_equals(f.getEncoding(), "UTF-8"); - - var g = fs.open(FILENAME, { charset: "SJIS", mode: "r" }); - this.add_cleanup(function () { g.close(); }); - assert_equals(g.getEncoding(), "Shift_JIS"); - -}, "set the encoding on open", {/* unsupported */expected_fail: true}); - -test(function () { - var f = fs.open(FILENAME, { charset: "UTF-8", mode: "r" }); - this.add_cleanup(function () { f.close(); }); - assert_equals(f.getEncoding(), "UTF-8"); - f.setEncoding("utf8"); - assert_equals(f.getEncoding(), "UTF-8"); - - var g = fs.open(FILENAME, { charset: "SJIS", mode: "r" }); - this.add_cleanup(function () { g.close(); }); - assert_equals(g.getEncoding(), "Shift_JIS"); - g.setEncoding("eucjp"); - assert_equals(g.getEncoding(), "EUC-JP"); - -}, "change the encoding using setEncoding", {/* unsupported */expected_fail: true}); - -test(function () { - assert_is_false(fs.exists(FILENAME_COPY)); - fs.copy(FILENAME, FILENAME_COPY); - assert_is_true(fs.exists(FILENAME_COPY)); - assert_equals(fs.read(FILENAME), fs.read(FILENAME_COPY)); - -}, "copy a file"); - -test(function () { - assert_is_true(fs.exists(FILENAME)); - var contentBeforeMove = fs.read(FILENAME); - fs.move(FILENAME, FILENAME_MOVED); - assert_is_false(fs.exists(FILENAME)); - assert_is_true(fs.exists(FILENAME_MOVED)); - assert_equals(fs.read(FILENAME_MOVED), contentBeforeMove); - -}, "move a file"); - -test(function () { - assert_is_true(fs.exists(FILENAME_MOVED)); - assert_is_true(fs.exists(FILENAME_COPY)); - assert_is_true(fs.exists(FILENAME_EMPTY)); - - fs.remove(FILENAME_MOVED); - fs.remove(FILENAME_COPY); - fs.remove(FILENAME_EMPTY); - - assert_is_false(fs.exists(FILENAME_MOVED)); - assert_is_false(fs.exists(FILENAME_COPY)); - assert_is_false(fs.exists(FILENAME_EMPTY)); - -}, "remove a file"); - -test(function () { - assert_throws("Unable to open file '"+ ABSENT +"'", - function () { fs.open(ABSENT, "r"); }); - - assert_throws("Unable to copy file '" + ABSENT + - "' at '" + FILENAME_COPY + "'", - function () { fs.copy(ABSENT, FILENAME_COPY); }); - -}, "operations on nonexistent files throw an exception", {/* unsupported */expected_fail: true}); - -test(function () { - var data = "ÄABCÖ"; - var data_b = String.fromCharCode( - 0xC3, 0x84, 0x41, 0x42, 0x43, 0xC3, 0x96); - - var f = fs.open(FILENAME_ENC, "w"); - this.add_cleanup(function () { - f.close(); - fs.remove(FILENAME_ENC); - }); - - f.write(data); - f.close(); - - f = fs.open(FILENAME_ENC, "r"); - assert_equals(f.read(), data); - - var g = fs.open(FILENAME_ENC, "rb"); - this.add_cleanup(function () { g.close(); }); - assert_equals(g.read(), data_b); - -}, "read/write UTF-8 text by default"); - -test(function () { - var data = "ピタゴラスイッチ"; - var data_b = String.fromCharCode( - 0x83, 0x73, 0x83, 0x5e, 0x83, 0x53, 0x83, 0x89, - 0x83, 0x58, 0x83, 0x43, 0x83, 0x62, 0x83, 0x60); - - var f = fs.open(FILENAME_ENC, { mode: "w", charset: "Shift_JIS" }); - this.add_cleanup(function () { - f.close(); - fs.remove(FILENAME_ENC); - }); - - f.write(data); - f.close(); - - f = fs.open(FILENAME_ENC, { mode: "r", charset: "Shift_JIS" }); - assert_equals(f.read(), data); - - var g = fs.open(FILENAME_ENC, "rb"); - this.add_cleanup(function () { g.close(); }); - assert_equals(g.read(), data_b); - -}, "read/write Shift-JIS text with options", {/* unsupported */expected_fail: true}); - -test(function () { - var data = String.fromCharCode(0, 1, 2, 3, 4, 5); - - var f = fs.open(FILENAME_BIN, "wb"); - this.add_cleanup(function () { - f.close(); - fs.remove(FILENAME_BIN); - }); - - f.write(data); - f.close(); - - f = fs.open(FILENAME_BIN, "rb"); - assert_equals(f.read(), data); - -}, "read/write binary data"); - -test(function () { - var data = String.fromCharCode(0, 1, 2, 3, 4, 5); - - fs.write(FILENAME_BIN, data, "b"); - this.add_cleanup(function () { - fs.remove(FILENAME_BIN); - }); - - assert_equals(fs.read(FILENAME_BIN, "b"), data); - -}, "read/write binary data (shortcuts)"); diff --git a/third_party/phantomjs/test/module/fs/fileattrs.js b/third_party/phantomjs/test/module/fs/fileattrs.js deleted file mode 100644 index f973abbaeb2..00000000000 --- a/third_party/phantomjs/test/module/fs/fileattrs.js +++ /dev/null @@ -1,91 +0,0 @@ - -var fs = require('fs'); - -var ABSENT_DIR = "absentdir02", - ABSENT_FILE = "absentfile02", - TEST_DIR = "testdir02", - TEST_FILE = "temp-02.test", - TEST_FILE_PATH = fs.join(TEST_DIR, TEST_FILE), - TEST_CONTENT = "test content", - CONTENT_MULTIPLIER = 1024; - -test(function () { - assert_throws("Unable to read file '"+ ABSENT_FILE +"' size", - function () { fs.size(ABSENT_FILE); }); - - assert_equals(fs.lastModified(ABSENT_FILE), null); - -}, "size/date queries on nonexistent files", {/* unsupported */expected_fail: true}); - -test(function () { - // Round down to the nearest multiple of two seconds, because - // file timestamps might only have that much precision. - var before_creation = Math.floor(Date.now() / 2000) * 2000; - - var f = fs.open(TEST_FILE, "w"); - this.add_cleanup(function () { - if (f !== null) f.close(); - fs.remove(TEST_FILE); - }); - - for (var i = 0; i < CONTENT_MULTIPLIER; i++) { - f.write(TEST_CONTENT); - } - f.close(); f = null; - - // Similarly, but round _up_. - var after_creation = Math.ceil(Date.now() / 2000) * 2000; - - assert_equals(fs.size(TEST_FILE), - TEST_CONTENT.length * CONTENT_MULTIPLIER); - - var flm = fs.lastModified(TEST_FILE).getTime(); - - assert_greater_than_equal(flm, before_creation); - assert_less_than_equal(flm, after_creation); - -}, "size/date queries on existing files"); - -test(function () { - fs.makeDirectory(TEST_DIR); - this.add_cleanup(function () { fs.removeTree(TEST_DIR); }); - fs.write(TEST_FILE_PATH, TEST_CONTENT, "w"); - - assert_is_true(fs.exists(TEST_FILE_PATH)); - assert_is_true(fs.exists(TEST_DIR)); - assert_is_false(fs.exists(ABSENT_FILE)); - assert_is_false(fs.exists(ABSENT_DIR)); - - assert_is_true(fs.isDirectory(TEST_DIR)); - assert_is_false(fs.isDirectory(ABSENT_DIR)); - - - assert_is_true(fs.isFile(TEST_FILE_PATH)); - assert_is_false(fs.isFile(ABSENT_FILE)); - - var absPath = fs.absolute(TEST_FILE_PATH); - assert_is_false(fs.isAbsolute(TEST_FILE_PATH)); - assert_is_true(fs.isAbsolute(absPath)); - - assert_is_true(fs.isReadable(TEST_FILE_PATH)); - assert_is_true(fs.isWritable(TEST_FILE_PATH)); - assert_is_false(fs.isExecutable(TEST_FILE_PATH)); - - assert_is_false(fs.isReadable(ABSENT_FILE)); - assert_is_false(fs.isWritable(ABSENT_FILE)); - assert_is_false(fs.isExecutable(ABSENT_FILE)); - - assert_is_true(fs.isReadable(TEST_DIR)); - assert_is_true(fs.isWritable(TEST_DIR)); - assert_is_true(fs.isExecutable(TEST_DIR)); - - assert_is_false(fs.isReadable(ABSENT_DIR)); - assert_is_false(fs.isWritable(ABSENT_DIR)); - assert_is_false(fs.isExecutable(ABSENT_DIR)); - - assert_is_false(fs.isLink(TEST_DIR)); - assert_is_false(fs.isLink(TEST_FILE_PATH)); - assert_is_false(fs.isLink(ABSENT_DIR)); - assert_is_false(fs.isLink(ABSENT_FILE)); - -}, "file types and access modes"); diff --git a/third_party/phantomjs/test/module/fs/paths.js b/third_party/phantomjs/test/module/fs/paths.js deleted file mode 100644 index 0910f20bb3d..00000000000 --- a/third_party/phantomjs/test/module/fs/paths.js +++ /dev/null @@ -1,72 +0,0 @@ - -var fs = require('fs'); -var system = require('system'); - -var TEST_DIR = "testdir", - TEST_FILE = "testfile", - START_CWD = fs.workingDirectory; - -test(function () { - assert_is_true(fs.makeDirectory(TEST_DIR)); - this.add_cleanup(function () { fs.removeTree(TEST_DIR); }); - - assert_is_true(fs.changeWorkingDirectory(TEST_DIR)); - this.add_cleanup(function () { fs.changeWorkingDirectory(START_CWD); }); - - fs.write(TEST_FILE, TEST_FILE, "w"); - var suffix = fs.join("", TEST_DIR, TEST_FILE), - abs = fs.absolute(".." + suffix), - lastIndex = abs.lastIndexOf(suffix); - - assert_not_equals(lastIndex, -1); - assert_equals(lastIndex + suffix.length, abs.length); - -}, "manipulation of current working directory"); - -test(function () { - - fs.copyTree(phantom.libraryPath, TEST_DIR); - this.add_cleanup(function () { fs.removeTree(TEST_DIR); }); - - assert_deep_equals(fs.list(phantom.libraryPath), fs.list(TEST_DIR)); - -}, "copying a directory tree"); - -test(function () { - assert_type_of(fs.readLink, 'function'); - // TODO: test the actual functionality once we can create symlinks. -}, "fs.readLink exists"); - -generate_tests(function fs_join_test (parts, expected) { - var actual = fs.join.apply(null, parts); - assert_equals(actual, expected); -}, [ - [ "fs.join: []", [], "." ], - [ "fs.join: nonsense", [[], null], "." ], - [ "fs.join: 1 element", [""], "." ], - [ "fs.join: 2 elements", ["", "a"], "/a" ], - [ "fs.join: 3 elements", ["a", "b", "c"], "a/b/c" ], - [ "fs.join: 4 elements", ["", "a", "b", "c"], "/a/b/c" ], - [ "fs.join: empty elements", ["", "a", "", "b", "", "c"], "/a/b/c" ], - [ "fs.join: empty elements 2", ["a", "", "b", "", "c"], "a/b/c" ] -]); - -generate_tests(function fs_split_test (input, expected) { - var path = input.join(fs.separator); - var actual = fs.split(path); - assert_deep_equals(actual, expected); -}, [ - [ "fs.split: absolute", - ["", "a", "b", "c", "d"], ["", "a", "b", "c", "d"] ], - [ "fs.split: absolute, trailing", - ["", "a", "b", "c", "d", ""], ["", "a", "b", "c", "d"] ], - [ "fs.split: non-absolute", - ["a", "b", "c", "d"], ["a", "b", "c", "d"] ], - [ "fs.split: non-absolute, trailing", - ["a", "b", "c", "d", ""], ["a", "b", "c", "d"] ], - [ "fs.split: repeated separators", - ["a", "", "", "", - "b", "", - "c", "", "", - "d", "", "", ""], ["a", "b", "c", "d"] ] -]); diff --git a/third_party/phantomjs/test/module/system/stdin.js b/third_party/phantomjs/test/module/system/stdin.js deleted file mode 100644 index 8a08f2631cf..00000000000 --- a/third_party/phantomjs/test/module/system/stdin.js +++ /dev/null @@ -1,22 +0,0 @@ -//! stdin: Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich -//! stdin: いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす - -//^ first line: pangram in German -//^ second line: pan+isogram in hiragana (the Iroha) - -var stdin; -setup(function () { stdin = require("system").stdin; }); - -test(function () { - assert_equals(stdin.readLine(), - "Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich"); -}, "input line one (German)"); - -test(function () { - assert_equals(stdin.readLine(), - "いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす"); -}, "input line two (Japanese)"); - -test(function () { - assert_equals(stdin.readLine(), ""); -}, "input line three (EOF)"); diff --git a/third_party/phantomjs/test/module/system/stdout-err.js b/third_party/phantomjs/test/module/system/stdout-err.js deleted file mode 100644 index 2281b42fdd8..00000000000 --- a/third_party/phantomjs/test/module/system/stdout-err.js +++ /dev/null @@ -1,14 +0,0 @@ -//! no-harness -//! expect-stdout: Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich -//! expect-stderr: いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす - -//^ stdout: pangram in German -//^ stderr: pan+isogram in hiragana (the Iroha) - -phantom.onError = function () { phantom.exit(1); }; - -var sys = require("system"); - -sys.stdout.write("Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich\n"); -sys.stderr.write("いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす"); -phantom.exit(0); diff --git a/third_party/phantomjs/test/module/system/system.js b/third_party/phantomjs/test/module/system/system.js deleted file mode 100644 index ae5422d041b..00000000000 --- a/third_party/phantomjs/test/module/system/system.js +++ /dev/null @@ -1,77 +0,0 @@ -var system = require('system'); - -test(function () { - assert_type_of(system, 'object'); - assert_not_equals(system, null); -}, "system object"); - -test(function () { - assert_own_property(system, 'pid'); - assert_type_of(system.pid, 'number'); - assert_greater_than(system.pid, 0); -}, "system.pid"); - -test(function () { - assert_own_property(system, 'isSSLSupported'); - assert_type_of(system.isSSLSupported, 'boolean'); - assert_equals(system.isSSLSupported, true); -}, "system.isSSLSupported", {/* unsupported */expected_fail: true}); - -test(function () { - assert_own_property(system, 'args'); - assert_type_of(system.args, 'object'); - assert_instance_of(system.args, Array); - assert_greater_than_equal(system.args.length, 1); - - // args[0] will be the test harness. - assert_regexp_match(system.args[0], /\btestharness\.js$/); -}, "system.args", {/* unsupported */expected_fail: true}); - -test(function () { - assert_own_property(system, 'env'); - assert_type_of(system.env, 'object'); -}, "system.env"); - -test(function () { - assert_own_property(system, 'platform'); - assert_type_of(system.platform, 'string'); - assert_equals(system.platform, 'phantomjs'); -}, "system.platform"); - -test(function () { - assert_own_property(system, 'os'); - assert_type_of(system.os, 'object'); - - assert_type_of(system.os.architecture, 'string'); - assert_type_of(system.os.name, 'string'); - assert_type_of(system.os.version, 'string'); - - if (system.os.name === 'mac') { - // release is x.y.z with x = 10 for Snow Leopard and 14 for Yosemite - assert_type_of(system.os.release, 'string'); - assert_greater_than_equal(parseInt(system.os.release, 10), 10); - } -}, "system.os"); - -test(function () { - assert_type_of(system.stdin, 'object'); - assert_type_of(system.stdin.read, 'function'); - assert_type_of(system.stdin.readLine, 'function'); - assert_type_of(system.stdin.close, 'function'); -}, "system.stdin"); - -test(function () { - assert_type_of(system.stdout, 'object'); - assert_type_of(system.stdout.write, 'function'); - assert_type_of(system.stdout.writeLine, 'function'); - assert_type_of(system.stdout.flush, 'function'); - assert_type_of(system.stdout.close, 'function'); -}, "system.stdout"); - -test(function () { - assert_type_of(system.stderr, 'object'); - assert_type_of(system.stderr.write, 'function'); - assert_type_of(system.stderr.writeLine, 'function'); - assert_type_of(system.stderr.flush, 'function'); - assert_type_of(system.stderr.close, 'function'); -}, "system.stderr"); diff --git a/third_party/phantomjs/test/module/webpage/abort-network-request.js b/third_party/phantomjs/test/module/webpage/abort-network-request.js deleted file mode 100644 index 06430e14b0a..00000000000 --- a/third_party/phantomjs/test/module/webpage/abort-network-request.js +++ /dev/null @@ -1,36 +0,0 @@ -var webpage = require('webpage'); - -async_test(function () { - var page = webpage.create(); - var abortCount = 0; - var errorCount = 0; - var abortedIds = {}; - var urlToBlockRegExp = /logo\.png$/i; - - page.onResourceRequested = this.step_func(function(requestData, request) { - assert_type_of(request, 'object'); - assert_type_of(request.abort, 'function'); - if (urlToBlockRegExp.test(requestData.url)) { - request.abort(); - ++abortCount; - abortedIds[requestData.id] = 1; - } - }); - page.onResourceError = this.step_func(function(error) { - // We can't match up errors to requests by URL because error.url will - // be the empty string in this case. FIXME. - assert_own_property(abortedIds, error.id); - ++errorCount; - }); - page.onResourceReceived = this.step_func(function(response) { - assert_regexp_not_match(response.url, urlToBlockRegExp); - }); - - page.open(TEST_HTTP_BASE + 'logo.html', - this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_equals(abortCount, 1); - assert_equals(errorCount, 1); - })); - -}, "can abort network requests", { timeout: 5000 }); diff --git a/third_party/phantomjs/test/module/webpage/add-header.js b/third_party/phantomjs/test/module/webpage/add-header.js deleted file mode 100644 index 46b70bb1b0e..00000000000 --- a/third_party/phantomjs/test/module/webpage/add-header.js +++ /dev/null @@ -1,24 +0,0 @@ -async_test(function () { - var webpage = require('webpage'); - - // NOTE: HTTP header names are case-insensitive. Our test server - // returns the name in lowercase. - - var page = webpage.create(); - assert_type_of(page.customHeaders, 'object'); - assert_deep_equals(page.customHeaders, {}); - - page.onResourceRequested = this.step_func(function(requestData, request) { - assert_type_of(request.setHeader, 'function'); - request.setHeader('CustomHeader', 'CustomValue'); - }); - page.open(TEST_HTTP_BASE + 'echo', this.step_func_done(function (status) { - var json, headers; - assert_equals(status, 'success'); - json = JSON.parse(page.plainText); - headers = json.headers; - assert_own_property(headers, 'customheader'); - assert_equals(headers.customheader, 'CustomValue'); - })); - -}, "add custom headers in onResourceRequested"); diff --git a/third_party/phantomjs/test/module/webpage/callback.js b/third_party/phantomjs/test/module/webpage/callback.js deleted file mode 100644 index c8edb1b4b8c..00000000000 --- a/third_party/phantomjs/test/module/webpage/callback.js +++ /dev/null @@ -1,16 +0,0 @@ -test(function () { - var page = require('webpage').create(); - - var msgA = "a", - msgB = "b", - result, - expected = msgA + msgB; - page.onCallback = function(a, b) { - return a + b; - }; - result = page.evaluate(function(a, b) { - return window.callPhantom(a, b); - }, msgA, msgB); - - assert_equals(result, expected); -}, "page.onCallback", { expected_fail : true }); diff --git a/third_party/phantomjs/test/module/webpage/capture-content.js b/third_party/phantomjs/test/module/webpage/capture-content.js deleted file mode 100644 index 99f64ad57c4..00000000000 --- a/third_party/phantomjs/test/module/webpage/capture-content.js +++ /dev/null @@ -1,50 +0,0 @@ -//! unsupported -var content; -setup(function () { - var fs = require('fs'); - // libraryPath is test/module/webpage - content = fs.read(fs.join(phantom.libraryPath, - "../../www/hello.html")); -}); - -// XFAIL: This feature had to be backed out for breaking WebSockets. -async_test(function () { - var page = require('webpage').create(); - var lastChunk = ""; - var bodySize = 0; - page.captureContent = ['.*']; - // Not a step function because it may be called several times - // and doesn't need to make assertions. - page.onResourceReceived = function (resource) { - lastChunk = resource.body; - bodySize = resource.bodySize; - }; - page.open(TEST_HTTP_BASE + "hello.html", - this.step_func_done(function (status) { - assert_equals(status, "success"); - assert_equals(bodySize, content.length); - assert_equals(lastChunk, content); - })); - -}, "onResourceReceived sees the body if captureContent is activated", - { expected_fail: true } -); - -async_test(function () { - var page = require('webpage').create(); - var lastChunk = ""; - var bodySize = 0; - page.captureContent = ['/some/other/url']; - // Not a step function because it may be called several times - // and doesn't need to make assertions. - page.onResourceReceived = function (resource) { - lastChunk = resource.body; - bodySize = resource.bodySize; - }; - page.open(TEST_HTTP_BASE + "hello.html", - this.step_func_done(function (status) { - assert_equals(status, "success"); - assert_equals(bodySize, 0); - assert_equals(lastChunk, ""); - })); -}, "onResourceReceived doesn't see the body if captureContent doesn't match"); diff --git a/third_party/phantomjs/test/module/webpage/change-request-encoded-url.js b/third_party/phantomjs/test/module/webpage/change-request-encoded-url.js deleted file mode 100644 index 37778a73e6c..00000000000 --- a/third_party/phantomjs/test/module/webpage/change-request-encoded-url.js +++ /dev/null @@ -1,26 +0,0 @@ -var webpage = require('webpage'); - -async_test(function () { - var page = webpage.create(); - - var url = TEST_HTTP_BASE + "cdn-cgi/pe/bag?r%5B%5D="+ - "http%3A%2F%2Fwww.example.org%2Fcdn-cgi%2Fnexp%2F"+ - "abv%3D927102467%2Fapps%2Fabetterbrowser.js"; - var receivedUrl; - - page.onResourceRequested = this.step_func(function(requestData, request) { - request.changeUrl(requestData.url); - }); - - page.onResourceReceived = this.step_func(function(data) { - if (data.stage === 'end') { - receivedUrl = data.url; - } - }); - - page.open(url, this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_equals(receivedUrl, url); - })); - -}, "encoded URLs properly round-trip through request.changeUrl"); diff --git a/third_party/phantomjs/test/module/webpage/change-request-url.js b/third_party/phantomjs/test/module/webpage/change-request-url.js deleted file mode 100644 index ea8e7e8a583..00000000000 --- a/third_party/phantomjs/test/module/webpage/change-request-url.js +++ /dev/null @@ -1,40 +0,0 @@ -//! unsupported -var webpage = require('webpage'); - -async_test(function () { - - var page = webpage.create(); - var urlToChange = TEST_HTTP_BASE + 'logo.png'; - var alternativeUrl = TEST_HTTP_BASE + 'phantomjs-logo.gif'; - var startStage = 0; - var endStage = 0; - - page.onResourceRequested = this.step_func(function(requestData, request) { - if (requestData.url === urlToChange) { - assert_type_of(request, 'object'); - assert_type_of(request.changeUrl, 'function'); - request.changeUrl(alternativeUrl); - } - }); - - page.onResourceReceived = this.step_func(function(data) { - if (data.url === alternativeUrl && data.stage === 'start') { - ++startStage; - } - if (data.url === alternativeUrl && data.stage === 'end') { - ++endStage; - } - }); - - page.open(TEST_HTTP_BASE + 'logo.html', - this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_equals(startStage, 1); - assert_equals(endStage, 1); - - // The page HTML should still refer to the original image. - assert_regexp_match(page.content, /logo\.png/); - assert_regexp_not_match(page.content, /logo\.gif/); - })); - -}, "request.changeUrl"); diff --git a/third_party/phantomjs/test/module/webpage/cjk-text-codecs.js b/third_party/phantomjs/test/module/webpage/cjk-text-codecs.js deleted file mode 100644 index afd653c6982..00000000000 --- a/third_party/phantomjs/test/module/webpage/cjk-text-codecs.js +++ /dev/null @@ -1,33 +0,0 @@ -var webpage = require('webpage'); - -function test_one(text) { - var t = async_test(text.codec); - t.step(function () { - var page = webpage.create(); - page.open(text.url, t.step_func_done(function () { - var decodedText = page.evaluate(function() { - return document.querySelector('pre').innerText; - }); - var regex = '^' + text.reference + '$'; - assert_regexp_match(text.reference, new RegExp(regex)); - })); - }); -} - -function Text(codec, base64, reference) { - this.codec = codec; - this.base64 = base64; - this.reference = reference; - this.url = 'data:text/plain;charset=' + this.codec + - ';base64,' + this.base64; -} - -[ - new Text('Shift_JIS', 'g3SDQIOTg2eDgA==', 'ファントム'), - new Text('EUC-JP', 'pdWloaXzpcil4A0K', 'ファントム'), - new Text('ISO-2022-JP', 'GyRCJVUlISVzJUglYBsoQg0K', 'ファントム'), - new Text('Big5', 'pNu2SA0K', '幻象'), - new Text('GBK', 'u8PP8w0K', '幻象'), - new Text('EUC-KR', 'yK+/tQ==', '환영'), -] - .forEach(test_one); diff --git a/third_party/phantomjs/test/module/webpage/clip-rect.js b/third_party/phantomjs/test/module/webpage/clip-rect.js deleted file mode 100644 index 46c9e40d840..00000000000 --- a/third_party/phantomjs/test/module/webpage/clip-rect.js +++ /dev/null @@ -1,19 +0,0 @@ -var webpage = require('webpage'); - -test(function () { - var defaultPage = webpage.create(); - assert_deep_equals(defaultPage.clipRect, {height:0,left:0,top:0,width:0}); -}, "default page.clipRect"); - -test(function () { - var options = { - clipRect: { - height: 100, - left: 10, - top: 20, - width: 200 - } - }; - var customPage = webpage.create(options); - assert_deep_equals(customPage.clipRect, options.clipRect); -}, "custom page.clipRect"); diff --git a/third_party/phantomjs/test/module/webpage/construction-with-options.js b/third_party/phantomjs/test/module/webpage/construction-with-options.js deleted file mode 100644 index 42d67371d49..00000000000 --- a/third_party/phantomjs/test/module/webpage/construction-with-options.js +++ /dev/null @@ -1,59 +0,0 @@ -//! unsupported -test(function () { - var opts = {}, - page = new WebPage(opts); - assert_type_of(page, 'object'); - assert_not_equals(page, null); -}, "webpage constructor accepts an opts object"); - -async_test(function () { - var opts = { - onConsoleMessage: this.step_func_done(function (msg) { - assert_equals(msg, "test log"); - }) - }; - var page = new WebPage(opts); - assert_equals(page.onConsoleMessage, opts.onConsoleMessage); - page.evaluate(function () {console.log('test log');}); - -}, "specifying onConsoleMessage with opts"); - -async_test(function () { - var page_opened = false; - var opts = { - onLoadStarted: this.step_func_done(function (msg) { - assert_is_true(page_opened); - }) - }; - var page = new WebPage(opts); - assert_equals(page.onLoadStarted, opts.onLoadStarted); - page_opened = true; - page.open("about:blank"); - -}, "specifying onLoadStarted with opts"); - -async_test(function () { - var page_opened = false; - var opts = { - onLoadFinished: this.step_func_done(function (msg) { - assert_is_true(page_opened); - }) - }; - var page = new WebPage(opts); - assert_equals(page.onLoadFinished, opts.onLoadFinished); - page_opened = true; - page.open("about:blank"); - -}, "specifying onLoadFinished with opts"); - -// FIXME: Actually test that the timeout is effective. -test(function () { - var opts = { - settings: { - timeout: 100 // time in ms - } - }; - var page = new WebPage(opts); - assert_equals(page.settings.timeout, opts.settings.timeout); - -}, "specifying timeout with opts"); diff --git a/third_party/phantomjs/test/module/webpage/contextclick-event.js b/third_party/phantomjs/test/module/webpage/contextclick-event.js deleted file mode 100644 index 7716ba51f9f..00000000000 --- a/third_party/phantomjs/test/module/webpage/contextclick-event.js +++ /dev/null @@ -1,32 +0,0 @@ -test(function () { - var page = require('webpage').create(); - - page.evaluate(function() { - window.addEventListener('contextmenu', function(event) { - window.loggedEvent = window.loggedEvent || {}; - window.loggedEvent.contextmenu = {clientX: event.clientX, clientY: event.clientY, shiftKey: event.shiftKey}; - }, false); - }); - page.sendEvent('contextmenu', 42, 217); - - var event = page.evaluate(function() { - return window.loggedEvent; - }); - assert_equals(event.contextmenu.clientX, 42); - assert_equals(event.contextmenu.clientY, 217); - - // click with modifier key - page.evaluate(function() { - window.addEventListener('contextmenu', function(event) { - window.loggedEvent = window.loggedEvent || {}; - window.loggedEvent.contextmenu = {clientX: event.clientX, clientY: event.clientY, shiftKey: event.shiftKey}; - }, false); - }); - page.sendEvent('contextmenu', 100, 100, 'left', page.event.modifier.shift); - - var event = page.evaluate(function() { - return window.loggedEvent.contextmenu; - }); - assert_is_true(event.shiftKey); - -}, "context click events"); diff --git a/third_party/phantomjs/test/module/webpage/cookies.js b/third_party/phantomjs/test/module/webpage/cookies.js deleted file mode 100644 index 344dffb1916..00000000000 --- a/third_party/phantomjs/test/module/webpage/cookies.js +++ /dev/null @@ -1,112 +0,0 @@ -async_test(function () { - var url = TEST_HTTP_BASE + "echo"; - var webpage = require('webpage'); - - var page = webpage.create(); - - page.cookies = [{ - 'name' : 'Valid-Cookie-Name', - 'value' : 'Valid-Cookie-Value', - 'domain' : 'localhost', - 'path' : '/', - 'httpOnly' : true, - 'secure' : false - },{ - 'name' : 'Valid-Cookie-Name-Sec', - 'value' : 'Valid-Cookie-Value-Sec', - 'domain' : 'localhost', - 'path' : '/', - 'httpOnly' : true, - 'secure' : false, - 'expires': (Date.now()/1000) + 3600 - }]; - - page.open(url, this.step_func(function (status) { - assert_equals(status, "success"); - var headers = JSON.parse(page.plainText).headers; - assert_own_property(headers, 'cookie'); - assert_regexp_match(headers.cookie, /\bValid-Cookie-Name\b/); - assert_regexp_match(headers.cookie, /\bValid-Cookie-Value\b/); - assert_regexp_match(headers.cookie, /\bValid-Cookie-Name-Sec\b/); - assert_regexp_match(headers.cookie, /\bValid-Cookie-Value-Sec\b/); - assert_not_equals(page.cookies.length, 0); - - page.cookies = []; - page.open(url, this.step_func_done(function (status) { - assert_equals(status, "success"); - var headers = JSON.parse(page.plainText).headers; - assert_no_property(headers, 'cookie'); - })); - })); -}, "adding and deleting cookies with page.cookies"); - -async_test(function () { - var url = TEST_HTTP_BASE + "echo"; - var webpage = require('webpage'); - - var page = webpage.create(); - - page.addCookie({ - 'name' : 'Added-Cookie-Name', - 'value' : 'Added-Cookie-Value', - 'domain' : 'localhost' - }); - - page.open(url, this.step_func(function (status) { - assert_equals(status, "success"); - var headers = JSON.parse(page.plainText).headers; - assert_own_property(headers, 'cookie'); - assert_regexp_match(headers.cookie, /\bAdded-Cookie-Name\b/); - assert_regexp_match(headers.cookie, /\bAdded-Cookie-Value\b/); - - page.deleteCookie("Added-Cookie-Name"); - page.open(url, this.step_func_done(function (status) { - assert_equals(status, "success"); - var headers = JSON.parse(page.plainText).headers; - assert_no_property(headers, 'cookie'); - })); - })); - -}, "adding and deleting cookies with page.addCookie and page.deleteCookie"); - -async_test(function () { - var url = TEST_HTTP_BASE + "echo"; - var webpage = require('webpage'); - - var page = webpage.create(); - - page.cookies = [ - { // domain mismatch. - 'name' : 'Invalid-Cookie-Name-1', - 'value' : 'Invalid-Cookie-Value-1', - 'domain' : 'foo.example' - },{ // path mismatch: the cookie will be set, - // but won't be visible from the given URL (not same path). - 'name' : 'Invalid-Cookie-Name-2', - 'value' : 'Invalid-Cookie-Value-2', - 'domain' : 'localhost', - 'path' : '/bar' - },{ // cookie expired. - 'name' : 'Invalid-Cookie-Name-3', - 'value' : 'Invalid-Cookie-Value-3', - 'domain' : 'localhost', - 'expires' : 5 - },{ // https only: the cookie will be set, - // but won't be visible from the given URL (not https). - 'name' : 'Invalid-Cookie-Name-4', - 'value' : 'Invalid-Cookie-Value-4', - 'domain' : 'localhost', - 'secure' : true - },{ // cookie expired (date in "sec since epoch"). - 'name' : 'Invalid-Cookie-Name-5', - 'value' : 'Invalid-Cookie-Value-5', - 'domain' : 'localhost', - 'expires' : (Date.now()/1000) - 10 //< date in the past - }]; - - page.open(url, this.step_func_done(function (status) { - assert_equals(status, "success"); - var headers = JSON.parse(page.plainText).headers; - assert_no_property(headers, 'cookie'); - })); -}, "page.cookies provides cookies only to appropriate requests"); diff --git a/third_party/phantomjs/test/module/webpage/custom-headers.js b/third_party/phantomjs/test/module/webpage/custom-headers.js deleted file mode 100644 index 0aaefd79dc7..00000000000 --- a/third_party/phantomjs/test/module/webpage/custom-headers.js +++ /dev/null @@ -1,30 +0,0 @@ -async_test(function () { - var webpage = require('webpage'); - var page = webpage.create(); - assert_type_of(page.customHeaders, 'object'); - assert_deep_equals(page.customHeaders, {}); - - // NOTE: HTTP header names are case-insensitive. Our test server - // returns the name in lowercase. - page.customHeaders = { - 'Custom-Key': 'Custom-Value', - 'User-Agent': 'Overriden-UA', - 'Referer': 'http://example.com/' - }; - page.open(TEST_HTTP_BASE + 'echo', this.step_func_done(function (status) { - var json, headers; - assert_equals(status, 'success'); - json = JSON.parse(page.plainText); - assert_type_of(json, 'object'); - headers = json.headers; - assert_type_of(headers, 'object'); - - assert_own_property(headers, 'custom-key'); - assert_own_property(headers, 'user-agent'); - assert_own_property(headers, 'referer'); - assert_equals(headers['custom-key'], 'Custom-Value'); - assert_equals(headers['user-agent'], 'Overriden-UA'); - assert_equals(headers['referer'], 'http://example.com/'); - })); - -}, "adding custom headers with page.customHeaders"); diff --git a/third_party/phantomjs/test/module/webpage/evaluate-broken-json.js b/third_party/phantomjs/test/module/webpage/evaluate-broken-json.js deleted file mode 100644 index 1f1d263598e..00000000000 --- a/third_party/phantomjs/test/module/webpage/evaluate-broken-json.js +++ /dev/null @@ -1,14 +0,0 @@ -test(function () { - var webpage = require('webpage'); - var page = webpage.create(); - - // Hijack JSON.parse to something completely useless. - page.content = ''; - - var result = page.evaluate(function(obj) { - return obj.value * obj.value; - }, { value: 4 }); - - assert_equals(result, 16); - -}, "page script should not interfere with page.evaluate"); diff --git a/third_party/phantomjs/test/module/webpage/file-upload.js b/third_party/phantomjs/test/module/webpage/file-upload.js deleted file mode 100644 index 780ffd7bcaa..00000000000 --- a/third_party/phantomjs/test/module/webpage/file-upload.js +++ /dev/null @@ -1,54 +0,0 @@ -// Note: uses various files in module/webpage as things to be uploaded. -// Which files they are doesn't matter. - -var page; -setup(function () { - page = require('webpage').create(); - page.content = - '\n' + - '\n' + - '' + - ''; - page.uploadFile("#file", "file-upload.js"); - page.uploadFile("#file2", "file-upload.js"); - page.uploadFile("#file3", ["file-upload.js", "object.js"]); -}); - -function test_one_elt(id, names) { - var files = page.evaluate(function (id) { - var elt = document.getElementById(id); - var rv = []; - for (var i = 0; i < elt.files.length; i++) { - rv.push(elt.files[i].name); - } - return rv; - }, id); - assert_deep_equals(files, names); -} - -generate_tests(test_one_elt, [ - ["single upload single file", "file", ["file-upload.js"]], - ["multiple upload single file", "file2", ["file-upload.js"]], - ["multiple upload multiple file", "file3", ["file-upload.js", "object.js"]], -], { expected_fail: false }); - -async_test(function () { - page.onFilePicker = this.step_func(function (oldFile) { - assert_equals(oldFile, ""); - return "no-plugin.js"; - }); - - test_one_elt("file4", []); - - page.evaluate(function () { - var fileUp = document.querySelector("#file4"); - var ev = document.createEvent("MouseEvents"); - ev.initEvent("click", true, true); - fileUp.dispatchEvent(ev); - }); - - setTimeout(this.step_func_done(function () { - test_one_elt("file4", ["no-plugin.js"]); - }, 0)); - -}, "page.onFilePicker", { expected_fail: true }); diff --git a/third_party/phantomjs/test/module/webpage/frame-switching-deprecated.js b/third_party/phantomjs/test/module/webpage/frame-switching-deprecated.js deleted file mode 100644 index 54e5b7484ef..00000000000 --- a/third_party/phantomjs/test/module/webpage/frame-switching-deprecated.js +++ /dev/null @@ -1,68 +0,0 @@ -async_test(function () { - var p = require("webpage").create(); - - function pageTitle(page) { - return page.evaluate(function(){ - return window.document.title; - }); - } - - function setPageTitle(page, newTitle) { - page.evaluate(function(newTitle){ - window.document.title = newTitle; - }, newTitle); - } - - function testFrameSwitchingDeprecated() { - assert_equals(pageTitle(p), "index"); - assert_equals(p.currentFrameName(), ""); - assert_equals(p.childFramesCount(), 2); - assert_deep_equals(p.childFramesName(), ["frame1", "frame2"]); - setPageTitle(p, pageTitle(p) + "-visited"); - - assert_is_true(p.switchToChildFrame("frame1")); - assert_equals(pageTitle(p), "frame1"); - assert_equals(p.currentFrameName(), "frame1"); - assert_equals(p.childFramesCount(), 2); - assert_deep_equals(p.childFramesName(), ["frame1-1", "frame1-2"]); - setPageTitle(p, pageTitle(p) + "-visited"); - - assert_is_true(p.switchToChildFrame("frame1-2")); - assert_equals(pageTitle(p), "frame1-2"); - assert_equals(p.currentFrameName(), "frame1-2"); - assert_equals(p.childFramesCount(), 0); - assert_deep_equals(p.childFramesName(), []); - setPageTitle(p, pageTitle(p) + "-visited"); - - assert_is_true(p.switchToParentFrame()); - assert_equals(pageTitle(p), "frame1-visited"); - assert_equals(p.currentFrameName(), "frame1"); - assert_equals(p.childFramesCount(), 2); - assert_deep_equals(p.childFramesName(), ["frame1-1", "frame1-2"]); - - assert_is_true(p.switchToChildFrame(0)); - assert_equals(pageTitle(p), "frame1-1"); - assert_equals(p.currentFrameName(), "frame1-1"); - assert_equals(p.childFramesCount(), 0); - assert_deep_equals(p.childFramesName(), []); - - assert_equals(p.switchToMainFrame(), undefined); - assert_equals(pageTitle(p), "index-visited"); - assert_equals(p.currentFrameName(), ""); - assert_equals(p.childFramesCount(), 2); - assert_deep_equals(p.childFramesName(), ["frame1", "frame2"]); - - assert_is_true(p.switchToChildFrame("frame2")); - assert_equals(pageTitle(p), "frame2"); - assert_equals(p.currentFrameName(), "frame2"); - assert_equals(p.childFramesCount(), 3); - assert_deep_equals(p.childFramesName(), - ["frame2-1", "frame2-2", "frame2-3"]); - } - - p.open(TEST_HTTP_BASE + "frameset", this.step_func_done(function (s) { - assert_equals(s, "success"); - testFrameSwitchingDeprecated(); - })); - -}, "frame switching deprecated API"); diff --git a/third_party/phantomjs/test/module/webpage/frame-switching.js b/third_party/phantomjs/test/module/webpage/frame-switching.js deleted file mode 100644 index a821320330f..00000000000 --- a/third_party/phantomjs/test/module/webpage/frame-switching.js +++ /dev/null @@ -1,97 +0,0 @@ -async_test(function () { - var p = require("webpage").create(); - - function pageTitle(page) { - return page.evaluate(function(){ - return window.document.title; - }); - } - - function setPageTitle(page, newTitle) { - page.evaluate(function(newTitle){ - window.document.title = newTitle; - }, newTitle); - } - - function testFrameSwitching() { - assert_equals(pageTitle(p), "index"); - assert_equals(p.frameName, ""); - assert_equals(p.framesCount, 2); - assert_deep_equals(p.framesName, ["frame1", "frame2"]); - setPageTitle(p, pageTitle(p) + "-visited"); - - assert_is_true(p.switchToFrame("frame1")); - assert_equals(pageTitle(p), "frame1"); - assert_equals(p.frameName, "frame1"); - assert_equals(p.framesCount, 2); - assert_deep_equals(p.framesName, ["frame1-1", "frame1-2"]); - setPageTitle(p, pageTitle(p) + "-visited"); - - assert_is_true(p.switchToFrame("frame1-2")); - assert_equals(pageTitle(p), "frame1-2"); - assert_equals(p.frameName, "frame1-2"); - assert_equals(p.framesCount, 0); - assert_deep_equals(p.framesName, []); - setPageTitle(p, pageTitle(p) + "-visited"); - - assert_is_true(p.switchToParentFrame()); - assert_equals(pageTitle(p), "frame1-visited"); - assert_equals(p.frameName, "frame1"); - assert_equals(p.framesCount, 2); - assert_deep_equals(p.framesName, ["frame1-1", "frame1-2"]); - - assert_is_true(p.switchToFrame(0)); - assert_equals(pageTitle(p), "frame1-1"); - assert_equals(p.frameName, "frame1-1"); - assert_equals(p.framesCount, 0); - assert_deep_equals(p.framesName, []); - - assert_equals(p.switchToMainFrame(), undefined); - assert_equals(pageTitle(p), "index-visited"); - assert_equals(p.frameName, ""); - assert_equals(p.framesCount, 2); - assert_deep_equals(p.framesName, ["frame1", "frame2"]); - - assert_is_true(p.switchToFrame("frame2")); - assert_equals(pageTitle(p), "frame2"); - assert_equals(p.frameName, "frame2"); - assert_equals(p.framesCount, 3); - assert_deep_equals(p.framesName, - ["frame2-1", "frame2-2", "frame2-3"]); - - assert_equals(p.focusedFrameName, ""); - - p.evaluate(function(){ - window.focus(); - }); - assert_equals(p.focusedFrameName, "frame2"); - - assert_is_true(p.switchToFrame("frame2-1")); - p.evaluate(function(){ - window.focus(); - }); - assert_equals(p.focusedFrameName, "frame2-1"); - - assert_equals(p.switchToMainFrame(), undefined); - p.evaluate(function(){ - window.focus(); - }); - assert_equals(p.focusedFrameName, ""); - - p.evaluate(function(){ - window.frames[0].focus(); - }); - assert_equals(p.focusedFrameName, "frame1"); - assert_equals(p.frameName, ""); - - assert_equals(p.switchToFocusedFrame(), undefined); - assert_equals(p.frameName, "frame1"); - } - - p.open(TEST_HTTP_BASE + "frameset", - this.step_func_done(function (s) { - assert_equals(s, "success"); - testFrameSwitching(); - })); - -}, "frame switching API"); diff --git a/third_party/phantomjs/test/module/webpage/https-bad-cert.js b/third_party/phantomjs/test/module/webpage/https-bad-cert.js deleted file mode 100644 index fcdb7d4878b..00000000000 --- a/third_party/phantomjs/test/module/webpage/https-bad-cert.js +++ /dev/null @@ -1,15 +0,0 @@ -async_test(function () { - // This loads the same page as https-good-cert.js, but does not - // tell PhantomJS to trust the snakeoil certificate that the test - // HTTPS server uses, so it should fail. - - var page = require('webpage').create(); - var url = TEST_HTTPS_BASE; - page.onResourceError = this.step_func(function (err) { - assert_equals(err.url, url); - assert_equals(err.errorString, "SSL handshake failed"); - }); - page.open(url, this.step_func_done(function (status) { - assert_not_equals(status, "success"); - })); -}, "should fail to load an HTTPS webpage with a self-signed certificate"); diff --git a/third_party/phantomjs/test/module/webpage/https-good-cert.js b/third_party/phantomjs/test/module/webpage/https-good-cert.js deleted file mode 100644 index af9cf075c83..00000000000 --- a/third_party/phantomjs/test/module/webpage/https-good-cert.js +++ /dev/null @@ -1,14 +0,0 @@ -//! unsupported -//! snakeoil -async_test(function () { - // This loads the same page as https-bad-cert.js, but tells - // PhantomJS to trust the snakeoil certificate - // that the test HTTPS server uses, so it should succeed. - - var page = require('webpage').create(); - var url = TEST_HTTPS_BASE; - page.onResourceError = this.unreached_func(); - page.open(url, this.step_func_done(function (status) { - assert_equals(status, "success"); - })); -}, "loading an HTTPS webpage"); diff --git a/third_party/phantomjs/test/module/webpage/includejs.js b/third_party/phantomjs/test/module/webpage/includejs.js deleted file mode 100644 index df3d922ebb2..00000000000 --- a/third_party/phantomjs/test/module/webpage/includejs.js +++ /dev/null @@ -1,42 +0,0 @@ -var webpage = require('webpage'); - -async_test(function () { - var page = webpage.create(); - page.open(TEST_HTTP_BASE + 'includejs1.html', - this.step_func(function (status) { - assert_equals(status, 'success'); - page.includeJs(TEST_HTTP_BASE + 'includejs.js', - this.step_func_done(function () { - var title = page.evaluate('getTitle'); - assert_equals(title, 'i am includejs one'); - })); - })); - -}, "including JS in a page"); - -async_test(function () { - var page = webpage.create(); - var already = false; - page.open(TEST_HTTP_BASE + 'includejs1.html', - this.step_func(function (status) { - assert_equals(status, 'success'); - page.includeJs(TEST_HTTP_BASE + 'includejs.js', - this.step_func(function () { - assert_is_false(already); - already = true; - var title = page.evaluate('getTitle'); - assert_equals(title, 'i am includejs one'); - page.open(TEST_HTTP_BASE + 'includejs2.html', - this.step_func(function (status) { - assert_equals(status, 'success'); - page.includeJs(TEST_HTTP_BASE + 'includejs.js', - this.step_func_done(function () { - assert_is_true(already); - var title = page.evaluate('getTitle'); - assert_equals(title, 'i am includejs two'); - })); - })); - })); - })); - -}, "after-inclusion callbacks should fire only once"); diff --git a/third_party/phantomjs/test/module/webpage/keydown-event.js b/third_party/phantomjs/test/module/webpage/keydown-event.js deleted file mode 100644 index ec9d52edf63..00000000000 --- a/third_party/phantomjs/test/module/webpage/keydown-event.js +++ /dev/null @@ -1,20 +0,0 @@ -test(function () { - var webpage = require('webpage'); - - var page = webpage.create(); - - page.evaluate(function() { - window.addEventListener('keydown', function(event) { - window.loggedEvent = window.loggedEvent || []; - window.loggedEvent.push(event.which); - }, false); - }); - - page.sendEvent('keydown', page.event.key.A); - var loggedEvent = page.evaluate(function() { - return window.loggedEvent; - }); - - assert_equals(loggedEvent.length, 1); - assert_equals(loggedEvent[0], page.event.key.A); -}, "key-down events"); diff --git a/third_party/phantomjs/test/module/webpage/keypress-event.js b/third_party/phantomjs/test/module/webpage/keypress-event.js deleted file mode 100644 index b3b86ca77b5..00000000000 --- a/third_party/phantomjs/test/module/webpage/keypress-event.js +++ /dev/null @@ -1,67 +0,0 @@ -test(function () { - var webpage = require('webpage'); - - var page = webpage.create(); - - page.evaluate(function() { - window.addEventListener('keypress', function(event) { - window.loggedEvent = window.loggedEvent || []; - window.loggedEvent.push(event.which); - }, false); - }); - - page.sendEvent('keypress', page.event.key.C); - var loggedEvent = page.evaluate(function() { - return window.loggedEvent; - }); - - assert_equals(loggedEvent.length, 1); - assert_equals(loggedEvent[0], page.event.key.C); - - - // Send keypress events to an input element and observe the effect. - - page.content = ''; - page.evaluate(function() { - document.querySelector('input').focus(); - }); - - function getText() { - return page.evaluate(function() { - return document.querySelector('input').value; - }); - } - - page.sendEvent('keypress', page.event.key.A); - assert_equals(getText(), 'A'); - page.sendEvent('keypress', page.event.key.B); - assert_equals(getText(), 'AB'); - page.sendEvent('keypress', page.event.key.Backspace); - assert_equals(getText(), 'A'); - page.sendEvent('keypress', page.event.key.Backspace); - assert_equals(getText(), ''); - - page.sendEvent('keypress', 'XYZ'); - assert_equals(getText(), 'XYZ'); - - // Special character: A with umlaut - page.sendEvent('keypress', 'ä'); - assert_equals(getText(), 'XYZä'); - - // 0x02000000 is the Shift modifier. - page.sendEvent('keypress', page.event.key.Home, null, null, 0x02000000); - page.sendEvent('keypress', page.event.key.Delete); - assert_equals(getText(), ''); - - - // Joel: This works, but it causes you to lose your clipboard when running the tests. - // Cut and Paste - // 0x04000000 is the Control modifier. - // page.sendEvent('keypress', 'ABCD'); - // assert_equals(getText(), 'ABCD'); - // page.sendEvent('keypress', page.event.key.Home, null, null, 0x02000000); - // page.sendEvent('keypress', page.event.key.Cut); - // assert_equals(getText(), ''); - // page.sendEvent('keypress', page.event.key.Paste); - // assert_equals(getText(), 'ABCD'); -}, "key press events"); diff --git a/third_party/phantomjs/test/module/webpage/keyup-event.js b/third_party/phantomjs/test/module/webpage/keyup-event.js deleted file mode 100644 index 383582a6869..00000000000 --- a/third_party/phantomjs/test/module/webpage/keyup-event.js +++ /dev/null @@ -1,20 +0,0 @@ -test(function () { - var webpage = require('webpage'); - - var page = webpage.create(); - - page.evaluate(function() { - window.addEventListener('keyup', function(event) { - window.loggedEvent = window.loggedEvent || []; - window.loggedEvent.push(event.which); - }, false); - }); - - page.sendEvent('keyup', page.event.key.B); - var loggedEvent = page.evaluate(function() { - return window.loggedEvent; - }); - - assert_equals(loggedEvent.length, 1); - assert_equals(loggedEvent[0], page.event.key.B); -}, "key-up events"); diff --git a/third_party/phantomjs/test/module/webpage/loading.js b/third_party/phantomjs/test/module/webpage/loading.js deleted file mode 100644 index 6af3324429d..00000000000 --- a/third_party/phantomjs/test/module/webpage/loading.js +++ /dev/null @@ -1,21 +0,0 @@ -async_test(function () { - var webpage = require('webpage'); - var page = webpage.create(); - - assert_type_of(page, 'object'); - assert_type_of(page.loading, 'boolean'); - assert_type_of(page.loadingProgress, 'number'); - - assert_is_false(page.loading); - assert_equals(page.loadingProgress, 0); - - page.open(TEST_HTTP_BASE + 'hello.html', - this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_equals(page.loading, false); - assert_equals(page.loadingProgress, 100); - })); - - assert_is_true(page.loading); - assert_greater_than(page.loadingProgress, 0); -}, "page loading progress"); diff --git a/third_party/phantomjs/test/module/webpage/local-urls-disabled-iframe.js b/third_party/phantomjs/test/module/webpage/local-urls-disabled-iframe.js deleted file mode 100644 index 3144299b318..00000000000 --- a/third_party/phantomjs/test/module/webpage/local-urls-disabled-iframe.js +++ /dev/null @@ -1,23 +0,0 @@ -//! unsupported -//! phantomjs: --web-security=no --local-url-access=no - -var webpage = require("webpage"); - -async_test(function () { - var page = webpage.create(); - var url = TEST_HTTP_BASE + "iframe.html#file:///nonexistent"; - var rsErrorCalled = false; - - page.onResourceError = this.step_func(function (error) { - rsErrorCalled = true; - assert_equals(error.url, "file:///nonexistent"); - assert_equals(error.errorCode, 301); - assert_equals(error.errorString, 'Protocol "file" is unknown'); - }); - - page.open(url, this.step_func_done(function () { - assert_is_true(rsErrorCalled); - })); - -}, -"doesn't attempt to load a file: URL in an iframe with --local-url-access=no"); diff --git a/third_party/phantomjs/test/module/webpage/local-urls-disabled.js b/third_party/phantomjs/test/module/webpage/local-urls-disabled.js deleted file mode 100644 index 07853d86e8f..00000000000 --- a/third_party/phantomjs/test/module/webpage/local-urls-disabled.js +++ /dev/null @@ -1,22 +0,0 @@ -//! unsupported -//! phantomjs: --local-url-access=no - -var webpage = require("webpage"); - -async_test(function () { - var page = webpage.create(); - var url = "file:///nonexistent"; - var rsErrorCalled = false; - - page.onResourceError = this.step_func(function (error) { - rsErrorCalled = true; - assert_equals(error.url, url); - assert_equals(error.errorCode, 301); - assert_equals(error.errorString, 'Protocol "file" is unknown'); - }); - - page.open(url, this.step_func_done(function () { - assert_is_true(rsErrorCalled); - })); - -}, "doesn't attempt to load a file: URL with --local-url-access=no"); diff --git a/third_party/phantomjs/test/module/webpage/local-urls-enabled-iframe.js b/third_party/phantomjs/test/module/webpage/local-urls-enabled-iframe.js deleted file mode 100644 index 76d05a5aade..00000000000 --- a/third_party/phantomjs/test/module/webpage/local-urls-enabled-iframe.js +++ /dev/null @@ -1,23 +0,0 @@ -//! unsupported -//! phantomjs: --web-security=no --local-url-access=yes - -var webpage = require("webpage"); - -async_test(function () { - var page = webpage.create(); - var url = TEST_HTTP_BASE + "iframe.html#file:///nonexistent"; - var rsErrorCalled = false; - - page.onResourceError = this.step_func(function (error) { - rsErrorCalled = true; - assert_equals(error.url, "file:///nonexistent"); - assert_equals(error.errorCode, 203); - assert_regexp_match(error.errorString, - /^Error opening\b.*?\bnonexistent:/); - }); - - page.open(url, this.step_func_done(function () { - assert_is_true(rsErrorCalled); - })); - -}, "attempts to load a file: URL in an iframe with --local-url-access=yes"); diff --git a/third_party/phantomjs/test/module/webpage/local-urls-enabled.js b/third_party/phantomjs/test/module/webpage/local-urls-enabled.js deleted file mode 100644 index b3f74bf5de5..00000000000 --- a/third_party/phantomjs/test/module/webpage/local-urls-enabled.js +++ /dev/null @@ -1,23 +0,0 @@ -//! unsupported -//! phantomjs: --local-url-access=yes - -var webpage = require("webpage"); - -async_test(function () { - var page = webpage.create(); - var url = "file:///nonexistent"; - var rsErrorCalled = false; - - page.onResourceError = this.step_func(function (error) { - rsErrorCalled = true; - assert_equals(error.url, url); - assert_equals(error.errorCode, 203); - assert_regexp_match(error.errorString, - /^Error opening\b.*?\bnonexistent:/); - }); - - page.open(url, this.step_func_done(function () { - assert_is_true(rsErrorCalled); - })); - -}, "attempts to load a file: URL with --local-url-access=yes"); diff --git a/third_party/phantomjs/test/module/webpage/long-running-javascript.js b/third_party/phantomjs/test/module/webpage/long-running-javascript.js deleted file mode 100644 index e8ce46a9c01..00000000000 --- a/third_party/phantomjs/test/module/webpage/long-running-javascript.js +++ /dev/null @@ -1,18 +0,0 @@ -async_test(function () { - var page = require('webpage').create(); - - page.onLongRunningScript = this.step_func_done(function () { - page.stopJavaScript(); - }); - - page.open(TEST_HTTP_BASE + "js-infinite-loop.html", - this.step_func(function (s) { - assert_equals(s, "success"); - })); - -}, "page.onLongRunningScript can interrupt scripts", { - skip: true // https://github.com/ariya/phantomjs/issues/13490 - // The underlying WebKit feature is so broken that an - // infinite loop in a _page_ script prevents timeouts - // from firing in the _controller_! -}); diff --git a/third_party/phantomjs/test/module/webpage/modify-header.js b/third_party/phantomjs/test/module/webpage/modify-header.js deleted file mode 100644 index b7ba7814a5f..00000000000 --- a/third_party/phantomjs/test/module/webpage/modify-header.js +++ /dev/null @@ -1,27 +0,0 @@ -async_test(function () { - var webpage = require('webpage'); - - // NOTE: HTTP header names are case-insensitive. Our test server - // returns the name in lowercase. - - var page = webpage.create(); - assert_type_of(page.customHeaders, 'object'); - assert_deep_equals(page.customHeaders, {}); - - page.customHeaders = { 'CustomHeader': 'CustomValue' }; - - page.onResourceRequested = this.step_func(function(requestData, request) { - assert_type_of(request.setHeader, 'function'); - request.setHeader('CustomHeader', 'ModifiedCustomValue'); - }); - - page.open(TEST_HTTP_BASE + 'echo', this.step_func_done(function (status) { - var json, headers; - assert_equals(status, 'success'); - json = JSON.parse(page.plainText); - headers = json.headers; - assert_own_property(headers, 'customheader'); - assert_equals(headers.customheader, 'ModifiedCustomValue'); - })); - -}, "modifying HTTP headers"); diff --git a/third_party/phantomjs/test/module/webpage/mouseclick-event.js b/third_party/phantomjs/test/module/webpage/mouseclick-event.js deleted file mode 100644 index 917c91a487b..00000000000 --- a/third_party/phantomjs/test/module/webpage/mouseclick-event.js +++ /dev/null @@ -1,38 +0,0 @@ -test(function () { - var page = require('webpage').create(); - - page.evaluate(function() { - window.addEventListener('mousedown', function(event) { - window.loggedEvent = window.loggedEvent || {}; - window.loggedEvent.mousedown = {clientX: event.clientX, clientY: event.clientY, shiftKey: event.shiftKey}; - }, false); - window.addEventListener('mouseup', function(event) { - window.loggedEvent = window.loggedEvent || {}; - window.loggedEvent.mouseup = {clientX: event.clientX, clientY: event.clientY, shiftKey: event.shiftKey}; - }, false); - }); - page.sendEvent('click', 42, 217); - - var event = page.evaluate(function() { - return window.loggedEvent; - }); - assert_equals(event.mouseup.clientX, 42); - assert_equals(event.mouseup.clientY, 217); - assert_equals(event.mousedown.clientX, 42); - assert_equals(event.mousedown.clientY, 217); - - // click with modifier key - page.evaluate(function() { - window.addEventListener('click', function(event) { - window.loggedEvent = window.loggedEvent || {}; - window.loggedEvent.click = {clientX: event.clientX, clientY: event.clientY, shiftKey: event.shiftKey}; - }, false); - }); - page.sendEvent('click', 100, 100, 'left', page.event.modifier.shift); - - var event = page.evaluate(function() { - return window.loggedEvent.click; - }); - assert_is_true(event.shiftKey); - -}, "mouse click events"); diff --git a/third_party/phantomjs/test/module/webpage/mousedoubleclick-event.js b/third_party/phantomjs/test/module/webpage/mousedoubleclick-event.js deleted file mode 100644 index f98dd2cd750..00000000000 --- a/third_party/phantomjs/test/module/webpage/mousedoubleclick-event.js +++ /dev/null @@ -1,30 +0,0 @@ -test(function () { - var page = require('webpage').create(); - - page.content = ''; - var point = page.evaluate(function () { - var el = document.querySelector('input'); - var rect = el.getBoundingClientRect(); - return { x: rect.left + Math.floor(rect.width / 2), y: rect.top + (rect.height / 2) }; - }); - page.sendEvent('doubleclick', point.x, point.y); - - var text = page.evaluate(function () { - return document.querySelector('input').value; - }); - assert_equals(text, "doubleclicked"); - - // click with modifier key - page.evaluate(function() { - window.addEventListener('dblclick', function(event) { - window.loggedEvent = window.loggedEvent || {}; - window.loggedEvent.dblclick = {clientX: event.clientX, clientY: event.clientY, shiftKey: event.shiftKey}; - }, false); - }); - page.sendEvent('doubleclick', 100, 100, 'left', page.event.modifier.shift); - - var event = page.evaluate(function() { - return window.loggedEvent.dblclick; - }); - assert_is_true(event.shiftKey); -}, "mouse double-click events"); diff --git a/third_party/phantomjs/test/module/webpage/mousedown-event.js b/third_party/phantomjs/test/module/webpage/mousedown-event.js deleted file mode 100644 index e79fa85af45..00000000000 --- a/third_party/phantomjs/test/module/webpage/mousedown-event.js +++ /dev/null @@ -1,26 +0,0 @@ -test(function () { - var page = require('webpage').create(); - - page.evaluate(function() { - window.addEventListener('mousedown', function(event) { - window.loggedEvent = window.loggedEvent || []; - window.loggedEvent.push({clientX: event.clientX, clientY: event.clientY, shiftKey: event.shiftKey}); - }, false); - }); - - page.sendEvent('mousedown', 42, 217); - var loggedEvent = page.evaluate(function() { - return window.loggedEvent; - }); - assert_equals(loggedEvent.length, 1); - assert_equals(loggedEvent[0].clientX, 42); - assert_equals(loggedEvent[0].clientY, 217); - - page.sendEvent('mousedown', 100, 100, 'left', page.event.modifier.shift); - loggedEvent = page.evaluate(function() { - return window.loggedEvent; - }); - assert_equals(loggedEvent.length, 2); - assert_is_true(loggedEvent[1].shiftKey); - -}, "mouse-down events"); diff --git a/third_party/phantomjs/test/module/webpage/mousemove-event.js b/third_party/phantomjs/test/module/webpage/mousemove-event.js deleted file mode 100644 index ece419a0a21..00000000000 --- a/third_party/phantomjs/test/module/webpage/mousemove-event.js +++ /dev/null @@ -1,18 +0,0 @@ -test(function () { - var page = require('webpage').create(); - - page.evaluate(function() { - window.addEventListener('mousemove', function(event) { - window.loggedEvent = window.loggedEvent || []; - window.loggedEvent.push({clientX: event.clientX, clientY: event.clientY}); - }, false); - }); - - page.sendEvent('mousemove', 14, 3); - var loggedEvent = page.evaluate(function() { - return window.loggedEvent; - }); - assert_equals(loggedEvent.length, 1); - assert_equals(loggedEvent[0].clientX, 14); - assert_equals(loggedEvent[0].clientY, 3); -}, "mouse-move events"); diff --git a/third_party/phantomjs/test/module/webpage/mouseup-event.js b/third_party/phantomjs/test/module/webpage/mouseup-event.js deleted file mode 100644 index e4b973821f5..00000000000 --- a/third_party/phantomjs/test/module/webpage/mouseup-event.js +++ /dev/null @@ -1,26 +0,0 @@ -test(function () { - var webpage = require('webpage'); - var page = webpage.create(); - - page.evaluate(function() { - window.addEventListener('mouseup', function(event) { - window.loggedEvent = window.loggedEvent || []; - window.loggedEvent.push({clientX: event.clientX, clientY: event.clientY, shiftKey: event.shiftKey}); - }, false); - }); - - page.sendEvent('mouseup', 42, 217); - var loggedEvent = page.evaluate(function() { - return window.loggedEvent; - }); - assert_equals(loggedEvent.length, 1); - assert_equals(loggedEvent[0].clientX, 42); - assert_equals(loggedEvent[0].clientY, 217); - - page.sendEvent('mouseup', 100, 100, 'left', page.event.modifier.shift); - loggedEvent = page.evaluate(function() { - return window.loggedEvent; - }); - assert_equals(loggedEvent.length, 2); - assert_is_true(loggedEvent[1].shiftKey); -}, "mouse-up events"); diff --git a/third_party/phantomjs/test/module/webpage/navigation.js b/third_party/phantomjs/test/module/webpage/navigation.js deleted file mode 100644 index 41c1509419f..00000000000 --- a/third_party/phantomjs/test/module/webpage/navigation.js +++ /dev/null @@ -1,31 +0,0 @@ -//! unsupported -async_test(function () { - var page = require("webpage").create(); - var url1 = TEST_HTTP_BASE + "navigation/index.html"; - var url2 = TEST_HTTP_BASE + "navigation/dest.html"; - - var onLoadFinished1 = this.step_func(function (status) { - assert_equals(status, "success"); - assert_equals(page.url, url1); - assert_equals(page.evaluate(function () { - return document.body.innerHTML; - }), "INDEX\n"); - - page.onLoadFinished = onLoadFinished2; - page.evaluate(function() { - window.location = "dest.html"; - }); - }); - - var onLoadFinished2 = this.step_func_done(function (status) { - assert_equals(status, "success"); - assert_equals(page.url, url2); - assert_equals(page.evaluate(function () { - return document.body.innerHTML; - }), "DEST\n"); - }); - - page.onLoadFinished = onLoadFinished1; - page.open(url1); - -}, "navigating to a relative URL using window.location"); diff --git a/third_party/phantomjs/test/module/webpage/no-plugin.js b/third_party/phantomjs/test/module/webpage/no-plugin.js deleted file mode 100644 index 1e563f2a9b9..00000000000 --- a/third_party/phantomjs/test/module/webpage/no-plugin.js +++ /dev/null @@ -1,19 +0,0 @@ -async_test(function () { - var webpage = require('webpage'); - var page = webpage.create(); - - var pluginLength = page.evaluate(function() { - return window.navigator.plugins.length; - }); - assert_equals(pluginLength, 0); - - page.open(TEST_HTTP_BASE + 'hello.html', - this.step_func_done(function (status) { - assert_equals(status, 'success'); - var pluginLength = page.evaluate(function() { - return window.navigator.plugins.length; - }); - assert_equals(pluginLength, 0); - })); - -}, "window.navigator.plugins is empty"); diff --git a/third_party/phantomjs/test/module/webpage/object.js b/third_party/phantomjs/test/module/webpage/object.js deleted file mode 100644 index d0920e28120..00000000000 --- a/third_party/phantomjs/test/module/webpage/object.js +++ /dev/null @@ -1,77 +0,0 @@ -//! unsupported -var webpage = require("webpage"); -var page = webpage.create(); - -test(function () { - assert_equals(webpage.create, WebPage); -}, "require('webpage').create === global WebPage"); - -test(function () { - assert_type_of(page, 'object'); - assert_not_equals(page, null); - - assert_equals(page.objectName, 'WebPage'); - assert_deep_equals(page.paperSize, {}); - - assert_not_equals(page.settings, null); - assert_not_equals(page.settings, {}); - - assert_type_of(page.canGoForward, 'boolean'); - assert_type_of(page.canGoBack, 'boolean'); - assert_type_of(page.clipRect, 'object'); - assert_type_of(page.content, 'string'); - assert_type_of(page.cookieJar, 'object'); - assert_type_of(page.cookies, 'object'); - assert_type_of(page.customHeaders, 'object'); - assert_type_of(page.event, 'object'); - assert_type_of(page.libraryPath, 'string'); - assert_type_of(page.loading, 'boolean'); - assert_type_of(page.loadingProgress, 'number'); - assert_type_of(page.navigationLocked, 'boolean'); - assert_type_of(page.offlineStoragePath, 'string'); - assert_type_of(page.offlineStorageQuota, 'number'); - assert_type_of(page.paperSize, 'object'); - assert_type_of(page.plainText, 'string'); - assert_type_of(page.scrollPosition, 'object'); - assert_type_of(page.settings, 'object'); - assert_type_of(page.title, 'string'); - assert_type_of(page.url, 'string'); - assert_type_of(page.frameUrl, 'string'); - assert_type_of(page.viewportSize, 'object'); - assert_type_of(page.windowName, 'string'); - assert_type_of(page.zoomFactor, 'number'); - -}, "page object properties"); - -test(function () { - assert_type_of(page.childFramesCount, 'function'); - assert_type_of(page.childFramesName, 'function'); - assert_type_of(page.clearMemoryCache, 'function'); - assert_type_of(page.close, 'function'); - assert_type_of(page.currentFrameName, 'function'); - assert_type_of(page.deleteLater, 'function'); - assert_type_of(page.destroyed, 'function'); - assert_type_of(page.evaluate, 'function'); - assert_type_of(page.initialized, 'function'); - assert_type_of(page.injectJs, 'function'); - assert_type_of(page.javaScriptAlertSent, 'function'); - assert_type_of(page.javaScriptConsoleMessageSent, 'function'); - assert_type_of(page.loadFinished, 'function'); - assert_type_of(page.loadStarted, 'function'); - assert_type_of(page.openUrl, 'function'); - assert_type_of(page.release, 'function'); - assert_type_of(page.render, 'function'); - assert_type_of(page.resourceError, 'function'); - assert_type_of(page.resourceReceived, 'function'); - assert_type_of(page.resourceRequested, 'function'); - assert_type_of(page.uploadFile, 'function'); - assert_type_of(page.sendEvent, 'function'); - assert_type_of(page.setContent, 'function'); - assert_type_of(page.switchToChildFrame, 'function'); - assert_type_of(page.switchToMainFrame, 'function'); - assert_type_of(page.switchToParentFrame, 'function'); - - assert_type_of(page.addCookie, 'function'); - assert_type_of(page.deleteCookie, 'function'); - assert_type_of(page.clearCookies, 'function'); -}, "page object methods"); diff --git a/third_party/phantomjs/test/module/webpage/on-confirm.js b/third_party/phantomjs/test/module/webpage/on-confirm.js deleted file mode 100644 index f4f6e31c872..00000000000 --- a/third_party/phantomjs/test/module/webpage/on-confirm.js +++ /dev/null @@ -1,33 +0,0 @@ -test(function () { - var page = require('webpage').create(); - - var msg = "message body", - result, - expected = true; - - assert_equals(page.onConfirm, undefined); - - var onConfirmTrue = function(msg) { - return true; - }; - page.onConfirm = onConfirmTrue; - assert_equals(page.onConfirm, onConfirmTrue); - - result = page.evaluate(function(m) { - return window.confirm(m); - }, msg); - - assert_equals(result, expected); - - var onConfirmFunc = function() { return !!"y"; }; - page.onConfirm = onConfirmFunc; - assert_equals(page.onConfirm, onConfirmFunc); - assert_not_equals(page.onConfirm, onConfirmTrue); - - page.onConfirm = null; - // Will only allow setting to a function value, so setting it to `null` returns `undefined` - assert_equals(page.onConfirm, undefined); - page.onConfirm = undefined; - assert_equals(page.onConfirm, undefined); - -}, "page.onConfirm"); diff --git a/third_party/phantomjs/test/module/webpage/on-error.js b/third_party/phantomjs/test/module/webpage/on-error.js deleted file mode 100644 index f5f892a7645..00000000000 --- a/third_party/phantomjs/test/module/webpage/on-error.js +++ /dev/null @@ -1,110 +0,0 @@ -//! unsupported -var webpage = require('webpage'); - -test(function () { - var page = webpage.create(); - assert_not_equals(page.onError, undefined); - - var onErrorFunc1 = function() { return !"x"; }; - page.onError = onErrorFunc1; - assert_equals(page.onError, onErrorFunc1); - - var onErrorFunc2 = function() { return !!"y"; }; - page.onError = onErrorFunc2; - assert_equals(page.onError, onErrorFunc2); - assert_not_equals(page.onError, onErrorFunc1); - - page.onError = null; - // Will only allow setting to a function value, so setting it to `null` returns `undefined` - assert_equals(page.onError, undefined); - page.onError = undefined; - assert_equals(page.onError, undefined); -}, "setting and clearing page.onError"); - -test(function () { - var page = webpage.create(); - var lastError = null; - page.onError = function(message) { lastError = message; }; - - page.evaluate(function() { referenceError2(); }); - assert_equals(lastError, "ReferenceError: Can't find variable: referenceError2"); - - page.evaluate(function() { throw "foo"; }); - assert_equals(lastError, "foo"); - - page.evaluate(function() { throw Error("foo"); }); - assert_equals(lastError, "Error: foo"); -}, "basic error reporting"); - -async_test(function () { - var page = webpage.create(); - var lastError = null; - page.onError = this.step_func_done(function(message) { - assert_equals(message, "ReferenceError: Can't find variable: referenceError"); - }); - - page.evaluate(function() { - setTimeout(function() { referenceError(); }, 0); - }); - -}, "error reporting from async events"); - -test(function () { - var page = webpage.create(); - var hadError = false; - page.onError = function() { hadError = true; }; - page.evaluate(function() { - window.caughtError = false; - - try { - referenceError(); - } catch(e) { - window.caughtError = true; - } - }); - - assert_equals(hadError, false); - assert_is_true(page.evaluate(function() { return window.caughtError; })); -}, "should not report errors that were caught"); - -function check_stack(message, stack) { - assert_equals(message, - "ReferenceError: Can't find variable: referenceError"); - - if (typeof stack === "string") { - var lines = stack.split("\n"); - assert_regexp_match(lines[0], RegExp("^bar@.*?"+helperBase+":7:23$")); - assert_regexp_match(lines[1], RegExp("^foo@.*?"+helperBase+":3:17$")); - } else { - assert_regexp_match(stack[0].file, RegExp(helperBase)); - assert_equals(stack[0].line, 7); - assert_equals(stack[0]["function"], "bar"); - - assert_regexp_match(stack[1].file, RegExp(helperBase)); - assert_equals(stack[1].line, 3); - assert_equals(stack[1]["function"], "foo"); - } -} - -var helperBase = "error-helper.js"; -var helperFile = "../../fixtures/" + helperBase; -assert_is_true(phantom.injectJs(helperFile)); - -test(function () { - try { - ErrorHelper.foo(); - } catch (e) { - check_stack(e.toString(), e.stack); - } -}, "stack trace accuracy (controller script)"); - -async_test(function () { - var page = webpage.create(); - page.libraryPath = phantom.libraryPath; - assert_is_true(page.injectJs(helperFile)); - - page.onError = this.step_func_done(check_stack); - page.evaluate(function () { - setTimeout(function () { ErrorHelper.foo(); }, 0); - }); -}, "stack trace accuracy (webpage script)"); diff --git a/third_party/phantomjs/test/module/webpage/on-initialized.js b/third_party/phantomjs/test/module/webpage/on-initialized.js deleted file mode 100644 index 3f8c735c118..00000000000 --- a/third_party/phantomjs/test/module/webpage/on-initialized.js +++ /dev/null @@ -1,21 +0,0 @@ -test(function () { - var page = require('webpage').create(); - - assert_equals(page.onInitialized, undefined); - - var onInitialized1 = function() { var x = "x"; }; - page.onInitialized = onInitialized1; - assert_equals(page.onInitialized, onInitialized1); - - var onInitialized2 = function() { var y = "y"; }; - page.onInitialized = onInitialized2; - assert_equals(page.onInitialized, onInitialized2); - assert_not_equals(page.onInitialized, onInitialized1); - - page.onInitialized = null; - // Will only allow setting to a function value, so setting it to `null` returns `undefined` - assert_equals(page.onInitialized, undefined); - - page.onInitialized = undefined; - assert_equals(page.onInitialized, undefined); -}, "page.onInitialized"); diff --git a/third_party/phantomjs/test/module/webpage/open.js b/third_party/phantomjs/test/module/webpage/open.js deleted file mode 100644 index ff7ef855a70..00000000000 --- a/third_party/phantomjs/test/module/webpage/open.js +++ /dev/null @@ -1,53 +0,0 @@ -async_test(function () { - var webpage = require('webpage'); - var page = webpage.create(); - assert_type_of(page, 'object'); - - page.onResourceReceived = this.step_func(function (resource) { - assert_equals(resource.status, 200); - }); - page.open(TEST_HTTP_BASE + 'hello.html', - this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_type_of(page.title, 'string'); - assert_equals(page.title, 'Hello'); - assert_type_of(page.plainText, 'string'); - assert_equals(page.plainText, 'Hello, world!'); - })); -}, "opening a webpage"); - -async_test(function () { - var webpage = require('webpage'); - var page = webpage.create(); - - // both onResourceReceived and onResourceError should be called - page.onResourceReceived = this.step_func(function (resource) { - assert_equals(resource.status, 401); - }); - page.onResourceError = this.step_func(function (err) { - assert_equals(err.errorString, "Operation canceled"); - }); - - page.open(TEST_HTTP_BASE + 'status?status=401' + - '&WWW-Authenticate=Basic%20realm%3D%22PhantomJS%20test%22', - this.step_func_done(function (status) { - assert_equals(status, 'fail'); - })); - -}, "proper handling of HTTP error responses", {/* unsupported */expected_fail: true}); - -async_test(function () { - var webpage = require('webpage'); - var page = webpage.create(); - - page.settings.resourceTimeout = 1; - - // This is all you have to do to assert that a hook does get called. - page.onResourceTimeout = this.step_func(function(){}); - - page.open(TEST_HTTP_BASE + "delay?5", - this.step_func_done(function (s) { - assert_not_equals(s, "success"); - })); - -}, "onResourceTimeout fires after resourceTimeout ms", {/* unsupported */expected_fail: true}); diff --git a/third_party/phantomjs/test/module/webpage/postdata.js b/third_party/phantomjs/test/module/webpage/postdata.js deleted file mode 100644 index dd3d725fa92..00000000000 --- a/third_party/phantomjs/test/module/webpage/postdata.js +++ /dev/null @@ -1,47 +0,0 @@ -//! unsupported -function validate_echo_response (status, page, postdata) { - assert_equals(status, 'success'); - - var desc = JSON.parse(page.plainText); - assert_equals(desc.command, "POST"); - assert_equals(desc.postdata, postdata); - assert_equals(desc.headers['content-type'], - 'application/x-www-form-urlencoded'); -} - -async_test(function () { - - var utfString = '안녕'; - var openOptions = { - operation: 'POST', - data: utfString, - encoding: 'utf8' - }; - var pageOptions = { - onLoadFinished: this.step_func_done(function(status) { - validate_echo_response(status, page, utfString); - }) - }; - var page = new WebPage(pageOptions); - page.openUrl(TEST_HTTP_BASE + "echo", openOptions, {}); - - -}, "processing request body for POST"); - -async_test(function () { - - var postdata = "ab=cd"; - var pageOptions = { - onResourceRequested: this.step_func(function (request) { - assert_equals(request.postData, postdata); - }), - onLoadFinished: this.step_func_done(function (status) { - validate_echo_response(status, page, postdata); - }) - }; - - var page = new WebPage(pageOptions); - page.open(TEST_HTTP_BASE + "echo", 'post', postdata); - - -}, "POST data is available in onResourceRequested"); diff --git a/third_party/phantomjs/test/module/webpage/prompt.js b/third_party/phantomjs/test/module/webpage/prompt.js deleted file mode 100644 index d1f099e4ada..00000000000 --- a/third_party/phantomjs/test/module/webpage/prompt.js +++ /dev/null @@ -1,16 +0,0 @@ -test(function () { - var page = require('webpage').create(); - - var msg = "message", - value = "value", - result, - expected = "extra-value"; - page.onPrompt = function(msg, value) { - return "extra-"+value; - }; - result = page.evaluate(function(m, v) { - return window.prompt(m, v); - }, msg, value); - - assert_equals(result, expected); -}, "page.onPrompt"); diff --git a/third_party/phantomjs/test/module/webpage/remove-header.js b/third_party/phantomjs/test/module/webpage/remove-header.js deleted file mode 100644 index 900a870fe2d..00000000000 --- a/third_party/phantomjs/test/module/webpage/remove-header.js +++ /dev/null @@ -1,26 +0,0 @@ -var webpage = require('webpage'); - -// NOTE: HTTP header names are case-insensitive. Our test server -// returns the name in lowercase. -async_test(function () { - var page = webpage.create(); - assert_type_of(page.customHeaders, 'object'); - assert_deep_equals(page.customHeaders, {}); - - page.customHeaders = { 'CustomHeader': 'ModifiedCustomValue' }; - - page.onResourceRequested = this.step_func(function(requestData, request) { - assert_type_of(request.setHeader, 'function'); - request.setHeader('CustomHeader', null); - }); - - page.open(TEST_HTTP_BASE + 'echo', - this.step_func_done(function (status) { - var json, headers; - assert_equals(status, 'success'); - json = JSON.parse(page.plainText); - headers = json.headers; - assert_no_property(headers, 'customheader'); - assert_no_property(headers, 'CustomHeader'); - })); -}); diff --git a/third_party/phantomjs/test/module/webpage/render.js b/third_party/phantomjs/test/module/webpage/render.js deleted file mode 100644 index 7a1fb4343fe..00000000000 --- a/third_party/phantomjs/test/module/webpage/render.js +++ /dev/null @@ -1,68 +0,0 @@ -//! unsupported -var fs = require("fs"); -var system = require("system"); -var webpage = require("webpage"); -var renders = require("./renders"); - -function clean_pdf(data) { - // FIXME: This is not nearly enough normalization. - data = data.replace(/\/(Title|Creator|Producer|CreationDate) \([^\n]*\)/g, "/$1 ()"); - data = data.replace(/\nxref\n[0-9 nf\n]+trailer\b/, "\ntrailer"); - data = data.replace(/\nstartxref\n[0-9]+\n%%EOF\n/, "\n"); - return data; -} - -function render_test(format, option) { - var opt = option || {}; - var scratch = "temp_render"; - if (!opt.format) { - scratch += "."; - scratch += format; - } - var expect_content = renders.get(format, opt.quality || ""); - var p = webpage.create(); - - p.paperSize = { width: '300px', height: '300px', border: '0px' }; - p.clipRect = { top: 0, left: 0, width: 300, height: 300}; - p.viewportSize = { width: 300, height: 300}; - - p.open(TEST_HTTP_BASE + "render/", this.step_func_done(function (status) { - p.render(scratch, opt); - this.add_cleanup(function () { fs.remove(scratch); }); - var content = fs.read(scratch, "b"); - - // expected variation in PDF output - if (format === "pdf") { - content = clean_pdf(content); - expect_content = clean_pdf(expect_content); - } - - // Don't dump entire images to the log on failure. - assert_is_true(content === expect_content); - })); -} - -[ - ["PDF", "pdf", {}], - ["PDF (format option)", "pdf", {format: "pdf"}], - ["PNG", "png", {}], - ["PNG (format option)", "png", {format: "png"}], - ["JPEG", "jpg", {}], - ["JPEG (format option)", "jpg", {format: "jpg"}], - ["JPEG (quality option)", "jpg", {quality: 50}], - ["JPEG (format and quality options)", "jpg", {format: "jpg", quality: 50}], -] -.forEach(function (arr) { - var label = arr[0]; - var format = arr[1]; - var opt = arr[2]; - var props = {}; - - // All tests fail on Linux. All tests except JPG fail on Mac. - // Currently unknown which tests fail on Windows. - if (format !== "jpg" || system.os.name !== "mac") - props.expected_fail = true; - - async_test(function () { render_test.call(this, format, opt); }, - label, props); -}); diff --git a/third_party/phantomjs/test/module/webpage/renders/index.js b/third_party/phantomjs/test/module/webpage/renders/index.js deleted file mode 100644 index 47e83b6a7ea..00000000000 --- a/third_party/phantomjs/test/module/webpage/renders/index.js +++ /dev/null @@ -1,7 +0,0 @@ -var fs = require("fs"); - -exports.get = function get(format, quality) { - var expect_file = fs.join( - module.dirname, "test" + quality + "." + format); - return fs.read(expect_file, "b"); -}; diff --git a/third_party/phantomjs/test/module/webpage/renders/test.jpg b/third_party/phantomjs/test/module/webpage/renders/test.jpg deleted file mode 100644 index b597dba47fbe3eff8feea07176102bef6888688f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6818 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 diff --git a/third_party/phantomjs/test/module/webpage/renders/test.pdf b/third_party/phantomjs/test/module/webpage/renders/test.pdf deleted file mode 100644 index b1beecd1d73546632f913a3edb920255f0b96065..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27123 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

d2Ai7B! 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

N`F+PMZVS7mm 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 JS?83{1OR1~IrIPk diff --git a/third_party/phantomjs/test/module/webpage/renders/test50.jpg b/third_party/phantomjs/test/module/webpage/renders/test50.jpg deleted file mode 100644 index a3e04420682ef5eb26d00dc270a5de293b0ecab3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4930 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 diff --git a/third_party/phantomjs/test/module/webpage/repaint-requested.js b/third_party/phantomjs/test/module/webpage/repaint-requested.js deleted file mode 100644 index bb3bb355d5e..00000000000 --- a/third_party/phantomjs/test/module/webpage/repaint-requested.js +++ /dev/null @@ -1,20 +0,0 @@ -//! unsupported -var webpage = require('webpage'); - -async_test(function () { - var page = webpage.create(); - var requestCount = 0; - - page.onRepaintRequested = this.step_func(function(x, y, w, h) { - if ((w > 0) && (h > 0)) { - ++requestCount; - } - }); - - page.open(TEST_HTTP_BASE + 'hello.html', - this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_greater_than(requestCount, 0); - })); - -}, "onRepaintRequested should be called at least once for each page load"); diff --git a/third_party/phantomjs/test/module/webpage/resource-received-error.js b/third_party/phantomjs/test/module/webpage/resource-received-error.js deleted file mode 100644 index dae581e1115..00000000000 --- a/third_party/phantomjs/test/module/webpage/resource-received-error.js +++ /dev/null @@ -1,33 +0,0 @@ -//! unsupported -var webpage = require('webpage'); - -async_test(function () { - var page = webpage.create(); - var url = TEST_HTTP_BASE + 'status?400'; - var startStage = 0; - var endStage = 0; - var errors = 0; - - page.onResourceReceived = this.step_func(function (resource) { - assert_equals(resource.url, url); - if (resource.stage === 'start') { - ++startStage; - } - if (resource.stage === 'end') { - ++endStage; - } - }); - page.onResourceError = this.step_func(function (error) { - assert_equals(error.url, url); - assert_equals(error.status, 400); - ++errors; - }); - - page.open(url, this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_equals(startStage, 1); - assert_equals(endStage, 1); - assert_equals(errors, 1); - })); - -}, "onResourceReceived should still be called for failed requests"); diff --git a/third_party/phantomjs/test/module/webpage/resource-request-error.js b/third_party/phantomjs/test/module/webpage/resource-request-error.js deleted file mode 100644 index 0f150362392..00000000000 --- a/third_party/phantomjs/test/module/webpage/resource-request-error.js +++ /dev/null @@ -1,27 +0,0 @@ -//! unsupported -var webpage = require('webpage'); - -async_test(function () { - var page = webpage.create(); - var resourceErrors = 0; - - page.onResourceError = this.step_func(function(err) { - ++resourceErrors; - - assert_equals(err.status, 404); - assert_equals(err.statusText, 'File not found'); - assert_equals(err.url, TEST_HTTP_BASE + 'notExist.png'); - assert_equals(err.errorCode, 203); - assert_regexp_match(err.errorString, - /Error downloading http:\/\/localhost:[0-9]+\/notExist\.png/); - assert_regexp_match(err.errorString, - /server replied: File not found/); - }); - - page.open(TEST_HTTP_BASE + 'missing-img.html', - this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_equals(resourceErrors, 1); - })); - -}, "resourceError basic functionality"); diff --git a/third_party/phantomjs/test/module/webpage/scroll-position.js b/third_party/phantomjs/test/module/webpage/scroll-position.js deleted file mode 100644 index a1550531a14..00000000000 --- a/third_party/phantomjs/test/module/webpage/scroll-position.js +++ /dev/null @@ -1,18 +0,0 @@ -//! unsupported -var webpage = require('webpage'); - -test(function () { - var defaultPage = webpage.create(); - assert_deep_equals(defaultPage.scrollPosition, {left:0,top:0}); -}, "default scroll position"); - -test(function () { - var options = { - scrollPosition: { - left: 1, - top: 2 - } - }; - var customPage = webpage.create(options); - assert_deep_equals(customPage.scrollPosition, options.scrollPosition); -}, "custom scroll position"); diff --git a/third_party/phantomjs/test/module/webpage/set-content.js b/third_party/phantomjs/test/module/webpage/set-content.js deleted file mode 100644 index 52e823368c1..00000000000 --- a/third_party/phantomjs/test/module/webpage/set-content.js +++ /dev/null @@ -1,20 +0,0 @@ -//! unsupported -var webpage = require('webpage'); - -test(function () { - var page = webpage.create(); - var expectedContent = '

Test div
'; - var expectedLocation = 'http://www.phantomjs.org/'; - page.setContent(expectedContent, expectedLocation); - - var actualContent = page.evaluate(function() { - return document.documentElement.textContent; - }); - assert_equals(actualContent, 'Test div'); - - var actualLocation = page.evaluate(function() { - return window.location.href; - }); - assert_equals(actualLocation, expectedLocation); - -}, "manually set page content and location"); diff --git a/third_party/phantomjs/test/module/webpage/subwindows.js b/third_party/phantomjs/test/module/webpage/subwindows.js deleted file mode 100644 index 392b664d6a8..00000000000 --- a/third_party/phantomjs/test/module/webpage/subwindows.js +++ /dev/null @@ -1,130 +0,0 @@ -//! unsupported -async_test(function () { - var test = this; - var top = require('webpage').create(); - var pages_created = 0; - var expect_to_close = null; - var after_close = null; - - top.onPageCreated = function (page) { - pages_created++; - page.onClosing = test.step_func(function (page) { - assert_equals(page.windowName, expect_to_close); - setTimeout(after_close, 0); - }); - if (pages_created === 3) { - setTimeout(after_open_3, 0); - } - }; - - var after_open_3 = test.step_func(function () { - assert_equals(top.pages.length, 3); - assert_deep_equals(top.pagesWindowName, ["A", "B", "C"]); - - after_close = after_close_1; - expect_to_close = "A"; - top.evaluate(function () { window.wA.close(); }); - }); - - var after_close_1 = test.step_func(function () { - assert_equals(top.pages.length, 2); - assert_deep_equals(top.pagesWindowName, ["B", "C"]); - - - var pageB = top.getPage("B"); - assert_not_equals(pageB, null); - - after_close = after_close_2; - expect_to_close = "B"; - pageB.close(); - }); - - var after_close_2 = test.step_func(function () { - assert_equals(top.pages.length, 1); - assert_deep_equals(top.pagesWindowName, ["C"]); - - // Must close C as well, because its onclosing hook is a step - // function that hasn't run yet. - after_close = test.step_func_done(); - expect_to_close = "C"; - top.close(); - }); - - top.evaluate(function () { - var w = window; - w.wA = w.open("data:text/html,%3Ctitle%3Epage%20A%3C/title%3E", "A"); - w.wB = w.open("data:text/html,%3Ctitle%3Epage%20B%3C/title%3E", "B"); - w.wC = w.open("data:text/html,%3Ctitle%3Epage%20C%3C/title%3E", "C"); - }); - -}, "pages and pagesWindowName arrays; onPageCreated and onClosing hooks"); - -async_test(function () { - var test = this; - var pages_opened = 1, pages_closed = 0; - var top = require("webpage").create(); - - var onPageCreated = test.step_func(function onPageCreated(page) { - pages_opened++; - page.onPageCreated = onPageCreated; - page.onClosing = onClosing; - if (pages_opened === 4) { - setTimeout(after_open_4, 0); - } - }); - var onClosing = test.step_func(function onClosing(page) { - pages_closed++; - if (pages_opened === pages_closed) { - test.done(); - } - }); - - // This can't be inlined into onPageCreated because - // pagesWindowName is not quite up-to-date when that hook fires. - var after_open_4 = test.step_func(function () { - assert_equals(top.pages.length, 3); - assert_deep_equals(top.pagesWindowName, ["A", "B", "C"]); - top.close(); - }); - - top.onPageCreated = onPageCreated; - top.onClosing = onClosing; - - top.evaluate(function () { - var w = window; - w.wA = w.open("data:text/html,%3Ctitle%3Epage%20A%3C/title%3E", "A"); - w.wB = w.open("data:text/html,%3Ctitle%3Epage%20B%3C/title%3E", "B"); - w.wC = w.open("data:text/html,%3Ctitle%3Epage%20C%3C/title%3E", "C"); - }); - -}, "close subwindows when parent page is closed (default behavior)"); - -async_test(function () { - var test = this; - var pages_opened = 1; - var top = require("webpage").create(); - top.ownsPages = false; - - var onPageCreated = test.step_func(function onPageCreated(page) { - pages_opened++; - page.onPageCreated = onPageCreated; - page.onClosing = test.unreached_func(); - if (pages_opened === 4) { - assert_equals(top.pages.length, 0); - assert_deep_equals(top.pagesWindowName, []); - top.close(); - } - }); - top.onPageCreated = onPageCreated; - - top.onClosing = test.step_func(function onTopClosing(page) { - setTimeout(function () { test.done(); }, 50); - }); - - top.evaluate(function () { - var w = window; - w.wA = w.open("data:text/html,%3Ctitle%3Epage%20A%3C/title%3E", "A"); - w.wB = w.open("data:text/html,%3Ctitle%3Epage%20B%3C/title%3E", "B"); - w.wC = w.open("data:text/html,%3Ctitle%3Epage%20C%3C/title%3E", "C"); - }); -}, "don't close subwindows when parent page is closed (ownsPages=false)"); diff --git a/third_party/phantomjs/test/module/webpage/url-encoding.js b/third_party/phantomjs/test/module/webpage/url-encoding.js deleted file mode 100644 index d0026dc40cc..00000000000 --- a/third_party/phantomjs/test/module/webpage/url-encoding.js +++ /dev/null @@ -1,134 +0,0 @@ -//! unsupported -var webpage = require('webpage'); - -// Many of the URLs used in this file contain text encoded in -// Shift_JIS, so that they will not round-trip correctly if -// misinterpreted at any point as UTF-8 (and thus, the test will -// fail). See www/url-encoding.py for Unicode equivalents. - -function URL(path) { - return TEST_HTTP_BASE + 'url-encoding?' + path; -} - -async_test(function () { - var p = webpage.create(); - p.open(URL('/'), this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_equals(p.url, URL('/%83y%81[%83W')); - assert_equals(p.plainText, 'PASS'); - })); - -}, "page.url"); - -async_test(function () { - var p = webpage.create(); - p.open(URL('/f'), this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_equals(p.url, URL('/f')); - assert_equals(p.framesCount, 2); - - assert_is_true(p.switchToFrame('a')); - assert_equals(p.frameUrl, URL('/%98g')); - assert_equals(p.framePlainText, 'PASS'); - - assert_is_true(p.switchToParentFrame()); - assert_is_true(p.switchToFrame('b')); - assert_equals(p.frameUrl, URL('/%95s%96%D1%82%C8%98_%91%88')); - assert_equals(p.framePlainText, 'FRAME'); - })); - -}, "page.frameUrl"); - -async_test(function () { - var p = webpage.create(); - var n = 0; - var expectedUrls = [ URL('/'), URL('/%83y%81[%83W') ]; - - p.onNavigationRequested = this.step_func(function (url, ty, will, main) { - assert_equals(url, expectedUrls[n]); - assert_equals(ty, 'Other'); - assert_is_true(will); - assert_is_true(main); - n++; - - if (n === expectedUrls.length) { - p.onNavigationRequested = this.unreached_func(); - } - }); - p.open(URL('/'), this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_equals(n, expectedUrls.length); - assert_equals(p.plainText, 'PASS'); - })); - -}, "arguments to onNavigationRequested"); - -async_test(function () { - var p = webpage.create(); - var n = 0; - var n_req = 0; - var n_recv = 0; - var expectedUrls = [ URL('/r'), URL('/%8F%91') ]; - var receivedUrls = {}; - - p.onResourceRequested = this.step_func(function (req, nr) { - assert_equals(req.url, expectedUrls[n_req]); - n_req++; - if (n_req === expectedUrls.length) { - p.onResourceRequested = this.unreached_func(); - } - }); - - p.onResourceReceived = this.step_func(function (resp) { - // This function may be called more than once per URL. - if (receivedUrls.hasOwnProperty(resp.url)) - return; - receivedUrls[resp.url] = true; - assert_equals(resp.url, expectedUrls[n_recv]); - n_recv++; - }); - - p.open(URL('/r'), this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_equals(n_req, expectedUrls.length); - assert_equals(n_recv, expectedUrls.length); - assert_equals(p.plainText, 'PASS'); - })); - -}, "arguments to onResourceRequested and onResourceReceived"); - -async_test(function () { - var p = webpage.create(); - p.settings.resourceTimeout = 100; - - var n_timeout = 0; - var n_error = 0; - var expectedUrls_timeout = [ URL('/%89i%8Bv') ]; - // the error hook is called for timeouts as well - var expectedUrls_error = [ URL('/%8C%CC%8F%E1'), URL('/%89i%8Bv') ]; - - p.onResourceTimeout = this.step_func(function (req) { - assert_equals(req.url, expectedUrls_timeout[n_timeout]); - n_timeout++; - - if (n_timeout === expectedUrls_timeout.length) { - p.onResourceTimeout = this.unreached_func(); - } - }); - - p.onResourceError = this.step_func(function (err) { - assert_equals(err.url, expectedUrls_error[n_error]); - n_error++; - - if (n_error === expectedUrls_error.length) { - p.onResourceTimeout = this.unreached_func(); - } - }); - - p.open(URL("/re"), this.step_func_done(function (status) { - assert_equals(status, 'success'); - assert_equals(n_timeout, expectedUrls_timeout.length); - assert_equals(n_error, expectedUrls_error.length); - })); - -}, " arguments to onResourceError and onResourceTimeout"); diff --git a/third_party/phantomjs/test/module/webpage/user-agent.js b/third_party/phantomjs/test/module/webpage/user-agent.js deleted file mode 100644 index 1dc1962ea8e..00000000000 --- a/third_party/phantomjs/test/module/webpage/user-agent.js +++ /dev/null @@ -1,22 +0,0 @@ -var webpage = require('webpage'); - -async_test(function () { - var ua = 'PHANTOMJS-TEST-USER-AGENT'; - var page = webpage.create({ - settings: { - userAgent: ua - } - }); - - assert_equals(page.settings.userAgent, ua); - - page.open(TEST_HTTP_BASE + 'user-agent.html', - this.step_func_done(function (status) { - assert_equals(status, 'success'); - var agent = page.evaluate(function() { - return document.getElementById('ua').textContent; - }); - assert_equals(agent, ua); - })); - -}, "load a page with a custom user agent"); diff --git a/third_party/phantomjs/test/module/webpage/viewport-size.js b/third_party/phantomjs/test/module/webpage/viewport-size.js deleted file mode 100644 index dc2412c2793..00000000000 --- a/third_party/phantomjs/test/module/webpage/viewport-size.js +++ /dev/null @@ -1,17 +0,0 @@ -var webpage = require('webpage'); - -test(function () { - var defaultPage = webpage.create(); - assert_deep_equals(defaultPage.viewportSize, {height:300,width:400}); -}, "default viewport size"); - -test(function () { - var options = { - viewportSize: { - height: 100, - width: 200 - } - }; - var customPage = webpage.create(options); - assert_deep_equals(customPage.viewportSize, options.viewportSize); -}, "custom viewport size"); diff --git a/third_party/phantomjs/test/module/webpage/window.js b/third_party/phantomjs/test/module/webpage/window.js deleted file mode 100644 index c8ddaaf63ce..00000000000 --- a/third_party/phantomjs/test/module/webpage/window.js +++ /dev/null @@ -1,4 +0,0 @@ -test(function () { - assert_own_property(window, 'WebPage'); - assert_type_of(window.WebPage, 'function'); -}, "window.WebPage global property"); diff --git a/third_party/phantomjs/test/module/webpage/zoom-factor.js b/third_party/phantomjs/test/module/webpage/zoom-factor.js deleted file mode 100644 index f8f447e4eca..00000000000 --- a/third_party/phantomjs/test/module/webpage/zoom-factor.js +++ /dev/null @@ -1,18 +0,0 @@ -//! unsupported -var webpage = require('webpage'); - -test(function () { - var page = webpage.create(); - assert_equals(page.zoomFactor, 1.0); - - page.zoomFactor = 1.5; - assert_equals(page.zoomFactor, 1.5); - - page.zoomFactor = 2.0; - assert_equals(page.zoomFactor, 2.0); - - page.zoomFactor = 0.5; - assert_equals(page.zoomFactor, 0.5); -}, "page.zoomFactor"); - -// TODO: render using zoomFactor != 1 and check the result diff --git a/third_party/phantomjs/test/module/webserver/basics.js b/third_party/phantomjs/test/module/webserver/basics.js deleted file mode 100644 index 4f124cc4202..00000000000 --- a/third_party/phantomjs/test/module/webserver/basics.js +++ /dev/null @@ -1,25 +0,0 @@ -test(function () { - assert_no_property(window, "WebServer", - "WebServer constructor should not be global"); - - var WebServer = require("webserver").create; - assert_type_of(WebServer, "function"); - -}, "WebServer constructor"); - -test(function () { - var server = require("webserver").create(); - - assert_not_equals(server, null); - assert_type_of(server, "object"); - assert_equals(server.objectName, "WebServer"); - - assert_own_property(server, "port"); - assert_type_of(server.port, "string"); - assert_equals(server.port, ""); - - assert_type_of(server.listenOnPort, "function"); - assert_type_of(server.newRequest, "function"); - assert_type_of(server.close, "function"); - -}, "WebServer object properties"); diff --git a/third_party/phantomjs/test/module/webserver/requests.js b/third_party/phantomjs/test/module/webserver/requests.js deleted file mode 100644 index f8d4e8b9f1f..00000000000 --- a/third_party/phantomjs/test/module/webserver/requests.js +++ /dev/null @@ -1,179 +0,0 @@ -var server, port, request_cb; -setup(function () { - server = require("webserver").create(); - - // Should be unable to listen on port 1 (FIXME: this might succeed if - // the test suite is being run with root privileges). - assert_is_false(server.listen(1, function () {})); - assert_equals(server.port, ""); - - // Find an unused port in the 1024--32767 range on which to run the - // rest of the tests. The function in "request_cb" will be called - // for each request; it is set appropriately by each test case. - for (var i = 1024; i < 32768; i++) { - if (server.listen(i, function(rq,rs){return request_cb(rq,rs);})) { - assert_equals(server.port, i.toString()); - port = server.port; - return; - } - } - assert_unreached("unable to find a free TCP port for server tests"); -}, - { "test_timeout": 3000 }); - -function arm_check_request (test, expected_postdata, expected_bindata, - expected_mimetype) { - request_cb = test.step_func(function check_request (request, response) { - try { - assert_type_of(request, "object"); - assert_own_property(request, "url"); - assert_own_property(request, "method"); - assert_own_property(request, "httpVersion"); - assert_own_property(request, "headers"); - assert_type_of(request.headers, "object"); - - assert_type_of(response, "object"); - assert_own_property(response, "statusCode"); - assert_own_property(response, "headers"); - assert_type_of(response.setHeaders, "function"); - assert_type_of(response.setHeader, "function"); - assert_type_of(response.header, "function"); - assert_type_of(response.write, "function"); - assert_type_of(response.writeHead, "function"); - - if (expected_postdata !== false) { - assert_equals(request.method, "POST"); - assert_own_property(request, "post"); - if (request.headers["Content-Type"] === - "application/x-www-form-urlencoded") { - assert_own_property(request, "postRaw"); - assert_type_of(request.postRaw, "string"); - assert_type_of(request.post, "object"); - assert_deep_equals(request.post, expected_postdata); - } else { - assert_no_property(request, "postRaw"); - assert_type_of(request.post, "string"); - assert_not_equals(request.post, expected_postdata); - } - } - - response.setHeader("X-Request-URL", request.url); - - if (expected_bindata !== false) { - response.setEncoding("binary"); - response.setHeader("Content-Type", expected_mimetype); - response.write(expected_bindata); - } else { - response.write("request handled"); - } - } finally { - response.close(); - request_cb = test.unreached_func(); - } - }); -} - -async_test(function () { - var page = require("webpage").create(); - var url = "http://localhost:"+port+"/foo/bar.php?asdf=true"; - - arm_check_request(this, false, false); - page.open(url, this.step_func_done(function (status) { - assert_equals(status, "success"); - assert_equals(page.plainText, "request handled"); - })); - -}, "basic request handling"); - -async_test(function () { - var page = require("webpage").create(); - var url = "http://localhost:"+port+"/%95s%96%D1%82%C8%98_%91%88"; - var already = false; - - arm_check_request(this, false, false); - page.onResourceReceived = this.step_func(function (resp) { - if (already) return; - already = true; - - var found = false; - resp.headers.forEach(function (hdr) { - if (hdr.name.toLowerCase() === "x-request-url") { - assert_equals(hdr.value, "/%95s%96%D1%82%C8%98_%91%88"); - found = true; - } - }); - assert_is_true(found); - }); - - page.open(url, this.step_func_done(function (status) { - assert_equals(status, "success"); - assert_equals(page.plainText, "request handled"); - })); - -}, "round-trip of URLs containing encoded non-Unicode text"); - -async_test(function () { - var page = require("webpage").create(); - var url = "http://localhost:"+port+"/foo/bar.txt?asdf=true"; - - arm_check_request(this, - {"answer" : "42", "universe" : "expanding"}, false); - - page.open(url, "post", "universe=expanding&answer=42", - { "Content-Type" : "application/x-www-form-urlencoded" }, - this.step_func_done(function (status) { - assert_equals(status, "success"); - assert_equals(page.plainText, "request handled"); - })); - -}, "handling POST with application/x-www-form-urlencoded data", { - expected_fail: true /* unsupported */ -}); - -async_test(function () { - var page = require("webpage").create(); - var url = "http://localhost:"+port+"/foo/bar.txt?asdf=true"; - - arm_check_request(this, - {"answer" : "42", "universe" : "expanding"}, false); - - page.open(url, "post", "universe=expanding&answer=42", - { "Content-Type" : "application/json;charset=UTF-8" }, - this.step_func_done(function (status) { - assert_equals(status, "success"); - assert_equals(page.plainText, "request handled"); - })); - -}, "handling POST with ill-formed application/json data", { - expected_fail: true /* unsupported */ -}); - -async_test(function () { - var page = require("webpage").create(); - var url = "http://localhost:"+port+"/"; - var fs = require("fs"); - var png = fs.read(fs.join(phantom.libraryPath, - "../../www/phantomjs.png"), "b"); - - arm_check_request(this, false, png, "image/png"); - page.open(url, "get", this.step_func_done(function (status) { - assert_equals(status, "success"); - function checkImg() { - var img = document.querySelector("img"); - if (img) { - return { w: img.width, h: img.height }; - } else { - return {}; - } - } - // XFAIL: image doesn't load properly and we receive the dimensions of - // the ?-in-a-box placeholder - assert_deep_equals(page.evaluate(checkImg), { w: 200, h: 200 }); - })); - -}, "handling binary data", { - skip: true, // crash: https://github.com/ariya/phantomjs/issues/13461 - expected_fail: true // received image is corrupt: - // https://github.com/ariya/phantomjs/issues/13026 - // and perhaps others -}); diff --git a/third_party/phantomjs/test/node_modules/dummy_exposed.js b/third_party/phantomjs/test/node_modules/dummy_exposed.js deleted file mode 100644 index 143519bddd5..00000000000 --- a/third_party/phantomjs/test/node_modules/dummy_exposed.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = module; diff --git a/third_party/phantomjs/test/node_modules/dummy_file.js b/third_party/phantomjs/test/node_modules/dummy_file.js deleted file mode 100644 index a18d8a9185a..00000000000 --- a/third_party/phantomjs/test/node_modules/dummy_file.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'spec/node_modules/dummy_file'; diff --git a/third_party/phantomjs/test/node_modules/dummy_file2.js b/third_party/phantomjs/test/node_modules/dummy_file2.js deleted file mode 100644 index 77e02ec1ebf..00000000000 --- a/third_party/phantomjs/test/node_modules/dummy_file2.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = 'spec/node_modules/dummy_file2'; diff --git a/third_party/phantomjs/test/regression/README b/third_party/phantomjs/test/regression/README deleted file mode 100644 index 2e8394c9e3d..00000000000 --- a/third_party/phantomjs/test/regression/README +++ /dev/null @@ -1,3 +0,0 @@ -Tests in this directory are named for their bug number. -pjs-NNNN corresponds to https://github.com/ariya/phantomjs/issues/NNNN. -webkit-NNNN corresponds to ​https://bugs.webkit.org/show_bug.cgi?id=NNNN. diff --git a/third_party/phantomjs/test/regression/pjs-10690.js b/third_party/phantomjs/test/regression/pjs-10690.js deleted file mode 100644 index 7e45c82d45e..00000000000 --- a/third_party/phantomjs/test/regression/pjs-10690.js +++ /dev/null @@ -1,14 +0,0 @@ -// Issue 10690: the second page load used to crash on OSX. - -var url = TEST_HTTP_BASE + 'regression/pjs-10690/index.html'; -function do_test() { - var page = require('webpage').create(); - - page.open(url, this.step_func_done (function (status) { - assert_equals(status, "success"); - page.release(); - })); -} - -async_test(do_test, "load a page with a downloadable font, once"); -async_test(do_test, "load a page with a downloadable font, again"); diff --git a/third_party/phantomjs/test/regression/pjs-12482.js b/third_party/phantomjs/test/regression/pjs-12482.js deleted file mode 100644 index 7df89dd3540..00000000000 --- a/third_party/phantomjs/test/regression/pjs-12482.js +++ /dev/null @@ -1,48 +0,0 @@ -//! no-harness - -// https://github.com/ariya/phantomjs/issues/12482 -// regression caused by fix for -// https://github.com/ariya/phantomjs/issues/12431 - -var webpage = require('webpage'); -var sys = require('system'); - -var pages = [ - webpage.create(), - webpage.create(), - webpage.create() -]; - -var loaded = 0; - -sys.stdout.write("1.." + pages.length + "\n"); -setTimeout(function () { phantom.exit(1); }, 200); - -function loadHook (status) { - loaded++; - if (status === "success") { - sys.stdout.write("ok " + loaded + " loading page\n"); - } else { - sys.stdout.write("not ok " + loaded + " loading page\n"); - } - - if (loaded === pages.length) { - pages[1].close(); - setTimeout(function(){ - phantom.exit(0); - sys.stdout.write("not ok " + (pages.length+1) + - " should not get here # TODO\n"); - }, 50); - } -} -function consoleHook (msg) { - sys.stdout.write(msg + "\n"); -} - -for (var i = 0; i < pages.length; i++) { - pages[i].onConsoleMessage = consoleHook; - pages[i].open( - "data:text/html,", - loadHook); -} diff --git a/third_party/phantomjs/test/regression/pjs-13551.js b/third_party/phantomjs/test/regression/pjs-13551.js deleted file mode 100644 index 73236b2cb9d..00000000000 --- a/third_party/phantomjs/test/regression/pjs-13551.js +++ /dev/null @@ -1,52 +0,0 @@ -//! unsupported -// Issue #13551: Crash when switching "back" from frame that no longer -// exists (for whatever reason) - -var webpage = require('webpage'); - -function test_template(parent, action) { - var page; - var url = TEST_HTTP_BASE + - "/regression/pjs-13551/" + parent + "-parent.html"; - var s_callback0, s_callback1, s_callback2; - - function callback0 (n) { - assert_equals(n, 0); - page.onCallback = s_callback1; - page.evaluate(function () { - document.getElementById("prepare").click(); - }); - } - function callback1 (n) { - assert_equals(n, 1); - page.onCallback = s_callback2; - assert_equals(page.switchToFrame("target"), true); - assert_equals(page.switchToFrame("actor"), true); - page.evaluate(function () { - document.getElementById("execute").click(); - }); - } - function callback2 (n) { - assert_equals(n, 2); - assert_is_true(action == 'main' || action == 'parent'); - if (action == 'main') { - page.switchToMainFrame(); // Crash here - } else { - page.switchToParentFrame(); // Or here - } - } - - return function test_action () { - page = webpage.create(); - s_callback0 = this.step_func(callback0); - s_callback1 = this.step_func(callback1); - s_callback2 = this.step_func_done(callback2); - page.onCallback = s_callback0; - page.open(url); - }; -} - -async_test(test_template('closing', 'main'), "main from closed"); -async_test(test_template('closing', 'parent'), "parent from closed"); -async_test(test_template('reloading', 'main'), "main from reloaded"); -async_test(test_template('reloading', 'parent'), "parent from reloaded"); diff --git a/third_party/phantomjs/test/regression/webkit-60448.js b/third_party/phantomjs/test/regression/webkit-60448.js deleted file mode 100644 index 46280936f6a..00000000000 --- a/third_party/phantomjs/test/regression/webkit-60448.js +++ /dev/null @@ -1,12 +0,0 @@ -var url = TEST_HTTP_BASE + "regression/webkit-60448.html"; - -async_test(function () { - var p = require("webpage").create(); - p.open(url, this.step_func_done(function (status) { - assert_equals(status, "success"); - assert_is_true(p.evaluate(function () { - return document.getElementById("test") === null; - })); - })); -}, -"remove an inline HTML element from the document"); diff --git a/third_party/phantomjs/test/run-tests.py b/third_party/phantomjs/test/run-tests.py deleted file mode 100755 index 038dda6d2cc..00000000000 --- a/third_party/phantomjs/test/run-tests.py +++ /dev/null @@ -1,1051 +0,0 @@ -#!/usr/bin/env python - -import argparse -import collections -import errno -import glob -import imp -import os -import platform -import posixpath -import re -import shlex -import SimpleHTTPServer -import socket -import SocketServer -import ssl -import string -import cStringIO as StringIO -import subprocess -import sys -import threading -import time -import traceback -import urllib - -# All files matching one of these glob patterns will be run as tests. -TESTS = [ - 'basics/*.js', - 'module/*/*.js', - 'standards/*/*.js', - 'regression/*.js', -] - -TIMEOUT = 7 # Maximum duration of PhantomJS execution (in seconds). - # This is a backstop; testharness.js imposes a shorter - # timeout. Both can be increased if necessary. - -# -# Utilities -# - -# FIXME: assumes ANSI/VT100 escape sequences -# properly this should use curses, but that's an awful lot of work -# One of colors 30 ("black" -- usually a dark gray) and 37 ("white" -- -# usually a very light gray) will almost certainly be illegible -# against the terminal background, so we provide neither. -# The colorization mode is global because so is sys.stdout. -_COLOR_NONE = { - "_": "", "^": "", - "r": "", "R": "", - "g": "", "G": "", - "y": "", "Y": "", - "b": "", "B": "", - "m": "", "M": "", - "c": "", "C": "", -} -_COLOR_ON = { - "_": "\033[0m", "^": "\033[1m", - "r": "\033[31m", "R": "\033[1;31m", - "g": "\033[32m", "G": "\033[1;32m", - "y": "\033[33m", "Y": "\033[1;33m", - "b": "\033[34m", "B": "\033[1;34m", - "m": "\033[35m", "M": "\033[1;35m", - "c": "\033[36m", "C": "\033[1;36m", -} -_COLOR_BOLD = { - "_": "\033[0m", "^": "\033[1m", - "r": "\033[0m", "R": "\033[1m", - "g": "\033[0m", "G": "\033[1m", - "y": "\033[0m", "Y": "\033[1m", - "b": "\033[0m", "B": "\033[1m", - "m": "\033[0m", "M": "\033[1m", - "c": "\033[0m", "C": "\033[1m", -} -_COLORS = None -def activate_colorization(options): - global _COLORS - if options.color == "always": - _COLORS = _COLOR_ON - elif options.color == "never": - _COLORS = _COLOR_NONE - else: - if sys.stdout.isatty() and platform.system() != "Windows": - try: - n = int(subprocess.check_output(["tput", "colors"])) - if n >= 8: - _COLORS = _COLOR_ON - else: - _COLORS = _COLOR_BOLD - except subprocess.CalledProcessError: - _COLORS = _COLOR_NONE - else: - _COLORS = _COLOR_NONE - -def colorize(color, message): - return _COLORS[color] + message + _COLORS["_"] - -# create_default_context and SSLContext were only added in 2.7.9, -# which is newer than the python2 that ships with OSX :-( -# The fallback tries to mimic what create_default_context(CLIENT_AUTH) -# does. Security obviously isn't important in itself for a test -# server, but making sure the PJS client can talk to a server -# configured according to modern TLS best practices _is_ important. -# Unfortunately, there is no way to set things like OP_NO_SSL2 or -# OP_CIPHER_SERVER_PREFERENCE prior to 2.7.9. -CIPHERLIST_2_7_9 = ( - 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:' - 'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:' - '!eNULL:!MD5:!DSS:!RC4' -) -def wrap_socket_ssl(sock, base_path): - crtfile = os.path.join(base_path, 'certs/https-snakeoil.crt') - keyfile = os.path.join(base_path, 'certs/https-snakeoil.key') - - try: - ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) - ctx.load_cert_chain(crtfile, keyfile) - return ctx.wrap_socket(sock, server_side=True) - - except AttributeError: - return ssl.wrap_socket(sock, - keyfile=keyfile, - certfile=crtfile, - server_side=True, - ciphers=CIPHERLIST_2_7_9) - -# This should be in the standard library somewhere, but as far as I -# can tell, it isn't. -class ResponseHookImporter(object): - def __init__(self, www_path): - # All Python response hooks, no matter how deep below www_path, - # are treated as direct children of the fake "test_www" package. - if 'test_www' not in sys.modules: - imp.load_source('test_www', www_path + '/__init__.py') - - self.tr = string.maketrans('-./%', '____') - - def __call__(self, path): - modname = 'test_www.' + path.translate(self.tr) - try: - return sys.modules[modname] - except KeyError: - return imp.load_source(modname, path) - -# This should also be in the standard library somewhere, and -# definitely isn't. -# -# FIXME: This currently involves *three* threads for every process, -# and a fourth if the process takes input. (On Unix, clever use of -# select() might be able to get that down to one, but zero is Hard. -# On Windows, we're hosed. 3.4's asyncio module would make everything -# better, but 3.4 is its own can of worms.) -try: - devnull = subprocess.DEVNULL -except: - devnull = os.open(os.devnull, os.O_RDONLY) - -def do_call_subprocess(command, verbose, stdin_data, timeout): - - def read_thread(linebuf, fp): - while True: - line = fp.readline().rstrip() - if not line: break # EOF - line = line.rstrip() - if line: - linebuf.append(line) - if verbose >= 3: - sys.stdout.write(line + '\n') - - def write_thread(data, fp): - fp.writelines(data) - fp.close() - - def reap_thread(proc, timed_out): - if proc.returncode is None: - proc.terminate() - timed_out[0] = True - - class DummyThread: - def start(self): pass - def join(self): pass - - if stdin_data: - stdin = subprocess.PIPE - else: - stdin = devnull - - proc = subprocess.Popen(command, - stdin=stdin, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - - if stdin_data: - sithrd = threading.Thread(target=write_thread, - args=(stdin_data, proc.stdin)) - else: - sithrd = DummyThread() - - stdout = [] - stderr = [] - timed_out = [False] - sothrd = threading.Thread(target=read_thread, args=(stdout, proc.stdout)) - sethrd = threading.Thread(target=read_thread, args=(stderr, proc.stderr)) - rpthrd = threading.Timer(timeout, reap_thread, args=(proc, timed_out)) - - sithrd.start() - sothrd.start() - sethrd.start() - rpthrd.start() - - proc.wait() - if not timed_out[0]: rpthrd.cancel() - - sithrd.join() - sothrd.join() - sethrd.join() - rpthrd.join() - - if timed_out[0]: - stderr.append("TIMEOUT: Process terminated after {} seconds." - .format(timeout)) - if verbose >= 3: - sys.stdout.write(stderr[-1] + "\n") - - rc = proc.returncode - if verbose >= 3: - if rc < 0: - sys.stdout.write("## killed by signal {}\n".format(-rc)) - else: - sys.stdout.write("## exit {}\n".format(rc)) - return proc.returncode, stdout, stderr - -# -# HTTP/HTTPS server, presented on localhost to the tests -# - -class FileHandler(SimpleHTTPServer.SimpleHTTPRequestHandler, object): - - def __init__(self, *args, **kwargs): - self._cached_untranslated_path = None - self._cached_translated_path = None - self.postdata = None - super(FileHandler, self).__init__(*args, **kwargs) - - # silent, do not pollute stdout nor stderr. - def log_message(self, format, *args): - return - - # accept POSTs, read the postdata and stash it in an instance variable, - # then forward to do_GET; handle_request hooks can vary their behavior - # based on the presence of postdata and/or the command verb. - def do_POST(self): - try: - ln = int(self.headers.get('content-length')) - except TypeError, ValueError: - self.send_response(400, 'Bad Request') - self.send_header('Content-Type', 'text/plain') - self.end_headers() - self.wfile.write("No or invalid Content-Length in POST (%r)" - % self.headers.get('content-length')) - return - - self.postdata = self.rfile.read(ln) - self.do_GET() - - # allow provision of a .py file that will be interpreted to - # produce the response. - def send_head(self): - path = self.translate_path(self.path) - - # do not allow direct references to .py(c) files, - # or indirect references to __init__.py - if (path.endswith('.py') or path.endswith('.pyc') or - path.endswith('__init__')): - self.send_error(404, 'File not found') - return None - - if os.path.exists(path): - return super(FileHandler, self).send_head() - - py = path + '.py' - if os.path.exists(py): - try: - mod = self.get_response_hook(py) - return mod.handle_request(self) - except: - self.send_error(500, 'Internal Server Error in '+py) - raise - - self.send_error(404, 'File not found') - return None - - # modified version of SimpleHTTPRequestHandler's translate_path - # to resolve the URL relative to the www/ directory - # (e.g. /foo -> test/www/foo) - def translate_path(self, path): - - # Cache for efficiency, since our send_head calls this and - # then, in the normal case, the parent class's send_head - # immediately calls it again. - if (self._cached_translated_path is not None and - self._cached_untranslated_path == path): - return self._cached_translated_path - - orig_path = path - - # Strip query string and/or fragment, if present. - x = path.find('?') - if x != -1: path = path[:x] - x = path.find('#') - if x != -1: path = path[:x] - - # Ensure consistent encoding of special characters, then - # lowercase everything so that the tests behave consistently - # whether or not the local filesystem is case-sensitive. - path = urllib.quote(urllib.unquote(path)).lower() - - # Prevent access to files outside www/. - # At this point we want specifically POSIX-like treatment of 'path' - # because it is still a URL component and not a filesystem path. - # SimpleHTTPRequestHandler.send_head() expects us to preserve the - # distinction between paths with and without a trailing slash, but - # posixpath.normpath() discards that distinction. - trailing_slash = path.endswith('/') - path = posixpath.normpath(path) - while path.startswith('/'): - path = path[1:] - while path.startswith('../'): - path = path[3:] - - # Now resolve the normalized, clamped path relative to the www/ - # directory, according to local OS conventions. - path = os.path.normpath(os.path.join(self.www_path, *path.split('/'))) - if trailing_slash: - # it must be a '/' even on Windows - path += '/' - - self._cached_untranslated_path = orig_path - self._cached_translated_path = path - return path - -class TCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): - # This is how you are officially supposed to set SO_REUSEADDR per - # https://docs.python.org/2/library/socketserver.html#SocketServer.BaseServer.allow_reuse_address - allow_reuse_address = True - - def __init__(self, use_ssl, handler, base_path, signal_error): - SocketServer.TCPServer.__init__(self, ('localhost', 0), handler) - if use_ssl: - self.socket = wrap_socket_ssl(self.socket, base_path) - self._signal_error = signal_error - - def handle_error(self, request, client_address): - # Ignore errors which can occur naturally if the client - # disconnects in the middle of a request. EPIPE and - # ECONNRESET *should* be the only such error codes - # (according to the OSX manpage for send()). - _, exval, _ = sys.exc_info() - if getattr(exval, 'errno', None) in (errno.EPIPE, errno.ECONNRESET): - return - - # Otherwise, report the error to the test runner. - self._signal_error(sys.exc_info()) - -class HTTPTestServer(object): - def __init__(self, base_path, signal_error, verbose): - self.httpd = None - self.httpsd = None - self.base_path = base_path - self.www_path = os.path.join(base_path, 'www') - self.signal_error = signal_error - self.verbose = verbose - - def __enter__(self): - handler = FileHandler - handler.extensions_map.update({ - '.htm': 'text/html', - '.html': 'text/html', - '.css': 'text/css', - '.js': 'application/javascript', - '.json': 'application/json' - }) - handler.www_path = self.www_path - handler.get_response_hook = ResponseHookImporter(self.www_path) - - self.httpd = TCPServer(False, handler, - self.base_path, self.signal_error) - os.environ['TEST_HTTP_BASE'] = \ - 'http://localhost:{}/'.format(self.httpd.server_address[1]) - httpd_thread = threading.Thread(target=self.httpd.serve_forever) - httpd_thread.daemon = True - httpd_thread.start() - if self.verbose >= 3: - sys.stdout.write("## HTTP server at {}\n".format( - os.environ['TEST_HTTP_BASE'])) - - self.httpsd = TCPServer(True, handler, - self.base_path, self.signal_error) - os.environ['TEST_HTTPS_BASE'] = \ - 'https://localhost:{}/'.format(self.httpsd.server_address[1]) - httpsd_thread = threading.Thread(target=self.httpsd.serve_forever) - httpsd_thread.daemon = True - httpsd_thread.start() - if self.verbose >= 3: - sys.stdout.write("## HTTPS server at {}\n".format( - os.environ['TEST_HTTPS_BASE'])) - - return self - - def __exit__(self, *dontcare): - self.httpd.shutdown() - del os.environ['TEST_HTTP_BASE'] - self.httpsd.shutdown() - del os.environ['TEST_HTTPS_BASE'] - -# -# Running tests and interpreting their results -# -class TestDetailCode(collections.namedtuple("TestDetailCode", ( - "idx", "color", "short_label", "label", "long_label"))): - def __index__(self): return self.idx - def __hash__(self): return self.idx - def __eq__(self, other): return self.idx == other.idx - def __ne__(self, other): return self.idx != other.idx - -class T(object): - PASS = TestDetailCode(0, "g", ".", "pass", "passed") - FAIL = TestDetailCode(1, "R", "F", "FAIL", "failed") - XFAIL = TestDetailCode(2, "y", "f", "xfail", "failed as expected") - XPASS = TestDetailCode(3, "Y", "P", "XPASS", "passed unexpectedly") - ERROR = TestDetailCode(4, "R", "E", "ERROR", "had errors") - SKIP = TestDetailCode(5, "m", "s", "skip", "skipped") - UNSUPPORTED = TestDetailCode(6, "y", "u", "unsupported", "unsupported") - MAX = 7 - -class TestDetail(object): - """Holds one block of details about a test that failed.""" - # types of details: - - def __init__(self, message, test_id, detail_type): - if not isinstance(message, list): - message = [message] - self.message = [line.rstrip() - for chunk in message - for line in chunk.split("\n")] - - self.dtype = detail_type - self.test_id = test_id - - def report(self, fp): - col, label = self.dtype.color, self.dtype.label - if self.test_id: - fp.write("{:>5}: {}\n".format(colorize(col, label), - self.test_id)) - lo = 0 - else: - fp.write("{:>5}: {}\n".format(colorize(col, label), - self.message[0])) - lo = 1 - for line in self.message[lo:]: - fp.write(" {}\n".format(colorize("b", line))) - -class TestGroup(object): - """Holds the result of one group of tests (that is, one .js file), - parsed from the output of run_phantomjs (see below). - Subclasses specify what the output means. - A test with zero details is considered to be successful. - """ - - def __init__(self, name): - self.name = name - self.n = [0]*T.MAX - self.details = [] - - def parse(self, rc, out, err): - raise NotImplementedError - - def _add_d(self, message, test_id, dtype): - self.n[dtype] += 1 - self.details.append(TestDetail(message, test_id, dtype)) - - def add_pass (self, m, t): self._add_d(m, t, T.PASS) - def add_fail (self, m, t): self._add_d(m, t, T.FAIL) - def add_xpass(self, m, t): self._add_d(m, t, T.XPASS) - def add_xfail(self, m, t): self._add_d(m, t, T.XFAIL) - def add_error(self, m, t): self._add_d(m, t, T.ERROR) - def add_skip (self, m, t): self._add_d(m, t, T.SKIP) - def add_unsupported (self, m, t): self._add_d(m, t, T.UNSUPPORTED) - - def default_interpret_exit_code(self, rc): - if rc == 0: - if not self.is_successful() and not self.n[T.ERROR]: - self.add_error([], - "PhantomJS exited successfully when test failed") - - # Exit code -15 indicates a timeout. - elif rc == 1 or rc == -15: - if self.is_successful(): - self.add_error([], "PhantomJS exited unsuccessfully") - - elif rc >= 2: - self.add_error([], "PhantomJS exited with code {}".format(rc)) - else: - self.add_error([], "PhantomJS killed by signal {}".format(-rc)) - - def is_successful(self): - return self.n[T.FAIL] + self.n[T.XPASS] + self.n[T.ERROR] == 0 - - def worst_code(self): - # worst-to-best ordering - for code in (T.ERROR, T.FAIL, T.XPASS, T.SKIP, T.XFAIL, T.PASS, T.UNSUPPORTED): - if self.n[code] > 0: - return code - return T.PASS - - def one_char_summary(self, fp): - code = self.worst_code() - fp.write(colorize(code.color, code.short_label)) - fp.flush() - - def line_summary(self, fp): - code = self.worst_code() - fp.write("{}: {}\n".format(colorize("^", self.name), - colorize(code.color, code.label))) - - def report(self, fp, show_all): - self.line_summary(fp) - need_blank_line = False - for detail in self.details: - if show_all or detail.dtype not in (T.PASS, T.XFAIL, T.SKIP): - detail.report(fp) - need_blank_line = True - if need_blank_line: - fp.write("\n") - - def report_for_verbose_level(self, fp, verbose): - if verbose == 0: - self.one_char_summary(sys.stdout) - elif verbose == 1: - self.report(sys.stdout, False) - else: - self.report(sys.stdout, True) - -class UnsupportedTestGroup(TestGroup): - """Test group which is currently unsupported and should - be skipped altogether. - """ - def __init__(self, name): - TestGroup.__init__(self, name) - self.add_unsupported('', 'Skipping the whole file'); - - -class ExpectTestGroup(TestGroup): - """Test group whose output must be exactly as specified by directives - in the file. This is how you test for an _unsuccessful_ exit code, - or for output appearing on a specific one of stdout/stderr. - """ - def __init__(self, name, rc_exp, stdout_exp, stderr_exp, - rc_xfail, stdout_xfail, stderr_xfail): - TestGroup.__init__(self, name) - if rc_exp is None: rc_exp = 0 - self.rc_exp = rc_exp - self.stdout_exp = stdout_exp - self.stderr_exp = stderr_exp - self.rc_xfail = rc_xfail - self.stdout_xfail = stdout_xfail - self.stderr_xfail = stderr_xfail - - def parse(self, rc, out, err): - self.parse_output("stdout", self.stdout_exp, out, self.stdout_xfail) - self.parse_output("stderr", self.stderr_exp, err, self.stderr_xfail) - - exit_msg = ["expected exit code {} got {}" - .format(self.rc_exp, rc)] - - if rc != self.rc_exp: - exit_desc = "did not exit as expected" - if self.rc_xfail: - self.add_xfail(exit_msg, exit_desc) - else: - self.add_fail(exit_msg, exit_desc) - else: - exit_desc = "exited as expected" - if self.rc_xfail: - self.add_xpass(exit_msg, exit_desc) - else: - self.add_pass(exit_msg, exit_desc) - - def parse_output(self, what, exp, got, xfail): - diff = [] - le = len(exp) - lg = len(got) - for i in range(max(le, lg)): - e = "" - g = "" - if i < le: e = exp[i] - if i < lg: g = got[i] - if e != g: - diff.extend(("{}: line {} not as expected".format(what, i+1), - "-" + repr(e)[1:-1], - "+" + repr(g)[1:-1])) - - if diff: - desc = what + " not as expected" - if xfail: - self.add_xfail(diff, desc) - else: - self.add_fail(diff, desc) - else: - desc = what + " as expected" - if xfail: - self.add_xpass(diff, desc) - else: - self.add_pass(diff, desc) - - -class TAPTestGroup(TestGroup): - """Test group whose output is interpreted according to a variant of the - Test Anything Protocol (http://testanything.org/tap-specification.html). - - Relative to that specification, these are the changes: - - * Plan-at-the-end, explanations for directives, and "Bail out!" - are not supported. ("1..0 # SKIP: explanation" *is* supported.) - * "Anything else" lines are an error. - * Repeating a test point number, or using one outside the plan - range, is an error (this is unspecified in TAP proper). - * Diagnostic lines beginning with # are taken as additional - information about the *next* test point. Diagnostic lines - beginning with ## are ignored. - * Directives are case sensitive. - - """ - - diag_r = re.compile(r"^#(#*)\s*(.*)$") - plan_r = re.compile(r"^1..(\d+)(?:\s*\#\s*SKIP(?::\s*(.*)))?$") - test_r = re.compile(r"^(not ok|ok)\s*" - r"([0-9]+)?\s*" - r"([^#]*)(?:# (TODO|SKIP))?$") - - def parse(self, rc, out, err): - self.parse_tap(out, err) - self.default_interpret_exit_code(rc) - - def parse_tap(self, out, err): - points_already_used = set() - messages = [] - - # Look for the plan. - # Diagnostic lines are allowed to appear above the plan, but not - # test lines. - for i in range(len(out)): - line = out[i] - m = self.diag_r.match(line) - if m: - if not m.group(1): - messages.append(m.group(2)) - continue - - m = self.plan_r.match(line) - if m: - break - - messages.insert(0, line) - self.add_error(messages, "Plan line not interpretable") - if i + 1 < len(out): - self.add_skip(out[(i+1):], "All further output ignored") - return - else: - self.add_error(messages, "No plan line detected in output") - return - - max_point = int(m.group(1)) - if max_point == 0: - if any(msg.startswith("ERROR:") for msg in messages): - self.add_error(messages, m.group(2) or "Test group skipped") - else: - self.add_skip(messages, m.group(2) or "Test group skipped") - if i + 1 < len(out): - self.add_skip(out[(i+1):], "All further output ignored") - return - - prev_point = 0 - - for i in range(i+1, len(out)): - line = out[i] - m = self.diag_r.match(line) - if m: - if not m.group(1): - messages.append(m.group(2)) - continue - m = self.test_r.match(line) - if m: - status = m.group(1) - point = m.group(2) - desc = m.group(3) - dirv = m.group(4) - - if point: - point = int(point) - else: - point = prev_point + 1 - - if point in points_already_used: - # A reused test point is an error. - self.add_error(messages, desc + " [test point repeated]") - else: - points_already_used.add(point) - # A point above the plan limit is an automatic *fail*. - # The test suite relies on this in testing exit(). - if point > max_point: - status = "not ok" - - if status == "ok": - if not dirv: - self.add_pass(messages, desc) - elif dirv == "TODO": - self.add_xpass(messages, desc) - elif dirv == "SKIP": - self.add_skip(messages, desc) - else: - self.add_error(messages, desc + - " [ok, with invalid directive "+dirv+"]") - else: - if not dirv: - self.add_fail(messages, desc) - elif dirv == "TODO": - self.add_xfail(messages, desc) - else: - self.add_error(messages, desc + - " [not ok, with invalid directive "+dirv+"]") - - del messages[:] - prev_point = point - - else: - self.add_error([line], "neither a test nor a diagnostic") - - # Any output on stderr is an error, with one exception: the timeout - # message added by record_process_output, which is treated as an - # unnumbered "not ok". - if err: - if len(err) == 1 and err[0].startswith("TIMEOUT: "): - points_already_used.add(prev_point + 1) - self.add_fail(messages, err[0][len("TIMEOUT: "):]) - else: - self.add_error(err, "Unexpected output on stderr") - - # Any missing test points are fails. - for pt in range(1, max_point+1): - if pt not in points_already_used: - self.add_fail([], "test {} did not report status".format(pt)) - -class TestRunner(object): - def __init__(self, base_path, phantomjs_exe, options): - self.base_path = base_path - self.cert_path = os.path.join(base_path, 'certs') - self.harness = os.path.join(base_path, 'testharness.js') - self.phantomjs_exe = phantomjs_exe - self.verbose = options.verbose - self.debugger = options.debugger - self.to_run = options.to_run - self.run_unsupported = options.run_unsupported - self.server_errs = [] - - def signal_server_error(self, exc_info): - self.server_errs.append(exc_info) - - def get_base_command(self, debugger): - if debugger is None: - return ["node", self.phantomjs_exe] - elif debugger == "gdb": - return ["gdb", "--args", "node", self.phantomjs_exe] - elif debugger == "lldb": - return ["lldb", "--", "node", self.phantomjs_exe] - elif debugger == "valgrind": - return ["valgrind", "node", self.phantomjs_exe] - else: - raise RuntimeError("Don't know how to invoke " + self.debugger) - - def run_phantomjs(self, script, - script_args=[], pjs_args=[], stdin_data=[], - timeout=TIMEOUT, silent=False): - verbose = self.verbose - debugger = self.debugger - if silent: - verbose = False - debugger = None - - output = [] - command = self.get_base_command(debugger) - command.extend(pjs_args) - command.append(script) - if verbose: - command.append('--verbose={}'.format(verbose)) - command.extend(script_args) - - if verbose >= 3: - sys.stdout.write("## running {}\n".format(" ".join(command))) - - if debugger: - # FIXME: input-feed mode doesn't work with a debugger, - # because how do you tell the debugger that the *debuggee* - # needs to read from a pipe? - subprocess.call(command) - return 0, [], [] - else: - return do_call_subprocess(command, verbose, stdin_data, timeout) - - def run_test(self, script, name): - script_args = [] - pjs_args = [] - use_harness = True - use_snakeoil = False - stdin_data = [] - stdout_exp = [] - stderr_exp = [] - rc_exp = None - stdout_xfail = False - stderr_xfail = False - rc_xfail = False - timeout = TIMEOUT - unsupported = False - - def require_args(what, i, tokens): - if i+1 == len(tokens): - raise ValueError(what + "directive requires an argument") - - if self.verbose >= 3: - sys.stdout.write(colorize("^", name) + ":\n") - # Parse any directives at the top of the script. - try: - with open(script, "rt") as s: - for line in s: - if not line.startswith("//!"): - break - tokens = shlex.split(line[3:], comments=True) - - skip = False - for i in range(len(tokens)): - if skip: - skip = False - continue - tok = tokens[i] - if tok == "unsupported": - unsupported = True - elif tok == "no-harness": - use_harness = False - elif tok == "snakeoil": - use_snakeoil = True - elif tok == "expect-exit-fails": - rc_xfail = True - elif tok == "expect-stdout-fails": - stdout_xfail = True - elif tok == "expect-stderr-fails": - stderr_xfail = True - elif tok == "timeout:": - require_args(tok, i, tokens) - timeout = float(tokens[i+1]) - if timeout <= 0: - raise ValueError("timeout must be positive") - skip = True - elif tok == "expect-exit:": - require_args(tok, i, tokens) - rc_exp = int(tokens[i+1]) - skip = True - elif tok == "phantomjs:": - require_args(tok, i, tokens) - pjs_args.extend(tokens[(i+1):]) - break - elif tok == "script:": - require_args(tok, i, tokens) - script_args.extend(tokens[(i+1):]) - break - elif tok == "stdin:": - require_args(tok, i, tokens) - stdin_data.append(" ".join(tokens[(i+1):]) + "\n") - break - elif tok == "expect-stdout:": - require_args(tok, i, tokens) - stdout_exp.append(" ".join(tokens[(i+1):])) - break - elif tok == "expect-stderr:": - require_args(tok, i, tokens) - stderr_exp.append(" ".join(tokens[(i+1):])) - break - else: - raise ValueError("unrecognized directive: " + tok) - - except Exception as e: - grp = TestGroup(name) - if hasattr(e, 'strerror') and hasattr(e, 'filename'): - grp.add_error([], '{} ({}): {}\n' - .format(name, e.filename, e.strerror)) - else: - grp.add_error([], '{} ({}): {}\n' - .format(name, script, str(e))) - return grp - - if use_harness: - script_args.insert(0, script) - script = self.harness - - if use_snakeoil: - pjs_args.insert(0, '--ssl-certificates-path=' + self.cert_path) - - if unsupported and not self.run_unsupported: - return UnsupportedTestGroup(name) - rc, out, err = self.run_phantomjs(script, script_args, pjs_args, - stdin_data, timeout) - - if rc_exp or stdout_exp or stderr_exp: - grp = ExpectTestGroup(name, - rc_exp, stdout_exp, stderr_exp, - rc_xfail, stdout_xfail, stderr_xfail) - else: - grp = TAPTestGroup(name) - grp.parse(rc, out, err) - return grp - - def run_tests(self): - start = time.time() - base = self.base_path - nlen = len(base) + 1 - - results = [] - - for test_glob in TESTS: - test_glob = os.path.join(base, test_glob) - - for test_script in sorted(glob.glob(test_glob)): - tname = os.path.splitext(test_script)[0][nlen:] - if self.to_run: - for to_run in self.to_run: - if to_run in tname: - break - else: - continue - - any_executed = True - grp = self.run_test(test_script, tname) - grp.report_for_verbose_level(sys.stdout, self.verbose) - results.append(grp) - - grp = TestGroup("HTTP server errors") - for ty, val, tb in self.server_errs: - grp.add_error(traceback.format_tb(tb, 5), - traceback.format_exception_only(ty, val)[-1]) - grp.report_for_verbose_level(sys.stdout, self.verbose) - results.append(grp) - - sys.stdout.write("\n") - return self.report(results, time.time() - start) - - def report(self, results, elapsed): - # There is always one test group, for the HTTP server errors. - if len(results) == 1: - sys.stderr.write("No tests selected for execution.\n") - return 1 - - n = [0] * T.MAX - - for grp in results: - if self.verbose == 0 and not grp.is_successful(): - grp.report(sys.stdout, False) - for i, x in enumerate(grp.n): n[i] += x - - sys.stdout.write("{:6.3f}s elapsed\n".format(elapsed)) - for s in (T.PASS, T.FAIL, T.XPASS, T.XFAIL, T.ERROR, T.SKIP, T.UNSUPPORTED): - if n[s]: - sys.stdout.write(" {:>4} {}\n".format(n[s], s.long_label)) - - if n[T.FAIL] == 0 and n[T.XPASS] == 0 and n[T.ERROR] == 0: - return 0 - else: - return 1 - -def init(): - base_path = os.path.normpath(os.path.dirname(os.path.abspath(__file__))) - phantomjs_exe = os.path.normpath(base_path + '/../../../phantom_shim/runner.js') - if not os.path.isfile(phantomjs_exe): - sys.stdout.write("{} is unavailable, cannot run tests.\n" - .format(phantomjs_exe)) - sys.exit(1) - - parser = argparse.ArgumentParser(description='Run PhantomJS tests.') - parser.add_argument('-v', '--verbose', action='count', default=0, - help='Increase verbosity of logs (repeat for more)') - parser.add_argument('to_run', nargs='*', metavar='test', - help='tests to run (default: all of them)') - parser.add_argument('--debugger', default=None, - help="Run PhantomJS under DEBUGGER") - parser.add_argument('--run-unsupported', action='count', default=0, - help='Run unsupported tests.') - parser.add_argument('--color', metavar="WHEN", default='auto', - choices=['always', 'never', 'auto'], - help="colorize the output; can be 'always'," - " 'never', or 'auto' (the default)") - - options = parser.parse_args() - activate_colorization(options) - runner = TestRunner(base_path, phantomjs_exe, options) - if options.verbose: - rc, ver, err = runner.run_phantomjs('--version', silent=True) - if rc != 0 or len(ver) != 1 or len(err) != 0: - sys.stdout.write(colorize("R", "FATAL")+": Version check failed\n") - for l in ver: - sys.stdout.write(colorize("b", "## " + l) + "\n") - for l in err: - sys.stdout.write(colorize("b", "## " + l) + "\n") - sys.stdout.write(colorize("b", "## exit {}".format(rc)) + "\n") - sys.exit(1) - - sys.stdout.write(colorize("b", "## Testing PhantomJS "+ver[0])+"\n") - - # Run all the tests in Chatham Islands Standard Time, UTC+12:45. - # This timezone is deliberately chosen to be unusual: it's not a - # whole number of hours offset from UTC *and* it's more than twelve - # hours offset from UTC. - # - # The Chatham Islands do observe daylight savings, but we don't - # implement that because testsuite issues only reproducible on two - # particular days out of the year are too much tsuris. - # - # Note that the offset in a TZ value is the negative of the way it's - # usually written, e.g. UTC+1 would be xxx-1:00. - os.environ["TZ"] = "CIST-12:45:00" - - return runner - -def main(): - runner = init() - try: - with HTTPTestServer(runner.base_path, - runner.signal_server_error, - runner.verbose): - sys.exit(runner.run_tests()) - - except Exception: - trace = traceback.format_exc(5).split("\n") - # there will be a blank line at the end of 'trace' - sys.stdout.write(colorize("R", "FATAL") + ": " + trace[-2] + "\n") - for line in trace[:-2]: - sys.stdout.write(colorize("b", "## " + line) + "\n") - - sys.exit(1) - - except KeyboardInterrupt: - sys.exit(2) - -main() diff --git a/third_party/phantomjs/test/standards/console/console_log.js b/third_party/phantomjs/test/standards/console/console_log.js deleted file mode 100644 index 7b17aba81c8..00000000000 --- a/third_party/phantomjs/test/standards/console/console_log.js +++ /dev/null @@ -1,9 +0,0 @@ -async_test(function () { - var page = require('webpage').create(); - page.onConsoleMessage = this.step_func_done(function (msg) { - assert_equals(msg, "answer 42"); - }); - page.evaluate(function () { - console.log('answer', 42); - }); -}, "console.log should support multiple arguments"); diff --git a/third_party/phantomjs/test/standards/javascript/date.js b/third_party/phantomjs/test/standards/javascript/date.js deleted file mode 100644 index b2a1f97f83a..00000000000 --- a/third_party/phantomjs/test/standards/javascript/date.js +++ /dev/null @@ -1,12 +0,0 @@ -test(function() { - var date = new Date('2012-09-07'); - assert_not_equals(date.toString(), 'Invalid Date'); - assert_equals(date.getUTCDate(), 7); - assert_equals(date.getUTCMonth(), 8); - assert_equals(date.getYear(), 112); -}, "new Date()"); - -test(function () { - var date = Date.parse("2012-01-01"); - assert_equals(date, 1325376000000); -}, "Date.parse()"); diff --git a/third_party/phantomjs/test/standards/javascript/function.js b/third_party/phantomjs/test/standards/javascript/function.js deleted file mode 100644 index 2b6f4734c76..00000000000 --- a/third_party/phantomjs/test/standards/javascript/function.js +++ /dev/null @@ -1,46 +0,0 @@ -test(function () { - assert_type_of(Function.length, 'number'); - assert_type_of(Function.prototype, 'function'); - assert_type_of(Function.prototype.apply, 'function'); - assert_type_of(Function.prototype.bind, 'function'); - assert_type_of(Function.prototype.call, 'function'); - assert_type_of(Function.prototype.name, 'string'); - assert_type_of(Function.prototype.toString, 'function'); -}, "Function properties"); - -test(function () { - var f = function foo(){}; - assert_equals(f.name, 'foo'); -}, ".name"); - -test(function () { - assert_equals(Function.length, 1); - assert_equals(function(){}.length, 0); - assert_equals(function(x){}.length, 1); - assert_equals(function(x, y){}.length, 2); - assert_equals(function(x, y){}.length, 2); -}, ".length"); - -test(function () { - var args, keys, str, enumerable; - (function() { - args = arguments; - keys = Object.keys(arguments); - str = JSON.stringify(arguments); - enumerable = false; - for (var i in arguments) enumerable = true; - })(14); - - assert_type_of(args, 'object'); - assert_type_of(args.length, 'number'); - assert_equals(args.toString(), '[object Arguments]'); - assert_equals(args.length, 1); - assert_equals(args[0], 14); - - assert_type_of(keys.length, 'number'); - assert_equals(keys.length, 1); - assert_equals(keys[0], "0"); - - assert_equals(str, '{"0":14}'); - assert_is_true(enumerable); -}, "arguments object"); diff --git a/third_party/phantomjs/test/testharness.js b/third_party/phantomjs/test/testharness.js deleted file mode 100644 index 706048b3d79..00000000000 --- a/third_party/phantomjs/test/testharness.js +++ /dev/null @@ -1,1489 +0,0 @@ -/* vim: set expandtab shiftwidth=4 tabstop=4: */ -/*global require, phantom, setTimeout, clearTimeout */ - -/* - This file is part of the PhantomJS project from Ofi Labs. - - Copyright 2015 Zachary Weinberg - - Based on testharness.js - produced by the W3C and distributed under the W3C 3-Clause BSD - License . - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL 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. - - */ - -(function () { - -"use strict"; - -/** Public API: Defining and running tests. - * - * Compared to the W3C testharness.js, a number of minor changes have - * been made to fit the rather different PhantomJS controller - * environment, but the basic API is the same. - */ - -/** Define an asynchronous test. Returns a Test object. In response - to appropriate events, call the Test object's step() method, - passing a function containing assertions (as for synch tests). - Eventually, call the Test object's done() method (inside a step). - - All arguments are optional. If |func| is provided, it is called - immediately (after the previous test completes) as the first step - function. |properties| is the same as for test(). - - Test has several convenience methods for creating step functions, - see below. */ -function async_test(func, name, properties) { - var test_obj; - - if (func && typeof func !== "function") { - properties = name; - name = func; - func = null; - } - test_obj = new Test(test_name(func, name), properties); - if (func) { - test_obj.step(func); - } - return test_obj; -} -expose(async_test, 'async_test'); - -/** Define a synchronous test, which is just an asynchronous test that - calls done() immediately after its first step function (func) returns. - - |func| is a function containing the test code, and |name| - (optionally) is a descriptive name for the test. |func| will be - called (after the previous test completes), with |this| a Test - object (see below), and should make use of the global assert_* - functions. |properties| is an optional dictionary of test - properties; currently only one is defined: - - timeout - Timeout for this test, in milliseconds. */ -function test(func, name, properties) { - return async_test(function sync_step () { - func.call(this); - this.done(); - }, name, properties); -} -expose(test, 'test'); - -/** Define a series of synchronous tests all at once. - Easiest to explain by example: - - generate_tests(assert_equals, [ - ["Sum one and one", 1+1, 2], - ["Sum one and zero", 1+0, 1] - ]); - - is equivalent to - - test(function() {assert_equals(1+1, 2)}, "Sum one and one"); - test(function() {assert_equals(1+0, 1)}, "Sum one and zero"); - - The first argument can be an arbitrary function, and you can provide - as many arguments in each test vector entry as you like. - - The properties argument can be a single dictionary, which is applied to - all the tests, or an array, applied entry-by-entry. - */ -function generate_tests(func, args, properties) { - function generate_one_test(argv) { - return function generated_step () { - // 'this' will be set by bind() inside test(). - func.apply(this, argv); - }; - } - - var i; - for (i = 0; i < args.length; i++) { - test(generate_one_test(args[i].slice(1)), - args[i][0], - Array.isArray(properties) ? properties[i] : properties); - } -} -expose(generate_tests, 'generate_tests'); - -/** Set up the test harness. Does nothing if called after any test has - begun execution. May be called as setup(func), setup(properties), or - setup(func, properties). |func| is a function to call synchronously; - if it throws an exception the entire test group is considered failed. - |properties| is a dictionary containing one or more of these keys: - - explicit_done - Wait for an explicit call to done() before - declaring all tests complete (see below; implicitly true for - single-test files) - - allow_uncaught_exception - Don't treat an uncaught exception from - non-test code as an error. (Exceptions thrown out of test - functions are still errors.) - - timeout - Global timeout in milliseconds (default: 5 seconds) - test_timeout - Per-test timeout in milliseconds, unless overridden - by the timeout property on a specific test (default: none) - */ -function setup(func_or_properties, maybe_properties) { - var func = null, - properties = {}; - - if (arguments.length === 2) { - func = func_or_properties; - properties = maybe_properties; - } else if (typeof func_or_properties === "function") { - func = func_or_properties; - } else { - properties = func_or_properties; - } - tests.setup(func, properties); -} -expose(setup, 'setup'); - -/** Signal that all tests are complete. Must be called explicitly if - setup({explicit_done: true}) was used; otherwise implicitly - happens when all individual tests are done. */ -function done() { - tests.end_wait(); -} -expose(done, 'done'); - - -/** Public API: Assertions. - * All assertion functions take a |description| argument which is used to - * annotate any failing tests. - */ - -/** Assert that |actual| is strictly true. */ -function assert_is_true(actual, description) { - assert(actual === true, "assert_is_true", description, - "expected true got ${actual}", {actual: actual}); -} -expose(assert_is_true, 'assert_is_true'); - -/** Assert that |actual| is strictly false. */ -function assert_is_false(actual, description) { - assert(actual === false, "assert_is_false", description, - "expected false got ${actual}", {actual: actual}); -} -expose(assert_is_false, 'assert_is_false'); - -/** Assert that |actual| is strictly equal to |expected|. - The test is even more stringent than === (see same_value, below). */ -function assert_equals(actual, expected, description) { - if (typeof actual !== typeof expected) { - assert(false, "assert_equals", description, - "expected (${expectedT}) ${expected} " + - "but got (${actualT}) ${actual}", - {expectedT: typeof expected, - expected: expected, - actualT: typeof actual, - actual: actual}); - } - assert(same_value(actual, expected), "assert_equals", description, - "expected ${expected} but got ${actual}", - {expected: expected, actual: actual}); -} -expose(assert_equals, 'assert_equals'); - -/** Assert that |actual| is not strictly equal to |expected|, using the - same extra-stringent criterion as for assert_equals. */ -function assert_not_equals(actual, expected, description) { - if (typeof actual !== typeof expected) { - return; - } - assert(!same_value(actual, expected), "assert_not_equals", description, - "got disallowed value ${actual}", - {actual: actual}); -} -expose(assert_not_equals, 'assert_not_equals'); - -/** Assert that |expected|, a duck-typed array, contains |actual|, - according to indexOf. */ -function assert_in_array(actual, expected, description) { - assert(expected.indexOf(actual) !== -1, "assert_in_array", description, - "value ${actual} not in array ${expected}", - {actual: actual, expected: expected}); -} -expose(assert_in_array, 'assert_in_array'); - -/** Assert that |expected| and |actual| have all the same properties, - which are, recursively, strictly equal. For primitive types this - is the same as |assert_equals|. - */ -function assert_deep_equals(actual, expected, description) { - var stack = []; - function check_equal_r(act, exp) { - if (is_primitive_value(exp) || is_primitive_value(act)) { - assert(same_value(act, exp), - "assert_deep_equals", description, - "expected ${exp} but got ${act}" + - " (top level: expected ${expected} but got ${actual})", - {exp: exp, act: act, expected: expected, actual: actual}); - - } else if (stack.indexOf(act) === -1) { - var ka = {}, ke = {}, k; - stack.push(act); - - Object.getOwnPropertyNames(actual).forEach(function (x) { - ka[x] = true; - }); - Object.getOwnPropertyNames(expected).forEach(function (x) { - ke[x] = true; - }); - - for (k in ke) { - assert(k in ka, - "assert_deep_equals", description, - "expected property ${k} missing" + - " (top level: expected ${expected} but got ${actual})", - {k: k, expected: expected, actual: actual}); - - check_equal_r(act[k], exp[k]); - delete ka[k]; - } - for (k in ka) { - assert(false, "assert_deep_equals", description, - "unexpected property ${k}" + - " (top level: expected ${expected} but got ${actual})", - {k: k, expected: expected, actual: actual}); - } - - stack.pop(); - } - } - check_equal_r(actual, expected); -} -expose(assert_deep_equals, 'assert_deep_equals'); - -/** Assert that |expected| and |actual|, both primitive numbers, are - within |epsilon| of each other. */ -function assert_approx_equals(actual, expected, epsilon, description) { - assert(typeof actual === "number", - "assert_approx_equals", description, - "expected a number but got a ${type_actual}", - {type_actual: typeof actual}); - assert(typeof expected === "number", - "assert_approx_equals", description, - "expectation should be a number, got a ${type_expected}", - {type_expected: typeof expected}); - assert(typeof epsilon === "number", - "assert_approx_equals", description, - "epsilon should be a number but got a ${type_epsilon}", - {type_epsilon: typeof epsilon}); - - assert(Math.abs(actual - expected) <= epsilon, - "assert_approx_equals", description, - "expected ${expected} +/- ${epsilon} but got ${actual}", - {expected: expected, actual: actual, epsilon: epsilon}); -} -expose(assert_approx_equals, 'assert_approx_equals'); - -/** Assert that |actual| is less than |expected|, where both are - primitive numbers. */ -function assert_less_than(actual, expected, description) { - assert(typeof actual === "number", - "assert_less_than", description, - "expected a number but got a ${type_actual}", - {type_actual: typeof actual}); - assert(typeof expected === "number", - "assert_approx_equals", description, - "expectation should be a number, got a ${type_expected}", - {type_expected: typeof expected}); - - assert(actual < expected, - "assert_less_than", description, - "expected a number less than ${expected} but got ${actual}", - {expected: expected, actual: actual}); -} -expose(assert_less_than, 'assert_less_than'); - -/** Assert that |actual| is greater than |expected|, where both are - primitive numbers. */ -function assert_greater_than(actual, expected, description) { - assert(typeof actual === "number", - "assert_greater_than", description, - "expected a number but got a ${type_actual}", - {type_actual: typeof actual}); - assert(typeof expected === "number", - "assert_approx_equals", description, - "expectation should be a number, got a ${type_expected}", - {type_expected: typeof expected}); - - assert(actual > expected, - "assert_greater_than", description, - "expected a number greater than ${expected} but got ${actual}", - {expected: expected, actual: actual}); -} -expose(assert_greater_than, 'assert_greater_than'); - -/** Assert that |actual| is less than or equal to |expected|, where - both are primitive numbers. */ -function assert_less_than_equal(actual, expected, description) { - assert(typeof actual === "number", - "assert_less_than_equal", description, - "expected a number but got a ${type_actual}", - {type_actual: typeof actual}); - assert(typeof expected === "number", - "assert_approx_equals", description, - "expectation should be a number, got a ${type_expected}", - {type_expected: typeof expected}); - - assert(actual <= expected, - "assert_less_than", description, - "expected a number less than or equal to ${expected} "+ - "but got ${actual}", - {expected: expected, actual: actual}); -} -expose(assert_less_than_equal, 'assert_less_than_equal'); - -/** Assert that |actual| is greater than or equal to |expected|, where - both are primitive numbers. */ -function assert_greater_than_equal(actual, expected, description) { - assert(typeof actual === "number", - "assert_greater_than_equal", description, - "expected a number but got a ${type_actual}", - {type_actual: typeof actual}); - assert(typeof expected === "number", - "assert_approx_equals", description, - "expectation should be a number, got a ${type_expected}", - {type_expected: typeof expected}); - - assert(actual >= expected, - "assert_greater_than_equal", description, - "expected a number greater than or equal to ${expected} "+ - "but got ${actual}", - {expected: expected, actual: actual}); -} -expose(assert_greater_than_equal, 'assert_greater_than_equal'); - -/** Assert that |actual|, a string, matches a regexp, |expected|. */ -function assert_regexp_match(actual, expected, description) { - assert(expected.test(actual), - "assert_regexp_match", description, - "expected ${actual} to match ${expected}", - {expected: expected, actual: actual}); -} -expose(assert_regexp_match, 'assert_regexp_match'); - -/** Assert that |actual|, a string, does _not_ match a regexp, |expected|. */ -function assert_regexp_not_match(actual, expected, description) { - assert(!expected.test(actual), - "assert_regexp_not_match", description, - "expected ${actual} not to match ${expected}", - {expected: expected, actual: actual}); -} -expose(assert_regexp_not_match, 'assert_regexp_not_match'); - -/** Assert that |typeof object| is strictly equal to |type|. */ -function assert_type_of(object, type, description) { - assert(typeof object === type, - "assert_type_of", description, - "expected typeof ${object} to be ${expected}, got ${actual}", - {object: object, expected: type, actual: typeof object}); -} -expose(assert_type_of, 'assert_type_of'); - -/** Assert that |object instanceof type|. */ -function assert_instance_of(object, type, description) { - assert(object instanceof type, - "assert_instance_of", description, - "expected ${object} to be instanceof ${expected}", - {object: object, expected: type}); -} -expose(assert_instance_of, 'assert_instance_of'); - -/** Assert that |object| has the class string |expected|. */ -function assert_class_string(object, expected, description) { - var actual = ({}).toString.call(object).slice(8, -1); - assert(actual === expected, - "assert_class_string", description, - "expected ${object} to have class string ${expected}, "+ - "but got ${actual}", - {object: object, expected: expected, actual: actual}); -} -expose(assert_class_string, 'assert_class_string'); - -/** Assert that |object| has a property named |name|. */ -function assert_own_property(object, name, description) { - assert(typeof object === "object", - "assert_own_property", description, - "provided value is not an object"); - - assert("hasOwnProperty" in object, - "assert_own_property", description, - "provided value is an object but has no hasOwnProperty method"); - - assert(object.hasOwnProperty(name), - "assert_own_property", description, - "expected property ${name} missing", {name: name}); -} -expose(assert_own_property, 'assert_own_property'); - -/** Assert that |object| inherits a property named |name|. - Note: this assertion will fail for objects that have an - own-property named |name|. */ -function assert_inherits(object, name, description) { - assert(typeof object === "object", - "assert_inherits", description, - "provided value is not an object"); - - assert("hasOwnProperty" in object, - "assert_inherits", description, - "provided value is an object but has no hasOwnProperty method"); - - assert(!object.hasOwnProperty(name), - "assert_inherits", description, - "property ${p} found on object, expected only in prototype chain", - {p: name}); - - assert(name in object, - "assert_inherits", description, - "property ${p} not found in prototype chain", - {p: name}); - -} -expose(assert_inherits, 'assert_inherits'); - -/** Assert that |object| neither has nor inherits a property named |name|. */ -function assert_no_property(object, name, description) { - assert(typeof object === "object", - "assert_no_property", description, - "provided value is not an object"); - - assert("hasOwnProperty" in object, - "assert_no_property", description, - "provided value is an object but has no hasOwnProperty method"); - - assert(!object.hasOwnProperty(name), - "assert_no_property", description, - "property ${p} found on object, expected to be absent", - {p: name}); - - assert(!(name in object), - "assert_no_property", description, - "property ${p} found in prototype chain, expected to be absent", - {p: name}); -} -expose(assert_no_property, 'assert_no_property'); - -/** Assert that property |name| of |object| is read-only according - to its property descriptor. */ -function assert_readonly(object, name, description) { - var o = {}, desc; - - assert('getOwnPropertyDescriptor' in o, - "assert_readonly", description, - "Object.getOwnPropertyDescriptor is missing"); - - assert(object.hasOwnProperty(name), - "assert_readonly", description, - "expected property ${name} missing", {name: name}); - - desc = o.getOwnPropertyDescriptor.call(object, name); - if ('writable' in desc) { - assert(!desc.writable, "assert_readonly", description, - "data property ${name} is writable (expected read-only)", - {name: name}); - } else { - assert('get' in desc && 'set' in desc, - "assert_readonly", description, - "unrecognized type of property descriptor "+ - "for ${name}: ${desc}", - {name: name, desc: desc}); - assert(desc.set === undefined, - "assert_readonly", description, - "property ${name} has a setter (expected read-only)", - {name: name, desc: desc}); - } -} -expose(assert_readonly, 'assert_readonly'); - -/** Assert that |func| throws an exception described by |code|. - |func| is called with no arguments and no |this| -- use bind() if - that's a problem. |code| can take one of two forms: - - string - the thrown exception must be a DOMException with the - given name, e.g., "TimeoutError", or else it must - stringify to this string. - - object - must have one or more of the properties "code", "name", - and "message". Whichever properties are present must - match the corresponding properties of the thrown - exception. As a special case, "message" will also match - the stringification of the exception. -*/ - -function assert_throws(code, func, description) { - var name_code_map = { - IndexSizeError: 1, - HierarchyRequestError: 3, - WrongDocumentError: 4, - InvalidCharacterError: 5, - NoModificationAllowedError: 7, - NotFoundError: 8, - NotSupportedError: 9, - InvalidStateError: 11, - SyntaxError: 12, - InvalidModificationError: 13, - NamespaceError: 14, - InvalidAccessError: 15, - TypeMismatchError: 17, - SecurityError: 18, - NetworkError: 19, - AbortError: 20, - URLMismatchError: 21, - QuotaExceededError: 22, - TimeoutError: 23, - InvalidNodeTypeError: 24, - DataCloneError: 25, - - UnknownError: 0, - ConstraintError: 0, - DataError: 0, - TransactionInactiveError: 0, - ReadOnlyError: 0, - VersionError: 0 - }; - - if (typeof code === "object") { - assert("name" in code || "code" in code || "message" in code, - "assert_throws", description, - "exception spec ${code} has no 'name', 'code', or 'message'" + - "properties", - {code: code}); - } else if (name_code_map.hasOwnProperty(code)) { - code = { name: code, - code: name_code_map[code] }; - } else { - code = { message: code.toString() }; - } - - try { - func(); - assert(false, "assert_throws", description, - "${func} did not throw", {func: func}); - } catch (e) { - if (e instanceof AssertionError) { - throw e; - } - - // Backward compatibility wart for DOMExceptions identified - // only by numeric code. - if ("code" in code && code.code !== 0 && - (!("name" in e) || e.name === e.name.toUpperCase() || - e.name === "DOMException")) - delete code.name; - - if ("name" in code) { - assert("name" in e && e.name === code.name, - "assert_throws", description, - "${func} threw ${actual} (${actual_name}), "+ - "expected ${expected} (${expected_name})", - {func: func, actual: e, actual_name: e.name, - expected: code, - expected_name: code.name}); - } - if ("code" in code) { - assert("code" in e && e.code === code.code, - "assert_throws", description, - "${func} threw ${actual} (${actual_code}), "+ - "expected ${expected} (${expected_code})", - {func: func, actual: e, actual_code: e.code, - expected: code, - expected_code: code.code}); - } - if ("message" in code) { - if (Object.hasOwnProperty.call(e, "message")) { - assert(e.message === code.message, - "assert_throws", description, - "${func} threw ${actual} (${actual_message}), "+ - "expected ${expected} (${expected_message})", - {func: func, actual: e, actual_message: e.message, - expected: code, expected_message: code.message}); - } else { - // Intentional use of loose equality - assert(e == code.message, - "assert_throws", description, - "${func} threw ${actual}, expected ${expected})", - {func: func, actual: e, expected: code.message}); - } - } - } -} -expose(assert_throws, 'assert_throws'); - -/** Assert that control flow cannot reach the point where this - assertion appears. */ -function assert_unreached(description) { - assert(false, "assert_unreached", description, - "reached unreachable code"); -} -expose(assert_unreached, 'assert_unreached'); - -/** Test object. - * These must be created by calling test() or async_test(), but - * many of their methods are part of the public API. - */ - -function Test(name, properties) { - this.name = name; - this.phase = Test.phases.INITIAL; - this.in_done = false; - this.status = Test.NOTRUN; - this.timeout_id = null; - this.message = null; - this.steps = []; - this.cleanup_callbacks = []; - - if (!properties) { - properties = {}; - } - this.properties = properties; - this.timeout_length = properties.timeout ? properties.timeout - : tests.test_timeout_length; - this.should_run = !properties.skip; - tests.push(this); - this.number = tests.tests.length; - - if (!this.should_run) { - // Fake initial step that _does_ run, but short-circuits the test. - // All other steps will be marked not to be run via the defaults - // in step(). The step function does not call done() because that - // would record a success. We can't do this ourselves because the - // plan line has not been emitted yet. - var stepdata = this.step(function () { - this.phase = Test.phases.COMPLETE; - tests.result(this); - }); - stepdata.should_run = true; - stepdata.auto_run = true; - } -} - -Test.phases = { - INITIAL: 0, - STARTED: 1, - HAS_RESULT: 2, - COMPLETE: 3 -}; -Test.statuses = { - NOTRUN: -1, - PASS: 0, - FAIL: 1, - XFAIL: 4, - XPASS: 5 -}; -Test.prototype.phases = Test.phases; -Test.prototype.statuses = Test.phases; - -(function() { - var x; - var o = Test.statuses; - for (x in o) { - if (o.hasOwnProperty(x)) { - Test[x] = Test.statuses[x]; - Test.prototype[x] = Test.statuses[x]; - } - } -})(); - -/** Queue one step of a test. |func| will eventually be called, with - |this| set to |this_obj|, or to the Test object if |this_obj| is - absent. Any further arguments will be passed down to |func|. It - should carry out some tests using assert_* and eventually return. - |func| will _not_ be called if a previous step of the test has - already failed. - - Returns an object which can be passed to this.perform_step() to - cause |func| actually to be called -- but you should not do this - yourself unless absolutely unavoidable. - */ -Test.prototype.step = function step(func, this_obj) { - if (this_obj == null) { - this_obj = this; - } - func = func.bind(this_obj, ...Array.prototype.slice.call(arguments, 2)); - - var stepdata = { - func: func, - should_run: this.should_run, - auto_run: this.should_run, - has_run: false - }; - - this.steps.push(stepdata); - return stepdata; -}; - -/** Internal: perform one step of a test. - */ -Test.prototype.perform_step = function perform_step(stepdata) { - var message; - - if (this.phase > this.phases.STARTED || - tests.phase > tests.phases.HAVE_RESULTS) { - return undefined; - } - - this.phase = this.phases.STARTED; - tests.started = true; - stepdata.has_run = true; - - // Arm the local timeout if it hasn't happened already. - if (this.timeout_id === null && this.timeout_length !== null) { - this.timeout_id = setTimeout(this.force_timeout.bind(this), - this.timeout_length); - } - - var rv = undefined; - try { - rv = stepdata.func(); - } catch (e) { - this.fail(format_exception(e)); - } - return rv; -}; - -/** Mark this test as failed. */ -Test.prototype.fail = function fail(message) { - if (this.phase < this.phases.HAS_RESULT) { - this.message = message; - this.status = this.FAIL; - this.phase = this.phases.HAS_RESULT; - if (!this.in_done) { - this.done(); - } - } else { - tests.output.error(message); - } -}; - -/** Mark this test as completed. */ -Test.prototype.done = function done() { - var i; - - this.in_done = true; - - if (this.timeout_id !== null) { - clearTimeout(this.timeout_id); - this.timeout_id = null; - } - - if (this.phase == this.phases.COMPLETE) { - return; - } - - // Cleanups run in reverse order (most recently added first). - for (i = this.cleanup_callbacks.length - 1; i >= 0; i--) { - try { - this.cleanup_callbacks[i].call(this); - } catch (e) { - this.fail("In cleanup: " + format_exception(e)); - } - } - - // If any step of the test was not run (except those that are not - // _supposed_ to run), and no previous error was detected, that is - // an error. - if (this.phase < this.phases.HAS_RESULT) { - for (i = 0; i < this.steps.length; i++) { - if (this.steps[i].should_run && !this.steps[i].has_run) { - this.fail("Step "+i+" was not run"); - } else if (!this.steps[i].should_run && this.steps[i].has_run) { - this.fail("Step "+i+" should not have run"); - } - } - } - - if (this.phase == this.phases.STARTED) { - this.message = null; - this.status = this.PASS; - } - - if (this.properties.expected_fail) { - if (this.status === this.PASS) { - this.status = this.XPASS; - } else if (this.status === this.FAIL) { - this.status = this.XFAIL; - } - } - - this.phase = this.phases.COMPLETE; - - tests.result(this); - -}; - -/** Register |func| as a step function, and return a function that - will run |func|'s step when called. The arguments to |func| are - whatever the arguments to the callback were, and |this| is - |this_obj|, which defaults to the Test object. Useful as an event - handler, for instance. */ -Test.prototype.step_func = function(func, this_obj) { - var test_this = this; - var cb_args = []; - if (arguments.length === 1) { - this_obj = test_this; - } - - // The function returned stashes its arguments in |cb_args|, then - // the registered step function uses them to call |func| with the - // appropriate arguments. We have to do it this way because - // perform_step() doesn't forward its arguments. - var stepdata = this.step(function cb_step () { - return func.apply(this_obj, cb_args); - }); - - stepdata.auto_run = false; - return function() { - cb_args = Array.prototype.slice.call(arguments); - return test_this.perform_step(stepdata); - }; -}; - -/** As |step_func|, but the step calls this.done() after |func| - returns (regardless of what it returns). |func| may be omitted, - in which case the step just calls this.done(). */ -Test.prototype.step_func_done = function(func, this_obj) { - var test_this = this; - var cb_args = []; - - if (arguments.length <= 1) { - this_obj = test_this; - } - if (!func) { - func = function () {}; - } - - // The function returned stashes its arguments in |cb_args|, then - // the registered step function uses them to call |func| with the - // appropriate arguments. We have to do it this way because - // perform_step() doesn't forward its arguments. - var stepdata = this.step(function cb_done_step () { - var rv = func.apply(this_obj, cb_args); - test_this.done(); - return rv; - }); - - stepdata.auto_run = false; - return function() { - cb_args = Array.prototype.slice.call(arguments); - return test_this.perform_step(stepdata); - }; -}; - -/** Returns a function that, if called, will call assert_unreached() - inside a perform_step() invocation. Use to set event handlers for - events that should _not_ happen. */ -Test.prototype.unreached_func = function unreached_func(description) { - var test_this = this; - var stepdata = this.step(function unreached_step () { - assert_unreached(description); - }); - stepdata.should_run = false; - stepdata.auto_run = false; - - return function() { test_this.perform_step(stepdata); }; -}; - -/** Register |callback| to be called once this test is done. */ -Test.prototype.add_cleanup = function add_cleanup(callback) { - this.cleanup_callbacks.push(callback); -}; - -/** Treat this test as having timed out. */ -Test.prototype.force_timeout = function force_timeout() { - this.message = "Test timed out"; - this.status = this.FAIL; - this.phase = this.phases.HAS_RESULT; - this.done(); -}; - - -/* - * Private implementation logic begins at this point. - */ - -/* - * The Tests object is responsible for tracking the complete set of - * tests in this file. - */ - -function Tests(output) { - this.tests = []; - this.num_pending = 0; - - this.all_loaded = false; - this.wait_for_finish = false; - this.allow_uncaught_exception = false; - - this.test_timeout_length = settings.test_timeout; - this.harness_timeout_length = settings.harness_timeout; - this.timeout_id = null; - - this.properties = {}; - this.phase = Test.phases.INITIAL; - this.output = output; - - var this_obj = this; - phantom.onError = function (message, stack) { - if (!tests.allow_uncaught_exception) { - this_obj.output.error(message); - } - if (this_obj.all_done()) { - this_obj.complete(); - } - }; - phantom.page.onConsoleMessage = function (message) { - if (!tests.allow_uncaught_exception) { - this_obj.output.error("stray console message: " + message); - } - }; - this.set_timeout(); -} - -Tests.phases = { - INITIAL: 0, - SETUP: 1, - HAVE_TESTS: 2, - HAVE_RESULTS: 3, - ABANDONED: 4, - COMPLETE: 5 -}; -Tests.prototype.phases = Tests.phases; - -Tests.prototype.setup = function setup(func, properties) { - if (this.phase >= this.phases.HAVE_RESULTS) { - return; - } - - if (this.phase < this.phases.SETUP) { - this.phase = this.phases.SETUP; - } - - this.properties = properties; - - for (var p in properties) { - if (properties.hasOwnProperty(p)) { - var value = properties[p]; - if (p == "allow_uncaught_exception") { - this.allow_uncaught_exception = value; - } else if (p == "explicit_done" && value) { - this.wait_for_finish = true; - } else if (p == "timeout" && value) { - this.harness_timeout_length = value; - } else if (p == "test_timeout") { - this.test_timeout_length = value; - } - } - } - this.set_timeout(); - - if (func) { - try { - func(); - } catch (e) { - this.output.error(e); - this.phase = this.phases.ABANDONED; - } - } -}; - -Tests.prototype.set_timeout = function set_timeout() { - var this_obj = this; - clearTimeout(this.timeout_id); - if (this.harness_timeout_length !== null) { - this.timeout_id = setTimeout(function () { this_obj.timeout(); }, - this.harness_timeout_length); - } -}; - -Tests.prototype.timeout = function timeout() { - this.output.error("Global timeout expired"); - for (var i = 0; i < tests.tests.length; i++) { - var t = tests.tests[i]; - if (t.phase < Test.phases.HAS_RESULT) { - t.force_timeout(); - } - } - this.complete(); -}; - -Tests.prototype.end_wait = function end_wait() { - this.wait_for_finish = false; - if (this.all_done()) { - this.complete(); - } -}; - -Tests.prototype.push = function push(test) -{ - if (this.phase < this.phases.HAVE_TESTS) { - this.phase = this.phases.HAVE_TESTS; - } - this.num_pending++; - this.tests.push(test); -}; - -Tests.prototype.all_done = function all_done() { - return (this.tests.length > 0 && - this.all_loaded && - this.num_pending === 0 && - !this.wait_for_finish); -}; - -Tests.prototype.result = function result(test) { - if (this.phase < this.phases.HAVE_RESULTS) { - this.phase = this.phases.HAVE_RESULTS; - } - this.num_pending--; - this.output.result(test); - if (this.all_done()) { - this.complete(); - } else { - setTimeout(this.run_tests.bind(this), 0); - } -}; - -Tests.prototype.run_tests = function run_tests() { - if (this.phase >= this.phases.COMPLETE) { - return; - } - if (this.all_done() || this.phase >= this.phases.ABANDONED) { - this.complete(); - return; - } - for (var i = 0; i < this.tests.length; i++) { - var t = this.tests[i]; - if (t.phase < t.phases.STARTED && t.steps.length > 0) { - for (var j = 0; j < t.steps.length; j++) { - if (t.steps[j].auto_run) { - t.perform_step(t.steps[j]); - } - } - // We will come back here via the setTimeout in - // Tests.prototype.result. - break; - } - } -}; - -Tests.prototype.begin = function begin() { - this.all_loaded = true; - this.output.begin(this.tests.length, this.phase); - this.run_tests(); - if (this.all_done()) { - this.complete(); - } -}; - -Tests.prototype.complete = function complete() { - var i, x; - - if (this.phase === this.phases.COMPLETE) { - return; - } - for (i = 0; i < this.tests.length; i++) { - this.tests[i].done(); - } - - this.phase = this.phases.COMPLETE; - this.output.complete(this); -}; - -/* - * The Output object is responsible for reporting the status of each - * test. For PhantomJS, output is much simpler than for the W3C - * harness; we basically just log things to the console as - * appropriate. The output format is meant to be compatible with - * TAP (http://testanything.org/tap-specification.html). - */ - -function Output(fp, verbose) { - this.fp = fp; - this.verbose = verbose; - this.failed = false; -} - -Output.prototype.begin = function begin(n, phase) { - if (phase === Tests.phases.ABANDONED) { - this.fp.write("1..0 # SKIP: setup failed\n"); - } else { - this.fp.write("1.." + n + "\n"); - } -}; - -Output.prototype.diagnostic = function diagnostic(message, is_info) { - var fp = this.fp; - var prefix = "# "; - if (is_info) { - prefix = "## "; - } - message.split("\n").forEach(function (line) { - fp.write(prefix + line + "\n"); - }); -}; - -Output.prototype.error = function error(message) { - this.diagnostic("ERROR: " + message); - this.failed = true; -}; - -Output.prototype.info = function info(message) { - this.diagnostic(message, true); -}; - -Output.prototype.result = function result(test) { - if (test.message) { - this.diagnostic(test.message); - } - var prefix, directive = ""; - switch (test.status) { - case Test.PASS: prefix = "ok "; break; - case Test.FAIL: prefix = "not ok "; break; - case Test.XPASS: prefix = "ok "; directive = " # TODO"; break; - case Test.XFAIL: prefix = "not ok "; directive = " # TODO"; break; - case Test.NOTRUN: prefix = "ok "; directive = " # SKIP"; break; - default: - this.error("Unrecognized test status " + test.status); - prefix = "not ok "; - } - if ((prefix === "not ok " && directive !== " # TODO") || - (prefix === "ok " && directive === " # TODO")) { - this.failed = true; - } - this.fp.write(prefix + test.number + " " + test.name + directive + "\n"); -}; - -Output.prototype.complete = function complete(tests) { - phantom.exit(this.failed ? 1 : 0); -}; - -/* - * Utilities. - */ - -function expose(fn, name) { - window[name] = fn; -} - -/** This function is not part of the public API, but its - *behavior* is part of the contract of several assert_* functions. */ -function same_value(x, y) { - if (x === y) { - // Distinguish +0 and -0 - if (x === 0 && y === 0) { - return 1/x === 1/y; - } - return true; - } else { - // NaN !== _everything_, including another NaN. - // Make it same_value as itself. - if (x !== x) { - return y !== y; - } - // Compare Date and RegExp by value. - if (x instanceof Date) { - return y instanceof Date && x.getTime() === y.getTime(); - } - if (x instanceof RegExp) { - return y instanceof RegExp && x.toString() === y.toString(); - } - return false; - } -} - -/** Similarly, this function's behavior is part of the contract of - assert_deep_equals. (These are the things for which it will just - call same_value rather than doing a recursive property comparison.) */ -function is_primitive_value(val) { - return (val === undefined || val === null || typeof val !== 'object' || - val instanceof Date || val instanceof RegExp); -} - -var names_used = {}; -function test_name(func, name) { - var n, c; - - if (name) - ; - else if (func && func.displayName) - name = func.displayName; - else if (func && func.name) - name = func.name; - else - name = "test"; - - n = name; - c = 0; - while (n in names_used) { - n = name + "." + c.toString(); - c += 1; - } - return n; -} - -function AssertionError(message) { - this.message = message; -} - -AssertionError.prototype.toString = function toString() { - return this.message; -}; - -function assert(expected_true, name, description, error, substitutions) { - if (expected_true !== true) { - throw new AssertionError(make_message( - name, description, error, substitutions)); - } else if (output.verbose >= 4) { - output.info(make_message(name, description, error, substitutions)); - } -} - -function make_message(function_name, description, error, substitutions) { - var p, message; - - for (p in substitutions) { - if (substitutions.hasOwnProperty(p)) { - substitutions[p] = format_value(substitutions[p]); - } - } - - if (description) { - description += ": "; - } else { - description = ""; - } - - return (function_name + ": " + description + - error.replace(/\$\{[^}]+\}/g, function (match) { - return substitutions[match.slice(2,-1)]; - })); -} - -function format_value(val, seen) { - if (seen === undefined) - seen = []; - - var s; - function truncate(s, len) { - if (s.length > len) { - return s.slice(-3) + "..."; - } - return s; - } - - switch (typeof val) { - case "number": - // In JavaScript, -0 === 0 and String(-0) == "0", so we have to - // special-case. - if (val === -0 && 1/val === -Infinity) { - return "-0"; - } - // falls through - case "boolean": - case "undefined": - return String(val); - - case "string": - // Escape ", \, all C0 and C1 control characters, and - // Unicode's LINE SEPARATOR and PARAGRAPH SEPARATOR. - // The latter two are the only characters above U+009F - // that may not appear verbatim in a JS string constant. - val = val.replace(/["\\\u0000-\u001f\u007f-\u009f\u2028\u2029]/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: - // We know by construction that c is - // a single BMP character. - c = c.charCodeAt(0); - if (c < 0x0080) { - return "\\x" + - ("00" + c.toString(16)).slice(-2); - } else { - return "\\u" + - ("0000" + c.toString(16)).slice(-4); - } - } - }); - return '"' + val + '"'; - - case "object": - if (val === null) { - return "null"; - } - if (seen.indexOf(val) >= 0) { - return ""; - } - seen.push(val); - - if (Array.isArray(val)) { - return "[" + val.map(function (x) { - return format_value(x, seen); - }).join(", ") + "]"; - } - - s = String(val); - if (s != "[object Object]") { - return truncate(s, 60); - } - return "{ " + Object.keys(val).map(function (k) { - return format_value(k, seen) + ": " + format_value(val[k], seen); - }).join(", ") + "}"; - - default: - return typeof val + ' "' + truncate(String(val), 60) + '"'; - } -} - -function format_exception (e) { - var message = (typeof e === "object" && e !== null) ? e.message : e; - if (typeof e.stack != "undefined" && typeof e.message == "string") { - // Prune the stack. This knows the format of WebKit's stack traces. - var stack = e.stack.split("\n"); - var lo, hi; - // We do not need to hear about initial lines naming the - // assertion function. - for (lo = 0; lo < stack.length; lo++) { - if (!/^assert(?:_[a-z0-9_]+)?@.*?testharness\.js:/ - .test(stack[lo])) { - break; - } - } - // We do not need to hear about how we got _to_ the test function. - // The caller of the test function is guaranteed to have "_step" in - // its name. - for (hi = lo; hi < stack.length; hi++) { - if (/^[a-z_]+_step.*?testharness\.js:/.test(stack[hi])) { - break; - } - } - if (lo < stack.length && lo < hi) { - stack = stack.slice(lo, hi); - } - message += "\n"; - message += stack.join("\n"); - } - return message; -} - -function process_command_line(sys) { - function usage(error) { - sys.stderr.write("error: " + error + "\n"); - sys.stderr.write("usage: " + sys.args[0] + - " [--verbose=N] test_script.js ...\n"); - } - var args = { verbose: -1, - test_script: "" }; - - for (var i = 1; i < sys.args.length; i++) { - if (sys.args[i].length === 0) { - usage("empty argument is not meaningful"); - return args; - } - if (sys.args[i][0] !== '-') { - args.test_script = sys.args[i]; - break; - } - var n = "--verbose=".length; - var v = sys.args[i].slice(0, n); - var a = sys.args[i].slice(n); - if (v === "--verbose=" && /^[0-9]+$/.test(a)) { - if (args.verbose === -1) { - args.verbose = parseInt(a, 10); - continue; - } else { - usage("--verbose specified twice"); - return args; - } - } - usage("unrecognized option " + format_value(sys.args[i])); - return args; - } - - if (args.test_script === "") { - usage("no test script specified"); - return args; - } - - if (args.verbose === -1) { - args.verbose = 0; - } - - return args; -} - -/* - * Global state - */ - -var settings = { - harness_timeout: 5000, - test_timeout: null -}; - -var sys = require('system'); -var fs = require('fs'); -var args = process_command_line(sys); - -if (args.test_script === "") { - // process_command_line has already issued an error message. - phantom.exit(2); -} else { - // Reset the library paths for injectJs and require to the - // directory containing the test script, so relative imports work - // as expected. Unfortunately, phantom.libraryPath is not a - // proper search path -- it can only hold one directory at a time. - // require.paths has no such limitation. - var test_script = fs.absolute(args.test_script); - phantom.libraryPath = test_script.slice(0, - test_script.lastIndexOf(fs.separator)); - require.paths.push(phantom.libraryPath); - - // run-tests.py sets these environment variables to the base URLs - // of its HTTP and HTTPS servers. - expose(sys.env['TEST_HTTP_BASE'], 'TEST_HTTP_BASE'); - expose(sys.env['TEST_HTTPS_BASE'], 'TEST_HTTPS_BASE'); - - var output = new Output(sys.stdout, args.verbose); - var tests = new Tests(output); - - // This evaluates the test script synchronously. - // Any errors should be caught by our onError hook. - phantom.injectJs(test_script); - - tests.begin(); -} - -})(); diff --git a/third_party/phantomjs/test/writing-tests.md b/third_party/phantomjs/test/writing-tests.md deleted file mode 100644 index c04f27beaa0..00000000000 --- a/third_party/phantomjs/test/writing-tests.md +++ /dev/null @@ -1,596 +0,0 @@ -# How to Write Tests for PhantomJS - -PhantomJS's automated tests are `.js` files located in subdirectories -of this directory. The test runner, [`run-tests.py`](run-tests.py), -executes each as a PhantomJS controller script. (Not all -subdirectories of this directory contain tests; the authoritative list -of test subdirectories is in -[the `TESTS` variable in `run-tests.py`](run-tests.py#L26).) - -In addition to all of the usual PhantomJS API, these scripts have -access to a special testing API, loosely based on -[W3C testharness.js](https://github.com/w3c/testharness.js) and -defined in [`testharness.js`](testharness.js) in this directory. They -also have access to HTTP and HTTPS servers on `localhost`, which serve -the files in the [`www`](www) directory. - -## The Structure of Test Scripts - -Test scripts are divided into _subtests_. There are two kinds of -subtest: synchronous and asynchronous. The only difference is that a -synchronous subtest consists of a single JavaScript function (plus -anything it calls) and is considered to be complete when that function -returns. An asynchronous subtest, however, consists of many -JavaScript functions; these functions are referred to as _steps_. One -step will be invoked to start the subtest, and the others are called -in response to events. Eventually one of the steps will indicate that -the subtest is complete. (The single function used for a synchronous -subtest is also referred to as a step, when the difference doesn't -matter.) - -All of the code in a test script should be part of a subtest, or part -of a setup function (see below). You may define helper functions at -top level, so long as they are only ever _called_ from subtests. You -may also initialize global variables at top level if this -initialization cannot possibly fail, e.g. with constant data or with -`require` calls for core PhantomJS modules. - -The testing API is visible to a test script as a collection of global -functions and variables, documented below. - -A subtest is considered to have failed if any of its steps throws a -JavaScript exception, if an `unreached_func` is called, if the -per-test timeout expires, or if `done` is called before all of its -steps have run. It is considered to succeed if `done` is called -(explicitly or implicitly) after all of its steps have run to -completion. Normally, you should use the assertion functions to detect -failure conditions; these ensure that clear diagnostic information is -printed when a test fails. - -Subtests are executed strictly in the order they appear in the file, -even if some of them are synchronous and some are asynchronous. The -order of steps *within* an asynchronous subtest, however, may be -unpredictable. Also, subtests do not begin to execute until after all -top-level code in the file has been evaluated. - -Some anomalous conditions are reported not as a failure, but as an -"error". For instance, if PhantomJS crashes during a test run, or if -an exception is thrown from outside a step, that is an error, and the -entire test will be abandoned. - -**WARNING:** The harness will become confused if any function passed -as the `func` argument to `test`, `async_test`, `generate_tests`, -`Test.step`, `Test.step_func`, `Test.step_func_done`, or -`Test.add_cleanup` has a name that ends with `_step`. - -### Accessing the HTTP and HTTPS Test Servers - -The global variables `TEST_HTTP_BASE` and `TEST_HTTPS_BASE` are the -base URLs of the test HTTP and HTTPS servers, respectively. Their -values are guaranteed to match the regex `/https?:\/\/localhost:[0-9]+\//`, -but the port number is dynamically assigned for each test run, so you -must not hardwire it. - -### Synchronous Subtests - -There are two functions for defining synchronous subtests. - -* `test(func, name, properties)` - - Run `func` as a subtest; the subtest is considered to be complete as - soon as it returns. `name` is an optional descriptive name for the - subtest. `func` will be called with no arguments, and `this` set to - a `Test` object (see below). `properties` is an optional object - containing properties to apply to the test. Currently there are - three meaningful properties; any other keys in the `properties` - object are ignored: - - * `timeout` - Maximum amount of time the subtest is allowed to run, in - milliseconds. If the timeout expires, the subtest will be - considered to have failed. - - * `expected_fail`: If truthy, this subtest is expected to fail. It will - still be run, but a failure will be considered "normal" and the - overall test will be reported as successful. Conversely, if the - subtest *succeeds* that is considered "abnormal" and the overall - test will be reported as failing. - - * `skip`: If truthy, this subtest will not be run at all, will be - reported as "skipped" rather than "succeeded" or "failed", and - will not affect the overall outcome of the test. Use `skip` only - when `expected_fail` will not do—for instance, when a test - provokes a PhantomJS crash (there currently being no way to label - a crash as "expected"). - - `test` returns the same `Test` object that is available as `this` - within `func`. - -* `generate_tests(func, args, properties)` - - Define a group of synchronous subtests, each of which will call - `func`, but with different arguments. This is easiest to explain by - example: - - generate_tests(assert_equals, [ - ["Sum one and one", 1 + 1, 2], - ["Sum one and zero", 1 + 0, 1] - ]); - - ... is equivalent to ... - - test(function() {assert_equals(1+1, 2)}, "Sum one and one"); - test(function() {assert_equals(1+0, 1)}, "Sum one and zero"); - - Of course `func` may be as complicated as you like, and there is no - limit either to the number of arguments passed to each subtest, or - to the number of subtests. - - The `properties` argument may be a single properties object, which - will be applied uniformly to all the subtests, or an array of the - same length as `args`, containing appropriate property objects for - each subtest. - - `generate_tests` returns no value. - -### Asynchronous Subtests - -An asynchronous subtest consists of one or more _step_ functions, and -unlike a synchronous subtest, it is not considered to be complete until -the `done` method is called on its `Test` object. When this happens, -if any of the step functions have not been executed, the subtest is a -failure. - -Asynchronous subtests are defined with the `async_test` function, which -is almost the same as `test`: - -* `async_test(func, name, properties)` - - Define an asynchronous subtest. The arguments and their - interpretation are the same as for `test`, except that `func` is - optional, and the subtest is *not* considered to be complete after - `func` returns; `func` (if present) is only the first step of the - subtest. Additional steps may be defined, either within `func` or - outside the call to `async_test`, by use of methods on the `Test` - object that is returned (and available as `this` within `func`). - - Normally, an asynchronous subtest's first step will set up whatever - is being tested, and define the remainder of the steps, which will - be run in response to events. - -### Test Object Methods - -These methods are provided by the `Test` object which is returned by -`test` and `async_test`, and available as `this` within step -functions. - -* `Test.step(func[, this_obj, ...])` - - Queue one step of a subtest. `func` will eventually be called, with - `this` set to `this_obj`, or (if `this_obj` is null or absent) to - the `Test` object. Any further arguments will be passed down to - `func`. `func` will _not_ be called if a previous step has failed. - - Do not use this function to define steps that should run in response - to event callbacks; only steps that should be automatically run by - the test harness. - - The object returned by this function is private. Please let us know - if you think you need to use it. - -* `Test.done()` - - Indicate that this subtest is complete. One, and only one, step of - an asynchronous subtest must call this function, or the subtest will - never complete (and eventually it will time out). - - If an asynchronous subtest has several steps, but not all of them - have run when `done` is called, the subtest is considered to have - failed. - -* `Test.step_func(func[, this_obj])` - - Register `func` as a step that will *not* be run automatically by - the test harness. Instead, the function *returned* by this function - (the "callback") will run `func`'s step when it is called. - (`func`'s step must still somehow get run before `done` is called, - or the subtest will be considered to have failed.) - - `this_obj` will be supplied as `this` to `func`; if omitted, it - defaults to the `Test` object. Further arguments are ignored. - However, `func` will receive all of the arguments passed to the - callback, and the callback will return whatever `func` returns. - - This is the normal way to register a step that should run in - response to an event. For instance, here is a minimal test of a - page load: - - async_test(function () { - var p = require('webpage').create(); - p.open(TEST_HTTP_BASE + 'hello.html', - this.step_func(function (status) { - assert_equals(status, 'success'); - this.done(); - })); - }); - - This also serves to illustrate why asynchronous subtests may be - necessary: this subtest is not complete when its first step returns, - only when the `onLoadFinished` event fires. - -* `Test.step_func_done([func[, this_obj]])` - - Same as `Test.step_func`, but the callback additionally calls `done` - after `func` returns. `func` may be omitted, in which case the - callback just calls `done`. - - The example above can be shortened to - - async_test(function () { - var p = require('webpage').create(); - p.open(TEST_HTTP_BASE + 'hello.html', - this.step_func_done(function (status) { - assert_equals(status, 'success'); - })); - }); - -* `Test.unreached_func([description])` - - Returns a function that, if called, will call - `assert_unreached(description)` inside a step. Use this to set - event handlers for events that should _not_ happen. You need to use - this method instead of `step_func(function () { assert_unreached(); })` - so the step is properly marked as expected _not_ to run; otherwise - the test will fail whether or not the event happens. - - A slightly more thorough test of a page load might read - - async_test(function () { - var p = require('webpage').create(); - p.onResourceError = this.unreached_func("onResourceError"); - p.open(TEST_HTTP_BASE + 'hello.html', - this.step_func_done(function (status) { - assert_equals(status, 'success'); - })); - }); - -* `Test.add_cleanup(func)` - - Register `func` to be called (with no arguments, and `this` set to - the `Test` object) when `done` is called, whether or not the subtest - has failed. Use this to deallocate persistent resources or undo - changes to global state. For example, a subtest that uses a scratch - file might read - - test(function () { - var fs = require('fs'); - var f = fs.open('scratch_file', 'w'); - this.add_cleanup(function () { - f.close(); - fs.remove('scratch_file'); - }); - - // ... more test logic here ... - }); - - If the step function had simply deleted the file at its end, the - file would only get deleted when the test succeeds. This example - could be rewritten using `try ... finally ...`, but that will not - work for asynchronous tests. - -* `Test.fail(message)` - - Explicitly mark this subtest has having failed, with failure message - `message`. You should not normally need to call this function yourself. - -* `Test.force_timeout()` - - Explicitly mark this subtest as having failed because its timeout has - expired. You should not normally need to call this function yourself. - -### Test Script-Wide Setup - -All of the subtests of a test script are normally run, even if one of -them fails. Complex tests may involve complex initialization actions -that may fail, in which case the entire test script should be aborted. -There is also a small amount of harness-wide configuration that is -possible. Both these tasks are handled by the global function -`setup`. - -* `setup([func], [properties])` - - One may specify either `func` or `properties` or both, but if both - are specified, `func` must be first. - - `func` is called immediately, with no arguments. If it throws an - exception, the entire test script is considered to have failed and - none of the subtests are run. - - `properties` is an object containing one or more of the following - keys: - - * `explicit_done`: Wait for the global function `done` (not to be - confused with `Test.done` to be called, before declaring the test - script complete. - - * `allow_uncaught_exception`: Don't treat an uncaught exception from - non-test code as an error. (Exceptions thrown out of test steps - are still errors.) - - * `timeout`: Overall timeout for the test script, in milliseconds. - The default is five seconds. Note that `run-tests.py` imposes a - "backstop" timeout itself; if you raise this timeout you may also - need to raise that one. - - * `test_timeout`: Default timeout for individual subtests. This may - be overridden by the `timeout` property on a specific subtest. - The default is not to have a timeout for individual subtests. - - -### Assertions - -Whenever possible, use these functions to detect failure conditions. -All of them either throw a JavaScript exception (when the test fails) -or return no value (when the test succeeds). All take one or more -values to be tested, and an optional _description_. If present, the -description should be a string to be printed to clarify why the test -has failed. (The assertions all go to some length to print out values -that were not as expected in a clear format, so descriptions will -often not be necessary.) - -* `assert_is_true(value[, description])` - - `value` must be strictly equal to `true`. - -* `assert_is_false(value[, description])` - - `value` must be strictly equal to `false`. - -* `assert_equals(actual, expected[, description])` - - `actual` and `expected` must be shallowly, strictly equal. The - criterion used is `===` with the following exceptions: - - * If `x === y`, but one of them is `+0` and the other is `-0`, they - are *not* considered equal. - - * If `x !== y`, but one of the following cases holds, they *are* - considered equal: - * both are `NaN` - * both are `Date` objects and `x.getTime() === y.getTime()` - * both are `RegExp` objects and `x.toString() === y.toString()` - -* `assert_not_equals(actual, expected[, description])` - - `actual` and `expected` must *not* be shallowly, strictly equal, - using the same criterion as `assert_equals`. - -* `assert_deep_equals(actual, expected[, description])` - - If `actual` and `expected` are not objects, or if they are - `Date` or `RegExp` objects, this is the same as `assert_equals`. - - Objects that are not `Date` or `RegExp` must have the same set of - own-properties (including non-enumerable own-properties), and each - pair of values for with each own-property must be `deep_equals`, - recursively. Prototype chains are ignored. Back-references are - detected and ignored; they will not cause an infinite recursion. - -* `assert_approx_equals(actual, expected, epsilon[, description])` - - The absolute value of the difference between `actual` and `expected` - must be no greater than `epsilon`. All three arguments must be - primitive numbers. - -* `assert_less_than(actual, expected[, description])` -* `assert_less_than_equal(actual, expected[, description])` -* `assert_greater_than(actual, expected[, description])` -* `assert_greater_than_equal(actual, expected[, description])` - - `actual` and `expected` must be primitive numbers, and `actual` must - be, respectively: less than, less than or equal to, greater than, - greater than or equal to `expected`. - -* `assert_in_array(value, array[, description])` - - `array` must contain `value` according to `Array.indexOf`. - -* `assert_regexp_match(string, regexp[, description])` - - The regular expression `regexp` must match the string `string`, - according to `RegExp.test()`. - -* `assert_regexp_not_match(string, regexp[, description])` - - The regular expression `regexp` must *not* match the string `string`, - according to `RegExp.test()`. - -* `assert_type_of(object, type[, description])` - - `typeof object` must be strictly equal to `type`. - -* `assert_instance_of(object, type[, description])` - - `object instanceof type` must be true. - -* `assert_class_string(object, expected[, description])` - - `object` must have the class string `expected`. The class string is - the second word in the string returned by `Object.prototype.toString`: - for instance, `({}).toString.call([])` returns `[object Array]`, so - `[]`'s class string is `Array`. - -* `assert_own_property(object, name[, description])` - - `object` must have an own-property named `name`. - -* `assert_inherits(object, name[, description])` - - `object` must inherit a property named `name`; that is, - `name in object` must be true but `object.hasOwnProperty(name)` - must be false. - -* `assert_no_property(object, name[, description])` - - `object` must neither have nor inherit a property named `name`. - -* `assert_readonly(object, name[, description])` - - `object` must have an own-property named `name` which is marked - read-only (according to `Object.getOwnPropertyDescriptor`). - -* `assert_throws(code, func[, description])` - - `func` must throw an exception described by `code`. `func` is - called with no arguments and no `this` (you can supply arguments - using `bind`). `code` can take one of two forms. If it is a - string, the thrown exception must either stringify to that string, - or it must be a DOMException whose `name` property is that string. - Otherwise, `code` must be an object with one or more of the - properties `code`, `name`, and `message`; whichever properties are - present must be `===` to the corresponding properties of the - exception. As a special case, if `message` is present in the - `code` object but *not* on the exception object, and the exception - stringifies to the same string as `message`, that's also considered - valid. - - `assert_throws` cannot be used to catch the exception thrown by any - of the other `assert_*` functions when they fail. (You might be - looking for the `expected_fail` property on a subtest.) - -* `assert_unreached([description])` - - Control flow must not reach the point where this assertion appears. - (In other words, this assertion fails unconditionally.) - -## Test Annotations - -Some tests need to be run in a special way. You can indicate this to -the test runner with _annotations_. Annotations are lines in the test -script that begin with the three characters '`//!`'. They must be all -together at the very top of the script; `run-tests.py` stops parsing -at the first line that does _not_ begin with the annotation marker. - -Annotation lines are split into _tokens_ in a shell-like fashion, -which means they are normally separated by whitespace, but you can use -backslashes or quotes to put whitespace inside a token. Backslashes -are significant inside double quotes, but not inside single quotes. -There can be any number of tokens on a line. Everything following an -unquoted, un-backslashed `#` is discarded. (The exact algorithm is -[`shlex.split`](https://docs.python.org/2/library/shlex.html), in -`comments=True`, `posix=True` mode.) - -These are the recognized tokens: - -* `no-harness`: Run this test script directly; the testing API - described above will not be available. This is necessary to - test PhantomJS features that `testharness.js` reserves for its - own use, such as `phantom.onError` and `phantom.exit`. No-harness - tests will usually also be output-expectations tests (see below) - but this is not required. - -* `snakeoil`: Instruct PhantomJS to accept the self-signed - certificate presented by the HTTPS test server. - -* `timeout:` The next token on the line must be a positive - floating-point number. `run-tests.py` will kill the PhantomJS - process, and consider the test to have failed, if it runs for longer - than that many seconds. The default timeout is seven seconds. - - This timeout is separate from the per-subtest and global timeouts - enforced by the testing API. It is intended as a backstop against - bugs which cause PhantomJS to stop executing the controller script. - (In no-harness mode, it's the only timeout, unless you implement - your own.) - -* `phantomjs:` All subsequent tokens on the line will be passed as - command-line arguments to PhantomJS, before the controller script. - Note that `run-tests.py` sets several PhantomJS command line options - itself; you must take care not to do something contradictory. - -* `script:` All subsequent tokens on the line will be passed as - command-line arguments to the *controller script*; that is, they - will be available in - [`system.args`](http://phantomjs.org/api/system/property/args.html). - Note that your controller script will only be `system.args[0]` if - you are using no-harness mode, and that `run-tests.py` may pass - additional script arguments of its own. - -* `stdin:` All subsequent tokens on the line will be concatenated - (separated by a single space) and fed to PhantomJS's standard input, - with a trailing newline. If this token is used more than once, - that produces several lines of input. If this token is not used at - all, standard input will read as empty. - -* `unsupported:` The whole file will be skipped. - This directive should be used to notify that the functionality is not yet - implemented by Puppeteer. Tests could be run ignoring this directive - with the `--run-unsupported` flag. - -## Output-Expectations Tests - -Normally, `run-tests.py` expects each test to produce parseable output -in the [TAP](http://testanything.org/tap-specification.html) format. -This is too inflexible for testing things like `system.stdout.write`, -so there is also a mode in which you specify exactly what output the -test should produce, with additional annotations. Output-expectations -tests are not *required* to be no-harness tests, but the only reason -to use this mode for harness tests would be to test the harness -itself, and it's not sophisticated enough for that. - -Using any of the following annotations makes a test an -output-expectations test: - -* `expect-exit:` The next token on the line must be an integer. If it - is nonnegative, the PhantomJS process is expected to exit with that - exit code. If it is negative, the process is expected to be - terminated by the signal whose number is the absolute value of the - token. (For instance, `expect-exit: -15` for a test that is - expected to hit the backstop timeout.) - -* `expect-stdout:` All subsequent tokens on the line are concatenated, - with spaces in between, and a newline is appeneded. The PhantomJS - process is expected to emit that text, verbatim, on its standard - output. If used more than once, that produces multiple lines of - expected output. - -* `expect-stderr:` Same as `expect-stdout`, but the output is expected - to appear on standard error. - -* `expect-exit-fails`, `expect-stdout-fails`, `expect-stderr-fails`: - The corresponding test (of the exit code, stdout, or stderr) is - expected to fail. - -If some but not all of these annotations are used in a test, the -omitted ones default to exit code 0 (success) and no output on their -respective streams. - -## Test Server Modules - -The HTTP and HTTPS servers exposed to the test suite serve the static -files in the `www` subdirectory with URLs corresponding to their paths -relative to that directory. If you need more complicated server -behavior than that, you can write custom Python code that executes -when the server receives a request. Any `.py` file below the `www` -directory will be invoked to provide the response for that path -*without* the `.py` suffix. (For instance, `www/echo.py` provides -responses for `TEST_HTTP_BASE + 'echo'`.) Such files must define a -top-level function named `handle_request`. This function receives a -single argument, which is an instance of a subclass of -[`BaseHTTPServer.BaseHTTPRequestHandler`](https://docs.python.org/2/library/basehttpserver.html#BaseHTTPServer.BaseHTTPRequestHandler). -The request headers and body (if any) may be retrieved from this -object. The function must use the `send_response`, `send_header`, and -`end_headers` methods of this object to generate HTTP response -headers, and then return a *file-like object* (**not** a string) -containing the response body. The function is responsible for -generating appropriate `Content-Type` and `Content-Length` headers; -the server framework does not do this automatically. - -Test server modules cannot directly cause a test to fail; the server -does not know which test is responsible for any given request. If -there is something wrong with a request, generate an HTTP error -response; then write your test to fail if it receives an error -response. - -Python exceptions thrown by test server modules are treated as -failures *of the testsuite*, but they are all attributed to a virtual -"HTTP server errors" test. diff --git a/third_party/phantomjs/test/www/__init__.py b/third_party/phantomjs/test/www/__init__.py deleted file mode 100644 index b2858867a75..00000000000 --- a/third_party/phantomjs/test/www/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file makes test/www/ into a "package" so that -# importing Python response hooks works correctly. diff --git a/third_party/phantomjs/test/www/delay.py b/third_party/phantomjs/test/www/delay.py deleted file mode 100644 index 9653499eb8b..00000000000 --- a/third_party/phantomjs/test/www/delay.py +++ /dev/null @@ -1,15 +0,0 @@ -import cStringIO as StringIO -import urlparse -import time - -def handle_request(req): - url = urlparse.urlparse(req.path) - delay = float(int(url.query)) - time.sleep(delay / 1000) # argument is in milliseconds - - body = "OK ({}ms delayed)\n".format(delay) - req.send_response(200) - req.send_header('Content-Type', 'text/plain') - req.send_header('Content-Length', str(len(body))) - req.end_headers() - return StringIO.StringIO(body) diff --git a/third_party/phantomjs/test/www/echo.py b/third_party/phantomjs/test/www/echo.py deleted file mode 100644 index 8a7ba2d9693..00000000000 --- a/third_party/phantomjs/test/www/echo.py +++ /dev/null @@ -1,29 +0,0 @@ -import json -import urlparse -import cStringIO as StringIO - -def handle_request(req): - url = urlparse.urlparse(req.path) - headers = {} - for name, value in req.headers.items(): - headers[name] = value.rstrip() - - d = dict( - command = req.command, - version = req.protocol_version, - origin = req.client_address, - url = req.path, - path = url.path, - params = url.params, - query = url.query, - fragment = url.fragment, - headers = headers, - postdata = req.postdata - ) - body = json.dumps(d, indent=2) + '\n' - - req.send_response(200) - req.send_header('Content-Type', 'application/json') - req.send_header('Content-Length', str(len(body))) - req.end_headers() - return StringIO.StringIO(body) diff --git a/third_party/phantomjs/test/www/frameset/frame1-1.html b/third_party/phantomjs/test/www/frameset/frame1-1.html deleted file mode 100644 index c80ec458368..00000000000 --- a/third_party/phantomjs/test/www/frameset/frame1-1.html +++ /dev/null @@ -1,8 +0,0 @@ - - - frame1-1 - - -

index > frame1 > frame1-1

- - diff --git a/third_party/phantomjs/test/www/frameset/frame1-2.html b/third_party/phantomjs/test/www/frameset/frame1-2.html deleted file mode 100644 index b0c38d2f4a3..00000000000 --- a/third_party/phantomjs/test/www/frameset/frame1-2.html +++ /dev/null @@ -1,8 +0,0 @@ - - - frame1-2 - - -

index > frame1 > frame1-2

- - diff --git a/third_party/phantomjs/test/www/frameset/frame1.html b/third_party/phantomjs/test/www/frameset/frame1.html deleted file mode 100644 index b23c274193c..00000000000 --- a/third_party/phantomjs/test/www/frameset/frame1.html +++ /dev/null @@ -1,9 +0,0 @@ - - - frame1 - - - - - - diff --git a/third_party/phantomjs/test/www/frameset/frame2-1.html b/third_party/phantomjs/test/www/frameset/frame2-1.html deleted file mode 100644 index 2f7c121a9ff..00000000000 --- a/third_party/phantomjs/test/www/frameset/frame2-1.html +++ /dev/null @@ -1,8 +0,0 @@ - - - frame2-1 - - -

index > frame2 > frame2-1

- - diff --git a/third_party/phantomjs/test/www/frameset/frame2-2.html b/third_party/phantomjs/test/www/frameset/frame2-2.html deleted file mode 100644 index 99f603d78f6..00000000000 --- a/third_party/phantomjs/test/www/frameset/frame2-2.html +++ /dev/null @@ -1,8 +0,0 @@ - - - frame2-2 - - -

index > frame2 > frame2-2

- - diff --git a/third_party/phantomjs/test/www/frameset/frame2-3.html b/third_party/phantomjs/test/www/frameset/frame2-3.html deleted file mode 100644 index b6f18089dec..00000000000 --- a/third_party/phantomjs/test/www/frameset/frame2-3.html +++ /dev/null @@ -1,8 +0,0 @@ - - - frame2-3 - - -

index > frame2 > frame2-3

- - diff --git a/third_party/phantomjs/test/www/frameset/frame2.html b/third_party/phantomjs/test/www/frameset/frame2.html deleted file mode 100644 index d3484bd15cc..00000000000 --- a/third_party/phantomjs/test/www/frameset/frame2.html +++ /dev/null @@ -1,10 +0,0 @@ - - - frame2 - - - - - - - diff --git a/third_party/phantomjs/test/www/frameset/index.html b/third_party/phantomjs/test/www/frameset/index.html deleted file mode 100644 index dbe01bb5d02..00000000000 --- a/third_party/phantomjs/test/www/frameset/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - index - - - - - - diff --git a/third_party/phantomjs/test/www/hello.html b/third_party/phantomjs/test/www/hello.html deleted file mode 100644 index ee4bc5924a5..00000000000 --- a/third_party/phantomjs/test/www/hello.html +++ /dev/null @@ -1,8 +0,0 @@ - - - Hello - - -

Hello, world!

- - diff --git a/third_party/phantomjs/test/www/iframe.html b/third_party/phantomjs/test/www/iframe.html deleted file mode 100644 index ce62c6dc654..00000000000 --- a/third_party/phantomjs/test/www/iframe.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - diff --git a/third_party/phantomjs/test/www/includejs.js b/third_party/phantomjs/test/www/includejs.js deleted file mode 100644 index 5c0e4bd619a..00000000000 --- a/third_party/phantomjs/test/www/includejs.js +++ /dev/null @@ -1,3 +0,0 @@ -function getTitle () { - return document.title; -} diff --git a/third_party/phantomjs/test/www/includejs1.html b/third_party/phantomjs/test/www/includejs1.html deleted file mode 100644 index 4be4b1fb603..00000000000 --- a/third_party/phantomjs/test/www/includejs1.html +++ /dev/null @@ -1,2 +0,0 @@ - -i am includejs one diff --git a/third_party/phantomjs/test/www/includejs2.html b/third_party/phantomjs/test/www/includejs2.html deleted file mode 100644 index 89aeab2a62a..00000000000 --- a/third_party/phantomjs/test/www/includejs2.html +++ /dev/null @@ -1,2 +0,0 @@ - -i am includejs two diff --git a/third_party/phantomjs/test/www/js-infinite-loop.html b/third_party/phantomjs/test/www/js-infinite-loop.html deleted file mode 100644 index 6dcb77525c0..00000000000 --- a/third_party/phantomjs/test/www/js-infinite-loop.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/third_party/phantomjs/test/www/logo.html b/third_party/phantomjs/test/www/logo.html deleted file mode 100644 index 1323ffdf5a4..00000000000 --- a/third_party/phantomjs/test/www/logo.html +++ /dev/null @@ -1,8 +0,0 @@ - - - Show logo - - - - - diff --git a/third_party/phantomjs/test/www/logo.png b/third_party/phantomjs/test/www/logo.png deleted file mode 100644 index 7b44e54189fa80bf2b35227cffcd1559d9e3947a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22055 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 - - Missing image - - - - - diff --git a/third_party/phantomjs/test/www/navigation/dest.html b/third_party/phantomjs/test/www/navigation/dest.html deleted file mode 100644 index e336f9cbb3e..00000000000 --- a/third_party/phantomjs/test/www/navigation/dest.html +++ /dev/null @@ -1,2 +0,0 @@ - -DEST diff --git a/third_party/phantomjs/test/www/navigation/index.html b/third_party/phantomjs/test/www/navigation/index.html deleted file mode 100644 index 9d3b35f2d1d..00000000000 --- a/third_party/phantomjs/test/www/navigation/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -INDEX diff --git a/third_party/phantomjs/test/www/phantomjs.png b/third_party/phantomjs/test/www/phantomjs.png deleted file mode 100644 index 381a3789b75719ee94ca13d0d56cf8226b4284da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26905 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 NRo`nVmA*3z_&=u(avcBw diff --git a/third_party/phantomjs/test/www/regression/pjs-10690/Windsong.ttf b/third_party/phantomjs/test/www/regression/pjs-10690/Windsong.ttf deleted file mode 100644 index 22c8e697c7b4031663a29cde4366c786e0c1e0b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84852 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

L8~+In3IeG!(mZt_HDqP7vK$FqBgYz@XKOTnG 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%0AFY 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 diff --git a/third_party/phantomjs/test/www/regression/pjs-10690/font.css b/third_party/phantomjs/test/www/regression/pjs-10690/font.css deleted file mode 100644 index 959d531cb35..00000000000 --- a/third_party/phantomjs/test/www/regression/pjs-10690/font.css +++ /dev/null @@ -1,7 +0,0 @@ -@font-face { - font-family: 'WindsongRegular'; - src: url("Windsong.ttf") format("truetype"); -} -h1 { - font: 90px/98px "WindsongRegular", Arial, sans-serif; -} diff --git a/third_party/phantomjs/test/www/regression/pjs-10690/index.html b/third_party/phantomjs/test/www/regression/pjs-10690/index.html deleted file mode 100644 index 6d4d3cfb12d..00000000000 --- a/third_party/phantomjs/test/www/regression/pjs-10690/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - -

Hello World

- - diff --git a/third_party/phantomjs/test/www/regression/pjs-10690/jquery.js b/third_party/phantomjs/test/www/regression/pjs-10690/jquery.js deleted file mode 100644 index f66a95ce6cb..00000000000 --- a/third_party/phantomjs/test/www/regression/pjs-10690/jquery.js +++ /dev/null @@ -1,9441 +0,0 @@ -/*! - * jQuery JavaScript Library v1.8.2 - * http://jquery.com/ - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: Thu Sep 20 2012 21:13:05 GMT-0400 (Eastern Daylight Time) - */ - -(function( window, undefined ) { -var - // A central reference to the root jQuery(document) - rootjQuery, - - // The deferred used on DOM ready - readyList, - - // Use the correct document accordingly with window argument (sandbox) - document = window.document, - location = window.location, - navigator = window.navigator, - - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$, - - // Save a reference to some core methods - core_push = Array.prototype.push, - core_slice = Array.prototype.slice, - core_indexOf = Array.prototype.indexOf, - core_toString = Object.prototype.toString, - core_hasOwn = Object.prototype.hasOwnProperty, - core_trim = String.prototype.trim, - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); - }, - - // Used for matching numbers - core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source, - - // Used for detecting and trimming whitespace - core_rnotwhite = /\S/, - core_rspace = /\s+/, - - // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, - rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return ( letter + "" ).toUpperCase(); - }, - - // The ready event handler and self cleanup method - DOMContentLoaded = function() { - if ( document.addEventListener ) { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - jQuery.ready(); - } else if ( document.readyState === "complete" ) { - // we're here because readyState === "complete" in oldIE - // which is good enough for us to call the dom ready! - document.detachEvent( "onreadystatechange", DOMContentLoaded ); - jQuery.ready(); - } - }, - - // [[Class]] -> type pairs - class2type = {}; - -jQuery.fn = jQuery.prototype = { - constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem, ret, doc; - - // Handle $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - doc = ( context && context.nodeType ? context.ownerDocument || context : document ); - - // scripts is true for back-compat - selector = jQuery.parseHTML( match[1], doc, true ); - if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { - this.attr.call( selector, context, true ); - } - - return jQuery.merge( this, selector ); - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return rootjQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return rootjQuery.ready( selector ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }, - - // Start with an empty selector - selector: "", - - // The current version of jQuery being used - jquery: "1.8.2", - - // The default length of a jQuery object is 0 - length: 0, - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - toArray: function() { - return core_slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == null ? - - // Return a 'clean' array - this.toArray() : - - // Return just the object - ( num < 0 ? this[ this.length + num ] : this[ num ] ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) { - ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; - } else if ( name ) { - ret.selector = this.selector + "." + name + "(" + selector + ")"; - } - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - ready: function( fn ) { - // Add the callback - jQuery.ready.promise().done( fn ); - - return this; - }, - - eq: function( i ) { - i = +i; - return i === -1 ? - this.slice( i ) : - this.slice( i, i + 1 ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - slice: function() { - return this.pushStack( core_slice.apply( this, arguments ), - "slice", core_slice.call(arguments).join(",") ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: core_push, - sort: [].sort, - splice: [].splice -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( length === i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - noConflict: function( deep ) { - if ( window.$ === jQuery ) { - window.$ = _$; - } - - if ( deep && window.jQuery === jQuery ) { - window.jQuery = _jQuery; - } - - return jQuery; - }, - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( jQuery.ready, 1 ); - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.trigger ) { - jQuery( document ).trigger("ready").off("ready"); - } - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; - }, - - isWindow: function( obj ) { - return obj != null && obj == obj.window; - }, - - isNumeric: function( obj ) { - return !isNaN( parseFloat(obj) ) && isFinite( obj ); - }, - - type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ core_toString.call(obj) ] || "object"; - }, - - isPlainObject: function( obj ) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - try { - // Not own constructor property must be Object - if ( obj.constructor && - !core_hasOwn.call(obj, "constructor") && - !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - } catch ( e ) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - - var key; - for ( key in obj ) {} - - return key === undefined || core_hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - var name; - for ( name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw new Error( msg ); - }, - - // data: string of html - // context (optional): If specified, the fragment will be created in this context, defaults to document - // scripts (optional): If true, will include scripts passed in the html string - parseHTML: function( data, context, scripts ) { - var parsed; - if ( !data || typeof data !== "string" ) { - return null; - } - if ( typeof context === "boolean" ) { - scripts = context; - context = 0; - } - context = context || document; - - // Single tag - if ( (parsed = rsingleTag.exec( data )) ) { - return [ context.createElement( parsed[1] ) ]; - } - - parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] ); - return jQuery.merge( [], - (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes ); - }, - - parseJSON: function( data ) { - if ( !data || typeof data !== "string") { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - - // Attempt to parse using the native JSON parser first - if ( window.JSON && window.JSON.parse ) { - return window.JSON.parse( data ); - } - - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test( data.replace( rvalidescape, "@" ) - .replace( rvalidtokens, "]" ) - .replace( rvalidbraces, "")) ) { - - return ( new Function( "return " + data ) )(); - - } - jQuery.error( "Invalid JSON: " + data ); - }, - - // Cross-browser xml parsing - parseXML: function( data ) { - var xml, tmp; - if ( !data || typeof data !== "string" ) { - return null; - } - try { - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - } catch( e ) { - xml = undefined; - } - if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; - }, - - noop: function() {}, - - // Evaluates a script in a global context - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context - globalEval: function( data ) { - if ( data && core_rnotwhite.test( data ) ) { - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than jQuery in Firefox - ( window.execScript || function( data ) { - window[ "eval" ].call( window, data ); - } )( data ); - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - // args is for internal usage only - each: function( obj, callback, args ) { - var name, - i = 0, - length = obj.length, - isObj = length === undefined || jQuery.isFunction( obj ); - - if ( args ) { - if ( isObj ) { - for ( name in obj ) { - if ( callback.apply( obj[ name ], args ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.apply( obj[ i++ ], args ) === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isObj ) { - for ( name in obj ) { - if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) { - break; - } - } - } - } - - return obj; - }, - - // Use native String.trim function wherever possible - trim: core_trim && !core_trim.call("\uFEFF\xA0") ? - function( text ) { - return text == null ? - "" : - core_trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var type, - ret = results || []; - - if ( arr != null ) { - // The window, strings (and functions) also have 'length' - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - type = jQuery.type( arr ); - - if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) { - core_push.call( ret, arr ); - } else { - jQuery.merge( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - var len; - - if ( arr ) { - if ( core_indexOf ) { - return core_indexOf.call( arr, elem, i ); - } - - len = arr.length; - i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; - - for ( ; i < len; i++ ) { - // Skip accessing in sparse arrays - if ( i in arr && arr[ i ] === elem ) { - return i; - } - } - } - - return -1; - }, - - merge: function( first, second ) { - var l = second.length, - i = first.length, - j = 0; - - if ( typeof l === "number" ) { - for ( ; j < l; j++ ) { - first[ i++ ] = second[ j ]; - } - - } else { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, inv ) { - var retVal, - ret = [], - i = 0, - length = elems.length; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - retVal = !!callback( elems[ i ], i ); - if ( inv !== retVal ) { - ret.push( elems[ i ] ); - } - } - - return ret; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, key, - ret = [], - i = 0, - length = elems.length, - // jquery objects are treated as arrays - isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; - - // Go through the array, translating each of the items to their - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - - // Go through every key on the object, - } else { - for ( key in elems ) { - value = callback( elems[ key ], key, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - } - - // Flatten any nested arrays - return ret.concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var tmp, args, proxy; - - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - args = core_slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context, args.concat( core_slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - // Multifunctional method to get and set values of a collection - // The value/s can optionally be executed if it's a function - access: function( elems, fn, key, value, chainable, emptyGet, pass ) { - var exec, - bulk = key == null, - i = 0, - length = elems.length; - - // Sets many values - if ( key && typeof key === "object" ) { - for ( i in key ) { - jQuery.access( elems, fn, i, key[i], 1, emptyGet, value ); - } - chainable = 1; - - // Sets one value - } else if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = pass === undefined && jQuery.isFunction( value ); - - if ( bulk ) { - // Bulk operations only iterate when executing function values - if ( exec ) { - exec = fn; - fn = function( elem, key, value ) { - return exec.call( jQuery( elem ), value ); - }; - - // Otherwise they run against the entire set - } else { - fn.call( elems, value ); - fn = null; - } - } - - if ( fn ) { - for (; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); - } - } - - chainable = 1; - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call( elems ) : - length ? fn( elems[0], key ) : emptyGet; - }, - - now: function() { - return ( new Date() ).getTime(); - } -}); - -jQuery.ready.promise = function( obj ) { - if ( !readyList ) { - - readyList = jQuery.Deferred(); - - // Catch cases where $(document).ready() is called after the browser event has already occurred. - // we once tried to use readyState "interactive" here, but it caused issues like the one - // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout( jQuery.ready, 1 ); - - // Standards-based browsers support DOMContentLoaded - } else if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", jQuery.ready, false ); - - // If IE event model is used - } else { - // Ensure firing before onload, maybe late but safe also for iframes - document.attachEvent( "onreadystatechange", DOMContentLoaded ); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", jQuery.ready ); - - // If IE and not a frame - // continually check to see if the document is ready - var top = false; - - try { - top = window.frameElement == null && document.documentElement; - } catch(e) {} - - if ( top && top.doScroll ) { - (function doScrollCheck() { - if ( !jQuery.isReady ) { - - try { - // Use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - top.doScroll("left"); - } catch(e) { - return setTimeout( doScrollCheck, 50 ); - } - - // and execute any waiting functions - jQuery.ready(); - } - })(); - } - } - } - return readyList.promise( obj ); -}; - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -// All jQuery objects should point back to these -rootjQuery = jQuery(document); -// String to Object options format cache -var optionsCache = {}; - -// Convert String-formatted options into Object-formatted ones and store in cache -function createOptions( options ) { - var object = optionsCache[ options ] = {}; - jQuery.each( options.split( core_rspace ), function( _, flag ) { - object[ flag ] = true; - }); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - ( optionsCache[ options ] || createOptions( options ) ) : - jQuery.extend( {}, options ); - - var // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list was already fired - fired, - // Flag to know if list is currently firing - firing, - // First callback to fire (used internally by add and fireWith) - firingStart, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = !options.once && [], - // Fire callbacks - fire = function( data ) { - memory = options.memory && data; - fired = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - firing = true; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { - memory = false; // To prevent further calls using add - break; - } - } - firing = false; - if ( list ) { - if ( stack ) { - if ( stack.length ) { - fire( stack.shift() ); - } - } else if ( memory ) { - list = []; - } else { - self.disable(); - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - // First, we save the current length - var start = list.length; - (function add( args ) { - jQuery.each( args, function( _, arg ) { - var type = jQuery.type( arg ); - if ( type === "function" && ( !options.unique || !self.has( arg ) ) ) { - list.push( arg ); - } else if ( arg && arg.length && type !== "string" ) { - // Inspect recursively - add( arg ); - } - }); - })( arguments ); - // Do we need to add the callbacks to the - // current firing batch? - if ( firing ) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away - } else if ( memory ) { - firingStart = start; - fire( memory ); - } - } - return this; - }, - // Remove a callback from the list - remove: function() { - if ( list ) { - jQuery.each( arguments, function( _, arg ) { - var index; - while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - // Handle firing indexes - if ( firing ) { - if ( index <= firingLength ) { - firingLength--; - } - if ( index <= firingIndex ) { - firingIndex--; - } - } - } - }); - } - return this; - }, - // Control if a given callback is in the list - has: function( fn ) { - return jQuery.inArray( fn, list ) > -1; - }, - // Remove all callbacks from the list - empty: function() { - list = []; - return this; - }, - // Have the list do nothing anymore - disable: function() { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function() { - return !list; - }, - // Lock the list in its current state - lock: function() { - stack = undefined; - if ( !memory ) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function() { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - if ( list && ( !fired || stack ) ) { - if ( firing ) { - stack.push( args ); - } else { - fire( args ); - } - } - return this; - }, - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; -jQuery.extend({ - - Deferred: function( func ) { - var tuples = [ - // action, add listener, listener list, final state - [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], - [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], - [ "notify", "progress", jQuery.Callbacks("memory") ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - then: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - return jQuery.Deferred(function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - var action = tuple[ 0 ], - fn = fns[ i ]; - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[1] ]( jQuery.isFunction( fn ) ? - function() { - var returned = fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .done( newDefer.resolve ) - .fail( newDefer.reject ) - .progress( newDefer.notify ); - } else { - newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); - } - } : - newDefer[ action ] - ); - }); - fns = null; - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Keep pipe for back-compat - promise.pipe = promise.then; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 3 ]; - - // promise[ done | fail | progress ] = list.add - promise[ tuple[1] ] = list.add; - - // Handle state - if ( stateString ) { - list.add(function() { - // state = [ resolved | rejected ] - state = stateString; - - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); - } - - // deferred[ resolve | reject | notify ] = list.fire - deferred[ tuple[0] ] = list.fire; - deferred[ tuple[0] + "With" ] = list.fireWith; - }); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( subordinate /* , ..., subordinateN */ ) { - var i = 0, - resolveValues = core_slice.call( arguments ), - length = resolveValues.length, - - // the count of uncompleted subordinates - remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, - - // the master Deferred. If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), - - // Update function for both resolve and progress values - updateFunc = function( i, contexts, values ) { - return function( value ) { - contexts[ i ] = this; - values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; - if( values === progressValues ) { - deferred.notifyWith( contexts, values ); - } else if ( !( --remaining ) ) { - deferred.resolveWith( contexts, values ); - } - }; - }, - - progressValues, progressContexts, resolveContexts; - - // add listeners to Deferred subordinates; treat others as resolved - if ( length > 1 ) { - progressValues = new Array( length ); - progressContexts = new Array( length ); - resolveContexts = new Array( length ); - for ( ; i < length; i++ ) { - if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { - resolveValues[ i ].promise() - .done( updateFunc( i, resolveContexts, resolveValues ) ) - .fail( deferred.reject ) - .progress( updateFunc( i, progressContexts, progressValues ) ); - } else { - --remaining; - } - } - } - - // if we're not waiting on anything, resolve the master - if ( !remaining ) { - deferred.resolveWith( resolveContexts, resolveValues ); - } - - return deferred.promise(); - } -}); -jQuery.support = (function() { - - var support, - all, - a, - select, - opt, - input, - fragment, - eventName, - i, - isSupported, - clickFn, - div = document.createElement("div"); - - // Preliminary tests - div.setAttribute( "className", "t" ); - div.innerHTML = "
a"; - - all = div.getElementsByTagName("*"); - a = div.getElementsByTagName("a")[ 0 ]; - a.style.cssText = "top:1px;float:left;opacity:.5"; - - // Can't get basic test support - if ( !all || !all.length ) { - return {}; - } - - // First batch of supports tests - select = document.createElement("select"); - opt = select.appendChild( document.createElement("option") ); - input = div.getElementsByTagName("input")[ 0 ]; - - support = { - // IE strips leading whitespace when .innerHTML is used - leadingWhitespace: ( div.firstChild.nodeType === 3 ), - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - tbody: !div.getElementsByTagName("tbody").length, - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - htmlSerialize: !!div.getElementsByTagName("link").length, - - // Get the style information from getAttribute - // (IE uses .cssText instead) - style: /top/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: ( a.getAttribute("href") === "/a" ), - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - opacity: /^0.5/.test( a.style.opacity ), - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - cssFloat: !!a.style.cssFloat, - - // Make sure that if no value is specified for a checkbox - // that it defaults to "on". - // (WebKit defaults to "" instead) - checkOn: ( input.value === "on" ), - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) - getSetAttribute: div.className !== "t", - - // Tests for enctype support on a form(#6743) - enctype: !!document.createElement("form").enctype, - - // Makes sure cloning an html5 element does not cause problems - // Where outerHTML is undefined, this still works - html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", - - // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode - boxModel: ( document.compatMode === "CSS1Compat" ), - - // Will be defined later - submitBubbles: true, - changeBubbles: true, - focusinBubbles: false, - deleteExpando: true, - noCloneEvent: true, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableMarginRight: true, - boxSizingReliable: true, - pixelPosition: false - }; - - // Make sure checked status is properly cloned - input.checked = true; - support.noCloneChecked = input.cloneNode( true ).checked; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as disabled) - select.disabled = true; - support.optDisabled = !opt.disabled; - - // Test to see if it's possible to delete an expando from an element - // Fails in Internet Explorer - try { - delete div.test; - } catch( e ) { - support.deleteExpando = false; - } - - if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { - div.attachEvent( "onclick", clickFn = function() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - support.noCloneEvent = false; - }); - div.cloneNode( true ).fireEvent("onclick"); - div.detachEvent( "onclick", clickFn ); - } - - // Check if a radio maintains its value - // after being appended to the DOM - input = document.createElement("input"); - input.value = "t"; - input.setAttribute( "type", "radio" ); - support.radioValue = input.value === "t"; - - input.setAttribute( "checked", "checked" ); - - // #11217 - WebKit loses check when the name is after the checked attribute - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - fragment = document.createDocumentFragment(); - fragment.appendChild( div.lastChild ); - - // WebKit doesn't clone checked state correctly in fragments - support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - support.appendChecked = input.checked; - - fragment.removeChild( input ); - fragment.appendChild( div ); - - // Technique from Juriy Zaytsev - // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ - // We only care about the case where non-standard event systems - // are used, namely in IE. Short-circuiting here helps us to - // avoid an eval call (in setAttribute) which can cause CSP - // to go haywire. See: https://developer.mozilla.org/en/Security/CSP - if ( div.attachEvent ) { - for ( i in { - submit: true, - change: true, - focusin: true - }) { - eventName = "on" + i; - isSupported = ( eventName in div ); - if ( !isSupported ) { - div.setAttribute( eventName, "return;" ); - isSupported = ( typeof div[ eventName ] === "function" ); - } - support[ i + "Bubbles" ] = isSupported; - } - } - - // Run tests that need a body at doc ready - jQuery(function() { - var container, div, tds, marginDiv, - divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;", - body = document.getElementsByTagName("body")[0]; - - if ( !body ) { - // Return for frameset docs that don't have a body - return; - } - - container = document.createElement("div"); - container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px"; - body.insertBefore( container, body.firstChild ); - - // Construct the test element - div = document.createElement("div"); - container.appendChild( div ); - - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - // (only IE 8 fails this test) - div.innerHTML = "
t
"; - tds = div.getElementsByTagName("td"); - tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; - isSupported = ( tds[ 0 ].offsetHeight === 0 ); - - tds[ 0 ].style.display = ""; - tds[ 1 ].style.display = "none"; - - // Check if empty table cells still have offsetWidth/Height - // (IE <= 8 fail this test) - support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); - - // Check box-sizing and margin behavior - div.innerHTML = ""; - div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; - support.boxSizing = ( div.offsetWidth === 4 ); - support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 ); - - // NOTE: To any future maintainer, we've window.getComputedStyle - // because jsdom on node.js will break without it. - if ( window.getComputedStyle ) { - support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; - support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; - - // Check if div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container. For more - // info see bug #3333 - // Fails in WebKit before Feb 2011 nightlies - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - marginDiv = document.createElement("div"); - marginDiv.style.cssText = div.style.cssText = divReset; - marginDiv.style.marginRight = marginDiv.style.width = "0"; - div.style.width = "1px"; - div.appendChild( marginDiv ); - support.reliableMarginRight = - !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); - } - - if ( typeof div.style.zoom !== "undefined" ) { - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - // (IE < 8 does this) - div.innerHTML = ""; - div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; - support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); - - // Check if elements with layout shrink-wrap their children - // (IE 6 does this) - div.style.display = "block"; - div.style.overflow = "visible"; - div.innerHTML = "
"; - div.firstChild.style.width = "5px"; - support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); - - container.style.zoom = 1; - } - - // Null elements to avoid leaks in IE - body.removeChild( container ); - container = div = tds = marginDiv = null; - }); - - // Null elements to avoid leaks in IE - fragment.removeChild( div ); - all = a = select = opt = input = fragment = div = null; - - return support; -})(); -var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, - rmultiDash = /([A-Z])/g; - -jQuery.extend({ - cache: {}, - - deletedIds: [], - - // Remove at next major release (1.9/2.0) - uuid: 0, - - // Unique for each copy of jQuery on the page - // Non-digits removed to match rinlinejQuery - expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), - - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", - "applet": true - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var thisCache, ret, - internalKey = jQuery.expando, - getByName = typeof name === "string", - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) { - return; - } - - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++; - } else { - id = internalKey; - } - } - - if ( !cache[ id ] ) { - cache[ id ] = {}; - - // Avoids exposing jQuery metadata on plain JS objects when the object - // is serialized using JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ] = jQuery.extend( cache[ id ], name ); - } else { - cache[ id ].data = jQuery.extend( cache[ id ].data, name ); - } - } - - thisCache = cache[ id ]; - - // jQuery data() is stored in a separate object inside the object's internal data - // cache in order to avoid key collisions between internal data and user-defined - // data. - if ( !pvt ) { - if ( !thisCache.data ) { - thisCache.data = {}; - } - - thisCache = thisCache.data; - } - - if ( data !== undefined ) { - thisCache[ jQuery.camelCase( name ) ] = data; - } - - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if ( getByName ) { - - // First Try to find as-is property data - ret = thisCache[ name ]; - - // Test for null|undefined property data - if ( ret == null ) { - - // Try to find the camelCased property - ret = thisCache[ jQuery.camelCase( name ) ]; - } - } else { - ret = thisCache; - } - - return ret; - }, - - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var thisCache, i, l, - - isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - id = isNode ? elem[ jQuery.expando ] : jQuery.expando; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - - thisCache = pvt ? cache[ id ] : cache[ id ].data; - - if ( thisCache ) { - - // Support array or space separated string names for data keys - if ( !jQuery.isArray( name ) ) { - - // try the string as a key before any manipulation - if ( name in thisCache ) { - name = [ name ]; - } else { - - // split the camel cased version by spaces unless a key with the spaces exists - name = jQuery.camelCase( name ); - if ( name in thisCache ) { - name = [ name ]; - } else { - name = name.split(" "); - } - } - } - - for ( i = 0, l = name.length; i < l; i++ ) { - delete thisCache[ name[i] ]; - } - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( !pvt ) { - delete cache[ id ].data; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject( cache[ id ] ) ) { - return; - } - } - - // Destroy the cache - if ( isNode ) { - jQuery.cleanData( [ elem ], true ); - - // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) - } else if ( jQuery.support.deleteExpando || cache != cache.window ) { - delete cache[ id ]; - - // When all else fails, null - } else { - cache[ id ] = null; - } - }, - - // For internal use only. - _data: function( elem, name, data ) { - return jQuery.data( elem, name, data, true ); - }, - - // A method for determining if a DOM node can handle the data expando - acceptData: function( elem ) { - var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; - - // nodes accept data unless otherwise specified; rejection can be conditional - return !noData || noData !== true && elem.getAttribute("classid") === noData; - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var parts, part, attr, name, l, - elem = this[0], - i = 0, - data = null; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = jQuery.data( elem ); - - if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { - attr = elem.attributes; - for ( l = attr.length; i < l; i++ ) { - name = attr[i].name; - - if ( !name.indexOf( "data-" ) ) { - name = jQuery.camelCase( name.substring(5) ); - - dataAttr( elem, name, data[ name ] ); - } - } - jQuery._data( elem, "parsedAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } - - parts = key.split( ".", 2 ); - parts[1] = parts[1] ? "." + parts[1] : ""; - part = parts[1] + "!"; - - return jQuery.access( this, function( value ) { - - if ( value === undefined ) { - data = this.triggerHandler( "getData" + part, [ parts[0] ] ); - - // Try to fetch any internally stored data first - if ( data === undefined && elem ) { - data = jQuery.data( elem, key ); - data = dataAttr( elem, key, data ); - } - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - } - - parts[1] = value; - this.each(function() { - var self = jQuery( this ); - - self.triggerHandler( "setData" + part, parts ); - jQuery.data( this, key, value ); - self.triggerHandler( "changeData" + part, parts ); - }); - }, null, value, arguments.length > 1, null, false ); - }, - - removeData: function( key ) { - return this.each(function() { - jQuery.removeData( this, key ); - }); - } -}); - -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - - var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); - - } else { - data = undefined; - } - } - - return data; -} - -// checks a cache object for emptiness -function isEmptyDataObject( obj ) { - var name; - for ( name in obj ) { - - // if the public data object is empty, the private is still empty - if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { - continue; - } - if ( name !== "toJSON" ) { - return false; - } - } - - return true; -} -jQuery.extend({ - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = jQuery._data( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || jQuery.isArray(data) ) { - queue = jQuery._data( elem, type, jQuery.makeArray(data) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // not intended for public consumption - generates a queueHooks object, or returns the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return jQuery._data( elem, key ) || jQuery._data( elem, key, { - empty: jQuery.Callbacks("once memory").add(function() { - jQuery.removeData( elem, type + "queue", true ); - jQuery.removeData( elem, key, true ); - }) - }); - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[0], type ); - } - - return data === undefined ? - this : - this.each(function() { - var queue = jQuery.queue( this, type, data ); - - // ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - delay: function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = setTimeout( next, time ); - hooks.stop = function() { - clearTimeout( timeout ); - }; - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while( i-- ) { - tmp = jQuery._data( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -}); -var nodeHook, boolHook, fixSpecified, - rclass = /[\t\r\n]/g, - rreturn = /\r/g, - rtype = /^(?:button|input)$/i, - rfocusable = /^(?:button|input|object|select|textarea)$/i, - rclickable = /^a(?:rea|)$/i, - rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, - getSetAttribute = jQuery.support.getSetAttribute; - -jQuery.fn.extend({ - attr: function( name, value ) { - return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each(function() { - jQuery.removeAttr( this, name ); - }); - }, - - prop: function( name, value ) { - return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - name = jQuery.propFix[ name ] || name; - return this.each(function() { - // try/catch handles cases where IE balks (such as removing a property on window) - try { - this[ name ] = undefined; - delete this[ name ]; - } catch( e ) {} - }); - }, - - addClass: function( value ) { - var classNames, i, l, elem, - setClass, c, cl; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).addClass( value.call(this, j, this.className) ); - }); - } - - if ( value && typeof value === "string" ) { - classNames = value.split( core_rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - - if ( elem.nodeType === 1 ) { - if ( !elem.className && classNames.length === 1 ) { - elem.className = value; - - } else { - setClass = " " + elem.className + " "; - - for ( c = 0, cl = classNames.length; c < cl; c++ ) { - if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) { - setClass += classNames[ c ] + " "; - } - } - elem.className = jQuery.trim( setClass ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var removes, className, elem, c, cl, i, l; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).removeClass( value.call(this, j, this.className) ); - }); - } - if ( (value && typeof value === "string") || value === undefined ) { - removes = ( value || "" ).split( core_rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - if ( elem.nodeType === 1 && elem.className ) { - - className = (" " + elem.className + " ").replace( rclass, " " ); - - // loop over each item in the removal list - for ( c = 0, cl = removes.length; c < cl; c++ ) { - // Remove until there is nothing to remove, - while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) { - className = className.replace( " " + removes[ c ] + " " , " " ); - } - } - elem.className = value ? jQuery.trim( className ) : ""; - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( i ) { - jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - state = stateVal, - classNames = value.split( core_rspace ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space separated list - state = isBool ? state : !self.hasClass( className ); - self[ state ? "addClass" : "removeClass" ]( className ); - } - - } else if ( type === "undefined" || type === "boolean" ) { - if ( this.className ) { - // store className if set - jQuery._data( this, "__className__", this.className ); - } - - // toggle whole className - this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " ", - i = 0, - l = this.length; - for ( ; i < l; i++ ) { - if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - var hooks, ret, isFunction, - elem = this[0]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { - return ret; - } - - ret = elem.value; - - return typeof ret === "string" ? - // handle most common string cases - ret.replace(rreturn, "") : - // handle cases where value is null/undef or number - ret == null ? "" : ret; - } - - return; - } - - isFunction = jQuery.isFunction( value ); - - return this.each(function( i ) { - var val, - self = jQuery(this); - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call( this, i, self.val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - } else if ( typeof val === "number" ) { - val += ""; - } else if ( jQuery.isArray( val ) ) { - val = jQuery.map(val, function ( value ) { - return value == null ? "" : value + ""; - }); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - valHooks: { - option: { - get: function( elem ) { - // attributes.value is undefined in Blackberry 4.7 but - // uses .value. See #6932 - var val = elem.attributes.value; - return !val || val.specified ? elem.value : elem.text; - } - }, - select: { - get: function( elem ) { - var value, i, max, option, - index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type === "select-one"; - - // Nothing was selected - if ( index < 0 ) { - return null; - } - - // Loop through all the selected options - i = one ? index : 0; - max = one ? index + 1 : options.length; - for ( ; i < max; i++ ) { - option = options[ i ]; - - // Don't return options that are disabled or in a disabled optgroup - if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - // Fixes Bug #2551 -- select.val() broken in IE after form.reset() - if ( one && !values.length && options.length ) { - return jQuery( options[ index ] ).val(); - } - - return values; - }, - - set: function( elem, value ) { - var values = jQuery.makeArray( value ); - - jQuery(elem).find("option").each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; - }); - - if ( !values.length ) { - elem.selectedIndex = -1; - } - return values; - } - } - }, - - // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9 - attrFn: {}, - - attr: function( elem, name, value, pass ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) { - return jQuery( elem )[ name ]( value ); - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { - return jQuery.prop( elem, name, value ); - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - // All attributes are lowercase - // Grab necessary hook if one is defined - if ( notxml ) { - name = name.toLowerCase(); - hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); - } - - if ( value !== undefined ) { - - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return; - - } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - elem.setAttribute( name, value + "" ); - return value; - } - - } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - - ret = elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return ret === null ? - undefined : - ret; - } - }, - - removeAttr: function( elem, value ) { - var propName, attrNames, name, isBool, - i = 0; - - if ( value && elem.nodeType === 1 ) { - - attrNames = value.split( core_rspace ); - - for ( ; i < attrNames.length; i++ ) { - name = attrNames[ i ]; - - if ( name ) { - propName = jQuery.propFix[ name ] || name; - isBool = rboolean.test( name ); - - // See #9699 for explanation of this approach (setting first, then removal) - // Do not do this for boolean attributes (see #10870) - if ( !isBool ) { - jQuery.attr( elem, name, "" ); - } - elem.removeAttribute( getSetAttribute ? name : propName ); - - // Set corresponding property to false for boolean attributes - if ( isBool && propName in elem ) { - elem[ propName ] = false; - } - } - } - } - }, - - attrHooks: { - type: { - set: function( elem, value ) { - // We can't allow the type property to be changed (since it causes problems in IE) - if ( rtype.test( elem.nodeName ) && elem.parentNode ) { - jQuery.error( "type property can't be changed" ); - } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { - // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to it's default in case type is set after value - // This is for element creation - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - }, - // Use the value property for back compat - // Use the nodeHook for button elements in IE6/7 (#1954) - value: { - get: function( elem, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.get( elem, name ); - } - return name in elem ? - elem.value : - null; - }, - set: function( elem, value, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.set( elem, value, name ); - } - // Does not return so that setAttribute is also used - elem.value = value; - } - } - }, - - propFix: { - tabindex: "tabIndex", - readonly: "readOnly", - "for": "htmlFor", - "class": "className", - maxlength: "maxLength", - cellspacing: "cellSpacing", - cellpadding: "cellPadding", - rowspan: "rowSpan", - colspan: "colSpan", - usemap: "useMap", - frameborder: "frameBorder", - contenteditable: "contentEditable" - }, - - prop: function( elem, name, value ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - if ( notxml ) { - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - return ( elem[ name ] = value ); - } - - } else { - if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - return elem[ name ]; - } - } - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - var attributeNode = elem.getAttributeNode("tabindex"); - - return attributeNode && attributeNode.specified ? - parseInt( attributeNode.value, 10 ) : - rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? - 0 : - undefined; - } - } - } -}); - -// Hook for boolean attributes -boolHook = { - get: function( elem, name ) { - // Align boolean attributes with corresponding properties - // Fall back to attribute presence where some booleans are not supported - var attrNode, - property = jQuery.prop( elem, name ); - return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? - name.toLowerCase() : - undefined; - }, - set: function( elem, value, name ) { - var propName; - if ( value === false ) { - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - // value is true since we know at this point it's type boolean and not false - // Set boolean attributes to the same name and set the DOM property - propName = jQuery.propFix[ name ] || name; - if ( propName in elem ) { - // Only set the IDL specifically if it already exists on the element - elem[ propName ] = true; - } - - elem.setAttribute( name, name.toLowerCase() ); - } - return name; - } -}; - -// IE6/7 do not support getting/setting some attributes with get/setAttribute -if ( !getSetAttribute ) { - - fixSpecified = { - name: true, - id: true, - coords: true - }; - - // Use this for any attribute in IE6/7 - // This fixes almost every IE6/7 issue - nodeHook = jQuery.valHooks.button = { - get: function( elem, name ) { - var ret; - ret = elem.getAttributeNode( name ); - return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ? - ret.value : - undefined; - }, - set: function( elem, value, name ) { - // Set the existing or create a new attribute node - var ret = elem.getAttributeNode( name ); - if ( !ret ) { - ret = document.createAttribute( name ); - elem.setAttributeNode( ret ); - } - return ( ret.value = value + "" ); - } - }; - - // Set width and height to auto instead of 0 on empty string( Bug #8150 ) - // This is for removals - jQuery.each([ "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - set: function( elem, value ) { - if ( value === "" ) { - elem.setAttribute( name, "auto" ); - return value; - } - } - }); - }); - - // Set contenteditable to false on removals(#10429) - // Setting to empty string throws an error as an invalid value - jQuery.attrHooks.contenteditable = { - get: nodeHook.get, - set: function( elem, value, name ) { - if ( value === "" ) { - value = "false"; - } - nodeHook.set( elem, value, name ); - } - }; -} - - -// Some attributes require a special call on IE -if ( !jQuery.support.hrefNormalized ) { - jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - get: function( elem ) { - var ret = elem.getAttribute( name, 2 ); - return ret === null ? undefined : ret; - } - }); - }); -} - -if ( !jQuery.support.style ) { - jQuery.attrHooks.style = { - get: function( elem ) { - // Return undefined in the case of empty string - // Normalize to lowercase since IE uppercases css property names - return elem.style.cssText.toLowerCase() || undefined; - }, - set: function( elem, value ) { - return ( elem.style.cssText = value + "" ); - } - }; -} - -// Safari mis-reports the default selected property of an option -// Accessing the parent's selectedIndex property fixes it -if ( !jQuery.support.optSelected ) { - jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { - get: function( elem ) { - var parent = elem.parentNode; - - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - return null; - } - }); -} - -// IE6/7 call enctype encoding -if ( !jQuery.support.enctype ) { - jQuery.propFix.enctype = "encoding"; -} - -// Radios and checkboxes getter/setter -if ( !jQuery.support.checkOn ) { - jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - get: function( elem ) { - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - } - }; - }); -} -jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { - set: function( elem, value ) { - if ( jQuery.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); - } - } - }); -}); -var rformElems = /^(?:textarea|input|select)$/i, - rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/, - rhoverHack = /(?:^|\s)hover(\.\S+|)\b/, - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - hoverHack = function( events ) { - return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); - }; - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - add: function( elem, types, handler, data, selector ) { - - var elemData, eventHandle, events, - t, tns, type, namespaces, handleObj, - handleObjIn, handlers, special; - - // Don't attach events to noData or text/comment nodes (allow plain objects tho) - if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - events = elemData.events; - if ( !events ) { - elemData.events = events = {}; - } - eventHandle = elemData.handle; - if ( !eventHandle ) { - elemData.handle = eventHandle = function( e ) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? - jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : - undefined; - }; - // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events - eventHandle.elem = elem; - } - - // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - types = jQuery.trim( hoverHack(types) ).split( " " ); - for ( t = 0; t < types.length; t++ ) { - - tns = rtypenamespace.exec( types[t] ) || []; - type = tns[1]; - namespaces = ( tns[2] || "" ).split( "." ).sort(); - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: tns[1], - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join(".") - }, handleObjIn ); - - // Init the event handler queue if we're the first - handlers = events[ type ]; - if ( !handlers ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener/attachEvent if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - global: {}, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var t, tns, type, origType, namespaces, origCount, - j, events, special, eventType, handleObj, - elemData = jQuery.hasData( elem ) && jQuery._data( elem ); - - if ( !elemData || !(events = elemData.events) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = jQuery.trim( hoverHack( types || "" ) ).split(" "); - for ( t = 0; t < types.length; t++ ) { - tns = rtypenamespace.exec( types[t] ) || []; - type = origType = tns[1]; - namespaces = tns[2]; - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector? special.delegateType : special.bindType ) || type; - eventType = events[ type ] || []; - origCount = eventType.length; - namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null; - - // Remove matching events - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !namespaces || namespaces.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - eventType.splice( j--, 1 ); - - if ( handleObj.selector ) { - eventType.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( eventType.length === 0 && origCount !== eventType.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - delete elemData.handle; - - // removeData also checks for emptiness and clears the expando if empty - // so use it instead of delete - jQuery.removeData( elem, "events", true ); - } - }, - - // Events that are safe to short-circuit if no handlers are attached. - // Native DOM events should not be added, they may have inline handlers. - customEvent: { - "getData": true, - "setData": true, - "changeData": true - }, - - trigger: function( event, data, elem, onlyHandlers ) { - // Don't do events on text and comment nodes - if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { - return; - } - - // Event object or event type - var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType, - type = event.type || event, - namespaces = []; - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf( "!" ) >= 0 ) { - // Exclusive events trigger only for the exact event (no namespaces) - type = type.slice(0, -1); - exclusive = true; - } - - if ( type.indexOf( "." ) >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - - if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { - // No jQuery handlers for this event type, and it can't have inline handlers - return; - } - - // Caller can pass in an Event, Object, or just an event type string - event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : - // Object literal - new jQuery.Event( type, event ) : - // Just the event type (string) - new jQuery.Event( type ); - - event.type = type; - event.isTrigger = true; - event.exclusive = exclusive; - event.namespace = namespaces.join( "." ); - event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null; - ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; - - // Handle a global trigger - if ( !elem ) { - - // TODO: Stop taunting the data cache; remove global events and always attach to document - cache = jQuery.cache; - for ( i in cache ) { - if ( cache[ i ].events && cache[ i ].events[ type ] ) { - jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); - } - } - return; - } - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data != null ? jQuery.makeArray( data ) : []; - data.unshift( event ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - eventPath = [[ elem, special.bindType || type ]]; - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; - for ( old = elem; cur; cur = cur.parentNode ) { - eventPath.push([ cur, bubbleType ]); - old = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( old === (elem.ownerDocument || document) ) { - eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); - } - } - - // Fire handlers on the event path - for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { - - cur = eventPath[i][0]; - event.type = eventPath[i][1]; - - handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - // Note that this is a bare JS function and not a jQuery handler - handle = ontype && cur[ ontype ]; - if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { - event.preventDefault(); - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && - !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction() check here because IE6/7 fails that test. - // Don't do default actions on window, that's where global variables be (#6170) - // IE<9 dies on focus/blur to hidden element (#1486) - if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - old = elem[ ontype ]; - - if ( old ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - elem[ type ](); - jQuery.event.triggered = undefined; - - if ( old ) { - elem[ ontype ] = old; - } - } - } - } - - return event.result; - }, - - dispatch: function( event ) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event || window.event ); - - var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related, - handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), - delegateCount = handlers.delegateCount, - args = core_slice.call( arguments ), - run_all = !event.exclusive && !event.namespace, - special = jQuery.event.special[ event.type ] || {}, - handlerQueue = []; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers that should run if there are delegated events - // Avoid non-left-click bubbling in Firefox (#3861) - if ( delegateCount && !(event.button && event.type === "click") ) { - - for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { - - // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.disabled !== true || event.type !== "click" ) { - selMatch = {}; - matches = []; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - sel = handleObj.selector; - - if ( selMatch[ sel ] === undefined ) { - selMatch[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) >= 0 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( selMatch[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push({ elem: cur, matches: matches }); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if ( handlers.length > delegateCount ) { - handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); - } - - // Run delegates first; they may want to stop propagation beneath us - for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { - matched = handlerQueue[ i ]; - event.currentTarget = matched.elem; - - for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { - handleObj = matched.matches[ j ]; - - // Triggered event must either 1) be non-exclusive and have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { - - event.data = handleObj.data; - event.handleObj = handleObj; - - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** - props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function( event, original ) { - var eventDoc, doc, body, - button = original.button, - fromElement = original.fromElement; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && fromElement ) { - event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, - originalEvent = event, - fixHook = jQuery.event.fixHooks[ event.type ] || {}, - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = jQuery.Event( originalEvent ); - - for ( i = copy.length; i; ) { - prop = copy[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) - if ( !event.target ) { - event.target = originalEvent.srcElement || document; - } - - // Target should not be a text node (#504, Safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8) - event.metaKey = !!event.metaKey; - - return fixHook.filter? fixHook.filter( event, originalEvent ) : event; - }, - - special: { - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - - focus: { - delegateType: "focusin" - }, - blur: { - delegateType: "focusout" - }, - - beforeunload: { - setup: function( data, namespaces, eventHandle ) { - // We only want to do this special case on windows - if ( jQuery.isWindow( this ) ) { - this.onbeforeunload = eventHandle; - } - }, - - teardown: function( namespaces, eventHandle ) { - if ( this.onbeforeunload === eventHandle ) { - this.onbeforeunload = null; - } - } - } - }, - - simulate: function( type, elem, event, bubble ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { type: type, - isSimulated: true, - originalEvent: {} - } - ); - if ( bubble ) { - jQuery.event.trigger( e, null, elem ); - } else { - jQuery.event.dispatch.call( elem, e ); - } - if ( e.isDefaultPrevented() ) { - event.preventDefault(); - } - } -}; - -// Some plugins are using, but it's undocumented/deprecated and will be removed. -// The 1.7 special event interface should provide all the hooks needed now. -jQuery.event.handle = jQuery.event.dispatch; - -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - var name = "on" + type; - - if ( elem.detachEvent ) { - - // #8545, #7054, preventing memory leaks for custom events in IE6-8 – - // detachEvent needed property on element, by name of that event, to properly expose it to GC - if ( typeof elem[ name ] === "undefined" ) { - elem[ name ] = null; - } - - elem.detachEvent( name, handle ); - } - }; - -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !(this instanceof jQuery.Event) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || - src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -function returnFalse() { - return false; -} -function returnTrue() { - return true; -} - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - - // if preventDefault exists run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // otherwise set the returnValue property of the original event to false (IE) - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - // if stopPropagation exists run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - // otherwise set the cancelBubble property of the original event to true (IE) - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; - -// Create mouseenter/leave events using mouseover/out and event-time checks -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj, - selector = handleObj.selector; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !jQuery.contains( target, related )) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -}); - -// IE submit delegation -if ( !jQuery.support.submitBubbles ) { - - jQuery.event.special.submit = { - setup: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Lazy-add a submit handler when a descendant form may potentially be submitted - jQuery.event.add( this, "click._submit keypress._submit", function( e ) { - // Node name check avoids a VML-related crash in IE (#9807) - var elem = e.target, - form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; - if ( form && !jQuery._data( form, "_submit_attached" ) ) { - jQuery.event.add( form, "submit._submit", function( event ) { - event._submit_bubble = true; - }); - jQuery._data( form, "_submit_attached", true ); - } - }); - // return undefined since we don't need an event listener - }, - - postDispatch: function( event ) { - // If form was submitted by the user, bubble the event up the tree - if ( event._submit_bubble ) { - delete event._submit_bubble; - if ( this.parentNode && !event.isTrigger ) { - jQuery.event.simulate( "submit", this.parentNode, event, true ); - } - } - }, - - teardown: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Remove delegated handlers; cleanData eventually reaps submit handlers attached above - jQuery.event.remove( this, "._submit" ); - } - }; -} - -// IE change delegation and checkbox/radio fix -if ( !jQuery.support.changeBubbles ) { - - jQuery.event.special.change = { - - setup: function() { - - if ( rformElems.test( this.nodeName ) ) { - // IE doesn't fire change on a check/radio until blur; trigger it on click - // after a propertychange. Eat the blur-change in special.change.handle. - // This still fires onchange a second time for check/radio after blur. - if ( this.type === "checkbox" || this.type === "radio" ) { - jQuery.event.add( this, "propertychange._change", function( event ) { - if ( event.originalEvent.propertyName === "checked" ) { - this._just_changed = true; - } - }); - jQuery.event.add( this, "click._change", function( event ) { - if ( this._just_changed && !event.isTrigger ) { - this._just_changed = false; - } - // Allow triggered, simulated change events (#11500) - jQuery.event.simulate( "change", this, event, true ); - }); - } - return false; - } - // Delegated event; lazy-add a change handler on descendant inputs - jQuery.event.add( this, "beforeactivate._change", function( e ) { - var elem = e.target; - - if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "_change_attached" ) ) { - jQuery.event.add( elem, "change._change", function( event ) { - if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { - jQuery.event.simulate( "change", this.parentNode, event, true ); - } - }); - jQuery._data( elem, "_change_attached", true ); - } - }); - }, - - handle: function( event ) { - var elem = event.target; - - // Swallow native change events from checkbox/radio, we already triggered them above - if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { - return event.handleObj.handler.apply( this, arguments ); - } - }, - - teardown: function() { - jQuery.event.remove( this, "._change" ); - - return !rformElems.test( this.nodeName ); - } - }; -} - -// Create "bubbling" focus and blur events -if ( !jQuery.support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler while someone wants focusin/focusout - var attaches = 0, - handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - if ( attaches++ === 0 ) { - document.addEventListener( orig, handler, true ); - } - }, - teardown: function() { - if ( --attaches === 0 ) { - document.removeEventListener( orig, handler, true ); - } - } - }; - }); -} - -jQuery.fn.extend({ - - on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { // && selector != null - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - this.on( type, selector, data, types[ type ], one ); - } - return this; - } - - if ( data == null && fn == null ) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return this; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return this.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - }); - }, - one: function( types, selector, data, fn ) { - return this.on( types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each(function() { - jQuery.event.remove( this, types, fn, selector ); - }); - }, - - bind: function( types, data, fn ) { - return this.on( types, null, data, fn ); - }, - unbind: function( types, fn ) { - return this.off( types, null, fn ); - }, - - live: function( types, data, fn ) { - jQuery( this.context ).on( types, this.selector, data, fn ); - return this; - }, - die: function( types, fn ) { - jQuery( this.context ).off( types, this.selector || "**", fn ); - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.on( types, selector, data, fn ); - }, - undelegate: function( selector, types, fn ) { - // ( namespace ) or ( selector, types [, fn] ) - return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - if ( this[0] ) { - return jQuery.event.trigger( type, data, this[0], true ); - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, - guid = fn.guid || jQuery.guid++, - i = 0, - toggler = function( event ) { - // Figure out which function to execute - var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; - jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ lastToggle ].apply( this, arguments ) || false; - }; - - // link all the functions, so any of them can unbind this click handler - toggler.guid = guid; - while ( i < args.length ) { - args[ i++ ].guid = guid; - } - - return this.click( toggler ); - }, - - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -}); - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - if ( fn == null ) { - fn = data; - data = null; - } - - return arguments.length > 0 ? - this.on( name, null, data, fn ) : - this.trigger( name ); - }; - - if ( rkeyEvent.test( name ) ) { - jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; - } - - if ( rmouseEvent.test( name ) ) { - jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; - } -}); -/*! - * Sizzle CSS Selector Engine - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license - * http://sizzlejs.com/ - */ -(function( window, undefined ) { - -var cachedruns, - assertGetIdNotName, - Expr, - getText, - isXML, - contains, - compile, - sortOrder, - hasDuplicate, - outermostContext, - - baseHasDuplicate = true, - strundefined = "undefined", - - expando = ( "sizcache" + Math.random() ).replace( ".", "" ), - - Token = String, - document = window.document, - docElem = document.documentElement, - dirruns = 0, - done = 0, - pop = [].pop, - push = [].push, - slice = [].slice, - // Use a stripped-down indexOf if a native one is unavailable - indexOf = [].indexOf || function( elem ) { - var i = 0, - len = this.length; - for ( ; i < len; i++ ) { - if ( this[i] === elem ) { - return i; - } - } - return -1; - }, - - // Augment a function for special use by Sizzle - markFunction = function( fn, value ) { - fn[ expando ] = value == null || value; - return fn; - }, - - createCache = function() { - var cache = {}, - keys = []; - - return markFunction(function( key, value ) { - // Only keep the most recent entries - if ( keys.push( key ) > Expr.cacheLength ) { - delete cache[ keys.shift() ]; - } - - return (cache[ key ] = value); - }, cache ); - }, - - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - - // Regex - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors - operators = "([*^$|!~]?=)", - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + - "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", - - // Prefer arguments not in parens/brackets, - // then attribute selectors and non-pseudos (denoted by :), - // then anything else - // These preferences are here to reduce the number of selectors - // needing tokenize in the PSEUDO preFilter - pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)", - - // For matchExpr.POS and matchExpr.needsContext - pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + - "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), - rpseudo = new RegExp( pseudos ), - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, - - rnot = /^:not/, - rsibling = /[\x20\t\r\n\f]*[+~]/, - rendsWithNot = /:not\($/, - - rheader = /h\d/i, - rinputs = /input|select|textarea|button/i, - - rbackslash = /\\(?!\\)/g, - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "POS": new RegExp( pos, "i" ), - "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - // For use in libraries implementing .is() - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) - }, - - // Support - - // Used for testing something on an element - assert = function( fn ) { - var div = document.createElement("div"); - - try { - return fn( div ); - } catch (e) { - return false; - } finally { - // release memory in IE - div = null; - } - }, - - // Check if getElementsByTagName("*") returns only elements - assertTagNameNoComments = assert(function( div ) { - div.appendChild( document.createComment("") ); - return !div.getElementsByTagName("*").length; - }), - - // Check if getAttribute returns normalized href attributes - assertHrefNotNormalized = assert(function( div ) { - div.innerHTML = ""; - return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && - div.firstChild.getAttribute("href") === "#"; - }), - - // Check if attributes should be retrieved by attribute nodes - assertAttributes = assert(function( div ) { - div.innerHTML = ""; - var type = typeof div.lastChild.getAttribute("multiple"); - // IE8 returns a string for some attributes even when not present - return type !== "boolean" && type !== "string"; - }), - - // Check if getElementsByClassName can be trusted - assertUsableClassName = assert(function( div ) { - // Opera can't find a second classname (in 9.6) - div.innerHTML = ""; - if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { - return false; - } - - // Safari 3.2 caches class attributes and doesn't catch changes - div.lastChild.className = "e"; - return div.getElementsByClassName("e").length === 2; - }), - - // Check if getElementById returns elements by name - // Check if getElementsByName privileges form controls or returns elements by ID - assertUsableName = assert(function( div ) { - // Inject content - div.id = expando + 0; - div.innerHTML = "
"; - docElem.insertBefore( div, docElem.firstChild ); - - // Test - var pass = document.getElementsByName && - // buggy browsers will return fewer than the correct 2 - document.getElementsByName( expando ).length === 2 + - // buggy browsers will return more than the correct 0 - document.getElementsByName( expando + 0 ).length; - assertGetIdNotName = !document.getElementById( expando ); - - // Cleanup - docElem.removeChild( div ); - - return pass; - }); - -// If slice is not available, provide a backup -try { - slice.call( docElem.childNodes, 0 )[0].nodeType; -} catch ( e ) { - slice = function( i ) { - var elem, - results = []; - for ( ; (elem = this[i]); i++ ) { - results.push( elem ); - } - return results; - }; -} - -function Sizzle( selector, context, results, seed ) { - results = results || []; - context = context || document; - var match, elem, xml, m, - nodeType = context.nodeType; - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - if ( nodeType !== 1 && nodeType !== 9 ) { - return []; - } - - xml = isXML( context ); - - if ( !xml && !seed ) { - if ( (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { - push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); - return results; - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed, xml ); -} - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - return Sizzle( expr, null, null, [ elem ] ).length > 0; -}; - -// Returns a function to use in pseudos for input types -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -// Returns a function to use in pseudos for buttons -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -// Returns a function to use in pseudos for positionals -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( nodeType ) { - if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (see #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - } else { - - // If no nodeType, this is expected to be an array - for ( ; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } - return ret; -}; - -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -// Element contains another -contains = Sizzle.contains = docElem.contains ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); - } : - docElem.compareDocumentPosition ? - function( a, b ) { - return b && !!( a.compareDocumentPosition( b ) & 16 ); - } : - function( a, b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - return false; - }; - -Sizzle.attr = function( elem, name ) { - var val, - xml = isXML( elem ); - - if ( !xml ) { - name = name.toLowerCase(); - } - if ( (val = Expr.attrHandle[ name ]) ) { - return val( elem ); - } - if ( xml || assertAttributes ) { - return elem.getAttribute( name ); - } - val = elem.getAttributeNode( name ); - return val ? - typeof elem[ name ] === "boolean" ? - elem[ name ] ? name : null : - val.specified ? val.value : null : - null; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - // IE6/7 return a modified href - attrHandle: assertHrefNotNormalized ? - {} : - { - "href": function( elem ) { - return elem.getAttribute( "href", 2 ); - }, - "type": function( elem ) { - return elem.getAttribute("type"); - } - }, - - find: { - "ID": assertGetIdNotName ? - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - } : - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - - return m ? - m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? - [m] : - undefined : - []; - } - }, - - "TAG": assertTagNameNoComments ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { - return context.getElementsByTagName( tag ); - } - } : - function( tag, context ) { - var results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - var elem, - tmp = [], - i = 0; - - for ( ; (elem = results[i]); i++ ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }, - - "NAME": assertUsableName && function( tag, context ) { - if ( typeof context.getElementsByName !== strundefined ) { - return context.getElementsByName( name ); - } - }, - - "CLASS": assertUsableClassName && function( className, context, xml ) { - if ( typeof context.getElementsByClassName !== strundefined && !xml ) { - return context.getElementsByClassName( className ); - } - } - }, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( rbackslash, "" ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 3 xn-component of xn+y argument ([+-]?\d*n|) - 4 sign of xn-component - 5 x of xn-component - 6 sign of y-component - 7 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1] === "nth" ) { - // nth-child requires argument - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); - match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); - - // other types prohibit arguments - } else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var unquoted, excess; - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - if ( match[3] ) { - match[2] = match[3]; - } else if ( (unquoted = match[4]) ) { - // Only check arguments that contain a pseudo - if ( rpseudo.test(unquoted) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - unquoted = unquoted.slice( 0, excess ); - match[0] = match[0].slice( 0, excess ); - } - match[2] = unquoted; - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - "ID": assertGetIdNotName ? - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - return elem.getAttribute("id") === id; - }; - } : - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === id; - }; - }, - - "TAG": function( nodeName ) { - if ( nodeName === "*" ) { - return function() { return true; }; - } - nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); - - return function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ expando ][ className ]; - if ( !pattern ) { - pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") ); - } - return function( elem ) { - return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); - }; - }, - - "ATTR": function( name, operator, check ) { - return function( elem, context ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.substr( result.length - check.length ) === check : - operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, argument, first, last ) { - - if ( type === "nth" ) { - return function( elem ) { - var node, diff, - parent = elem.parentNode; - - if ( first === 1 && last === 0 ) { - return true; - } - - if ( parent ) { - diff = 0; - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - diff++; - if ( elem === node ) { - break; - } - } - } - } - - // Incorporate the offset (or cast to NaN), then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - }; - } - - return function( elem ) { - var node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - /* falls through */ - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf.call( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), - // not comment, processing instructions, or others - // Thanks to Diego Perini for the nodeName shortcut - // Greater than "@" means alpha characters (specifically not starting with "#" or "?") - var nodeType; - elem = elem.firstChild; - while ( elem ) { - if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { - return false; - } - elem = elem.nextSibling; - } - return true; - }, - - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "text": function( elem ) { - var type, attr; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && - (type = elem.type) === "text" && - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); - }, - - // Input types - "radio": createInputPseudo("radio"), - "checkbox": createInputPseudo("checkbox"), - "file": createInputPseudo("file"), - "password": createInputPseudo("password"), - "image": createInputPseudo("image"), - - "submit": createButtonPseudo("submit"), - "reset": createButtonPseudo("reset"), - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "focus": function( elem ) { - var doc = elem.ownerDocument; - return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href); - }, - - "active": function( elem ) { - return elem === elem.ownerDocument.activeElement; - }, - - // Positional types - "first": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = 0; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = 1; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -function siblingCheck( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; -} - -sortOrder = docElem.compareDocumentPosition ? - function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? - a.compareDocumentPosition : - a.compareDocumentPosition(b) & 4 - ) ? -1 : 1; - } : - function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - -// Always assume the presence of duplicates if sort doesn't -// pass them to our comparison function (as in Google Chrome). -[0, 0].sort( sortOrder ); -baseHasDuplicate = !hasDuplicate; - -// Document sorting and removing duplicates -Sizzle.uniqueSort = function( results ) { - var elem, - i = 1; - - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( ; (elem = results[i]); i++ ) { - if ( elem === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - - return results; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -function tokenize( selector, parseOnly ) { - var matched, match, tokens, type, soFar, groups, preFilters, - cached = tokenCache[ expando ][ selector ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - soFar = soFar.slice( match[0].length ); - } - groups.push( tokens = [] ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - tokens.push( matched = new Token( match.shift() ) ); - soFar = soFar.slice( matched.length ); - - // Cast descendant combinators to space - matched.type = match[0].replace( rtrim, " " ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - // The last two arguments here are (context, xml) for backCompat - (match = preFilters[ type ]( match, document, true ))) ) { - - tokens.push( matched = new Token( match.shift() ) ); - soFar = soFar.slice( matched.length ); - matched.type = type; - matched.matches = match; - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && combinator.dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if ( !xml ) { - var cache, - dirkey = dirruns + " " + doneName + " ", - cachedkey = dirkey + cachedruns; - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - if ( (cache = elem[ expando ]) === cachedkey ) { - return elem.sizset; - } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { - if ( elem.sizset ) { - return elem; - } - } else { - elem[ expando ] = cachedkey; - if ( matcher( elem, context, xml ) ) { - elem.sizset = true; - return elem; - } - elem.sizset = false; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - if ( matcher( elem, context, xml ) ) { - return elem; - } - } - } - } - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - // Positional selectors apply to seed elements, so it is invalid to follow them with relative ones - if ( seed && postFinder ) { - return; - } - - var i, elem, postFilterIn, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [], seed ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - postFilterIn = condense( matcherOut, postMap ); - postFilter( postFilterIn, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = postFilterIn.length; - while ( i-- ) { - if ( (elem = postFilterIn[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - // Keep seed and results synchronized - if ( seed ) { - // Ignore postFinder because it can't coexist with seed - i = preFilter && matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - seed[ preMap[i] ] = !(results[ preMap[i] ] = elem); - } - } - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf.call( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; - } else { - // The concatenated values are (context, xml) for backCompat - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && tokens.join("") - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, expandContext ) { - var elem, j, matcher, - setMatched = [], - matchedCount = 0, - i = "0", - unmatched = seed && [], - outermost = expandContext != null, - contextBackup = outermostContext, - // We must always have either seed elements or context - elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), - // Nested matchers should use non-integer dirruns - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E); - - if ( outermost ) { - outermostContext = context !== document && context; - cachedruns = superMatcher.el; - } - - // Add elements passing elementMatchers directly to results - for ( ; (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - for ( j = 0; (matcher = elementMatchers[j]); j++ ) { - if ( matcher( elem, context, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - cachedruns = ++superMatcher.el; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if ( bySet && i !== matchedCount ) { - for ( j = 0; (matcher = setMatchers[j]); j++ ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - superMatcher.el = 0; - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ expando ][ selector ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !group ) { - group = tokenize( selector ); - } - i = group.length; - while ( i-- ) { - cached = matcherFromTokens( group[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - } - return cached; -}; - -function multipleContexts( selector, contexts, results, seed ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results, seed ); - } - return results; -} - -function select( selector, context, results, seed, xml ) { - var i, tokens, token, type, find, - match = tokenize( selector ), - j = match.length; - - if ( !seed ) { - // Try to minimize operations if there is only one group - if ( match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - context.nodeType === 9 && !xml && - Expr.relative[ tokens[1].type ] ) { - - context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0]; - if ( !context ) { - return results; - } - - selector = selector.slice( tokens.shift().length ); - } - - // Fetch a seed set for right-to-left matching - for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( rbackslash, "" ), - rsibling.test( tokens[0].type ) && context.parentNode || context, - xml - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && tokens.join(""); - if ( !selector ) { - push.apply( results, slice.call( seed, 0 ) ); - return results; - } - - break; - } - } - } - } - } - - // Compile and execute a filtering function - // Provide `match` to avoid retokenization if we modified the selector above - compile( selector, match )( - seed, - context, - xml, - results, - rsibling.test( selector ) - ); - return results; -} - -if ( document.querySelectorAll ) { - (function() { - var disconnectedMatch, - oldSelect = select, - rescape = /'|\\/g, - rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, - - // qSa(:focus) reports false when true (Chrome 21), - // A support test would require too much code (would include document ready) - rbuggyQSA = [":focus"], - - // matchesSelector(:focus) reports false when true (Chrome 21), - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - // A support test would require too much code (would include document ready) - // just skip matchesSelector for :active - rbuggyMatches = [ ":active", ":focus" ], - matches = docElem.matchesSelector || - docElem.mozMatchesSelector || - docElem.webkitMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector; - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explictly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = ""; - - // IE8 - Some boolean attributes are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here (do not put tests after this one) - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function( div ) { - - // Opera 10-12/IE9 - ^= $= *= and empty values - // Should not select anything - div.innerHTML = "

"; - if ( div.querySelectorAll("[test^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here (do not put tests after this one) - div.innerHTML = ""; - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push(":enabled", ":disabled"); - } - }); - - // rbuggyQSA always contains :focus, so no need for a length check - rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") ); - - select = function( selector, context, results, seed, xml ) { - // Only use querySelectorAll when not filtering, - // when this is not xml, - // and when no QSA bugs apply - if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - var groups, i, - old = true, - nid = expando, - newContext = context, - newSelector = context.nodeType === 9 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - groups = tokenize( selector ); - - if ( (old = context.getAttribute("id")) ) { - nid = old.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while ( i-- ) { - groups[i] = nid + groups[i].join(""); - } - newContext = rsibling.test( selector ) && context.parentNode || context; - newSelector = groups.join(","); - } - - if ( newSelector ) { - try { - push.apply( results, slice.call( newContext.querySelectorAll( - newSelector - ), 0 ) ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - - return oldSelect( selector, context, results, seed, xml ); - }; - - if ( matches ) { - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - try { - matches.call( div, "[test!='']:sizzle" ); - rbuggyMatches.push( "!=", pseudos ); - } catch ( e ) {} - }); - - // rbuggyMatches always contains :active and :focus, so no need for a length check - rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); - - Sizzle.matchesSelector = function( elem, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - // rbuggyMatches always contains :active, so no need for an existence check - if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) { - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch(e) {} - } - - return Sizzle( expr, null, null, [ elem ] ).length > 0; - }; - } - })(); -} - -// Deprecated -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Back-compat -function setFilters() {} -Expr.filters = setFilters.prototype = Expr.pseudos; -Expr.setFilters = new setFilters(); - -// Override sizzle attribute retrieval -Sizzle.attr = jQuery.attr; -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.pseudos; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})( window ); -var runtil = /Until$/, - rparentsprev = /^(?:parents|prev(?:Until|All))/, - isSimple = /^.[^:#\[\.,]*$/, - rneedsContext = jQuery.expr.match.needsContext, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend({ - find: function( selector ) { - var i, l, length, n, r, ret, - self = this; - - if ( typeof selector !== "string" ) { - return jQuery( selector ).filter(function() { - for ( i = 0, l = self.length; i < l; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }); - } - - ret = this.pushStack( "", "find", selector ); - - for ( i = 0, l = this.length; i < l; i++ ) { - length = ret.length; - jQuery.find( selector, this[i], ret ); - - if ( i > 0 ) { - // Make sure that the results are unique - for ( n = length; n < ret.length; n++ ) { - for ( r = 0; r < length; r++ ) { - if ( ret[r] === ret[n] ) { - ret.splice(n--, 1); - break; - } - } - } - } - } - - return ret; - }, - - has: function( target ) { - var i, - targets = jQuery( target, this ), - len = targets.length; - - return this.filter(function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - not: function( selector ) { - return this.pushStack( winnow(this, selector, false), "not", selector); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector, true), "filter", selector ); - }, - - is: function( selector ) { - return !!selector && ( - typeof selector === "string" ? - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - rneedsContext.test( selector ) ? - jQuery( selector, this.context ).index( this[0] ) >= 0 : - jQuery.filter( selector, this ).length > 0 : - this.filter( selector ).length > 0 ); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - ret = [], - pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( ; i < l; i++ ) { - cur = this[i]; - - while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); - break; - } - cur = cur.parentNode; - } - } - - ret = ret.length > 1 ? jQuery.unique( ret ) : ret; - - return this.pushStack( ret, "closest", selectors ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; - } - - // index in selector - if ( typeof elem === "string" ) { - return jQuery.inArray( this[0], jQuery( elem ) ); - } - - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this ); - }, - - add: function( selector, context ) { - var set = typeof selector === "string" ? - jQuery( selector, context ) : - jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), - all = jQuery.merge( this.get(), set ); - - return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? - all : - jQuery.unique( all ) ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter(selector) - ); - } -}); - -jQuery.fn.andSelf = jQuery.fn.addBack; - -// A painfully simple check to see if an element is disconnected -// from a document (should be improved, where feasible). -function isDisconnected( node ) { - return !node || !node.parentNode || node.parentNode.nodeType === 11; -} - -function sibling( cur, dir ) { - do { - cur = cur[ dir ]; - } while ( cur && cur.nodeType !== 1 ); - - return cur; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ); - - if ( !runtil.test( name ) ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); - } - - ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; - - if ( this.length > 1 && rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - - return this.pushStack( ret, name, core_slice.call( arguments ).join(",") ); - }; -}); - -jQuery.extend({ - filter: function( expr, elems, not ) { - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 ? - jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : - jQuery.find.matches(expr, elems); - }, - - dir: function( elem, dir, until ) { - var matched = [], - cur = elem[ dir ]; - - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); - } - cur = cur[dir]; - } - return matched; - }, - - sibling: function( n, elem ) { - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); - } - } - - return r; - } -}); - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, keep ) { - - // Can't pass null or undefined to indexOf in Firefox 4 - // Set to 0 to skip string check - qualifier = qualifier || 0; - - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep(elements, function( elem, i ) { - var retVal = !!qualifier.call( elem, i, elem ); - return retVal === keep; - }); - - } else if ( qualifier.nodeType ) { - return jQuery.grep(elements, function( elem, i ) { - return ( elem === qualifier ) === keep; - }); - - } else if ( typeof qualifier === "string" ) { - var filtered = jQuery.grep(elements, function( elem ) { - return elem.nodeType === 1; - }); - - if ( isSimple.test( qualifier ) ) { - return jQuery.filter(qualifier, filtered, !keep); - } else { - qualifier = jQuery.filter( qualifier, filtered ); - } - } - - return jQuery.grep(elements, function( elem, i ) { - return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; - }); -} -function createSafeFragment( document ) { - var list = nodeNames.split( "|" ), - safeFrag = document.createDocumentFragment(); - - if ( safeFrag.createElement ) { - while ( list.length ) { - safeFrag.createElement( - list.pop() - ); - } - } - return safeFrag; -} - -var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + - "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", - rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, - rtagName = /<([\w:]+)/, - rtbody = /]", "i"), - rcheckableType = /^(?:checkbox|radio)$/, - // checked="checked" or checked - rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, - rscriptType = /\/(java|ecma)script/i, - rcleanScript = /^\s*\s*$/g, - wrapMap = { - option: [ 1, "" ], - legend: [ 1, "
", "
" ], - thead: [ 1, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], - col: [ 2, "", "
" ], - area: [ 1, "", "" ], - _default: [ 0, "", "" ] - }, - safeFragment = createSafeFragment( document ), - fragmentDiv = safeFragment.appendChild( document.createElement("div") ); - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, -// unless wrapped in a div with non-breaking characters in front of it. -if ( !jQuery.support.htmlSerialize ) { - wrapMap._default = [ 1, "X
", "
" ]; -} - -jQuery.fn.extend({ - text: function( value ) { - return jQuery.access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); - }, null, value, arguments.length ); - }, - - wrapAll: function( html ) { - if ( jQuery.isFunction( html ) ) { - return this.each(function(i) { - jQuery(this).wrapAll( html.call(this, i) ); - }); - } - - if ( this[0] ) { - // The elements to wrap the target around - var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); - - if ( this[0].parentNode ) { - wrap.insertBefore( this[0] ); - } - - wrap.map(function() { - var elem = this; - - while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { - elem = elem.firstChild; - } - - return elem; - }).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( jQuery.isFunction( html ) ) { - return this.each(function(i) { - jQuery(this).wrapInner( html.call(this, i) ); - }); - } - - return this.each(function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - }); - }, - - wrap: function( html ) { - var isFunction = jQuery.isFunction( html ); - - return this.each(function(i) { - jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); - }); - }, - - unwrap: function() { - return this.parent().each(function() { - if ( !jQuery.nodeName( this, "body" ) ) { - jQuery( this ).replaceWith( this.childNodes ); - } - }).end(); - }, - - append: function() { - return this.domManip(arguments, true, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 ) { - this.appendChild( elem ); - } - }); - }, - - prepend: function() { - return this.domManip(arguments, true, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 ) { - this.insertBefore( elem, this.firstChild ); - } - }); - }, - - before: function() { - if ( !isDisconnected( this[0] ) ) { - return this.domManip(arguments, false, function( elem ) { - this.parentNode.insertBefore( elem, this ); - }); - } - - if ( arguments.length ) { - var set = jQuery.clean( arguments ); - return this.pushStack( jQuery.merge( set, this ), "before", this.selector ); - } - }, - - after: function() { - if ( !isDisconnected( this[0] ) ) { - return this.domManip(arguments, false, function( elem ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - }); - } - - if ( arguments.length ) { - var set = jQuery.clean( arguments ); - return this.pushStack( jQuery.merge( this, set ), "after", this.selector ); - } - }, - - // keepData is for internal use only--do not document - remove: function( selector, keepData ) { - var elem, - i = 0; - - for ( ; (elem = this[i]) != null; i++ ) { - if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { - if ( !keepData && elem.nodeType === 1 ) { - jQuery.cleanData( elem.getElementsByTagName("*") ); - jQuery.cleanData( [ elem ] ); - } - - if ( elem.parentNode ) { - elem.parentNode.removeChild( elem ); - } - } - } - - return this; - }, - - empty: function() { - var elem, - i = 0; - - for ( ; (elem = this[i]) != null; i++ ) { - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( elem.getElementsByTagName("*") ); - } - - // Remove any remaining nodes - while ( elem.firstChild ) { - elem.removeChild( elem.firstChild ); - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map( function () { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - }); - }, - - html: function( value ) { - return jQuery.access( this, function( value ) { - var elem = this[0] || {}, - i = 0, - l = this.length; - - if ( value === undefined ) { - return elem.nodeType === 1 ? - elem.innerHTML.replace( rinlinejQuery, "" ) : - undefined; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && - ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && - !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { - - value = value.replace( rxhtmlTag, "<$1>" ); - - try { - for (; i < l; i++ ) { - // Remove element nodes and prevent memory leaks - elem = this[i] || {}; - if ( elem.nodeType === 1 ) { - jQuery.cleanData( elem.getElementsByTagName( "*" ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch(e) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function( value ) { - if ( !isDisconnected( this[0] ) ) { - // Make sure that the elements are removed from the DOM before they are inserted - // this can help fix replacing a parent with child elements - if ( jQuery.isFunction( value ) ) { - return this.each(function(i) { - var self = jQuery(this), old = self.html(); - self.replaceWith( value.call( this, i, old ) ); - }); - } - - if ( typeof value !== "string" ) { - value = jQuery( value ).detach(); - } - - return this.each(function() { - var next = this.nextSibling, - parent = this.parentNode; - - jQuery( this ).remove(); - - if ( next ) { - jQuery(next).before( value ); - } else { - jQuery(parent).append( value ); - } - }); - } - - return this.length ? - this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : - this; - }, - - detach: function( selector ) { - return this.remove( selector, true ); - }, - - domManip: function( args, table, callback ) { - - // Flatten any nested arrays - args = [].concat.apply( [], args ); - - var results, first, fragment, iNoClone, - i = 0, - value = args[0], - scripts = [], - l = this.length; - - // We can't cloneNode fragments that contain checked, in WebKit - if ( !jQuery.support.checkClone && l > 1 && typeof value === "string" && rchecked.test( value ) ) { - return this.each(function() { - jQuery(this).domManip( args, table, callback ); - }); - } - - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - args[0] = value.call( this, i, table ? self.html() : undefined ); - self.domManip( args, table, callback ); - }); - } - - if ( this[0] ) { - results = jQuery.buildFragment( args, this, scripts ); - fragment = results.fragment; - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - if ( first ) { - table = table && jQuery.nodeName( first, "tr" ); - - // Use the original fragment for the last item instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - // Fragments from the fragment cache must always be cloned and never used in place. - for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) { - callback.call( - table && jQuery.nodeName( this[i], "table" ) ? - findOrAppend( this[i], "tbody" ) : - this[i], - i === iNoClone ? - fragment : - jQuery.clone( fragment, true, true ) - ); - } - } - - // Fix #11809: Avoid leaking memory - fragment = first = null; - - if ( scripts.length ) { - jQuery.each( scripts, function( i, elem ) { - if ( elem.src ) { - if ( jQuery.ajax ) { - jQuery.ajax({ - url: elem.src, - type: "GET", - dataType: "script", - async: false, - global: false, - "throws": true - }); - } else { - jQuery.error("no ajax"); - } - } else { - jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "" ) ); - } - - if ( elem.parentNode ) { - elem.parentNode.removeChild( elem ); - } - }); - } - } - - return this; - } -}); - -function findOrAppend( elem, tag ) { - return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) ); -} - -function cloneCopyEvent( src, dest ) { - - if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { - return; - } - - var type, i, l, - oldData = jQuery._data( src ), - curData = jQuery._data( dest, oldData ), - events = oldData.events; - - if ( events ) { - delete curData.handle; - curData.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - - // make the cloned public data object a copy from the original - if ( curData.data ) { - curData.data = jQuery.extend( {}, curData.data ); - } -} - -function cloneFixAttributes( src, dest ) { - var nodeName; - - // We do not need to do anything for non-Elements - if ( dest.nodeType !== 1 ) { - return; - } - - // clearAttributes removes the attributes, which we don't want, - // but also removes the attachEvent events, which we *do* want - if ( dest.clearAttributes ) { - dest.clearAttributes(); - } - - // mergeAttributes, in contrast, only merges back on the - // original attributes, not the events - if ( dest.mergeAttributes ) { - dest.mergeAttributes( src ); - } - - nodeName = dest.nodeName.toLowerCase(); - - if ( nodeName === "object" ) { - // IE6-10 improperly clones children of object elements using classid. - // IE10 throws NoModificationAllowedError if parent is null, #12132. - if ( dest.parentNode ) { - dest.outerHTML = src.outerHTML; - } - - // This path appears unavoidable for IE9. When cloning an object - // element in IE9, the outerHTML strategy above is not sufficient. - // If the src has innerHTML and the destination does not, - // copy the src.innerHTML into the dest.innerHTML. #10324 - if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) { - dest.innerHTML = src.innerHTML; - } - - } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - // IE6-8 fails to persist the checked state of a cloned checkbox - // or radio button. Worse, IE6-7 fail to give the cloned element - // a checked appearance if the defaultChecked value isn't also set - - dest.defaultChecked = dest.checked = src.checked; - - // IE6-7 get confused and end up setting the value of a cloned - // checkbox/radio button to an empty string instead of "on" - if ( dest.value !== src.value ) { - dest.value = src.value; - } - - // IE6-8 fails to return the selected option to the default selected - // state when cloning options - } else if ( nodeName === "option" ) { - dest.selected = src.defaultSelected; - - // IE6-8 fails to set the defaultValue to the correct value when - // cloning other types of input fields - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - - // IE blanks contents when cloning scripts - } else if ( nodeName === "script" && dest.text !== src.text ) { - dest.text = src.text; - } - - // Event data gets referenced instead of copied if the expando - // gets copied too - dest.removeAttribute( jQuery.expando ); -} - -jQuery.buildFragment = function( args, context, scripts ) { - var fragment, cacheable, cachehit, - first = args[ 0 ]; - - // Set context from what may come in as undefined or a jQuery collection or a node - // Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 & - // also doubles as fix for #8950 where plain objects caused createDocumentFragment exception - context = context || document; - context = !context.nodeType && context[0] || context; - context = context.ownerDocument || context; - - // Only cache "small" (1/2 KB) HTML strings that are associated with the main document - // Cloning options loses the selected state, so don't cache them - // IE 6 doesn't like it when you put or elements in a fragment - // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache - // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501 - if ( args.length === 1 && typeof first === "string" && first.length < 512 && context === document && - first.charAt(0) === "<" && !rnocache.test( first ) && - (jQuery.support.checkClone || !rchecked.test( first )) && - (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) { - - // Mark cacheable and look for a hit - cacheable = true; - fragment = jQuery.fragments[ first ]; - cachehit = fragment !== undefined; - } - - if ( !fragment ) { - fragment = context.createDocumentFragment(); - jQuery.clean( args, context, fragment, scripts ); - - // Update the cache, but only store false - // unless this is a second parsing of the same content - if ( cacheable ) { - jQuery.fragments[ first ] = cachehit && fragment; - } - } - - return { fragment: fragment, cacheable: cacheable }; -}; - -jQuery.fragments = {}; - -jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - i = 0, - ret = [], - insert = jQuery( selector ), - l = insert.length, - parent = this.length === 1 && this[0].parentNode; - - if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) { - insert[ original ]( this[0] ); - return this; - } else { - for ( ; i < l; i++ ) { - elems = ( i > 0 ? this.clone(true) : this ).get(); - jQuery( insert[i] )[ original ]( elems ); - ret = ret.concat( elems ); - } - - return this.pushStack( ret, name, insert.selector ); - } - }; -}); - -function getAll( elem ) { - if ( typeof elem.getElementsByTagName !== "undefined" ) { - return elem.getElementsByTagName( "*" ); - - } else if ( typeof elem.querySelectorAll !== "undefined" ) { - return elem.querySelectorAll( "*" ); - - } else { - return []; - } -} - -// Used in clean, fixes the defaultChecked property -function fixDefaultChecked( elem ) { - if ( rcheckableType.test( elem.type ) ) { - elem.defaultChecked = elem.checked; - } -} - -jQuery.extend({ - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var srcElements, - destElements, - i, - clone; - - if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { - clone = elem.cloneNode( true ); - - // IE<=8 does not properly clone detached, unknown element nodes - } else { - fragmentDiv.innerHTML = elem.outerHTML; - fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); - } - - if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && - (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { - // IE copies events bound via attachEvent when using cloneNode. - // Calling detachEvent on the clone will also remove the events - // from the original. In order to get around this, we use some - // proprietary methods to clear the events. Thanks to MooTools - // guys for this hotness. - - cloneFixAttributes( elem, clone ); - - // Using Sizzle here is crazy slow, so we use getElementsByTagName instead - srcElements = getAll( elem ); - destElements = getAll( clone ); - - // Weird iteration because IE will replace the length property - // with an element if you are cloning the body and one of the - // elements on the page has a name or id of "length" - for ( i = 0; srcElements[i]; ++i ) { - // Ensure that the destination node is not null; Fixes #9587 - if ( destElements[i] ) { - cloneFixAttributes( srcElements[i], destElements[i] ); - } - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - cloneCopyEvent( elem, clone ); - - if ( deepDataAndEvents ) { - srcElements = getAll( elem ); - destElements = getAll( clone ); - - for ( i = 0; srcElements[i]; ++i ) { - cloneCopyEvent( srcElements[i], destElements[i] ); - } - } - } - - srcElements = destElements = null; - - // Return the cloned set - return clone; - }, - - clean: function( elems, context, fragment, scripts ) { - var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags, - safe = context === document && safeFragment, - ret = []; - - // Ensure that context is a document - if ( !context || typeof context.createDocumentFragment === "undefined" ) { - context = document; - } - - // Use the already-created safe fragment if context permits - for ( i = 0; (elem = elems[i]) != null; i++ ) { - if ( typeof elem === "number" ) { - elem += ""; - } - - if ( !elem ) { - continue; - } - - // Convert html string into DOM nodes - if ( typeof elem === "string" ) { - if ( !rhtml.test( elem ) ) { - elem = context.createTextNode( elem ); - } else { - // Ensure a safe container in which to render the html - safe = safe || createSafeFragment( context ); - div = context.createElement("div"); - safe.appendChild( div ); - - // Fix "XHTML"-style tags in all browsers - elem = elem.replace(rxhtmlTag, "<$1>"); - - // Go to html and back, then peel off extra wrappers - tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - depth = wrap[0]; - div.innerHTML = wrap[1] + elem + wrap[2]; - - // Move to the right depth - while ( depth-- ) { - div = div.lastChild; - } - - // Remove IE's autoinserted from table fragments - if ( !jQuery.support.tbody ) { - - // String was a , *may* have spurious - hasBody = rtbody.test(elem); - tbody = tag === "table" && !hasBody ? - div.firstChild && div.firstChild.childNodes : - - // String was a bare or - wrap[1] === "
" && !hasBody ? - div.childNodes : - []; - - for ( j = tbody.length - 1; j >= 0 ; --j ) { - if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { - tbody[ j ].parentNode.removeChild( tbody[ j ] ); - } - } - } - - // IE completely kills leading whitespace when innerHTML is used - if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { - div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); - } - - elem = div.childNodes; - - // Take out of fragment container (we need a fresh div each time) - div.parentNode.removeChild( div ); - } - } - - if ( elem.nodeType ) { - ret.push( elem ); - } else { - jQuery.merge( ret, elem ); - } - } - - // Fix #11356: Clear elements from safeFragment - if ( div ) { - elem = div = safe = null; - } - - // Reset defaultChecked for any radios and checkboxes - // about to be appended to the DOM in IE 6/7 (#8060) - if ( !jQuery.support.appendChecked ) { - for ( i = 0; (elem = ret[i]) != null; i++ ) { - if ( jQuery.nodeName( elem, "input" ) ) { - fixDefaultChecked( elem ); - } else if ( typeof elem.getElementsByTagName !== "undefined" ) { - jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked ); - } - } - } - - // Append elements to a provided document fragment - if ( fragment ) { - // Special handling of each script element - handleScript = function( elem ) { - // Check if we consider it executable - if ( !elem.type || rscriptType.test( elem.type ) ) { - // Detach the script and store it in the scripts array (if provided) or the fragment - // Return truthy to indicate that it has been handled - return scripts ? - scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) : - fragment.appendChild( elem ); - } - }; - - for ( i = 0; (elem = ret[i]) != null; i++ ) { - // Check if we're done after handling an executable script - if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) { - // Append to fragment and handle embedded scripts - fragment.appendChild( elem ); - if ( typeof elem.getElementsByTagName !== "undefined" ) { - // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration - jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript ); - - // Splice the scripts into ret after their former ancestor and advance our index beyond them - ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) ); - i += jsTags.length; - } - } - } - } - - return ret; - }, - - cleanData: function( elems, /* internal */ acceptData ) { - var data, id, elem, type, - i = 0, - internalKey = jQuery.expando, - cache = jQuery.cache, - deleteExpando = jQuery.support.deleteExpando, - special = jQuery.event.special; - - for ( ; (elem = elems[i]) != null; i++ ) { - - if ( acceptData || jQuery.acceptData( elem ) ) { - - id = elem[ internalKey ]; - data = id && cache[ id ]; - - if ( data ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Remove cache only if it was not already removed by jQuery.event.remove - if ( cache[ id ] ) { - - delete cache[ id ]; - - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( deleteExpando ) { - delete elem[ internalKey ]; - - } else if ( elem.removeAttribute ) { - elem.removeAttribute( internalKey ); - - } else { - elem[ internalKey ] = null; - } - - jQuery.deletedIds.push( id ); - } - } - } - } - } -}); -// Limit scope pollution from any deprecated API -(function() { - -var matched, browser; - -// Use of jQuery.browser is frowned upon. -// More details: http://api.jquery.com/jQuery.browser -// jQuery.uaMatch maintained for back-compat -jQuery.uaMatch = function( ua ) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) || - /(webkit)[ \/]([\w.]+)/.exec( ua ) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) || - /(msie) ([\w.]+)/.exec( ua ) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; -}; - -matched = jQuery.uaMatch( navigator.userAgent ); -browser = {}; - -if ( matched.browser ) { - browser[ matched.browser ] = true; - browser.version = matched.version; -} - -// Chrome is Webkit, but Webkit is also Safari. -if ( browser.chrome ) { - browser.webkit = true; -} else if ( browser.webkit ) { - browser.safari = true; -} - -jQuery.browser = browser; - -jQuery.sub = function() { - function jQuerySub( selector, context ) { - return new jQuerySub.fn.init( selector, context ); - } - jQuery.extend( true, jQuerySub, this ); - jQuerySub.superclass = this; - jQuerySub.fn = jQuerySub.prototype = this(); - jQuerySub.fn.constructor = jQuerySub; - jQuerySub.sub = this.sub; - jQuerySub.fn.init = function init( selector, context ) { - if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { - context = jQuerySub( context ); - } - - return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); - }; - jQuerySub.fn.init.prototype = jQuerySub.fn; - var rootjQuerySub = jQuerySub(document); - return jQuerySub; -}; - -})(); -var curCSS, iframe, iframeDoc, - ralpha = /alpha\([^)]*\)/i, - ropacity = /opacity=([^)]*)/, - rposition = /^(top|right|bottom|left)$/, - // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" - // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rmargin = /^margin/, - rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), - rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), - rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ), - elemdisplay = {}, - - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: 0, - fontWeight: 400 - }, - - cssExpand = [ "Top", "Right", "Bottom", "Left" ], - cssPrefixes = [ "Webkit", "O", "Moz", "ms" ], - - eventsToggle = jQuery.fn.toggle; - -// return a css property mapped to a potentially vendor prefixed property -function vendorPropName( style, name ) { - - // shortcut for names that are not vendor prefixed - if ( name in style ) { - return name; - } - - // check for vendor prefixed names - var capName = name.charAt(0).toUpperCase() + name.slice(1), - origName = name, - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in style ) { - return name; - } - } - - return origName; -} - -function isHidden( elem, el ) { - elem = el || elem; - return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); -} - -function showHide( elements, show ) { - var elem, display, - values = [], - index = 0, - length = elements.length; - - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - values[ index ] = jQuery._data( elem, "olddisplay" ); - if ( show ) { - // Reset the inline display of this element to learn if it is - // being hidden by cascaded rules or not - if ( !values[ index ] && elem.style.display === "none" ) { - elem.style.display = ""; - } - - // Set elements which have been overridden with display: none - // in a stylesheet to whatever the default browser style is - // for such an element - if ( elem.style.display === "" && isHidden( elem ) ) { - values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); - } - } else { - display = curCSS( elem, "display" ); - - if ( !values[ index ] && display !== "none" ) { - jQuery._data( elem, "olddisplay", display ); - } - } - } - - // Set the display of most of the elements in a second loop - // to avoid the constant reflow - for ( index = 0; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - if ( !show || elem.style.display === "none" || elem.style.display === "" ) { - elem.style.display = show ? values[ index ] || "" : "none"; - } - } - - return elements; -} - -jQuery.fn.extend({ - css: function( name, value ) { - return jQuery.access( this, function( elem, name, value ) { - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - }, - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state, fn2 ) { - var bool = typeof state === "boolean"; - - if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) { - return eventsToggle.apply( this, arguments ); - } - - return this.each(function() { - if ( bool ? state : isHidden( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - }); - } -}); - -jQuery.extend({ - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - - } - } - } - }, - - // Exclude the following css properties to add px - cssNumber: { - "fillOpacity": true, - "fontWeight": true, - "lineHeight": true, - "opacity": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: { - // normalize float css property - "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" - }, - - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = jQuery.camelCase( name ), - style = elem.style; - - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // convert relative number strings (+= or -=) to relative numbers. #7345 - if ( type === "string" && (ret = rrelNum.exec( value )) ) { - value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); - // Fixes bug #9237 - type = "number"; - } - - // Make sure that NaN and null values aren't set. See: #7116 - if ( value == null || type === "number" && isNaN( value ) ) { - return; - } - - // If a number was passed in, add 'px' to the (except for certain CSS properties) - if ( type === "number" && !jQuery.cssNumber[ origName ] ) { - value += "px"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { - // Wrapped to prevent IE from throwing errors when 'invalid' values are provided - // Fixes bug #5509 - try { - style[ name ] = value; - } catch(e) {} - } - - } else { - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { - return ret; - } - - // Otherwise just get the value from the style object - return style[ name ]; - } - }, - - css: function( elem, name, numeric, extra ) { - var val, num, hooks, - origName = jQuery.camelCase( name ); - - // Make sure that we're working with the right name - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } - - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name ); - } - - //convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } - - // Return, converting to number if forced or a qualifier was provided and val looks numeric - if ( numeric || extra !== undefined ) { - num = parseFloat( val ); - return numeric || jQuery.isNumeric( num ) ? num || 0 : val; - } - return val; - }, - - // A method for quickly swapping in/out CSS properties to get correct calculations - swap: function( elem, options, callback ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.call( elem ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; - } -}); - -// NOTE: To any future maintainer, we've window.getComputedStyle -// because jsdom on node.js will break without it. -if ( window.getComputedStyle ) { - curCSS = function( elem, name ) { - var ret, width, minWidth, maxWidth, - computed = window.getComputedStyle( elem, null ), - style = elem.style; - - if ( computed ) { - - ret = computed[ name ]; - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { - ret = jQuery.style( elem, name ); - } - - // A tribute to the "awesome hack by Dean Edwards" - // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right - // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels - // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values - if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - return ret; - }; -} else if ( document.documentElement.currentStyle ) { - curCSS = function( elem, name ) { - var left, rsLeft, - ret = elem.currentStyle && elem.currentStyle[ name ], - style = elem.style; - - // Avoid setting ret to empty string here - // so we don't default to auto - if ( ret == null && style && style[ name ] ) { - ret = style[ name ]; - } - - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - // but not position css attributes, as those are proportional to the parent element instead - // and we can't measure the parent instead because it might trigger a "stacking dolls" problem - if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { - - // Remember the original values - left = style.left; - rsLeft = elem.runtimeStyle && elem.runtimeStyle.left; - - // Put in the new values to get a computed value out - if ( rsLeft ) { - elem.runtimeStyle.left = elem.currentStyle.left; - } - style.left = name === "fontSize" ? "1em" : ret; - ret = style.pixelLeft + "px"; - - // Revert the changed values - style.left = left; - if ( rsLeft ) { - elem.runtimeStyle.left = rsLeft; - } - } - - return ret === "" ? "auto" : ret; - }; -} - -function setPositiveNumber( elem, value, subtract ) { - var matches = rnumsplit.exec( value ); - return matches ? - Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : - value; -} - -function augmentWidthOrHeight( elem, name, extra, isBorderBox ) { - var i = extra === ( isBorderBox ? "border" : "content" ) ? - // If we already have the right measurement, avoid augmentation - 4 : - // Otherwise initialize for horizontal or vertical properties - name === "width" ? 1 : 0, - - val = 0; - - for ( ; i < 4; i += 2 ) { - // both box models exclude margin, so add it if we want it - if ( extra === "margin" ) { - // we use jQuery.css instead of curCSS here - // because of the reliableMarginRight CSS hook! - val += jQuery.css( elem, extra + cssExpand[ i ], true ); - } - - // From this point on we use curCSS for maximum performance (relevant in animations) - if ( isBorderBox ) { - // border-box includes padding, so remove it if we want content - if ( extra === "content" ) { - val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0; - } - - // at this point, extra isn't border nor margin, so remove border - if ( extra !== "margin" ) { - val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; - } - } else { - // at this point, extra isn't content, so add padding - val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0; - - // at this point, extra isn't content nor padding, so add border - if ( extra !== "padding" ) { - val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; - } - } - } - - return val; -} - -function getWidthOrHeight( elem, name, extra ) { - - // Start with offset property, which is equivalent to the border-box value - var val = name === "width" ? elem.offsetWidth : elem.offsetHeight, - valueIsBorderBox = true, - isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"; - - // some non-html elements return undefined for offsetWidth, so check for null/undefined - // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 - // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 - if ( val <= 0 || val == null ) { - // Fall back to computed then uncomputed css if necessary - val = curCSS( elem, name ); - if ( val < 0 || val == null ) { - val = elem.style[ name ]; - } - - // Computed unit is not pixels. Stop here and return. - if ( rnumnonpx.test(val) ) { - return val; - } - - // we need the check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); - - // Normalize "", auto, and prepare for extra - val = parseFloat( val ) || 0; - } - - // use the active box-sizing model to add/subtract irrelevant styles - return ( val + - augmentWidthOrHeight( - elem, - name, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox - ) - ) + "px"; -} - - -// Try to determine the default display value of an element -function css_defaultDisplay( nodeName ) { - if ( elemdisplay[ nodeName ] ) { - return elemdisplay[ nodeName ]; - } - - var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ), - display = elem.css("display"); - elem.remove(); - - // If the simple way fails, - // get element's real default display by attaching it to a temp iframe - if ( display === "none" || display === "" ) { - // Use the already-created iframe if possible - iframe = document.body.appendChild( - iframe || jQuery.extend( document.createElement("iframe"), { - frameBorder: 0, - width: 0, - height: 0 - }) - ); - - // Create a cacheable copy of the iframe document on first call. - // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML - // document to it; WebKit & Firefox won't allow reusing the iframe document. - if ( !iframeDoc || !iframe.createElement ) { - iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document; - iframeDoc.write(""); - iframeDoc.close(); - } - - elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) ); - - display = curCSS( elem, "display" ); - document.body.removeChild( iframe ); - } - - // Store the correct default display - elemdisplay[ nodeName ] = display; - - return display; -} - -jQuery.each([ "height", "width" ], function( i, name ) { - jQuery.cssHooks[ name ] = { - get: function( elem, computed, extra ) { - if ( computed ) { - // certain elements can have dimension info if we invisibly show them - // however, it must have a current display style that would benefit from this - if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, "display" ) ) ) { - return jQuery.swap( elem, cssShow, function() { - return getWidthOrHeight( elem, name, extra ); - }); - } else { - return getWidthOrHeight( elem, name, extra ); - } - } - }, - - set: function( elem, value, extra ) { - return setPositiveNumber( elem, value, extra ? - augmentWidthOrHeight( - elem, - name, - extra, - jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box" - ) : 0 - ); - } - }; -}); - -if ( !jQuery.support.opacity ) { - jQuery.cssHooks.opacity = { - get: function( elem, computed ) { - // IE uses filters for opacity - return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ? - ( 0.01 * parseFloat( RegExp.$1 ) ) + "" : - computed ? "1" : ""; - }, - - set: function( elem, value ) { - var style = elem.style, - currentStyle = elem.currentStyle, - opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "", - filter = currentStyle && currentStyle.filter || style.filter || ""; - - // IE has trouble with opacity if it does not have layout - // Force it by setting the zoom level - style.zoom = 1; - - // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652 - if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" && - style.removeAttribute ) { - - // Setting style.filter to null, "" & " " still leave "filter:" in the cssText - // if "filter:" is present at all, clearType is disabled, we want to avoid this - // style.removeAttribute is IE Only, but so apparently is this code path... - style.removeAttribute( "filter" ); - - // if there there is no filter style applied in a css rule, we are done - if ( currentStyle && !currentStyle.filter ) { - return; - } - } - - // otherwise, set new filter values - style.filter = ralpha.test( filter ) ? - filter.replace( ralpha, opacity ) : - filter + " " + opacity; - } - }; -} - -// These hooks cannot be added until DOM ready because the support test -// for it is not run until after DOM ready -jQuery(function() { - if ( !jQuery.support.reliableMarginRight ) { - jQuery.cssHooks.marginRight = { - get: function( elem, computed ) { - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - // Work around by temporarily setting element display to inline-block - return jQuery.swap( elem, { "display": "inline-block" }, function() { - if ( computed ) { - return curCSS( elem, "marginRight" ); - } - }); - } - }; - } - - // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 - // getComputedStyle returns percent when specified for top/left/bottom/right - // rather than make the css module depend on the offset module, we just check for it here - if ( !jQuery.support.pixelPosition && jQuery.fn.position ) { - jQuery.each( [ "top", "left" ], function( i, prop ) { - jQuery.cssHooks[ prop ] = { - get: function( elem, computed ) { - if ( computed ) { - var ret = curCSS( elem, prop ); - // if curCSS returns percentage, fallback to offset - return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + "px" : ret; - } - } - }; - }); - } - -}); - -if ( jQuery.expr && jQuery.expr.filters ) { - jQuery.expr.filters.hidden = function( elem ) { - return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none"); - }; - - jQuery.expr.filters.visible = function( elem ) { - return !jQuery.expr.filters.hidden( elem ); - }; -} - -// These hooks are used by animate to expand properties -jQuery.each({ - margin: "", - padding: "", - border: "Width" -}, function( prefix, suffix ) { - jQuery.cssHooks[ prefix + suffix ] = { - expand: function( value ) { - var i, - - // assumes a single number if not a string - parts = typeof value === "string" ? value.split(" ") : [ value ], - expanded = {}; - - for ( i = 0; i < 4; i++ ) { - expanded[ prefix + cssExpand[ i ] + suffix ] = - parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; - } - - return expanded; - } - }; - - if ( !rmargin.test( prefix ) ) { - jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; - } -}); -var r20 = /%20/g, - rbracket = /\[\]$/, - rCRLF = /\r?\n/g, - rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, - rselectTextarea = /^(?:select|textarea)/i; - -jQuery.fn.extend({ - serialize: function() { - return jQuery.param( this.serializeArray() ); - }, - serializeArray: function() { - return this.map(function(){ - return this.elements ? jQuery.makeArray( this.elements ) : this; - }) - .filter(function(){ - return this.name && !this.disabled && - ( this.checked || rselectTextarea.test( this.nodeName ) || - rinput.test( this.type ) ); - }) - .map(function( i, elem ){ - var val = jQuery( this ).val(); - - return val == null ? - null : - jQuery.isArray( val ) ? - jQuery.map( val, function( val, i ){ - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - }) : - { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - }).get(); - } -}); - -//Serialize an array of form elements or a set of -//key/values into a query string -jQuery.param = function( a, traditional ) { - var prefix, - s = [], - add = function( key, value ) { - // If value is a function, invoke it and return its value - value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); - s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); - }; - - // Set traditional to true for jQuery <= 1.3.2 behavior. - if ( traditional === undefined ) { - traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; - } - - // If an array was passed in, assume that it is an array of form elements. - if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { - // Serialize the form elements - jQuery.each( a, function() { - add( this.name, this.value ); - }); - - } else { - // If traditional, encode the "old" way (the way 1.3.2 or older - // did it), otherwise encode params recursively. - for ( prefix in a ) { - buildParams( prefix, a[ prefix ], traditional, add ); - } - } - - // Return the resulting serialization - return s.join( "&" ).replace( r20, "+" ); -}; - -function buildParams( prefix, obj, traditional, add ) { - var name; - - if ( jQuery.isArray( obj ) ) { - // Serialize array item. - jQuery.each( obj, function( i, v ) { - if ( traditional || rbracket.test( prefix ) ) { - // Treat each array item as a scalar. - add( prefix, v ); - - } else { - // If array item is non-scalar (array or object), encode its - // numeric index to resolve deserialization ambiguity issues. - // Note that rack (as of 1.0.0) can't currently deserialize - // nested arrays properly, and attempting to do so may cause - // a server error. Possible fixes are to modify rack's - // deserialization algorithm or to provide an option or flag - // to force array serialization to be shallow. - buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); - } - }); - - } else if ( !traditional && jQuery.type( obj ) === "object" ) { - // Serialize object item. - for ( name in obj ) { - buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); - } - - } else { - // Serialize scalar item. - add( prefix, obj ); - } -} -var - // Document location - ajaxLocParts, - ajaxLocation, - - rhash = /#.*$/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - rquery = /\?/, - rscript = /)<[^<]*)*<\/script>/gi, - rts = /([?&])_=[^&]*/, - rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/, - - // Keep a copy of the old load method - _load = jQuery.fn.load, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = ["*/"] + ["*"]; - -// #8138, IE may throw an exception when accessing -// a field from window.location if document.domain has been set -try { - ajaxLocation = location.href; -} catch( e ) { - // Use the href attribute of an A element - // since IE will modify it given document.location - ajaxLocation = document.createElement( "a" ); - ajaxLocation.href = ""; - ajaxLocation = ajaxLocation.href; -} - -// Segment location into parts -ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; - -// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport -function addToPrefiltersOrTransports( structure ) { - - // dataTypeExpression is optional and defaults to "*" - return function( dataTypeExpression, func ) { - - if ( typeof dataTypeExpression !== "string" ) { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, list, placeBefore, - dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ), - i = 0, - length = dataTypes.length; - - if ( jQuery.isFunction( func ) ) { - // For each dataType in the dataTypeExpression - for ( ; i < length; i++ ) { - dataType = dataTypes[ i ]; - // We control if we're asked to add before - // any existing element - placeBefore = /^\+/.test( dataType ); - if ( placeBefore ) { - dataType = dataType.substr( 1 ) || "*"; - } - list = structure[ dataType ] = structure[ dataType ] || []; - // then we add to the structure accordingly - list[ placeBefore ? "unshift" : "push" ]( func ); - } - } - }; -} - -// Base inspection function for prefilters and transports -function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR, - dataType /* internal */, inspected /* internal */ ) { - - dataType = dataType || options.dataTypes[ 0 ]; - inspected = inspected || {}; - - inspected[ dataType ] = true; - - var selection, - list = structure[ dataType ], - i = 0, - length = list ? list.length : 0, - executeOnly = ( structure === prefilters ); - - for ( ; i < length && ( executeOnly || !selection ); i++ ) { - selection = list[ i ]( options, originalOptions, jqXHR ); - // If we got redirected to another dataType - // we try there if executing only and not done already - if ( typeof selection === "string" ) { - if ( !executeOnly || inspected[ selection ] ) { - selection = undefined; - } else { - options.dataTypes.unshift( selection ); - selection = inspectPrefiltersOrTransports( - structure, options, originalOptions, jqXHR, selection, inspected ); - } - } - } - // If we're only executing or nothing was selected - // we try the catchall dataType if not done already - if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) { - selection = inspectPrefiltersOrTransports( - structure, options, originalOptions, jqXHR, "*", inspected ); - } - // unnecessary when only executing (prefilters) - // but it'll be ignored by the caller in that case - return selection; -} - -// A special extend for ajax options -// that takes "flat" options (not to be deep extended) -// Fixes #9887 -function ajaxExtend( target, src ) { - var key, deep, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - for ( key in src ) { - if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; - } - } - if ( deep ) { - jQuery.extend( true, target, deep ); - } -} - -jQuery.fn.load = function( url, params, callback ) { - if ( typeof url !== "string" && _load ) { - return _load.apply( this, arguments ); - } - - // Don't do a request if no elements are being requested - if ( !this.length ) { - return this; - } - - var selector, type, response, - self = this, - off = url.indexOf(" "); - - if ( off >= 0 ) { - selector = url.slice( off, url.length ); - url = url.slice( 0, off ); - } - - // If it's a function - if ( jQuery.isFunction( params ) ) { - - // We assume that it's the callback - callback = params; - params = undefined; - - // Otherwise, build a param string - } else if ( params && typeof params === "object" ) { - type = "POST"; - } - - // Request the remote document - jQuery.ajax({ - url: url, - - // if "type" variable is undefined, then "GET" method will be used - type: type, - dataType: "html", - data: params, - complete: function( jqXHR, status ) { - if ( callback ) { - self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); - } - } - }).done(function( responseText ) { - - // Save response for use in complete callback - response = arguments; - - // See if a selector was specified - self.html( selector ? - - // Create a dummy div to hold the results - jQuery("
") - - // inject the contents of the document in, removing the scripts - // to avoid any 'Permission Denied' errors in IE - .append( responseText.replace( rscript, "" ) ) - - // Locate the specified elements - .find( selector ) : - - // If not, just inject the full result - responseText ); - - }); - - return this; -}; - -// Attach a bunch of functions for handling common AJAX events -jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){ - jQuery.fn[ o ] = function( f ){ - return this.on( o, f ); - }; -}); - -jQuery.each( [ "get", "post" ], function( i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - // shift arguments if data argument was omitted - if ( jQuery.isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - return jQuery.ajax({ - type: method, - url: url, - data: data, - success: callback, - dataType: type - }); - }; -}); - -jQuery.extend({ - - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - if ( settings ) { - // Building a settings object - ajaxExtend( target, jQuery.ajaxSettings ); - } else { - // Extending ajaxSettings - settings = target; - target = jQuery.ajaxSettings; - } - ajaxExtend( target, settings ); - return target; - }, - - ajaxSettings: { - url: ajaxLocation, - isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), - global: true, - type: "GET", - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - processData: true, - async: true, - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - xml: "application/xml, text/xml", - html: "text/html", - text: "text/plain", - json: "application/json, text/javascript", - "*": allTypes - }, - - contents: { - xml: /xml/, - html: /html/, - json: /json/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText" - }, - - // List of data converters - // 1) key format is "source_type destination_type" (a single space in-between) - // 2) the catchall symbol "*" can be used for source_type - converters: { - - // Convert anything to text - "* text": window.String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": jQuery.parseJSON, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - context: true, - url: true - } - }, - - ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), - ajaxTransport: addToPrefiltersOrTransports( transports ), - - // Main method - ajax: function( url, options ) { - - // If url is an object, simulate pre-1.5 signature - if ( typeof url === "object" ) { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var // ifModified key - ifModifiedKey, - // Response headers - responseHeadersString, - responseHeaders, - // transport - transport, - // timeout handle - timeoutTimer, - // Cross-domain detection vars - parts, - // To know if global events are to be dispatched - fireGlobals, - // Loop variable - i, - // Create the final options object - s = jQuery.ajaxSetup( {}, options ), - // Callbacks context - callbackContext = s.context || s, - // Context for global events - // It's the callbackContext if one was provided in the options - // and if it's a DOM node or a jQuery collection - globalEventContext = callbackContext !== s && - ( callbackContext.nodeType || callbackContext instanceof jQuery ) ? - jQuery( callbackContext ) : jQuery.event, - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks( "once memory" ), - // Status-dependent callbacks - statusCode = s.statusCode || {}, - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - // The jqXHR state - state = 0, - // Default abort message - strAbort = "canceled", - // Fake xhr - jqXHR = { - - readyState: 0, - - // Caches the header - setRequestHeader: function( name, value ) { - if ( !state ) { - var lname = name.toLowerCase(); - name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Raw string - getAllResponseHeaders: function() { - return state === 2 ? responseHeadersString : null; - }, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( state === 2 ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while( ( match = rheaders.exec( responseHeadersString ) ) ) { - responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; - } - } - match = responseHeaders[ key.toLowerCase() ]; - } - return match === undefined ? null : match; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( !state ) { - s.mimeType = type; - } - return this; - }, - - // Cancel the request - abort: function( statusText ) { - statusText = statusText || strAbort; - if ( transport ) { - transport.abort( statusText ); - } - done( 0, statusText ); - return this; - } - }; - - // Callback for when everything is done - // It is defined here because jslint complains if it is declared - // at the end of the function (which would be more logical and readable) - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Called once - if ( state === 2 ) { - return; - } - - // State is "done" now - state = 2; - - // Clear timeout if it exists - if ( timeoutTimer ) { - clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // If successful, handle type chaining - if ( status >= 200 && status < 300 || status === 304 ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - - modified = jqXHR.getResponseHeader("Last-Modified"); - if ( modified ) { - jQuery.lastModified[ ifModifiedKey ] = modified; - } - modified = jqXHR.getResponseHeader("Etag"); - if ( modified ) { - jQuery.etag[ ifModifiedKey ] = modified; - } - } - - // If not modified - if ( status === 304 ) { - - statusText = "notmodified"; - isSuccess = true; - - // If we have data - } else { - - isSuccess = ajaxConvert( s, response ); - statusText = isSuccess.state; - success = isSuccess.data; - error = isSuccess.error; - isSuccess = !error; - } - } else { - // We extract error from statusText - // then normalize statusText and status for non-aborts - error = statusText; - if ( !statusText || status ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger( "ajaxStop" ); - } - } - } - - // Attach deferreds - deferred.promise( jqXHR ); - jqXHR.success = jqXHR.done; - jqXHR.error = jqXHR.fail; - jqXHR.complete = completeDeferred.add; - - // Status-dependent callbacks - jqXHR.statusCode = function( map ) { - if ( map ) { - var tmp; - if ( state < 2 ) { - for ( tmp in map ) { - statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; - } - } else { - tmp = map[ jqXHR.status ]; - jqXHR.always( tmp ); - } - } - return this; - }; - - // Remove hash character (#7531: and string promotion) - // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) - // We also use the url parameter if available - s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); - - // Extract dataTypes list - s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace ); - - // A cross-domain request is in order when we have a protocol:host:port mismatch - if ( s.crossDomain == null ) { - parts = rurl.exec( s.url.toLowerCase() ) || false; - s.crossDomain = parts && ( parts.join(":") + ( parts[ 3 ] ? "" : parts[ 1 ] === "http:" ? 80 : 443 ) ) !== - ( ajaxLocParts.join(":") + ( ajaxLocParts[ 3 ] ? "" : ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ); - } - - // Convert data if not already a string - if ( s.data && s.processData && typeof s.data !== "string" ) { - s.data = jQuery.param( s.data, s.traditional ); - } - - // Apply prefilters - inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); - - // If request was aborted inside a prefilter, stop there - if ( state === 2 ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - fireGlobals = s.global; - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test( s.type ); - - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger( "ajaxStart" ); - } - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // If data is available, append data to url - if ( s.data ) { - s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Get ifModifiedKey before adding the anti-cache parameter - ifModifiedKey = s.url; - - // Add anti-cache in url if needed - if ( s.cache === false ) { - - var ts = jQuery.now(), - // try replacing _= if it is there - ret = s.url.replace( rts, "$1_=" + ts ); - - // if nothing was replaced, add timestamp to the end - s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); - } - } - - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - ifModifiedKey = ifModifiedKey || s.url; - if ( jQuery.lastModified[ ifModifiedKey ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] ); - } - if ( jQuery.etag[ ifModifiedKey ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] ); - } - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? - s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : - s.accepts[ "*" ] - ); - - // Check for headers option - for ( i in s.headers ) { - jqXHR.setRequestHeader( i, s.headers[ i ] ); - } - - // Allow custom headers/mimetypes and early abort - if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { - // Abort if not done already and return - return jqXHR.abort(); - - } - - // aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - for ( i in { success: 1, error: 1, complete: 1 } ) { - jqXHR[ i ]( s[ i ] ); - } - - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - jqXHR.readyState = 1; - // Send global event - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = setTimeout( function(){ - jqXHR.abort( "timeout" ); - }, s.timeout ); - } - - try { - state = 1; - transport.send( requestHeaders, done ); - } catch (e) { - // Propagate exception as error if not done - if ( state < 2 ) { - done( -1, e ); - // Simply rethrow otherwise - } else { - throw e; - } - } - } - - return jqXHR; - }, - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {} - -}); - -/* Handles responses to an ajax request: - * - sets all responseXXX fields accordingly - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ -function ajaxHandleResponses( s, jqXHR, responses ) { - - var ct, type, finalDataType, firstDataType, - contents = s.contents, - dataTypes = s.dataTypes, - responseFields = s.responseFields; - - // Fill responseXXX fields - for ( type in responseFields ) { - if ( type in responses ) { - jqXHR[ responseFields[type] ] = responses[ type ]; - } - } - - // Remove auto dataType and get content-type in the process - while( dataTypes[ 0 ] === "*" ) { - dataTypes.shift(); - if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader( "content-type" ); - } - } - - // Check if we're dealing with a known content-type - if ( ct ) { - for ( type in contents ) { - if ( contents[ type ] && contents[ type ].test( ct ) ) { - dataTypes.unshift( type ); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if ( dataTypes[ 0 ] in responses ) { - finalDataType = dataTypes[ 0 ]; - } else { - // Try convertible dataTypes - for ( type in responses ) { - if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { - finalDataType = type; - break; - } - if ( !firstDataType ) { - firstDataType = type; - } - } - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if ( finalDataType ) { - if ( finalDataType !== dataTypes[ 0 ] ) { - dataTypes.unshift( finalDataType ); - } - return responses[ finalDataType ]; - } -} - -// Chain conversions given the request and the original response -function ajaxConvert( s, response ) { - - var conv, conv2, current, tmp, - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(), - prev = dataTypes[ 0 ], - converters = {}, - i = 0; - - // Apply the dataFilter if provided - if ( s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } - - // Create converters map with lowercased keys - if ( dataTypes[ 1 ] ) { - for ( conv in s.converters ) { - converters[ conv.toLowerCase() ] = s.converters[ conv ]; - } - } - - // Convert to each sequential dataType, tolerating list modification - for ( ; (current = dataTypes[++i]); ) { - - // There's only work to do if current dataType is non-auto - if ( current !== "*" ) { - - // Convert response if prev dataType is non-auto and differs from current - if ( prev !== "*" && prev !== current ) { - - // Seek a direct converter - conv = converters[ prev + " " + current ] || converters[ "* " + current ]; - - // If none found, seek a pair - if ( !conv ) { - for ( conv2 in converters ) { - - // If conv2 outputs current - tmp = conv2.split(" "); - if ( tmp[ 1 ] === current ) { - - // If prev can be converted to accepted input - conv = converters[ prev + " " + tmp[ 0 ] ] || - converters[ "* " + tmp[ 0 ] ]; - if ( conv ) { - // Condense equivalence converters - if ( conv === true ) { - conv = converters[ conv2 ]; - - // Otherwise, insert the intermediate dataType - } else if ( converters[ conv2 ] !== true ) { - current = tmp[ 0 ]; - dataTypes.splice( i--, 0, current ); - } - - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if ( conv !== true ) { - - // Unless errors are allowed to bubble, catch and return them - if ( conv && s["throws"] ) { - response = conv( response ); - } else { - try { - response = conv( response ); - } catch ( e ) { - return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; - } - } - } - } - - // Update prev for next iteration - prev = current; - } - } - - return { state: "success", data: response }; -} -var oldCallbacks = [], - rquestion = /\?/, - rjsonp = /(=)\?(?=&|$)|\?\?/, - nonce = jQuery.now(); - -// Default jsonp settings -jQuery.ajaxSetup({ - jsonp: "callback", - jsonpCallback: function() { - var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); - this[ callback ] = true; - return callback; - } -}); - -// Detect, normalize options and install callbacks for jsonp requests -jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { - - var callbackName, overwritten, responseContainer, - data = s.data, - url = s.url, - hasCallback = s.jsonp !== false, - replaceInUrl = hasCallback && rjsonp.test( url ), - replaceInData = hasCallback && !replaceInUrl && typeof data === "string" && - !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && - rjsonp.test( data ); - - // Handle iff the expected data type is "jsonp" or we have a parameter to set - if ( s.dataTypes[ 0 ] === "jsonp" || replaceInUrl || replaceInData ) { - - // Get callback name, remembering preexisting value associated with it - callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? - s.jsonpCallback() : - s.jsonpCallback; - overwritten = window[ callbackName ]; - - // Insert callback into url or form data - if ( replaceInUrl ) { - s.url = url.replace( rjsonp, "$1" + callbackName ); - } else if ( replaceInData ) { - s.data = data.replace( rjsonp, "$1" + callbackName ); - } else if ( hasCallback ) { - s.url += ( rquestion.test( url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; - } - - // Use data converter to retrieve json after script execution - s.converters["script json"] = function() { - if ( !responseContainer ) { - jQuery.error( callbackName + " was not called" ); - } - return responseContainer[ 0 ]; - }; - - // force json dataType - s.dataTypes[ 0 ] = "json"; - - // Install callback - window[ callbackName ] = function() { - responseContainer = arguments; - }; - - // Clean-up function (fires after converters) - jqXHR.always(function() { - // Restore preexisting value - window[ callbackName ] = overwritten; - - // Save back as free - if ( s[ callbackName ] ) { - // make sure that re-using the options doesn't screw things around - s.jsonpCallback = originalSettings.jsonpCallback; - - // save the callback name for future use - oldCallbacks.push( callbackName ); - } - - // Call if it was a function and we have a response - if ( responseContainer && jQuery.isFunction( overwritten ) ) { - overwritten( responseContainer[ 0 ] ); - } - - responseContainer = overwritten = undefined; - }); - - // Delegate to script - return "script"; - } -}); -// Install script dataType -jQuery.ajaxSetup({ - accepts: { - script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /javascript|ecmascript/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } -}); - -// Handle cache's special case and global -jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - s.global = false; - } -}); - -// Bind script tag hack transport -jQuery.ajaxTransport( "script", function(s) { - - // This transport only deals with cross domain requests - if ( s.crossDomain ) { - - var script, - head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement; - - return { - - send: function( _, callback ) { - - script = document.createElement( "script" ); - - script.async = "async"; - - if ( s.scriptCharset ) { - script.charset = s.scriptCharset; - } - - script.src = s.url; - - // Attach handlers for all browsers - script.onload = script.onreadystatechange = function( _, isAbort ) { - - if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { - - // Handle memory leak in IE - script.onload = script.onreadystatechange = null; - - // Remove the script - if ( head && script.parentNode ) { - head.removeChild( script ); - } - - // Dereference the script - script = undefined; - - // Callback if not abort - if ( !isAbort ) { - callback( 200, "success" ); - } - } - }; - // Use insertBefore instead of appendChild to circumvent an IE6 bug. - // This arises when a base node is used (#2709 and #4378). - head.insertBefore( script, head.firstChild ); - }, - - abort: function() { - if ( script ) { - script.onload( 0, 1 ); - } - } - }; - } -}); -var xhrCallbacks, - // #5280: Internet Explorer will keep connections alive if we don't abort on unload - xhrOnUnloadAbort = window.ActiveXObject ? function() { - // Abort all pending requests - for ( var key in xhrCallbacks ) { - xhrCallbacks[ key ]( 0, 1 ); - } - } : false, - xhrId = 0; - -// Functions to create xhrs -function createStandardXHR() { - try { - return new window.XMLHttpRequest(); - } catch( e ) {} -} - -function createActiveXHR() { - try { - return new window.ActiveXObject( "Microsoft.XMLHTTP" ); - } catch( e ) {} -} - -// Create the request object -// (This is still attached to ajaxSettings for backward compatibility) -jQuery.ajaxSettings.xhr = window.ActiveXObject ? - /* Microsoft failed to properly - * implement the XMLHttpRequest in IE7 (can't request local files), - * so we use the ActiveXObject when it is available - * Additionally XMLHttpRequest can be disabled in IE7/IE8 so - * we need a fallback. - */ - function() { - return !this.isLocal && createStandardXHR() || createActiveXHR(); - } : - // For all other browsers, use the standard XMLHttpRequest object - createStandardXHR; - -// Determine support properties -(function( xhr ) { - jQuery.extend( jQuery.support, { - ajax: !!xhr, - cors: !!xhr && ( "withCredentials" in xhr ) - }); -})( jQuery.ajaxSettings.xhr() ); - -// Create transport if the browser can provide an xhr -if ( jQuery.support.ajax ) { - - jQuery.ajaxTransport(function( s ) { - // Cross domain only allowed if supported through XMLHttpRequest - if ( !s.crossDomain || jQuery.support.cors ) { - - var callback; - - return { - send: function( headers, complete ) { - - // Get a new xhr - var handle, i, - xhr = s.xhr(); - - // Open the socket - // Passing null username, generates a login popup on Opera (#2865) - if ( s.username ) { - xhr.open( s.type, s.url, s.async, s.username, s.password ); - } else { - xhr.open( s.type, s.url, s.async ); - } - - // Apply custom fields if provided - if ( s.xhrFields ) { - for ( i in s.xhrFields ) { - xhr[ i ] = s.xhrFields[ i ]; - } - } - - // Override mime type if needed - if ( s.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( s.mimeType ); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !s.crossDomain && !headers["X-Requested-With"] ) { - headers[ "X-Requested-With" ] = "XMLHttpRequest"; - } - - // Need an extra try/catch for cross domain requests in Firefox 3 - try { - for ( i in headers ) { - xhr.setRequestHeader( i, headers[ i ] ); - } - } catch( _ ) {} - - // Do send the request - // This may raise an exception which is actually - // handled in jQuery.ajax (so no try/catch here) - xhr.send( ( s.hasContent && s.data ) || null ); - - // Listener - callback = function( _, isAbort ) { - - var status, - statusText, - responseHeaders, - responses, - xml; - - // Firefox throws exceptions when accessing properties - // of an xhr when a network error occurred - // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE) - try { - - // Was never called and is aborted or complete - if ( callback && ( isAbort || xhr.readyState === 4 ) ) { - - // Only called once - callback = undefined; - - // Do not keep as active anymore - if ( handle ) { - xhr.onreadystatechange = jQuery.noop; - if ( xhrOnUnloadAbort ) { - delete xhrCallbacks[ handle ]; - } - } - - // If it's an abort - if ( isAbort ) { - // Abort it manually if needed - if ( xhr.readyState !== 4 ) { - xhr.abort(); - } - } else { - status = xhr.status; - responseHeaders = xhr.getAllResponseHeaders(); - responses = {}; - xml = xhr.responseXML; - - // Construct response list - if ( xml && xml.documentElement /* #4958 */ ) { - responses.xml = xml; - } - - // When requesting binary data, IE6-9 will throw an exception - // on any attempt to access responseText (#11426) - try { - responses.text = xhr.responseText; - } catch( _ ) { - } - - // Firefox throws an exception when accessing - // statusText for faulty cross-domain requests - try { - statusText = xhr.statusText; - } catch( e ) { - // We normalize with Webkit giving an empty statusText - statusText = ""; - } - - // Filter status for non standard behaviors - - // If the request is local and we have data: assume a success - // (success with no data won't get notified, that's the best we - // can do given current implementations) - if ( !status && s.isLocal && !s.crossDomain ) { - status = responses.text ? 200 : 404; - // IE - #1450: sometimes returns 1223 when it should be 204 - } else if ( status === 1223 ) { - status = 204; - } - } - } - } catch( firefoxAccessException ) { - if ( !isAbort ) { - complete( -1, firefoxAccessException ); - } - } - - // Call complete if needed - if ( responses ) { - complete( status, statusText, responses, responseHeaders ); - } - }; - - if ( !s.async ) { - // if we're in sync mode we fire the callback - callback(); - } else if ( xhr.readyState === 4 ) { - // (IE6 & IE7) if it's in cache and has been - // retrieved directly we need to fire the callback - setTimeout( callback, 0 ); - } else { - handle = ++xhrId; - if ( xhrOnUnloadAbort ) { - // Create the active xhrs callbacks list if needed - // and attach the unload handler - if ( !xhrCallbacks ) { - xhrCallbacks = {}; - jQuery( window ).unload( xhrOnUnloadAbort ); - } - // Add to list of active xhrs callbacks - xhrCallbacks[ handle ] = callback; - } - xhr.onreadystatechange = callback; - } - }, - - abort: function() { - if ( callback ) { - callback(0,1); - } - } - }; - } - }); -} -var fxNow, timerId, - rfxtypes = /^(?:toggle|show|hide)$/, - rfxnum = new RegExp( "^(?:([-+])=|)(" + core_pnum + ")([a-z%]*)$", "i" ), - rrun = /queueHooks$/, - animationPrefilters = [ defaultPrefilter ], - tweeners = { - "*": [function( prop, value ) { - var end, unit, - tween = this.createTween( prop, value ), - parts = rfxnum.exec( value ), - target = tween.cur(), - start = +target || 0, - scale = 1, - maxIterations = 20; - - if ( parts ) { - end = +parts[2]; - unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - - // We need to compute starting value - if ( unit !== "px" && start ) { - // Iteratively approximate from a nonzero starting point - // Prefer the current property, because this process will be trivial if it uses the same units - // Fallback to end or a simple constant - start = jQuery.css( tween.elem, prop, true ) || end || 1; - - do { - // If previous iteration zeroed out, double until we get *something* - // Use a string for doubling factor so we don't accidentally see scale as unchanged below - scale = scale || ".5"; - - // Adjust and apply - start = start / scale; - jQuery.style( tween.elem, prop, start + unit ); - - // Update scale, tolerating zero or NaN from tween.cur() - // And breaking the loop if scale is unchanged or perfect, or if we've just had enough - } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); - } - - tween.unit = unit; - tween.start = start; - // If a +=/-= token was provided, we're doing a relative animation - tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end; - } - return tween; - }] - }; - -// Animations created synchronously will run synchronously -function createFxNow() { - setTimeout(function() { - fxNow = undefined; - }, 0 ); - return ( fxNow = jQuery.now() ); -} - -function createTweens( animation, props ) { - jQuery.each( props, function( prop, value ) { - var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( collection[ index ].call( animation, prop, value ) ) { - - // we're done with this property - return; - } - } - }); -} - -function Animation( elem, properties, options ) { - var result, - index = 0, - tweenerIndex = 0, - length = animationPrefilters.length, - deferred = jQuery.Deferred().always( function() { - // don't match elem in the :animated selector - delete tick.elem; - }), - tick = function() { - var currentTime = fxNow || createFxNow(), - remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - percent = 1 - ( remaining / animation.duration || 0 ), - index = 0, - length = animation.tweens.length; - - for ( ; index < length ; index++ ) { - animation.tweens[ index ].run( percent ); - } - - deferred.notifyWith( elem, [ animation, percent, remaining ]); - - if ( percent < 1 && length ) { - return remaining; - } else { - deferred.resolveWith( elem, [ animation ] ); - return false; - } - }, - animation = deferred.promise({ - elem: elem, - props: jQuery.extend( {}, properties ), - opts: jQuery.extend( true, { specialEasing: {} }, options ), - originalProperties: properties, - originalOptions: options, - startTime: fxNow || createFxNow(), - duration: options.duration, - tweens: [], - createTween: function( prop, end, easing ) { - var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); - animation.tweens.push( tween ); - return tween; - }, - stop: function( gotoEnd ) { - var index = 0, - // if we are going to the end, we want to run all the tweens - // otherwise we skip this part - length = gotoEnd ? animation.tweens.length : 0; - - for ( ; index < length ; index++ ) { - animation.tweens[ index ].run( 1 ); - } - - // resolve when we played the last frame - // otherwise, reject - if ( gotoEnd ) { - deferred.resolveWith( elem, [ animation, gotoEnd ] ); - } else { - deferred.rejectWith( elem, [ animation, gotoEnd ] ); - } - return this; - } - }), - props = animation.props; - - propFilter( props, animation.opts.specialEasing ); - - for ( ; index < length ; index++ ) { - result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); - if ( result ) { - return result; - } - } - - createTweens( animation, props ); - - if ( jQuery.isFunction( animation.opts.start ) ) { - animation.opts.start.call( elem, animation ); - } - - jQuery.fx.timer( - jQuery.extend( tick, { - anim: animation, - queue: animation.opts.queue, - elem: elem - }) - ); - - // attach callbacks from options - return animation.progress( animation.opts.progress ) - .done( animation.opts.done, animation.opts.complete ) - .fail( animation.opts.fail ) - .always( animation.opts.always ); -} - -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = jQuery.camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( jQuery.isArray( value ) ) { - easing = value[ 1 ]; - value = props[ index ] = value[ 0 ]; - } - - if ( index !== name ) { - props[ name ] = value; - delete props[ index ]; - } - - hooks = jQuery.cssHooks[ name ]; - if ( hooks && "expand" in hooks ) { - value = hooks.expand( value ); - delete props[ name ]; - - // not quite $.extend, this wont overwrite keys already present. - // also - reusing 'index' from above because we have the correct "name" - for ( index in value ) { - if ( !( index in props ) ) { - props[ index ] = value[ index ]; - specialEasing[ index ] = easing; - } - } - } else { - specialEasing[ name ] = easing; - } - } -} - -jQuery.Animation = jQuery.extend( Animation, { - - tweener: function( props, callback ) { - if ( jQuery.isFunction( props ) ) { - callback = props; - props = [ "*" ]; - } else { - props = props.split(" "); - } - - var prop, - index = 0, - length = props.length; - - for ( ; index < length ; index++ ) { - prop = props[ index ]; - tweeners[ prop ] = tweeners[ prop ] || []; - tweeners[ prop ].unshift( callback ); - } - }, - - prefilter: function( callback, prepend ) { - if ( prepend ) { - animationPrefilters.unshift( callback ); - } else { - animationPrefilters.push( callback ); - } - } -}); - -function defaultPrefilter( elem, props, opts ) { - var index, prop, value, length, dataShow, tween, hooks, oldfire, - anim = this, - style = elem.style, - orig = {}, - handled = [], - hidden = elem.nodeType && isHidden( elem ); - - // handle queue: false promises - if ( !opts.queue ) { - hooks = jQuery._queueHooks( elem, "fx" ); - if ( hooks.unqueued == null ) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function() { - if ( !hooks.unqueued ) { - oldfire(); - } - }; - } - hooks.unqueued++; - - anim.always(function() { - // doing this makes sure that the complete handler will be called - // before this completes - anim.always(function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - }); - }); - } - - // height/width overflow pass - if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { - // Make sure that nothing sneaks out - // Record all 3 overflow attributes because IE does not - // change the overflow attribute when overflowX and - // overflowY are set to the same value - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - - // Set display property to inline-block for height/width - // animations on inline elements that are having width/height animated - if ( jQuery.css( elem, "display" ) === "inline" && - jQuery.css( elem, "float" ) === "none" ) { - - // inline-level elements accept inline-block; - // block-level elements need to be inline with layout - if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) { - style.display = "inline-block"; - - } else { - style.zoom = 1; - } - } - } - - if ( opts.overflow ) { - style.overflow = "hidden"; - if ( !jQuery.support.shrinkWrapBlocks ) { - anim.done(function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - }); - } - } - - - // show/hide pass - for ( index in props ) { - value = props[ index ]; - if ( rfxtypes.exec( value ) ) { - delete props[ index ]; - if ( value === ( hidden ? "hide" : "show" ) ) { - continue; - } - handled.push( index ); - } - } - - length = handled.length; - if ( length ) { - dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} ); - if ( hidden ) { - jQuery( elem ).show(); - } else { - anim.done(function() { - jQuery( elem ).hide(); - }); - } - anim.done(function() { - var prop; - jQuery.removeData( elem, "fxshow", true ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - }); - for ( index = 0 ; index < length ; index++ ) { - prop = handled[ index ]; - tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 ); - orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop ); - - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = tween.start; - if ( hidden ) { - tween.end = tween.start; - tween.start = prop === "width" || prop === "height" ? 1 : 0; - } - } - } - } -} - -function Tween( elem, options, prop, end, easing ) { - return new Tween.prototype.init( elem, options, prop, end, easing ); -} -jQuery.Tween = Tween; - -Tween.prototype = { - constructor: Tween, - init: function( elem, options, prop, end, easing, unit ) { - this.elem = elem; - this.prop = prop; - this.easing = easing || "swing"; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - }, - cur: function() { - var hooks = Tween.propHooks[ this.prop ]; - - return hooks && hooks.get ? - hooks.get( this ) : - Tween.propHooks._default.get( this ); - }, - run: function( percent ) { - var eased, - hooks = Tween.propHooks[ this.prop ]; - - if ( this.options.duration ) { - this.pos = eased = jQuery.easing[ this.easing ]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = ( this.end - this.start ) * eased + this.start; - - if ( this.options.step ) { - this.options.step.call( this.elem, this.now, this ); - } - - if ( hooks && hooks.set ) { - hooks.set( this ); - } else { - Tween.propHooks._default.set( this ); - } - return this; - } -}; - -Tween.prototype.init.prototype = Tween.prototype; - -Tween.propHooks = { - _default: { - get: function( tween ) { - var result; - - if ( tween.elem[ tween.prop ] != null && - (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { - return tween.elem[ tween.prop ]; - } - - // passing any value as a 4th parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails - // so, simple values such as "10px" are parsed to Float. - // complex values such as "rotate(1rad)" are returned as is. - result = jQuery.css( tween.elem, tween.prop, false, "" ); - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function( tween ) { - // use step hook for back compat - use cssHook if its there - use .style if its - // available and use plain properties where available - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; - -// Remove in 2.0 - this supports IE8's panic based approach -// to setting things on disconnected nodes - -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; - -jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { - var cssFn = jQuery.fn[ name ]; - jQuery.fn[ name ] = function( speed, easing, callback ) { - return speed == null || typeof speed === "boolean" || - // special check for .toggle( handler, handler, ... ) - ( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ? - cssFn.apply( this, arguments ) : - this.animate( genFx( name, true ), speed, easing, callback ); - }; -}); - -jQuery.fn.extend({ - fadeTo: function( speed, to, easing, callback ) { - - // show any hidden elements after setting opacity to 0 - return this.filter( isHidden ).css( "opacity", 0 ).show() - - // animate to the value specified - .end().animate({ opacity: to }, speed, easing, callback ); - }, - animate: function( prop, speed, easing, callback ) { - var empty = jQuery.isEmptyObject( prop ), - optall = jQuery.speed( speed, easing, callback ), - doAnimation = function() { - // Operate on a copy of prop so per-property easing won't be lost - var anim = Animation( this, jQuery.extend( {}, prop ), optall ); - - // Empty animations resolve immediately - if ( empty ) { - anim.stop( true ); - } - }; - - return empty || optall.queue === false ? - this.each( doAnimation ) : - this.queue( optall.queue, doAnimation ); - }, - stop: function( type, clearQueue, gotoEnd ) { - var stopQueue = function( hooks ) { - var stop = hooks.stop; - delete hooks.stop; - stop( gotoEnd ); - }; - - if ( typeof type !== "string" ) { - gotoEnd = clearQueue; - clearQueue = type; - type = undefined; - } - if ( clearQueue && type !== false ) { - this.queue( type || "fx", [] ); - } - - return this.each(function() { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = jQuery._data( this ); - - if ( index ) { - if ( data[ index ] && data[ index ].stop ) { - stopQueue( data[ index ] ); - } - } else { - for ( index in data ) { - if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { - stopQueue( data[ index ] ); - } - } - } - - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { - timers[ index ].anim.stop( gotoEnd ); - dequeue = false; - timers.splice( index, 1 ); - } - } - - // start the next in the queue if the last step wasn't forced - // timers currently will call their complete callbacks, which will dequeue - // but only if they were gotoEnd - if ( dequeue || !gotoEnd ) { - jQuery.dequeue( this, type ); - } - }); - } -}); - -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - attrs = { height: type }, - i = 0; - - // if we include width, step value is 1 to do all cssExpand values, - // if we don't include width, step value is 2 to skip over Left and Right - includeWidth = includeWidth? 1 : 0; - for( ; i < 4 ; i += 2 - includeWidth ) { - which = cssExpand[ i ]; - attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; - } - - if ( includeWidth ) { - attrs.opacity = attrs.width = type; - } - - return attrs; -} - -// Generate shortcuts for custom animations -jQuery.each({ - slideDown: genFx("show"), - slideUp: genFx("hide"), - slideToggle: genFx("toggle"), - fadeIn: { opacity: "show" }, - fadeOut: { opacity: "hide" }, - fadeToggle: { opacity: "toggle" } -}, function( name, props ) { - jQuery.fn[ name ] = function( speed, easing, callback ) { - return this.animate( props, speed, easing, callback ); - }; -}); - -jQuery.speed = function( speed, easing, fn ) { - var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { - complete: fn || !fn && easing || - jQuery.isFunction( speed ) && speed, - duration: speed, - easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing - }; - - opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : - opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; - - // normalize opt.queue - true/undefined/null -> "fx" - if ( opt.queue == null || opt.queue === true ) { - opt.queue = "fx"; - } - - // Queueing - opt.old = opt.complete; - - opt.complete = function() { - if ( jQuery.isFunction( opt.old ) ) { - opt.old.call( this ); - } - - if ( opt.queue ) { - jQuery.dequeue( this, opt.queue ); - } - }; - - return opt; -}; - -jQuery.easing = { - linear: function( p ) { - return p; - }, - swing: function( p ) { - return 0.5 - Math.cos( p*Math.PI ) / 2; - } -}; - -jQuery.timers = []; -jQuery.fx = Tween.prototype.init; -jQuery.fx.tick = function() { - var timer, - timers = jQuery.timers, - i = 0; - - for ( ; i < timers.length; i++ ) { - timer = timers[ i ]; - // Checks the timer has not already been removed - if ( !timer() && timers[ i ] === timer ) { - timers.splice( i--, 1 ); - } - } - - if ( !timers.length ) { - jQuery.fx.stop(); - } -}; - -jQuery.fx.timer = function( timer ) { - if ( timer() && jQuery.timers.push( timer ) && !timerId ) { - timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); - } -}; - -jQuery.fx.interval = 13; - -jQuery.fx.stop = function() { - clearInterval( timerId ); - timerId = null; -}; - -jQuery.fx.speeds = { - slow: 600, - fast: 200, - // Default speed - _default: 400 -}; - -// Back Compat <1.8 extension point -jQuery.fx.step = {}; - -if ( jQuery.expr && jQuery.expr.filters ) { - jQuery.expr.filters.animated = function( elem ) { - return jQuery.grep(jQuery.timers, function( fn ) { - return elem === fn.elem; - }).length; - }; -} -var rroot = /^(?:body|html)$/i; - -jQuery.fn.offset = function( options ) { - if ( arguments.length ) { - return options === undefined ? - this : - this.each(function( i ) { - jQuery.offset.setOffset( this, options, i ); - }); - } - - var docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft, - box = { top: 0, left: 0 }, - elem = this[ 0 ], - doc = elem && elem.ownerDocument; - - if ( !doc ) { - return; - } - - if ( (body = doc.body) === elem ) { - return jQuery.offset.bodyOffset( elem ); - } - - docElem = doc.documentElement; - - // Make sure it's not a disconnected DOM node - if ( !jQuery.contains( docElem, elem ) ) { - return box; - } - - // If we don't have gBCR, just use 0,0 rather than error - // BlackBerry 5, iOS 3 (original iPhone) - if ( typeof elem.getBoundingClientRect !== "undefined" ) { - box = elem.getBoundingClientRect(); - } - win = getWindow( doc ); - clientTop = docElem.clientTop || body.clientTop || 0; - clientLeft = docElem.clientLeft || body.clientLeft || 0; - scrollTop = win.pageYOffset || docElem.scrollTop; - scrollLeft = win.pageXOffset || docElem.scrollLeft; - return { - top: box.top + scrollTop - clientTop, - left: box.left + scrollLeft - clientLeft - }; -}; - -jQuery.offset = { - - bodyOffset: function( body ) { - var top = body.offsetTop, - left = body.offsetLeft; - - if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) { - top += parseFloat( jQuery.css(body, "marginTop") ) || 0; - left += parseFloat( jQuery.css(body, "marginLeft") ) || 0; - } - - return { top: top, left: left }; - }, - - setOffset: function( elem, options, i ) { - var position = jQuery.css( elem, "position" ); - - // set position first, in-case top/left are set even on static elem - if ( position === "static" ) { - elem.style.position = "relative"; - } - - var curElem = jQuery( elem ), - curOffset = curElem.offset(), - curCSSTop = jQuery.css( elem, "top" ), - curCSSLeft = jQuery.css( elem, "left" ), - calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1, - props = {}, curPosition = {}, curTop, curLeft; - - // need to be able to calculate position if either top or left is auto and position is either absolute or fixed - if ( calculatePosition ) { - curPosition = curElem.position(); - curTop = curPosition.top; - curLeft = curPosition.left; - } else { - curTop = parseFloat( curCSSTop ) || 0; - curLeft = parseFloat( curCSSLeft ) || 0; - } - - if ( jQuery.isFunction( options ) ) { - options = options.call( elem, i, curOffset ); - } - - if ( options.top != null ) { - props.top = ( options.top - curOffset.top ) + curTop; - } - if ( options.left != null ) { - props.left = ( options.left - curOffset.left ) + curLeft; - } - - if ( "using" in options ) { - options.using.call( elem, props ); - } else { - curElem.css( props ); - } - } -}; - - -jQuery.fn.extend({ - - position: function() { - if ( !this[0] ) { - return; - } - - var elem = this[0], - - // Get *real* offsetParent - offsetParent = this.offsetParent(), - - // Get correct offsets - offset = this.offset(), - parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); - - // Subtract element margins - // note: when an element has margin: auto the offsetLeft and marginLeft - // are the same in Safari causing offset.left to incorrectly be 0 - offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; - offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; - - // Add offsetParent borders - parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; - parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; - - // Subtract the two offsets - return { - top: offset.top - parentOffset.top, - left: offset.left - parentOffset.left - }; - }, - - offsetParent: function() { - return this.map(function() { - var offsetParent = this.offsetParent || document.body; - while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { - offsetParent = offsetParent.offsetParent; - } - return offsetParent || document.body; - }); - } -}); - - -// Create scrollLeft and scrollTop methods -jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) { - var top = /Y/.test( prop ); - - jQuery.fn[ method ] = function( val ) { - return jQuery.access( this, function( elem, method, val ) { - var win = getWindow( elem ); - - if ( val === undefined ) { - return win ? (prop in win) ? win[ prop ] : - win.document.documentElement[ method ] : - elem[ method ]; - } - - if ( win ) { - win.scrollTo( - !top ? val : jQuery( win ).scrollLeft(), - top ? val : jQuery( win ).scrollTop() - ); - - } else { - elem[ method ] = val; - } - }, method, val, arguments.length, null ); - }; -}); - -function getWindow( elem ) { - return jQuery.isWindow( elem ) ? - elem : - elem.nodeType === 9 ? - elem.defaultView || elem.parentWindow : - false; -} -// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods -jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { - jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { - // margin is only for outerHeight, outerWidth - jQuery.fn[ funcName ] = function( margin, value ) { - var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), - extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); - - return jQuery.access( this, function( elem, type, value ) { - var doc; - - if ( jQuery.isWindow( elem ) ) { - // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there - // isn't a whole lot we can do. See pull request at this URL for discussion: - // https://github.com/jquery/jquery/pull/764 - return elem.document.documentElement[ "client" + name ]; - } - - // Get document width or height - if ( elem.nodeType === 9 ) { - doc = elem.documentElement; - - // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest - // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it. - return Math.max( - elem.body[ "scroll" + name ], doc[ "scroll" + name ], - elem.body[ "offset" + name ], doc[ "offset" + name ], - doc[ "client" + name ] - ); - } - - return value === undefined ? - // Get width or height on the element, requesting but not forcing parseFloat - jQuery.css( elem, type, value, extra ) : - - // Set width or height on the element - jQuery.style( elem, type, value, extra ); - }, type, chainable ? margin : undefined, chainable, null ); - }; - }); -}); -// Expose jQuery to the global object -window.jQuery = window.$ = jQuery; - -// Expose jQuery as an AMD module, but only for AMD loaders that -// understand the issues with loading multiple versions of jQuery -// in a page that all might call define(). The loader will indicate -// they have special allowances for multiple jQuery versions by -// specifying define.amd.jQuery = true. Register as a named module, -// since jQuery can be concatenated with other files that may use define, -// but not use a proper concatenation script that understands anonymous -// AMD modules. A named AMD is safest and most robust way to register. -// Lowercase jquery is used because AMD module names are derived from -// file names, and jQuery is normally delivered in a lowercase file name. -// Do this after creating the global so that if an AMD module wants to call -// noConflict to hide this version of jQuery, it will work. -if ( typeof define === "function" && define.amd && define.amd.jQuery ) { - define( "jquery", [], function () { return jQuery; } ); -} - -})( window ); diff --git a/third_party/phantomjs/test/www/regression/pjs-13551/child1.html b/third_party/phantomjs/test/www/regression/pjs-13551/child1.html deleted file mode 100644 index 1f9ee6573d9..00000000000 --- a/third_party/phantomjs/test/www/regression/pjs-13551/child1.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/third_party/phantomjs/test/www/regression/pjs-13551/child1a.html b/third_party/phantomjs/test/www/regression/pjs-13551/child1a.html deleted file mode 100644 index fdaa7f100d1..00000000000 --- a/third_party/phantomjs/test/www/regression/pjs-13551/child1a.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/third_party/phantomjs/test/www/regression/pjs-13551/child2.html b/third_party/phantomjs/test/www/regression/pjs-13551/child2.html deleted file mode 100644 index 93322fc8179..00000000000 --- a/third_party/phantomjs/test/www/regression/pjs-13551/child2.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - -

success

diff --git a/third_party/phantomjs/test/www/regression/pjs-13551/closing-parent.html b/third_party/phantomjs/test/www/regression/pjs-13551/closing-parent.html deleted file mode 100644 index 5ad4d2bd91d..00000000000 --- a/third_party/phantomjs/test/www/regression/pjs-13551/closing-parent.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - diff --git a/third_party/phantomjs/test/www/regression/pjs-13551/reloading-parent.html b/third_party/phantomjs/test/www/regression/pjs-13551/reloading-parent.html deleted file mode 100644 index 6364ec6c2f5..00000000000 --- a/third_party/phantomjs/test/www/regression/pjs-13551/reloading-parent.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - diff --git a/third_party/phantomjs/test/www/regression/webkit-60448.html b/third_party/phantomjs/test/www/regression/webkit-60448.html deleted file mode 100644 index 1de358b3cd4..00000000000 --- a/third_party/phantomjs/test/www/regression/webkit-60448.html +++ /dev/null @@ -1,15 +0,0 @@ - - -Test passes if it does not crash. - -
- - - \ No newline at end of file diff --git a/third_party/phantomjs/test/www/render/image.jpg b/third_party/phantomjs/test/www/render/image.jpg deleted file mode 100644 index 53de7f6f13f23ade7bcc75e9305d9782b3d9bebc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19583 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 diff --git a/third_party/phantomjs/test/www/render/index.html b/third_party/phantomjs/test/www/render/index.html deleted file mode 100644 index aa7e80f24a2..00000000000 --- a/third_party/phantomjs/test/www/render/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/third_party/phantomjs/test/www/status.py b/third_party/phantomjs/test/www/status.py deleted file mode 100644 index e7a1c3e403f..00000000000 --- a/third_party/phantomjs/test/www/status.py +++ /dev/null @@ -1,50 +0,0 @@ -import cStringIO as StringIO -import urlparse - -def html_esc(s): - return s.replace('&','&').replace('<','<').replace('>','>') - -def handle_request(req): - url = urlparse.urlparse(req.path) - headers = [] - body = "" - - try: - query = urlparse.parse_qsl(url.query, strict_parsing=True) - status = None - for key, value in query: - if key == 'status': - if status is not None: - raise ValueError("status can only be specified once") - status = int(value) - elif key == 'Content-Type' or key == 'Content-Length': - raise ValueError("cannot override " + key) - else: - headers.append((key, value)) - - if status is None: - status = 200 - - body = "

Status: {}

".format(status) - if headers: - body += "
"
-            for key, value in headers:
-                body += html_esc("{}: {}\n".format(key, value))
-            body += "
" - - except Exception as e: - try: - status = int(url.query) - body = "

Status: {}

".format(status) - except: - status = 400 - body = "

Status: 400

" - body += "
" + html_esc(str(e)) + "
" - - req.send_response(status) - req.send_header('Content-Type', 'text/html') - req.send_header('Content-Length', str(len(body))) - for key, value in headers: - req.send_header(key, value) - req.end_headers() - return StringIO.StringIO(body) diff --git a/third_party/phantomjs/test/www/url-encoding.py b/third_party/phantomjs/test/www/url-encoding.py deleted file mode 100644 index 300dfdcba35..00000000000 --- a/third_party/phantomjs/test/www/url-encoding.py +++ /dev/null @@ -1,85 +0,0 @@ -# -*- encoding: utf-8 -*- -import urlparse -from cStringIO import StringIO -import time - -def html_esc(s): - return s.replace('&','&').replace('<','<').replace('>','>') - -def do_response(req, body, code=200, headers={}): - req.send_response(code) - req.send_header('Content-Length', str(len(body))) - if 'Content-Type' not in headers: - req.send_header('Content-Type', 'text/html') - for k, v in headers.items(): - if k != 'Content-Length': - req.send_header(k, v) - req.end_headers() - return StringIO(body) - -def do_redirect(req, target): - return do_response(req, - 'Go here'.format(target), - code=302, headers={ 'Location': target }) - -def handle_request(req): - url = urlparse.urlparse(req.path) - - # This handler returns one of several different documents, - # depending on the query string. Many of the URLs involved contain - # text encoded in Shift_JIS, and will not round-trip correctly if - # misinterpreted as UTF-8. Comments indicate the Unicode equivalent. - - if url.query == '/': - return do_redirect(req, '?/%83y%81[%83W') - - elif url.query == '/f': - return do_response(req, - '' - 'framed' - '' - '' - '' - '') - - elif url.query == "/r": - return do_response(req, - '') - - elif url.query == "/re": - return do_response(req, - '' - '' - '') - - elif url.query == "/%83y%81[%83W": # ページ - return do_response(req, '

PASS

') - - elif url.query == "/%98g": # 枠 - return do_response(req, '

PASS

') - - elif url.query == "/%95s%96%D1%82%C8%98_%91%88": # 不毛な論争 - return do_response(req, '

FRAME

') - - elif url.query == "/%8F%91": # 書 - return do_response(req, - 'window.onload=function(){' - 'document.body.innerHTML="

PASS

";};', - headers={'Content-Type': 'application/javascript'}) - - elif url.query == "/%8C%CC%8F%E1": # 故障 - return do_response(req, - 'internal server error', - code=500) - - elif url.query == "/%89i%8Bv": # 永久 - time.sleep(5) - return do_response(req, '', code=204) - - else: - return do_response(req, - '404 Not Found' - '

URL not found: {}

' - .format(html_esc(req.path)), - code=404) diff --git a/third_party/phantomjs/test/www/user-agent.html b/third_party/phantomjs/test/www/user-agent.html deleted file mode 100644 index adab8e830d7..00000000000 --- a/third_party/phantomjs/test/www/user-agent.html +++ /dev/null @@ -1,9 +0,0 @@ - - -User Agent - - -

User agent is: Unknown.

- - -